Jump to content


Photo

Keeping 30fps


  • Please log in to reply
28 replies to this topic

#1 holgersson1988

holgersson1988

    GMC Member

  • GMC Member
  • 141 posts
  • Version:GM:Studio

Posted 07 July 2010 - 03:38 PM

Hi I'm pretty much done with a game that I am very proud of and have worked on for pretty much a year and a half.
It's a top down strategy/castle defense game called Fortify.

The problem I have now, is that even a high end computer can have trouble keeping a steady frame rate in a few levels when there are a lot of enemies. On old computers and laptops it's almost unplayable :(

Now I've tried to keep code out of the step event of an object, and if necessary I've minimized it (as much as my skill permits).

The question is...are there any other common causes of frame rate drop than a lot of stuff in the step event??

Thank you for your time :)
//The Holgmeister
  • 0

#2 Phantom107

Phantom107

    Engineer

  • GMC Member
  • 2592 posts
  • Version:GM:Studio

Posted 07 July 2010 - 03:46 PM

Using a ton of objects instead of using arrays, tons of collision checking, unnecessary updating: for example executing AI planning every 30 steps.
  • 0

#3 Xcure

Xcure

    GMC Member

  • New Member
  • 44 posts

Posted 07 July 2010 - 03:46 PM

What I think make games slow is, big sprites,large sounds/music,many objects in a room,and Hight quality sprites, :P that is all I think :P so you may have to cut stuff like sprites in some games, or else the pc you try your games on is just slow, have you published the game so I can test it and may say whats wrong
  • 0

#4 holgersson1988

holgersson1988

    GMC Member

  • GMC Member
  • 141 posts
  • Version:GM:Studio

Posted 07 July 2010 - 03:52 PM

Thanks for the fast replies it helps to hear from someone else instead of sitting alone and speculating :D

Yes I uploaded a beta a few weeks ago, you can try it here:
Fortify Beta
It will probably now start to lag until you have played it for some time, but you get the concept.

I have a new computer with i7 processor (Quad 2,66GHz), 6gb DDR3 and 1,8Gb graphics memory...


Using a ton of objects instead of using arrays, tons of collision checking, unnecessary updating: for example executing AI planning every 30 steps.


What do you mean by "...instead of using arrays"? should I use arrays for objects? how?


Thanks!
//The Holgmeister
  • 0

#5 Phantom107

Phantom107

    Engineer

  • GMC Member
  • 2592 posts
  • Version:GM:Studio

Posted 07 July 2010 - 04:44 PM

What do you mean by "...instead of using arrays"? should I use arrays for objects? how?

By using arrays you can simulate objects, which is TONS faster that using a lot of objects. You will agree with me when you master this technique.

For example, simulating movement for 100 virtual objects (by using simulation by arrays):

i = -1;
repeat 100
begin
    i += 1;

    object_x[i] += object_x_speed[i];
    object_y[i] += object_y_speed[i];
end;

PS: Saying "I got 1.8 GB on my video card" isn't saying much, since it's the speed that really counts. For example, my GTX 275 896 MB is tons better than a 8800GTX with 2 GB. It's all in the speed.

PPS: Do realise that your i7 has 8 calculating threads, and GM can only use 1 of them. Single, dual, quad or octo core doesn't matter a thing, GM will only use 1 thread.
  • 0

#6 holgersson1988

holgersson1988

    GMC Member

  • GMC Member
  • 141 posts
  • Version:GM:Studio

Posted 07 July 2010 - 05:03 PM

By using arrays you can simulate objects, which is TONS faster that using a lot of objects. You will agree with me when you master this technique.

For example, simulating movement for 100 virtual objects (by using simulation by arrays):

i = -1;
repeat 100
begin
    i += 1;

    object_x[i] += object_x_speed[i];
    object_y[i] += object_y_speed[i];
end;

PS: Saying "I got 1.8 GB on my video card" isn't saying much, since it's the speed that really counts. For example, my GTX 275 896 MB is tons better than a 8800GTX with 2 GB. It's all in the speed.

PPS: Do realise that your i7 has 8 calculating threads, and GM can only use 1 of them. Single, dual, quad or octo core doesn't matter a thing, GM will only use 1 thread.


Ok i don't really get it :P, but it seems it won't work for me or will be way too complicated now...guess I'll go on the hunt on google for a tutorial :)


To your PS:es - I have a Geforce GTX260, I dont know how fast it is :P
I figured that GM only used 1 thread :(
  • 0

#7 Radmetalmonk

Radmetalmonk

    GMC Member

  • New Member
  • 180 posts

Posted 07 July 2010 - 05:57 PM


What do you mean by "...instead of using arrays"? should I use arrays for objects? how?

By using arrays you can simulate objects, which is TONS faster that using a lot of objects. You will agree with me when you master this technique.

For example, simulating movement for 100 virtual objects (by using simulation by arrays):

i = -1;
repeat 100
begin
    i += 1;

    object_x[i] += object_x_speed[i];
    object_y[i] += object_y_speed[i];
end;

PS: Saying "I got 1.8 GB on my video card" isn't saying much, since it's the speed that really counts. For example, my GTX 275 896 MB is tons better than a 8800GTX with 2 GB. It's all in the speed.

PPS: Do realise that your i7 has 8 calculating threads, and GM can only use 1 of them. Single, dual, quad or octo core doesn't matter a thing, GM will only use 1 thread.


My array knowledge is low and exclusive to java (even though it's more or less the same concept). What that snippet of code is doing is this:
Firstly, think of i as a variable, one that usually counts (IE i = 0, i = 1, i = 2, ect). So this counting variable is starting at -1.

Next, repeat 100 will execute the code between the begin and end (like the drag and drop brackets kind of, or just the { } in code). What's that repeated code doing? Well i is being increased by 1 each time, so again, i is acting as a "counting variable".

Now I'm not entirely sure what's going on with object_x[i] += object_x_speed[i]; But, i is counting right? Well what this does is allows you to store data into an array.

For example, say you have this code (we'll ignore the concept of i)
array[0] = 'Bob'
array[1] = 100
array[2] = 4
array[3] = 20
array[4] = 'Bob is a cool guy, sometimes...'
This is storing information into 'array' (just the name a picked, you can call it walnutfeces if you want...it doesn't matter). So at position (what's in the [ ] ) 0 so [0] is a name which is a string. At [1] is hp, at [2] could be movement or speed, [3] is attack, [4] is a description. Notice how you can store different types of stuff in arrays (Actually, I'm not sure on this...in java arrays have types like a string array or an integer array...I've used GM arrays with different types of data though).

So when using i, you can move through the array "automatically" so to speak, count through it.
Like by using a for loop (or the repeat)
for (i = 0; i < 5; i += 1){
draw_text(0,0+i*16,string(array[i]));
}

What the above code will do (put into a draw event) will loop 5 times. i starts at 0, it checks to see if i is less than 5 (if you started on 1, you'd want it to be less than or equal to 5 or less than 6) and it increases i by 1 each loop.

Inside the loop (done 5 times) it will draw text at 0,0+i*16 so when i = 0 (on the first loop) it will draw it at 0,0+0*16 so at 0,0. On the 2nd loop (i is now 1) it will draw the text at 0,0+1*16 so at 0,16...and so on.

What it draws will be what is stored in array 'array'. So when i = 0, it will draw 'Bob', when it is 1 it will draw 100, and so on (see what I stored in it above).

I understand some of this stuff won't work (I don't know if you can draw with a for loop, it sounds like a bad idea) but you get the picture. I added a string(...) to it because some of the data is not a string.

object_x[i] += object_x_speed[i]
So basically what this would do, what I think anyways is that
it's increasing the speeds of individual objects by what they are set to increase.
It's 2 arrays, object_x which is a list of objects and object_x_speed which is a list of speeds for those objects (to increase by).
So on i = 0, object_x[0] (whatever is stored there, could be an id could be an object name, whatever). increases by object_x_speed[0]...which doesn't make sense.

Perhaps
object_x[i].hspeed += object_x_speed[i];
? That way it's hspeed is increasing, not it's id or whatever. Granted, I may not undestand what's really going down here.

Well I hope this rough tut on arrays helped. Also for lowering the FPS, make sure anything out of the room is either destroyed or not visible. Don't bog down the draw events either.
  • 0

#8 holgersson1988

holgersson1988

    GMC Member

  • GMC Member
  • 141 posts
  • Version:GM:Studio

Posted 07 July 2010 - 08:51 PM

Ok I think i get the idea now, what Radmetalmonk said makes sense.
And I do have some stuff in the draw event of many objects... but I can't see how I can remove this, perhaps I will try to do some Array stuff for objects.

//The Holgmeister
  • 0

#9 Phantom107

Phantom107

    Engineer

  • GMC Member
  • 2592 posts
  • Version:GM:Studio

Posted 07 July 2010 - 08:54 PM

Be careful with array drawing, it is key to develop efficiency systems for it.

For instance, put all array-objects in square zones and only loop through the array-objects when they're in a zone visible to the player.

And Radmetalmonk, "object_x[i].hspeed += object_x_speed[i];" is indeed a replacement of hspeed.
  • 0

#10 spicydeath82

spicydeath82

    Awesomesauce

  • New Member
  • 138 posts
  • Version:GM8

Posted 07 July 2010 - 09:09 PM

you could turn off synchronization in the game options, from what i understand it really doesn't do much and eats up some valuable cpu time. but with out seeing your editable i'm not sure what can be done...
  • 0

#11 holgersson1988

holgersson1988

    GMC Member

  • GMC Member
  • 141 posts
  • Version:GM:Studio

Posted 08 July 2010 - 12:24 AM

you could turn off synchronization in the game options, from what i understand it really doesn't do much and eats up some valuable cpu time. but with out seeing your editable i'm not sure what can be done...


Thank you! That's exactly the kind of stuff I'm looking for. While checking that on google I also found this if anyone is interested: Optimizing for speed and memory

I will report back tomorrow when i have tested the game again...it's getting late G'night!

//The Holgmeister
  • 0

#12 Phantom107

Phantom107

    Engineer

  • GMC Member
  • 2592 posts
  • Version:GM:Studio

Posted 08 July 2010 - 12:35 AM

Make an option for vsync. Don't disable stuff if you don't know what it does. RTS gameplay is horrible without it.

Also, if you do learn how to do the array techniques, your game will likely increase +100% performance and I'm not kidding. That is where you should look into, but I do think it's intimidating at first.

  • 0

#13 phocker

phocker

    GMC Member

  • GMC Member
  • 46 posts
  • Version:Unknown

Posted 08 July 2010 - 03:38 AM


What do you mean by "...instead of using arrays"? should I use arrays for objects? how?

By using arrays you can simulate objects, which is TONS faster that using a lot of objects. You will agree with me when you master this technique.

For example, simulating movement for 100 virtual objects (by using simulation by arrays):

i = -1;
repeat 100
begin
    i += 1;

    object_x[i] += object_x_speed[i];
    object_y[i] += object_y_speed[i];
end;

PS: Saying "I got 1.8 GB on my video card" isn't saying much, since it's the speed that really counts. For example, my GTX 275 896 MB is tons better than a 8800GTX with 2 GB. It's all in the speed.

PPS: Do realise that your i7 has 8 calculating threads, and GM can only use 1 of them. Single, dual, quad or octo core doesn't matter a thing, GM will only use 1 thread.


I'm not getting the whole "using an array as an object" example. Are you saying that one could setup an array for all the different attributes that an object has? Are there any tuts out there on this technique?
  • 0

#14 Phantom107

Phantom107

    Engineer

  • GMC Member
  • 2592 posts
  • Version:GM:Studio

Posted 08 July 2010 - 09:33 AM

I'm not getting the whole "using an array as an object" example. Are you saying that one could setup an array for all the different attributes that an object has? Are there any tuts out there on this technique?

All objects are, is a collection of variables and easy interaction. But that can be completely simulated using arrays. The benefits are no useless variables, no useless internal object calculations and most of all: extreme control over drawing performance. I don't think there are any tutorials though. Maybe I'll make one some day.
  • 0

#15 Kresjah

Kresjah

    GMC Member

  • GMC Member
  • 45 posts

Posted 08 July 2010 - 10:13 AM



What do you mean by "...instead of using arrays"? should I use arrays for objects? how?

By using arrays you can simulate objects, which is TONS faster that using a lot of objects. You will agree with me when you master this technique.

For example, simulating movement for 100 virtual objects (by using simulation by arrays):

i = -1;
repeat 100
begin
    i += 1;

    object_x[i] += object_x_speed[i];
    object_y[i] += object_y_speed[i];
end;

PS: Saying "I got 1.8 GB on my video card" isn't saying much, since it's the speed that really counts. For example, my GTX 275 896 MB is tons better than a 8800GTX with 2 GB. It's all in the speed.

PPS: Do realise that your i7 has 8 calculating threads, and GM can only use 1 of them. Single, dual, quad or octo core doesn't matter a thing, GM will only use 1 thread.


I'm not getting the whole "using an array as an object" example. Are you saying that one could setup an array for all the different attributes that an object has? Are there any tuts out there on this technique?


Just as an example (and probably not the best example either, but should be clear enough in my opinion), you want some effects that make it look like some object with an animating sprite is moving across the room. However, you want this object to solely be a scenery object and nothing else (no form of interaction, no collision, nothing else but purely the visual stuff). Instead of making an object with nothingness in it, create an array that stores the necessary animation and movement info, then iterate through that array instead. For this particular example, you would still need a controller object, but you will still only need a single real object to handle all the "virtual objects" (arrays).

I.e.
/* Code defining available virtual objects. Could be placed in create event
	of the controller object, or room creation, or something completely else
	depending on intended use.

	Let's start with only defining a single object. We need to know what sprite it
	should use and its starting x and y positions. */

// List of sprites for the objects
virtualobjects_sprite[0] = ground_ball_rolling_1;

// Assume that the second level index 0 is x and index 1 is y.
virtualobjects_position[0,0] = 200;
virtualobjects_position[0,1] = 35;

number_of_virtual_objects = 1; // We only have one object in here for now.
 
/* This is the code where things are happening. Placed in the step event for the
	controller object. */

i = 0;
repeat(number_of_virtual_objects) {
	// Assume we want to move the object 5 pixels x and 2 pixels y per step.
	virtualobjects_position[i,0] += 5;
	virtualobjects_position[i,1] += 2;

	draw_sprite(virtualobjects_sprite[i], -1, virtualobjects_position[0,0], virtualobjects_position[0,1]);
	i += 1;
}

Does this seem fairly straight forward? If you only have a single object, simulating it through an array like this won't yield all that much. However, if you have a larger game with multiple of these kinds of objects, you can gain a fair bit, as you'd still only need to do it in a single controller object. The base premise here is that if you don't need an object to have any particular interactions requiring them to be instances (not being dependant on GM functions that expect an instance, like move_bounce_solid), then you may be eligible for saving some processing cycles on this.

One of the reasons this works well is that Game Maker cycles through all objects (active at least, don't know about inactive ones) each step to run its relevant events, whilst with this one you can control yourself how, when and where to cycle through the virtual objects. Each time an object is created, Game Maker also sets a bunch of variables for it, even though we never use them; like these: x, y, xprevious, yprevious, xstart, ystart, hspeed, vspeed, direction, speed, friction, gravity, gravity_direction). Even if you never have any use for vspeed, friction and the two gravity variables, these variables will still be created.

Note that the following paragraph is theorycrafting of sorts. I don't know how GM handles the updating of these though, if it updates them once per step or if it updates them only when it changes. If it is the former (so that even if you haven't moved the object, it still sets a "new" x; if x is 5 last step and it hasn't moved, instead of leaving it, GM may [again, depending on how it handles it] execute some code similar to x = 5 each step), then using arrays like this might again save cycles since, as mentioned before, you have control of when to update and what to update.

The example I chose probably isn't all that efficient, but it does serve its purpose. With it, you have effectively created an "object" (in the virtual sense) that moves across the room. However, it will not use up extra cycles in with loops (except for one due to the controller object) as they don't treat it as a real object, it will never enter any regular collision check, they won't take up an instance IDs, there is no attempts to draw them when you don't explicitly tell it do so, etc.

I am actually doing something like this for a game right now. I have certain "tiles" in my room that I want to animate, but there shouldn't be any kind of interactions with it. Instead of having it as objects with animated sprites and placing them into the room, I have a subset of arrays that a controller object loops through to play these animations. It doesn't set any of these useless variables, and I will never have to worry about them being iterated through during a with loop (which would waste cycles), nor that I accidentally include them in collision checks.

EDIT: Code errors fixed.

Edited by Kresjah, 08 July 2010 - 11:34 AM.

  • 0

#16 Phantom107

Phantom107

    Engineer

  • GMC Member
  • 2592 posts
  • Version:GM:Studio

Posted 08 July 2010 - 10:56 AM

Kresjah, you're far better than me at explaining things in Englishm but your code isn't fully correct:

i = -1; // Start at -1 so the loop will start at -1 + 1 = 0. Array variables start at index 0
repeat number_of_virtual_objects
begin;
        i += 1; // Increase loop index ID, this is important

        // Assume we want to move the object 5 pixels x and 2 pixels y per step.
        virtualobjects_position[i,0] += 5;
        virtualobjects_position[i,1] += 2;
        // Don't forget to use i in the array indexes, otherwise it won't be dynamic.

        draw_sprite(virtualobjects_sprite[i], -1, virtualobjects_position[i,0], virtualobjects_position[i,1]);
end

Using begin end; or { } doesn't matter since it's the same, but I'm one of the few that prefers begin end;
  • 0

#17 Kresjah

Kresjah

    GMC Member

  • GMC Member
  • 45 posts

Posted 08 July 2010 - 11:33 AM

Kresjah, you're far better than me at explaining things in Englishm but your code isn't fully correct:

i = -1; // Start at -1 so the loop will start at -1 + 1 = 0. Array variables start at index 0
repeat number_of_virtual_objects
begin;
        i += 1; // Increase loop index ID, this is important

        // Assume we want to move the object 5 pixels x and 2 pixels y per step.
        virtualobjects_position[i,0] += 5;
        virtualobjects_position[i,1] += 2;
        // Don't forget to use i in the array indexes, otherwise it won't be dynamic.

        draw_sprite(virtualobjects_sprite[i], -1, virtualobjects_position[i,0], virtualobjects_position[i,1]);
end

Using begin end; or { } doesn't matter since it's the same, but I'm one of the few that prefers begin end;


You are absolutely right. I didn't actually test the code, whipped it up in a hurry (slightly busy since I'm leaving for holiday tomorrow). Regardless, I'll fix it up right away. :)

Oh, and it doesn't necessarily have to be i = -1, as that depends on where one puts the i += 1 (which I incidentally completely forgot). I would normally have put it after the calculations (unless I needed it to happen before the calculations for some reason). And I forgot to actually replace the first index of each virtualobjects_position with i... hooray for copy and paste. xD

On a slight off-topic sidenote just to reply, it's good to see people using that method (begin/end) too. Whilst it might be easier to read other peoples code when there is a single, stringent standard, having multiple choices and preferences allows flexibility for people who have troubles understanding certain parts of the foundation behind the language, and is something that will sometimes spark a little debate on what is best... which can be healthy as I'd say that if everyone was satisfied with a single standard, there would be little chances for improved evolutions of the standards. [Wow, too long sentence]

Edited by Kresjah, 08 July 2010 - 11:36 AM.

  • 0

#18 rade134

rade134

    GMC Member

  • New Member
  • 211 posts

Posted 10 July 2010 - 02:22 PM

These are my main way of creating fast game play...

Draw only what's on the screen! The results from a laggy game would speed up without graphic's.
So if you're only drawing what you have on the screen it lower's the amount of work gamemaker has to do every
drawing step.


I also agree that creating array's for objects will speed things up, but there is another way to do this than
array's. An easier way would be having a drawing object which draw's everything on the screen
for each object. This will mean that you wont have to initialize a drawing system
for each object and this will speed up your.

I can give you an example which show's 2000 fake 3D object's which are drawn when only on the screen which
creates no lag.

Edited by rade134, 10 July 2010 - 02:24 PM.

  • 0

#19 tabc3dd

tabc3dd

    GMC Member

  • GMC Member
  • 658 posts

Posted 10 July 2010 - 06:01 PM

These are my main way of creating fast game play...

Draw only what's on the screen! The results from a laggy game would speed up without graphic's.
So if you're only drawing what you have on the screen it lower's the amount of work gamemaker has to do every
drawing step.


I also agree that creating array's for objects will speed things up, but there is another way to do this than
array's. An easier way would be having a drawing object which draw's everything on the screen
for each object. This will mean that you wont have to initialize a drawing system
for each object and this will speed up your.

I can give you an example which show's 2000 fake 3D object's which are drawn when only on the screen which
creates no lag.




But then again, if most of your objects are on the screen, wouldn't the lag caused by verifying if the object is on the screen compensate the lag lost by not drawing stuff out of the screen ?


  • 0

#20 Phantom107

Phantom107

    Engineer

  • GMC Member
  • 2592 posts
  • Version:GM:Studio

Posted 10 July 2010 - 08:11 PM

Absolutely not. With your object technique, you're constantly checking if an object is in the view. Do you know how much power that consumes if you have 50-100 objects? It would be an enormous waste.

With array looping however, it is easy to link array entries to grid fields in the map (because the grid field an array "object" is in is already calculated by the pathfinding!). Then you just let a loop run through the array entries that are in a visible grid field. Instead of checking if something is visible, this technique already knows what's visible and can directly draw it!

  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users