Artificial intelligence/templates/examples/rts/rpg/strategy ect. in MonkeyX/CerberusX language. You can download the free version of MonkeyX from itch.io or Cerberus-x.com The Flash applets will stop working in around 2020.
Here is a new version of my Dungeon Generator. I have now used open and closed lists for the doors. The code can generate larger maps. Hundreds of rooms.
Code below :
This basically is how it works :
It creates one door in the open list.
It creates a room on the door and 3 new doors on the walls
the doors are added to the open list
it selects a random door and tries to create a new room there
if that fails then the door is removed from the open list. if it succeeds then it is removed from the open list and added to the closed list.
this continues until the number of rooms has been reached or the open list is empty (check for bounds to)
The door locations are in the closed list (x,y) and can be drawn to the map.
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Global tilewidth:Int=6 Global tileheight:Int=4 Global mapwidth:Int=100 Global mapheight:Int=100 Const isnothing:Int=0 Const iswall:Int=1 Const isfloor:Int=2 Const isdoor:Int=3 Const minroomw:Int=5 Const minroomh:Int=5 Const maxroomw:Int=10 Const maxroomh:Int=10 Global map:Int[mapwidth][] Global rcount:Int=0 Class debug Field x:Int Field y:Int Method New(_x:Int,_y:Int) x=_x y=_y End Method End Class Class dooropenlist Field x:Int Field y:Int Method New(_x:Int,_y:Int) x=_x y=_y End Method End Class Class doorclosedlist Field x:Int Field y:Int Method New(_x:Int,_y:Int) x=_x y=_y End Method End Class Global dol:List<dooropenlist> = New List<dooropenlist> Global dcl:List<doorclosedlist> = New List<doorclosedlist> Global d:List<debug> = New List<debug> Class MyGame Extends App Method OnCreate() SetUpdateRate(1) Seed = Millisecs() For Local i = 0 Until mapwidth map[i] = New Int[mapheight] Next createmap(25,mapwidth/2,mapheight/2) End Method Method OnUpdate() createmap(Rnd(10,125),mapwidth/2,mapheight/2) End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 drawmap End Method End Class Function createmap:Bool(numrooms:Int,sx:Int,sy:Int) For Local y=0 Until mapheight For Local x=0 Until mapwidth map[x][y] = isnothing Next Next d.Clear dol.Clear dcl.Clear dol.AddLast(New dooropenlist(sx,sy)) Local roomcount:Int=0 Local tx:Int Local ty:Int While roomcount<numrooms And dol.IsEmpty() = False Local founddoor:Bool=False While founddoor=False For Local i:=Eachin dol If Rnd(100)<2 founddoor = True tx = i.x ty = i.y Exit End If Next Wend If makeroomondoor(tx,ty) = True Then roomcount+=1 removedoorfromopenlist(tx,ty) dcl.AddLast(New doorclosedlist(tx,ty)) Else removedoorfromopenlist(tx,ty) End If Wend For Local i:=Eachin dcl If i.x = sx And i.y = sy Then dcl.Remove i Next rcount = roomcount End Function Function makeroomondoor:Bool(x:Int,y:Int) Local makeroom:Bool=False Local cnt:Int=0 Local x1:Int Local y1:Int Local w1:Int Local h1:Int Local facing:String If x+maxroomw > mapwidth Then Return False If y+maxroomh > mapheight Then Return False If x-maxroomw < 0 Then Return False If y-maxroomh < 0 Then Return False If map[x+1][y]=isnothing Then facing = "right" If map[x][y-1]=isnothing Then facing = "up" If map[x][y+1]=isnothing Then facing = "down" If map[x-1][y]=isnothing Then facing = "left" If facing="" Then Return False While cnt<100 w1 = Rnd(minroomw,maxroomw) h1 = Rnd(minroomh,maxroomh) Select facing Case "left" x1=x-w1 y1=y-Rnd(h1/2) Case "right" x1=x+1 y1=y-Rnd(h1/2) Case "up" x1=x-Rnd(w1/2) y1=y-h1 Case "down" x1=x-Rnd(w1/2) y1=y+1 End Select If spaceisempty(x1,y1,w1,h1) = True Then For Local y2=0 Until h1 For Local x2=0 Until w1 map[x2+x1][y2+y1] = isfloor If y2 = 0 Or x2 = 0 Or y2 = h1-1 Or x2 = w1-1 Then map[x2+x1][y2+y1] = 1 ' wall Next Next ' shift map Select facing Case "left" For Local y2=0 Until h1 For Local x2=w1 Until 0 Step -1 map[x2+x1][y2+y1] = map[x2+x1-1][y2+y1] Next Next For Local y2=0 Until h1 map[x1][y2+y1] = isnothing Next 'make doors makedoors(x1,y1,w1,h1,True,False,True,True) Case "right" For Local y2=0 Until h1 For Local x2=0 Until w1 map[x2+x1-1][y2+y1] = map[x2+x1][y2+y1] Next Next For Local y2=0 Until h1 map[x1+w1-1][y2+y1] = isnothing Next 'make doors makedoors(x1-1,y1,w1,h1,False,True,True,True) Case "up" For Local y2=h1 Until 0 Step -1 For Local x2=0 Until w1 map[x2+x1][y2+y1] = map[x2+x1][y2+y1-1] Next Next For Local x2=0 Until w1 map[x1+x2][y1] = isnothing Next 'make doors makedoors(x1,y1+1,w1,h1,True,True,True,False) Case "down" For Local y2=0 Until h1 For Local x2=0 Until w1 map[x2+x1][y2+y1-1] = map[x2+x1][y2+y1] Next Next For Local x2=0 Until w1 map[x1+x2][y1+h1-1] = isnothing Next 'make doors makedoors(x1-1,y1-1,w1+1,h1,True,True,False,True) End Select Return True End If cnt+=1 Wend Return False End Function Function makedoors:Void(x:Int,y:Int,w:Int,h:Int,l:Bool,r:Bool,u:Bool,d:Bool) Local dx:Int Local dy:Int If l=True Then 'left side dx = x+1 dy = y+Rnd(h-4)+2 dol.AddLast(New dooropenlist(dx,dy)) End If If r=True Then 'right side dx = x+w-1 dy = y+Rnd(h-4)+2 dol.AddLast(New dooropenlist(dx,dy)) End If If u=True Then 'up side dx = x+Rnd(w-4)+2 dy = y dol.AddLast(New dooropenlist(dx,dy)) End If If d=True Then ' down side dx = x+Rnd(w-4)+2 dy = y+h-1 dol.AddLast(New dooropenlist(dx,dy)) End If End Function Function spaceisempty:Bool(x:Int,y:Int,w:Int,h:Int) For Local y1=0 Until h For Local x1=0 Until w If map[x1+x][y1+y] <> isnothing Then Return False Next Next Return True End Function Function makeroom(x:Int,y:Int,w:Int,h:Int) For Local y1=0 Until h For Local x1=0 Until w map[x1+x][y1+y] = 2 ' floor If y1 = 0 Or x1 = 0 Or y1 = h-1 Or x1 = w-1 Then map[x1+x][y1+y] = 1 ' wall Next Next End Function Function drawmap:Bool() For Local y=0 Until mapheight For Local x=0 Until mapwidth Select map[x][y] Case isnothing ; Case iswall ; SetColor 150,150,150 ' wall Case isfloor ; SetColor 50,50,50 ' floor Case isdoor ; SetColor 200,200,0 ' door End Select If map[x][y]<>isnothing Then DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight Next Next SetColor 255,255,0 For Local i:=Eachin dcl DrawRect i.x*tilewidth,i.y*tileheight,tilewidth,tileheight Next SetColor 255,255,255 DrawText "Number of rooms :"+rcount,0,0 #rem SetColor 255,0,0 For Local i:=Eachin d DrawRect i.x*tilewidth,i.y*tileheight,tilewidth,tileheight Next #End End Function Function removedoorfromopenlist:Void(x:Int,y:Int) For Local i:=Eachin dol If i.x = x And i.y = y Then dol.Remove i d.AddLast(New debug(x,y)) Return End If Next End Function Function Main() New MyGame() End Function
This is code for a 2d dungeon generator. It makes maps with 1 to 5 rooms connected with doors. It is the first time I tried to make it so the code might be somewhat long for what it does.
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Global tilewidth:Int=16 Global tileheight:Int=16 Global mapwidth:Int=40 Global mapheight:Int=30 Const isnothing:Int=0 Const iswall:Int=1 Const isfloor:Int=2 Const isdoor:Int=3 Const minroomw:Int=5 Const minroomh:Int=5 Const maxroomw:Int=10 Const maxroomh:Int=10 Global map:Int[mapwidth][] Global rcount:Int=0 Class MyGame Extends App Method OnCreate() SetUpdateRate(60) Seed = Millisecs() For Local i = 0 Until mapwidth map[i] = New Int[mapheight] Next createmap(Rnd(1,6)) End Method Method OnUpdate() rcount+=1 Local exitloop=False If KeyHit(KEY_SPACE) Or rcount > 140 Then createmap(Rnd(1,6)) rcount=0 End If End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 DrawText "Generates dungeons with 1 to 5 rooms",0,0 drawmap End Method End Class Function createmap:Bool(numrooms:Int) Local succes:Bool=False Seed = Millisecs() If numrooms<1 Then numrooms=1 If numrooms>5 Then numrooms=4 While succes = False For Local y=0 Until mapheight For Local x=0 Until mapwidth map[x][y] = isnothing Next Next Local startx:Int=mapwidth/2-5 Local starty:Int=mapheight/2-5 Local roomw:Int=Rnd(minroomw,maxroomw) Local roomh:Int=Rnd(minroomh,maxroomh) makeroom(startx,starty,roomw,roomh) If numrooms = 1 Then Return True Local roomcount:Int=1 Local l1:Bool=False Local r1:Bool=False Local u1:Bool=False Local d1:Bool=False While roomcount < numrooms If Rnd(10)<2 And roomcount<numrooms And r1=False Then makedoor("right",startx,starty,roomw,roomh) ; roomcount+=1 ; r1=True If Rnd(10)<2 And roomcount<numrooms And l1=False Then makedoor("left",startx,starty,roomw,roomh) ; roomcount+=1;l1=True If Rnd(10)<2 And roomcount<numrooms And u1=False Then makedoor("up",startx,starty,roomw,roomh) ; roomcount+=1 ; u1=True If Rnd(10)<2 And roomcount<numrooms And d1=False Then makedoor("down",startx,starty,roomw,roomh) ; roomcount+=1;d1=True Wend Local doorfound=False Local x1:Int Local y1:Int roomcount=1 Local cnt:Int=0 While roomcount<numrooms x1=Rnd(mapwidth) y1=Rnd(mapheight) If map[x1][y1] = isdoor Then If makeroomondoor(x1,y1) = True Then roomcount+=1 End If cnt+=1 If cnt>1000 Then Exit Wend If cnt>1000 Then succes=False Else succes = true Wend End Function Function makeroomondoor:Bool(x:Int,y:Int) Local makeroom:Bool=False Local cnt:Int=0 Local x1:Int Local y1:Int Local w1:Int Local h1:Int Local facing:String If map[x-1][y]=isnothing Then facing = "left" If map[x+1][y]=isnothing Then facing = "right" If map[x][y-1]=isnothing Then facing = "up" If map[x][y+1]=isnothing Then facing = "down" While cnt<100 w1 = Rnd(minroomw,maxroomw) h1 = Rnd(minroomh,maxroomh) x1=-1 Select facing Case "left" x1=x-w1 y1=y-Rnd(h1/2) Case "right" x1=x+1 y1=y-Rnd(h1/2) Case "up" x1=x-Rnd(w1/2) y1=y-h1 Case "down" x1=x-Rnd(w1/2) y1=y+1 End Select If x1<>-1 If spaceisempty(x1,y1,w1,h1) = True Then For Local y2=0 Until h1 For Local x2=0 Until w1 map[x2+x1][y2+y1] = isfloor If y2 = 0 Or x2 = 0 Or y2 = h1-1 Or x2 = w1-1 Then map[x2+x1][y2+y1] = 1 ' wall Next Next ' shift map Select facing Case "left" For Local y2=0 Until h1 For Local x2=w1 Until 0 Step -1 If map[x2+x1][y2+y1] <> isdoor map[x2+x1][y2+y1] = map[x2+x1-1][y2+y1] End If Next Next For Local y2=0 Until h1 map[x1][y2+y1] = isnothing Next Case "right" For Local y2=0 Until h1 For Local x2=0 Until w1 If map[x2+x1-1][y2+y1] <> isdoor map[x2+x1-1][y2+y1] = map[x2+x1][y2+y1] End If Next Next For Local y2=0 Until h1 map[x1+w1-1][y2+y1] = isnothing Next Case "up" For Local y2=h1 Until 0 Step -1 For Local x2=0 Until w1 If map[x2+x1][y2+y1] <> isdoor map[x2+x1][y2+y1] = map[x2+x1][y2+y1-1] End If Next Next For Local x2=0 Until w1 map[x1+x2][y1] = isnothing Next Case "down" For Local y2=0 Until h1 For Local x2=0 Until w1 If map[x2+x1][y2+y1-1] <> isdoor map[x2+x1][y2+y1-1] = map[x2+x1][y2+y1] End If Next Next For Local x2=0 Until w1 map[x1+x2][y1+h1-1] = isnothing Next End Select Return True End If End If cnt+=1 Wend Return False End Function Function spaceisempty:Bool(x:Int,y:Int,w:Int,h:Int) For Local y1=0 Until h For Local x1=0 Until w If map[x1+x][y1+y] <> isnothing Then Return False Next Next Return True End Function Function makedoor(side:String,x:Int,y:Int,w:Int,h:Int) Local x1:Int Local y1:Int Select side Case "left" x1=x y1=y+Rnd(h-6)+3 Case "right" x1=x+w-1 y1=y+Rnd(h-6)+3 Case "up" x1=x+Rnd(w-6)+3 y1=y Case "down" x1=x+Rnd(w-6)+3 y1=y+h-1 End Select map[x1][y1] = isdoor End Function Function makeroom(x:Int,y:Int,w:Int,h:Int) For Local y1=0 Until h For Local x1=0 Until w map[x1+x][y1+y] = 2 ' floor If y1 = 0 Or x1 = 0 Or y1 = h-1 Or x1 = w-1 Then map[x1+x][y1+y] = 1 ' wall Next Next End Function Function drawmap:Bool() For Local y=0 Until mapheight For Local x=0 Until mapwidth Select map[x][y] Case isnothing ; Case iswall ; SetColor 150,150,150 ' wall Case isfloor ; SetColor 50,50,50 ' floor Case isdoor ; SetColor 200,200,0 ' door End Select If map[x][y]<>isnothing Then DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight Next Next End Function Function Main() New MyGame() End Function
It took me more then 6 hours to get this example working. It still has a small bug sometimes that I have not been able to find yet. But for the most it works good.
Here in this example you can move a red unit with the mouse through a huge group of units and they will move out of the way. Handy for rts games and such.
It works like this: When moving into a direction it checks if the destination is taken. If so then this unit is moved into a random position. When this is not possible then the next location in that direction is handled this way. The units in that line are pushed into that direction until a free position is found.
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Const tilewidth:Int=16 Const tileheight:Int=16 Class player Field x:Int Field y:Int Field dx:Int Field dy:Int Field ox:Int Field oy:Int Field w:Int=16 Field h:Int=16 Method New(_x:Int,_y:Int) x=_x y=_y dx=x dy=y End Method Method update() Local x1:Int=MouseX()/tilewidth Local y1:Int=MouseY()/tileheight Local moved:Bool=False If MouseHit(MOUSE_LEFT) If rectsoverlap(x1,y1,1,1,x-1,y-1,3,3) = True Then moved=True End If If moved=True moveunit(x1,y1) dx = x1 dy = y1 End If If x<> dx Or y<>dy If x<dx Then ox+=1 If x>dx Then ox-=1 If y<dy Then oy+=1 If y>dy Then oy-=1 If ox=16 Then x+=1 ; dx=x ; ox=0 If oy=16 Then y+=1 ; dy=y ; oy=0 If ox=-16 Then x-=1 ; dx=x ; ox = 0 If oy=-16 Then y-=1 ; dy=y ; oy = 0 End If End Method Method moveunit(_x,_y) Local occupied:Bool=False For Local i:=Eachin u If i.x = _x And i.y=_y Then occupied = True Next If occupied = False Then dx=_x dy=_y Else dx=_x dy=_y moveunitoutoftheway(_x,_y) End If End Method Method moveunitoutoftheway(x1:Int,y1:Int) Local xdir:Int = x1-x Local ydir:Int = y1-y Local eloop:Bool=False Local mx:Int=0 Local my:Int=0 While eloop=False eloop=True For Local i:=Eachin u If i.x = x1+mx And i.y=y1+my If moveintofreepos(i.x,i.y) = False Then i.dx+=xdir i.dy+=ydir eloop=False Else Return True End If End If Next mx+=xdir my+=ydir Wend End Method Method moveintofreepos:Bool(x1:Int,y1:Int) Local eloop:Bool=False Local mx:Int Local my:Int Local cnt:Int=0 For Local i:=Eachin u If i.x = x1 And i.y=y1 While eloop = False eloop=True mx=Rnd(-2,2) my=Rnd(-2,2) If x1+mx = p.x And y1+my = p.y Then eloop = False If x1+mx = p.dx And y1+my = p.dy Then eloop = False If x1+mx = x1 And y1+my = y1 Then eloop = False For Local ii:=Eachin u If ii.x = x1+mx And ii.y = y1+my Then eloop = False If ii.dx = x1+mx And ii.dy = y1+my Then eloop = False Next cnt+=1 If cnt>100 Then Return False Wend i.dx = x1+mx i.dy = y1+my End If Next Return True End Method Method draw() SetColor 255,0,0 DrawOval x*tilewidth+ox,y*tileheight+oy,tilewidth,tileheight End Method End Class Class unit Field x:Int Field y:Int Field w:Int=16 Field h:Int=16 Field dx:Float Field dy:Float Field ox:Int Field oy:Int Field moved:Bool=False Field hasmoved:Bool=False Method New(_x:Int,_y:Int) x=_x y=_y dx=x dy=y End Method Method update() If x<>dx Or y<>dy If x<dx Then ox+=1 If x>dx Then ox-=1 If y<dy Then oy+=1 If y>dy Then oy-=1 If ox=16 Then x=dx ; ox=0 If oy=16 Then y=dy ; oy=0 If ox=-16 Then x=dx ; ox = 0 If oy=-16 Then y=dy ; oy = 0 End If If hasmoved = True And x=dx And y=dy Then hasmoved=False End Method Method draw() SetColor 255,255,0 DrawOval (x*tilewidth)+ox,(y*tileheight)+oy,tilewidth,tileheight End Method End Class Global u:List<unit> = New List<unit> Global p:player = New player(10,10) Class MyGame Extends App Method OnCreate() SetUpdateRate(60) Local x1:Int=20 Local y1:Int=15 Local x3:Int Local y3:Int For Local i=0 Until 300 Local taken:Bool=True While taken=True Local x2:Int=(Rnd(-10,10)) Local y2:Int=(Rnd(-10,10)) x3=x1+x2 y3=y1+y2 taken=False For Local ii:=Eachin u If ii.x = x3 And ii.y = y3 Then taken = True ; Exit Next Wend u.AddLast(New unit(x3,y3)) Next End Method Method OnUpdate() p.update For Local i:=Eachin u i.update Next End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 DrawText "Press the mouse near the red oval to move it into that direction.",0,0 DrawText "The yellow ovals move out of the way.",0,16 For Local i:=Eachin u i.draw Next p.draw End Method End Class Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1) + Abs(y2-y1) End Function Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return ATan2(y1-y2, x1-x2) End Function Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int) If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False Return True End Function Function Main() New MyGame() End Function
#monkey-X #gamedev Here a small example of how ai flies to asteroids to mine them. They fly back to their base planet and continue to mine until all asteroids are gone. The map resets to a random new map at random intervals. In this example there can be up to 50 ai mining ships per map. Code below :
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Global numships:Int=45 Global minerals:Int=0 Global resettime:Int=Millisecs()+15000 Class ship Field x:Float Field y:Float Field angle:Int Field destangle:Int Field incx:Float Field incy:Float Field homex:Int Field homey:Int Field destx:Int Field desty:Int Field state:String="evaluate" Field laststate:String Field cargo:Int=0 Field minetime:Int Method New(_x:Float,_y:Float,_angle:Int) x = _x y = _y homex = x homey = y angle = _angle End Method Method update() Select state Case "evaluate" ; eval Case "findasteroidtomine" ; findasteroid Case "flytotarget" ; flytot Case "mineasteroid" ; mineasteroid End Select End Method Method mineasteroid() If minetime < Millisecs() Then For Local i:=Eachin a If i.x = destx And i.y = desty i.s -=1 If i.s < 1 Then i.delete = True Exit End If Next cargo = 1 laststate=state destx = homex desty = homey state="flytotarget" End If End Method Method flytot() destangle = getangle(x,y,destx,desty) If leftangle(angle,destangle) = True Then angle-=5 Else angle+=5 If angle<-180 Then angle=180 If angle>180 Then angle = -180 incx = Cos(angle) incy = Sin(angle) x+=incx y+=incy If distance(x,y,destx,desty) < 5 Then If laststate = "findasteroidtomine" Then laststate = state ; state = "mineasteroid" minetime = Millisecs()+2000 End If If laststate = "mineasteroid" cargo = 0 minerals+=1 laststate = state ; state = "evaluate" End If End If End Method Method findasteroid() Local sd:Int = 100000 Local afound:Bool=False Local taken:Bool=False For Local i:=Eachin a Local d:Int = distance(i.x,i.y,x,y) If d<sd Then Local taken = False For Local ii:=Eachin sh If ii.destx = i.x And ii.desty=i.y taken = True End If Next If taken=False sd=d destx=i.x desty=i.y afound=True End If End If Next If afound = True Then laststate= state ; state="flytotarget" 'Print "found asteroid to mine"+Millisecs() Else 'Print "Nothing state ship"+Millisecs state="evaluate" End If End Method Method eval() If Rnd(200)<2 And cargo = 0 Then laststate=state ; state="findasteroidtomine" End Method Method draw() SetColor 255,255,0 DrawPoint x,y End Method End Class Class star Field x:Int Field y:Int Method New(_x:Int,_y:Int) x=_x y=_y End Method Method draw() SetColor 255,255,255 DrawPoint x,y End Method End Class Class asteroid Field x:Float Field y:Float Field s:Float Field rotangle:Float Field rotangles:Float Field delete:Bool=False Method New(_x:Float,_y:Float,_s:Float) x = _x y = _y s = _s rotangle = 0.0 rotangles = Rnd(-1,1) End Method Method update() rotangle += rotangles If rotangle <-180 Then rotangle = 180 If rotangle >180 Then rotangle = -180 For Local i:=Eachin a If i.delete = True Then a.Remove i Next End Method Method draw() PushMatrix() Translate x,y Rotate(-rotangle) Translate -x,-y SetColor 100,100,100 DrawRect x-s/2,y-s/2,s,s PopMatrix() End Method End Class Class planet Field x:Float Field y:Float Field s:Float Field t:Int ' planet type Method New(_x:Float,_y:Float,_s:Float,_t:Int) x = _x y = _y s = _s t = _t End Method Method update() End Method Method draw() Select t Case 1 'earthlike SetColor 0,200,0 Case 2 'gas SetColor 255,0,0 End Select DrawOval x-s/2,y-s/2,s,s End Method End Class Global p:List<planet> = New List<planet> Global a:List<asteroid> = New List<asteroid> Global s:List<star> = New List<star> Global sh:List<ship> = New List<ship> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) createmap End Method Method OnUpdate() If Rnd(1600)<2 And resettime<Millisecs() Then createmap ; resettime=Millisecs()+15000 For Local i:=Eachin p 'update planets i.update Next For Local i:=Eachin a 'update asteroids i.update Next For Local i:=Eachin sh i.update Next End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 DrawText "Minerals Mined : " + minerals,0,0 For Local i:=Eachin s 'draw stars i.draw Next For Local i:=Eachin p 'draw planets i.draw Next For Local i:=Eachin a 'draw asteroids i.draw Next For Local i:=Eachin sh 'draw ships i.draw Next End Method End Class Function createmap() a.Clear() sh.Clear() s.Clear() p.Clear() minerals = 0 numships = Rnd(10,300) Seed = Millisecs() 'Make planets For Local i=0 Until 3 Local x1 = Rnd(25,screenwidth-50) Local y1 = Rnd(25,screenheight-50) p.AddLast(New planet(x1,y1,Rnd(5,10),2)) Next Local x1 = 320 Local y1 = 240 p.AddLast(New planet(x1,y1,Rnd(5,25),1)) ' Make asteroids Local numfields:Int=Int(Rnd(3,6)) For Local i=0 Until numfields Local x1 = Rnd(50,screenwidth-50) Local y1 = Rnd(50,screenheight-50) Local numa:Int=Rnd(3,45) For Local ii=0 Until numa Local x2 = Rnd(-50,50) Local y2 = Rnd(-50,50) a.AddLast(New asteroid(x1+x2,y1+y2,Rnd(2,8))) Next Next 'Make stars For Local i=0 Until 100 s.AddLast(New star(Rnd(screenwidth),Rnd(screenheight))) Next 'Make ships For Local i=0 Until numships Local v:Int=Rnd(360) Local x1:Float Local y1:Float x1=320+(Cos(v)*32)+Rnd(-2,2) y1=240+(Sin(v)*32)+Rnd(-2,2) sh.AddLast(New ship(x1,y1,Rnd(-180,180))) Next End Function Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1) + Abs(y2-y1) End Function Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return ATan2(y1-y2, x1-x2) End Function Function leftangle:Bool(_angle:Int,_destinationangle:Int) Local cnt1 = 0 Local a1 = _angle While a1<>_destinationangle a1+=1 If a1>180 Then a1=-180 cnt1+=1 Wend If cnt1<180 Then Return True Else Return False End Function Function Main() New MyGame() End Function
Here 3 screens playable of the game Cybernoid 2. Most of the things are remade. There is no collision so you can not die. (use cursors to control ship)
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Const tilewidth:Int=32 Const tileheight:Int=32 Const mapwidth:Int=16 Const mapheight:Int=10 Global currentscreen:Int=0 '1 = block '2 = circle turn around ship thingy Global screen1:Int[][] = [ [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,1,0,0,0,0,0,0,1,1,0,0,0,0,1,1], [1,1,0,0,0,0,0,0,1,1,0,0,0,0,1,1], [1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1], [1,1,0,1,0,1,0,0,0,0,0,0,0,0,1,1], [1,1,0,1,0,1,0,0,0,0,0,0,0,0,1,1], [1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1], [1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1], [1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1]] Global screen2:Int[][] = [ [1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0], [1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0], [1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0], [0,0,0,1,1,1,0,0,0,0,1,1,1,1,1,1], [0,0,0,1,1,1,1,1,0,0,1,1,1,1,1,1], [0,0,0,1,1,1,1,1,0,0,1,1,1,1,1,1], [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1], [0,0,0,0,2,0,0,0,0,0,0,0,1,1,1,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]] Global screen3:Int[][] = [ [1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1], [1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1], [1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0], [1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0], [1,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0], [1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0], [1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,0], [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]] Class effect Field x:Int Field y:Int Field w:Float Field h:Float Field delete:Bool=False Method New(_x:Int,_y:Int) x=_x y=_y w=10 h=10 End Method Method update() w-=.2 h-=.2 If w<0 Or h<0 Then delete = True For Local i:=Eachin e If i.delete = True Then e.Remove i Next End Method Method draw() SetColor 255,255,0 DrawOval x+w/2,y+h/2,w,h End Method End Class Class powerup Field x:Int Field y:Int Field w:Int=32 Field h:Int=32 Field delete:Bool=False Method New(_x:Int,_y:Int) x=_x y=_y End Method Method update() If rectsoverlap(p.x,p.y,p.w,p.h,x,y,w,h) = True delete = True p.cweapon=True End If For Local i:=Eachin pu If i.delete=True Then pu.Remove i Next End Method Method draw() SetColor 255,255,0 DrawOval x,y,w,h SetColor 255,255,255 DrawText "W",x+w/2,y+h/2,0.5,0.5 End Method End Class Class dualslider Field x1:Int Field y1:Int Field w:Int=32 Field h:Int=32 Field x2:Int Field y2:Int Field dir:String="right" Method New(_x1:Int,_y1:Int,_x2:Int,_y2:Int) x1 = _x1 y1 = _y1 x2 = _x2 y2 = _y2 End Method Method update() If dir="right" Local s:Bool=False If tc(x1+1,y1,w,h) = True Then s=True If tc(x2+1,y1,w,h) = True Then s=True If s = False x1+=1 x2+=1 Else dir="left" End If End If If dir="left" Local s:Bool=False If tc(x1-1,y1,w,h) = True Then s=True If tc(x2-1,y1,w,h) = True Then s=True If s = False x1-=1 x2-=1 Else dir="right" End If End If End Method Method draw() SetColor 255,0,0 DrawOval x1,y1,w,h DrawOval x2,y2,w,h End Method End Class Class laser Field x:Float Field y:Float Field w:Int=8 Field h:Int=8 Field incx:Float Field incy:Float Field delete:Bool=False Method New(_x:Float,_y:Float,_incx:Float,_incy:Float) x = _x y = _y incx = _incx incy = _incy End Method Method update() x+=incx y+=incy If tc(x,y,w,h) = True delete=True End If For Local i:=Eachin l If i.delete = True Then l.Remove i Next End Method Method draw() SetColor 255,255,0 DrawOval x-w/2,y-h/2,w,h End Method End Class Class turret Field x:Int Field y:Int Field w:Int=64 Field h:Int=64 Field shottimer:Int Method New(_x,_y) x = _x y = _y End Method Method update() If shottimer < Millisecs() If p.x < x Local a:Int=getangle(p.x+p.w/2,p.y+p.h/2,x,y+h/2) Local ix:Float=Cos(a) Local iy:Float=Sin(a) l.AddLast(New laser(x,y+h/2,ix,iy)) shottimer = Millisecs() + 1000 End If End If End Method Method draw() SetColor 255,0,0 DrawRect x,y,w,h End Method End Class Class player Field x:Float Field dir:String="right" Field y:Float Field w:Int=32 Field h:Int=32 Field shield:Int=100 Field msl:Int=1 Field msr:Int=1 Field cweapon:Bool=False Field cweapona:Int=0 Field cwd:Int=0 Method New() End Method Method update() If cweapon = True cwd+=1 If cwd>10 Then e.AddLast(New effect(x+Cos(cweapona)*50,y+Sin(cweapona)*50)) cwd=0 End If If dir="left" Then cweapona-=5 Else cweapona+=5 If cweapona < -180 Then cweapona = 180 If cweapona > 180 Then cweapona = -180 End If Select currentscreen Case 0 If p.y+p.h > mapheight*tileheight+96 Then currentscreen = 1 t.AddLast(New turret(12*tilewidth,9*tileheight)) pu.AddLast(New powerup(6*tilewidth,10*tileheight)) p.y=96 End If Case 1 If p.x < 64 Then currentscreen = 2 t.Clear() l.Clear() pu.Clear() Local x1:Int=5*tilewidth Local y1:Int=8*tileheight ds.AddLast(New dualslider(x1,y1,x1+4*tilewidth,y1)) p.x = 32+mapwidth*tilewidth End If Case 2 If p.y < 96 Then currentscreen = 0 ds.Clear() e.Clear() p.cweapon=False p.x = 6*tilewidth p.y = 8*tileheight End If End Select If msl>0 Then msl-=1 If msr>0 Then msr-=1 'gravity for ship If p.y+p.h < mapheight*tileheight+97 For Local i=0 Until 2 If tc(p.x,p.y+1,p.w,p.h) = False p.y+=1 End If Next End If If KeyDown(KEY_UP) If p.y-1 > 96 For Local i=0 Until 4 If tc(p.x,p.y-1,p.w,p.h) = False p.y-=1 End If Next End If End If If KeyDown(KEY_LEFT) dir="left" If msl<3 Then msl+=2 For Local i=0 Until msl If tc(p.x-1,p.y,p.w,p.h) = False p.x-=1 End If Next End If If KeyDown(KEY_RIGHT) dir="right" If p.x+p.w+1 < mapwidth*tilewidth+64 If msr<3 Then msr+=2 For Local i=0 Until msr If tc(p.x+1,p.y,p.w,p.h) = False p.x+=1 End If Next End If End If End Method Method draw() SetColor 0,0,255 DrawRect x,y,w,h If cweapon = True Then DrawOval x+Cos(cweapona)*50,y+Sin(cweapona)*50,20,20 End If End Method End Class Global p:player = New player Global t:List<turret> = New List<turret> Global l:List<laser> = New List<laser> Global ds:List<dualslider> = New List<dualslider> Global pu:List<powerup> = New List<powerup> Global e:List<effect> = New List<effect> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) ' player start position screen 1 p.x = 6*tilewidth p.y = 8*tileheight End Method Method OnUpdate() p.update ' update player For Local i:=Eachin l 'update lasers i.update Next For Local i:=Eachin t 'update turrets i.update Next For Local i:=Eachin ds 'update dual sliders i.update Next For Local i:=Eachin pu 'update powerups i.update Next For Local i:=Eachin e ' update effects i.update Next End Method Method OnRender() Cls 0,0,0 SetColor 100,100,100 DrawRect 64,32,screenwidth-128,64 SetColor 255,255,255 drawboxedrect 64,32,screenwidth-1-128,64 drawmap drawboxedrect 64,96,screenwidth-1-128,mapheight*tileheight For Local i:=Eachin t' draw turrets i.draw Next For Local i:=Eachin ds 'draw dual sliders i.draw Next For Local i:=Eachin l' 'draw lasers i.draw Next For Local i:=Eachin pu 'draw powerups i.draw Next For Local i:=Eachin e 'draw effects i.draw Next p.draw 'draw player End Method End Class Function drawmap:Void() SetColor 255,255,255 For Local y=0 Until mapheight For Local x=0 Until mapwidth Local t:Int=0 Select currentscreen Case 0 t = screen1[y][x] Case 1 t = screen2[y][x] Case 2 t = screen3[y][x] End Select If t=1 Then DrawRect x*tilewidth+64,y*tileheight+96,tilewidth,tileheight End If Next Next End Function 'coords collide with map solid blocks true/false Function tc:Bool(x:Int,y:Int,w:Int,h:Int) Local cx = (x-64)/tilewidth Local cy = (y-96)/tileheight For Local y2=cy-1 Until cy+4 For Local x2=cx-1 Until cx+4 If x2>=0 And x2<mapwidth And y2>=0 And y2<mapheight Local t:Int=0 Select currentscreen Case 0;t = screen1[y2][x2] Case 1;t = screen2[y2][x2] Case 2;t = screen3[y2][x2] End Select If t = 1 Local x3 = (x2)*tilewidth Local y3 = (y2)*tileheight If rectsoverlap(x-64,y-96,w,h,x3,y3,tilewidth,tileheight) = True Return True End If End If End If Next Next Return False End Function Function drawboxedrect:Void(x:Int,y:Int,w:Int,h:Int) DrawLine x,y,x+w,y DrawLine x,y,x,y+h DrawLine x,y+h,x+w,y+h DrawLine x+w,y,x+w,y+h End Function Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int) If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False Return True End Function Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return ATan2(y1-y2, x1-x2) End Function Function Main() New MyGame() End Function
This is the first time I made something like this. You control a player with the cursor left and right. Space is hitting. 2 baddies move towards you and try to hit you. When you hit them 3 times they dissapear. When both baddies are gone then 2 new one appear. You can not die. The hitcount is shown on the characters.
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Class baddie Field x:Float Field y:Float Field w:Int=32 Field h:Int=48 Field state:String="movein" Field laststate:String Field frame:String Field lastframe:String Field delay:Int Field fight:Bool Field hitcount:Int=3 Field delete:Bool=False Field hashit:Bool Method update() Select state Case "fight" If delay<Millisecs() And distance(x+w/2,y+h/2,p.x+p.w/2,p.y+p.h/2) < 40 Then state="verticalalign" If frame="right" And x>p.x Then frame="left" If frame="left" And x<p.x Then frame="right" If delay< Millisecs() And distance(x+w/2,y+h/2,p.x+p.w/2,p.y+p.h/2) > 80 Then state = "movein" ; fight=False If delay < Millisecs() And (frame="hitright" Or frame="hitleft") frame=lastframe hashit=False End If If delay < Millisecs() And (frame="left" Or frame="right") If Rnd(100)<2 lastframe=frame delay = Millisecs()+400 If frame="left" Then frame="hitleft" hashit = True If rectsoverlap(x-w,y,w*2,h,p.x,p.y,p.w,p.h) = True Then p.hitcount-=1 Else frame="hitright" hashit=True If rectsoverlap(x,y,w*2,h,p.x,p.y,p.w,p.h) = True Then p.hitcount-=1 End If End If End If Case "verticalalign" keepaidistance() If x<p.x And distance(x+w/2,y+h/2,p.x+p.w/2,p.y+p.h/2) < 40 Then x-=1 If x+w>p.x And distance(x+w/2,y+h/2,p.x+p.w/2,p.y+p.h/2) < 40 Then x+=1 If y<p.y Then y+=1 If y>p.y Then y-=1 If y=p.y Then state="fight" Case "evaluate" Local otherfighting:Bool=False For Local i:=Eachin b If i.fight=True Then otherfighting=True Next If otherfighting = False fight=True state="verticalalign" Else state="movein" End If Case "movein" keepaidistance() If distance(x+w/2,y+w/2,p.x+p.w/2,p.y+p.h/2) > 60 If x>p.x Then x-=1 ; frame="left" If x<p.x Then x+=1 ; frame="right" Else state="evaluate" End If If x=p.x Then state="evaluate" End Select For Local i:=Eachin b If i.delete = True Then b.Remove i Next End Method Method keepaidistance() For Local i:=Eachin b If x<>i.x And y<>i.y If distance(x+16,y+16,i.x+16,i.y+16) < 64 Then If x<=i.x Then x-=1 Else x+=1 If y<=i.y Then y-=1 Else y+=1 End If End If Next End Method Method New(_x:Float,_y:Float) x=_x y=_y End Method Method draw() SetColor 255,255,255 Select frame Case "right" DrawRect x,y,w,h Case "left" DrawRect x,y,w,h Case "hitright" DrawRect x,y,w,h DrawRect x,y+10,w*2,10 Case "hitleft" DrawRect x,y,w,h DrawRect x-w,y+10,w,10 End Select DrawText "HC:"+hitcount,x+w/2,y+h/2,0.5,0.5 End Method End Class Class game Method update() End Method End Class Class player Field x:Float=100 Field y:Float=240 Field w:Int=32 Field h:Int=48 Field frame:String="right" Field lastframe:String Field delay:Int Field hitcount:Int=3 Field hashit:Bool=False Method update() If frame="left" Or frame="right" If KeyDown(KEY_DOWN) y+=3 If y>400 Then y=400 End If If KeyDown(KEY_UP) y-=3 If y<200 Then y=200 End If If KeyDown(KEY_RIGHT) frame="right" x+=3 If x+w>screenwidth Then x=screenwidth-w End If If KeyDown(KEY_LEFT) frame="left" x-=3 If x<0 Then x=0 End If End If If KeyDown(KEY_SPACE) If frame="right" Or frame="left" hashit=False delay = Millisecs()+200 If frame="right" Then frame = "hitright" lastframe="right" End If If frame="left" Then frame = "hitleft" lastframe="left" End If End If End If Select frame Case "hitright" If hashit = False For Local i:=Eachin b If rectsoverlap(x,y,w*2,h,i.x,i.y,i.w,i.h) = True i.hitcount -=1 If i.hitcount = 0 Then i.delete = True End If Next hashit=True End If If delay < Millisecs() frame=lastframe End If Case "hitleft" If hashit = False For Local i:=Eachin b If rectsoverlap(x-w,y,w*2,h,i.x,i.y,i.w,i.h) = true i.hitcount -=1 If i.hitcount = 0 Then i.delete = True End If Next hashit=True End If If delay < Millisecs() frame=lastframe End If End Select End Method Method draw() SetColor 255,255,255 Select frame Case "right" DrawRect x,y,w,h Case "left" DrawRect x,y,w,h Case "hitright" DrawRect x,y,w,h DrawRect x,y+10,w*2,10 Case "hitleft" DrawRect x,y,w,h DrawRect x-w,y+10,w,10 End Select DrawText "HC:"+hitcount,x+w/2,y+h/2,0.5,0.5 End Method End Class Global g:game = New game Global p:player = New player Global b:List<baddie> = New List<baddie> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) b.AddLast(New baddie(screenwidth+32,200)) b.AddLast(New baddie(screenwidth+32,350)) End Method Method OnUpdate() If b.IsEmpty() = True Then b.AddLast(New baddie(screenwidth+32,200)) b.AddLast(New baddie(screenwidth+32,350)) End If For Local i:=Eachin b i.update Next p.update End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 DrawText "Use cursor left/right to move, space to hit.",0,0 For Local i:=Eachin b i.draw Next p.draw End Method End Class Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1) + Abs(y2-y1) End Function Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int) If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False Return True End Function Main() New MyGame() End Function
Here a example of how to let the player jump on the ai to kill them. Use the cursor keys to ove the player, space to jump. When the player lands on a baddie he bounces back up again.
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Const tilewidth:Int=32 Const tileheight:Int=32 Const mapwidth:Int=20 Const mapheight:Int=15 Const numbaddies:Int=10 Global map:Int[][] = [ [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] ] Class baddie Field x:Float Field y:Float Field w:Int Field h:Float Field delete:Bool=False Field state:String = "wait" Method New(_x:Float,_y:Float,_w:Int,_h:Int) x=_x y=_y w=_w h=_h End Method Method update() Select state Case "sink" h-=1 If h<=0 Then delete = true Case "moveright" For Local i=0 Until 1 If tc(x,y-h,w,h,1,0) = False Then x+=1 Else state="moveleft" Next If Rnd(100)<2 Then state="wait" Case "moveleft" For Local i=0 Until 1 If tc(x,y-h,w,h,-1,0) = False Then x-=1 Else state="moveright" Next If Rnd(100)<2 Then state="wait" Case "wait" If Rnd(100)<2 If Int(Rnd(1,3)) = 1 state="moveleft" Else state="moveright" End If End If End Select For Local i:=Eachin b If i.delete = True Then b.Remove i Next End Method Method draw() SetColor 255,0,0 DrawRect x,y-h,w,h End Method End Class Class player Field x:Float=3*tilewidth Field y:Float=3*tileheight Field w:Int=tilewidth Field h:Int=tileheight Field isjumping:Bool=False Field incy:Float=0 Method update() If KeyDown(KEY_SPACE) If isjumping = False isjumping = True incy=-9 End If End If If KeyDown(KEY_RIGHT) For Local i=0 Until 5 If ptc(1,0) = False x+=1 Else Exit End If Next End If If KeyDown(KEY_LEFT) For Local i=0 Until 5 If ptc(-1,0) = False x-=1 Else Exit End If Next End If If isjumping = False If ptc(0,1) = False incy = 0 isjumping = True End If End If If isjumping = True If incy>=0 If incy<5 Then incy+=.3 For Local i=0 Until incy If ptc(0,1) = False y+=1 Else incy = 0 isjumping = False Exit End If Next End If If incy<0 incy+=.3 For Local i=0 Until Abs(incy) If ptc(0,-1) = False y-=1 Else incy=0 Exit End If Next End If End If jumponbaddie End Method Method jumponbaddie() For Local i:=Eachin b If isjumping=True If incy>0 If rectsoverlap(x,y,w,h,i.x,i.y-i.h,i.w,i.h) = True Then i.state = "sink" incy=-9 End If End If End If Next End Method Method draw() SetColor 255,255,0 DrawRect x,y,w,h SetColor 255,255,255 DrawText "P",x+w/2,y+h/2,0.5,0.5 End Method End Class Global p:player = New player Global b:List<baddie> = New List<baddie> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) For Local i=0 Until numbaddies Local w:Int=Rnd(10,32) Local h:Int=Rnd(10,32) b.AddLast(New baddie(Rnd(100,screenwidth-64),mapheight*tileheight-32,w,h)) Next End Method Method OnUpdate() For Local i:=Eachin b i.update Next p.update End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 drawmap For Local i:=Eachin b i.draw Next p.draw SetColor 255,255,255 DrawText "Use cursor left/right to move, space to jump.",0,0 DrawText "Jump on ai to kill them.",0,16 End Method End Class Function drawmap:Void() SetColor 255,255,255 For Local y=0 Until mapheight For Local x=0 Until mapwidth If map[y][x] = 1 DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight End If Next Next End Function 'tile collision Function tc:Bool(x:Int,y:Int,w:Int,h:Int,offsetx:Int=0,offsety:Int=0) Local cx = (x+offsetx)/tilewidth Local cy = (y+offsety)/tileheight For Local y2=cy-1 Until cy+4 For Local x2=cx-1 Until cx+4 If x2>=0 And x2<mapwidth And y2>=0 And y2<mapheight If map[y2][x2] = 1 Local x3 = (x2)*tilewidth Local y3 = y2*tileheight If rectsoverlap(x+offsetx,y+offsety,w,h,x3,y3,tilewidth,tileheight) = True Return True End If End If End If Next Next Return False End Function 'player tile collision Function ptc:Bool(offsetx:Int=0,offsety:Int=0) Local cx = (p.x+offsetx)/tilewidth Local cy = (p.y+offsety)/tileheight For Local y2=cy-1 Until cy+4 For Local x2=cx-1 Until cx+4 If x2>=0 And x2<mapwidth And y2>=0 And y2<mapheight If map[y2][x2] = 1 Local x3 = (x2)*tilewidth Local y3 = y2*tileheight If rectsoverlap(p.x+offsetx,p.y+offsety,p.w,p.h,x3,y3,tilewidth,tileheight) = True Return True End If End If End If Next Next Return False End Function Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int) If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False Return True End Function Function Main() New MyGame() End Function
Here a short example of how to make effects with Monkey. In this example rectangles are shot up from the center of the screen, they rotate and then they fall down. The SetAlpha is used so they are transparent.
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Class effect Field x:Float Field y:Float Field incx:Float Field incy:Float Field w:Int Field h:Int Field col:Int Field angle:Int=Rnd(-180,180) Field angleturn:Int Field delete:Bool = False Method New(_x:Float,_y:Float,_w:Int,_h:Int) x = _x y = _y w = _w h = _h col = Rnd(50,150) incx = Rnd(-2,2) incy = Rnd(-10,-5) angleturn = Rnd(-5,5) End Method Method update() angle+=angleturn If angle>180 Then angle=-180 If angle<-180 Then angle=180 x+=incx y+=incy incy+=.1 If y>screenheight Then delete = True For Local i:=Eachin e If i.delete = True Then e.Remove i Next End Method Method draw() PushMatrix() Translate x,y Rotate(-angle) Translate -x,-y SetColor 10+col,0,0 SetAlpha 0.5 'part transparent setting DrawRect x,y,w,h PopMatrix() SetAlpha 1 'restore transparent setting to none transparent End Method End Class Global e:List<effect> = New List<effect> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) End Method Method OnUpdate() If Rnd(10) < 2 Then e.AddLast(New effect(320,240,Rnd(5,25),Rnd(5,25))) For Local i:=Eachin e i.update Next End Method Method OnRender() Cls 0,0,0 For Local i:=Eachin e i.draw Next SetColor 255,255,255 End Method End Class Function Main() New MyGame() End Function
Here is begin part of a space game. There is a ship that can rotate and increase/decrease speed. The map moves and the spaceship stays in the center of the screen. The rotation of the ship is done using the Pushmatrix and popmatrix commands.
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Const numstars:Int=150 Class player Field x:Float=screenwidth/2 Field y:Float=screenheight/2 Field incx:Float=0 Field incy:Float=0 Field w:Int=16 Field h:Int=16 Field angle:Int=0 Method draw() PushMatrix() Translate 320,240 Rotate(-angle) DrawPoly([Float(0-8),0 ,8,0-8 ,8,8]) DrawLine -10,0,8,0 PopMatrix() End Method Method update() If KeyDown(KEY_UP) incx = incx+Cos(angle)/10 incy = incy+Sin(angle)/10 End If If KeyDown(KEY_DOWN) incx = incx-Cos(angle)/30 incy = incy-Sin(angle)/30 End If If incx>3 Then incx = 3 If incy>3 Then incy = 3 If incx<-3 Then incx = -3 If incy<-3 Then incy = -3 If KeyDown(KEY_LEFT) angle-=1 If angle<-180 Then angle = 180 End If If KeyDown(KEY_RIGHT) angle+=1 If angle>180 Then angle=-180 End If For Local i:=Eachin s i.x+=incx i.y+=incy If i.x>screenwidth Then i.x = 0 ; i.y=Rnd(screenheight) If i.y>screenheight Then i.y=0 ; i.x = Rnd(screenwidth) If i.x<0 Then i.x=screenwidth ; i.y=Rnd(screenheight) If i.y<0 Then i.y=screenheight ; i.x=Rnd(screenwidth) Next End Method End Class Class star Field x:Float Field y:Float Method New() x = Rnd(screenwidth) y = Rnd(screenheight) End Method Method draw() DrawPoint x,y End Method End Class Global s:List<star> = New List<star> Global p:player = New player Class MyGame Extends App Method OnCreate() SetUpdateRate(60) For Local i=0 Until numstars s.AddLast(New star()) Next End Method Method OnUpdate() p.update End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 DrawText "Use cursor keys to control the ship.",0,0 For Local i:=Eachin s i.draw Next p.draw End Method End Class Function Main() New MyGame() End Function
Here a minimap example. Press the mouse in the minimap(right top) and the map will move to that part.
Import mojo Const screenwidth:Int=640 Const screenheight:Int=480 Const tilewidth:Int=16 Const tileheight:Int=16 Const mapwidth=100 Const mapheight=100 Global numland:Int = 0 Global percland:Float = 1.7 Global map:Int[mapwidth][] Global mapx:Int=0 Global mapy:Int=0 Class minimap Field image:Image Field pixels:Int[100*100] Method makeminimap() For Local y=0 Until 100 For Local x=0 Until 100 'Local pc = y*mapheight+x Local val = map[x][y] Local val2:Int ' tile 1,2,3,4 is sea If val<5 Then val2 = argb(0,0,val*10+100) ' tile 5 6 7 8 is grasslands/trees If val>=5 And val <9 Then val2 = argb(0,val*15,0) 'tiles 9 10 11 12 13 is mountains If val>=9 Then val2 = argb(val*15,val*4,0) drawr(x,y,1,1,val2) Next Next image.WritePixels(mm.pixels, 0, 0, 100, 100, 0) End Method Method drawr(x1,y1,w1,h1,col) For Local y2=y1 Until y1+h1 For Local x2=x1 Until x1+w1 Local pc = y2*100+x2 If pc >= 0 And pc < 100*100 pixels[pc] = col End If Next Next End Method Method draw(_x:Int,_y:Int) DrawImage image,_x,_y End Method End Class Global mm:minimap = New minimap Class MyGame Extends App Method OnCreate() 'make the map array For Local i = 0 Until mapwidth map[i] = New Int[mapheight] Next makemap 'create the minimap image mm.image = CreateImage(100, 100) 'draw the minimap image mm.makeminimap SetUpdateRate(60) End Method Method OnUpdate() 'here we move the map from the minimap If MouseDown(MOUSE_LEFT) If MouseX()>screenwidth-105 If MouseY()>5 If MouseX()<screenwidth-5 If MouseY()<110 mapx = 100-(screenwidth-MouseX())+5 mapy = MouseY()-5 mapx = mapx - (screenwidth/tilewidth)/2 mapy = mapy - (screenheight/tileheight)/2 'Print "mapx:"+mapx+"mapy:"+mapy If mapx<0 Then mapx=0 If mapy<0 Then mapy=0 If mapx+screenwidth/tilewidth>mapwidth Then mapx=mapwidth-screenwidth/tilewidth If mapy+screenheight/tileheight>mapheight Then mapy=mapheight-screenheight/tileheight End If End If End If End If End If End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 drawmap SetColor 0,0,0 DrawRect screenwidth-110,0,110,110 SetColor 255,255,255 'here we draw the minimap image mm.draw(screenwidth-105,5) 'here we draw the white box in the minimap drawboxedrect(mapx+screenwidth-105,5+mapy,screenwidth/tilewidth,screenheight/tileheight) DrawText "Press the mouse in the minimap to move the big map",0,0 ' drawminimap End Method End Class Function makemap:Void() numland=0 ' exit loop if conditions on land percentage is good While numland<(mapwidth*mapheight/percland) ' erase the old data For Local y=0 Until mapheight For Local x=0 Until mapwidth map[x][y] = 0 Next Next 'lowest hold the highest tile value Local lowest = 0 ' while land height is below 13 While lowest < 13 Local x1 = Rnd(mapwidth) Local y1 = Rnd(mapheight) ' create a radius for draw oval Local radius = Rnd(3,6) ' loop and create oval For Local y2=-radius To radius For Local x2=-radius To radius If ((x2*x2)+(y2*y2)) <= radius*radius+radius*0.8 Local x3 = x1+x2 Local y3 = y1+y2 If x3>=0 And y3>=0 And x3<mapwidth And y3<mapheight ' add current position with added older tile value map[x3][y3]=map[x3][y3]+1 ' if current value is higher then lowest loop value ' then store it in the loop exit variable If map[x3][y3] > lowest Then lowest = map[x3][y3] End If End If Next Next Wend 'Count the number of land tiles numland=0 For Local y=0 Until mapheight For Local x=0 Until mapwidth ' if the value is above 4 then add landtile counter If map[x][y] >= 5 Then numland+=1 Next Next Wend End Function Function drawmap:Void() For Local y=0 Until screenheight/tileheight For Local x=0 Until screenwidth/tilewidth Local val:Int=map[x+mapx][y+mapy] ' tile 1,2,3,4 is sea If val<5 Then SetColor 0,0,val*10+100 ' tile 5 6 7 8 is grasslands/trees If val>=5 And val <9 Then SetColor 0,val*15,0 'tiles 9 10 11 12 13 is mountains If val>=9 Then SetColor val*15,val*4,0 ' draw the tile DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight Next Next End Function Function argb:Int(r:Int, g:Int, b:Int ,alpha:Int=255) Return (alpha Shl 24) | (r Shl 16) | (g Shl 8) | b End Function Function drawboxedrect:Void(x:Int,y:Int,w:Int,h:Int) DrawLine x,y,x+w,y DrawLine x,y,x,y+h DrawLine x,y+h,x+w,y+h DrawLine x+w,y,x+w,y+h End Function Function Main() New MyGame() End Function
I made a simple shooter. The ai follows/homes towards the player. on a random point he moves away and then when he if far enough he return into the follow state. The ai can not shoot. You can shoot. The ai can take 4 hits before they are removed from the list.
Import mojo Class _ai Field x:Float Field y:Float Field angle:Int Field speed:Float=2 Field destinationangle:Int Field dist:Int Field state:String="follow" Field hitpoints:Int=4 Method New(_x:Float,_y:Float,_angle:Int) x = _x y = _y angle=_angle End Method Method update() dist = distance(x,y,p.x,p.y) Select state Case "follow" x+=Cos(angle)*speed y+=Sin(angle)*speed destinationangle = getangle(p.x,p.y,x,y) If dist>50 Then 'turn towards player If leftangle(angle,destinationangle) = True Then angle+=3 Else angle-=3 If angle>180 Then angle=-180 If angle<-180 Then angle=180 End If If Rnd(100) < 2 Then state="evade" Case "evade" destinationangle = getangle(x,y,p.x,p.y) If leftangle(angle,destinationangle) = True Then angle+=3 Else angle-=3 If angle>180 Then angle=-180 If angle<-180 Then angle=180 x+=Cos(angle)*speed y+=Sin(angle)*speed If dist > 250 Then state="follow" End Select End Method Method draw() SetColor 255,0,0 DrawOval x,y,10,10 End Method End Class Class playerlaser Field x:Float Field y:Float Field angle:Int Field speed:Float=4 Field delete:Bool=False Method New(_x:Float,_y:Float,_angle:Int) x = _x y = _y angle=_angle End Method Method update() x+=Cos(angle)*speed y+=Sin(angle)*speed If x<-100 Then delete=True If x>DeviceWidth()+100 Then delete = True If y<-100 Then delete = True If y>DeviceHeight+100 Then delete = True ' laser ai collision For Local i:=Eachin ai If rectsoverlap(i.x,i.y,10,10,x,y,10,10) = True delete = True i.hitpoints-=1 If i.hitpoints=0 Then ai.Remove(i) End If Next ' For Local i:=Eachin pl If i.delete = True Then pl.Remove(i) Next End Method Method draw() SetColor 255,255,0 DrawOval x,y,3,3 End Method End Class Class player Field angle:Int Field x:Float = 100 Field y:Float = 100 Field mx:Float = 2 'movement speed x Field my:Float = 2 'movement speed y Method update() ' player controls If KeyHit(KEY_SPACE) pl.AddLast(New playerlaser(x,y,angle)) End If x+=Cos(angle)*mx y+=Sin(angle)*my Local destinationangle = getangle(MouseX(),MouseY(),x,y) If leftangle(angle,destinationangle) = True Then angle+=3 Else angle-=3 If angle>180 Then angle=-180 If angle<-180 Then angle=180 End Method Method draw() SetColor 255,255,255 DrawOval x,y,10,10 End Method End Class Global p:player = New player Global pl:List<playerlaser> = New List<playerlaser> Global ai:List<_ai> = New List<_ai> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) ai.AddLast(New _ai(-100,100,0)) ai.AddLast(New _ai(-100,200,0)) ai.AddLast(New _ai(-100,300,0)) ai.AddLast(New _ai(-100,400,0)) End Method Method OnUpdate() p.update For Local i:=Eachin pl i.update Next For Local i:=Eachin ai i.update Next End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 For Local i:=Eachin ai i.draw Next For Local i:=Eachin pl i.draw Next p.draw SetColor 255,255,255 DrawText "Player (white) moves towards mouse, space = shoot",0,0 End Method End Class Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1) + Abs(y2-y1) End Function Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return ATan2(y1-y2, x1-x2) End Function Function leftangle:Bool(_angle:Int,_destinationangle:Int) Local cnt1 = 0 Local a1 = _angle While a1<>_destinationangle a1+=1 If a1>180 Then a1=-180 cnt1+=1 Wend If cnt1<180 Then Return True Else Return False End Function Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int) If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False Return True End Function Main() New MyGame() End Function
Here is code that shows how to make a player move towards the mouse. Not directly but it will slowly turn towards the destination angle. It checks which direction is closest. This method is nice for homing missiles and such and space ship thrust movement.
I was able to shorten the code for the turning. Now I only have one loop to count up to the closest turn.
I hope to create a space shooter with some smart ai and turrets this morning and post it online. Hope I can get it working.
Import mojo Class player Field angle:Int Field x:Float = 100 Field y:Float = 100 Field mx:Float = 2 'movement speed x Field my:Float = 2 'movement speed y Method update() ' here we move the player with the current angle x+=Cos(angle)*mx y+=Sin(angle)*my 'get the real angle between the mouse and player Local destinationangle = getangle(MouseX(),MouseY(),x,y) ' cnt1 is used to see which direction is closer towards the destination angle Local cnt1 = 0 ' put the angle value in a1 Local a1 = angle ' we exit the loop if the a1 value is the destination angle While a1<>destinationangle 'increase the a1 value a1+=1 ' valid angles range from -180 to 180 If a1>180 Then a1=-180 'increase the cnt1 counter with one cnt1+=1 Wend ' if going left is shorter If cnt1<180 Then angle+=3 Else angle-=3 ' Keep the angle in the valid angle range If angle>180 Then angle=-180 If angle<-180 Then angle=180 End Method Method draw() SetColor 255,255,255 DrawOval x,y,10,10 End Method End Class Global p:player = New player Class MyGame Extends App Method OnCreate() SetUpdateRate(60) End Method Method OnUpdate() p.update End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 p.draw End Method End Class Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return ATan2(y1-y2, x1-x2) End Function Function Main() New MyGame() End Function
I still have problems with angles and cos and sin and atan2 and commands like that. Below here is a simple example of how to move a oval automatically towards te mouse.
Import mojo Global angle:Int=0 Global x1:Float=100 Global y1:Float=100 Class MyGame Extends App Method OnCreate() SetUpdateRate(60) End Method Method OnUpdate() angle = getangle(MouseX(),MouseY(),x1,y1) x1+=Cos(angle)*1 y1+=Sin(angle)*1 End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 DrawOval x1,y1,10,10 End Method End Class Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return ATan2(y1-y2, x1-x2) End Function Function Main() New MyGame() End Function
Here is a example where you have a sidescrolling map on which the player can move. There is simple ai and there are blocks that you can bump into. they dissapear. On the map in the code the 3 characters is the ai. The 2 character is the bump tiles. And the 1 characters is the solid blocks.
Import mojo ' The most left and most right tiles do not get drawn. Global map:Int[][] = [ [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1], [1,0,0,0,0,0,0,0,0,1,2,2,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,2,2,2,1,0,0,0,0,0,0,0,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,3,0,3,0,0,0,0,0,1,1,1,1,1,1], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]] Const mapwidth:Int=50 Const mapheight:Int=10 Const tilewidth:Int=32 Const tileheight:Int=32 ' Level array x location (left of the screen) Global mapx:Int = 0 ' Scrolling offset Global mapsx:Int = 0 Class baddie Field d:String = "left" Field x:Float Field y:Float Field w:Int=20 Field h:Int=12 Field isjumping:Bool=False Field incy:Float=0 Method update() If isjumping = True If incy < 5 Then incy+=.3 For Local i=0 Until incy If btc(x,y,0,1) = False y+=1 Else isjumping=False Exit End If Next End If Select d Case "left" For Local i = 0 Until 1 If x-1<0 Then d = "right" Exit End If If isjumping = False And btc(x,y,0,1) = False incy = 0 isjumping = True End If If btc(x,y,-1,0) = True d="right" Exit End If x-=1 Next Case "right" For Local i=0 Until 1 If x+w+1>mapwidth*tilewidth Then d="left" Exit End If If btc(x,y,1,0) = True d="left" Exit End If x+=1 Next End Select End Method Method New(_x:Float,_y:Float) x=_x y=_y End Method Method draw() SetColor 255,0,0 Local x1 = x-(mapx*tilewidth)+mapsx Local y1 = y+tileheight-h DrawRect x1,y1,w,h End Method End Class Class player Field x:Float=32*3 Field y:Float=32*3 Field w:Int=32 Field h:Int=32 Field incy:Float=0 Field isjumping:Bool=False Method update() If KeyDown(KEY_SPACE) If isjumping = False isjumping = True incy=-9 End If End If If KeyDown(KEY_RIGHT) For Local i=0 Until 5 If ptc(1,0) = False x+=1 Else Exit End If Next End If If KeyDown(KEY_LEFT) For Local i=0 Until 5 If ptc(-1,0) = False x-=1 Else Exit End If Next End If If isjumping = False If ptc(0,1) = False incy = 0 isjumping = True End If End If If isjumping = True If incy>=0 If incy<5 Then incy+=.3 For Local i=0 Until incy If ptc(0,1) = False y+=1 Else incy = 0 isjumping = False Exit End If Next End If If incy<0 incy+=.3 For Local i=0 Until Abs(incy) If ptc(0,-1) = False y-=1 Else If psc(0,-1) = True End If incy=0 Exit End If Next End If End If End Method Method draw() SetColor 255,255,0 DrawRect x,y,w,h SetColor 255,255,255 DrawText "P",x+w/2,y+h/2,0.5,0.5 End Method End Class Global b:List<baddie> = New List<baddie> Global p:player = New player Class MyGame Extends App Method OnCreate() SetUpdateRate(60) For Local y=0 Until mapheight For Local x=0 Until mapwidth If map[y][x] = 3 b.AddLast(New baddie(x*tilewidth,y*tileheight)) End If Next Next End Method Method OnUpdate() p.update For Local i:=Eachin b i.update Next alignmap End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 For Local y=0 Until 10 For Local x=0 Until 21 Local x1=x*tilewidth+mapsx-tilewidth Local y1 = y*tileheight Select map[y][x+mapx] Case 1 SetColor 255,255,255 DrawRect x1,y1,tilewidth,tileheight Case 2 SetColor 255,155,22 DrawRect x1,y1,tilewidth,tileheight SetColor 255,255,255 DrawText "B",x1+tilewidth/2,y1+tileheight/2,0.5,0.5 End Select Next Next For Local i:=Eachin b i.draw Next p.draw DrawText "Use cursor Left and Right and space to control player.",10,20 End End Function alignmap:Bool() For Local i=0 Until 5 If p.x > DeviceWidth / 2 If mapx+20 < mapwidth-1 mapsx-=1 If mapsx < 0 Then mapsx = 31 mapx += 1 Endif p.x-=1 End If End If Next For Local i=0 Until 5 If p.x < DeviceWidth / 2 If mapx > 0 mapsx+=1 If mapsx > 32 Then mapsx = 0 mapx -= 1 Endif p.x+=1 End If End If Next End Function 'player collide with special blocks true/false Function psc:Bool(offsetx:Int=0,offsety:Int=0) Local cx = (p.x+offsetx)/tilewidth+mapx Local cy = (p.y+offsety)/tileheight For Local y2=cy-1 Until cy+4 For Local x2=cx-1 Until cx+4 If x2>=0 And x2<mapwidth And y2>=0 And y2<mapheight If map[y2][x2] = 2 Local x3 = (x2-mapx)*tilewidth-32+mapsx Local y3 = y2*tileheight If rectsoverlap(p.x+offsetx,p.y+offsety,p.w,p.h,x3,y3,tilewidth,tileheight) = True map[y2][x2] = 1 Return True End If End If End If Next Next Return False End Function 'player collide with solid blocks true/false Function ptc:Bool(offsetx:Int=0,offsety:Int=0) Local cx = (p.x+offsetx)/tilewidth+mapx Local cy = (p.y+offsety)/tileheight For Local y2=cy-1 Until cy+4 For Local x2=cx-1 Until cx+4 If x2>=0 And x2<mapwidth And y2>=0 And y2<mapheight If map[y2][x2] = 1 Or map[y2][x2] = 2 Local x3 = (x2-mapx)*tilewidth-32+mapsx Local y3 = y2*tileheight If rectsoverlap(p.x+offsetx,p.y+offsety,p.w,p.h,x3,y3,tilewidth,tileheight) = True Return True End If End If End If Next Next Return False End Function 'baddie collide with solid blocks true/false Function btc:Bool(x1:Int,y1:Int,offsetx:Int=0,offsety:Int=0) Local cx = (x1+offsetx)/tilewidth Local cy = (y1+offsety)/tileheight For Local y2=cy-1 Until cy+4 For Local x2=cx-1 Until cx+4 If x2>=0 And x2<mapwidth And y2>=0 And y2<mapheight If map[y2][x2] = 1 Or map[y2][x2] = 2 Local x3 = (x2)*tilewidth-32 Local y3 = y2*tileheight If rectsoverlap(x1+offsetx,y1+offsety+tileheight-12,20,12,x3,y3,tilewidth,tileheight) = True Return True End If End If End If Next Next Return False End Function Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int) If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False Return True End Function Function Main() New MyGame() End