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
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.
Monday, October 30, 2017
Monkey-X - Generator - Tileable Textured Stones - code example
Monday, October 23, 2017
Monkey-x - Generator - 2d flasks and bottles - code example
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
Monkey-X - Generator - 2d Maps using Lines - code example
' 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
Monkey-X - Breath First Search(bfs) - code example
'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
Thursday, October 19, 2017
Monkey-X - Ai Taking Cover - Shooter - code example
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
Monkey-X - Astar Pathfinding - Object Oriented - code example
' 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
Wednesday, October 11, 2017
Monkey-X - Player vs Monsters on Random Map - code example
'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
Monkey-X - Player vs Monsters on Empty map - code example
' 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
Subscribe to:
Comments (Atom)