Reducing redundancy:When referring to the resolution of the game:
Normal
(not initialized)
- Code: Select all
x=view.width*0.5;
y=view.height*0.5;
Would put an actor in the center (of a 320,240 game center (not 0))
But how many times will you do this?
How about having more variables? On startup:
- Code: Select all
vx=view.width*0.5;
vy=view.height*0.5;
Now you can refer to an already set variable to find a spot in the view; instead of having width*0.5; appear (in a swarming game, perhaps millions of times) in an enemy script? If you change the game resolution, vx and vy will still initialize normally.
Changing Resolutions:So too, when the bullet is fired, directional_velocity=5; but when you lower the game resolution (for gp2x or such), now your bullets fly too fast. You have to go readjust
everything to change your game resolution. BUT
If the game is intended for , say 640x480, you initialize with:
- Code: Select all
globalspeed=(view.width/640);
Now when you change the resolution to 320 x240, globalspeed will come out as 0.5, and on bullet>createactor>
directional_velocity=5*globalspeed;
Now if you're using a good system of inheritance, where a ship holds the speed of its created bullet, and passes that speed on, you don't have to use the globalspeed very often; you simply spawn a ship with a bulletspeed variable of 5*globalspeed, which it will pass on to the bullets it spawns.
It sounds complicated, but if you use an intelligent inheritance system, you can write a game that takes NO RECODING to change the resolutions.
Always try to push decisions farther up the chain! If you can decide something at startup, do it!
If you need to create a complex map array, do it while the user is on the title screen, and cpu usage is low!
Push randoms, algorithms, and initializers higher and higher up the chain, using inheritance to distribute them to the lower actors.
Not only is it more efficient cpuwise, but it helps you consolidate your code into one spot, so you don't have to hunt down actor events one at a time. (Remember, you can change the bulletspeed before the game even starts, and not have to reset it ANYWHERE else in the script, yet it will work for all ships and all bullets)!
Reducing Randoms:Often you use the rand(); function to give an enemy its own unique movement; to make things seem more real, but rand takes a lot of cpu compared to a static variable;
So if i want my enemies to shoot at different, random times, i can say
- Code: Select all
timevar=round(rand(30));
if(timervar==10){CreateActor("Shot (etc));}
Now all my enemies will shoot at different, random times, approximately once every 30 frames.
But what about this?
On startup, create an array:
- Code: Select all
int i;
int rands[10];
for(i=0; i<10; i++){
rands[i]=round(rand(framerate));
}
Where framerate is the actual framerate of your game.
Now on Actor>createactor>
- Code: Select all
mytime=round(rand(10));
and in its draw actor....
- Code: Select all
timevar++;
if(timevar==rands[mytime]){...
Now you have ten different times, but enemy
only uses rand on startup. 10 is enough to make it seem random (and you can use 30 or 9 million if you like), while setting them to rand(framerate) allows you to use TIMEVAR as a global variable (only one actor needs to track the time now!), combined with modulo...
- Code: Select all
if(timevar%rands[mytime]==0){};
Not only did we get rid of a rand(), but we also got rid of the 'timevar++' line!
Because our rands are based on framerate, they're distributed throughout the time cycle evenly(randomly), so an enemy with a cycle of 10 frames and an enemy with a cycle of 30 frames can both work from the same global timevar.
0 != null:This can also allow you to overcome the <0.5 rounding issue; where round(rand()); produces only half as many 0's as the other numbers. You need to compensate, but don't do it every time a decision is made! Instead, use that startup...
- Code: Select all
int i;
int j;
int rands[10];
for(i=0; i<10; i++){
j=0; //force j back to 0 so the while loop will operate
while (j<1){ //keep doing this till we push j to 1 or greater, eliminating all 0 answers
j=round(rand(framerate+1)); //compensate for the next line's -1
rands[i]=j-1; //-1 replaces 0's, but now they're just as likely as any other number.
}
}
It doesn't matter if the 'j-1' part produces a negative number; it'll just force it to run the loop again.
You don't have to worry about the highest number (which also has a rounding issue). You don't have to use the highest number for anything. CPU isn't an issue because using startup initializers, like i said, can be done during the title/menu screens.
Ideally, if you want to have a thorough, in-depth system of game menus and options, your entire titlescreen/menu should be its own separate ged file; Which outputs a list of saved vars that the actual game uses when it starts up. Your game should be able to startup from a saved dat/txt of variables anyway, if you want the user to be able to save anything (even high scores).
If you put your menus inside the same ged with your game, you get slowed down by the complexity, and your menus aren't as polished as they should be. Big games companies sometimes hire people who ONLY MAKE MENUS! (and you've seen some games with menus more complex than most of our ENTIRE GAMES.)
Like pushing up the chain, events in a precursor menu exe file will leave you more room to program in your actual game file.
Please reserve the next post in this thread for pyrometal to tell me how wrong i am!