Game Programming Patterns / Паттерны программирования в играх: 1.6. State
| Английский оригинал | Перевод на русский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
Статичное состояние не сработает для состояния ducking. bubenok 13.06.14 в 06:51 |
|
|
Оно содержит поле chargeTime_ и эта особенность возникает только в момент приседания. bubenok 13.06.14 в 07:01 |
||
|
Это может случайно сработать в нашей игре, если у нас только одна героиня, но если мы попытаемся добавить игру вдвоем, когда на экране одновременно нужно управлять двумя персонажами, у нас будут проблемы. bubenok 13.06.14 в 07:03 |
||
|
В этом случае мы на самом деле должны создавать объект состояния, когда мы переходим к нему: bubenok 13.06.14 в 07:06 |
||
|
// In StandingState: bubenok 13.06.14 в 07:06 |
||
|
if (input == PRESS_DOWN) bubenok 13.06.14 в 07:06 |
||
|
{ bubenok 13.06.14 в 07:06 |
||
|
delete heroine. bubenok 13.06.14 в 07:06 |
||
|
state_; bubenok 13.06.14 в 07:06 |
||
|
heroine. bubenok 13.06.14 в 07:06 |
||
|
state_ = new DuckingState(); bubenok 13.06.14 в 07:07 |
||
|
// Other code... bubenok 13.06.14 в 07:07 |
||
|
} bubenok 13.06.14 в 07:07 |
||
|
Такое решение позволяет каждому КА иметь собственный экземпляр состояния. bubenok 13.06.14 в 07:08 |
||
|
По возможности я предпочитаю использовать статичные состояния, т.к. они не тратят память и ресурсы процессора на создание объектов при каждом изменении состояния. bubenok 13.06.14 в 07:10 |
||
|
Но для состояний, которые, э-э-э, больше являются состоянием, это тот путь по которому следует идти. bubenok 13.06.14 в 07:15 |
||
|
Когда вы динамически управляете состояниями, вы можете не беспокоиться о фрагментации и использовании памяти. bubenok 13.06.14 в 07:17 |
||
|
Паттерны Flyweight и Object Pool помогут вам с этим. bubenok 13.06.14 в 07:18 |
||
|
Входные и выходные действия. bubenok 02.07.14 в 11:43 |
||
|
Цель паттерна State - инкапсулировать все, что относится к поведению и данным одного состояния в отдельный класс. bubenok 13.06.14 в 16:32 |
||
|
Мы неплохо справились с этой задачей, но есть еще один нюанс. bubenok 13.06.14 в 16:33 |
||
|
Мы переместили обработку пользовательского ввода и обновление времени восполнения энергии в DuckingState, но у нас есть еще небольшой кусочек кода, специфичный для этого состояния, который находится вне этого класса. bubenok 13.06.14 в 16:38 |
||
|
Когда мы присаживаемся из положения стоя происходит следующая инициализация: bubenok 13.06.14 в 16:42 |
||
|
// In standing state: bubenok 13.06.14 в 16:42 |
||
|
if (input == PRESS_DOWN) bubenok 13.06.14 в 16:43 |
||
|
{ bubenok 13.06.14 в 16:43 |
||
|
// Change state... bubenok 13.06.14 в 16:43 |
||
|
chargeTime_ = 0; bubenok 13.06.14 в 16:43 |
||
|
setGraphics(IMAGE_DUCK) bubenok 13.06.14 в 16:43 |
||
|
; bubenok 13.06.14 в 16:43 |
||
|
} bubenok 13.06.14 в 16:43 |
||
|
По идее, состояние ducking должно позаботиться о сбросе времени заряда (в конце концов именно этот объект содержит поле chargeTime_ ) bubenok 01.07.14 в 14:02 |
||
|
и воспроизведении анимации. bubenok 01.07.14 в 14:03 |
||
|
Мы можем решить эту задачу передавая состоянию входное действие: bubenok 01.07.14 в 14:05 |
||
|
class DuckingState : public HeroineState bubenok 01.07.14 в 14:05 |
||
|
{ bubenok 01.07.14 в 14:05 |
||
|
public: bubenok 01.07.14 в 14:05 |
||
|
virtual void enter(Heroine& heroine) bubenok 01.07.14 в 14:05 |
||
|
{ bubenok 01.07.14 в 14:05 |
||
|
chargeTime_ = 0; bubenok 01.07.14 в 14:05 |
||
|
heroine. bubenok 01.07.14 в 14:06 |
||
|
setGraphics(IMAGE_DUCK) bubenok 01.07.14 в 14:06 |
||
|
; bubenok 01.07.14 в 14:06 |
||
|
} bubenok 01.07.14 в 14:06 |
||
|
// Other code... bubenok 01.07.14 в 14:06 |
||
|
}; bubenok 01.07.14 в 14:06 |
||
|
Вернемся к классу Heroine и обернем изменение состояния в небольшую удобную функцию, которая вызывается при каждом новом состоянии: bubenok 01.07.14 в 14:09 |
||
|
void Heroine::changeState(HeroineState* state) bubenok 01.07.14 в 14:09 |
||
|
{ bubenok 01.07.14 в 14:09 |
||
|
delete state_; bubenok 01.07.14 в 14:10 |
