StateMachine

Previous topic - Next topic

Albert

Hi!

I've created this simple state machine for creating simple menus and game states during my LD48.

[attachment deleted by admin]

Albert

#1
Here is how it's work:

Code (glbasic) Select

PROTOTYPE STATEPROTO: state AS TSTATE

TYPE TSTATE
id
typ$ //const enum
pos AS TPOINT
_paused //bool
_visible //bool
_created //bool
_inited //bool
create AS STATEPROTO //first create, load everything
destroy AS STATEPROTO //destroy, unload everything
init AS STATEPROTO //init after create or reset
reset AS STATEPROTO //reset all the stuff then init
update AS STATEPROTO //update
render AS STATEPROTO //draw

FUNCTION _superinit:
self.id=-1
self._paused = TRUE
self._created = FALSE
self._inited = FALSE
self._visible = FALSE
self.pos.set(0,0)
ENDFUNCTION

FUNCTION _isready:
IF (self._created AND self._inited)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNCTION

FUNCTION _pause:
self._paused=TRUE
ENDFUNCTION

FUNCTION _start:
IF (self._isready())
self._paused=FALSE
ENDIF
ENDFUNCTION
ENDTYPE

// call these super TSTATE functions from your custom functions
FUNCTION state_create: stateid //first create, load everything
ALIAS state AS STATES[stateid]
state.create(state)
state._created=TRUE
state_init(stateid)
ENDFUNCTION

FUNCTION state_destroy: stateid //destroy, unload everything
ALIAS state AS STATES[stateid]
state_destroy(stateid)
state._paused=TRUE
state._inited=FALSE
state._created=FALSE
ENDFUNCTION

FUNCTION state_init: stateid //init after create or reset
ALIAS state AS STATES[stateid]
DBG("state._created:"+state._created,"state_init")
IF (state._created)
DBG("state.init()","state_init")
state.init(state)
state._inited=TRUE
ENDIF
ENDFUNCTION

FUNCTION state_reset: stateid //reset all the stuff then init
ALIAS state AS STATES[stateid]
state.reset(state)
state._inited = FALSE
state.pos.set(0,0)
state_init(stateid)
ENDFUNCTION

FUNCTION state_update: stateid //update
ALIAS state AS STATES[stateid]
IF (NOT state._paused)
state.update(state)
ENDIF
ENDFUNCTION

FUNCTION state_render: stateid //draw
ALIAS state AS STATES[stateid]
state.render(state)
ENDFUNCTION

FUNCTION state_emptyfunction: state AS TSTATE //dummy empty function
ENDFUNCTION

GLOBAL STATES[] AS TSTATE
GLOBAL currStateID
GLOBAL nextStateID
GLOBAL switchingState

FUNCTION newState AS TSTATE: typ$
LOCAL o AS TSTATE
o.typ$ = typ$
o.create = state_emptyfunction
o.destroy = state_emptyfunction
o.reset = state_emptyfunction
o.update = state_emptyfunction
o.render = state_emptyfunction
o._superinit()
RETURN o
ENDFUNCTION

FUNCTION addState: o AS TSTATE
o.id = BOUNDS(STATES[], 0)
DIMPUSH STATES[], o
RETURN o.id
ENDFUNCTION

FUNCTION changeState: stateid
STATES[currStateID]._pause()
currStateID = stateid
STATES[currStateID]._start()
ENDFUNCTION


Code (glbasic) Select

//an empty template, copy this for a new State, and rename all the words with 'Template' in it.

CONSTANT STATETYPE_TEMPLATE$ = "template"


FUNCTION state_Template_create: state AS TSTATE //first create, load everything

ENDFUNCTION

FUNCTION state_Template_destroy: state AS TSTATE //destroy, unload everything

ENDFUNCTION

FUNCTION state_Template_init: state AS TSTATE //init after create or reset
IF (state._created)
ENDIF

ENDFUNCTION

FUNCTION state_Template_reset: state AS TSTATE //reset all the stuff then init

ENDFUNCTION

FUNCTION state_Template_update: state AS TSTATE //update

ENDFUNCTION

FUNCTION state_Template_render: state AS TSTATE //draw

ENDFUNCTION

FUNCTION state_Template_register:
LOCAL state AS TSTATE
state = newState(STATETYPE_TEMPLATE$)
state.create = state_Template_create
state.destroy = state_Template_destroy
state.init = state_Template_init
state.reset = state_Template_reset
state.update = state_Template_update
state.render = state_Template_render
RETURN addState(state)
ENDFUNCTION


So we can create as many sates as we want, we can start/pause them, or reset/destroy.

Each state implements these functions (or use the default empty one):

create: load all the resources (Sprites, images, sounds, music, other resources), call only once

destroy: unload all the resources loaded on create, free all the memory used by state, If you want to use this state again, you have to create again before.

init: can be called only after already created the state, init all the variables, init timers, health points and so on

reset: reset the state, free all the variables initialized during init, then call the init to reinit them

update: process state, make all the calc inside update or ignore it if the state paused

render: render the state, make all your draw inside render

Albert

#2
The main loop using state machine:


Code (glbasic) Select
//gameloop
WHILE NOT KEY(0)
//init
CLEARSCREEN RGB(128,128,128)

IF (switchingState)
IF (transitionStates())
changeState(nextStateID)
ENDIF

//render
state_render(currStateID)
state_render(nextStateID)

ELSE

//process
state_update(currStateID)

//render
state_render(currStateID)
ENDIF

//finish
SHOWSCREEN
WEND


TI-994A

Hi Albert. Really great work, beautifully done! It clearly illustrates working GUI techniques in GLBasic. Thank you for sharing it with us.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too!

I love my Brick

Interesting stuff Albert, summit for me to play with later.

Thanx
I like things and do stuff.

erico

Great!
A bit over my possibility of understanding but, I guess a template for LD work always comes in handy to speed us up on such and many more occasions.

TI-994A

Hi guys! Does anyone know why the code fails on some earlier versions of GLBasic? I wasn't able to run the project on v.9.006, but it worked fine on v.10.202.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too!

Albert

If you think this stuff is cool, then check out my LD48 entry. Unfinished, but there are some cool features in it, like the simple platform game physics http://www.ludumdare.com/compo/ludum-dare-23/?action=preview&uid=11574

mentalthink

Hi Albert thanks for the Code, I use in my game Machine States, and goes very well for make a lot of things into in a Class

Slim

Thank you.
Very useful. :good:

Albert

I've compiled to HTML5 and uploaded to Kongregate just to see if this is possible. http://www.kongregate.com/games/Alberton/glbasic-test-game
Not the perfect game to showcase GLBasic true performance but I wanted smthing playable fast.

erico

Super interesting! :good:

I gave a try, works fine, hard to play.