`Challenge Compo - Asteroids Game `by Bill Robinson `due: 2-25-06 `@Kimosabi - you do NOT have rights to use this program as your own. `And you never should have used Ric's pong game as your own, on your web sight! ` `Use 'Z' and 'X' to rotate ship, leftarrow and rightarrow work too `Use comma ',' to fire, period '.' to thrust `Use 'Space' to Hyperspace to a new position `Use 'Shift' for shields, you have a limited number of shields per level `You only get 5 shots on the screen at a time ` `Using Hyperspace FREEZES TIME while your ship is in hyperspace traveling to new location. `If ship traveling through Hyperspace lands on an asteroid, `you have a brief moment to engage Hyperspace again to save your ship `Hyperspace will also bring your moving ship to a stop ` set display mode 1024,768,32 autocam off sync on sync rate 60 Hide Mouse Backdrop on Color Backdrop 0 set ambient light 15 set camera range 1,5000 randomize timer() `--- Game Setup --- #constant MAX_ASTEROIDS 199 global GREEN GREEN=rgb(0,255,0) global RED RED=rgb(255,0,0) global level global newlevel global score global targetsleft global numasteroids global lives global playersafetime global shields global syncrate=60 `--- Player --- global ship_x# global ship_y# global ship_z#=0 global shipangle# global shipthrust# global shipmass# global explode_object=0 global expdone=0 global exparrayindex=1 global expparticleindex=1 global numhits global playerdeadtime global velx#=0 global vely#=0 global shipincx#=0 global shipincy#=0 `--- enemy --- `1=active, 2=size, 3=x, 4=y, 5=z, 6=xinc, 7=yinc, 8=zinc, 9=color dim enemy#(10) dim eshots#(10) `--- asteroids --- `1=active, 2=size, 3=x, 4=y, 5=z, 6=xinc, 7=yinc, 8=zinc, 9=xrot,10=yrot, 11=zrot, 12=color dim ast_info#(MAX_ASTEROIDS,15) ` highest number of vertexes = 200 for now global vcount=200 dim vertex_count(199) dim v_pos_x#(199,vcount) dim v_pos_y#(199,vcount) dim v_pos_z#(199,vcount) `--- explosion particles --- rem Arrays for position, velocity and life of each explosion particle dim partx#(300) dim party#(300) dim partz#(300) dim partxvel#(300) dim partyvel#(300) dim partzvel#(300) dim partlife(300) dim explosion(10,10) global start_time=0 global inten#=60.0 global max=200 `--- ship thrust --- dim thrust#(50,10) global thrustptr `--- Shots Fired --- dim shots(100,4) global shotptr global shotspeed# global lastshot global shottime global shotpause global hitnum global maxshots global numshots `--- Players shots getting made --- for i=400 to 410 make object sphere i,30,3,3 xrotate object i,90 color object i,rgb(255,255,255) scale object i,20,20,100 set object collision off i hide object i next i `--- hyperspace ships --- global numhyper=5 dim hyperinfo#(numhyper,6) color=GREEN for i=1 to numhyper obnum=1020+i make object cone obnum, 20 color object obnum,color ghost object on obnum hide object obnum next i `------------------------ screen_xmax=screen width() screen_ymax=screen height() screen_center=screen_xmax/2 `--- make cone for ship --- make object cone 1000,20 color object 1000,rgb(0,255,0) set object collision on 1000 set object collision to spheres 1000 fix object pivot 1000 make object sphere 1001,50 color object 1001,rgb(0,255,255) set object collision off 1001 ghost object on 1001 `set object wireframe 1001,1 set object ambient 1001,0 position object 1001,-2700,-2700,-2700 make object cone 4000,50 scale object 4000,100,50,100 color object 4000,rgb(255,0,0) set object collision on 4000 set object collision to spheres 4000 position object 4000,-2600,-2600,-2600 `--- make exhaust particles --- for i=1 to 40 color=rgb(rnd(55)+200,rnd(55)+200,0) obnum=600+i make object plain obnum,2,2 color object obnum,color hide object obnum next i `--- make explosion pieces --- color=rgb(255,255,255) for i=1 to max obnum=199+i make object plain obnum,6,6 color object obnum,color hide object obnum next i _reset_vars() _make_stars() `--- setup starfield in background --- make object plain 998,1300,1000 texture object 998, 1 position object 998,0,0,200 `--- debug limits of screen, for wrap-around of objects --- global lwall=-480 global rwall=480 global twall=360 global bwall=-360 position object 1000, 0,0,0 position camera 0,0,-600 point camera 0,0,0 do set object collision on 1000 if newlevel=1 _new_level() endif if targetsleft=0 then newlevel=1 `explosion 1=active flag, 2=object, 3=#particles, 4=intensity, 5=particle life, 6=particle start num, 7=color if keystate(48)=1 :`b key - self destruct _set_explosion(1000,50,30,100,GREEN) playerdeadtime=200 endif if leftkey()=1 then inc shipangle#,3 :`left arrow key if rightkey()=1 then dec shipangle#,3 :`right arrow key if keystate(44)=1 then inc shipangle#,3 :`z key if keystate(45)=1 then dec shipangle#,3 :`x key if keystate(29)=1 then _fire_missle() :`ctrl key if keystate(42)=1 or keystate(54)=1 then _raise_shields() if keystate(57)=1 :`space key _hyperspace(1) velx#=0:vely#=0:shipincx#=0:shipincy#=0 endif if keystate(51)=1 and numshots<maxshots then _shoot() if keystate(52)=1 shipincx#=-sin(shipangle#)*shipthrust# shipincy#=cos(shipangle#)*shipthrust# _start_thrust() else shipincx#=0 shipincy#=0 endif `calc ship velocity deltax#=shipincx#/shipmass# deltay#=shipincy#/shipmass# inc velx#,deltax# inc vely#,deltay# inc ship_x#,velx# inc ship_y#,vely# _show_thrust() shipangle#=wrapvalue(shipangle#) ship_x#=_ship_screen_wrapx(ship_x#) :`wrap players ship around screen if needed ship_y#=_ship_screen_wrapy(ship_y#) zrotate object 1000,shipangle# :`rotate players ship position object 1000,ship_x#,ship_y#,ship_z# :`position ship on screen if playersafetime>0 and playerdeadtime=0 position object 1001,ship_x#,ship_y#-5,ship_z# :`safety shield else position object 1001,-2500,-2500,-2500 endif _check_newexplosions() _check_asthits() :`check for player hits from shots _move_shots() :`move player shots _continue_explosion() :`continue to explode pieces _move_asteroids() if lives=0 then _game_over() if playersafetime>0 dec playersafetime else _check_playerhit() endif if level>1 if enemy#(1)=0 _start_enemy() else _move_enemy() endif endif ` _check_enemyhit() if playerdeadtime>0 dec playerdeadtime if playerdeadtime<200 then center text screen width()/2,300,"GET READY! - For Next Ship" if playerdeadtime=0 velx#=0:vely#=0:shipincx#=0:shipincy#=0 _hyperspace(2) set object collision on 1000 playersafetime=120 endif endif if expdone=1 explode_object=0 start_time=0 expdone=0 endif if numshots<=0 then numshots=0 :`just correcting for a bug I haven't figured out yet set cursor 1,1 print screen fps() center text screen_center,10,"Level: "+str$(level)+" Lives: "+str$(lives)+" Targets Left: "+str$(targetsleft)+" Shields: "+str$(shields)+" Score: "+str$(score) sync loop function _start_thrust() thrustlife=10 i=thrustptr if thrust#(i,1)=0 thrust#(i,1)=1 thrust#(i,2)=ship_x# thrust#(i,3)=ship_y# thrust#(i,4)=-shipincx#-(rnd(3)/4.0) thrust#(i,5)=-shipincy#-(rnd(3)/4.0) thrust#(i,6)=thrustlife inc thrustptr if thrustptr>40 then thrustptr=1 show object 600+i endif endfunction function _show_thrust() for i=1 to 40 if thrust#(i,6)>0 position object 600+i,thrust#(i,2),thrust#(i,3),0 dec thrust#(i,6) inc thrust#(i,2),thrust#(i,4) inc thrust#(i,3),thrust#(i,5) else thrust#(i,1)=0 hide object 600+i endif next i endfunction function _start_enemy() `1=active, 2=size, 3=x, 4=y, 5=z, 6=xinc, 7=yinc, 8=yloc_change, 9=vis_counter if enemy#(1)=0 if enemy#(9)>0 dec enemy#(9) else enemy#(1)=1 enemy#(3)=-500.0 enemy#(4)=rnd(320)-100 enemy#(5)=0 enemy#(6)=(rnd(120)+60)/60.0 enemy#(7)=0 enemy#(8)=rnd(100)+50 ` enemy#(9)=rnd(1000)+2000 position object 4000,enemy#(3),enemy#(4),enemy#(5) show object 4000 endif endif endfunction function _move_enemy() `1=active, 2=size, 3=x, 4=y, 5=z, 6=xinc, 7=yinc, 8=yloc_change, 9=vis_counter if enemy#(1)=1 dec enemy#(8) inc enemy#(3),enemy#(6) if enemy#(4)<300 and enemy#(4)>-300 then inc enemy#(4),enemy#(7) position object 4000,enemy#(3),enemy#(4),enemy#(5) if enemy#(8)<0 enemy#(8)=rnd(50)+50 enemy#(7)=(rnd(360)-180)/60.0 endif if enemy#(3)>500 enemy#(1)=0 position object 4000,-2700,-2700,-2700 enemy#(8)=rnd(50)+50 enemy#(9)=rnd(1000)+2000 endif endif endfunction function _enemy_shots() endfunction function _raise_shields() if shields>=200 and playersafetime=0 playersafetime=200 dec shields,200 endif endfunction function _check_newexplosions() for ex=1 to 10 if explosion(ex,1)=1 ex#=object position x(explosion(ex,2)) ey#=object position y(explosion(ex,2)) ez#=object position z(explosion(ex,2)) if expparticleindex+explosion(ex,3)>=200 expparticleindex=1 endif explosion(ex,6)=expparticleindex inc expparticleindex,explosion(ex,3) `explosion() 1=active flag, 2=object, 3=#particles, 4=intensity, 5=particle life, 6=particle start num, 7=color _request_explosion(ex#,ey#,ez#,explosion(ex,3),explosion(ex,4),explosion(ex,5),explosion(ex,6),explosion(ex,7)) start_time=1 hide object explosion(ex,2) :`was explode_object set object collision off explosion(ex,2) :`was explode_object explosion(ex,1)=2 endif next ex endfunction `--- move asteroids --- function _move_asteroids() for i=1 to numasteroids pitch object down i,ast_info#(i,9) :`tumble asteroids in all three axis turn object right i,ast_info#(i,10) roll object right i,ast_info#(i,11) inc ast_info#(i,3),ast_info#(i,6) inc ast_info#(i,4),ast_info#(i,7) `--- wrap asteroids around screen if needed ----- ast_info#(i,3)=_asteroid_screen_wrapx(ast_info#(i,3),ast_info#(i,2)) :`returns a screen wrap coord if object x-value went off screen ast_info#(i,4)=_asteroid_screen_wrapy(ast_info#(i,4),ast_info#(i,2)) :`returns a screen wrap coord if object y-value went off screen position object i,ast_info#(i,3),ast_info#(i,4),ast_info#(i,5) :`position asteroid in new location next i endfunction `--- array entry for another explosion --- function _set_explosion(object,numparticles,intensity,particlelife,color) explosion(exparrayindex,1)=1 :`explosion flag 1=on 0=off explosion(exparrayindex,2)=object :`object to explode explosion(exparrayindex,3)=numparticles :`number of particles explosion(exparrayindex,4)=intensity :`intensity explosion(exparrayindex,5)=particlelife :`particle life explosion(exparrayindex,7)=color :`color of particles inc exparrayindex if exparrayindex>10 then exparrayindex=1 endfunction function _game_over() do center text screen width()/2,10,"Level: "+str$(level)+" Lives: "+str$(lives)+" Targets Left: "+str$(targetsleft)+" Score: "+str$(score) center text screen width()/2,300,"GAME OVER - Thanks For Playing!" center text screen width()/2,350,"Press escape key to exit" _check_newexplosions() _continue_explosion() _move_asteroids() sync loop endfunction `--- builds new level --- function _new_level() inc level set text font "Arial" set text size 18 sync center text screen width()/2,300,"Get Ready - For Level "+str$(level) sync wait 1000 numasteroids=0 newasteroids=7+level for i=1 to 199 if object exist(i)=1 delete object i endif next i size=3 _add_asteroids(newasteroids,size,0) newlevel=0 ship_x#=0 ship_y#=0 playersafetime=200 numshots=0 shields=1000 if level>1 then enemy#(9)=2000 :`reset enemy visible counter endfunction function _check_playerhit() hnum=object collision(1000,0) if hnum>0 if hnum<=199 inc numhits if numhits>50 hide object 1000 :`hide player ship set object collision off 1000 position object 1000,-2000,-2000,-2000 :`just move offscreen _set_explosion(1000,50,30,100,GREEN) numhits=0 playerdeadtime=400 playersafetime=450 dec lives endif endif endif endfunction function _check_enemyhit() sync rate 0 for i=1 to 10 if shots(i,1)=1 objnum=shots(i,2) hitnum=object collision(objnum,0) if hitnum>0 if hitnum=4000 hide object objnum :`hide shot set object collision off objnum position object objnum,-3000,-3000,-3000 :`just move offscreen hide object hitnum :`hide asteroid set object collision off hitnum position object hitnum,-2000,-2000,-2000 :`just move offscreen inc score,200 _remove_shot(objnum) shots(i,1)=0 _set_explosion(hitnum,10,10,20,RED) endif endif endif next i sync rate syncrate endfunction function _check_asthits() sync rate 0 for i=1 to 10 if shots(i,1)=1 objnum=shots(i,2) hitnum=object collision(objnum,0) if hitnum>0 if hitnum<199 hide object objnum :`hide shot set object collision off objnum position object objnum,-3000,-3000,-3000 :`just move offscreen hide object hitnum :`hide asteroid set object collision off hitnum position object hitnum,-2000,-2000,-2000 :`just move offscreen inc score,10 dec targetsleft _remove_shot(objnum) shots(i,1)=0 size=ast_info#(hitnum,2) :`size of the hit asteroid if size>1 _add_asteroids(2,size-1,hitnum) endif _set_explosion(hitnum,10,3*size,20,ast_info#(hitnum,12)) endif endif endif next i sync rate syncrate endfunction `--- Player Shots - 1=active, 2=obnum, 3=shotlife, --- function _shoot() shottime=timer()-lastshot if shottime<shotpause then exitfunction position object shotptr,ship_x#,ship_y#,0 show object shotptr zrotate object shotptr,shipangle# set object collision on shotptr set object collision to spheres shotptr shots(shotptr-399,1)=1 shots(shotptr-399,2)=shotptr shots(shotptr-399,3)=500 inc shotptr if shotptr>=410 then shotptr=400 lastshot=timer() inc numshots endfunction function _move_shots() for i=1 to 10 if shots(i,1)=1 obnum=shots(i,2) move object obnum,-shotspeed# posx#=object position x(obnum) posy#=object position y(obnum) posx#=_ship_screen_wrapx(posx#) posy#=_ship_screen_wrapy(posy#) position object obnum,posx#,posy#,0 dec shots(i,3),shotspeed# if shots(i,3)<=0 _remove_shot(obnum) shots(i,1)=0 endif endif next i endfunction function _remove_shot(obnum) set object collision off obnum position object shotptr,-2000,-2000,-2000 :`just move offscreen hide object obnum dec numshots endfunction function _fire_missle() endfunction function _asteroid_screen_wrapx(x#,size#) limit#=490+size#*15.0 if x#>limit# then x#=-limit# if x#<-limit# then x#=limit# endfunction x# function _asteroid_screen_wrapy(y#,size#) limit#=380+size#*15.0 if y#>limit# then y#=-limit# if y#<-limit# then y#=limit# endfunction y# function _ship_screen_wrapx(x#) if x#>500 then x#=-500 if x#<-500 then x#=500 endfunction x# function _ship_screen_wrapy(y#) if y#>380 then y#=-380 if y#<-380 then y#=380 endfunction y# function _make_stars() ink rgb(255,255,255),0 for x=1 to 250 dot rnd(1024),rnd(768) next x get image 1,0,0,1024,768,1 endfunction function _reset_vars() level=0 newlevel=1 targetsleft=0 numasteroids=0 lives=5 playersafetime=100 ship_y#=0 ship_x#=0 shipthrust#=3.0 shipmass#=50.0 expdone=0 exparrayindex=1 expparticleindex=1 shotptr=400 shotspeed#=4 shotpause=150 maxshots=5 numshots=0 fusetime#=1 fuselength=1 boomflag=0 thrustptr=1 endfunction `--------DB demo routines for explosions-------- function _request_explosion(ex#,ey#,ez#,particles,intensity#,life,partindex,color) for i=partindex to partindex+particles partlife(i)=life + rnd(life/5) partx#(i)=ex# party#(i)=ey# partz#(i)=ez# partyvel#(i)=rnd(intensity#)-(intensity#/2) partxvel#(i)=rnd(intensity#)-(intensity#/2) partzvel#(i)=rnd(intensity#)-(intensity#/2) show object 199+i color object 199+i,color next i endfunction `explosion 1=active flag, 2=object, 3=#particles, 4=intensity, 5=particle life, 6=particle start num, 7= function _continue_explosion() for ex=1 to 10 if explosion(ex,1)=2 for t=explosion(ex,6) to explosion(ex,6)+explosion(ex,3) if partlife(t)>1 dec partlife(t) position object 199+t,partx#(t),party#(t),partz#(t) partxvel#(t)=partxvel#(t)*0.98 :`was 0.95 partyvel#(t)=partyvel#(t)*0.98 ` partzvel#(t)=partzvel#(t)*0.95 :`particles slow down from air friction partzvel#(t)=0.0 ` partyvel#(t)=partyvel#(t)-0.5 :`particles effected by gravity inc partx#(t),partxvel#(t) inc party#(t),partyvel#(t) inc partz#(t),partzvel#(t) ` if party#(t)<=0 then partyvel#(t)=partyvel#(t)*-0.7 :`particles bounce on the ground rotate object t+199,wrapvalue(object angle x(t+199)+rnd(50)),wrapvalue(object angle y(t+199)+rnd(100)),0 endif if partlife(t)=1 partlife(t)=0 hide object 199+t start_time=0 expdone=1 ` explosion(ex,1)=0 endif next t endif next ex endfunction function _add_asteroids(num,size,hitnum) sync rate 0 for i=1 to num astnum=numasteroids+1 _make_asteroids(astnum,size) set object smoothing astnum,0 set object collision on astnum set object collision to spheres astnum `1=active, 2=size, 3=x, 4=y, 5=z, 6=xinc, 7=yinc, 8=zinc, 9=xrot,10=yrot, 11=zrot, 12=color ast_info#(astnum,1)=1 ast_info#(astnum,2)=size if hitnum>0 ast_info#(astnum,3)=ast_info#(hitnum,3) :`use larger asteroid location ast_info#(astnum,4)=ast_info#(hitnum,4) else ast_info#(astnum,3)=rnd(1200)-600 :`random location ast_info#(astnum,4)=rnd(1200)-600 endif ast_info#(astnum,5)=0 v#=(rnd(3)+0.8)/(rnd(8)+size) :`generate a motion value d=rnd(10):if d>5 then v#=v#*-1.0 :`decide whether a positive or negative motion ast_info#(astnum,6)=v# v#=(rnd(3)+0.8)/(rnd(8)+size) :`generate a motion value d=rnd(10):if d>5 then v#=v#*-1.0 :`decide whether a positive or negative motion ast_info#(astnum,7)=v# ast_info#(astnum,8)=0 v#=rnd(3)/(rnd(10)+1.0) :`generate a rotation value d=rnd(10):if d>5 then v#=v#*-1.0 :`decide whether a positive or negative rotation ast_info#(astnum,9)=v# v#=rnd(3)/(rnd(10)+1.0) d=rnd(10):if d>5 then v#=v#*-1.0 ast_info#(astnum,10)=v# v#=rnd(3)/(rnd(10)+1.0) d=rnd(10):if d>5 then v#=v#*-1.0 ast_info#(astnum,11)=v# if hitnum>0 color=ast_info#(hitnum,12) :`use larger asteroid color else color=rgb(rnd(255),rnd(255),rnd(255)) :`use random color endif ast_info#(astnum,12)=color color object astnum,ast_info#(astnum,12) position object astnum,ast_info#(astnum,3),ast_info#(astnum,4),ast_info#(astnum,5) show object astnum inc numasteroids inc targetsleft next i sync rate syncrate endfunction ` ----- Make Asteroids --- Trying vertex commands for the first time! ----- function _make_asteroids(num,size) objs=num make object sphere objs,60 if size=2 then scale object objs,70,70,70 if size=1 then scale object objs,30,30,30 ` get vertex data ob=objs make mesh from object 1,ob lock vertexdata for mesh 1 vertex_count(ob)=(GET VERTEXDATA VERTEX COUNT()-1) for v=0 to vertex_count(ob) v_pos_x#(ob,v)=GET VERTEXDATA POSITION X(v)+object position x(ob) v_pos_y#(ob,v)=GET VERTEXDATA POSITION y(v)+object position y(ob) v_pos_z#(ob,v)=GET VERTEXDATA POSITION z(v)+object position z(ob) next v unlock vertexdata delete mesh 1 ` deform vertices 4-10 times for jagged look for deftimes=1 to (rnd(6)+4) make mesh from object 1,ob lock vertexdata for mesh 1 for i=0 to vertex_count(ob) xdir=rnd(10):if xdir>5 then xdir=1 else xdir=-1 ydir=rnd(10):if ydir>5 then ydir=1 else ydir=-1 zdir=rnd(10):if zdir>5 then zdir=1 else zdir=-1 inc v_pos_x#(ob,i),rnd(5)*xdir inc v_pos_y#(ob,i),rnd(5)*ydir inc v_pos_z#(ob,i),rnd(5)*zdir SET VERTEXDATA POSITION i, v_pos_x#(ob,i),v_pos_y#(ob,i),v_pos_z#(ob,i) next i unlock vertexdata make object 5000,1,0 delete mesh 1 delete object ob clone object ob,5000 delete object 5000 next deftimes endfunction ` ----- Hyperspace ship to new location --- This was interesting to work out ----- function _hyperspace(source) sync rate 0 hyperflag=1 numslices=3 destx#=rnd(850)-425 desty#=rnd(650)-325 hide object 1000 for i=1 to numhyper if source=2 ship_x#=1500 ship_y#=400 endif hyperinfo#(i,1)=ship_x# hyperinfo#(i,2)=ship_y# obnum=1020+i xrotate object obnum,object angle x(1000) yrotate object obnum,object angle y(1000) zrotate object obnum,object angle z(1000) position object obnum,hyperinfo#(i,1), hyperinfo#(i,2), 0 show object obnum next i hyperinfo#(1,1)=destx# hyperinfo#(1,2)=desty# position object 1021,hyperinfo#(1,1), hyperinfo#(1,2), 0 count=0 while hyperflag=1 for i=2 to numhyper hyperinfo#(i,3)=(hyperinfo#(i-1,1)-hyperinfo#(i,1))/numslices hyperinfo#(i,4)=(hyperinfo#(i-1,2)-hyperinfo#(i,2))/numslices inc hyperinfo#(i,1),hyperinfo#(i,3) inc hyperinfo#(i,2),hyperinfo#(i,4) position object 1020+i,hyperinfo#(i,1), hyperinfo#(i,2), 0 sync next i inc count if count>=numhyper*numslices*2 then hyperflag=0 endwhile ship_x#=destx# ship_y#=desty# box_xdir#=0 box_ydir#=0 position object 1000,ship_x#,ship_y#,ship_z# show object 1000 for i=1 to numhyper hide object 1020+i next i sync sync rate syncrate endfunction