Author Topic: StateMachine  (Read 5315 times)

Offline Albert

  • Dr. Type
  • ****
  • Posts: 257
    • View Profile
    • Blog
StateMachine
« on: 2012-May-21 »
Hi!

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

[attachment deleted by admin]

Offline Albert

  • Dr. Type
  • ****
  • Posts: 257
    • View Profile
    • Blog
Re: StateMachine
« Reply #1 on: 2012-May-21 »
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
« Last Edit: 2012-May-21 by Albert »

Offline Albert

  • Dr. Type
  • ****
  • Posts: 257
    • View Profile
    • Blog
Re: StateMachine
« Reply #2 on: 2012-May-21 »
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
« Last Edit: 2012-May-21 by Albert »

Offline TI-994A

  • Community Developer
  • Mr. Polyvector
  • ******
  • Posts: 112
  • You can do it in BASIC!
    • View Profile
Re: StateMachine
« Reply #3 on: 2012-May-21 »
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!

Offline I love my Brick

  • Mr. Drawsprite
  • **
  • Posts: 61
    • View Profile
Re: StateMachine
« Reply #4 on: 2012-May-21 »
Interesting stuff Albert, summit for me to play with later.

Thanx
I like things and do stuff.

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4310
    • View Profile
    • Portfolio
Re: StateMachine
« Reply #5 on: 2012-May-22 »
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.

Offline TI-994A

  • Community Developer
  • Mr. Polyvector
  • ******
  • Posts: 112
  • You can do it in BASIC!
    • View Profile
Re: StateMachine
« Reply #6 on: 2012-May-22 »
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!

Offline Albert

  • Dr. Type
  • ****
  • Posts: 257
    • View Profile
    • Blog
Re: StateMachine
« Reply #7 on: 2012-Jun-22 »
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

Offline mentalthink

  • Prof. Inline
  • *****
  • Posts: 3372
  • Integrated Brain
    • View Profile
Re: StateMachine
« Reply #8 on: 2012-Jun-22 »
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

Offline Slim

  • Mc. Print
  • *
  • Posts: 12
    • View Profile
Re: StateMachine
« Reply #9 on: 2012-Jun-23 »
Thank you.
Very useful. :good:

Offline Albert

  • Dr. Type
  • ****
  • Posts: 257
    • View Profile
    • Blog
Re: StateMachine
« Reply #10 on: 2013-May-06 »
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.

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4310
    • View Profile
    • Portfolio
Re: StateMachine
« Reply #11 on: 2013-May-07 »
Super interesting! :good:

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