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.
I saw this enemy in a platformer game and thought it would be nice to make myself. I tried it 8 months ago and failed but today I figured out what I did wrong. (You can re-use the wallcrawler class)
Import mojo Const tilewidth = 32 Const tileheight = 32 Const mapwidth:Int=20 Const mapheight: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,2,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1], [1,0,0,0,0,0,1,1,1,0,0,0,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1], [1,1,1,1,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] ] Class wallcrawler 'x and y tilepositions(cells) Field x:Float,y:Float 'nx and ny is next tileposition Field nx:Int,ny:Int 'offset for drawing (smooth movement) Field offx:Int,offy:Int ' direction wallcrawler is goint to ' 1 = up, 2 = right, 3 = down, 4 = left Field direction:Int Method New(x:Float,y:Float) Self.x = x Self.y = y Self.nx = x Self.ny = y 'start going right Self.direction = 2 End Method Method update() If x = nx And y = ny Else ' if not on next position then slowly move there If x<nx Then offx+=1 If x>nx Then offx-=1 If y<ny Then offy+=1 If y>ny Then offy-=1 If offx>tilewidth Then x+=1;offx=0 If offx<-tilewidth Then x-=1;offx=0 If offy>tileheight Then y+=1;offy=0 If offy<-tileheight Then y-=1;offy=0 Return End If ' get the next directions Local rightd:Int=direction+1 Local forwardd:Int=direction Local leftd:Int=direction-1 ' b sure to stay in legal movement If rightd > 4 Then rightd = 1 If leftd < 1 Then leftd = 4 ' first see if we can go right If postaken(rightd) = True direction = rightd movepos(rightd) Return End If ' then see if we can go forward If postaken(forwardd) = True direction = forwardd movepos(forwardd) Return End If 'then see if we can go left If postaken(leftd) = True direction = leftd movepos(leftd) Return End If End Method ' get next cell position Method movepos(d:Int) nx = x ny = y Select d Case 1;ny-=1 Case 2;nx+=1 Case 3;ny+=1 Case 4;nx-=1 End Select End Method 'see if the next possible position if a wall Method postaken(d:Int) Select d Case 1;If map[y-1][x] = 0 Then Return True Case 2;If map[y][x+1] = 0 Then Return True Case 3;If map[y+1][x] = 0 Then Return True Case 4;If map[y][x-1] = 0 Then Return True End Select Return False End Method Method draw() SetColor 255,0,0 DrawRect x*tilewidth+offx,y*tileheight+offy,tilewidth,tileheight End Method End Class Class players Field x:Float = 640/2-16 Field y:Float = 480/2 Field pw:Int=32 Field ph:Int=32 Field incy:Float Field jump:Bool=False Method New() End Method Method update() playermovement playergravity End Method Method playergravity() ' If the player is on the ground and the space bar is pressed If jump = False And playertc(0,1) = False jump = True incy = 0 End If If jump = False And KeyDown(KEY_SPACE) = True incy = -4 jump = True End 'If the player is in the jump If jump = True incy += 0.1 'if the player is going up If incy <=0 For Local i:Int = 0 Until Abs(incy) y -= 1 If playertc(0,-1) = True incy = 0 Exit End If End End ' if the player if going down If incy > 0 For Local i:Int = 0 Until incy y += 1 'if the player touches the ground If playertc(0,1) = True jump = False Exit End End End End End Method Method playermovement() If KeyDown(KEY_RIGHT) For Local i=0 Until 2 If playertc(1,0) = False x+=1 End If Next End If If KeyDown(KEY_LEFT) For Local i=0 Until 2 If playertc(-1,0) = False x-=1 End If Next End If End Method Method playertc:Bool(x1:Int,y1:Int) Local cx = (x + x1) / tilewidth Local cy = (y + y1) / tileheight For Local y2=cy-1 Until cy+2 For Local x2=cx-1 Until cx+2 If x2>=0 And x2<mapwidth And y2>=0 And y2<mapheight If map[y2][x2] > 0 If rectsoverlap(x+x1,y+y1,pw,ph,x2*tilewidth, y2*tileheight,tilewidth,tileheight) = True Return True End If End If End If Next Next Return False End Method Method draw() ' draw the player SetColor 255,255,0 DrawOval x,y,pw,ph End Method End Class Global player:List<players> = New List<players> Global wallcrawlers:List<wallcrawler> = New List<wallcrawler> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) player.AddLast(New players()) createwallcrawlers End Method OnUpdate() ' Player left and right movement For Local i:=Eachin player i.update Next For Local i:=Eachin wallcrawlers i.update Next End Method OnRender() Cls(0,0,0) SetColor(255,255,255) ' draw the map For Local y:Int = 0 Until mapheight For Local x:Int = 0 Until mapwidth If map[y][x] = 1 Then DrawRect(x*tilewidth,y*tileheight,tilewidth,tileheight) End End DrawText "Platformer Example with Wallcrawlers(wall following)",10,10 DrawText "Use cursor left/right and space bar to move player",160,10 For Local i:=Eachin player i.draw Next For Local i:=Eachin wallcrawlers i.draw Next End End Function createwallcrawlers:Void() For Local y=0 Until mapheight For Local x=0 Until mapwidth If map[y][x] = 2 map[y][x] = 0 wallcrawlers.AddLast(New wallcrawler(x,y)) End If Next Next 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
Here a example of how to make Vertical Sliders. GUI stuff.
Import mojo Class vslider Field x:Int,y:Int Field w:Int,h:Int Field slidey:Float Field low:Float,heigh:Float Field name:String Method New(x:Int,y:Int,w:Int,h:Int,low:Int,heigh:Int,slidey:Int,name:String) Self.x = x Self.y = y Self.w = w Self.h = h Self.low = low Self.heigh = heigh Self.slidey = slidey Self.name = name End Method Method update() If MouseDown(MOUSE_LEFT) If rectsoverlap( MouseX(), MouseY(), 1, 1, x+5,y+25, w/2,h-50) Local val:Float val = MouseY()-(y+25) slidey = val*((heigh-low)/(h-50)) slidey+=low End If End If If MouseHit(MOUSE_LEFT) If rectsoverlap( MouseX(), MouseY(), 1,1, x+5,y+5, w/2,20) If slidey>low Then slidey-=1 Return End If If rectsoverlap( MouseX(), MouseY(), 1,1, x+5,y+h-25, w/2,20) If slidey<heigh Then slidey+=1 Return End If End If slidey=Floor(slidey) End Method Method draw() SetColor 0,0,0 DrawRect x,y,w,h SetColor 150,150,150 DrawRect x+1,y+1,w-2,h-2 SetColor 255,255,255 DrawLine x+1,y+1,x+w-1,y+1 DrawLine x+1,y+1,x+1,y+h-1 SetColor 50,50,50 DrawRect x+5,y+25,w-10,h-50 SetColor 0,0,0 Local val:Float val = (slidey-low)*((h-70)/(heigh-low)) DrawRect x+5,y+25+val,w/2,20 SetColor 255,255,255 DrawText name,x+w/2,y-16,0.5 End Method Method 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 Method End Class Global sr:vslider Global sg:vslider Global sb:vslider Class MyGame Extends App Method OnCreate() SetUpdateRate(60) sr = New vslider(100,100,20,150,0,225,50,"R") sg = New vslider(148,100,20,150,0,255,50,"G") sb = New vslider(192,100,20,150,0,255,50,"B") End Method Method OnUpdate() sr.update sg.update sb.update End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 DrawText "MonkeyX - GUI - Simple Vertical Sliders - Code Example.",10,10 DrawText "Use the Mouse with the Sliders to change color of rect.",10,30 sr.draw sg.draw sb.draw SetColor 255,255,255 DrawRect 320,100,100,100 SetColor sr.slidey,sg.slidey,sb.slidey DrawRect 320+1,100+1,100-2,100-2 End Method End Class Function Main() New MyGame() End Function
A few times I was asked if I knew how to do those double jumps in games. It is not that hard to program. All you need is to have a extra boolean that sees if you are not double jumping and trigger the double jump while in a regular jump. See the code.
' Doublejump and jumping example Import mojo Global px:Float = 320 Global py:Float = 240 Global playerjump:Bool = False Global pincy:Float = 0 Global doublejump:Bool = False Class MyGame Extends App Method OnCreate() SetUpdateRate(60) End Method OnUpdate() ' If the player is on the ground and the space bar is pressed If playerjump = False And KeyDown(KEY_SPACE) = True pincy = -3 playerjump = True End 'Double jump If playerjump = True And doublejump = False If KeyDown(KEY_SPACE) If pincy < 0 And pincy >-2.0 pincy = -3 doublejump = True End If End If End If 'If the player is in the jump If playerjump = True pincy += 0.1 'if the player is going up If pincy <=0 For Local i:Int = 0 Until Abs(pincy) py -= 1 End End ' if the player if going down If pincy > 0 For Local i:Int = 0 Until pincy py += 1 'if the player touches the ground If py > 240 Then playerjump = False doublejump = False py = 240 Exit End End End End End Method OnRender() Cls(0,0,0) SetColor(255,255,255) DrawRect px,py,32,32 DrawText "Press space bar to jump. Press space again in jump to double jump.",10,10 If doublejump = True DrawText "Doublejump",px+16,py-10,0.5 End If End End Function Main() New MyGame() End
In games sometimes you want to agents to move towards the player. With Floodfill pathfinding you create a map around the player that increases in value the farther away from the player. These values van be used by the agents to count back towards the player. You can do more with the floodfill pathfinding I bet.
Import mojo Const tilewidth = 32 Const tileheight = 32 Const mapwidth:Int=20 Const mapheight:Int=15 Global gamemap: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,1,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,1,1,1,1,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,1], [1,0,1,1,1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1], [1,0,0,1,1,1,1,1,0,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,1,1,1,1], [1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,1], [1,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,0,0,1], [1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1], [1,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,1], [1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1], [1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,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 openlist Field x:Int,y:Int Field val:Int Method New(x:Int,y:Int,val:Int) Self.x=x Self.y=y Self.val=val End Method End Class Class closedlist Field x:Int,y:Int Field val:Int Method New(x:Int,y:Int,val:Int) Self.x=x Self.y=y Self.val=val End Method End Class Class agent Field x:Int,y:Int Field delay:Int Field delete:Bool=False Method New() Local exitloop:Bool=False While exitloop = False Local x1:Int=Rnd(mapwidth) Local y1:Int=Rnd(mapheight) If myplayer.map[x1][y1] > 10 x = x1 y=y1 exitloop=True End If Wend End Method Method update() delay-=1 If delay<1 delay = 30 'move towards the player Local val:Int=myplayer.map[x][y] Local exitloop:Bool=False Local dx:Int=x,dy:Int=y While exitloop = False Local x1:Int = x+Rnd(-1,2) Local y1:Int = y+Rnd(-1,2) If gamemap[y1][x1] = 0 If myplayer.map[x1][y1] < val dx=x1 dy=y1 val = myplayer.map[x1][y1] End If End If If Rnd(100)<5 Then exitloop = True Wend x = dx y = dy ' if close to the player remove If myplayer.map[x][y] < 2 delete = True End If End If End Method Method draw() SetColor 255,0,0 DrawOval x*tilewidth+5,y*tileheight+5,tilewidth-10,tileheight-10 End Method End Class Class player Field ol:List<openlist> = New List<openlist> Field x:Int=10,y:Int=10 Field map:Int[][] Method New() map = New Int[mapwidth][] For Local i = 0 Until mapwidth map[i] = New Int[mapheight] Next DebugLog mapwidth+","+mapheight makefloodmap() End Method Method update() If KeyHit(KEY_LEFT) If x-1 > 0 If gamemap[y][x-1] = 0 x-=1 makefloodmap End If End If End If If KeyHit(KEY_RIGHT) If x+1 < mapwidth If gamemap[y][x+1] = 0 x+=1 makefloodmap End If End If End If If KeyHit(KEY_UP) If y-1 > 0 If gamemap[y-1][x] = 0 y-=1 makefloodmap End If End If End If If KeyHit(KEY_DOWN) If y+1 < mapheight If gamemap[y+1][x] = 0 y+=1 makefloodmap End If End If End If End Method Method makefloodmap() For Local y1=0 Until mapheight For Local x1=0 Until mapwidth map[x1][y1] = 0 Next Next ol.Clear() ol.AddLast(New openlist(x,y,1)) map[x][y] = 1 While ol.IsEmpty() = False For Local i:=Eachin ol Local tx:Int=i.x Local ty:Int=i.y Local tv:Int=i.val ol.Remove i If ty-1 > 0 If map[tx][ty-1] = 0 If gamemap[ty-1][tx] = 0 ol.AddLast(New openlist(tx,ty-1,tv+1)) map[tx][ty-1] = tv+1 End If End If End If If tx+1 < mapwidth If map[tx+1][ty] = 0 If gamemap[ty][tx+1] = 0 ol.AddLast(New openlist(tx+1,ty,tv+1)) map[tx+1][ty] = tv+1 End If End If End If If ty+1 < mapheight If map[tx][ty+1] = 0 If gamemap[ty+1][tx] = 0 ol.AddLast(New openlist(tx,ty+1,tv+1)) map[tx][ty+1] = tv+1 End If End If End If If tx-1 > 0 If map[tx-1][ty] = 0 If gamemap[ty][tx-1] = 0 ol.AddLast(New openlist(tx-1,ty,tv+1)) map[tx-1][ty] = tv+1 End If End If End If Next Wend End Method Method isonclosedlist:Bool(x1:Int,y1:Int) For Local i:=Eachin cl If i.x = x1 And i.y = y1 Then Return True Next Return False End Method Method draw() SetColor 255,255,0 DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight SetColor 255,255,255 For Local y1=0 Until mapheight For Local x1=0 Until mapwidth If map[x1][y1] > 0 DrawText map[x1][y1],x1*tilewidth,y1*tileheight End If Next Next End Method End Class Global myplayer:player = New player() Global myagent:List<agent> = New List<agent> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) End Method Method OnUpdate() If Rnd(100) < 2 myagent.AddLast(New agent()) End If myplayer.update For Local i:=Eachin myagent i.update If i.delete = True myagent.Remove i End If Next End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 drawmap For Local i:=Eachin myagent i.draw Next myplayer.draw SetColor 255,255,255 DrawText "Monkey-X - Floodfill pathfinding agents - code example.",10,2 DrawText "Use Cursor keys to move (yellow) player.",10,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 gamemap[y][x] = 1 DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight End If Next Next End Function Function Main() New MyGame() End Function
I made one of my older group movement examples a little bit smarter. The units will now move a short time either left or right from the target direction if their path is blocked. If all paths are blocked then it will wait a second.
Import mojo Class ai ' unit locations Field x:Float,y:Float ' destination coords Field dx:Int,dy:Int ' movement speed Field ms:Float ' angle of x/y and dx/dy Field angle:Int ' state Field state:String="Direct Line" Field aroundang:Int Field countdown1:Int Method New(x:Int,y:Int) Self.x = x Self.y = y Self.ms = Rnd(0.5,1.5) Self.dx = DeviceWidth()/2 Self.dy = DeviceHeight()/2 End Method Method update() If state = "Wait" countdown1-=1 If countdown1 < 1 state="Direct Line" End If End If If state="Move Around" countdown1-=1 If countdown1 < 1 state="Direct Line" End If Local nx:Float = x+Cos(aroundang)*(ms*4) Local ny:Float = y+Sin(aroundang)*(ms*4) Local nxt:Bool=False For Local i:=Eachin myai If i.x <> x If i.y <> y If rectsoverlap(nx,ny,16,16,i.x,i.y,16,16) = True nxt = True state="Wait" End If End If End If Next If nxt = False x += Cos(aroundang)*ms y += Sin(aroundang)*ms End If End If If state="Direct Line" angle = getangle(dx,dy,x,y) If distance(x,y,dx,dy) > 5 Local nx:Float = x+Cos(angle)*(ms*4) Local ny:Float = y+Sin(angle)*(ms*4) Local nxt:Bool=False For Local i:=Eachin myai If i.x <> x If i.y <> y If rectsoverlap(nx,ny,16,16,i.x,i.y,16,16) = True nxt = True state="Move Around" countdown1 = 32 findopenspot() End If End If End If Next If nxt = False x += Cos(angle)*ms y += Sin(angle)*ms End If End If End If End Method Method findopenspot() Local sel:Int=Rnd(10) If sel<5 Then If rightturn() = False leftturn End If Else If leftturn() = False rightturn End If End If End Method Method rightturn:Bool() aroundang=angle+90 Local nx:Float = x+Cos(aroundang)*(ms*4) Local ny:Float = y+Sin(aroundang)*(ms*4) Local nxt:Bool=False For Local i:=Eachin myai If i.x <> x If i.y <> y If rectsoverlap(nx,ny,16,16,i.x,i.y,16,16) = True nxt = True state="Wait" countdown1 = 60 Return False End If End If End If Next Return True End Method Method leftturn:Bool() aroundang=angle-90 Local nx:Float = x+Cos(aroundang)*(ms*4) Local ny:Float = y+Sin(aroundang)*(ms*4) Local nxt:Bool=False For Local i:=Eachin myai If i.x <> x If i.y <> y If rectsoverlap(nx,ny,16,16,i.x,i.y,16,16) = True nxt = True state = "Wait" countdown1 = 60 Return False End If End If End If Next Return True End Method Method draw() SetColor 255,0,0 DrawOval x,y,16,16 If state="Move Around" SetColor 255,255,0 DrawOval x+(Cos(aroundang)*16), y+(Sin(aroundang)*16),16,16 End If End Method Method 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 Method Method getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return ATan2(y1-y2, x1-x2) End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Global numai:Int=10 Global myai:List<ai> = New List<ai> ' waittime before random new destination Global dxchangecountdown:Int=500 ' hold the destination of the units Global mydx:Int,mydy:Int Class MyApp Extends App Method OnCreate() SetUpdateRate(60) For Local i=0 To numai Local exitloop:Bool=False Local nx:Int,ny:Int While exitloop = False exitloop = True nx=Rnd(640) ny=Rnd(480) For Local ii:=Eachin myai If distance(nx,ny,ii.x,ii.y) < 32 exitloop = False End If Next Wend myai.AddLast(New ai(nx,ny)) Next Local date := GetDate() Seed = date[6] End Method Method OnUpdate() dxchangecountdown-=1 If dxchangecountdown < 0 dxchangecountdown = 500 mydx = Rnd(32,DeviceWidth()-64) mydy = Rnd(32,DeviceHeight()-64) For Local i:=Eachin myai i.dx = mydx i.dy = mydy Next End If For Local i:=Eachin myai i.update Next If MouseHit(MOUSE_LEFT) dxchangecountdown = 500 For Local i:=Eachin myai i.dx = MouseX() i.dy = MouseY() Next End If End Method Method OnRender() Cls 0,0,0 For Local i:=Eachin myai i.draw mydx = i.dx mydy = i.dy Next SetColor 255,255,0 DrawLine mydx,mydy,mydx-5,mydy DrawLine mydx,mydy,mydx+5,mydy DrawLine mydx,mydy,mydx,mydy-5 DrawLine mydx,mydy,mydx,mydy+5 SetColor 255,255,255 DrawText "Monkey-X Smarter group movement ai.",10,10 DrawText "Press the left mouse to change dx,dy",10,25 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 Main() New MyApp End Function
Here a example where there are zombies walkig around throwing parts of their body around.
Import mojo Class agent Field x:Float,y:Float Field w:Int=20+Rnd(20) Field h:Int=20+Rnd(20) Field incx:Float Method New(x:Int,incx:Float) Self.x = x Self.y = 272-h Self.incx = incx End Method Method update() x += incx If Rnd(60*60) < 10 Then incx = -incx End If If x<100 Then incx=-incx If x>640-100 Then incx=-incx If Rnd(60*60)<10 Local ix:Float=Rnd(-6,6) If ix >-0.5 And ix <0.5 Then ix = ix*2 mybodypart.AddLast(New bodypart(x-9+Rnd(w), y-h+Rnd(h/2), ix,Rnd(-4,-2))) End If End Method Method draw() SetColor 255,255,255 DrawRect x,y,w,h End Method End Class Class bodypart Field w:Int,h:Int Field x:Float,y:Float Field incx:Float,incy:Float Field mdf:Float Field stopped:Bool=False Field timeout:Int,delete:Bool=False Method New(x:Int,y:Int,incx:Float,incy:Float) Self.x = x Self.y = y Self.incx = incx Self.incy = incy w = Rnd(3,9) h = Rnd(3,9) mdf = 0.09 End Method Method update() If stopped = False x+=incx y+=incy If incx>0 Then incx-=mdf If incx<0 Then incx+=mdf If mdf>0.01 Then mdf-=0.001 incy+=0.1 If y>272 Then incy=-(Rnd(incy/2)) incx = Rnd(-incy,incy) End If If y>273 If incx >-0.2 And incx <0.2 If incy>-0.2 And incy<0.2 stopped=True End If End If End If End If If stopped = True timeout+=1 If timeout > 60*20 delete = True End If End If End Method Method draw() SetColor 255,0,0 DrawOval x,y,w,h End Method End Class Global mybodypart:List<bodypart> = New List<bodypart> Global myagent:List<agent> = New List<agent> Class MyGame Extends App Method OnCreate() SetUpdateRate(60) For Local i=0 Until 10 Local incx:Float=Rnd(-1.5,1.5) If incx>-0.3 And incx<0.3 incx=incx*2 End If myagent.AddLast(New agent(Rnd(100,640-100),incx)) Next End Method Method OnUpdate() For Local i:=Eachin myagent i.update Next For Local i:=Eachin mybodypart i.update If i.delete = True mybodypart.Remove i End If Next End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 For Local i:=Eachin myagent i.draw Next For Local i:=Eachin mybodypart i.draw Next SetColor 255,255,255 DrawText "Monkey-X - Zombies throwing body parts Example",10,10 End Method End Class Function Main() New MyGame() End Function