Lesson 11: Making a Game; States


Okay, the big thing to get through your head for making games is you get input, process data, change the states of anything based on that data, and then do it all again.

In the previous lesson, we showed that a button was pressed by entering setting a state to be "pressed". In this example, we will combine the concepts of animation, user input, and states to walk a guy left and right.
This will put together a number of the things we've learned. After this, you can study any of the pre-made games to learn collision with a maze, real-physics jumping, and so on!

/*#############################################################################
DEFINES
#############################################################################*/

#define @StateTest "2:1"
#define @Before "2:2"
#define @During "2:3"
#define @After "2:4"
#define @LeftWasPressed "2:8"
#define @RightWasPressed "2:9"
#define @ProcessEvent "2:10"
#define @UpdateCounters "2:11"

#define @DoLeftThings "2:110"
#define @DoRightThings "2:120"
#define @MoveGuy "2:130"
#define @GuyWalkLeft "2:140"
#define @GuyWalkRight "2:150"

/* -------------------------------------------------------
CONSTANTS
-------------------------------------------------------*/
#define %MSPERFRAME "50" 50 milliseconds * 20 = 1 sec
#define %FRAMESPERSECOND "20"

#define %LEFTSIDE "-100" //can move 100 left and 100 right
#define %RIGHTSIDE "100"

#define %PRESSED "1" //a button or key was pressed!

#define STATE_STANDINGLEFT "1"
#define STATE_STANDINGRIGHT "2"
#define STATE_WALKINGRIGHT "3"
#define STATE_WALKINGLEFT "4"

#define KEY_LEFT "1"
#define KEY_RIGHT "2"

/*#############################################################################
CODE
#############################################################################*/
#window @StateTest
startswitch @Before
thinkswitch @During
finishswitch @After

width 232
height 256
title "Using States"

if (guyState == STATE_WALKINGRIGHT) image apeshape\sideactr\GUYWR$guyFrame$.PCX guyX,guyY
if (guyState == STATE_WALKINGLEFT) image apeshape\sideactr\GUYWL$guyFrame$.PCX guyX,guyY
if (guyState == STATE_STANDINGLEFT) image apeshape\sideactr\GUYSL$guyFrame$.PCX guyX,guyY
if (guyState == STATE_STANDINGRIGHT) image apeshape\sideactr\GUYSR$guyFrame$.PCX guyX,guyY

/*=======================================================
Before
Initialize stuff!
=======================================================*/
#switch @Before
lastMS = func_GameTime
currentMS = lastMS

set guyX = 7 * 16
set guyY = 2 * 16
set guyFrame = 0
set guyState = STATE_STANDINGRIGHT //Start standing

console "pushbind"
console "bind LEFTARROW invoke @LeftWasPressed"
console "bind RIGHTARROW invoke @RightWasPressed"

return //at the program

/*=======================================================
During
Actively update appropriate variables
=======================================================*/
#switch @During
set currentMS = func_GameTime //get starting time, start to count
set delta = currentMS - lastMS
if (delta < %MSPERFRAME) return //do nothing unless frame starts

set lastMS = currentMS

if (keyMeaning > 0) gosub @ProcessEvent
gosub @UpdateCounters
gosub @MoveGuy
return

/*=======================================================
ProcessEvent
If someone pressed a key, let's do stuff!
=======================================================*/
#switch @ProcessEvent
if (keyMeaning == KEY_RIGHT) gosub @DoRightThings
else if (keyMeaning == KEY_LEFT) gosub @DoLeftThings
set keyMeaning = 0
return

#switch @DoRightThings
if (guyX > 200) guyState = STATE_STANDINGRIGHT
else guyState = STATE_WALKINGRIGHT
return

#switch @DoLeftThings
if (guyX < 8) guyState = STATE_STANDINGLEFT
else guyState = STATE_WALKINGLEFT
return

/*=======================================================
Update Counters
Animate dude if he's walking.
=======================================================*/
#switch @UpdateCounters
if (guyState == STATE_WALKINGRIGHT || guyState == STATE_WALKINGLEFT)
{
guyFrame = guyFrame + 1
if (guyFrame > 3) guyFrame = 0
}

return //we're done!

#switch @MoveGuy
if (guyState == STATE_WALKINGRIGHT) gosub @GuyWalkRight
else if (guyState == STATE_WALKINGLEFT) gosub @GuyWalkLeft
return

#switch @GuyWalkRight
if (guyX < 200) guyX = guyX + 2
else
{
guyState = STATE_STANDINGRIGHT
guyFrame = 0
}
return

#switch @GuyWalkLeft
if (guyX > 8) guyX = guyX - 2
else
{
guyState = STATE_STANDINGLEFT
guyFrame = 0
}
return

/*=======================================================
After
Leave the place like we found it
=======================================================*/
#switch @After
unset delta
unset lastMS
unset currentMS
unset guyX
unset guyY
console "popbind"

return

/*=======================================================
LeftWasPressed
Service Keypad Left being pressed.
=======================================================*/
#switch @LeftWasPressed
keyMeaning = KEY_LEFT
return

/*=======================================================
RightWasPressed
Service KeyPad Right being pressed.
=======================================================*/
#switch @RightWasPressed
keyMeaning = KEY_RIGHT
return

To check out Lesson11...

MAP battlesize
LOADAPE Lesson11
loadape 2:1

More advanced commands in Lesson 12!