Import mojo
Class flowfield
Field mapwidth:Int,mapheight:Int
Field tilewidth:Float,tileheight:Float
Field screenwidth:Int,screenheight:Int
Field map:Int[][]
Field flowlinestartx:Int
Field flowlinestarty:Int
Method New(screenwidth:Int,screenheight:Int,mapwidth:Int,mapheight:Int)
Self.screenwidth = screenwidth
Self.screenheight = screenheight
Self.tilewidth = Float(screenwidth)/Float(mapwidth)
Self.tileheight = Float(screenheight)/Float(mapheight)
Self.mapwidth = mapwidth
Self.mapheight = mapheight
' make a array
map = New Int[mapwidth][]
For Local i = 0 Until mapwidth
map[i] = New Int[mapheight]
Next
' -1 if no direction
For Local y:=0 Until mapheight
For Local x:=0 Until mapheight
map[x][y] = -1
Next
Next
'
' Here we create a number of points
' with which we draw the lines in between.
'
Seed = GetDate[5]
Local lastx:Int=Rnd(2,mapwidth-2)
Local lasty:Int=Rnd(2,mapheight-2)
flowlinestartx = lastx
flowlinestarty = lasty
For Local i:=0 Until 5
Local newx:Int=Rnd(2,mapwidth-2)
Local newy:Int=Rnd(2,mapheight-2)
flowline(lastx,lasty,newx,newy)
lastx=newx
lasty=newy
Next
End Method
' Make a flowfield(line) between two points
Method flowline(x1:Int,y1:Int,x2:Int,y2:Int)
Local dx:Int, dy:Int, sx:Int, sy:Int, e:Int
dx = Abs(x2 - x1)
sx = -1
If x1 < x2 Then sx = 1
dy = Abs(y2 - y1)
sy = -1
If y1 < y2 Then sy = 1
If dx < dy Then
e = dx / 2
Else
e = dy / 2
End If
Local exitloop:Bool=False
While exitloop = False
'SetColor 255,255,255
'DrawPoint x1,y1
If x1 = x2
If y1 = y2
exitloop = True
End If
End If
For Local y:=-1 To 1
For Local x:=-1 To 1
map[x1+x][y1+y] = pointto(x1+x,y1+y,x1,y1)
Next
Next
map[x1][y1] = pointto(x1,y1,x2,y2)
If dx > dy Then
x1 += sx ; e -= dy
If e < 0 Then e += dx ; y1 += sy
Else
y1 += sy ; e -= dx
If e < 0 Then e += dy ; x1 += sx
Endif
Wend
End Method
' point the flow field direction to the x2,y2 from x1,y1
Function pointto:Int(x1:Int,y1:Int,x2:Int,y2:Int)
Local nd:Int=-1
If x1<x2 Then nd=0
If x1>x2 Then nd=4
If y1<y2 Then nd=2
If y1>y2 Then nd=6
If x1<x2 And y1<y2 Then nd=1
If x1>x2 And y1<y2 Then nd=3
If x1<x2 And y1>y2 Then nd=7
If x1>x2 And y1>y2 Then nd=5
Return nd
End Function
Method draw()
SetColor 255,255,255
For Local y:=0 Until mapheight
For Local x:=0 Until mapwidth
Local direction:Int = map[x][y]
If direction=-1 Then Continue
Local x1:Float=Float(x)*tilewidth+tilewidth/2
Local y1:Float=Float(y)*tileheight+tileheight/2
Local ang:Int= (360/8*direction)
Local x2:Float=x1+(Cos(ang)*tilewidth/2)
Local y2:Float=y1+(Sin(ang)*tileheight/2)
Local x3:Float=x1+(Cos(ang+150)*tilewidth/4)
Local y3:Float=y1+(Sin(ang+150)*tileheight/4)
Local x4:Float=x1+(Cos(ang-150)*tilewidth/4)
Local y4:Float=y1+(Sin(ang-150)*tileheight/4)
DrawPoly([x2,y2,x3,y3,x4,y4])
Next
Next
End Method
End Class
Class MyGame Extends App
Field myflowfield:flowfield
Field alienx:Int=200,alieny:Int=200
Field lastx:Int,lasty:Int
Method OnCreate()
SetUpdateRate(60)
myflowfield = New flowfield(DeviceWidth(),DeviceHeight(),50,50)
alienx = myflowfield.flowlinestartx * myflowfield.tilewidth
alieny = myflowfield.flowlinestarty * myflowfield.tileheight
End Method
Method OnUpdate()
Local d:Int=myflowfield.map[alienx/myflowfield.tilewidth][alieny/myflowfield.tileheight]
' Move the alien based on the flowfield array's direction 0=right 1=rightdown 7=rightup
Select d
Case 0
alienx+=1
Case 1
alienx+=1;alieny+=1
Case 2
alieny+=1
Case 3
alienx-=1
alieny+=1
Case 4
alienx-=1
Case 5
alienx-=1
alieny-=1
Case 6
alieny-=1
Case 7
alieny-=1
alienx+=1
End Select
' stay inside array(screen)
If alienx+10>DeviceWidth() Then alienx = DeviceWidth()-10
If alienx-10<0 Then alienx = 10
If alieny+10>DeviceHeight() Then alieny = DeviceHeight()-10
If alieny-10<0 Then alieny = 10
' if we press the left mouse then move the alien to mouse position
If MouseHit(MOUSE_LEFT) Then
alienx = MouseX
alieny = MouseY
End If
' if pressed space or no move by alien then new flowfield
If KeyHit(KEY_SPACE) Or lastx = alienx And lasty = alieny
myflowfield = New flowfield(DeviceWidth(),DeviceHeight(),50,50)
alienx = myflowfield.flowlinestartx * myflowfield.tilewidth
alieny = myflowfield.flowlinestarty * myflowfield.tileheight
End If
lastx = alienx
lasty = alieny
End Method
Method OnRender()
Cls 0,0,0
SetColor 255,255,255
myflowfield.draw()
SetColor 255,0,0
DrawCircle(alienx,alieny,20)
SetColor 255,255,255
DrawText("Flow Fields (lines)- Press lmb to place alien - space new map.",0,0)
End Method
End Class
Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int)
If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False
If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False
Return True
End
Function Main()
New MyGame()
End Function
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.
Wednesday, July 12, 2017
Monkey-X - Flow Fields - Lines - code example
Monkey-X - Flow Fields - code example
Import mojo
Class flowfield
Field mapwidth:Int,mapheight:Int
Field tilewidth:Float,tileheight:Float
Field screenwidth:Int,screenheight:Int
Field map:Int[][]
Method New(screenwidth:Int,screenheight:Int,mapwidth:Int,mapheight:Int)
Self.screenwidth = screenwidth
Self.screenheight = screenheight
Self.tilewidth = Float(screenwidth)/Float(mapwidth)
Self.tileheight = Float(screenheight)/Float(mapheight)
Self.mapwidth = mapwidth
Self.mapheight = mapheight
map = New Int[mapwidth][]
For Local i = 0 Until mapwidth
map[i] = New Int[mapheight]
Next
pointtocenter
End Method
'
' In the flowfield array there are 8 directions.
' Here we point the directions towards the center
'
Method pointtocenter()
For Local y:Int=0 Until mapheight
For Local x:Int=0 Until mapwidth
Local x2:Int=mapwidth/2
Local y2:Int=mapheight/2
Local nd:Int=0
If x<x2 Then nd=0
If x>x2 Then nd=4
If y<y2 Then nd=2
If y>y2 Then nd=6
If x<x2 And y<y2 Then nd=1
If x>x2 And y<y2 Then nd=3
If x<x2 And y>y2 Then nd=7
If x>x2 And y>y2 Then nd=5
map[x][y] = nd
Next
Next
End Method
Method draw()
SetColor 255,255,255
For Local y:=0 Until mapheight
For Local x:=0 Until mapwidth
Local direction:Int = map[x][y]
Local x1:Float=Float(x)*tilewidth+tilewidth/2
Local y1:Float=Float(y)*tileheight+tileheight/2
Local ang:Int= (360/8*direction)
Local x2:Float=x1+(Cos(ang)*tilewidth/2)
Local y2:Float=y1+(Sin(ang)*tileheight/2)
Local x3:Float=x1+(Cos(ang+150)*tilewidth/4)
Local y3:Float=y1+(Sin(ang+150)*tileheight/4)
Local x4:Float=x1+(Cos(ang-150)*tilewidth/4)
Local y4:Float=y1+(Sin(ang-150)*tileheight/4)
DrawPoly([x2,y2,x3,y3,x4,y4])
Next
Next
End Method
End Class
Class MyGame Extends App
Field myflowfield:flowfield
Field alienx:Int=200,alieny:Int=200
Method OnCreate()
SetUpdateRate(60)
myflowfield = New flowfield(DeviceWidth(),DeviceHeight(),20,20)
End Method
Method OnUpdate()
Local d:Int=myflowfield.map[alienx/myflowfield.tilewidth][alieny/myflowfield.tileheight]
Select d
Case 0
alienx+=1
Case 1
alienx+=1;alieny+=1
Case 2
alieny+=1
Case 3
alienx-=1
alieny+=1
Case 4
alienx-=1
Case 5
alienx-=1
alieny-=1
Case 6
alieny-=1
Case 7
alieny-=1
alienx+=1
End Select
If rectsoverlap(alienx-10,alieny-10,20,20,DeviceWidth/2-30,DeviceHeight/2-30,60,60)
alienx = Rnd(DeviceWidth)
alieny = Rnd(DeviceHeight)
End If
If MouseHit(MOUSE_LEFT) Then
alienx = MouseX
alieny = MouseY
End If
End Method
Method OnRender()
Cls 0,0,0
SetColor 255,255,255
myflowfield.draw()
SetColor 255,0,0
DrawCircle(alienx,alieny,20)
SetColor 255,255,255
DrawText("Flow Fields - Press Left Mouse to place alien",0,0)
End Method
End Class
Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int)
If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False
If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False
Return True
End
Function Main()
New MyGame()
End Function
Sunday, July 9, 2017
Monkey-X - Example - Boids Flocking - code example
' Converted to Monkey-X - from Blitzmax ( coded originally by Flanker) ' Import mojo Class obstacle Field x:Float,y:Float Field radius:Int Method New(x:Int,y:Int) Self.x = x Self.y = y Self.radius = 20 End Method Method draw() SetColor 255,255,0 DrawCircle(x,y,radius) End Method End Class Class boid Field friendlist:List<boid> = New List<boid> Field x:Float,y:Float,angle:Float Field vx:Float,vy:Float Field alignspeed:Float = 8 Field speed:Float = 3 Field smoothturn:Float = 25 Field radius:Float = 10 Field cohesionfactor:Float = 100 Field friendradius:Float = 75 Field frienddistance:Float = 30 Field friendsqradius:Float Field friendsqrdistance:Float Field obstaclemargin:Float = 2 Method New() friendsqradius = friendradius*friendradius friendsqrdistance = frienddistance*frienddistance End Method Method create(count:Int) For Local i:=0 Until count Local newboid:boid = New boid() newboid.x = Rnd(640) newboid.y = Rnd(480) newboid.angle = Rnd(360) boidlist.AddLast(newboid) Next End Method Method update() getfriends() If friendlist.Count > 0 vx = 0 vy = 0 cohesion() obstacle() distance() align() Else obstacle() End If ' Clamp the movement speed If vx < -2 Then vx = -2 If vy < -2 Then vy = -2 If vx > 2 Then vx = 2 If vy > 2 Then vy = 2 move() End Method Method obstacle() For Local i:=Eachin myobstacle Local diffx:Float = x - i.x Local diffy:Float = y - i.y Local sqrdistance:Float=diffx*diffx+diffy*diffy If diffx*diffx+diffy*diffy < i.radius*i.radius*i.radius/obstaclemargin vx -= (i.x - x) / Sqrt(sqrdistance) vy -= (i.y - y) / Sqrt(sqrdistance) End If Next End Method Method cohesion() Local centerx:Float Local centery:Float For Local i:= Eachin friendlist centerx += i.x centery += i.y Next centerx /= friendlist.Count centery /= friendlist.Count vx += (centerx-x) / cohesionfactor vy += (centery-y) / cohesionfactor End Method Method distance() For Local i:=Eachin friendlist Local diffx:Float=x-i.x Local diffy:Float=y-i.y Local sqrdistance:Float=diffx*diffx+diffy*diffy If diffx*diffx+diffy*diffy < friendsqrdistance vx -= (i.x - x) / Sqrt(sqrdistance) vy -= (i.y - y) / Sqrt(sqrdistance) End If Next End Method Method align() Local sumvx:Float Local sumvy:Float For Local i:=Eachin friendlist sumvx += i.vx sumvy += i.vy Next sumvx /= friendlist.Count sumvy /= friendlist.Count vx += (sumvx - vx) / alignspeed vy += (sumvy - vy) / alignspeed End Method Method move() x += vx y += vy angle = smoothrotate(x,y,angle,x+vx,y+vy,smoothturn) x += Cos(angle) * speed y += Sin(angle) * speed If x<0 Then x = 640 If y<0 Then y = 480 If x>640 Then x = 0 If y>480 Then y = 0 End Method Method getfriends() friendlist.Clear() For Local i:=Eachin boidlist Local diffx:Float=x-i.x Local diffy:Float=y-i.y If diffx*diffx+diffy*diffy < friendsqradius If i <> Self Then friendlist.AddLast(i) End If End If Next End Method Method updateall() For Local i:=Eachin boidlist i.update Next End Method Method drawall() For Local i:=Eachin boidlist i.draw Next End Method Method draw() SetColor 255,255,255 DrawCircle(x,y,10) End Method Function smoothrotate:Float(sourceX:Float,sourceY:Float,sourceAngle:Float,destX:Float,destY:Float,smooth:Float) ' Thanks to BlackSp1der on BB forums for this piece of code ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Local targetAngle:Float = ATan2(sourceY-destY,sourceX-destX) Local tempAngle:Float = targetAngle - Sgn(targetAngle-sourceAngle) * 360 If Abs(targetAngle-sourceAngle) > Abs(tempAngle-sourceAngle) Then targetAngle = tempAngle If sourceAngle <> targetAngle Then sourceAngle = sourceAngle - Sgn(targetAngle-sourceAngle) * (180-Abs(targetAngle-sourceAngle)) / (1+smooth) If sourceAngle >= 360 Then sourceAngle -= 360 Else If sourceAngle < 0 Then sourceAngle += 360 Return sourceAngle End Function End Class Global myobstacle:List<obstacle> Global boidlist:List<boid> = New List<boid> Class MyGame Extends App Field myboid:boid Method OnCreate() SetUpdateRate(60) myobstacle = New List<obstacle> For Local i:Int = 0 Until 10 myobstacle.AddLast(New obstacle(Rnd(640),Rnd(480))) Next myboid = New boid() myboid.create(20) End Method Method OnUpdate() myboid.updateall() If MouseDown(MOUSE_LEFT) Then myobstacle.AddLast(New obstacle(MouseX,MouseY)) If KeyHit(KEY_SPACE) Then For Local i:Int = 0 Until 10 myobstacle.AddLast(New obstacle(Rnd(640),Rnd(480))) Next End If End Method Method OnRender() Cls 0,0,0 SetColor 255,255,255 myboid.drawall() For Local i:=Eachin myobstacle i.draw Next SetColor 255,255,255 DrawText "Hold LMB to draw obstacles.",0,0 DrawText "Press space for random obstacles.",0,20 End Method End Class Function Main() New MyGame() End Function
Monkey-X - Beginners - 2D Vector Rotation - code example
Import mojo
Class vector
' A vector has a origin of 0,0. The length and direction
' is the x and y variables.
Field x:Float
Field y:Float
Method New(x:Float=0.0,y:Float=0.0)
' Fill in the x and y
Self.x = x
Self.y = y
End Method
' This method rotates the input vector by a value(degrees)
Method rotate:vector(v:vector,val:Int)
' create a temporary vector
Local u:vector = New vector()
' rotate the inputted vector and put the data in u.
u.x = v.x * Cos(val) - v.y * Sin(val)
u.y = v.x * Sin(val) + v.y * Cos(val)
' return the new vector
Return u
End Method
End Class
Class MyGame Extends App
' some local variables.
Field alienx:Float=100,alieny:Float=100
Field myvec:vector
Method OnCreate()
SetUpdateRate(60)
' create the new vector (2,2)
myvec = New vector(2,2)
End Method
Method OnUpdate()
End Method
Method OnRender()
Cls 0,0,0
SetColor 255,255,255
' Move the alien based on the vector's x,y
alienx+=myvec.x
alieny+=myvec.y
' rotate the vector.
myvec = myvec.rotate(myvec,10)
' draw the alien.
DrawCircle(alienx,alieny,10)
'
DrawText "2D Vector Rotation",0,0
End Method
End Class
Function Main()
New MyGame()
End Function
Friday, July 7, 2017
Monkey Getting started - MouseHit - code example
'import mojo needs to be called so that it recognizes the 'mojo commands. Import mojo Class MyGame Extends App Field timedown:Int Field mytext:String = "Press the mouse." Method OnCreate() 'This method is only run when the program starts SetUpdateRate(10) 'how many times should the screen be redrawn per second End Method Method OnUpdate() ' Run every frame(put keyinput ect. in here) timedown-=1 If timedown <= 0 Then timedown = 0 mytext = "Press the mouse" End If If MouseHit(MOUSE_LEFT) Then mytext = "The left mouse was last pressed." ; timedown=10 ' Flash does not recognize middle and right mouse buttons.... If MouseHit(MOUSE_RIGHT) Then mytext = "The Right mouse was last pressed."; timedown=10 If MouseHit(MOUSE_MIDDLE) Then mytext = "The Middle mouse was last pressed."; timedown=10 End Method Method OnRender() 'Drawing commands here. ' Clear the screen with color 0,0,0 Cls 0,0,0 ' Set the Color of the next drawing commands SetColor 255,255,255 ' Draw text to the screen. txt,x,y DrawText mytext,0,0 End Method End Class Function Main() New MyGame() End Function
Monkey Getting started - SetColor - code example
Import mojo
Class MyGame Extends App
Method OnCreate() 'This method is only run when the program starts
SetUpdateRate(10) 'how many times should the screen be redrawn per second
End Method
Method OnUpdate() ' Run every frame(put keyinput ect. in here)
End Method
Method OnRender() 'Drawing commands here.
' Clear the screen with color 0,0,0
Cls 0,0,0
' Set the Color of the next drawing commands
' red(0..255),green(0..255),blue(0..255)
SetColor 255,255,255
DrawText "This is text..",0,0
' Set the drawing color for the next drawing commands
SetColor 0,255,255
' Draw a rectangle
DrawRect 100,100,200,200
End Method
End Class
Function Main()
New MyGame()
End Function
Monkey-X - Fill Triangle with Bresenham Algorithm - code example
' ' Fill triangles using the bresenham algorithm ' Import mojo Class filledtriangle ' These variables are the points of ' the triangle. Field x1:Int,y1:Int Field x2:Int,y2:Int Field x3:Int,y3:Int ' This variable is the y of the triangle ' that has the lowest value. Field lowesty:Int ' This is the total height of the triangle. Field sizey:Int ' These arrays hold the x coordinates with ' which we draw the lines. Field lefty:Int[] Field righty:Int[] ' Here we create and draw the triangle. Method New(x1:Int,y1:int,x2:Int,y2:int,x3:int,y3:int) ' In order to draw below ZERO we add a value to the inputted ' coordinates. We decrease this amount when drawing the ' actual triangles on the canvas. Local offscreen:Int=10000 x1 += offscreen y1 += offscreen x2 += offscreen y2 += offscreen x3 += offscreen y3 += offscreen ' We need to know which coordinate has the lowest ' y value and we put that in the lowesty variable. 'find lowest If y1<y2 And y1<y3 Then lowesty = y1 If y2<y1 And y2<y3 Then lowesty = y2 If y3<y1 And y3<y2 Then lowesty = y3 ' We also need to know the total height of the ' triangle so we can create a array of that size ' where we store the left and right side line ' coordinates in. 'find height If y1>y2 And y1>y3 Then sizey = y1-lowesty If y2>y1 And y2>y3 Then sizey = y2-lowesty If y3>y1 And y3>y2 Then sizey = y3-lowesty ' ' If there is nothing to draw then ' exit this method. If sizey = 0 Then Return ' Create two arrays which will hold the coordinates ' for the lines inside the triangles. The x coordinates. lefty = New Int[sizey+1] righty = New Int[sizey+1] ' Here we fill the lefty and righty arrays with the ' x coordinates of the lines inside the triangles. bline(x1,y1,x2,y2) bline(x2,y2,x3,y3) bline(x1,y1,x3,y3) ' Here we draw the lines inside the triangles. Filling ' it. You can do per pixel for colloring ect. For Local y:Int=0 until sizey DrawLine(lefty[y]-offscreen,lowesty+y-offscreen,righty[y]-offscreen,lowesty+y-offscreen) Next End Method ' ' This is the bresenham algorithm. It is modified so ' it fills two arrays with the x coordinates of the ' lines inside the triangles. Method bline:Void(x4:Int,y4:Int,x5:Int,y5:Int) Local dx:Int, dy:Int, sx:Int, sy:Int, e:Int dx = Abs(x5 - x4) sx = -1 If x4 < x5 Then sx = 1 dy = Abs(y5 - y4) sy = -1 If y4 < y5 Then sy = 1 If dx < dy Then e = dx / 2 Else e = dy / 2 End If Local exitloop:Bool=False While exitloop = False ' Here we fill the left and right sides arrays. ' we draw lines between these later on to fill the triangle If lefty[y4-lowesty] = 0 Then 'If left not used then fill left lefty[y4-lowesty] = x4 Elseif righty[y4-lowesty] = 0 'if right not used then fill right righty[y4-lowesty] = x4 Else 'if both sides are filled If lefty[y4-lowesty] = x4 Then 'overwrite same value lefty[y4-lowesty] = x4 Else 'write new value righty[y4-lowesty] = x4 End If End If If x4 = x5 If y4 = y5 exitloop = True End If End If If dx > dy Then x4 += sx ; e -= dy If e < 0 Then e += dx ; y4 += sy Else y4 += sy ; e -= dx If e < 0 Then e += dy ; x4 += sx Endif Wend End Method End Class Class MyGame Extends App ' cnt is used for the seed Field cnt:Int ' mytriangle is used to draw a triangle Field mytriangle:filledtriangle Method OnCreate() SetUpdateRate(10) End Method Method OnUpdate() ' If pressed space/touch/lmb then new set of triangles If KeyHit(KEY_SPACE) Or MouseHit(MOUSE_LEFT) Then cnt+=1 End Method Method OnRender() Cls 0,0,0 ' Always draw the same using this seed Seed = cnt ' Draw 100 triangles For Local i:=0 Until 100 Local x1:Int=Rnd(0,DeviceWidth) Local y1:Int=Rnd(0,DeviceHeight) Local x2:Int=x1+Rnd(-80,80) Local y2:Int=y1+Rnd(-80,80) Local x3:Int=x1+Rnd(-80,80) Local y3:Int=y1+Rnd(-80,80) SetColor(Rnd(255),Rnd(255),Rnd(255)) mytriangle = New filledtriangle(x1,y1,x2,y2,x3,y3) Next ' Draw some text SetColor 255,255,255 DrawText("Press the space bar/lmb/touch to draw new set.",0,0) End Method End Class Function Main() New MyGame() End Function
Subscribe to:
Posts (Atom)