You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Last time I rewrote the FSM and gamestate modules I represented them as directed graphs. Im not a huge fan of how they ended up. Specifically I've grown to like modules to be "self contained". The ultimate goal being able to just copy/paste any one of the files if you'd like! Also the re-naming of macros is a bit goofy to me.
Since then I came across this random rust-lisp project, that had a really interesting class DSL that embedded states as a first class citizen of the class! In gamedev almost every class ends up needing states, so this api makes a lot of sense to me. It pretty cleanly represents the needs of FSM and gamestates!
Here's the half baked implementation I've used in a couple games
# Class Creator# Inspired by https://gamelisp.rs/reference/state-machines.html# dont worry though, it just wraps the common Table Prototype way of doing OOP in Janet
(defnfirst-as-keyword [[form-symbol&rest]]
[(keywordform-symbol) ;rest])
(defnto-class-prototype [forms&optstate-name]
(->>forms
(map |(match (first-as-keyword$)
[:defnname&body]
(tuple (keywordname)
~(fn ,(ifstate-name
(symbolstate-name"/"name)
name)
,;body))
[:def-statestate-name&state-forms]
(tuple (keywordstate-name)
(to-class-prototypestate-formsstate-name))
_ []))
(from-pairs)))
(defnto-default-values [forms]
(->>forms
(map |(match (first-as-keyword$)
[:fieldnameval]
(tuplenameval)
[:def-statestate-name&state-forms]
(tuple (keywordstate-name)
(to-default-valuesstate-forms))
_ []))
(from-pairs)))
(defmacrodef-class [name&forms]
~(upscope
(def ,name ,(to-class-prototypeforms))
(defn ,(symbolname"/init") [&overrides]
(defaultoverrides [])
(vartbl
(table/setproto
(merge ,(to-default-valuesforms)
(table ;overrides))
,name))
(when-let [init-fn (gettbl:init)]
(:inittbl))
tbl)))
(defnGOTO [tabstate-name&enter-args]
(varold-state-name (tab:state))
(puttab:statestate-name)
# Clear out old fields
(eachkey (gettab:__state_keys__ [])
(puttabkeynil))
# Copy new state keys out to tab
(let [proto-tab (get (table/getprototab) state-name)
inst-tab (gettabstate-name)
merged-tab (merge @{} proto-tabinst-tab)]
(puttab:__state_keys__ (keysmerged-tab))
(each [keyval] (pairsmerged-tab)
(puttabkeyval)))
# call the "on-enter" fn if present on new state
(when-let [on-enter-fn (gettab:on-enter)]
(on-enter-fntabold-state-name ;enter-args))
# return table for chainingtab)
The text was updated successfully, but these errors were encountered:
Last time I rewrote the FSM and gamestate modules I represented them as directed graphs. Im not a huge fan of how they ended up. Specifically I've grown to like modules to be "self contained". The ultimate goal being able to just copy/paste any one of the files if you'd like! Also the re-naming of macros is a bit goofy to me.
Since then I came across this random rust-lisp project, that had a really interesting class DSL that embedded states as a first class citizen of the class! In gamedev almost every class ends up needing states, so this api makes a lot of sense to me. It pretty cleanly represents the needs of FSM and gamestates!
Here's the half baked implementation I've used in a couple games
The text was updated successfully, but these errors were encountered: