@SnapFireStudios -- perhaps I got a little excited and overstated things a bit. But it is helpful to know that Boolean logic is available at the expression level. Its an extra capability that comes in handy. And besides, I like learning something new about this amazingly easy, yet incredibly versatile tool called GameSalad.
I will probably delete this and the previous three comments in a while. (I didn't mean to hijack the thread.)
tatiangMember, Sous Chef, PRO, Senior Sous-ChefPosts: 11,949
Wowsers! @ORBZ, I didn't realize that the expression editor could read Boolean operators. This is really cool! (I didn't make it to the yellow actors yet. I was floored with "not( game.Increment )" in the controller actor).
Boolean logic at the expression editor level changes everything!
I moved this post to the fast for loop. That's where I meant to post it originally. I updated the example to be faster than the original post I made here.
However, the new example doesn't use a controller so it's no longer needed to do a flip flop with the bool.
After reading this it make a huge difference in a game idea I had left alone because of the amount of timers need to make it work...I feel a game of the month coming up!!!...LOL
Not() is an undocumented function that you can use to negate a bool. ONLY a bool. Doesn't work on other data types.
Sorry, what do you mean by "negating" a bool? I know what both words mean, but are you just saying that it changes the bool to false or something? :-/ - Thomas
Have looked at it a bit already. There are some clear issues that need to be resolved. Have noted the issue for more work soon.
Is there any chance that we might one day see the performance of the Timer rule reaching the same sort of performance level of using the game.timer and self.timer approach instead?
Thanks for this! Great advice, especially breaking it down, so it is actually possible to understand what is going on there.
I actually built my own every "timer," based on the theory. It goes like this --
First off, set up two actor attributes: cycle_length and cycle_counter.
Then create a rule:
when self.Time = self.cycle_counter [do what you want to do] change self.cycle_counter to: self.cycle_counter+self.cycle_length
Set cycle_length for the duration of "every" and cycle_counter for the initial time offset, if you want (especially great for spawners, so they wait a bit before starting to work).
Looking at this approach, do you think it is as efficient as yours, or should I dump it? This came as an idea when reading your post, but I'm not sure whether the calculations happening under the surface are simpler or not.
Hello, thanks for amazing tips (in fact tutorial), but I don't understand how to do this " In fact, I recommend using these sorts of timers for animation instead of the standard animate function, it seems to play smoother and being able to adjust the animation parameters at runtime can be particularily useful for complex actors."
How to make animation with self timers, etc, how to replace GS Animation? (lets say you have 50 images for animation), thanks in advance.
Hey all (specifically @Kova), the question of how to use this method of fast looping for animation has been one of the most common questions I have received since I first made this post, and until now I have not fully diverged the secret of how I do it. At first, I purposely left it vague as this is a topic I discuss in my book, GameSalad Master Class, and I didn't want to give ALL of my secrets away . However, I feel that it is time to clarify exactly what I meant in the original post and give you all a full glimpse in on my technique for performing animation at optimal framerates using this method of looping. The following tutorial is a direct excerpt from my book (it may reference images and content from the original book that is not fully present here, but all the information you need to take advantage of this method is present) and should help to clarify the exact means that I use in my own projects to achieve ultra smooth animations that are capable of reaching a full 60fps. Of course, this full chapter of information adorned with graphics is available in my book (among many other advanced GS tips and techniques), which can be purchased from the following link: https://gumroad.com/l/gsmclass
Before we jump in, I just want to explicitly state just how bad the default GS animation behaviour is. Not only is it highly limited in its capabilities to provide robust support for advanced animation, it is highly prone to inconsistency among frame playback speed even when you are working within the 30fps limit of the default animate behaviour. This is one area where the GS team has made zero effort to improve GameSalad since as long as I've been using it; and given its poor capabilities I would have expected someone to have done some sort of overhaul on it by now. Anyways, without further adieu, here is everything you need to know about using pseudo-loops to create robust, accurate, and extremely fast animation with vastly improved performance over the default GS functions.
11.8 Animation Using Timers
For the creation of animated actors, GameSalad includes a behavior called Animate. This behavior allows you to specify a series of frames to be played in sequence at a specified speed, in FPS. The Animate behavior included in GameSalad is very glitchy, for lack of a better term, and does not lend well to high-quality animation. It tends to skip and stutter oddly, reducing the quality of your animated assets despite your best efforts to use the pre-built functions as they are intended to be used. Luckily, there is a way we can create our very own animate behavior which performs better, looks better, and allows a higher maximum FPS than 30 (which is the maximum of the included behavior).
To emulate animation as efficiently as possible, we make use of a rule-based "every" type timer, as described in the previous section. For this example, we will set our mod attribute to 0.05 and our modulus value to 0.1. The equation in our timer rule looks like so: when mod1>self.time%0.1. In addition to this, we create a new integer attribute called frame. We use the frame attribute to keep track of what frame of animation to show to the user. Inside the timer rule, we place two change attribute commands, one which increments our frame attribute (self.frame = self.frame+1) and one to apply the proper frame to our actor.
Applying the proper frame makes use of careful asset naming, combined with string concatenation. As previously mentioned, to make use of this optimization all the frames of an animation must have the same name and be sequentially numbered. Because of this correlation, we can simply force GameSalad to apply a new image with each tick of our timer using the following Change Attribute: self.image to [imagename] .. self.frame .. ".png". When we use concatenation to force GameSalad to apply an image, we must add the .png extension manually as demonstrated. Now, we wrap this rule in a second rule, which stops playing the animation when our final frame is reached. To do so, simply state when self.frame =/= [maximum frame].
The example above would play a new frame every 0.1 seconds, effectively creating animation at 10 FPS. To adjust the FPS, the value after the modulus operator (%) may be adjusted. In practice, if you need to play animation any faster than 10FPS it is better to duplicate your two Change Attribute behaviors into the otherwise section of your timer rule. This effectively doubles the FPS by switching the image during both the on and off state of the timer. When doing so, make sure your mod attribute value is exactly half of the value placed after the modulus in your equation, or the animation will play unevenly. This optimization can also be used with looping animations. To do so, simply add a Change Attribute in the otherwise section of the rule stating when self.frame =/= [maximum frame] resetting self.frame to 0, creating a looping behavior.
Depending on your needs, feel free to manipulate the frame number as you see fit. Through advanced modification of your self.frame variable, various types of animated content can be made with relative ease. For example, the animated character illustrated to the left has 24 total frames, grouped into sets of 6 frames for each cardinal direction per row. Knowing this, we can set the animation start frame for each cardinal direction at the appropriate spot, often called a keyframe, and play the next 6 frames looping in sequence. Create an integer value, I've called it keyframe, to hold this information. Modify our containing rule (self.frame =/= [maximum frame]) to state: when self.frame =/= self.keyframe+6. Next, modify the Change Attribute in the otherwise section of this rule to state: self.frame = self.keyframe. In this example, when the player moves right, we would set the self.keyframe to 18 and effectively play frames 18,19,20,21,22,23; then loop back to 18, repeating until the player is no longer moving right. The same concept applies for the other three directions. All that needs to be changed is the self.keyframe value to pick a different set of animations. In this example, the keyframes are: 0, 6, 12, and 18.
Hopefully this information should help to set you on the right path .
OMG!!! I think you just save my project as it's very heavy timer based and hitting performance issues with medium and low end devices. Can't wait to try this ASAP. Thank you so much!!!
@domenius - Is this timer technique still valid for optimization from when you originally posted it? Did GS make any crucial updates on timer func since the original post from back in 2012?
@ phamtastic As far as I know, the GS team has still failed to update the timer code to operate faster than the "trick" I have outlined in the original post. That said, GS itself has become faster than it was back when I originally posted this code. Even so, I still use this technique whenever possible to optimize advanced projects with complex code. You can get away with having a few "classic" timers in your code with minimal impact, but this technique is still very relevant to anyone trying to create advanced code or a project which requires a vast number of time events. For example, AI code can often benefit hugely from this technique since you are usually dealing with many actors that are making many decisions based on constantly repeating procedures. Even with the advances made by the GS team in recent times, this technique is still relevant in many cases.
@domenius - thanks for clarifying. I am making a huge project over 600 actors and with 40% of them using some sort of timer. Wish I read this post early
Please help, I want my splash image to change forth and back every 1 second.
I set the below rules and the first 2 seconds it changed back and forth properly but after that it is like turbo changing in 0.1 second.
Page 1:
Page 2:
tatiangMember, Sous Chef, PRO, Senior Sous-ChefPosts: 11,949
edited February 2015
I'm kind of a proponent for using built-in systems unless they don't work for me. This thread was started three years ago when the codebase for GameSalad was considerably different. Yes, you can optimize your code by swapping out Timer behaviors but unless they seem to be causing problems, why not just use them?
Timer every 1 second
.....Change attribute self.counter to self.counter+1
.....Change attribute self.Image to "Title2."..self.Counter
That will cycle through images named Title2.1, Title 2.2, Title 2.3, etc.
If you just want to cycle between two images, use the mod() function:
.....Change attribute self.Image to "Title2."..mod(self.Counter,2)+1
@tatiang said:
I'm kind of a proponent for using built-in systems unless they don't work for me. This thread was started three years ago when the codebase for GameSalad was considerably different. Yes, you can optimize your code by swapping out Timer behaviors but unless they seem to be causing problems, why not just use them?
Timer every 1 second
.....Change attribute self.counter to self.counter+1
.....Change attribute self.Image to "Title2."..self.Counter
That will cycle through images named Title2.1, Title 2.2, Title 2.3, etc.
I just want to try out the method since it will help to enhance the performance.
tatiangMember, Sous Chef, PRO, Senior Sous-ChefPosts: 11,949
An even simpler method than a Timer is to use an Animate behavior with two frames and Loop set to true. I'm a bit confused by the way you have your custom timer set up. If it's helpful, you might want to check out my Study of Loops demo that shows various ways for creating fast loops (although they could slowed down for every 1 second type timers):
Comments
Sorry, how is that helpful? :P
- Thomas
I will probably delete this and the previous three comments in a while. (I didn't mean to hijack the thread.)
New to GameSalad? (FAQs) | Tutorials | Templates | Greenleaf Games | Educator & Certified GameSalad User
However, the new example doesn't use a controller so it's no longer needed to do a flip flop with the bool.
Moved to: http://forums.gamesalad.com/discussion/55050/fast-for-loop-a-collection-from-the-community-merged-into-a-single-really-really-fast-loop#latest
Not() is an undocumented function that you can use to negate a bool. ONLY a bool. Doesn't work on other data types.
New to GameSalad? (FAQs) | Tutorials | Templates | Greenleaf Games | Educator & Certified GameSalad User
Thanks @domenius!!!
- Thomas
If the boolean is true, negating will make it false.
If the boolean is false, negating will make it true.
Here's also the wikipedia page about negation http://en.m.wikipedia.org/wiki/Negation
I hope that helps.
- Thomas
Guru Video Channel | Lost Oasis Games | FRYING BACON STUDIOS
Thanks for this! Great advice, especially breaking it down, so it is actually possible to understand what is going on there.
I actually built my own every "timer," based on the theory. It goes like this --
First off, set up two actor attributes: cycle_length and cycle_counter.
Then create a rule:
when self.Time = self.cycle_counter
[do what you want to do]
change self.cycle_counter to: self.cycle_counter+self.cycle_length
Set cycle_length for the duration of "every" and cycle_counter for the initial time offset, if you want (especially great for spawners, so they wait a bit before starting to work).
Looking at this approach, do you think it is as efficient as yours, or should I dump it? This came as an idea when reading your post, but I'm not sure whether the calculations happening under the surface are simpler or not.
Hello, thanks for amazing tips (in fact tutorial), but I don't understand how to do this " In fact, I recommend using these sorts of timers for animation instead of the standard animate function, it seems to play smoother and being able to adjust the animation parameters at runtime can be particularily useful for complex actors."
How to make animation with self timers, etc, how to replace GS Animation? (lets say you have 50 images for animation), thanks in advance.
@Kova
@Socks did a good explanation here - http://forums.gamesalad.com/discussion/63454/fast-frame-swap/p1
Website » Twitter » Facebook » Loaded Arts - Fun for thumbs.
Developer Blog » 08/01/2015 - Week 72 – Apple, the great dictator…
Before we jump in, I just want to explicitly state just how bad the default GS animation behaviour is. Not only is it highly limited in its capabilities to provide robust support for advanced animation, it is highly prone to inconsistency among frame playback speed even when you are working within the 30fps limit of the default animate behaviour. This is one area where the GS team has made zero effort to improve GameSalad since as long as I've been using it; and given its poor capabilities I would have expected someone to have done some sort of overhaul on it by now. Anyways, without further adieu, here is everything you need to know about using pseudo-loops to create robust, accurate, and extremely fast animation with vastly improved performance over the default GS functions.
11.8 Animation Using Timers
For the creation of animated actors, GameSalad includes a behavior called Animate. This behavior allows you to specify a series of frames to be played in sequence at a specified speed, in FPS. The Animate behavior included in GameSalad is very glitchy, for lack of a better term, and does not lend well to high-quality animation. It tends to skip and stutter oddly, reducing the quality of your animated assets despite your best efforts to use the pre-built functions as they are intended to be used. Luckily, there is a way we can create our very own animate behavior which performs better, looks better, and allows a higher maximum FPS than 30 (which is the maximum of the included behavior).
To emulate animation as efficiently as possible, we make use of a rule-based "every" type timer, as described in the previous section. For this example, we will set our mod attribute to 0.05 and our modulus value to 0.1. The equation in our timer rule looks like so: when mod1>self.time%0.1. In addition to this, we create a new integer attribute called frame. We use the frame attribute to keep track of what frame of animation to show to the user. Inside the timer rule, we place two change attribute commands, one which increments our frame attribute (self.frame = self.frame+1) and one to apply the proper frame to our actor.
Applying the proper frame makes use of careful asset naming, combined with string concatenation. As previously mentioned, to make use of this optimization all the frames of an animation must have the same name and be sequentially numbered. Because of this correlation, we can simply force GameSalad to apply a new image with each tick of our timer using the following Change Attribute: self.image to [imagename] .. self.frame .. ".png". When we use concatenation to force GameSalad to apply an image, we must add the .png extension manually as demonstrated. Now, we wrap this rule in a second rule, which stops playing the animation when our final frame is reached. To do so, simply state when self.frame =/= [maximum frame].
The example above would play a new frame every 0.1 seconds, effectively creating animation at 10 FPS. To adjust the FPS, the value after the modulus operator (%) may be adjusted. In practice, if you need to play animation any faster than 10FPS it is better to duplicate your two Change Attribute behaviors into the otherwise section of your timer rule. This effectively doubles the FPS by switching the image during both the on and off state of the timer. When doing so, make sure your mod attribute value is exactly half of the value placed after the modulus in your equation, or the animation will play unevenly. This optimization can also be used with looping animations. To do so, simply add a Change Attribute in the otherwise section of the rule stating when self.frame =/= [maximum frame] resetting self.frame to 0, creating a looping behavior.
Depending on your needs, feel free to manipulate the frame number as you see fit. Through advanced modification of your self.frame variable, various types of animated content can be made with relative ease. For example, the animated character illustrated to the left has 24 total frames, grouped into sets of 6 frames for each cardinal direction per row. Knowing this, we can set the animation start frame for each cardinal direction at the appropriate spot, often called a keyframe, and play the next 6 frames looping in sequence. Create an integer value, I've called it keyframe, to hold this information. Modify our containing rule (self.frame =/= [maximum frame]) to state: when self.frame =/= self.keyframe+6. Next, modify the Change Attribute in the otherwise section of this rule to state: self.frame = self.keyframe. In this example, when the player moves right, we would set the self.keyframe to 18 and effectively play frames 18,19,20,21,22,23; then loop back to 18, repeating until the player is no longer moving right. The same concept applies for the other three directions. All that needs to be changed is the self.keyframe value to pick a different set of animations. In this example, the keyframes are: 0, 6, 12, and 18.
Hopefully this information should help to set you on the right path .
Domenius
so i have a attribute and i have i in a timer right now. so to fix that would i simply do
mod1>self.time%(attribute)
This saved me so hard. I cannot tell you how much I appreciate this. Thank-you, thank-you, thank-you, thank-you. I will pay it forward.
OMG!!! I think you just save my project as it's very heavy timer based and hitting performance issues with medium and low end devices. Can't wait to try this ASAP. Thank you so much!!!
twitter.com/RoShamBoFighter
facebook.com/RoshamboFighter
@Iodine @phamtastic Always glad to hear success stories; Nice to know that even now this post is still helping people
@I_AM_BENJI This reply is a bit late but yes, you have the right idea.
Domenius
@domenius - Is this timer technique still valid for optimization from when you originally posted it? Did GS make any crucial updates on timer func since the original post from back in 2012?
Phamtastic
twitter.com/RoShamBoFighter
facebook.com/RoshamboFighter
Yes I agree with @phamtastic would be nice to have an update even though there have been improvements and @CodeWizard post is nearly two years old .
Universal Binary Template - Universal Binary Template Instructions Rev 4 (Short) - Custom Score Display Template
@ phamtastic As far as I know, the GS team has still failed to update the timer code to operate faster than the "trick" I have outlined in the original post. That said, GS itself has become faster than it was back when I originally posted this code. Even so, I still use this technique whenever possible to optimize advanced projects with complex code. You can get away with having a few "classic" timers in your code with minimal impact, but this technique is still very relevant to anyone trying to create advanced code or a project which requires a vast number of time events. For example, AI code can often benefit hugely from this technique since you are usually dealing with many actors that are making many decisions based on constantly repeating procedures. Even with the advances made by the GS team in recent times, this technique is still relevant in many cases.
@domenius - thanks for clarifying. I am making a huge project over 600 actors and with 40% of them using some sort of timer. Wish I read this post early
twitter.com/RoShamBoFighter
facebook.com/RoshamboFighter
Please help, I want my splash image to change forth and back every 1 second.
I set the below rules and the first 2 seconds it changed back and forth properly but after that it is like turbo changing in 0.1 second.
Page 1:
Page 2:
I'm kind of a proponent for using built-in systems unless they don't work for me. This thread was started three years ago when the codebase for GameSalad was considerably different. Yes, you can optimize your code by swapping out Timer behaviors but unless they seem to be causing problems, why not just use them?
Timer every 1 second
.....Change attribute self.counter to self.counter+1
.....Change attribute self.Image to "Title2."..self.Counter
That will cycle through images named Title2.1, Title 2.2, Title 2.3, etc.
If you just want to cycle between two images, use the mod() function:
.....Change attribute self.Image to "Title2."..mod(self.Counter,2)+1
New to GameSalad? (FAQs) | Tutorials | Templates | Greenleaf Games | Educator & Certified GameSalad User
I just want to try out the method since it will help to enhance the performance.
An even simpler method than a Timer is to use an Animate behavior with two frames and Loop set to true. I'm a bit confused by the way you have your custom timer set up. If it's helpful, you might want to check out my Study of Loops demo that shows various ways for creating fast loops (although they could slowed down for every 1 second type timers):
http://forums.gamesalad.com/discussion/comment/381275/#Comment_381275
New to GameSalad? (FAQs) | Tutorials | Templates | Greenleaf Games | Educator & Certified GameSalad User