You are the reason I understand how to read code and understand GMS 2 as much as I do now, watching your streams as lessons and less "follow and copy," utilizing these engines you have here on itch.io, going through this demo to see how the states work and what arguments pass through what to make an action execute, reading through everything and understanding what makes what tick, etc etc. Thank you Pixelated Pope! Both this and use_tdmc() have taught me more than I realized they would!
Thank you for your work! This is so unbelievably useful, and your documentation is great. Currently fiddling with TrueState for a solo project and it works wonders.
Thanks for making it "free" after all of these years. It's completely worth a donation if you're willing and able. We appreciate your contributions to the GameMaker community.
This is still an excellent way to structure a FSM in 2023 (and beyond).
I am not a programming expert, there is something i am struggling for. How to avoid code repetition? For example: I need to write the move code in every state that involves movement. Gravity is another issue, i am repeating all gravity stuffs all over the states. Any advice ?
Yeah, that is one of the downsides of the State Machine pattern. Because each state fully encapsulates everything that object is doing in any one step, that means anything that is shared is duplicated.
I often write functions like "move_and_collide" which would handle gravity and collision and all that. These "helper functions" are defined globally and available in any state on any object. Sometimes I'll allow those functions to accept arguments such as "in this state the gravity is .2, where as in this state the gravity is .3" or have them return results such as "I've hit the ground or a wall" so that the state can react accordingly.
Hmm. That may be a typo. You shouldn't need to pass the ID (which is normally the enum you use to define or switch to a state) since it should be drawing the "current" state. Sorry about the confusion.
Hello sir, I recently purchased truestate of gm market place and I cannot get the lock switch to work when trying to break out of queues. The line I ran is "truestate_switch(States.I,true)" but when i run it through debugger the truestate_switch_locked evaluates to false. Is the syntax im using wrong
Hello again, I don't know if the really fixed the problem, but i went into the truestate_switch script and alter the order of the if statements (Moved the last if statement to the top) as well as commented out the first "exit". THis seemed to work so far but i dont know if it will cause problems down the line. When you get the chance can you tell me if you find whats wrong with my queue statement? Thank you
Hmm, yeah... to be perfectly honest, the queue system is by far the least "exercised" part of TrueState. I never found a good personal use for it (and was planning on removing it from TrueState 3), and I most definitely did not test it in conjunction with the lock system.
I'd say if you got it to work, I'd be surprised if there was any real impact on other systems if you haven't already noticed them.
Yeah, nothing is broken so I think it’s fine. I find the queue system to be very useful. I’m using them to perform the attack combos for my bosses. I’ve created a library of enums, incorporating movement at attack types, and put them in an array. Now I just pick a random attack combo from that list and have boss run through the states to perform said combo. This makes creating new “dark soul type” boss combo very easy (By just make an enumeration of the attack order you want and put it in the array). I would highly suggest keeping it as I find it to be the most exciting feature in the package.
I should also thank you for the package and your web articles they have help me with my AI and game organization a lot.
Awesome! Yeah, it's really exciting to know that at least someone is using that feature. I'll definitely include it in the next version, and make sure it doesn't have the same issue you found here.
Probably not a manual, no. And Truestate itself is just a single script these days, so there's really no need for a separate package file. The reason I probably won't be releasing a manual is TrueState 3 is on the horizon, and with TS3 I intend to remove the choice between TrueState and TrueState+. As that will be a change for basic TrueState, I'll be updating the manual and hopefully putting together a video tutorial series. If you do check out TS+ and have any questions, feel free to hit me up on Discord and I'll answer any questions when I'm available.
Some packes I've created for myslef depend on TrueState. Wanted to move them to TS2+ but I guess I'll just wait for TS3 then. Thanks a lot for this great library :)
I found that "return" and removed it. Now works fine again! Thank you!
I recently started a new project and I also imported the true state parent obj, because I found it handy. So the 2022.2 update is irrelevant to this case and it was just an assumption...
If I may make a small suggestion? It is safe and won't break anything.
The debug text of truestate_draw_current is tiny and not readable on bigger resolution (and even worse in mobile development). It would be handy an additional scale argument:
I came back to you after extensively using Truestate (not Plus) and I have some question regarding the system.
1/ Why is it that when using `truestate_create_state` the function will trigger `truestate_set_default` ? On top of that `truestate_set_default`will execute the srcipt but, as I'm in the Create Event, I don't want any state's script to be executed.
There's case where it doesn't work. For exemple :
//playerSpawner Manager object
inst = instance_create_layer(x,y,"layer", obj_Player)
inst.PlayerID = 1 //or whatever value
//Player Object - player_state_init function
camera = instance_create_layer(x,y,"layer", obj_Camera)
camera.viewport = PlayerID
GMS will tell me that PlayerID is not set when it will try to assign `PlayerID` to the Camera's `viewport` variable. It's because `player_state_init` is fired when `truestate_create_state` is called in the Create Event of my new created obj_Player.
But I want `player_state_init` to be fired only when I switch to the Init state.
2/Related to 1/, I think `truestate_set_default` should be split in to distinct function :
truestate_set_default : where the systeme will rollback to if no state are found
truestate_set_start : which will be the starting state of the object.
The starting state is usually not the one you want to be the default. For exemple, I would want to launch an "intro" state, like my character walking in screen, but I don't want this state to be the default one during gameplay.
So is it me who get it wrong ? is this a bug or a "flaw" in the system and how can I work around that without doing the Alarm trick ?
Yes so having it this way solves some issues, but as you've discovered, can cause some others depending on what you are doing in your state new block.
It actually used to work the way you described, with the set default being a separate function.
There are a lot of ways to work around this, but the way you suggested would be totally okay. You have all the scripts, if you feel it should work differently from the way it does, go ahead and change it! Rip the set default out of the create script and split it out to its own function. And you can prevent the setting of the default from running the state new if you'd like and see if that simplifies things for you (though you may find it causes more problems)
You are free to use it in any commercial project! Only limitation is reselling the system to other developers as your own work, which I feel should go without saying :D
I bought this asset over at yoyo marketplace, the version there is still in 2.0.0 will we get an update there? do I need to buy the asset here on itch to get access to the update? is there a way to link my purchase to itch?
I bought this today and I missed a detail from the manual, so I contacted @Pixelated Pope via discord. He replied very fast, he was kind and helpful! As soon as he clarified a crucial detail to me I realized how powerful this tool is.
That's the plan, but I don't know exactly when I'm going to get around to it. Fortunately, the system still works really well in 2.3 as it is (I'm currently using it in a 2.3 project without any modifications)
The biggest thing I'm taking advantage of right now is that all of my state scripts for a single object are in a single script resource, which is super awesome. So my resource tree doesn't get nearly as bloated as it would have before. If I wasn't lazy, I could combine all of the truestate system scripts into a single script resource as well, but I've got them all in a folder that I never open, so it's not that big of a deal.
I have one script resource per character with a function for each state in said script resource. There is also another script resource with shared common state functions that all state code can access.
I just purchased the package and ran the demo. For the platformer, I noticed that you can move right but you can't move left. Also if you are against the wall you can't move at all... I haven't touched or manipulated any code so I thought I'd just pass this along. Cheers.
Oh, sorry for the late reply, I don't know how I missed this comment.
I just downloaded the latest yyz and tried it out and both demos seem to be working fine. If you are still experiencing issues, hit me up on discord and we'll take a look.
Are you on a mac? This seems to be related to keyboard input on Macs for some reason, and as I don't have a mac, there is no way for me to debug it. And slope collision was never a promised feature of TrueState.
I love this state machine! I did find two issues once I deleted the Top Down scripts and objects on the platformer.
"ai_vars=[0,AiState.stand,1,no_direction];" had to changed to "ai_vars=[0,AI.idle,1,no_direction];"
"ai_var[0] = 0;" had to be changed to "ai_vars[0] = 0;" for the AI to load. The AI character also cant turn left.
When I enabled "draw_text(x,y,string(dpad_dir));" on the Draw event for the Player the correct numbers appear for the directions (180, 0, 270, etc), but after moving or jumping it sets to -1. If I press left and down before jumping the character turn left before jumping but the number displayed when standing is also -1. Is the number being displayed the face_direction? If so that might be the problem.
The character will also move left after jumping (but not face left) if the left and down button are both pressed.
So -1 is the value of "no_direction". So any held direction should be between 0-360, and if there is no held direction, I use -1. If there are issues related to hitting multiple keys on the keyboard, make sure it isn't a keyboard ghosting issue (which is extremely common). Any time 3+ keys are hit at the same time, there's a good chance only 2 of them are actually registering.
I was going to fumble through making may spaceship dodge and shoot, but everywhere I looke, peeps talking about FSM and that you were the Pope in charge of such things. Looking forward to learning this and finding ways to make it work in other projects. Thanks, and also thanks for keeping the pricing low and assets great, it helps peeps like me that have pinched pennies in half.
Hmm, that's unusual. Are you using the standard state_switch() or are you trying to use the queue system? To be honest, the queue system hasn't been super well tested (not many people use it) so there may be some bugs with it. If you'd like to reach out to me on Discord, I'd be happy to help.
Additionally, and not to be a bother- is there a way to contact you for questions with using true state? I have some questions regarding changing states in response to colliding events and stuff
Absolutely! You are always welcome to ask me questions on Discord (that's just the easiest for me). I also recommend joining the GM discord server if you aren't already a member. It's a great place to get help with just about anything GM related! https://discord.gg/By6u9pC
Downloaded and implemented in no time. Extremely well organized and very effective state system! I will be using for all my upcoming projects. Thanks so much Pixelated Pope!
← Return to Asset
Comments
Log in with itch.io to leave a comment.
What's the licensing on the event system? Can the system be used in a commercial game?
You are the reason I understand how to read code and understand GMS 2 as much as I do now, watching your streams as lessons and less "follow and copy," utilizing these engines you have here on itch.io, going through this demo to see how the states work and what arguments pass through what to make an action execute, reading through everything and understanding what makes what tick, etc etc. Thank you Pixelated Pope! Both this and use_tdmc() have taught me more than I realized they would!
Happy to hear it!
Thank you for your work! This is so unbelievably useful, and your documentation is great. Currently fiddling with TrueState for a solo project and it works wonders.
Glad you enjoy it!
Thanks for making it "free" after all of these years. It's completely worth a donation if you're willing and able. We appreciate your contributions to the GameMaker community.
This is still an excellent way to structure a FSM in 2023 (and beyond).
I am not a programming expert, there is something i am struggling for. How to avoid code repetition? For example: I need to write the move code in every state that involves movement. Gravity is another issue, i am repeating all gravity stuffs all over the states. Any advice ?
Yeah, that is one of the downsides of the State Machine pattern. Because each state fully encapsulates everything that object is doing in any one step, that means anything that is shared is duplicated.
I often write functions like "move_and_collide" which would handle gravity and collision and all that. These "helper functions" are defined globally and available in any state on any object. Sometimes I'll allow those functions to accept arguments such as "in this state the gravity is .2, where as in this state the gravity is .3" or have them return results such as "I've hit the ground or a wall" so that the state can react accordingly.
Hey, using truestate_draw_current(truestate_id,x,y) what is truestate_id or how do I find it? The manual only lists the last two arguments.
Hmm. That may be a typo. You shouldn't need to pass the ID (which is normally the enum you use to define or switch to a state) since it should be drawing the "current" state. Sorry about the confusion.
Hello sir, I recently purchased truestate of gm market place and I cannot get the lock switch to work when trying to break out of queues. The line I ran is "truestate_switch(States.I,true)" but when i run it through debugger the truestate_switch_locked evaluates to false. Is the syntax im using wrong
**Edit**
Hello again, I don't know if the really fixed the problem, but i went into the truestate_switch script and alter the order of the if statements (Moved the last if statement to the top) as well as commented out the first "exit". THis seemed to work so far but i dont know if it will cause problems down the line. When you get the chance can you tell me if you find whats wrong with my queue statement? Thank you
Hmm, yeah... to be perfectly honest, the queue system is by far the least "exercised" part of TrueState. I never found a good personal use for it (and was planning on removing it from TrueState 3), and I most definitely did not test it in conjunction with the lock system.
I'd say if you got it to work, I'd be surprised if there was any real impact on other systems if you haven't already noticed them.
Yeah, nothing is broken so I think it’s fine. I find the queue system to be very useful. I’m using them to perform the attack combos for my bosses. I’ve created a library of enums, incorporating movement at attack types, and put them in an array. Now I just pick a random attack combo from that list and have boss run through the states to perform said combo. This makes creating new “dark soul type” boss combo very easy (By just make an enumeration of the attack order you want and put it in the array). I would highly suggest keeping it as I find it to be the most exciting feature in the package.
I should also thank you for the package and your web articles they have help me with my AI and game organization a lot.
Awesome! Yeah, it's really exciting to know that at least someone is using that feature. I'll definitely include it in the next version, and make sure it doesn't have the same issue you found here.
Hello your pixelated holyness
I'd like to try out TS+. I see the project file for a TS+ on 2.3.1 example. Is there also a package file and manual planned?
Probably not a manual, no. And Truestate itself is just a single script these days, so there's really no need for a separate package file.
The reason I probably won't be releasing a manual is TrueState 3 is on the horizon, and with TS3 I intend to remove the choice between TrueState and TrueState+. As that will be a change for basic TrueState, I'll be updating the manual and hopefully putting together a video tutorial series.
If you do check out TS+ and have any questions, feel free to hit me up on Discord and I'll answer any questions when I'm available.
Some packes I've created for myslef depend on TrueState. Wanted to move them to TS2+ but I guess I'll just wait for TS3 then. Thanks a lot for this great library :)
truestate_switch seems to not work in YCC builds, while it works in VM builds, after updating to 2022.2
I am not using TrueState PLUS
Interesting... Not sure why that would happen, but I'll look into it. Thanks for bringing it to my attention.
Okay. Check your begin step event.
...do you have a "return" in there?
If so, get rid of it.
Yeah, that's totally my bad. I have no idea why that is there.
I found that "return" and removed it. Now works fine again! Thank you!
I recently started a new project and I also imported the true state parent obj, because I found it handy. So the 2022.2 update is irrelevant to this case and it was just an assumption...
Thanks again!
No problem! Let me know if you find any other issues.
Excellent product!!!
If I may make a small suggestion? It is safe and won't break anything.
The debug text of truestate_draw_current is tiny and not readable on bigger resolution (and even worse in mobile development). It would be handy an additional scale argument:
Thank you for your time!
Yeah, I could probably do something like that. Good suggestion.
Hello Your Spriteness,
I came back to you after extensively using Truestate (not Plus) and I have some question regarding the system.
1/ Why is it that when using `truestate_create_state` the function will trigger `truestate_set_default` ? On top of that `truestate_set_default`will execute the srcipt but, as I'm in the Create Event, I don't want any state's script to be executed.
There's case where it doesn't work. For exemple :
GMS will tell me that PlayerID is not set when it will try to assign `PlayerID` to the Camera's `viewport` variable. It's because `player_state_init` is fired when `truestate_create_state` is called in the Create Event of my new created obj_Player.
But I want `player_state_init` to be fired only when I switch to the Init state.
2/Related to 1/, I think `truestate_set_default` should be split in to distinct function :
The starting state is usually not the one you want to be the default. For exemple, I would want to launch an "intro" state, like my character walking in screen, but I don't want this state to be the default one during gameplay.
So is it me who get it wrong ? is this a bug or a "flaw" in the system and how can I work around that without doing the Alarm trick ?
Thank you :D
Good question!
Yes so having it this way solves some issues, but as you've discovered, can cause some others depending on what you are doing in your state new block.
It actually used to work the way you described, with the set default being a separate function.
There are a lot of ways to work around this, but the way you suggested would be totally okay. You have all the scripts, if you feel it should work differently from the way it does, go ahead and change it! Rip the set default out of the create script and split it out to its own function. And you can prevent the setting of the default from running the state new if you'd like and see if that simplifies things for you (though you may find it causes more problems)
Wonderful. I'm buying, it will be very useful for me. How much license can I use in commercial products?
You are free to use it in any commercial project! Only limitation is reselling the system to other developers as your own work, which I feel should go without saying :D
I bought this asset over at yoyo marketplace, the version there is still in 2.0.0 will we get an update there? do I need to buy the asset here on itch to get access to the update? is there a way to link my purchase to itch?
I bought this today and I missed a detail from the manual, so I contacted @Pixelated Pope via discord. He replied very fast, he was kind and helpful! As soon as he clarified a crucial detail to me I realized how powerful this tool is.
Thank you @Pixelated Pope for this powerful tool!
It's good Pope. It's GOOD.
Hello, Your Spriteness.
Do you plan to write an alternative version for GMS 2.3 users to adress all the changes of the engine ?
That's the plan, but I don't know exactly when I'm going to get around to it. Fortunately, the system still works really well in 2.3 as it is (I'm currently using it in a 2.3 project without any modifications)
The biggest thing I'm taking advantage of right now is that all of my state scripts for a single object are in a single script resource, which is super awesome. So my resource tree doesn't get nearly as bloated as it would have before. If I wasn't lazy, I could combine all of the truestate system scripts into a single script resource as well, but I've got them all in a folder that I never open, so it's not that big of a deal.
Good to hear.
I was afraid that some of them would become those unreadable "compatibility script" GMS generate when you import stuff being obsolete.
Thanks.
Mmmh.
Just looking for an advice.
Is it better to:
a. keep one state script by script ressource.
b. make state as function and group them in one script ressources by character
?
I have one script resource per character with a function for each state in said script resource.
There is also another script resource with shared common state functions that all state code can access.
Hey Pope,
I just purchased the package and ran the demo. For the platformer, I noticed that you can move right but you can't move left. Also if you are against the wall you can't move at all... I haven't touched or manipulated any code so I thought I'd just pass this along. Cheers.
Oh, sorry for the late reply, I don't know how I missed this comment.
I just downloaded the latest yyz and tried it out and both demos seem to be working fine. If you are still experiencing issues, hit me up on discord and we'll take a look.
I am having this same issue. No manipulation either. This and the slope collisions don't work in the demo.
Are you on a mac? This seems to be related to keyboard input on Macs for some reason, and as I don't have a mac, there is no way for me to debug it. And slope collision was never a promised feature of TrueState.
Ah. Sorry about slope confusion. I just saw the red slope objects in the resources.
I am on a Mac. I also can't figure out what is going.
read_controls looks solid, state_ap_player_stand and state_ap_player_run and ap_move_player as well.
The weird thing is it is only run left and standard jump left. But the character will turn and move left if the down arrow/jump dash is used.
I love this state machine! I did find two issues once I deleted the Top Down scripts and objects on the platformer.
"ai_vars=[0,AiState.stand,1,no_direction];" had to changed to "ai_vars=[0,AI.idle,1,no_direction];"
"ai_var[0] = 0;" had to be changed to "ai_vars[0] = 0;" for the AI to load. The AI character also cant turn left.
When I enabled "draw_text(x,y,string(dpad_dir));" on the Draw event for the Player the correct numbers appear for the directions (180, 0, 270, etc), but after moving or jumping it sets to -1. If I press left and down before jumping the character turn left before jumping but the number displayed when standing is also -1. Is the number being displayed the face_direction? If so that might be the problem.
The character will also move left after jumping (but not face left) if the left and down button are both pressed.
So -1 is the value of "no_direction". So any held direction should be between 0-360, and if there is no held direction, I use -1. If there are issues related to hitting multiple keys on the keyboard, make sure it isn't a keyboard ghosting issue (which is extremely common). Any time 3+ keys are hit at the same time, there's a good chance only 2 of them are actually registering.
Big time follower, first time purchaser
I was going to fumble through making may spaceship dodge and shoot, but everywhere I looke, peeps talking about FSM and that you were the Pope in charge of such things. Looking forward to learning this and finding ways to make it work in other projects. Thanks, and also thanks for keeping the pricing low and assets great, it helps peeps like me that have pinched pennies in half.
Hmm, that's unusual. Are you using the standard state_switch() or are you trying to use the queue system? To be honest, the queue system hasn't been super well tested (not many people use it) so there may be some bugs with it. If you'd like to reach out to me on Discord, I'd be happy to help.
Ayy, I'm an idiot. I did not see there was a "draw_gui_end" truestate call that moved the stack forward.
System works great! Sorry for not cleaning this comment up :P
Additionally, and not to be a bother- is there a way to contact you for questions with using true state? I have some questions regarding changing states in response to colliding events and stuff
Absolutely! You are always welcome to ask me questions on Discord (that's just the easiest for me). I also recommend joining the GM discord server if you aren't already a member. It's a great place to get help with just about anything GM related!
https://discord.gg/By6u9pC
When it jumps and attacks it stays in the air?
Yes?
Downloaded and implemented in no time. Extremely well organized and very effective state system! I will be using for all my upcoming projects. Thanks so much Pixelated Pope!