I'm at a loss on how to do this effectively
by Simon Jensen · in Torque Game Builder · 10/15/2007 (5:53 pm) · 14 replies

And here's how I'm doing it right now:
basically call pickTile at the cell's position which gives me the xy in the tile layer and then do a getTileType on that and take the 3rd word which is the image frame and then do a switch$ on that.
function redBloodCell::checkFlowPosition(%this)
{
switch$(getWord ( $flowMapBackgroundObject.getTileType ( $flowMapBackgroundObject.pickTile (%this.getPosition() )),2))
{ case "0": do up impulse... etc etc.. for left down and right
}
this.schedule(2000, "checkFlowPosition");
}The only problem is that this completely grinds down the game. Ie the game runs at ~350fps without it and at around 35-40fps with it.. and that's only with 10 blood cells checking every 2 seconds..
So I'm open for suggestions on other ways to do this....
#2
--Triggers should work wonders, but only put them at appropriate places of flow change, instead of all the way along every possible path. Great call on that Phillip!
--Also, I'm really curious as to how many blood cells you have: nothing blatantly obvious in the code segment you showed screams "loss of an order of magnitude of performance!" at me, although you do have a total of 5 deep execution frames for each of those calls, which is pretty deep for TorqueScript (setting up and destroying execution frames, and especially the method calls related to them is relatively expensive).
10/15/2007 (6:51 pm)
Two quick things:--Triggers should work wonders, but only put them at appropriate places of flow change, instead of all the way along every possible path. Great call on that Phillip!
--Also, I'm really curious as to how many blood cells you have: nothing blatantly obvious in the code segment you showed screams "loss of an order of magnitude of performance!" at me, although you do have a total of 5 deep execution frames for each of those calls, which is pretty deep for TorqueScript (setting up and destroying execution frames, and especially the method calls related to them is relatively expensive).
#3
Stephen, when I have 10 blood cells calling the function i loose a little over 300 fps, however when I have just a single blood cell remaining Its only about a 10-12 fps hit. And at this point I didn't even get to write any more into the function the entire thing is the function as i posted above. I never made the cases actually do anything.
Granted all the blood cells are all trying to run at pretty much the same time (i had a 500ms randomize in their first scheduled call).
I'll be glad to provide a copy of the project if you think there's something worth investigating for a potential bug.
10/15/2007 (8:25 pm)
Thanks I'll look into triggers.Stephen, when I have 10 blood cells calling the function i loose a little over 300 fps, however when I have just a single blood cell remaining Its only about a 10-12 fps hit. And at this point I didn't even get to write any more into the function the entire thing is the function as i posted above. I never made the cases actually do anything.
Granted all the blood cells are all trying to run at pretty much the same time (i had a 500ms randomize in their first scheduled call).
I'll be glad to provide a copy of the project if you think there's something worth investigating for a potential bug.
#4
Ugh...just re-looked at your code, and you are checking every 200 milliseconds, for some strange reason I mis-read and thought I saw an extra zero (meaning checking every 2000 milliseconds, or 2 seconds).
That gives you 50 calls a second to that function, and while it still shouldn't be -that- bad, it adds up quickly.
Any chance there is an additional errant schedule that is also calling that method, so that your guys are actually checking flow much more often?
I'm going on a gut feeling here by the way--I know of games that were calling schedules that probably did more than you are at a 32 millisecond rate (design flaw!) that still got 25-ish fps, which is why it doesn't seem as if yours should be taking that much performance hit.
Triggers are definitely the way to go here though I think for optimization, as long as the trigger regions are relatively small, and you aren't doing a new trigger region for every tile, just when flow changes. That would give you a bit less direct control over the paths of your cells, but also IMO be more "realistic", if that makes sense.
10/15/2007 (8:54 pm)
I don't know that it's a bug, but it's possible. It's just that there doesn't seem to be anything that would cause that much performance loss in that code.Ugh...just re-looked at your code, and you are checking every 200 milliseconds, for some strange reason I mis-read and thought I saw an extra zero (meaning checking every 2000 milliseconds, or 2 seconds).
That gives you 50 calls a second to that function, and while it still shouldn't be -that- bad, it adds up quickly.
Any chance there is an additional errant schedule that is also calling that method, so that your guys are actually checking flow much more often?
I'm going on a gut feeling here by the way--I know of games that were calling schedules that probably did more than you are at a 32 millisecond rate (design flaw!) that still got 25-ish fps, which is why it doesn't seem as if yours should be taking that much performance hit.
Triggers are definitely the way to go here though I think for optimization, as long as the trigger regions are relatively small, and you aren't doing a new trigger region for every tile, just when flow changes. That would give you a bit less direct control over the paths of your cells, but also IMO be more "realistic", if that makes sense.
#5
I had put a warn in the function so I could make sure exactly how often it was being called, it was definitely just being called once per cell (10 times total) every 2 seconds.
I do think the triggers will give more 'realistic' feel to the flow and are going to be the way to go.
10/15/2007 (9:38 pm)
You saw right the first time, it's called every 2 seconds. ;-) I had put a warn in the function so I could make sure exactly how often it was being called, it was definitely just being called once per cell (10 times total) every 2 seconds.
I do think the triggers will give more 'realistic' feel to the flow and are going to be the way to go.
#6
In your switch statement you have a 4 or 5 deep set of nested calls--try breaking them in to single depth calls, such as:
switch$(getWord ( $flowMapBackgroundObject.getTileType ( $flowMapBackgroundObject.pickTile (%this.getPosition() )),2))
Theoretically, it shouldn't be much of a performance change, but I've always had a sneaking suspicion that nested stacks tend to cause performance issues, and it might help to point out a weakness.
10/15/2007 (9:45 pm)
This may sound weird, and it's a total guess, but would you try something for me?In your switch statement you have a 4 or 5 deep set of nested calls--try breaking them in to single depth calls, such as:
switch$(getWord ( $flowMapBackgroundObject.getTileType ( $flowMapBackgroundObject.pickTile (%this.getPosition() )),2))
%position = %this.getPosition();
%tile = $flowMapbackgroundObject.pickTile(%position);
%tileType = %flowMapbackgroundObject.getTileType(%tile);
%data = getWord(%tileType, 2);
switch$(%data)
{Theoretically, it shouldn't be much of a performance change, but I've always had a sneaking suspicion that nested stacks tend to cause performance issues, and it might help to point out a weakness.
#7
Something else you can do in regards to optimization is to store each redBloodCell's last tile in a field (redBloodCell.lastTile, for example). Then just compare the last known tile with the current tile and if they are equal then you don't have to do any more processing.
I take it these red blood cells are moving rather slowly if you are only checking every two seconds.
Also, a debugging technique is to slowly remove (comment them out) the function calls to find out if one in particular is slowing things down. Just fake out data if need be. For example, make %data = "0" and remove getWord. When doing this technique, you simply don't care how or where the blood cell's move. You are simply interested in finding out which call, if any, may be the culprit. Although I still don't see how calling this every 2 seconds for the few number of cells you have will cause such a drastic slowdown, but it may show something.
10/15/2007 (10:51 pm)
Triggers do seem appropriate.Something else you can do in regards to optimization is to store each redBloodCell's last tile in a field (redBloodCell.lastTile, for example). Then just compare the last known tile with the current tile and if they are equal then you don't have to do any more processing.
I take it these red blood cells are moving rather slowly if you are only checking every two seconds.
Also, a debugging technique is to slowly remove (comment them out) the function calls to find out if one in particular is slowing things down. Just fake out data if need be. For example, make %data = "0" and remove getWord. When doing this technique, you simply don't care how or where the blood cell's move. You are simply interested in finding out which call, if any, may be the culprit. Although I still don't see how calling this every 2 seconds for the few number of cells you have will cause such a drastic slowdown, but it may show something.
#8
Steven: That's a good thought I may see if that helps some. The cells do move rather slowly but the 2 second interval was just more of a test, I'm anticipating something more like every second. When I preak the function down this evening I'll post on the performance of each line.
I was actually thinking of breaking down the flow tiles into a huge 2d array loaded from a text file and just doing lookups on it based on the position of the sprite in the game world. Any thoughts using large 2d arrays (200x200)?
10/16/2007 (6:00 am)
Stephen: I'll give that a shot tonight and let ya know how it goes.Steven: That's a good thought I may see if that helps some. The cells do move rather slowly but the 2 second interval was just more of a test, I'm anticipating something more like every second. When I preak the function down this evening I'll post on the performance of each line.
I was actually thinking of breaking down the flow tiles into a huge 2d array loaded from a text file and just doing lookups on it based on the position of the sprite in the game world. Any thoughts using large 2d arrays (200x200)?
#9
So surprise surprise.
I broke the code down into very simple 1 call per line code like Steven Z suggested.
Almost no noticeable hit on the frame rate.
but!
everything seems to run at ~114 fps instead of the 350ish i was getting earlier.
and so I popped in the original code. and it works just as well. at 114fps
I haven't touched the code in a month... maybe it just needed to ferment..
The only thing I can think of that's really changed on my system is that I uninstalled google desktop (it had a nice habit of deciding to peg a core at 100% util whenever it wanted).
Anyway I'm going to keep the simple version so i can debug it if it happens again.
I'm not going to rule out I had something stupid in my code somewhere and I fixed it without knowing.
Oh and thanks Stephen S for the suggestion about keeping the last known tile position in a field. I put that in and I'm sure that's going to save some hefty processing when I start to scale this puppy up.
11/12/2007 (9:03 pm)
Whoa did time go flying or what.... I blame my wife for giving me a 360 and gears of war.... It was totally not my fault. So surprise surprise.
I broke the code down into very simple 1 call per line code like Steven Z suggested.
%tempPosition = %this.getPosition(); %tempTile = $flowMapBackgroundObject.pickTile(%tempPosition); %tempTileType = $flowMapBackgroundObject.getTileType(%tempTile); %tempWord = getWord(%tempTileType,2); switch$(%tempWord) ...switch echo test comments here ....And Vroooom.
Almost no noticeable hit on the frame rate.
but!
everything seems to run at ~114 fps instead of the 350ish i was getting earlier.
and so I popped in the original code. and it works just as well. at 114fps
I haven't touched the code in a month... maybe it just needed to ferment..
The only thing I can think of that's really changed on my system is that I uninstalled google desktop (it had a nice habit of deciding to peg a core at 100% util whenever it wanted).
Anyway I'm going to keep the simple version so i can debug it if it happens again.
I'm not going to rule out I had something stupid in my code somewhere and I fixed it without knowing.
Oh and thanks Stephen S for the suggestion about keeping the last known tile position in a field. I put that in and I'm sure that's going to save some hefty processing when I start to scale this puppy up.
#10
(quoting myself for reference)
It doesn't appear from your reports as if the deep execution stacks were the issue, but thanks much for checking this out for me--and grats on finding what seems to be the likely culprit (cpu pegged externally) if that does turn out to be the issue.
11/12/2007 (9:48 pm)
Quote:
Theoretically, it shouldn't be much of a performance change, but I've always had a sneaking suspicion that nested stacks tend to cause performance issues, and it might help to point out a weakness.
(quoting myself for reference)
It doesn't appear from your reports as if the deep execution stacks were the issue, but thanks much for checking this out for me--and grats on finding what seems to be the likely culprit (cpu pegged externally) if that does turn out to be the issue.
#11
But I just had to share anyway.
:)
11/12/2007 (10:40 pm)
Unexciting video of things working www.swiftthought.com/junk/flowFootage-01/index.htmlBut I just had to share anyway.
:)
#12
I thought the video looked terrific. All sorts of great looking animations. I was really impressed with the blood cells. I wasn't sure if the heart rate monitor was changing or not. I also noticed how the red cells would nudge based on the current arrow direction. Good job. Looks like you got things figured out.
Although I can't stand going to the doctor, I have always been fascinated by medical computer games. Maybe because I really liked the movie "Fantastic Voyage" as a child. I remember really wanting "Microsurgeon" for the Intellevision, but I didn't have an Intellevision to even play it.
This may sound goofy, but on the way to work, I was making a sputtering sound with my mouth/lips for your little ship.
11/13/2007 (10:59 am)
Thanks for sharing it. I didn't find it unexciting at all. I have actually been wondering how this project has been going. I referenced this thread the other day as I started implementing custom data into my tile layer and wanted to grab the code which figures out a tile, based on position coordinates.I thought the video looked terrific. All sorts of great looking animations. I was really impressed with the blood cells. I wasn't sure if the heart rate monitor was changing or not. I also noticed how the red cells would nudge based on the current arrow direction. Good job. Looks like you got things figured out.
Although I can't stand going to the doctor, I have always been fascinated by medical computer games. Maybe because I really liked the movie "Fantastic Voyage" as a child. I remember really wanting "Microsurgeon" for the Intellevision, but I didn't have an Intellevision to even play it.
This may sound goofy, but on the way to work, I was making a sputtering sound with my mouth/lips for your little ship.
#13
The heart rate monitor is probably the thing I'm most proud of. I wanted a two dimensional health indicator that was would make sense at a glance. The blips on the monitor scale vertically depending on how many healthy blood cells exist in the patient and the scrolling speed is based on how many pathogens/opponents are in the system.. Run out of blood or make the heart rate go too fast and it's game over.
Hehe I'll keep that in mind when I get to making sound effects :)
Oh and the vector arrows are just there while I build the levels, in the end they'll be replaced with a 100% transparent image.
11/13/2007 (5:27 pm)
Ahh I spent many many hours playing Microsurgeon on my old Ti99 (with speech) And those memories are very much a source of inspiration for this . Something both educational(ish) and fun.The heart rate monitor is probably the thing I'm most proud of. I wanted a two dimensional health indicator that was would make sense at a glance. The blips on the monitor scale vertically depending on how many healthy blood cells exist in the patient and the scrolling speed is based on how many pathogens/opponents are in the system.. Run out of blood or make the heart rate go too fast and it's game over.
Hehe I'll keep that in mind when I get to making sound effects :)
Oh and the vector arrows are just there while I build the levels, in the end they'll be replaced with a 100% transparent image.
#14
Neat about the heart rate monitor. I just wasn't sure how the monitor image related to what was actually going on. I thought it was a clever addition to the screen.
Keep us updated on your progress. Thanks!
11/13/2007 (7:45 pm)
Great background information. I always enjoy reading people's inspirations and insight into their creations.Neat about the heart rate monitor. I just wasn't sure how the monitor image related to what was actually going on. I thought it was a clever addition to the screen.
Keep us updated on your progress. Thanks!
Associate Phillip O'Shea
Violent Tulip
Thats just the first thing that popped into my head, I could be wrong, however.