Game development

Содержание серии «Avoider Game Tutorial»:

  1. Avoider Game tutorial на русском. Часть 1: Введение
  2. Avoider Game tutorial на русском. Часть 2: Несколько врагов
  3. Avoider Game tutorial на русском. Часть 3: Game Over
  4. Avoider Game tutorial на русском. Часть 4: Меню и кнопки
 (Оригинал на английском языке здесь)
 

Введение

В этой части урока avoider game tutorial AS3  мы добавим кнопки, чтобы позволить игроку перезапустить игру, если он проиграл, и добавим главное меню.

Кликните картинку ниже, чтобы увидеть, что мы получим:

Если вы не выполняли предыдущие части урока, скачайте архив и распакуйте его куда-нибудь. Если же у вас есть свои файлы, сохраните где-нибудь их резервную копию, и продолжайте проходить урок. Откройте файл FLA, и давайте начнем.

Попробуй еще раз

На данный момент, если игрок коснется врага, он попадет на экран «game over» и должен обновить страницу, чтобы поиграть снова. Мы добавим простенькую кнопку на этот экран, чтобы позволить игроку попробовать еще раз.

Создайте новый символ типа Button (Insert> New Symbol и выберите Button). Назовите его RestartButton, и нажмите кнопку OK.

Вы автоматически войдете в режим редактирования вашей кнопки. Нарисуйте кнопку, на которую хочется нажать и переиграть. Вот моя:

Теперь взгляните на таймлайн в нижней части экрана:

Кнопка вместо кадров содержит четыре отдельных состояния:

  • Up — Обычный вид кнопки.
  • Over — Как выглядит кнопка при наведении на нее курсора.
  • Down — Внешний вид кнопки при нажатии.
  • Hit — область кнопки, которая является «чувствительной» к курсору (подробнее об этом чуть позже).

Затемненный серый прямоугольник с точкой в колонке UP означает, что мы нарисовали изображение для этого состояния. Давайте нарисуем вид кнопки для других состояний. Щелкните правой кнопкой мыши по каждой из пустых клеточек, и выберите Insert Keyframe:

 

Ок, отлично. Нажмите на сером прямоугольнике с точкой в нем (далее — ключевой кадр) в колонке Over. Изображение из состояния Up должно было скопироваться в колонку over, если его там нет, вы можете скопировать и вставить его из одного столбца в другой. Измените изображение кнопки подходящим способом — я просто инвертировал цвета моей кнопки:

Теперь измените кадр down:

Ключевой кадр «Hit» немного отличается. Форма, которую вы нарисуете, определяет «интерактивную» область кнопки. Игрок никогда не увидит этот образ. Если вы нарисовали кнопку с тенью, например, и вы хотели бы, чтобы игрок мог нажать на кнопку, но не тень, то вы можете просто нарисовать форму кнопки без тени в кадре Hit.

Во всяком случае, я не хочу оставлять на кнопкt некликабельные участки, так что я сделаю фигуру такой же формы, как и кнопка:

У меня прямоугольник ярко-красный просто для того, чтобы напомнить себе, что он не будет увиден игроком, но я могу сделать его любым цветом. Вы даже можете оставить исходное изображение как есть, если вы хотите.

Теперь нам нужно добавить эту кнопку на игровой на экран. Сохраните все, что вы сделали, затем дважды щелкните GameOverScreen в библиотеке.

Найдите RestartButton в библиотеке и перетащите её в экран(мувиклип) Game Over.

(Ой. я забыл, что черных границ кнопки не будет видно на черном фоне. Ну да ладно.)

Помните еще в первой части этого урока, когда я говорил о экземплярах и классах? Вот, кнопка на экране gameOver — экземпляр класса RestartButton. Сейчас этот экземпляр в не имеет имени экземпляра. Если мы хотим, получить к нему доступ кодом (а мы хотим), мы должны дать кнопке instance name (имя экземпляра).

Кликните на кнопку, которую вы только что добавили, и посмотрите на панели свойств:

Видите поле instance name? Введите restartButton (как обычно, будьте осторожны с заглавными буквами!)

Ладно, теперь мы можем написать код, чтобы заставить игру делать что-то, когда кнопка нажата.

Эй! … Слушай!

До сих пор мы использовали слушателей событий, чтобы вызвать функцию смерти аватара и отследить «тик» игрового таймера. Теперь мы собираемся отслеживать «клик» на кнопке restart.

Так как кнопка существует в GameOverScreen, соответствующий код пишем в GameOverScreen класс. Но … мы же не создавали такого класса. Так давайте сделаем это сейчас! Создайте новый AS файл и введите следующее:

1
2
3
4
5
6
7
8
9
10
11
package 
{
    import flash.display.MovieClip;
    public class GameOverScreen extends MovieClip 
    {
        public function GameOverScreen() 
        {
 
        }
    }
}
package 
{
	import flash.display.MovieClip;
	public class GameOverScreen extends MovieClip 
	{
		public function GameOverScreen() 
		{

		}
	}
}

Сохраните GameOverScreen.as в папке классов (Classes).

Надеюсь, этот код выглядит знакомо. Сохраните все и протестируйте игру. Она выдаст вам ошибку:

1
GameOverScreen.as, Line 2 1046:  Type was not found or was not a compile-time constant: SimpleButton.
GameOverScreen.as, Line 2 1046:  Type was not found or was not a compile-time constant: SimpleButton.

или на русском:

1
 GameOverScreen.as, строка 2 1046: Тип не найден или не является константой во время компиляции: SimpleButton.
 GameOverScreen.as, строка 2 1046: Тип не найден или не является константой во время компиляции: SimpleButton.

Что? Флеш обнаружил, что есть кнопка на GameOverScreen, но говорит: «Что это такое? Я никогда не слышал об этой «кнопке». Флеш иногда бывает довольно глупым.

Мы должны указать флешу, что такое button. Вернитесь к GameOverScreen.as и измените его, чтобы импортировать определения класса SimpleButton (строка 4):

1
2
3
4
5
6
7
8
9
10
11
12
13
package 
{
    import flash.display.MovieClip;
    import flash.display.SimpleButton;
 
    public class GameOverScreen extends MovieClip 
    {
        public function GameOverScreen() 
        {
 
        }
    }
}
package 
{
	import flash.display.MovieClip;
	import flash.display.SimpleButton;

	public class GameOverScreen extends MovieClip 
	{
		public function GameOverScreen() 
		{

		}
	}
}

Теперь вы можете сохранить и протестировать кнопку. Вы заметите, что кнопка изменения при наведении на нее курсора и когда вы щелкните по ней. Очевидно, что это не сделает ничего, потому что мы еще не добавили слушатель событий. Так что давайте делать дальше.

Так как этот код похож на то, что мы добавляли в предыдущих частях, я просто вставлю все сразу и объясню:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package 
{
    import flash.display.MovieClip;
    import flash.display.SimpleButton;
    import flash.events.MouseEvent;
 
    public class GameOverScreen extends MovieClip 
    {
        public function GameOverScreen() 
        {
            restartButton.addEventListener( MouseEvent.CLICK, onClickRestart );
        }
 
        public function onClickRestart( mouseEvent:MouseEvent ):void 
        {
 
        }
    }
}
package 
{
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.events.MouseEvent;

	public class GameOverScreen extends MovieClip 
	{
		public function GameOverScreen() 
		{
			restartButton.addEventListener( MouseEvent.CLICK, onClickRestart );
		}

		public function onClickRestart( mouseEvent:MouseEvent ):void 
		{

		}
	}
}
  • public function onClickRestart( mouseEvent:MouseEvent ) — это функция, которую мы хотим запускать при нажатии кнопки перезапуска. Как и прежде, мы передаем информацию о событии (мыши), потому что так положено.
  • restartButton.addEventListener (MouseEvent.CLICK, onClickRestart); — Это добавляет слушатель события к кнопке и говорит ему, что, если нажата кнопка (да-да, Flash действительно требует от вас, писать CLICK большими буквами), то должна сработать функция onClickRestart.
  • import flash.events.MouseEvent; — Без этой строки, Flash не знает значение слова CLICK.

Чтобы запустить игру снова, мы должны удалить экран gameOver и перезагрузить игровой экран. В части 3 мы изменили структуру проекта так, что класс документа обрабатывает все манипуляции экранами, по-этому будем править его. Откройте DocumentClass.as и добавьте новую функцию:

24
25
26
27
28
29
30
31
public function restartGame():void
{
    playScreen = new AvoiderGame();
    playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
    addChild( playScreen );
 
    gameOverScreen = null;
}
public function restartGame():void
{
	playScreen = new AvoiderGame();
	playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
	addChild( playScreen );

	gameOverScreen = null;
}

Строки 26 и 27 создают игровой экран в точности так же, как это делал конструктор. Когда игрок попадает на экран GameOver, строкой playScreen = null мы удалаем слушатели событий и сбрашиваем х и у координаты игрового экрана, что я и объяснял в Части 3.

Строка 30 уберет из памяти gameOverScreen, но есть одна проблема. GameOverScreen определен только в функции onAvatarDeath(), так что он не доступен для функции restartGame(). Давайте сделаем gameOverScreen доступным для всего класса документа, как и playScreen:

1
2
3
4
5
6
7
package 
{
    import flash.display.MovieClip;
    public class DocumentClass extends MovieClip 
    {
        public var playScreen:AvoiderGame;
        public var gameOverScreen:GameOverScreen;
package 
{
	import flash.display.MovieClip;
	public class DocumentClass extends MovieClip 
	{
		public var playScreen:AvoiderGame;
		public var gameOverScreen:GameOverScreen;

Теперь нам нужно удалитьvar из var gameOverScreen в функции onAvatarDeath, так как мы уже определили gameOverScreen ранее:

16
17
18
19
20
21
22
23
24
public function onAvatarDeath( avatarEvent:AvatarEvent ):void
{
    gameOverScreen = new GameOverScreen();
    gameOverScreen.x = 0;
    gameOverScreen.y = 0;
    addChild( gameOverScreen );
 
    playScreen = null;
}
public function onAvatarDeath( avatarEvent:AvatarEvent ):void
{
	gameOverScreen = new GameOverScreen();
	gameOverScreen.x = 0;
	gameOverScreen.y = 0;
	addChild( gameOverScreen );

	playScreen = null;
}

Вот как выглядит мой класс документа на данный момент:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package 
{
    import flash.display.MovieClip;
    public class DocumentClass extends MovieClip 
    {
        public var playScreen:AvoiderGame;
        public var gameOverScreen:GameOverScreen;
 
        public function DocumentClass() 
        {
            playScreen = new AvoiderGame();
            playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
            playScreen.x = 0;
            playScreen.y = 0;
            addChild( playScreen );
        }
 
        public function onAvatarDeath( avatarEvent:AvatarEvent ):void
        {
            gameOverScreen = new GameOverScreen();
            gameOverScreen.x = 0;
            gameOverScreen.y = 0;
            addChild( gameOverScreen );
 
            playScreen = null;
        }
 
        public function restartGame():void
        {
            playScreen = new AvoiderGame();
            playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
            playScreen.x = 0;
            playScreen.y = 0;
            addChild( playScreen );
 
            gameOverScreen = null;
        }
    }
}
package 
{
	import flash.display.MovieClip;
	public class DocumentClass extends MovieClip 
	{
		public var playScreen:AvoiderGame;
		public var gameOverScreen:GameOverScreen;

		public function DocumentClass() 
		{
			playScreen = new AvoiderGame();
			playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
			playScreen.x = 0;
			playScreen.y = 0;
			addChild( playScreen );
		}

		public function onAvatarDeath( avatarEvent:AvatarEvent ):void
		{
			gameOverScreen = new GameOverScreen();
			gameOverScreen.x = 0;
			gameOverScreen.y = 0;
			addChild( gameOverScreen );

			playScreen = null;
		}

		public function restartGame():void
		{
			playScreen = new AvoiderGame();
			playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
			playScreen.x = 0;
			playScreen.y = 0;
			addChild( playScreen );

			gameOverScreen = null;
		}
	}
}

Я добавил строки 13 и 14, чтобы расположить игровой экран в точке (0,0), так же, как и gameOverScreen, и дублировал эти строчки в restartGame (). В следующей части, я упрощу код так, что нам не придется писать один и тот же код дважды.

ПЕРЕЗАГРУЗКА!

Теперь у нас есть функция в gameOverScreen, которая запускается при нажатии кнопки «рестарт», и функция в классе документа, которая выполняет перезапуск игры. Возникает желание соединить их друг с другом непосредственно, но, как я говорил в предыдущей части , это приводит к проблемам в будущем. Мы будем использовать тот же подход, который мы использовали со смертью аватара: создание нового пользовательского события.

Вот что произойдет:

  • Игрок нажимает кнопку «рестарт»
  • Кнопка отсылает MouseEvent типа CLICK
  • MouseEvent.CLICK поймает(услышит) слушатель события в gameOverScreen и запустит onClickRestart ()
  • onClickRestart (), в свою очередь, отсылает наше новое пользовательское событие — назовем его NavigationEvent — типа RESTART
  • NavigationEvent.RESTART поймает слушатель события в классе документа, и запустит новую функцию: onRequestRestart ()
  • onRequestRestart () запустит функцию restartGame ()

Тьфу! Много букв, но все на самом деле довольно просто. Это также дает нам возможность встроить рестарт игры разными способами: нажатием «R» или по прошествии некоторого времени. В любом случае, нам нужно просто отослать событие NavigationEvent.RESTART, и остальное уже готово.

Наше новое пользовательское событие выглядят так же, как и AvatarEvent:

1
2
3
4
5
6
7
8
9
10
11
12
13
package  
{
    import flash.events.Event;
    public class NavigationEvent extends Event 
    {
        public static const RESTART:String = "restart";
 
        public function NavigationEvent( type:String )
        {
            super( type );
        }
    }
}
package  
{
	import flash.events.Event;
	public class NavigationEvent extends Event 
	{
		public static const RESTART:String = "restart";

		public function NavigationEvent( type:String )
		{
			super( type );
		}
	}
}

(Сохраните файл как NavigationEvent.as в папке Classes). Создать событие также просто: (этот кусок кода пишем в GameOverScreen):

14
15
16
17
public function onClickRestart( mouseEvent:MouseEvent ):void
{
    dispatchEvent( new NavigationEvent( NavigationEvent.RESTART ) );
}
public function onClickRestart( mouseEvent:MouseEvent ):void
{
	dispatchEvent( new NavigationEvent( NavigationEvent.RESTART ) );
}

А учитывая, что это ваш третий слушатель события, не должно возникнуть проблем с добавлением его в класс документа (строка 21):

18
19
20
21
22
23
24
25
26
27
public function onAvatarDeath( avatarEvent:AvatarEvent ):void
{
    gameOverScreen = new GameOverScreen();
    gameOverScreen.addEventListener( NavigationEvent.RESTART, onRequestRestart );
    gameOverScreen.x = 0;
    gameOverScreen.y = 0;
    addChild( gameOverScreen );
 
    playScreen = null;
}
public function onAvatarDeath( avatarEvent:AvatarEvent ):void
{
	gameOverScreen = new GameOverScreen();
	gameOverScreen.addEventListener( NavigationEvent.RESTART, onRequestRestart );
	gameOverScreen.x = 0;
	gameOverScreen.y = 0;
	addChild( gameOverScreen );

	playScreen = null;
}

Не забудьте создать функцию onRequestRestart () внутри класса документа, и указать ей, что делать:

1
2
3
4
public function onRequestRestart( navigationEvent:NavigationEvent ):void
{
    restartGame();
}
public function onRequestRestart( navigationEvent:NavigationEvent ):void
{
	restartGame();
}

Теперь, после того, как мы нажали кнопку «рестарт» (и после длинной цепочки событий), функция restartGame() класса документа будет выполнена, что в свою очередь удалит экран gameOver и загрузит игровой экран. Сохраняем и тестируем. Наконец, игрок может перезапустить игру не обновляя страницы!

Главное меню

Добавить меню в начало игры теперь будет легко. Код практически такой же, как в gameOverScreen. Давайте рассмотрим следующие действия очень быстро.

Во-первых, создать меню. Вы можете создавать с нуля, если вам хочется, но так как экран gameOver уже нужного размера я собираюсь сделать его копию и внести некоторые правки.

Вернитесь в файл FLA и найдите GameOverScreen в библиотеке. Щелкните по нему правой кнопкой мыши и выберите Duplicate(Дублировать). Нужно будет ввести имя для дубликата. Я написал имя MenuScreen, оставив тип Movie Clip. Дважды щелкните на новом MenuScreen в библиотеке, чтобы войти в режим редактирования, и удаление кнопку рестарт. Сделайте все необходимые изменения в интерфейсе. Вот мой результат:

Истинное произведение искусства.

Теперь о кнопке. Опять же, вы можете создать с нуля, как мы делали раньше (помните, она должен быть типа Button!), или вы можете дублировать и править существующую RestartButton. Полностью ваш выбор. В любом случае, назовите новую кнопку StartButton и отредактируйте ее соответствующим образом. Вот моя:

Я не лентяй, я поддерживаю постоянный стиль на протяжении всего моего проекта. Добавьте новую кнопку на MenuScreen и задайте имя экземпляра «startButton».

Теперь давайте писать код. Щелкните правой кнопкой мыши на MenuScreen и выберите Properties. Поставьте галочку Export for ActionScript, введите MenuScreen в поле Class и нажмите кнопку OK. Как обычно, вас предупредят:

… Поэтому давайте создадим класс для MenuScreen.

Нажмите File> New и выберите файл ActionScript. Вот код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package 
{
    import flash.display.MovieClip;
    import flash.display.SimpleButton;
    import flash.events.MouseEvent;
 
    public class MenuScreen extends MovieClip 
    {
        public function MenuScreen() 
        {
            startButton.addEventListener( MouseEvent.CLICK, onClickStart );
        }
 
        public function onClickStart( event:MouseEvent ):void
        {
            dispatchEvent( new NavigationEvent( NavigationEvent.START ) );
        }
    }
}
package 
{
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.events.MouseEvent;

	public class MenuScreen extends MovieClip 
	{
		public function MenuScreen() 
		{
			startButton.addEventListener( MouseEvent.CLICK, onClickStart );
		}

		public function onClickStart( event:MouseEvent ):void
		{
			dispatchEvent( new NavigationEvent( NavigationEvent.START ) );
		}
	}
}

Сохраните файл в папке классы, «MenuScreen.as».

Я даже не собираюсь объяснить большую часть этого кода, потому что это почти тот же код, что и в GameOverScreen.as. Заметим, однако, что в строке 16 я отправляю NavigationEvent типа START, — но сейчас класс NavigationEvent имеет только тип RESTART. Давайте добавим новый тип в NavigationEvent.as прямо сейчас:

1
2
3
4
5
6
7
package  
{
    import flash.events.Event;
    public class NavigationEvent extends Event 
    {
        public static const RESTART:String = "restart";
        public static const START:String = "start";
package  
{
	import flash.events.Event;
	public class NavigationEvent extends Event 
	{
		public static const RESTART:String = "restart";
		public static const START:String = "start";

Легко.

Сейчас класс документа отображает игровой экран при запуске. Мы собираемся изменить код, чтобы увидеть наш новый экран меню вместо игрового. Измените следующие строки:

6
7
8
9
10
11
12
13
14
15
16
public var playScreen:AvoiderGame;
public var gameOverScreen:GameOverScreen;
 
public function DocumentClass() 
{
    playScreen = new AvoiderGame();
    playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
    playScreen.x = 0;
    playScreen.y = 0;
    addChild( playScreen );
}
public var playScreen:AvoiderGame;
public var gameOverScreen:GameOverScreen;

public function DocumentClass() 
{
	playScreen = new AvoiderGame();
	playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
	playScreen.x = 0;
	playScreen.y = 0;
	addChild( playScreen );
}

на это:

6
7
8
9
10
11
12
13
14
15
16
17
public var menuScreen:MenuScreen;
public var playScreen:AvoiderGame;
public var gameOverScreen:GameOverScreen;
 
public function DocumentClass() 
{
    menuScreen = new MenuScreen();
    menuScreen.addEventListener( NavigationEvent.START, onRequestStart );
    menuScreen.x = 0;
    menuScreen.y = 0;
    addChild( menuScreen );
}
public var menuScreen:MenuScreen;
public var playScreen:AvoiderGame;
public var gameOverScreen:GameOverScreen;

public function DocumentClass() 
{
	menuScreen = new MenuScreen();
	menuScreen.addEventListener( NavigationEvent.START, onRequestStart );
	menuScreen.x = 0;
	menuScreen.y = 0;
	addChild( menuScreen );
}

Обратите внимание, что я добавил новый menuScreen, и я больше не создаю игровой экран в конструкторе DocumentClass().

Теперь нам нужно написать функцию onRequestStart () (строка 13, выше), и мы закончим:

35
36
37
38
39
40
41
42
43
44
public function onRequestStart( navigationEvent:NavigationEvent ):void
{
    playScreen = new AvoiderGame();
    playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
    playScreen.x = 0;
    playScreen.y = 0;
    addChild( playScreen );
 
    menuScreen = null;
}
public function onRequestStart( navigationEvent:NavigationEvent ):void
{
	playScreen = new AvoiderGame();
	playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath );
	playScreen.x = 0;
	playScreen.y = 0;
	addChild( playScreen );

	menuScreen = null;
}

Сохраните все файлы и тестируйте игру и … успех!

Заключение

В этой части я объяснял знакомые моменты более кратко. Я делаю так, чтобы не повторяться, но если что-то не понятно, пожалуйста, задавайте вопросы.

Как всегда, вы можете скачать архив со всеми наработками здесь, и вы можете подписаться на мою рассылку RSS (чтобы получить извещение, как только появится новая часть) здесь .

В части 5 я покажу вам, как добавить часы и очки(счет). А пока, почему бы вам не попробовать добавить кнопку на экране GameOver, которая отправляет вас обратно в главное меню?

Avoider game tutorial перевод от Trost.

7 комментариев

  1. Body Body
    12.12.2012    

    ждём ещё

  2. Станислав Станислав
    08.02.2014    

    Хороший перевод.похоже перевод забросили уже,на сайте много частей появилось новых

    • Trost Trost
      08.02.2014    

      Когда начинал переводить, уже было 12 частей тутора (полный цикл). На момент написания переводов, я прошел те 12 туторов и сделал игру с полученными знаниями (brainDef). Потому и переводил, понимая что хотел сказать автор.
      К сожалению, переводить получалось ужасно медленно и скучно, потому да, забросил.
      Также автор сам признал эту линейку туторов устаревшей и выпустил что-то новое.

      • Станислав Станислав
        10.02.2014    

        а что выпустил новое не поделитесь ссылкой? может и устарело,но между прочим я многое узнал из статьи,так как тока Мука прочел.ну инглишь мой вообще никакой,через он лайн переводчик хочу добить. Что такое (brainDef) ?

        • Trost Trost
          10.02.2014    

          Ну ссылка на оригинал есть выше. На сайте автора в начале урока 1 этой серии в желтой рамочке есть сообщение (перевожу):
          »
          Этот урок(серия уроков) уже староват. Он все еще работает, но если вы хотите более актуальный урок по изучению Флеш, я рекомендую прочитать мой пост «Как выучить Флеш и АС3 для разработки игр.»
          http://gamedevelopment.tutsplus.com/articles/how-to-learn-flash-and-as3-for-game-development—gamedev-636
          »
          Эту новую версию сам лично не читал, если все-же будешь добивать эту серию — если будут вопросы по уроку — пиши здесь или в skype, помогу.
          BrainDef — моя первая игра, сделанная с помощью одних только знаний из вышеприведенной серии уроков. Т.е. до этого не программировал вообще.
          http://trost-flash.com/braindef/

          • Станислав Станислав
            18.03.2014    

            Привет, ты говорил можно местами обратиться к тебе, так онлайном переводил, код смотрел его — и понимал логику, но наткнулся на один момент который не пойму ну никак. Глава 6, где рассказывает про улучшения, ниже почти в конце есть глава — You Only Die Once. я думаю что суть онлайн перевода не пойму, а конкретно зачем там

            avatarHasBeenHit = true ,
            if ( avatarHasBeenHit )
            {
            dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) );
            }

            я понял что это от двойного столкновения за такт, но не понял чем хуже

            if ( avatar.hitTestObject( enemy ) )
            {
            gameTimer.stop();
            dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) );
            }

          • Trost Trost
            18.03.2014    

            В данном примере проблем этот баг не создает. В шутерах такое тоже вряд-ли нужно. Но если делать платформер, где есть например 3 жизни и после потери жизни дается пару секунд неуязвимости или делается рестарт, то можно было бы за одно столкновение в течении такта потерять 2 жизни сразу.
            По-сути это неуязвимость до конца цикла tick, если тебя ударили.
            В общем не критичный момент, можно также было бы просто сделать:
            <br />
            for each ( var enemy:Enemy in army )<br />
            {<br />
                enemy.moveABit();<br />
                if ( avatar.hitTestObject( enemy ) )<br />
                {<br />
                    gameTimer.stop();<br />
                    dispatchEvent( new AvatarEvent( AvatarEvent.DEAD ) );<br />
                            break;                                                 //ВЫХОДИТ ИЗ ЦИКЛА for each ( var enemy:Enemy in army )<br />
                }<br />
            }<br />

Добавить комментарий