Game Programming Patterns / Паттерны программирования в играх: 1.6. State
| Английский оригинал | Перевод на русский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
В нашем случае это: стоит, прыгает, приседает и ныряет. MrSmith33 06.05.14 в 17:18 |
|
|
Автомат может находиться только в одном из состояний. MrSmith33 06.05.14 в 17:18 |
||
|
Наша героиня не может одновременно стоять и прыгать. MrSmith33 06.05.14 в 17:19 |
||
|
Это одна из причин, по которой мы будем использовать конечные автоматы. MrSmith33 06.05.14 в 17:20 |
||
|
Последовательность вводов или событий посылается автомату. MrSmith33 06.05.14 в 17:22 |
||
|
В нашем случае это простые нажатия и отпускание кнопок. MrSmith33 06.05.14 в 17:22 |
||
|
Каждое состояние имеет набор переходов, каждый из которых связан с соответствующим вводом и указывает на другое состояние. MrSmith33 06.05.14 в 17:23 |
||
|
Если при подаче ввода находится соответствующий переход из текущего состояния, то автомат переходит в него. MrSmith33 06.05.14 в 17:25 |
||
|
Например, при нажатии кнопки "вниз", если мы находимся в стоячем состоянии, происходит переход в состояние приседания. MrSmith33 06.05.14 в 17:26 |
||
|
Когда игрок нажимает "вниз" пока мы в прыжке, происходит переход в нырок. MrSmith33 06.05.14 в 17:27 |
||
|
Если не найдено ни одного перехода по данному вводу, то ввод игнорируется. MrSmith33 06.05.14 в 17:28 |
||
|
По сути, в этом вся соль автоматов: состояния, вводы и переходы. MrSmith33 06.05.14 в 17:29 |
||
|
Можно представить это как диаграмму. MrSmith33 06.05.14 в 17:29 |
||
|
К сожалению компилятор не поймет наши каракули, так что как же мы реализуем это? MrSmith33 06.05.14 в 17:30 |
||
|
Паттерн "Состояние" Банды Четырех - это один из вариантов того, как мы можем поступить, но можно и проще. MrSmith33 06.05.14 в 17:31 |
||
|
Моя любимая аналогия для КА это старые приключенческие игры типа Zork. MrSmith33 06.05.14 в 17:32 |
||
|
Мир состоит из комнат, каждая из которых соединена с другими проходами. MrSmith33 06.05.14 в 17:33 |
||
|
Вы исследуете мир вводя команды, типа "идти на север". MrSmith33 06.05.14 в 17:34 |
||
|
Выглядит прямо, как конечный автомат: каждая комната - это состояние. MrSmith33 06.05.14 в 17:34 |
||
|
Комната в который вы сейчас находитесь - это текущее состояние. MrSmith33 06.05.14 в 17:35 |
||
|
Входы каждой комнаты - это переходы. MrSmith33 06.05.14 в 17:35 |
||
|
Команды перехода - это вводы. MrSmith33 06.05.14 в 17:36 |
||
|
Enum и Switch MrSmith33 06.05.14 в 17:38 |
||
|
Проблема нашей героини в том, что некоторые комбинации флагов не должны существовать. Например: isJumping_ и isDucking_ не должны быть true одновременно. MrSmith33 06.05.14 в 17:42 |
||
|
Если у вас много флагом и только один может быть включен в каждый момент времени, то это явная подсказка, что вам нужен enum. MrSmith33 06.05.14 в 17:43 |
||
|
В нашем случае, перечисление идеально подойдет для представления состояний нашего КА и мы определим его так: MrSmith33 06.05.14 в 17:48 |
||
|
enum State MrSmith33 06.05.14 в 17:48 |
||
|
{ MrSmith33 06.05.14 в 17:48 |
||
|
STATE_STANDING, MrSmith33 06.05.14 в 17:48 |
||
|
STATE_JUMPING, MrSmith33 06.05.14 в 17:48 |
||
|
STATE_DUCKING, MrSmith33 06.05.14 в 17:49 |
||
|
STATE_DIVING MrSmith33 06.05.14 в 17:49 |
||
|
}; MrSmith33 06.05.14 в 17:49 |
||
|
Вместо кучи флагов у героини будет только поле state_. MrSmith33 06.05.14 в 17:50 |
||
|
Также, мы поменяли порядок ветвления. MrSmith33 06.05.14 в 17:51 |
||
|
До этого мы сначала делали проверку ввода, а потом состояния. MrSmith33 06.05.14 в 17:52 |
||
|
Это позволяло нашему коду обрабатывать вместе одно нажатие кнопки, но одно состояние было размазано по коду. bubenok 17.05.14 в 05:58 |
||
|
Нам необходимо собрать все это вместе, поэтому сначала мы проверим состояние. bubenok 17.05.14 в 05:59 |
||
|
Мы получаем: bubenok 17.05.14 в 05:59 |
||
|
void Heroine::handleInput(Input input) bubenok 17.05.14 в 05:59 |
||
|
{ bubenok 17.05.14 в 06:00 |
||
|
switch (state_) bubenok 17.05.14 в 06:00 |
||
|
{ bubenok 17.05.14 в 06:00 |
||
|
case STATE_STANDING: bubenok 17.05.14 в 06:00 |
||
|
if (input == PRESS_B) bubenok 17.05.14 в 06:00 |
||
|
{ bubenok 17.05.14 в 06:00 |
||
|
state_ = STATE_JUMPING; bubenok 17.05.14 в 06:00 |
||
|
yVelocity_ = JUMP_VELOCITY; bubenok 17.05.14 в 06:01 |
||
|
setGraphics(IMAGE_JUMP) bubenok 17.05.14 в 06:01 |
||
|
; bubenok 17.05.14 в 06:01 |
