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.
Import mojo ' ' This is the tile class. ' Here a stone tile is created ' using the generate method Class tile Field width:Int,height:Int Field map:Int[][] Method New(w:Int,h:Int) Self.width = w Self.height = h map = New Int[width][] For Local i:Int=0 Until width map[i] = New Int[height] Next End Method Method generate(spacing:Int) ' Put a number of stone points on the map ' try to keep a distance between them Local numpoints:Int=Rnd(width/5,width/2) For Local i:Int=0 Until numpoints Local x:Int=Rnd(width) Local y:Int=Rnd(height) Local exitloop:Bool=False While exitloop=False exitloop = True If disttootherstone(x,y,i) < spacing x=Rnd(width) y=Rnd(height) exitloop=False End If Wend map[x][y] = i Next ' ' Grow the stone points For Local i:Int=0 Until (width*height)*10 Local x:Int=Rnd(width) Local y:Int=Rnd(height) If map[x][y] > 0 If disttootherstone(x,y,map[x][y]) < spacing Then Continue For Local y2:Int=y-1 To y+1 For Local x2:Int=x-1 To x+1 If x2<0 Or y2<0 Or x2>=width Or y2>=height Then Continue If Rnd(5)<2 Then If map[x2][y2] = 0 If x2 = 0 Then map[width-1][y2] = map[x][y] If x2 = width-1 Then map[0][y2] = map[x][y] If y2 = 0 Then map[x2][height-1] = map[x][y] If y2 = height-1 Then map[x2][0] = map[x][y] map[x2][y2] = map[x][y] End If End If Next Next End If Next shadeedges() End Method ' Add ligther and darker pixels ontop of the stones ' value 1 to <100 is each seperate stone ' value 200 is light color 100 is dark color Method shadeedges() For Local y:Int=0 Until height For Local x:Int=0 Until width If map[x][y] > 0 And map[x][y] <> 200 If x-1 >=0 And map[x-1][y] = 0 For Local x2:Int=x+2 To x+4 If Rnd(2)<1 If x2>=0 And x2<width And map[x2][y] >0 Then map[x2][y] = 100 End If Next End If If x-1 >=0 And y-1>=0 And map[x-1][y-1] = 0 map[x][y] = 100 End If If x+1 < width And map[x+1][y] = 0 For Local x2:Int=x-4 To x+2 If Rnd(2)<1 If x2>=0 And x2<width And map[x2][y] >0 Then map[x2][y] = 200 End If Next End If End If Next Next End Method ' Returns the shortest distance to any other stone part then ' the currentstore Method disttootherstone:Int(sx:Int,sy:Int,currentstone:Int) Local shortest:Int=9999 For Local y:Int=0 Until height For Local x:Int=0 Until width If map[x][y] <> 0 And map[x][y] <> currentstone Local d:Int=distance(sx,sy,x,y) If d<shortest Then shortest = d End If Next Next Return shortest End Method ' Draw the tile at x and y position and tw=size Method draw(sx:Int,sy:Int,tw:Int,th:Int) Local x:Int Local y:Int For y=0 Until height For x=0 Until width Local t:Int=map[x][y] Local x2:Int=x*tw Local y2:Int=y*th x2+=sx y2+=sy If t >= 1 Then 'grey base color SetColor 100,100,100 End If If t=100 Then SetColor 40,40,40 'dark shade color If t=200 Then SetColor 140,140,140 'light shade color If t>0 ' draw a rect (part of the stone) DrawRect x2,y2,tw,th End If Next Next End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Class MyGame Extends App Field mytile:tile Field cnt:Int=0 Method OnCreate() Seed = GetDate[4]*GetDate[5] SetUpdateRate(1) mytile = New tile(32,32) mytile.generate(6) End Method Method OnUpdate() cnt+=1 If KeyHit(KEY_SPACE) Or cnt>3 cnt = 0 mytile = New tile(32,32) 'reset/create new tile Local spacing:Int=Rnd(4,10) ' set random spacing If Rnd(3)<1 Then spacing=4 mytile.generate(spacing) ' generate the tile End If End Method Method OnRender() Cls 0,0,0 'draw the tiles in 4x the size For Local y:Int=0 Until DeviceHeight Step 32*4 For Local x:Int=0 Until DeviceWidth Step 32*4 mytile.draw(x,y,4,4) Next Next ' draw the tiles in 1x size SetColor 0,0,0 DrawRect 320,240,320,240 For Local y:Int=240 Until DeviceHeight Step 32 For Local x:Int=320 Until DeviceWidth Step 32 mytile.draw(x,y,1,1) Next Next End Method End Class Function Main() New MyGame() End Function
Import mojo Class tile Field width:Int,height:Int Field map:Int[][] Method New(w:Int,h:Int) Self.width = w Self.height = h map = New Int[width][] For Local i:Int=0 Until width map[i] = New Int[height] Next End Method ' Here we create the flasks or bottles ' or what else. Method generate() 'make right side ' from the center top to center bottom Local x:Float=width/2 Local y:Float=0 Local angle:Int=0 While y<=height For Local i:Int=0 Until 20 x+=Cos(angle)*.5 y+=Sin(angle)*.5 If x>=width Then x-=1 If x<0 Or y<0 Or x>=width Or y>=height Then Exit map[x][y] = 1 ' create border point fillleftside(x-1,y) ' fill left side Next angle=Rnd(0,120) Wend If y>height Then y=height-1 For Local x1:Int=x Until width/2-1 Step -1 map[x1][y] = 1 Next 'make left side (mirror right side) For y = 0 Until height For x = width/2 Until width map[width-x][y] = map[x][y] Next Next Return End Method ' here we put the value of ' 2 inside the map from inputted ' coords to most left position Method fillleftside(fx:Int,fy:Int) For Local x:Int=fx Until 0 Step -1 map[x][fy] = 2 Next End Method Method draw(sx:Int,sy:Int,ar:Int,ag:Int,ab:Int) Local c:Int Local g:Int Local b:Int Local lightpointx:Int=Rnd(5,width-5) For Local y:Int=0 Until height For Local x:Int=0 Until width If map[x][y] = 0 Then c=0+((ag/height)*y) g=0+((ab/height)*y) b=0+((ar/height)*y) If c>255 Then c=255 If g>255 Then g=255 If b>255 Then b=255 If c<0 Then c=0 If g<0 Then g=0 If b<0 Then b=0 SetColor c,g,b DrawRect sx+x,sy+y,1,1 Continue End If ' here we draw the border ' and the red (rainbowish color) Select map[x][y] Case 1'border c = 255-((255/height)*y) If x>width/2 Then c/=2 SetColor c,c,c Case 2 c = ar-((ar/height)*y) g = ag-((ag/height)*y) b = ab-((ab/height)*y) c=-distance(lightpointx,0,x,0)+c g=-distance(lightpointx,0,x,0)+g b=-distance(lightpointx,0,x,0)+b If c>255 Then c=255 If g>255 Then g=255 If b>255 Then b=255 If c<0 Then c=0 If g<0 Then g=0 If b<0 Then b=0 SetColor c,g,b End Select DrawRect sx+x,sy+y,1,1 Next Next End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Class MyGame Extends App Field mytile:tile Method OnCreate() Seed = GetDate[4]*GetDate[5] SetUpdateRate(1) End Method Method OnUpdate() End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 For Local y:Int=0 Until DeviceHeight Step 55 For Local x:Int=0 Until DeviceWidth Step 55 mytile = New tile(48,48) mytile.generate() mytile.draw(x,y,Rnd(24,255),Rnd(24,255),Rnd(24,255)) Next Next End Method End Class Function Main() New MyGame() End Function
' Create a map with lines. ' It works by randomly selecting a point on the map ' and the drawing into a random direction. We stop ' drawing if we are close to a previously drawn line. ' Import mojo Class map Field screenwidth:Int Field screenheight:Int Field mapwidth:Int Field mapheight:Int Field tilewidth:Float Field tileheight:Float Field map:Int[][] Method New(sw:Int,sh:Int,mw:Int,mh:Int) Self.screenwidth = sw Self.screenheight = sh Self.mapwidth = mw Self.mapheight = mh Self.tilewidth = Float(sw) / Float(mw) Self.tileheight = Float(sh) / Float(mh) map = New int[mapwidth][] For Local i:Int=0 Until mapwidth map[i] = New Int[mapheight] Next createmap() End Method Method createmap() ' Loop a number of times For Local i:Int=0 Until (mapwidth+mapheight) ' Get a random x and y spot on the map Local x:Float=Rnd(mapwidth) Local y:Float=Rnd(mapheight) ' Chose an angle Local angle:Int=Rnd(360) ' We will draw d into angle it's direction Local d:Int=Rnd(3,35) Local xitloop:Bool=False ' We change the angle and distance 3 times For Local iii:Int=0 Until 3 ' Loop the distance For Local ii:Int=0 Until d ' If spot taken with 1 or out of screen ' then exit the loop If maptaken(x-4,y-4,8,8) Then xitloop=True ; Exit ' Put value 2 into the map map[x][y] = 2 ' Next x and y position x+=Cos(angle)*1 y+=Sin(angle)*1 Next ' Exit the loop(spot taken) If xitloop=True Then Exit ' Change angle and distance angle+=Rnd(-90,90) d=Rnd(3,35) Next ' Turn all new drawn 2 value's into ' value of 1 For Local y:Int=0 Until mapheight For Local x:Int=0 Until mapwidth If map[x][y] = 2 Then map[x][y] = 1 Next Next Next End Method ' See if the area selected is outside the ' screen or if the map value is 1 Method maptaken:Bool(x:Int,y:Int,w:Int,h:Int) For Local y2:Int=y Until y+h For Local x2:Int=x Until x+w If x2<0 Or x2>=mapwidth Or y2<0 Or y2>=mapheight Then Return True If map[x2][y2] = 1 Then Return True Next Next Return False End Method ' Draw the map Method draw() For Local y:Int=0 Until mapheight For Local x:Int=0 Until mapwidth If map[x][y] = 0 Then Continue SetColor 255,255,255 Local x2:Int=x*tilewidth Local y2:Int=y*tileheight DrawRect x2,y2,tilewidth+1,tileheight+1 Next Next End Method End Class Class MyGame Extends App Field mymap:map Field cnt:Int=0 Method OnCreate() Seed = GetDate[4] * GetDate[5] SetUpdateRate(1) createrandommap() End Method Method OnUpdate() cnt+=1 If KeyHit(KEY_SPACE) Or cnt > 1 cnt=0 createrandommap() End If End Method Method OnRender() Cls 0,0,0 ' Draw the map mymap.draw() SetColor 255,255,255 Local mw:Int=mymap.mapwidth Local mh:Int=mymap.mapheight DrawText "Width : "+mw+" Height : "+mh,0,0 End Method Method createrandommap() Local size:Int=Rnd(20,200) mymap = New map(DeviceWidth,DeviceHeight,size,size) End Method End Class Function Main() New MyGame() End Function
'Is this the breath first search? Not to familiar with it. Import mojo Class search Field screenwidth:Int,screenheight:Int Field mapwidth:Int,mapheight:Int Field tilewidth:Float,tileheight:Float Field sx:Int,sy:Int Field ex:Int,ey:Int Field map:Int[][] Field myopenlist:List<node> Field myclosedlist:List<node> Field mypath:List<path> Field mx:Int[]=[0,-1,1,0] Field my:Int[]=[-1,0,0,1] Method New(screenwidth:Int,screenheight:Int,mapwidth:Int,mapheight:Int) Self.screenwidth = screenwidth Self.screenheight = screenheight Self.mapwidth = mapwidth Self.mapheight = mapheight Self.tilewidth = Float(screenwidth) / Float(mapwidth) Self.tileheight = Float(screenheight) / Float(mapheight) map = New Int[mapwidth][] For Local i:Int=0 Until mapwidth map[i] = New Int[mapheight] Next makemap() End Method Method makemap:Void() For Local i:Int=0 Until mapwidth/3 Local x1:Float=Rnd(0,mapwidth) Local y1:Float=Rnd(0,mapheight) Local angle:Int=Rnd(360) Local dist:Int=Rnd(3,7) For Local ii:Int=0 Until dist x1+=Cos(angle)*1 y1+=Sin(angle)*1 If x1<0 Or y1<0 Or x1>=mapwidth Or y1>=mapheight Then Exit map[x1][y1] = 1 Next Next End Method Method search:Bool(sx:Int,sy:Int,ex:Int,ey:Int) If sx=ex And sy=ey Then Return False If map[sx][sy] <> 0 Or map[ex][ey] <> 0 Then Return False Self.sx = sx Self.sy = sy Self.ex = ex Self.ey = ey myopenlist = New List<node> myclosedlist = New List<node> mypath = New List<path> myopenlist.AddFirst(New node(sx,sy,sx,sy)) ' the search While Not myopenlist.IsEmpty Local cx:Int=myopenlist.First.x Local cy:Int=myopenlist.First.y Local px:Int=myopenlist.First.parentx Local py:Int=myopenlist.First.parenty myclosedlist.AddFirst(New node(cx,cy,px,py)) If cx = ex And cy = ey Then findpathback() Return True End If myopenlist.RemoveFirst() For Local i:Int=0 Until mx.Length Local nx:Int=cx+mx[i] Local ny:Int=cy+my[i] If nx<0 Or ny<0 Or nx>=mapwidth Or ny>=mapheight Then Continue If map[nx][ny] = 0 'if the map is not obstructed If isonclosedlist(nx,ny) = False And isonopenlist(nx,ny) = False myopenlist.AddLast(New node(nx,ny,cx,cy)) End If End If Next Wend Return False End Method ' Here we calculate back from the end back to the ' start and create the path list. Method findpathback:Bool() Local x:Int=ex Local y:Int=ey mypath.AddFirst(New path(x,y)) Repeat For Local i:=Eachin myclosedlist If i.x = x And i.y = y x = i.parentx y = i.parenty mypath.AddFirst(New path(x,y)) End If Next If x = sx And y = sy Then Return True Forever End Method Method drawpath() If Not mypath Then Return For Local i:=Eachin mypath SetColor 255,0,0 DrawOval i.x*tilewidth+(tilewidth/4),i.y*tileheight,tilewidth/4,tileheight/2 Next End Method Method drawclosedlist() If Not myclosedlist Then Return For Local i:=Eachin myclosedlist DrawText "loc:"+i.x+","+i.y, i.x*tilewidth,i.y*tileheight+15 DrawText "par:"+i.parentx+","+i.parenty, i.x*tilewidth,i.y*tileheight+30 Next End Method Method isonopenlist:Bool(x:Int,y:Int) For Local i:=Eachin myopenlist If x = i.x And y = i.y Then Return True End If Next Return False End Method Method isonclosedlist:Bool(x:Int,y:Int) For Local i:=Eachin myclosedlist If x = i.x And y = i.y Then Return True End If Next Return False End Method Method draw() SetColor 255,255,255 For Local y:Int = 0 Until mapheight For Local x:Int = 0 Until mapheight If map[x][y] = 1 SetColor 155,155,155 DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight End If If sx = x And sy = y SetColor 255,0,0 DrawOval x*tilewidth+10,y*tileheight,10,10 End If If ex = x And ey = y SetColor 255,255,0 DrawOval x*tilewidth+10,y*tileheight,10,10 End If Next Next End Method End Class Class node Field x:Int Field y:Int Field parentx:Int Field parenty:Int Method New(x:Int,y:Int,parentx:Int,parenty:Int) Self.x = x Self.y = y Self.parentx = parentx Self.parenty = parenty End Method End Class Class path Field x:Int Field y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Class MyGame Extends App Field pathfound:Bool=False Field mysearch:search Field cnt:Int=0 Method OnCreate() Seed = GetDate[5] * GetDate[4] SetUpdateRate(10) mysearch = New search(DeviceWidth,DeviceHeight,10,10) pathfound = mysearch.search(2,2,6,6) End Method Method OnUpdate() cnt+=1 If KeyHit(KEY_SPACE) Or cnt>15 pathfound=False cnt=0 Local w:Int=Rnd(10,50) mysearch = New search(DeviceWidth,DeviceHeight,w,w) pathfound = mysearch.search(Rnd(w),Rnd(w),Rnd(w),Rnd(w)) End If End Method Method OnRender() Cls 0,0,0 mysearch.drawclosedlist mysearch.draw mysearch.drawpath SetColor 255,255,255 If pathfound DrawText "Path Found",0,0 End If End Method End Class Function Main() New MyGame() End Function
Import mojo Class enemy Field x:Int,y:Int Field w:Int,h:Int Field state:String Field deleteme:Bool Field cooldown:Int Field waittime:Int Field path:List<pathnode> = New List<pathnode> Method New() w = mymap.tilewidth-4 h = mymap.tileheight-4 findstartpos() End Method Method update() ' enemy shoot diagnal If Rnd(100)<2 Then Local px:Int=myplayer.x Local py:Int=myplayer.y If distance(px,py,x,y) < 200 If px<x And py<y And mymap.mapcollide(x-5,y-5,w/3,h/3) = False mybullet.AddLast(New bullet(x,y,"leftup","enemy")) End If If px>x And py<y And mymap.mapcollide(x+5,y-5,w/3,h/3) = False mybullet.AddLast(New bullet(x,y,"rightup","enemy")) End If If px<x And py>y And mymap.mapcollide(x-5,y+5,w/3,h/3) = False mybullet.AddLast(New bullet(x,y,"leftdown","enemy")) End If If px>x And py>y And mymap.mapcollide(x+5,y+5,w/3,h/3) = False mybullet.AddLast(New bullet(x,y,"rightdown","enemy")) End If End If End If 'enemy shoot horizontal vertical If Rnd(100)<2 Then Local px:Int=myplayer.x Local py:Int=myplayer.y If distance(px,py,x,y) < 200 If px<x And mymap.mapcollide(x-5,y,w/3,h/3) = False mybullet.AddLast(New bullet(x,y,"left","enemy")) End If If px>x And mymap.mapcollide(x+5,y-5,w/3,h/3) = False mybullet.AddLast(New bullet(x,y,"right","enemy")) End If If py>y And mymap.mapcollide(x,y+5,w/3,h/3) = False mybullet.AddLast(New bullet(x,y,"down","enemy")) End If If py<y And mymap.mapcollide(x,y-5,w/3,h/3) = False mybullet.AddLast(New bullet(x,y,"up","enemy")) End If End If End If ' move around the enemy If path.IsEmpty = False ' add 2 to the destination coords or gets stuck Local dx:Int=path.First.x*mymap.tilewidth+2 Local dy:Int=path.First.y*mymap.tileheight+2 If x<dx And mymap.mapcollide(x+1,y,w,h) = False Then x+=1 If x>dx And mymap.mapcollide(x-1,y,w,h) = False Then x-=1 If y<dy And mymap.mapcollide(x,y+1,w,h) = False Then y+=1 If y>dy And mymap.mapcollide(x,y-1,w,h) = False Then y-=1 'if near destination If distance(x,y,dx,dy) < 2 Then path.RemoveFirst x = dx y = dy End If End If 'if no more moves left find new cover spot If path.IsEmpty If waittime>0 Then waittime-=1 If waittime<=0 For Local i:Int=0 Until 100 Local dx:Int=Rnd(2,mymap.mapwidth-2) Local dy:Int=Rnd(2,mymap.mapheight-2) If mymap.covermap[dx][dy] = 1 Then createpath(dx,dy) waittime=200 Exit End If Next End If End If 'if player is nearby then move to closest cover spot If distance(myplayer.x,myplayer.y,x,y) < 160 If cooldown>0 Then cooldown-=1 If cooldown=0 cooldown=100 Local d:Int=10000 Local destx:Int,desty:Int Local fnd:Bool=False ' random spots until coverspot, log closest For Local i:Int=0 Until 250 Local dx:Int=Rnd(2,mymap.mapwidth-2) Local dy:Int=Rnd(2,mymap.mapheight-2) If mymap.covermap[dx][dy] = 1 Then Local d2:Int = distance(dx,dy,x/mymap.tilewidth,y/mymap.tileheight) If d2 < d Then d = d2 destx = dx desty = dy fnd=True End If End If Next ' if we have a new dest then plan it If fnd=True Then createpath(destx,desty) End If End If End Method Method createpath(ex:Int,ey:Int) path = New List<pathnode> Local dx:Int=x/mymap.tilewidth Local dy:Int=y/mymap.tileheight ' x = dx*mymap.tilewidth ' y = dy*mymap.tileheight myastar.findpath(dx,dy,ex,ey) For Local i:=Eachin myastar.path path.AddLast(New pathnode(i.x,i.y)) Next End Method Method drawpath() SetColor 255,0,0 For Local i:=Eachin path DrawOval i.x*mymap.tilewidth,i.y*mymap.tileheight,w/2,h/2 Next End Method Method findstartpos() Local cnt:Int=400 Local cnt2:Int=0 Repeat Local nx:Int=Rnd(0,mymap.screenwidth-20) Local ny:Int=Rnd(0,mymap.screenheight-20) Local found:Bool=True ' if the map position a tile If mymap.mapcollide(nx,ny,w,h) Then found = False ' if the position is to close other enemy For Local i:=Eachin myenemy If i=Self Then Continue If distance(i.x,i.y,nx,ny) < 30 Then found = False ;Exit Next ' if the position to close to player If distance(myplayer.x,myplayer.y,nx,ny) < cnt Then found = False If found = True Then x = nx y = ny Exit Else If cnt>32 Then cnt -=1 End If Forever End Method Method draw() SetColor 255,0,255 DrawOval x,y,w,h End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Class bullet Field x:Float,y:Float Field w:Int,h:Int Field mx:Int,my:Int Field direction:String Field deleteme:Bool=False Field speed:Int=2 Field shooter:String Method New(x:Int,y:Int,direction:String,shooter:String) Self.x = x Self.y = y Self.w = myplayer.w/3 Self.h = myplayer.h/3 Self.shooter = shooter Self.direction = direction If direction = "left" Then mx = -1 If direction = "right" Then mx = 1 If direction = "up" Then my = -1 If direction = "down" Then my = 1 If direction = "leftup" Then mx = -1 ; my = -1 If direction = "rightup" Then mx = 1 ; my = -1 If direction = "leftdown" Then mx = -1 ; my = 1 If direction = "rightdown" Then mx = 1 ; my = 1 End Method Method update() 'move the bullet and see collision with walls For Local i:Int=0 Until speed x += mx y += my If x < 0 Or x > mymap.screenwidth Then deleteme = True If y < 0 Or y > mymap.screenheight Then deleteme = True If mymap.mapcollide(x,y,w,h) Then deleteme = True Next ' collision with bullet vs enemy ' delete bullet and delete enemy If shooter = "player" For Local i:=Eachin myenemy If distance(i.x+(i.w/2),i.y+(i.h/2),x,y)<myplayer.w/1.5 Then deleteme = True i.deleteme = True End If Next End If ' collision with bullet vs player ' delete bullet and kill player If shooter = "enemy" If distance(myplayer.x+(myplayer.w/2),myplayer.y+(myplayer.h/2),x,y)<myplayer.w/1.5 Then deleteme = True myplayer.died = True End If End If End Method Method draw() SetColor 255,255,0 DrawOval x,y,w,h End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Class player Field x:Float,y:Float Field w:Int,h:Int Field direction:String="up" Field died:Bool=False Method New() w = mymap.tilewidth-4 h = mymap.tileheight-4 findstartingpos() End Method Method update() playercontrols() makecovermap() End Method Method playercontrols() ' movement If KeyDown(KEY_UP) And Not mymap.mapcollide(x,y-1,w,h) y-=1 direction = "up" End If If KeyDown(KEY_LEFT) And Not mymap.mapcollide(x-1,y,w,h) x-=1 direction = "left" End If If KeyDown(KEY_RIGHT) And Not mymap.mapcollide(x+1,y,w,h) x+=1 direction = "right" End If If KeyDown(KEY_DOWN) And Not mymap.mapcollide(x,y+1,w,h) y+=1 direction = "down" End If If KeyDown(KEY_LEFT) And KeyDown(KEY_UP) Then direction = "leftup" If KeyDown(KEY_RIGHT) And KeyDown(KEY_UP) Then direction = "rightup" If KeyDown(KEY_LEFT) And KeyDown(KEY_DOWN) Then direction = "leftdown" If KeyDown(KEY_RIGHT) And KeyDown(KEY_DOWN) Then direction = "rightdown" ' shooting If KeyHit(KEY_F) mybullet.AddLast(New bullet(x,y,direction,"player")) End If End Method Method makecovermap() If Rnd(60)>2 Then Return For Local y:Int=0 Until mymap.mapheight For Local x:Int=0 Until mymap.mapwidth mymap.covermap[x][y] = 1 If mymap.map[x][y] <> 0 Then mymap.covermap[x][y] = 2 Next Next ' shoot bullets into random directions around ' the player and see if any position is a cover position For Local i:Int=0 Until 600 Local x2:Float=x Local y2:Float=y Local xa:Float=Rnd(-1,1) Local ya:Float=Rnd(-1,1) For Local d:Int=0 Until 40 x2+=xa*Float(mymap.tilewidth/2) y2+=ya*Float(mymap.tileheight/2) Local mx:Int=x2/mymap.tilewidth Local my:Int=y2/mymap.tileheight If mx>=0 And my>=0 And mx<mymap.mapwidth And my<mymap.mapheight mymap.covermap[mx][my] = 0 Else Exit End If If mymap.mapcollide(x2,y2,w/3,h/3) Then Exit Next Next ' ' Remove every coverpoint except if they ' are near a wall. For Local y2:Int=0 Until mymap.mapheight For Local x2:Int=0 Until mymap.mapwidth Local remove:Bool=True For Local y3:Int=y2-1 To y2+1 For Local x3:Int=x2-1 To x2+1 If x3<0 Or y3<0 Or x3>=mymap.mapwidth Or y3>=mymap.mapheight Then Continue If mymap.map[x3][y3] <> 0 Then remove = False ; Exit Next Next If remove = True Then mymap.covermap[x2][y2] = 0 End If Next Next 'if closer to the player then higher movement cost per tile For Local y2:Int=0 Until mymap.mapheight For Local x2:Int=0 Until mymap.mapwidth If myastar.map[x2][y2] <> 1000 Then myastar.map[x2][y2] = 100-distance(myplayer.x/mymap.tilewidth,myplayer.y/mymap.tileheight,x2,y2) If myastar.map[x2][y2] < 85 Then myastar.map[x2][y2] = 0 If mymap.covermap[x2][y2] = 1 Then myastar.map[x2][y2] = 0 Next Next End Method Method findstartingpos() Repeat Local x1:Int = Rnd(0,mymap.mapwidth) Local y1:Int = Rnd(0,mymap.mapheight) Local istaken:Bool=False For Local x2:Int=x1-4 To x1+4 For Local y2:Int=y1-4 To y1+4 If x2<0 Or y2<0 Or x2>=mymap.mapwidth Or y2>=mymap.mapheight Then Continue If mymap.map[x2][y2] <> 0 Then istaken = True ; Exit Next Next If istaken=False Then x = x1*mymap.tilewidth y = y1*mymap.tileheight Exit End If Forever End Method Method draw() SetColor 255,255,255 DrawOval x,y,w,h End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Class astar Field mapwidth:Int,mapheight:Int Field sx:Int,sy:Int Field ex:Int,ey:Int Field olmap:Int[][] Field clmap:Int[][] Field map:Int[][] Field ol:List<openlist> = New List<openlist> Field cl:List<closedlist> = New List<closedlist> Field path:List<pathnode> = New List<pathnode> Field xstep:Int[] = [0,-1,1,0] Field ystep:Int[] = [-1,0,0,1] Method New() mapwidth = mymap.mapwidth mapheight = mymap.mapheight olmap = New Int[mapwidth][] clmap = New Int[mapwidth][] map = New Int[mapwidth][] For Local i:Int=0 Until mapwidth olmap[i] = New Int[mapheight] clmap[i] = New Int[mapheight] map[i] = New Int[mapheight] Next ' Copy the map into the astar class map For Local y:=0 Until mapheight For Local x:=0 Until mapwidth map[x][y] = mymap.map[x][y] Next Next End Method ' This creates the map and copies the ' path in the path list Method findpath:Bool(sx:Int,sy:Int,ex:Int,ey:Int) If sx = ex And sy = ey Then Return False Self.sx = sx Self.sy = sy Self.ex = ex Self.ey = ey For Local y=0 Until mapheight For Local x=0 Until mapwidth olmap[x][y] = 0 clmap[x][y] = 0 Next Next ol.Clear cl.Clear path.Clear ol.AddFirst(New openlist(sx,sy)) Local tx:Int Local ty:Int Local tf:Int Local tg:Int Local th:Int Local tpx:Int Local tpy:Int Local newx:Int Local newy:Int Local lowestf:Int olmap[sx][sy] = 1 While ol.IsEmpty() = False lowestf = 100000 For Local i:=Eachin ol If i.f < lowestf lowestf = i.f tx = i.x ty = i.y tf = i.f tg = i.g th = i.h tpx = i.px tpy = i.py End If Next If tx = ex And ty = ey cl.AddLast(New closedlist(tx,ty,tpx,tpy)) findpathback Return True Else removefromopenlist(tx,ty) olmap[tx][ty] = 0 clmap[tx][ty] = 1 cl.AddLast(New closedlist(tx,ty,tpx,tpy)) For Local i:Int=0 Until xstep.Length Local x:Int=xstep[i] Local y:Int=ystep[i] newx = tx+x newy = ty+y If newx>=0 And newy>=0 And newx<mapwidth And newy<mapheight If olmap[newx][newy] = 0 If clmap[newx][newy] = 0 olmap[newx][newy] = 1 Local gg = map[newx][newy]+1 Local hh = distance(newx,newy,ex,ey) Local ff = gg+hh ol.AddLast(New openlist(newx,newy,ff,gg,hh,tx,ty)) End If End If End If Next End If Wend Return False End Method Method drawpath:Void() Local cnt:Int=1 For Local i:=Eachin path SetColor 255,255,0 DrawOval i.x*mymap.tilewidth,i.y*mymap.tileheight,4,4 SetColor 255,255,255 DrawText cnt,i.x*mymap.tilewidth,i.y*mymap.tileheight cnt+=1 Next End Method ' Here we calculate back from the end back to the ' start and create the path list. Method findpathback:Bool() Local x=ex Local y=ey path.AddFirst(New pathnode(x,y)) Repeat For Local i:=Eachin cl If i.x = x And i.y = y x = i.px y = i.py path.AddFirst(New pathnode(x,y)) End If Next If x = sx And y = sy Then Return True Forever End Method Method removefromopenlist:Void(x1:Int,y1:Int) For Local i:=Eachin ol If i.x = x1 And i.y = y1 ol.Remove i Exit End If Next End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Class map Field mapwidth:Int Field mapheight:Int Field screenwidth:Int Field screenheight:Int Field tilewidth:Float Field tileheight:Float Field map:Int[][] Field covermap:Int[][] Method New(screenwidth:Int,screenheight:Int,mapwidth:Int,mapheight:Int) Self.screenheight = screenheight Self.screenwidth = screenwidth Self.mapwidth = mapwidth Self.mapheight = mapheight tilewidth = Float(screenwidth) / Float(mapwidth) tileheight = Float(screenheight) / Float(mapheight) map = New Int[mapwidth][] covermap = New Int[mapwidth][] For Local i:Int=0 Until mapwidth map[i] = New Int[mapheight] covermap[i] = New Int[mapheight] Next makemap(10) End Method Method makemap:Void(numobstacles:Int) For Local y=0 Until mapheight For Local x=0 Until mapwidth map[x][y] = 0 Next Next ' Here we create short lines on the map ' and sometimes draw some random blocks near them. For Local i:Int=0 Until numobstacles Local x1:Int=Rnd(4,mapwidth-4) Local y1:Int=Rnd(4,mapheight-4) Local dist:Int=Rnd(3,5) Local angle:Int=Rnd(0,360) Local x2:Float=x1 Local y2:Float=y1 While dist >= 0 x2 += Cos(angle) * 1 y2 += Sin(angle) * 1 dist -= 1 If x2<0 Or y2<0 Or x2>=mapwidth Or y2>=mapheight Then continue map[x2][y2] = 1000 ' If Rnd(10) < 2 Then ' If x2>2 And x2<mymap.mapwidth-2 And y2>2 And y2<mymap.mapheight-2 Then ' map[x2+Rnd(-1,1)][y2+Rnd(-1,1)] = 10 ' end if ' End If Wend Next End Method Method mapcollide:Bool(x:Int,y:Int,w:Int,h:Int) Local lefttopx:Int =((x)/tilewidth) Local lefttopy:Int =((y)/tileheight) Local righttopx:Int =((x+w)/tilewidth) Local righttopy:Int =((y)/tileheight) Local leftbottomx:Int =((x)/tilewidth) Local leftbottomy:Int =((y+h)/tileheight) Local rightbottomx:Int =((x+w)/tilewidth) Local rightbottomy:Int =((y+h)/tileheight) If lefttopx < 0 Or lefttopx >= mapwidth Then Return True If lefttopy < 0 Or lefttopy >= mapheight Then Return True If righttopx < 0 Or righttopx >= mapwidth Then Return True If righttopy < 0 Or righttopy >= mapheight Then Return True If leftbottomx < 0 Or leftbottomx >= mapwidth Then Return True If leftbottomy < 0 Or leftbottomy >= mapheight Then Return True If rightbottomx < 0 Or rightbottomx >= mapwidth Then Return True If rightbottomy < 0 Or rightbottomy >= mapheight Then Return True If map[lefttopx][lefttopy] <> 0 Then Return True If map[righttopx][righttopy] <> 0 Then Return True If map[leftbottomx][leftbottomy] <> 0 Then Return True If map[rightbottomx][rightbottomy] <> 0 Then Return True Return False End Method Method drawmap:Void() For Local y=0 Until mapheight For Local x=0 Until mapwidth If map[x][y] = 1000 SetColor 255,255,255 DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight End If Next Next End Method Method drawcovermap:Void() For Local y=0 Until mapheight For Local x=0 Until mapwidth If covermap[x][y] = 1 SetColor 0,15,0 DrawOval x*mymap.tilewidth,y*mymap.tileheight,tilewidth,tileheight End If Next Next End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class ' The open list used by the astar Class openlist Field x:Int Field y:Int Field f:Int Field g:Int Field h:Int Field px:Int Field py:Int Method New( x:Int=0,y:Int=0,f:Int=0, g:Int=0,h:Int=0,px:Int=0,py:Int=0) Self.x=x Self.y=y Self.f=f Self.g=g Self.h=h Self.px=px Self.py=py End Method End Class ' The closed list used by the astar Class closedlist Field x:Int Field y:Int Field px:Int Field py:Int Method New(x:Int,y:Int,px:Int,py:Int) Self.x = x Self.y = y Self.px = px Self.py = py End Method End Class ' the pathnodes (x and y variables) ' used by the astar Class pathnode Field x:Int Field y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Global mymap:map Global myastar:astar Global myplayer:player Global mybullet:List<bullet> = New List<bullet> Global myenemy:List<enemy> = New List<enemy> Class MyGame Extends App Field playerwins:Int Field enemywins:Int Method OnCreate() Seed = GetDate[4] * GetDate[5] SetUpdateRate(60) ' Create a new map mymap = New map(DeviceWidth(),DeviceHeight(),30,30) myastar = New astar() myplayer = New player() For Local i:Int=0 Until 10 myenemy.AddLast(New enemy()) Next End Method Method OnUpdate() myplayer.update() For Local i:=Eachin myenemy i.update() Next For Local i:=Eachin myenemy If i.deleteme = True Then myenemy.Remove(i) Next For Local i:=Eachin mybullet i.update() Next For Local i:=Eachin mybullet If i.deleteme = True Then mybullet.Remove(i) Next ' if no more enemies then reset level If myenemy.IsEmpty Or myplayer.died Or KeyHit(KEY_TILDE) If myplayer.died Then enemywins+=1 If myenemy.IsEmpty Then playerwins+=1 mymap = New map(DeviceWidth(),DeviceHeight(),30,30) myastar = New astar() myenemy = New List<enemy> mybullet = New List<bullet> myplayer = New player() For Local i:Int=0 Until 10 myenemy.AddLast(New enemy()) Next End If End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 mymap.drawmap() mymap.drawcovermap() For Local i:=Eachin myenemy i.draw() Next For Local i:=Eachin mybullet i.draw() Next myplayer.draw() 'drawdebug SetColor 255,255,255 DrawText "AI - 'Taking Cover' Locations - Example.`(Tilde = new level)",0,DeviceHeight-15 DrawText "Controls - cursor u/d/l/r and F - fire",0,15 DrawText "Matches Player Wins : " + playerwins + " vs Enemy Wins : " + enemywins,DeviceWidth/2,0,.5,0 End Method End Class Function drawdebug() SetColor 255,255,255 For Local i:=Eachin myenemy i.drawpath() Next Return Scale(.7,.7) For Local y:Int=0 Until mymap.mapwidth For Local x:Int=0 Until mymap.mapheight DrawText myastar.map[x][y],(x*mymap.tilewidth)*1.4,(y*mymap.tileheight)*1.4 Next Next End Function Function Main() New MyGame() End Function
' New Object oriented version of my Astar Code. Import mojo Class astar Field mapwidth:Int,mapheight:Int Field sx:Int,sy:Int Field ex:Int,ey:Int Field olmap:Int[][] Field clmap:Int[][] Field map:Int[][] Field ol:List<openlist> = New List<openlist> Field cl:List<closedlist> = New List<closedlist> Field path:List<pathnode> = New List<pathnode> Method New() mapwidth = mymap.mapwidth mapheight = mymap.mapheight olmap = New Int[mapwidth][] clmap = New Int[mapwidth][] map = New Int[mapwidth][] For Local i:Int=0 Until mapwidth olmap[i] = New Int[mapheight] clmap[i] = New Int[mapheight] map[i] = New Int[mapheight] Next ' Copy the map into the astar class map For Local y:=0 Until mapheight For Local x:=0 Until mapwidth map[x][y] = mymap.map[x][y] Next Next End Method ' This creates the map and copies the ' path in the path list Method findpath:Bool(sx:Int,sy:Int,ex:Int,ey:Int) If sx = ex And sy = ey Then Return False Self.sx = sx Self.sy = sy Self.ex = ex Self.ey = ey For Local y=0 Until mapheight For Local x=0 Until mapwidth olmap[x][y] = 0 clmap[x][y] = 0 Next Next ol.Clear cl.Clear path.Clear ol.AddFirst(New openlist(sx,sy)) Local tx:Int Local ty:Int Local tf:Int Local tg:Int Local th:Int Local tpx:Int Local tpy:Int Local newx:Int Local newy:Int Local lowestf:Int olmap[sx][sy] = 1 While ol.IsEmpty() = False lowestf = 100000 For Local i:=Eachin ol If i.f < lowestf lowestf = i.f tx = i.x ty = i.y tf = i.f tg = i.g th = i.h tpx = i.px tpy = i.py End If Next If tx = ex And ty = ey cl.AddLast(New closedlist(tx,ty,tpx,tpy)) findpathback Return True Else removefromopenlist(tx,ty) olmap[tx][ty] = 0 clmap[tx][ty] = 1 cl.AddLast(New closedlist(tx,ty,tpx,tpy)) For Local y=-1 To 1 For Local x=-1 To 1 newx = tx+x newy = ty+y If newx>=0 And newy>=0 And newx<mapwidth And newy<mapheight If olmap[newx][newy] = 0 If clmap[newx][newy] = 0 olmap[newx][newy] = 1 Local gg = map[newx][newy]+1 Local hh = distance(newx,newy,ex,ey) Local ff = gg+hh ol.AddLast(New openlist(newx,newy,ff,gg,hh,tx,ty)) End If End If End If Next Next End If Wend Return False End Method Method drawpath:Void() Local cnt:Int=1 For Local i:=Eachin path SetColor 255,255,0 DrawOval i.x*mymap.tilewidth,i.y*mymap.tileheight,4,4 SetColor 255,255,255 DrawText cnt,i.x*mymap.tilewidth,i.y*mymap.tileheight cnt+=1 Next End Method ' Here we calculate back from the end back to the ' start and create the path list. Method findpathback:Bool() Local x=ex Local y=ey path.AddFirst(New pathnode(x,y)) Repeat For Local i:=Eachin cl If i.x = x And i.y = y x = i.px y = i.py path.AddFirst(New pathnode(x,y)) End If Next If x = sx And y = sy Then Return True Forever End Method Method removefromopenlist:Void(x1:Int,y1:Int) For Local i:=Eachin ol If i.x = x1 And i.y = y1 ol.Remove i Exit End If Next End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Class map Field mapwidth:Int Field mapheight:Int Field screenwidth:Int Field screenheight:Int Field tilewidth:Float Field tileheight:Float Field map:Int[][] Method New(screenwidth:Int,screenheight:Int,mapwidth:Int,mapheight:Int) Self.screenheight = screenheight Self.screenwidth = screenwidth Self.mapwidth = mapwidth Self.mapheight = mapheight tilewidth = Float(screenwidth) / Float(mapwidth) tileheight = Float(screenheight) / Float(mapheight) map = New Int[mapwidth][] For Local i:Int=0 Until mapwidth map[i] = New Int[mapheight] Next makemap() End Method Method makemap:Void() For Local y=0 Until mapheight For Local x=0 Until mapwidth map[x][y] = 0 Next Next Local lowest = 0 While lowest < 13 Local x1 = Rnd(mapwidth) Local y1 = Rnd(mapheight) Local radius = Rnd(3,6) 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 map[x3][y3]=map[x3][y3]+1 If map[x3][y3] > lowest Then lowest = map[x3][y3] End If End If Next Next Wend End Method Method drawmap:Void() For Local y=0 Until mapheight For Local x=0 Until mapwidth SetColor 0,map[x][y]*10,0 DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight Next Next End Method End Class ' The open list used by the astar Class openlist Field x:Int Field y:Int Field f:Int Field g:Int Field h:Int Field px:Int Field py:Int Method New( x:Int=0,y:Int=0,f:Int=0, g:Int=0,h:Int=0,px:Int=0,py:Int=0) Self.x=x Self.y=y Self.f=f Self.g=g Self.h=h Self.px=px Self.py=py End Method End Class ' The closed list used by the astar Class closedlist Field x:Int Field y:Int Field px:Int Field py:Int Method New(x:Int,y:Int,px:Int,py:Int) Self.x = x Self.y = y Self.px = px Self.py = py End Method End Class ' the pathnodes (x and y variables) ' used by the astar Class pathnode Field x:Int Field y:Int Method New(x:Int,y:Int) Self.x = x Self.y = y End Method End Class Global mymap:map Global myastar:astar Class MyGame Extends App Method OnCreate() SetUpdateRate(1) ' Create a new map mymap = New map(DeviceWidth(),DeviceHeight(),30,30) ' Initiate the astar. Here the map from the mymap ' is copied into. Recreate this everytime the map is ' modified.. ' the map from the mymap should contain the heights/terrain ' costs. A tile with a high value is less likely to be chosen. myastar = New astar() End Method Method OnUpdate() ' create 2 unique start and end coordinates Local exitloop:Bool=False Local sx:Int,sy:Int,ex:Int,ey:Int While exitloop = False sx = Rnd(mymap.mapwidth) sy = Rnd(mymap.mapheight) ex = Rnd(mymap.mapwidth) ey = Rnd(mymap.mapheight) If sx <> ex And sy <> ey exitloop = True End If Wend ' Find/create the path myastar.findpath(sx,sy,ex,ey) End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 mymap.drawmap() myastar.drawpath() SetColor 255,255,255 DrawText "a Star Pathfinding example",0,0 End Method End Class Function Main() New MyGame() End Function
'Based on the game Legend of Pandora.
Import mojo Global tilewidth:Int=10 Global tileheight:Int=10 Class map Field tilewidth:Float Field tileheight:Float Field mapwidth:Int Field mapheight:Int Field screenwidth:Int Field screenheight:Int Field map:Int[][] Method New( screenwidth:Int, screenheight:Int, mapwidth:Int, mapheight:Int) Self.screenwidth = screenwidth Self.screenheight = screenheight Self.mapwidth = mapwidth Self.mapheight = mapheight Self.tilewidth = Float(screenwidth)/Float(mapwidth) Self.tileheight = Float(screenheight)/Float(mapheight) map = New Int[mapwidth][] For Local i=0 Until mapwidth map[i] = New Int[mapheight] Next map[mapwidth/2][mapheight/2] = 3 ' 3 is a door makemap End Method Method makemap() Local timeout:Int While timeout<(mapwidth*mapheight)*20 timeout+=1 Local x:Int=Rnd(11,mapwidth-11) Local y:Int=Rnd(11,mapheight-11) If map[x][y] = 3 makeroom(x,y) End If Wend 'here we turn doors into walls 'if they should be walls For Local y1=1 Until mapheight-1 For Local x1=1 Until mapwidth-1 If map[x1][y1] = 3 Local cnt:Int=0 For Local y2=y1-1 To y1+1 For Local x2=x1-1 To x1+1 If map[x2][y2] = 2 Then cnt+=1 Next Next If cnt>3 Then map[x1][y1] = 2 End If Next Next 'here we turn doors into walls if they ' touch tiles that are nothing (0) For Local y1=1 Until mapheight-1 For Local x1=1 Until mapwidth-1 If map[x1][y1] = 3 Local cnt:Int=0 For Local y2=y1-1 To y1+1 For Local x2=x1-1 To x1+1 If map[x2][y2] = 0 Then cnt+=1 Next Next If cnt>0 Then map[x1][y1] = 2 End If Next Next 'here we turn the doors into floors For Local y1=0 Until mapheight For Local x1=0 Until mapwidth If map[x1][y1] = 3 Then map[x1][y1] = 1 Next Next End Method Method makeroom(x:Int,y:Int) Local side:String If map[x][y-1] = 0 side="up" Elseif map[x+1][y] = 0 side="right" Elseif map[x][y+1] = 0 side="down" Elseif map[x-1][y] = 0 side="left" End If Local w:Int=Rnd(5,10) Local h:Int=Rnd(5,10) If side="up" Local x1:Int=x-w/2 Local y1:Int=y-h If roomfits(x1,y1,w,h) insertroom(x1,y1,w,h+1) 'door up map[x1+Rnd(2,w-2)][y1] = 3 ' door right map[x1+w-1][y1+Rnd(2,h-2)] = 3 'door left map[x1][y1+Rnd(2,h-2)] = 3 End If End If If side="right" Local x1:Int=x+1 Local y1:Int=y-h/2 If roomfits(x1,y1,w,h) insertroom(x1-1,y1,w,h) 'door up map[x1+Rnd(2,w-2)][y1] = 3 'door down map[x1+Rnd(2,w-2)][y1+h-1] = 3 ' door right map[x1+w-2][y1+Rnd(2,h-2)] = 3 End If End If If side="left" Local x1:Int=x-w Local y1:Int=y-h/2 If roomfits(x1,y1,w,h) insertroom(x1,y1,w+1,h) 'door up map[x1+Rnd(2,w-2)][y1] = 3 'door down map[x1+Rnd(2,w-2)][y1+h-1] = 3 'door left map[x1][y1+Rnd(2,h-2)] = 3 End If End If If side="down" Local x1:Int=x-w/2 Local y1:Int=y+1 If roomfits(x1,y1,w,h) insertroom(x1,y1-1,w,h) 'door down map[x1+Rnd(2,w-2)][y1+h-2] = 3 'door left map[x1][y1+Rnd(2,h-2)] = 3 ' door right map[x1+w-1][y1+Rnd(2,h-2)] = 3 End If End If End Method Method insertroom(x,y,w,h) For Local y2=y Until y+h For Local x2=x Until x+w If map[x2][y2] <> 3 Then map[x2][y2] = 2 Next Next For Local y2=y+1 Until y+h-1 For Local x2=x+1 Until x+w-1 map[x2][y2] = 1 Next Next End Method Method roomfits(x:Int,y:Int,w:Int,h:Int) For Local y1=y Until y+h For Local x1=x Until x+w If map[x1][y1] = 1 Then Return False Next Next Return True End Method Method draw() For Local y=0 Until mapheight For Local x=0 Until mapwidth Select map[x][y] Case 0 Case 1'floor SetColor 100,100,100 DrawRect x*tilewidth, y*tileheight, tilewidth+1, tileheight+1 Case 2'wall SetColor 200,200,200 DrawRect x*tilewidth, y*tileheight, tilewidth+1, tileheight+1 Case 3'wall SetColor 244,244,0 DrawRect x*tilewidth, y*tileheight, tilewidth+1, tileheight+1 End Select Next Next End Method End Class Class enemy Field x:Float,y:Float Field ms:Float 'movement speed Field w:Int=mymap.tilewidth-8 Field h:Int=mymap.tileheight-8 Field hp:Int Field hpceil:Int Field direction:String="up" ' left/right/up/down Field current:Bool=False 'if being updated Field deleteme:Bool=False Method New() ' find a spot to place the new enemy Local exitloop:Bool=False Local cnt:Int=0 While exitloop=False exitloop = True Local nx = Rnd(50,640-50) Local ny = Rnd(50,480-50) Local mx:Int=nx/mymap.tilewidth Local my:Int=ny/mymap.tileheight If mymap.map[mx][my] <> 1 Then exitloop = False For Local i:=Eachin myenemy If distance(nx,ny,i.x,i.y) < 30 Or distance(myplayer.x,myplayer.y,nx,ny) < 250-cnt exitloop = False End If Next If exitloop = True Then x = nx y = ny End If cnt+=1 Wend ' Here we set the movement speed ms = Rnd(.1,.5) ' Here we set the hitpoints hp = Rnd(1,50) ' the ceiling is what he has or had at start (powerbar) hpceil = hp End Method Method update() current=True ' store the old location Local oldx:Float=x Local oldy:Float=y ' move the enemy towards the player If collide(x+1,y) = False And x < myplayer.x Then x+=ms direction = "right" End If If collide(x-1,y) = False And x > myplayer.x Then x-=ms direction = "left" End If If collide(x,y+1) = False And y < myplayer.y Then y+=ms direction = "down" End If If collide(x,y-1) = False And y > myplayer.y Then y-=ms direction = "up" End If untangle() current=False End Method ' if the enemies are inside of each other ' then move them apart Method untangle() For Local i:=Eachin myenemy If i.current=False If distance(i.x,i.y,x,y) < w Local a:Int a = getangle(i.x,i.y,x,y) Local nx:Float=x Local ny:Float=y nx += Cos(a)*1 ny += Sin(a)*1 Local mx:Int=nx/mymap.tilewidth Local my:Int=ny/mymap.tileheight If mymap.map[mx][my] = 1 x = nx y = ny End If End If End If Next End Method Method draw() SetColor 255,255,0 DrawOval x-w/2,y-w/2,w,w 'powerbar Local current:Float=(Float(w)/Float(hpceil))*hp SetColor 0,0,0 DrawRect x-w/2,y+w/2,w,5 SetColor 255,0,0 DrawRect x-w/2,y+1+w/2,current,3 End Method Method collide:Bool(xx:Int,yy:Int) For Local i:=Eachin myenemy If i.current = False If distance(xx,yy,i.x,i.y) < w Then Return True End If Next Local mx:Int=xx/mymap.tilewidth Local my:Int=yy/mymap.tileheight If mymap.map[mx][my] <> 1 Then Return true Return False End Method 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) Local dx = x2 - x1 Local dy = y2 - y1 Return ATan2(dy,dx)+360 Mod 360 End Function End Class Class player Field x:Float,y:Float Field w:Int=mymap.tilewidth-8 Field h:Int=mymap.tileheight-8 Field wx:Int,wy:Int Field direction:String="up" ' up/left/down/right Field weapondamage:Int=3 Field swing:Bool=False Field swingcountdown:Int=0 Method New() Local exitloop:Bool=False While exitloop = False x = Rnd(640) y = Rnd(480) Local mx:Int=x/mymap.tilewidth Local my:Int=y/mymap.tileheight If mymap.map[mx][my] = 1 Then exitloop = True Wend direction = "up" End Method Method update() updatecontrols() weaponenemies() End Method Method weaponenemies() If swing = False Then Return For Local i:=Eachin myenemy If distance(i.x,i.y,wx,wy) < w+5 'make sure the weapon does not hit throught ' walls Local mx:Int=wx/mymap.tilewidth Local my:Int=wy/mymap.tileheight If mymap.map[mx][my] <> 1 Then Exit 'distance with the enemy Local a:Int=getangle(wx,wy ,i.x,i.y) For Local ww:Int=0 Until w Local nx:Float=i.x Local ny:Float=i.y nx += Cos(a) * 1 ny += Sin(a) * 1 Local mx:Int=nx/mymap.tilewidth Local my:Int=ny/mymap.tileheight If mymap.map[mx][my] = 1 Then i.x = nx i.y = ny Else Exit End If Next i.hp -= weapondamage If i.hp<1 Then i.deleteme = True End If Next End Method Method updatecontrols() ' store the location of the player Local oldx:Int=x Local oldy:Int=y 'handle the movement If collide(x+1,y)=False And KeyDown(KEY_RIGHT) Then x+=1 direction = "right" swing=False End If If collide(x-1,y)=False And KeyDown(KEY_LEFT) Then x-=1 direction = "left" swing=False End If If collide(x,y-1)=False And KeyDown(KEY_UP) Then y-=1 direction = "up" swing=False End If If collide(x,y+1)=False And KeyDown(KEY_DOWN) Then y+=1 direction = "down" swing=False End If 'Handle the weapon If swing = False If KeyDown(KEY_SPACE) Then swing=True If direction = "left" Then wx=x-w ; wy=y If direction = "right" Then wx=x+w ; wy=y If direction = "up" Then wx=x ; wy=y-h If direction = "down" Then wx=x ; wy=y+h swingcountdown = 20 End If Else swingcountdown-=1 If swingcountdown<0 Then swing=False End If End Method ' collide with map Method collide:Bool(xx:Int,yy:Int) Local mx:Int=xx/mymap.tilewidth Local my:Int=yy/mymap.tileheight If mymap.map[mx][my] <> 1 Then Return True Return False End Method Method draw() SetColor 255,100,0 DrawOval x-w/2,y-w/2,w,w If swing = True 'where does the swing graphic get drawn DrawOval wx-w/2,wy-w/2,w,w End If End Method Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Local dx = x2 - x1 Local dy = y2 - y1 Return ATan2(dy,dx)+360 Mod 360 End Function Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Global myplayer:player Global myenemy:List<enemy> = New List<enemy> Global mymap:map Class MyGame Extends App Method OnCreate() SetUpdateRate(60) mymap = New map(640,480,30,30) myplayer = New player() 'For Local i:=0 Until 10 ' myenemy.AddLast(New enemy()) 'Next End Method Method OnUpdate() myplayer.update() ' update the enemies For Local i:=Eachin myenemy i.update() Next ' if enemy hitpoint below 1 then remove him from list For Local i:=Eachin myenemy If i.deleteme = True Then myenemy.Remove(i) Next If myenemy.IsEmpty Local ms:Int=Rnd(30,36) mymap = New map(640,480,ms,ms) myplayer = New player() Local ecnt:Int=Rnd(2,10) For Local i:=0 Until ecnt myenemy.AddLast(New enemy()) Next End If End Method Method OnRender() Cls 0,0,0 mymap.draw() For Local i:=Eachin myenemy i.draw() Next myplayer.draw() SetColor 255,255,255 DrawText "Player vs Monsters on Random map",0,0 DrawText "Space = Weapon , Cursor l/r/u/d = movement",0,20 End Method End Class Function Main() New MyGame() End Function
' I programmed this after playing the game Legend of Pandora.
Import mojo Class enemy Field x:Float,y:Float Field ms:Float 'movement speed Field w:Int=32 Field h:Int=32 Field hp:Int Field hpceil:Int Field direction:String="up" ' left/right/up/down Field current:Bool=False 'if being updated Field deleteme:Bool=False Method New() ' find a spot to place the new enemy Local exitloop:Bool=False While exitloop=False exitloop = True Local nx = Rnd(50,640-50) Local ny = Rnd(50,480-50) For Local i:=Eachin myenemy If distance(nx,ny,i.x,i.y) < 30 Or distance(myplayer.x,myplayer.y,nx,ny) < 250 exitloop = False End If Next If exitloop = True Then x = nx y = ny End If Wend ' Here we set the movement speed ms = Rnd(.1,.5) ' Here we set the hitpoints hp = Rnd(1,50) ' the ceiling is what he has or had at start (powerbar) hpceil = hp End Method Method update() current=True ' store the old location Local oldx:Float=x Local oldy:Float=y ' move the enemy towards the player If collide(x+1,y) = False And x < myplayer.x Then x+=ms direction = "right" End If If collide(x-1,y) = False And x > myplayer.x Then x-=ms direction = "left" End If If collide(x,y+1) = False And y < myplayer.y Then y+=ms direction = "down" End If If collide(x,y-1) = False And y > myplayer.y Then y-=ms direction = "up" End If untangle() current=False End Method Method untangle() For Local i:=Eachin myenemy If i.current=False If distance(i.x,i.y,x,y) < w Local a:Int a = getangle(i.x,i.y,x,y) x += Cos(a)*1 y += Sin(a)*1 End If End If Next End Method Method draw() SetColor 255,255,0 DrawOval x-w/2,y-w/2,w,w 'powerbar Local current:Float=(Float(w)/Float(hpceil))*hp SetColor 0,0,0 DrawRect x-w/2,y+w/2,w,5 SetColor 255,0,0 DrawRect x-w/2,y+1+w/2,current,3 End Method Method collide:Bool(xx:Int,yy:Int) For Local i:=Eachin myenemy If i.current = False If distance(xx,yy,i.x,i.y) < w Then Return True End If Next Return False End Method 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) Local dx = x2 - x1 Local dy = y2 - y1 Return ATan2(dy,dx)+360 Mod 360 End Function End Class Class player Field x:Float,y:Float Field w:Int=32 Field h:Int=32 Field wx:Int,wy:Int Field direction:String="up" ' up/left/down/right Field weapondamage:Int=3 Field swing:Bool=False Field swingcountdown:Int=0 Method New(x:Int,y:Int) Self.x = x Self.y = y direction = "up" End Method Method update() updatecontrols() weaponenemies() End Method Method weaponenemies() If swing = False Then Return For Local i:=Eachin myenemy If distance(i.x,i.y,wx,wy) < 48 Local a:Int=getangle(wx,wy ,i.x,i.y) i.x += Cos(a) * 32 i.y += Sin(a) * 32 i.hp -= weapondamage If i.hp<1 Then i.deleteme = True End If Next End Method Method updatecontrols() ' store the location of the player Local oldx:Int=x Local oldy:Int=y 'handle the movement If KeyDown(KEY_RIGHT) Then x+=1 direction = "right" swing=False End If If KeyDown(KEY_LEFT) Then x-=1 direction = "left" swing=False End If If KeyDown(KEY_UP) Then y-=1 direction = "up" swing=False End If If KeyDown(KEY_DOWN) Then y+=1 direction = "down" swing=False End If 'Handle the weapon If swing = False If KeyDown(KEY_SPACE) Then swing=True If direction = "left" Then wx=x-w ; wy=y If direction = "right" Then wx=x+w ; wy=y If direction = "up" Then wx=x ; wy=y-h If direction = "down" Then wx=x ; wy=y+h swingcountdown = 20 End If Else swingcountdown-=1 If swingcountdown<0 Then swing=False End If End Method Method draw() SetColor 255,100,0 DrawOval x-w/2,y-w/2,w,w If swing = True 'where does the swing graphic get drawn DrawOval wx-w/2,wy-w/2,w,w End If End Method Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Local dx = x2 - x1 Local dy = y2 - y1 Return ATan2(dy,dx)+360 Mod 360 End Function Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Global myplayer:player Global myenemy:List<enemy> = New List<enemy> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) myplayer = New player(DeviceWidth()/2,DeviceHeight()/2) 'For Local i:=0 Until 10 ' myenemy.AddLast(New enemy()) 'Next End Method Method OnUpdate() myplayer.update() ' update the enemies For Local i:=Eachin myenemy i.update() Next ' if enemy hitpoint below 1 then remove him from list For Local i:=Eachin myenemy If i.deleteme = True Then myenemy.Remove(i) Next If myenemy.IsEmpty Local ecnt:Int=Rnd(2,10) For Local i:=0 Until ecnt myenemy.AddLast(New enemy()) Next End If End Method Method OnRender() Cls 0,0,0 For Local i:=Eachin myenemy i.draw() Next myplayer.draw() SetColor 255,255,255 DrawText "Player vs Monsters on empty map",0,0 DrawText "Space = Weapon , Cursor l/r/u/d = movement",0,20 End Method End Class Function Main() New MyGame() End Function