Hey, everybody...
As I'm learning DBP, I have been remaking classic games to try to get adjusted to the language and make sure I can replicate the game I have chosen. My first was 3d Space Invaders, which I released a couple weeks ago. I have since been working on an asteroids clone. It's not going nearly as smooth, but it's getting there. I have a couple problems, but I'm trying to solve them without help.
The main thing I'm here asking for right now is memory allocation, which is something I'm sure I can't learn on my own. There's no way I can play Dragon Age at full blast and have it be completely lossless but my little asteroids application is going slow as if it were really an Atari 2600 trying to run it.
So, are there any tricks or methods someone would be willing to share to help me squeeze some more juice out of my program? I can share my code, if you like. It's around 500 lines right now and has full base function except ship/asteroid collisions.
remstart
TO DO:
FINISHED **********************************************************************shoot lasers
FINISHED **********************************************************************lasers blow up asteroids
FINISHED **********************************************************************find out why asteroids aren't moving (don't clone objects)
FINISHED **********************************************************************ensure laser timers are working correctly
FINISHED **********************************************************************try to get a better-working skysphere in place of the textured backdrop
FINISHED **********************************************************************get a better texture on the skysphere
FINISHED **********************************************************************the actual act of an asteroid blowing up
FINISHED **********************************************************************loading screen, so beginning FPS will be neutralized at start
FINISHED **********************************************************************relocate asteroids when they get too far away to a random angle ahead of you
FINISHED **********************************************************************particle effects for an asteroid being blown up
FINISHED **********************************************************************shoot asteroid=score up
FINISHED **********************************************************************display score on screen
FINISHED **********************************************************************asteroid, on explosion, breaks into new asteroids with new vectors
FINISHED **********************************************************************FOV hyperspace effect
energy emissions on thrust
lighted weaponry
lighted exhaust
asteroid hitting the player reduces shield
asteroid hitting the player spins him around uncontrollably for a second
sound effects
start screen
hiscore saving
varying levels of difficulty - number of asteroids goes up with each level
controller support
shield completely reduced ends game with ship explosion
change camera angle to either bird's eye or follow
shield powerups randomly
limit maximum speed
headlights
dark mode, where you can only see by the light of your headlights and weapons
end game "cinematic" and reset to start on keypress
supernova bomb?
shaders
better loading screen with Sanba logo
remend
REM setup display
autocam off REM turn off autodisplay of each newly created object
sync on REM sets control of sync to manual
sync rate 60 REM sets sync rate to 60 FPS
set display mode 1024,768,32 REM set display width, height, and color depth
set window position desktop width()/4, 20 REM position window in the middle of the screen and 20 pixels from the top
fog on REM activate visual fog effect to hide distant objects
fog distance 200 REM fog distance of 200 pixels
starter: REM start of program: attempts to reset game will return to this heading
REM GLOBAL VARIABLES
global currentparticle=500
global thrusters=0 REM the amount of exhaust energy displayed
global newasteroids=0 REM the number of new asteroids that have been spawned since the start of the level
global score=0 REM the score, duh!
global fpstime# as float REM time between keyboard entry for valid buttonpresses
global fpstoggle=1 REM whether or not FPS display is toggled (default off)
global maxspeed=4 REM maximum speed of asteroid
global minspeed=1 REM minimum speed of asteroid
global maxtimebetweenlasers=15 REM number of temporal units allowed between laser fire
global laserlifetime=100 REM maximum lenght of time a laser is allowed to live
global maxheight=1 REM max height of asteroids
global maxobjects=400 REM maximum number of asteroids on the screen at any given time - make sure it is divisible by 2
global minobjects=3 REM lowest object number of asteroids
global maxlasers=10 REM max number of lasers that can exist simultaneously
global lasertimes=0 REM amount of time between shots before you can fire again
dim lasertime(maxlasers) REM lifespan of each laser
dim particlelife(maxobjects) REM how long before each explosion shuts off
global maxlaser=0 REM current laser number (ie. how many lasers exist currently)
global maxsize=700 REM maximum size of asteroids when added to minsize
global minsize=50 REM the smallest size an asteroid can be, formula is rnd(maxsize)+minsize
global areasize=300 REM size of the playing field
global angle#=0 REM starting angle of the ship, ie. straight ahead
global position=1 REM enumeration for vectors
global direction=2 REM ditto...
global facing=3 REM ditto...
global thrust=4 REM ditto...
null=make vector2(1) REM creation of vectors
null=make vector2(2) REM ditto...
null=make vector2(3) REM ditto...
null=make vector2(4) REM ditto...
set vector2 direction,0,0 REM initial vector settings
set vector2 facing,0,0 REM ditto...
set vector2 thrust,0,0 REM ditto...
type meteor REM User-defined type METEOR, to store info for each asteroid that currently exists
x as float REM asteroid x location
y as float REM asteroid y position
z as float REM asteroid z position
speedo# as float REM movement speed of asteroid
angler as integer REM angle of asteroid movement
parts as integer REM how many parts the asteroid can break into when destroyed
size as float REM how big the asteroid is
hit as integer REM how long since this asteroid has been hit
endtype
dim asteroid(maxobjects) as meteor REM dimension ASTEROID as a type of meteor
start() REM INITIALIZE STARTING OBJECTS
cls
do REM *******************************************MAIN GAME LOOP******************
text 20,50,str$(thrusters)
set vector2 position, object position x(1),object position z(1) REM update the "position" vector to the ship's current location
if fpstoggle=-1 then text 10,10,"FPS: "+str$(screen fps()) REM display FPS at top left if function is activated
center text screen width()/2,10, "Score: "+str$(score)
REM checks for other things that need to be watched each temporal unit
control_asteroids() REM control asteroids movement and collisions with other asteroids
control_lasers() REM control the motion of existing lasers
test_for_hit() REM perform collision detections between lasers and asteroids and process results
keycontrols() REM process user input
camaction() REM update camera position and focus point
checkup()
sync REM draw the screen
loop
REM *************************END MAIN GAME LOOP*********************************
REM **************************************************************LOAD OBJECTS
function START()
load image "rock.jpg",1 REM asteroid texture
load image "stars.jpg",2 REM background image
load image "explo1.jpg",3 REM explosion image
load image "explo.jpg",5 REM load another particle texture
load image "jet.jpg",4 REM load another particle texture
load object "ship.x",1 REM load ship model
load object "skysphere.x",2 REM load skysphere object
load image "engine.png",6 REM load engine exhaust texture
position object 2,areasize/2,0,areasize/2 REM position skysphere around your ship
texture object 2,2 REM texture skysphere
set object ambient 2,0 REM make sure light doesn't effect it
set object fog 2,0 REM make sure fog doesn't effect it
position object 1,areasize/2,0,areasize/2 REM position the ship in the middle of the asteroid field
set object collision to boxes 1 REM set the ship to collide when something comes within the bounds of an invisible box surrounding it
for i=minobjects to maxobjects/2 REM here we start making each asteroid on the field
asteroidmodel=rnd(3)+1 REM choose a random asteroid model
if asteroidmodel<=1 then load object "ast1.x",i REM load the random asteroid model for use with the current asteroid
if asteroidmodel =2 then load object "ast2.x",i REM ditto...
if asteroidmodel>=3 then load object "ast3.x",i REM ditto
texture object i,1 REM texture the asteroid model
scale object texture i,7,7 REM give the texture of the asteroid model a smaller and therefore more crisp appearance
scaler=rnd(maxsize)+minsize REM randomly choose a size
asteroid(i).size=scaler
scale object i,scaler,scaler,scaler REM use this randomly chosen size to scale it so they aren't all the same size
set object cull i,1 REM to reduce polygon count and improve performance, only draw polygons that are visible when drawing this object
asteroid(i).angler=rnd(359)+1 REM choose a random angle for the asteroid to be facing
yrotate object i,asteroid(i).angler REM rotate the asteroid to this randomly chosen angle
asteroid(i).speedo# = (rnd(maxspeed)+minspeed)*.05 REM randomly set the speed of the asteroid
asteroid(i).parts =3 REM tell this asteroid how many pieces it can be broken into
set object collision to spheres i REM set the collision style for this asteroid to a box shape around it
position object i,rnd (areasize),rnd(maxheight)-maxheight/2,rnd(areasize) REM randomly position the asteroid in question
asteroid(i).x = object position x(i) REM tell the asteroid its new coordinates
asteroid(i).y = object position y(i) REM ...
asteroid(i).z = object position z(i) REM ..
if object collision(i,0)>= minobjects then deleter=1 REM if the asteroid has been made on top of another asteroid, just delete it
if object collision(i,0)= 1 then deleter=1 REM if the asteroid has been made on top of the ship, just delete it
if deleter=1 then delete object i REM if either of the previous things happened...
deleter=0 REM ...just delete the current asteroid
REM this makes initial performance much faster, as the game was virtually getting permanently hung up trying to reposition colliding asteroids before
loadanig(i) REM the loading screen
next i
endfunction
REM *****************************FUNCTION TO CONTROL THE CAMERA POSITION AND DIRECTION
function CAMACTION()
x#=newxvalue(object position x(1),angle#+180,20) REM set x as a point somewhere 20 units behind the ship
y#=newyvalue(object position y(1),-10,40) REM set y as 40 units above the ship on a 10% incline
z#=newzvalue(object position z(1),angle#+180,20) REM set z as a point somewhere 20 units behind the ship
position camera x#,y#,z# REM place the camera at these just-calculated points
point camera object position x(1),object position y(1),object position z(1) REM point the camera at the ship
position object 2,object position x(1),object position y(1),object position z(1) REM position the skysphere around the ship (note that it does not rotate)
endfunction
REM ****************************FUNCTION TO CONTROL PLAYER OBJECT BY KEYBOARD
function KEYCONTROLS()
if rightkey()=1 then angle#=wrapvalue(angle#+1) REM if you pess right, rotate the ship right 1 degree
if leftkey()=1 then angle#=wrapvalue(angle#-1) REM if you press left, rotate the ship left 1 degree
yrotate object 1,angle# REM rotate the ship to the newly calculated angle
keypress$=inkey$()
if keypress$="f" and fpstime#+250<timer()
fpstime#=timer()
fpstoggle=fpstoggle*(-1)
endif
rem START BEING CONFUSING HERE
x#=sin(angle#) REM sets sin, cosine, and tangent of the angle to variables
y#=cos(angle#) REM cont'd
if upkey()=1 REM if you hit the up key...
set vector2 thrust,x#,y# rem set the thrust vector to equal the x and y vector of the angle you're at
scale vector2 thrust,thrust,.03 rem multiplies the thrust vector by the amount to increase by
add vector2 facing,thrust,facing rem ads this new vector to the direction you're facing
thrusters=thrusters+1
ENDIF
if downkey()=1 rem reverse thrust, same as above, only backward
set vector2 thrust,x#,y# REM ...
scale vector2 thrust,thrust,-.03 REM ...
add vector2 facing,thrust,facing REM ...
thrusters=thrusters-1 REM add to exhaust ball behind ship
if thrusters<0 then thrusters=0
endif
set vector2 position, object position x(1),object position z(1) REM sets the position vector to where you are right now
add vector2 direction, facing,position REM makes a new vector based on thrust and facing
position object 1,x vector2(direction),0,y vector2(direction) REM positions you according to this new vector
REM END BEING CONFUSING HERE
if spacekey()=1 then firer() REM space key fires, call function to fire here if space key is hit
endfunction
REM reset function, to start game from scratch
function RESET()
for i=1 to maxobjects+maxlaser rem encompasses all objects and lasers
delete object i rem then deletes them
next
goto starter rem return to the beginning of the main program
endfunction
REM function to control individual movement of the asteroids
function CONTROL_ASTEROIDS()
REM move asteroids
for i=minobjects to maxobjects REM check every asteroid, from the lowest possible to the highest possible
if object exist (i) REM if it exists...
newangle=wrapvalue(object angle y(i)-asteroid(i).angler) REM find out if the asteroid needs to be rotated
if newangle>0 then yrotate object i, object angle y(i)-1
if newangle<0 then yrotate object i, object angle y(i)+1
asteroid(i).hit=asteroid(i).hit-1 REM reduce the amount of time since the object has been hit by another asteroid
oldx=object position x(i)
oldz=object position z(i)
move object i, asteroid(i).speedo# REM move it in the direction it is facing a number of units equal to its speed
REM test asteroid on asteroid collisions
a=object collision(i,0) REM set value "a" to indicate the number of an object currently overlapping this asteroid
if a>=minobjects and a<=maxobjects REM if "a" is another asteroid...
if asteroid(i).hit <0 and asteroid(a).hit<0
aturn=rnd(1)
bturn=rnd(1)
if aturn=0 then asteroid(i).angler = wrapvalue(asteroid(i).angler-rnd(45)) REM randomly change the current angle of the asteroid in question, and...
if bturn=0 then asteroid(a).angler = wrapvalue(asteroid(a).angler-rnd(45)) REM ...randomly change the current angle of the asteroid that hit it
if aturn=1 then asteroid(i).angler = wrapvalue(asteroid(i).angler+rnd(45)) REM randomly change the current angle of the asteroid in question, and...
if bturn=1 then asteroid(a).angler = wrapvalue(asteroid(a).angler+rnd(45)) REM ...randomly change the current angle of the asteroid that hit it
asteroid(i).speedo#=.1 REM increase the speed of the initial asteroid, but...
asteroid(a).speedo#=.1 REM increase the speed of the second asteroid, but...
position object i,oldx,object position y(i),oldz
asteroid(i).hit=100
asteroid(a).hit=100
endif
endif
endif
REM This is the block of code that relocates an asteroid when it gets too far away from you
if calldistance(i,1)>areasize REM if the distance of the asteroid is further away than the max playing field size
a#=newxvalue(object position x(i),rnd(359),areasize*1.5) REM calculate a new x position...
b#=newzvalue(object position z(i),rnd(359),areasize*1.5) REM ...and a new z position...
c=rnd(maxheight)-maxheight/2 REM ...and a new height...
position object i,a#,c,b# REM ...and position the objects accordingly
endif
next i
endfunction
REM The function that controls the firing of lasers
function FIRER()
if lasertimes<=0 REM if you still have time left on your laser recharge then you can't fire
maxlaser=maxlaser+1
if maxlaser=11 then maxlaser=1 REM add one to the number of lasers currently in existence
Lposx#=newxvalue(object position x(1),angle#,5) REM set the laser position just in front of the ship
Lposz#=newzvalue(object position z(1),angle#,5) REM set the laser position just in front of the ship
if object exist (maxlaser+maxobjects)=0 REM just to be on the safe side, check again to make sure this laser doesn't already exist
make object cylinder maxlaser+maxobjects,1 REM make the laser a cylinder
scale object maxlaser+maxobjects, 100,300,100 REM scale the object to laser-size
position object maxlaser+maxobjects,Lposx#,object position y(1),Lposz# REM position the object appropriately, as earlier calculated
color object maxlaser+maxobjects,rgb(255,0,0) REM color the object bright red
set object ambient maxlaser+maxobjects,0 REM since a laser is made of light, make sure ambient light doesn't effect it so it's always bright
set object emissive maxlaser+maxobjects,rgb(255,0,0) REM also set it to make believe red light is always hitting it
xrotate object maxlaser+maxobjects,90 REM rotate the object on to its side
fix object pivot maxlaser+maxobjects REM set being rotated on its side to be the natural position for this object so it will pivot from here
yrotate object maxlaser+maxobjects,angle# REM rotate it to the same facing of the ship
lasertime(maxlaser)=laserlifetime REM set the number of temporal units the laser will remain alive
lasertimes=maxtimebetweenlasers REM set the number of temporal units between now and when the lasers can be fired again
set object collision to boxes maxlaser+maxobjects REM set the laser's collision to a bounding box around it
endif
endif
endfunction
REM This function controls the life and movement of lasers
function CONTROL_LASERS()
lasertimes=lasertimes-1 REM subtract one from the number of temporal units you have before you can fire again
for i=1 to maxlasers REM Check each object number that could possibly be a laser
if object exist(i+maxobjects) then move object i+maxobjects,6 REM if it exists, move it
lasertime(i)=lasertime(i)-1 REM reduce the amount of time this laser has to exist
next i
REM this bit deletes lasers that have run out of time
for i=1 to maxlasers REM Check each object number that could possibly be a laser
if lasertime(i)<0 REM If the object has run out of time...
if object exist (i+maxobjects) REM check again to make sure it exists
delete object i+maxobjects REM ...and if it does, destroy it
endif
endif
next i
endfunction
REM This function tests to see whether or not you've hit an asteroid with your laser
function TEST_FOR_HIT()
for i=minobjects to maxobjects REM check every object number that could be an asteroid
if object exist(i) REM if the currently inspected asteroid exists...
a=object collision(i,0) REM ...Then check to see if it is colliding with something, storing the collision object in variable "a"
if a>maxobjects REM check to make sure the object performing the collision (ie. "a") is a laser
if asteroid(i).parts=1 then addscore=300 REM if the asteroid is smaller, you get bouceaup points
if asteroid(i).parts=2 then addscore=200 REM if it is medium sized, you get medium points
if asteroid(i).parts=3 then addscore=100 REM if it is full sized, you get less points
score=score+addscore REM but either way, you get points
makeexplosion(i) REM call function that draws explosion
makenewasteroids(i) REM makes new asteroids out of a smaller destroyed asteroid
delete object i REM if it is, destroy the asteroid
delete object a REM also, destroy the offending laser
endif
endif
next i
endfunction
REM creates the particle explosions of each destroyed asteroid
function MAKEEXPLOSION(i)
particlepic=rnd(2)+1 REM choose image to use for the explosion
if particlepic=1 then make particles i,3,1000,8 REM creates the particles... following lines edit their parameters
if particlepic=2 then make particles i,5,1000,8 REM creates the particles... following lines edit their parameters
if particlepic=3 then make particles i,4,1000,8 REM creates the particles... following lines edit their parameters
position particles i,object position x(i),0,object position z(i)
set particle velocity i,3
set particle speed i,.02
set particle floor i,0
set particle gravity i,.05
set particle life i,50
set particle emissions i,500
particlelife(i)=6 REM sets the number of temporal units for which the emitter should remain alive
endfunction
REM This function checks up on random things throughout play
function CHECKUP()
if thrusters>90 then thrusters=90
set camera fov 70+(thrusters*.4)
REM THIS IS WHERE ENGINE EXHAUST GOES**********************************************************************************************************
rem minimum particle number is 500
rem maximum particle number is 1000
for i=minobjects to maxobjects REM check every asteroid's explosion...
if particles exist(i)
particlelife(i)=particlelife(i)-1 REM check the particle emitter's life
if particlelife(i)<0 REM if its life has expired...
if particles exist(i) then set particle emissions i,0 REM ...then turn it off
endif
if CALLDISTANCEPARTICLES(i,1)>areasize then delete particles i
endif
next i
if thrusters>0
if upkey()<>1 then thrusters=thrusters-1
endif
if thrusters <=0
if thrusters<0 then thrusters=0
endif
endfunction
REM This function finds the distance between two objects
function CALLDISTANCE(a,b)
if object exist(a)=1 and object exist(b)=1 REM if the objects in question exist...
null=make vector2(5) REM make a new vector to store their distance
xdist#=object position x(b)-object position x(a) REM find the x location differential
zdist#=object position z(b)-object position z(a) REM find the z location differential
set vector2 5,xdist#,zdist# REM store the location differentials in the vector
dist#=length vector2(5) REM determine the length of the vector
null=delete vector2(5) REM destroy the vector to make room for other assignations and to free up memory
endif
endfunction dist#
REM This function draws a loading bar
function LOADANIG(i)
box 0,0,screen width(),screen height(),rgb(0,0,0),rgb(0,0,0),rgb(0,0,0),rgb(0,0,0) REM black background
box 0,(screen height()/4)*3,(screen width()/(maxobjects-minobjects))*(i*2.55),((screen height()/4)*3)+25,rgb(255,0,0),rgb(255,0,0),rgb(255,0,0),rgb(255,0,0) REM bar
sync REM make sure the loading bar gets drawn over everything else
endfunction
REM This function makes new asteroids when a larger asteroid is destroyed
function MAKENEWASTEROIDS(a)
if asteroid(a).parts>0 REM as long as there are still parts in this asteroid...
if (maxobjects/2)+(newasteroids+asteroid(a).parts)<maxobjects REM if there is enough available space for the new asteroids
oldasteroids=newasteroids REM set a token of how many new asteroids there were before this
newasteroids=newasteroids+asteroid(a).parts REM add to the number of new asteroids
for i=1 to asteroid(a).parts
asteroidmodel=rnd(3)+1 REM choose a random asteroid model
whichone=(maxobjects/2)+(oldasteroids+i) REM determine which object number this asteroid will have
if asteroidmodel<=1 then load object "ast1.x",whichone REM load the random asteroid model for use with the current asteroid
if asteroidmodel =2 then load object "ast2.x",whichone REM ditto...
if asteroidmodel>=3 then load object "ast3.x",whichone REM ditto
texture object whichone,1 REM texture the asteroid model
scale object texture whichone,7,7 REM give the texture of the asteroid model a smaller and therefore more crisp appearance
scaler=asteroid(a).size/2 REM make it smaller than the original would have been
asteroid(whichone).size=scaler REM attribute this size to the new asteroid
scale object whichone,scaler,scaler,scaler REM use this randomly chosen size to scale it so they aren't all the same size
set object cull whichone,1 REM to reduce polygon count and improve performance, only draw polygons that are visible when drawing this object
asteroid(whichone).angler=rnd(359)+1 REM choose a random angle for the asteroid to be facing
yrotate object whichone,asteroid(whichone).angler REM rotate the asteroid to this randomly chosen angle
asteroid(whichone).speedo# = (rnd(maxspeed)+minspeed)*.05 REM randomly set the speed of the asteroid
asteroid(whichone).parts=asteroid(a).parts-1 REM tell this asteroid how many pieces it can be broken into
set object collision to boxes whichone REM set the collision style for this asteroid to a box shape around it
position object whichone,object position x(a),object position y(a),object position z(a) REM position the new asteroid where the original was
asteroid(whichone).x = object position x(whichone) REM tell the asteroid its new coordinates
asteroid(whichone).y = object position y(whichone) REM ...
asteroid(whichone).z = object position z(whichone) REM ..
next i
endif
endif
endfunction
REM This function finds the distance between the ship and a particle emitter
function CALLDISTANCEPARTICLES(a,b)
if particles exist(a)=1 and object exist(b)=1 REM if the objects in question exist...
null=make vector2(5) REM make a new vector to store their distance
xdist#=object position x(b)-particles position x(a) REM find the x location differential
zdist#=object position z(b)-particles position z(a) REM find the z location differential
set vector2 5,xdist#,zdist# REM store the location differentials in the vector
dist#=length vector2(5) REM determine the length of the vector
null=delete vector2(5) REM destroy the vector to make room for other assignations and to free up memory
endif
endfunction dist#
Sanba Games: Because We Can