forums

TNT Basic Forums > Programming Q&A
Any Speed Tips
< Last Thread     Next Thread >
Author
Thread        Post A Reply

11-06-2006 23:36

Posted by:
swagIT

Location:
Great Wet North (Vancouver)

Find more posts by swagIT

I've slogged through a lot of the past posts but reallly haven't found any definitive answers - I was wondering if anyone - Danny and Someone in particular could point out the top 5 or 10 WORST things to do in TNT in relation to game speed. I have been re-working a project and speeding things up considerably using the fabulous Trail and Error method but before I become too involved - it would be great to know what to avoid, if possible.

i.e. does using Map Tile to test for collisions slow things down more than using an array would?

does having 2 canvases ( canvas 0 for GUI, canvas 1 for playing surface in Viewport) slow things down.

If my gui is made up of 100+ static sprites does this slow things down when
draw frame is called? Would just a few larger

Do For Next loops slow things down a ton? Do too many Global variables cause problems are more local variables better?


etc......


cheers

barry

11-06-2006 23:40

Posted by:
someone

Location:
Quebec ( Canada )

Click Here to Email someone   Find more posts by someone

use as little drawing as possible. sprites are much faster

avoid exact collision detection

though apart from that, TNT is not the best choice for killer performances, since it's interpreted...

11-06-2006 23:56

Posted by:
swagIT

Location:
Great Wet North (Vancouver)

Find more posts by swagIT

what about buttons?

would I be better off using sprite collision instead of the Button command?

11-07-2006 00:10

Posted by:
someone

Location:
Quebec ( Canada )

Click Here to Email someone   Find more posts by someone

errr O_o buttons are to be used in menus... why do you want high performace in menus???

11-07-2006 01:25

Posted by:
swagIT

Location:
Great Wet North (Vancouver)

Find more posts by swagIT

the buttons are part of the gui to launch different windows (Notes, Macro Map, Load/Save, and Quit)

11-07-2006 08:09

Posted by:
allnodcoms

Location:
hertfordshire (England)

Click Here to Email allnodcoms   Find more posts by allnodcoms

Speed Tips...

I'll give it a go. Optimisation of code is a bit of an art, but the main thing to remember is: "The fastest piece of code in your game is the bit you don't write...". Keep it as small as possible!

Things to avoid:

Floating point. This is a lot slower than integer, so if you don't need it, don't use it. If you need finer resolution timing for example, increment as usual then check for it reaching power of two values, 8 or 16 for example. You'd just bit shift by 3 or 4 and use the resulting int.

Multiplication / Division. Ditto. SLOW! If you see M or D by a power of two value (2, 4, 8, 16 etc.) use bit shift instead, much quicker.

Drawing things you can't see. Sounds silly, but it's a lot quicker to check visibility than to let the internal clipping calls handle it. You know how big things are, the engine needs to work it out, which takes time.

Things to aim for:

Power of two. Always, always, always try to make things a power of two size. Sprites should never be 70 pixels square for example, make 'em 64. Same with maps, tile sizes and the width in tiles (number of columns, height isn't important).

Condense your 'ifs'. If you find yourself checking for something and then setting a value based on it, do you check for that value later? If so try and put the second bit of code in the original check.
If you are checking a list of conditions, for example 'if a>b and b<>c and d<e' etc. try breaking it down. In the example, if the first check fails the other two will still be evaluated, even though the following code will never execute.

To answer some questions:

'Map tile' is slower than an array check, and if you use a single dimension array it's even quicker. If your map is a power of two wide it's faster still...

Multiple canvases... Some things can't be avoided (but if they can then do it), so I'd say don't worry about this. If you need a scrolling area and static GUI then you're doing the right thing, so just go with it.

A screen completely built from sprites will be slower than a single background image. Sprites can contain transparency, but if even if they don't the code that draws them has to find this out. Fewer large sprites is quicker than more small ones, less calls to 'sprite'. And if you're drawing in a loop, less iterations.

Looping in code takes time, but the For...Next loop is the fastest conditional variant (unless you are using 'step', which slows it down). The reason for this is that machine code has a single call for this (in my day it was 'dbra', or 'decrement and branch'). Repeat...until and While...wend are compound commands, and the condition is checked every iteration, so it's slower.

Global variables make no difference, but if you want to get really picky they would be slightly faster than locals. Global values are initiated when the program starts while local values are created and disposed of at run time. You're literally talking about a few clock cycles, but at the end of the day it only takes one cycle to make you miss your next vbl...

Hope this helps...

Danny (nods)

11-07-2006 09:16

Posted by:
allnodcoms

Location:
hertfordshire (England)

Click Here to Email allnodcoms   Find more posts by allnodcoms

Forgot Buttons...

As far as I recall, button hits use 'pointInRect()' type calls but sprite collisions use bit masking as well. So button calls would be faster.

It's also good practice to divide your main loop into two sections for this type of game. If the mouse is in the GUI area you handle GUI stuff but ignore checks for clicking in the play area (you're not going to get any anyway!) and vice versa... Checking the location of the mouse is quicker then a complete set of interface checks, and the user can't click in two areas of the screen at once, so why check?

Danny (nods)

11-07-2006 12:58

Posted by:
someone

Location:
Quebec ( Canada )

Click Here to Email someone   Find more posts by someone

"'if a>b and b<>c and d<e' etc. try breaking it down. In the example, if the first check fails the other two will still be evaluated, even though the following code will never execute."

TNT does that??

11-07-2006 16:38

Posted by:
swagIT

Location:
Great Wet North (Vancouver)

Find more posts by swagIT

Wow - looks like the old "ask and you shall be given thing" does still apply in life. Thanks for such a comprehensive post Danny!

I think I'll print it out and staple it to my head!

Exactly what I was looking for!

cheers



11-07-2006 17:39

Posted by:
allnodcoms

Location:
hertfordshire (England)

Click Here to Email allnodcoms   Find more posts by allnodcoms

You're Welcome!

Glad to help out..

And 'Yes', TNT can do that.

Danny (nods)

11-07-2006 22:56

Posted by:
someone

Location:
Quebec ( Canada )

Click Here to Email someone   Find more posts by someone

"And 'Yes', TNT can do that."

no i wasn't asking if it could do 'and's in 'if's (i knew that), i was just a bit surprised that, unlike most languages, it continues evaluating conditions when the first one is wrong, even though it is sure the code won't be executed in the end anyway - so it's wasting time

11-08-2006 01:06

Posted by:
allnodcoms

Location:
hertfordshire (England)

Click Here to Email allnodcoms   Find more posts by allnodcoms

Sorry someone, been a long day...

Should have got the meaning.

Most languages? Some compilers may break down the right hand side of an if but in general, an if statement is only considered to be true if the compound result of the argument is also true. If my example had read 'if a>b and b<>c OR d<e' and the first condition failed, then by your argument, 'most languages' would get it totally wrong... Things may have changed a bit since I wrote commercial assembler, but 'way back when', the RHS was logically calculated to a single boolean.

An interesting point on 'if' statements though, did you know that an 'if' (once assembled) will do the total opposite of what you asked it to ( the result is NOTted)?

If you say 'if a=b then [do something]' the actual machine code will be 'if a<>b then [goto the bit after do something]', and the next line of code will be 'do something'. Makes sense if you think about it, just thought I'd throw that one in the mix.

Danny (nods)

11-08-2006 01:09

Posted by:
Jacob

Location:
San Francisco, CA

Click Here to Email Jacob   Find more posts by Jacob

If it does, then why doesn't this code make an error?

int a[1], b=1
if b=0 and a[-1]=0 then b=1

11-08-2006 07:21

Posted by:
allnodcoms

Location:
hertfordshire (England)

Click Here to Email allnodcoms   Find more posts by allnodcoms

Pass...

Jacob, even if TNT did bug out after a first failed argument it should still spot the array out of bounds error. It's a syntax error that should be found at 'compile' time, the contents of the variables are only evaluated at 'run' time, so how would TNT know to skip it?

Again, to be picky it is actually a valid address. It points to the byte directly before the array. An odd address, which could cause some interesting issues ( 8P ), but an address all the same.

Danny (nods)

11-08-2006 12:42

Posted by:
someone

Location:
Quebec ( Canada )

Click Here to Email someone   Find more posts by someone

hmmm... many of the tutorials i read while learning C++ and Java told that in a case of multiple 'and's, if the first one is wrong, the others are not evaluated. And i use this feature quite often - if it didn't stop evaluating it would crash, so i'm sure it works like this. Though you're right that if there's more than 'and's then it's another story.

Though, Danny, i don't understand your reaction to Jacob's code. I don't see any syntax error there?

try it like that:

int a[1], b=1, c=0
if b=0 and a[-1]=0
b=1
end if

if a[-1]=0 and b=0
b=1
end if


The first a[-1]=0 on line 2 does not seem to be excetuted, while the a[-1]=0 on line 6 is.

11-08-2006 17:33

Posted by:
allnodcoms

Location:
hertfordshire (England)

Click Here to Email allnodcoms   Find more posts by allnodcoms

This is going to run and run isn't it... ;)

They are both just logical operators. The exact operator makes no difference, it just alters the order (or precedence) of computation. Let's take if a>b and b<>c and d<e again, and assume that a is not greater than b (false), but the others are true. The computation is 'false & true & true' (note C boolean, not logical), which is false so the if fails. The second example 'if a>b and b<>c OR d<e' would give 'false & true || true' which in turn gives 'false | true', which gives a result of true, so the if passes muster and executes.

As for Jacob's code, a[-1] makes no sense. It is "Array out of Bounds". He declared an array with one element, so the only logical index value would be '0'. The name of the array is the address of the first element, and the number in parenthesis (*4 for integer) is the offset to query. Any value other than '0' will point to an area of memory that could well be occupied by something else, it is outside of the specified array dimensions and therefor an error. If the '-1' was held in a variable then the error would be a runtime one, but it's defined as a constant, and this should be picked up by TNT at 'compile' time. Whether it is technically a syntax error is open to debate, TNT would quite rightly expect to find an integer there, and it did. But the integer it found is a constant that is not within the valid range. It is therefor an error in the text of the program, not the logic... Should this be picked up by the semantic parser? IMHO it should, but either way it's an error.

Danny (nods)

11-08-2006 18:15

Posted by:
someone

Location:
Quebec ( Canada )

Click Here to Email someone   Find more posts by someone

whether it should be picked at runtime or parse time is not the point - what me and Jacob are trying to prove, is that when the command a[-1]=0 is run, the program crashes. So, if the following code doesn't crash:

int a[1], b=1, c=0
if b=0 and a[-1]=0
b=1
end if

the only reason to explain that is that a[-1]=0 is never executed. Thus, that since the first is false, the second is not evaluated at all.

just like the following C++ code will not exit:

#include <iostream>

bool exit(){
exit(0);
return true; //whatever
}

int main (int argc, char * const argv[]) {

bool b=false;

if(b && exit() ){ // the exit() func is NOT called
std::cout << "this will not print" << std::endl;
}

std::cout << "done" << std::endl;
}


hope you get my point.

11-08-2006 19:19

Posted by:
allnodcoms

Location:
hertfordshire (England)

Click Here to Email allnodcoms   Find more posts by allnodcoms

That told me then ;)

quote:
"Things may have changed a bit since I wrote commercial assembler"
Looks like they have...

quote:
"Some compilers may break down the right hand side of an if but in general, an if statement is only considered to be true if the compound result of the argument is also true."
And it looks as though TNT and gcc (or whichever app you ran the C in) do just that. I was not aware of this, so sorry SwaglT, but it still applies for 'OR' ;)

The optimisation tips I posted were taken from a series of articles I wrote for Atari World magazine about ten years ago, and were based on the STOS language, the for runner to AMOS which inspired Mark to write TNT. I could have posted many more, but unfortunately they require direct memory access, which TNT (unlike AMOS and STOS) doesn't provide. This was definitely the case for these older creators, so I assumed it still applied. My Bad...

Mmmmm... This pie is really good. What did you call it? Humble?

Danny (nods)

All times are GMT        Post A Reply

Forum Jump:
< Last Thread     Next Thread >

< Contact Us - TNT Basic >

Powered by: vBulletin Lite Version 1.0.1 Lite
Copyright © Jelsoft Enterprises Limited 2000.