Sunday, November 12, 2017

Monkey-X - Generator - Cartoon Clouds - code example


 Import mojo  
   
 Class cloud  
      Field px:Float,py:Float  
      Field pw:Int,ph:Int  
      Field mx:Float  
      Field sw:Int  
      Method New(x:Int,y:Int,w:Int,h:Int,sw:Int)  
           px = x  
           py = y  
           pw = w  
           ph = h  
           Self.sw = sw  
           mx = Rnd(0.05,0.2)  
      End Method  
      Method update()  
           px += mx  
           If px > sw+pw Then px = 0-(pw*2)  
      End Method  
      ' This method draws a cloud/  
      ' at x,y with width w and height h  
      Method draw()  
             
           ' Draw 7 plumps (go around in a circle)  
           For Local angle:Int=0 Until 360 Step 360/7  
                Local x2:Float=Cos(angle)*pw  
                Local y2:Float=Sin(angle)*ph  
                SetColor 0,0,0  
                DrawOval(x2+px,y2+py,pw,ph)  
                SetColor 255,255,255  
                DrawOval(x2+px+4,y2+py+4,pw-8,ph-8)  
           Next  
           ' Draw a white oval to erase the center of the cloud  
           SetColor 255,255,255  
           DrawOval(px-pw/2,py-ph/2,pw+pw,ph+ph)  
      End Method            
   
 End Class  
   
 Class MyGame Extends App  
      Field mycloud:List<cloud> = New List<cloud>  
   Method OnCreate()  
        SetUpdateRate(60)  
        Seed = GetDate[4]*GetDate[5]  
        For Local i:Int = 0 Until 15  
             mycloud.AddLast(New cloud(Rnd(-DeviceWidth*.5,DeviceWidth),Rnd(DeviceHeight),Rnd(30,130),Rnd(20,50),DeviceWidth))  
        Next  
   End Method  
   Method OnUpdate()   
        For Local i:=Eachin mycloud  
             i.update()  
        Next  
   End Method  
   Method OnRender()  
        Cls 0,0,255  
        For Local i:=Eachin mycloud  
             i.draw()  
        Next  
   End Method  
   
 End Class  
   
   
 Function Main()  
   New MyGame()  
 End Function  

Monkey-X - Generator - 10 Print Chr - code example


 Import mojo  
   
 Class MyGame Extends App  
      Field x:Int,y:Int  
      Field spacing:Int=10  
      Field map:Int[][]  
   Method OnCreate()  
        SetUpdateRate(60)  
        map = New Int[100][]  
        For Local i:Int=0 Until 100  
                map[i] = New Int[100]  
        Next  
        makemaze()  
   End Method  
   Method OnUpdate()   
        If KeyHit(KEY_SPACE) Or MouseHit(MOUSE_LEFT)  
             makemaze()  
        End If  
   End Method  
   Method OnRender()  
        Cls 0,0,0  
           drawmaze()  
           DrawText "Press Space or Mouse for new maze",0,0  
   End Method  
      Method drawmaze()            
        For Local y:Int=0 Until 100  
        For Local x:Int=0 Until 100  
             Select map[x][y]  
                  Case 0  
                       DrawLine x*10,y*10,x*10+10,y*10+10  
                  Case 1  
                       DrawLine x*10+10,y*10,x*10,y*10+10  
             End Select  
        Next  
        Next  
      End Method  
      Method makemaze()  
        For Local y:Int=0 Until 100  
        For Local x:Int=0 Until 100  
             If Rnd(1)<.5 Then map[x][y] = 1 Else map[x][y] = 0  
        Next  
        Next  
   End Method  
 End Class  
   
   
 Function Main()  
   New MyGame()  
 End Function  

Monkey-X - Beginners - Class in array - code example

 Import mojo  
   
 '  
 ' This is our enemy class  
 '   
 Class enemy  
      Field px:Int,py:Int  
      Method New(x:Int,y:Int)  
           Self.px = x  
           Self.py = y  
      End Method  
      Method move(x:Int,y:Int)  
           px += x  
           py += y  
      End Method  
 End Class  
   
 Class MyGame Extends App  
      ' How many enemies are there  
      Field numenemies:Int=10  
      ' Set up the array using the enemy class  
      Field myenemy:enemy[]  
   Method OnCreate()  
        ' Create the enemies in the array  
        myenemy = New enemy[numenemies]  
        For Local i:Int=0 Until numenemies  
             myenemy[i] = New enemy(Rnd(DeviceWidth()),Rnd(DeviceHeight))  
        Next  
   End Method  
   Method OnUpdate()   
   End Method  
   Method OnRender()  
     Cls 0,0,0       
     SetColor 255,255,255  
     ' Loop through all array containers (numenemies)  
     ' and draw them.  
     For Local i:=Eachin myenemy  
          DrawRect i.px,i.py,32,32  
     Next  
       
     ' We can acces arrays directly and call/modify anything inside it.  
     myenemy[0].move(5,0)  
     If myenemy[0].px > DeviceWidth Then myenemy[0].px = -10  
   End Method  
   
 End Class  
   
   
 Function Main()  
   New MyGame()  
 End Function  

Monkey-X - Lerp - Linear Interpolation - patrolling - code example


 Import mojo  
   
 Class MyGame Extends App  
      Field enemyx:Int,enemyy:Int  
      Field startx:Int=100,starty:Int=100  
      Field destx:Int=320,desty:Int=230  
      Field percentage:Float=0 ' how far in the path are we  
      Field stp:Float=0.01 ' how fast do we move  
   Method OnCreate()  
     SetUpdateRate(60) ' Fps  
           enemyx = startx  
           enemyy = starty            
   End Method  
   Method OnUpdate()   
        ' Get our new x and y position  
        enemyx = lerp(percentage,startx,destx)  
        enemyy = lerp(percentage,starty,desty)  
        ' Set the new position         
        percentage+=stp  
        ' Keep inside the value of 0.0 and 1.0  
        If percentage<=0 Or percentage>=1 Then stp=-stp  
   End Method  
   Method OnRender()  
     Cls 0,0,0       
     SetColor 255,255,255  
     ' Draw the enemy sprite  
     DrawRect enemyx,enemyy,32,32  
     '     
     DrawText "Lerp(Linear Interpolation) Patrolling - example",0,0  
   End Method  
      ' Percentage 0 to 1 returns number between a and b  
      Function lerp:Int(t:Float , a:Float, b:Float)   
           Return a + t * (b - a)  
      End Function   
 End Class  
   
   
 Function Main()  
   New MyGame()  
 End Function  

Friday, November 10, 2017

Monkey-X - Generator - Simple 2d Pixelart tree - code example


 Import mojo  
   
 Class tree  
      Field px:Int,py:Int  
      Field pw:Float,ph:Float  
      Field mapone:Int[][]  
      Field treecolor1:Int=Rnd(230,255)  
      Field treecolor1r:Int=Rnd(50,200)  
      Field treecolor2:Int=Rnd(190,220)  
      Field treecolor3:Int=Rnd(130,180)  
      Field treecolor4:Int=Rnd(70,120)  
      Field basecolor1:Int=150  
      Field basecolor2:Int=190  
      Field basecolor3:Int=220  
      Method New(x:Int,y:Int,w:Int,h:Int)  
           If Rnd(3)<2 Then treecolor1r = 0  
           px = x  
           py = y  
           pw = w  
           ph = h  
           mapone = New Int[w][]  
           For Local i:Int=0 Until w  
                mapone[i] = New Int[h]  
           Next  
           maketree()  
      End Method  
      Method maketree()  
           Local mx:Float=0.05  
           Local my:Float=.1  
           Local y:Float=1  
           Local x:Float=pw/2+1  
           Local base:Float=0  
           Local bounce:Float=.1  
           Local col:Int  
           Local num:Float=2  
           Local stap:Float=Rnd(0.001,0.005)  
           Local stap2:Float=Rnd(0.01,0.2)  
           Local stap3:Float=Rnd(0.5,1.5)  
           ' Place two black pixels at the top of the tree  
           mapone[x-1][0] = 1  
           mapone[x-2][0] = 1  
           ' create the tree  
           While (y+5)<=(ph-(ph/20))   
                y+=my  
                x+=mx  
                ' stay inside the image  
                If x>=pw Then x=pw-2  
                If x<=0 Then x=0  
                ' change color of the tree depending  
                ' on the current y location  
                If y<ph/1.4 Then col = treecolor4                                                    
                If y<ph/1.6 Then col = treecolor3  
                If y<ph/1.9 Then col = treecolor2  
                If y<ph/4 Then col = treecolor1  
                ' fill the current line  
                filltoleft(x,y,pw-x,col)  
                ' black pixel to the left and right  
                mapone[x][y] = 1  
                mapone[pw-x][y] = 1                      
                ' next step in the tree shape  
                mx-=stap  
                If y<ph/1.45 Then   
                     If mx<0   
                          If x < ((pw/2)+num) Then mx=bounce ; bounce+=stap2 ; num+=stap3  
                     End If                      
                Else       
                     If mx<0       
                     If x<((pw/2)+num) Then bounce=.1 ; mx=bounce ; num-=stap3  
                     Endif  
                End If  
           Wend  
           ' Make sure the bottom of the tree is also drawn  
           filltoleft(x,y,pw-x,1)  
           ' Make the tree trunk  
           maketreebase()  
      End Method  
      '  
      ' Fill from x to tox on y line using col(or)  
      ' We go from right to left and fill the line with   
      ' a number. (tree inside color)  
      '  
      Method filltoleft(x:Int,y:Int,tox:Int,col:Int)            
           Local ls:Int=(pw/2)  
           Local len1:Int=(x-ls)/2  
           Local len2:Int=(x-ls)/1.7            
           For Local x2:Int=x To tox Step -1  
                mapone[x2][y] = col  
                If col = treecolor2 Then  
                If Rnd(4) < 1 And distance(x2,0,tox,0) < len1 And y<ph/2 Then mapone[x2][y] = treecolor1  
                If Rnd(4) < 1 And distance(x2,0,x,0)< len1 And y<ph/2 Then mapone[x2][y] = treecolor1  
                If Rnd(2)<1.3 And distance(x2,0,ls-len1,0) < 2 And y<ph/2 Then mapone[x2][y] = treecolor1  
                If Rnd(2)<1.3 And distance(x2,0,ls+len1,0) < 2 And y<ph/2 Then mapone[x2][y] = treecolor1  
                End If  
                If col=treecolor1  
                If Rnd(2) < 1 And y>5 And distance(x2,0,ls,0) < 3 Then mapone[x2][y] = treecolor2  
                End If  
                If col=treecolor3  
                If Rnd(2)<1.3 And distance(x2,0,ls,0) < len2 And y<ph/1.8 Then mapone[x2][y] = treecolor2  
                End If  
                If col=treecolor4  
                If Rnd(2)<1.3 And distance(x2,0,ls,0) < len2 And y<ph/1.45 Then mapone[x2][y] = treecolor3  
                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   
      Method maketreebase()  
           ' treebase  
           For Local y:Int=ph-(ph/5) Until ph  
           For Local x:Int=(pw/2)-(pw/8) Until (pw/2)+(pw/8)  
                If x<0 Or y<0 Or x>=pw Or y>= ph Then Continue  
                mapone[x][y] = basecolor1  
                If x=(pw/2)-(pw/8) Then mapone[x][y] = 1  
                If x=(pw/2)+(pw/8)-1 Then mapone[x][y]=1  
                If y=ph-1 Then mapone[x][y]=1  
           Next  
           Next  
           For Local y:Int=ph-(ph/5) Until ph-(ph/5)  
           For Local x:Int=(pw/2)-(pw/8) Until (pw/2)+(pw/8)  
                If x<0 Or y<0 Or x>=pw Or y>= ph Then Continue  
                mapone[x][y] = 1  
           Next  
           Next  
   
           ' tree base center lighting  
           For Local y:Int=ph-(ph/7) Until ph-1  
           For Local x:Int=(pw/2)-(pw/30) Until (pw/2)+(pw/30)  
                If x<0 Or y<0 Or x>=pw Or y>= ph Then Continue  
                mapone[x][y] = basecolor3  
           Next  
           Next  
           For Local y:Int=ph-(ph/7) Until ph-1  
           For Local x:Int=(pw/2) Until (pw/2)+(pw/30)  
                If x<0 Or y<0 Or x>=pw Or y>= ph Then Continue  
                mapone[x][y] = basecolor2  
           Next  
           Next  
           'Remove two black pixels from the bottom of the treebase  
           mapone[(pw/2)-(pw/8)][ph-1] = 0  
           mapone[(pw/2)+(pw/8)-1][ph-1] = 0  
   
   
      End Method  
        
      Method draw()  
           For Local y:Int=0 Until ph  
           For Local x:Int=0 Until pw  
                If mapone[x][y] = 0 Then Continue  
                Select mapone[x][y]  
                     Case 1  
                          SetColor 0,0,0                           
                     Case treecolor1  
                          SetColor treecolor1r/2,treecolor1,0  
                     Case treecolor2  
                          SetColor treecolor1r/1.5,treecolor2,0  
                     Case treecolor3  
                          SetColor treecolor1r/1.2,treecolor3,0  
                     Case treecolor4  
                          SetColor treecolor1r,treecolor4,0  
                     Case basecolor1  
                          SetColor basecolor1,basecolor1/2,0  
                     Case basecolor2  
                          SetColor basecolor2,basecolor2/2,0  
                     Case basecolor3  
                          SetColor basecolor3,basecolor3/2,0                           
                End Select  
                DrawRect px+(x*1),py+(y*1),1,1  
           Next  
           Next  
      End Method  
 End Class  
   
 Class MyGame Extends App  
      Field mytree:List<tree>  
      Field time:Int=Millisecs()  
      Field hw:Int=48,hh:Int=64  
   Method OnCreate()  
        Seed = GetDate[4]*GetDate[5]  
     SetUpdateRate(1)  
           maketrees()  
   End Method  
   Method OnUpdate()      
           If KeyHit(KEY_SPACE) Or Millisecs() > time  
                time=Millisecs()+2000  
                maketrees  
           End If  
   End Method  
   Method OnRender()  
     Cls 0,0,0   
     SetColor 50,125,235      
     DrawRect 0,0,DeviceWidth,150+hh  
           SetColor 50,155,255  
     DrawRect 0,100,DeviceWidth,(150+hh)-100  
   
     SetColor 5,250,5  
     DrawRect 0,150+hh,DeviceWidth,DeviceHeight-(150+hh)  
     SetColor 125,250,125  
     DrawRect 0,150+hh,DeviceWidth,2  
             
           For Local i:=Eachin mytree  
          i.draw()  
     Next  
          
   End Method  
   Method maketrees()         
        mytree = New List<tree>  
        For Local x:Int=0 Until DeviceWidth Step 64  
             If Rnd(3)<2 Then mytree.AddLast(New tree(x,150,48,64))  
        Next  
        Local sy:Int=0  
           For Local i:Int=0 Until 35  
          mytree.AddLast(New tree(Rnd(DeviceWidth),150+sy,48,64))  
          sy+=8  
           Next  
   End Method  
 End Class  
   
   
 Function Main()  
   New MyGame()  
 End Function  

Thursday, November 9, 2017

Monkey-X - Generator - 2d Houses (town) - code example


 Import mojo  
   
 Class building  
      Field px:Int,py:Int  
      Field totalwidth:Int  
      Field blockhouse:Int=1  
      Field blockdoor:Int=2  
      ' For collision (enter/flee in home/shop)  
      Field doorx:Int,doory:Int  
      Field doorwidth:Int,doorheight:Int  
      Field blocksmallwindow:Int=3  
      Field blockwidewindow:Int=4  
      Field blockcrateleft:Int=5  
      Field blockcrateright:Int=6  
      Field blockiceboxleft:Int=7  
      Field blockiceboxright:Int=7  
      Field blocktoiletleft:Int=8  
      Field blocktoiletright:Int=9  
      Field blockfrontcrate:Int=10  
      Field blockrooftop:Int=11  
      Field blockchimney:Int=12  
      Field blockshopsign:Int=13  
      Field houselayer:Int[]=New Int[3] 'base blocks  
      Field rooftoplayer:Int[]=New Int[3]  
      Field chimneylayer:Int[]=New Int[3]  
      Field doorlayer:Int[] = New Int[3]  
      Field windowlayer:Int[] = New Int[3] '011010'  
      Field housesidelayer:Int[] = New Int[2]  
      Field shopsignlayer:Int[] = New Int[3]  
      Field frontlayer:Int[] = New Int[6]  
      Method New(x:Int,y:Int,w:Int,isshop:Bool)  
           px = x  
           py = y  
           totalwidth = w  
           makehouse(w,isshop)  
      End Method  
      Method makehouse(w:Int,isshop:Bool)  
   
   
   
           ' Make the base house blocks  
           For Local i:Int=0 Until w  
                houselayer[i] = blockhouse  
           Next  
           ' Create the items at the side of the houses  
           If Rnd(10)<5  
                ' add to which side(s)  
                Local sides:String="left"                 
                If Rnd(10)<3 Then sides="right"   
                If Rnd(10)<3 Then sides="both"  
                ' Add items to side(s)  
                If sides="left" Or sides="both" Then   
                     housesidelayer[0] = blocktoiletleft  
                     If Rnd(10)<3 Then   
                          housesidelayer[0] = blockcrateleft  
                     End If  
                     If Rnd(10)<3 Then  
                          housesidelayer[0] = blockiceboxleft  
                     End If       
                Endif                      
                If sides="right" Or sides="both" Then   
                     housesidelayer[1] = blocktoiletright  
                     If Rnd(10)<3 Then   
                          housesidelayer[1] = blockcrateright  
                     End If  
                     If Rnd(10)<3 Then  
                          housesidelayer[1] = blockiceboxright  
                     End If       
                Endif                      
           End If  
           'Create the crates at the front of the house  
           For Local i:Int= 0 Until (w*2)-2  
                If Rnd(10)<2 Then  
                     frontlayer[i] = blockfrontcrate  
                End If  
   
           Next  
           'Create windows  
           Select w  
                Case 2  
                     windowlayer[0] = blocksmallwindow  
                Case 3  
                     windowlayer[0] = blockwidewindow  
           End Select  
           ' create door  
           Select w  
                Case 1  
                     doorlayer[0] = blockdoor  
                     If isshop Then shopsignlayer[0] = blockshopsign  
                Case 2  
                     doorlayer[1] = blockdoor  
                     If isshop Then shopsignlayer[1] = blockshopsign                      
                Case 3  
                     doorlayer[2] = blockdoor  
                     If isshop Then shopsignlayer[2] = blockshopsign  
           End Select  
           ' rooftop  
           Select w  
                Case 1  
                     rooftoplayer[0] = blockrooftop  
                Case 2  
                     rooftoplayer[0] = blockrooftop  
                     rooftoplayer[1] = blockrooftop  
                Case 3  
                     rooftoplayer[0] = blockrooftop  
                     rooftoplayer[1] = blockrooftop  
                     rooftoplayer[2] = blockrooftop  
           End Select  
           ' chimney  
           Select w  
                Case 1  
                     chimneylayer[0] = blockchimney  
                Case 2  
                     chimneylayer[Rnd(0,2)] = blockchimney  
                Case 3  
                     chimneylayer[Rnd(0,3)] = blockchimney  
           End Select  
        
      End Method  
      Method draw(w:Int,h:Int)  
           Local bw:Int=w  
           Local bh:Int=h  
           ' Draw the house blocks  
           For Local i:Int=0 Until 3       
                If houselayer[i] = blockhouse Then  
                     SetColor 150,140,150  
                     DrawRect px+(i*bw),py,bw+1,bh  
   
                     SetColor 200,200,200  
                     DrawRect px+(i*bw),py,bw,bh  
                     'SetColor 230,230,230  
                     'shadow top  
                     SetColor 60,60,60  
                     DrawRect px+(i*bw),py,bw,bh/15  
                     'shadow bottom  
                     SetColor 150,150,150  
                     DrawRect px+(i*bw),py+bh/1.1,bw,bh/8  
                     'highlight left  
                     If i=0   
                          SetColor 220,220,220  
                          DrawRect px+(i*bw),py,1,bh/3  
                     Endif  
                End If  
           Next  
           ' Draw the rooftop  
           For Local i:Int=0 Until 3       
                If rooftoplayer[i] = blockrooftop Then  
                     'SetColor 200,100,100  
                     SetColor 170,70,60  
                     DrawRect px+(i*bw),py-(bh/1.5),bw,bh-(bh/3)  
                     ' Bottom shade  
                     SetColor 130,50,30  
                     'SetColor 200,100,100  
                     DrawRect px+(i*bw),py-(bh/8),bw,bh/8  
                     ' top shade  
                     SetColor 190,90,80  
                     DrawRect px+(i*bw),py-(bh/1.5),bw,1  
                     ' top shade  
                     If i=0  
                     'horizontal  
                     SetColor 220,120,110  
                     DrawRect px+(i*bw),py-(bh/1.5),bw/2,1  
                     'vertical  
                     SetColor 200,100,100  
                     DrawRect px+(i*bw),py-(bh/1.5),1,bh/3  
                     End If  
                End If  
           Next  
   
           ' Draw the chimney  
           For Local i:Int=0 Until 3       
                If chimneylayer[i] = blockchimney Then  
                     SetColor 100,100,100  
                     DrawRect px+(i*bw)+(bw/4),py-(bh/1.2),bw/2.5,bh/4  
                     'chimney highlight  
                     SetColor 140,130,120  
                     DrawRect px+(i*bw)+(bw/4),py-(bh/1.2),bw/6,1  
   
                End If  
           Next            
           'Draw the windows  
           For Local i:Int=0 Until 3  
                If windowlayer[i] = blocksmallwindow  
                     SetColor 0,100,200  
                     DrawRect px+(i*bw)+(bw/3),py+(bh/5),bw-(bw/3),bh-(bh/2.5)  
                     ' light bottom  
                     SetColor 0,115,210  
                     DrawRect px+(i*bw)+(bw/3),py+(bh/2),bw-(bw/3),(bh/3.3)  
                     ' dark bottom  
                     SetColor 180,125,20  
                     DrawRect px+(i*bw)+(bw/3),py+(bh*.7),bw-(bw/3),(bh/8.3)  
   
                End If  
                If windowlayer[i] = blockwidewindow  
                     SetColor 0,100,200  
                     DrawRect px+(i*bw)+(bw/3),py+(bh/5),(bw*2)-(bw/3),bh-(bh/2.5)  
                     'light bottom  
                     SetColor 0,115,210  
                     DrawRect px+(i*bw)+(bw/3),py+(bh/2),(bw*2)-(bw/3),(bh/3.3)  
                     'dark bottom  
                     SetColor 180,125,20  
                     DrawRect px+(i*bw)+(bw/3),py+(bh*.7),(bw*2)-(bw/3),(bh/8.3)  
   
                End If  
           Next  
           ' Draw the door  
           For Local i:Int=0 Until 3  
                If doorlayer[i] = blockdoor  
                     SetColor 100,50,50  
                     If shopsignlayer[i] = blockshopsign  
                          SetColor 250,200,50  
                     End If  
                     DrawRect px+(i*bw)+(bw/5),py+(bh/5),bw-(bw/2),bh-(bh/4)  
                     ' doorknob  
                     SetColor 200,210,210  
                     DrawRect px+(i*bw)+(bw/2),py+(bh/1.7),(bw/9),(bh/9)  
                     'numberplate  
                     SetColor 200,250,250  
                     DrawRect px+(i*bw)+(bw/1.3),py+(bh/3),(bw/9),(bh/9)  
                     SetColor 10,50,50  
                     DrawRect px+(i*bw)+(bw/1.25),py+(bh/2.8),(bw/18),(bh/14)  
   
                End If  
           Next  
           ' Draw the sides  
           If housesidelayer[0] = blocktoiletleft Then drawtoilet(px,py,bw,bh,"left")  
           If housesidelayer[1] = blocktoiletright Then drawtoilet(px,py,bw,bh,"right")  
           If housesidelayer[0] = blockcrateleft Then drawsidecrate(px,py,bw,bh,"left")  
           If housesidelayer[1] = blockcrateright Then drawsidecrate(px,py,bw,bh,"right")  
           If housesidelayer[0] = blockiceboxleft Then drawsideicebox(px,py,bw,bh,"left")  
           If housesidelayer[1] = blockiceboxright Then drawsideicebox(px,py,bw,bh,"right")  
             
           'Draw the crates at the front of the house  
           For Local i:Int=0 Until (totalwidth*2)-2  
                If frontlayer[i] = blockfrontcrate  
                     SetColor 100,50,50  
                     DrawRect px+((bw/2)*i),py+bh/1.2,bw/4,bh/6.4  
                End If  
           Next  
             
           'Draw the shop sign  
           For Local i:Int=0 Until totalwidth  
                If shopsignlayer[i] = blockshopsign  
                     SetColor 255,40,30  
                     Local x:Int=px+(bw*i)-bw/8  
                     Local y:Int=py-bh/5  
                     DrawRect x,y,bw*1.2,bh/3  
                     SetColor 255,255,255  
                     'DrawText "Shop X",x+5,y+5  
                     DrawRect x+bh/10,y+bh/12,4,4  
                End If  
           Next  
      End Method  
      Method drawtoilet(x:Int,y:Int,w:Int,h:Int,side:String)  
           If side = "left"  
           Local ltx:Float=x-w/2  
           Local lty:Float=y+(h/4)  
           Local rtx:Float=ltx+(w/2)  
           Local rty:Float=lty  
           Local lbx:Float=ltx  
           Local lby:Float=lty+(h-h/4)  
           Local rbx:Float=ltx+(w/2)  
           Local rby:Float=lby  
   
           Local toil:Float[8]  
           toil[0] = ltx  
           toil[1] = lty-(h/6)  
           toil[2] = rtx  
           toil[3] = rty  
           toil[4] = rbx  
           toil[5] = rby  
           toil[6] = lbx  
           toil[7] = lby  
             
           SetColor 150,50,50  
           DrawPoly(toil)  
             
           'DrawRect x-w/2,y+10,w/2,h-10  
           Elseif side="right"  
           Local ltx:Float=(x)+(totalwidth*w)  
           Local lty:Float=y+(h/4)  
           Local rtx:Float=ltx+(w/2)  
           Local rty:Float=lty  
           Local rbx:Float=ltx+(w/2)  
           Local rby:Float=rty+(h-h/4)  
           Local lbx:Float=ltx  
           Local lby:Float=rby  
           SetColor 150,50,50  
           Local box:Float[8]  
           box[0] = ltx  
           box[1] = lty  
           box[2] = rtx  
           box[3] = rty-(h/6)  
           box[4] = rbx  
           box[5] = rby  
           box[6] = lbx  
           box[7] = lby  
           DrawPoly(box)  
   
 '          SetColor 100,50,50  
 '          DrawRect (x)+totalwidth*w,y+10,w/2,h-10  
           End If  
      End Method  
      Method drawsidecrate(x:Int,y:Int,w:Int,h:Int,side:String)  
           If side = "left"  
           ' pipe  
           SetColor 120,120,120  
           DrawRect x-w/8,y,w/8,h  
           'barrel  
           SetColor 100,50,50  
           DrawRect x-w/3,y+(h/1.5),w/3,h-(h/1.5)  
           Elseif side="right"  
           'pipe  
           SetColor 120,120,120  
           DrawRect (x)+totalwidth*w,y,w/8,h  
           'barrel  
           SetColor 100,50,50  
           DrawRect (x)+totalwidth*w,y+(h/1.5),w/3,h-(h/1.5)  
           End If  
      End Method  
      Method drawsideicebox(x:Int,y:Int,w:Int,h:Int,side:String)  
           If side = "left"  
           Local ltx:Float=x-w/2  
           Local lty:Float=y+(h/1.5)  
           Local rtx:Float=ltx+(w/2)  
           Local rty:Float=lty  
           Local lbx:Float=ltx  
           Local lby:Float=lty+(h-h/1.5)  
           Local rbx:Float=ltx+(w/2)  
           Local rby:Float=lby  
           SetColor 200,200,200  
           Local box:Float[8]  
           box[0] = ltx  
           box[1] = lty+(h/6)  
           box[2] = rtx  
           box[3] = rty  
           box[4] = rbx  
           box[5] = rby  
           box[6] = lbx  
           box[7] = lby  
           'DrawRect ltx,lty,w/2,h-(h/1.5)  
           DrawPoly(box)  
           Elseif side="right"  
           Local ltx:Float=(x)+(totalwidth*w)  
           Local lty:Float=y+(h/1.5)  
           Local rtx:Float=ltx+(w/2)  
           Local rty:Float=lty  
           Local rbx:Float=ltx+(w/2)  
           Local rby:Float=rty+(h-h/1.5)  
           Local lbx:Float=ltx  
           Local lby:Float=rby  
           SetColor 200,200,200  
           Local box:Float[8]  
           box[0] = ltx  
           box[1] = lty  
           box[2] = rtx  
           box[3] = rty+h/6  
           box[4] = rbx  
           box[5] = rby  
           box[6] = lbx  
           box[7] = lby  
           DrawPoly(box)  
           'DrawRect (x)+totalwidth*w,y+(h/1.5),w/2,h-(h/1.5)  
           End If  
      End Method  
   
 End Class  
   
 Class MyGame Extends App  
      Field mybuilding:List<building>  
      Field time:Int=Millisecs()  
      Field hw:Int=48,hh:Int=64  
   Method OnCreate()  
        Seed = GetDate[4]*GetDate[5]  
     SetUpdateRate(2)  
           makehouses()  
   End Method  
   Method OnUpdate()      
           If KeyHit(KEY_SPACE) Or Millisecs() > time  
                time=Millisecs()+2000  
                makehouses  
           End If  
   End Method  
   Method OnRender()  
     Cls 0,0,0   
     SetColor 50,155,255  
     DrawRect 0,0,DeviceWidth,150+hh  
     SetColor 50,125,235  
     DrawRect 0,100,DeviceWidth,(150+hh)-100  
   
     SetColor 5,250,5  
     DrawRect 0,150+hh,DeviceWidth,DeviceHeight-(150+hh)  
     SetColor 125,250,125  
     DrawRect 0,150+hh,DeviceWidth,2  
             
           For Local i:=Eachin mybuilding  
          i.draw(hw,hh)  
     Next  
          
   End Method  
   Method makehouses()         
        mybuilding = New List<building>  
        hw = Rnd(20,50)  
        hh = hw  
        Local st:Int=hw*4  
        Local x:Int=0  
        While x<DeviceWidth  
               
                Local z1:Bool  
                If Rnd(5)<1 Then z1 = True  
                Local w:Int = Rnd(1,4)  
                st = hw*(w+2)  
 '         mybuilding = New building(x,150,Rnd(1,4),z1)  
          mybuilding.AddLast(New building(x,150,w,z1))  
          x+=st  
           Wend  
   End Method  
 End Class  
   
   
 Function Main()  
   New MyGame()  
 End Function  

Saturday, November 4, 2017

Monkey-X - Generator - 2D Fantasy maps (zelda ish) - code example


 ' Based somewhat on http://www.squidi.net/three/entry.php?id=164  
   
 Import mojo  
   
 Class map  
      Field sw:Int,sh:Int  
      Field tw:Float,th:Float  
      Field mw:Int,mh:Int  
      Field map:Int[][]  
      Field grassmap:Int[][]  
      Field bridgemap:Int[][]  
      Field tileroad:Int=999  
      Field numzones:Int  
      Method New(sw:Int,sh:Int,mw:Int,mh:Int,numzones:Int)  
           Self.numzones = numzones  
           Self.sw = sw  
           Self.sh = sh  
           Self.mw = mw  
           Self.mh = mh  
           Self.tw = Float(sw) / Float(mw)  
           Self.th = Float(sh) / Float(mh)            
           map = New Int[mw][]  
           grassmap = New Int[mw][]            
           bridgemap = New Int[mw][]  
           For Local i:Int=0 Until mw  
                map[i] = New Int[mh]  
                grassmap[i] = New Int[mh]  
                bridgemap[i] = New Int[mh]                 
           Next  
           createmap()  
      End Method  
      Method createmap()  
           'Create a number of zones (area's)  
           For Local zone:Int=0 Until numzones  
                map[Rnd(mw)][Rnd(mh)] = zone+1  
           Next  
           'Grow the zones  
           Local cangrow:Bool=True  
           Local mx:Int[]=[-1,0,1,0]  
           Local my:Int[]=[-1,0,0,1]  
           While cangrow=True  
                Local x:Int=Rnd(mw)  
                Local y:Int=Rnd(mh)  
                If map[x][y] > 0  
                     Local tile:Int=map[x][y]  
                     For Local i:Int=0 Until mx.Length  
                          Local x2:Int=mx[i]+x  
                          Local y2:Int=my[i]+y  
                          If x2<0 Or y2<0 Or x2>=mw Or y2>=mh Then Continue  
                          If Rnd(10)<2 And map[x2][y2] = 0  
                               map[x2][y2] = tile  
                          End If  
                     Next  
                End If  
                ' Every now and then check if every spot is taken  
                If Rnd(mw)<mw/10  
                     cangrow = False  
                     For Local y2:Int=0 Until mh  
                     For Local x2:Int=0 Until mw  
                          If map[x2][y2] = 0 Then cangrow = True;Exit  
                     Next  
                     Next  
                End If                 
           Wend  
           ' Create the roads  
           For Local y:Int=0 Until mh  
           For Local x:Int=0 Until mw  
                Local t:Int=map[x][y]  
                If x+1 < mw And map[x+1][y] <> t And grassmap[x+1][y] = 0 Then grassmap[x][y] = 1  
                If y+1 < mh And map[x][y+1] <> t And grassmap[x][y+1] = 0 Then grassmap[x][y] = 1  
                If x+1 < mw And y+1 < mh And map[x+1][y+1] <> t And grassmap[x+1][y+1] = 0 Then grassmap[x][y] = 1  
           Next  
           Next  
           'create the bridges  
           For Local y:Int=0 Until mh  
           For Local x:Int=0 Until mw  
                If grassmap[x][y] <> 1 Then Continue  
                Local cnt:Int=0  
                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>=mw Or y2>=mh Then Continue  
                     If map[x2][y2] >= numzones/3 Then cnt+=1  
                Next  
                Next  
                If cnt=0 Then bridgemap[x][y] = 1  
           Next  
           Next  
      End Method  
      Method draw()  
           ' map pass 1            
           For Local y:Int=0 Until mh  
           For Local x:Int=0 Until mw  
                If map[x][y] = 0 Then Continue                 
                Local x2:Int = x*tw  
                Local y2:Int = y*th  
                If map[x][y] < numzones/3 Or map[x][y] = 1 Then  
                ' water  
                SetColor 44,140,200  
                DrawRect x2,y2,tw+1,th+1  
                SetColor 46,165,225  
                DrawOval x2+tw/3,y2+th/5,tw/4,th/2  
                SetColor 56,195,255  
                DrawOval x2+tw/3,y2+th/4,tw/5,th/7  
   
                Else  
                'grass  
                SetColor 160,200,105  
                DrawRect x2,y2,tw+1,th+1  
                'treebase dark  
                SetColor 10,45,0  
                DrawOval x2+tw/3,y2+th/2,tw/2,th/1.5  
   
                'treebase light  
                SetColor 200,55,0  
                DrawOval x2+tw/2.2,y2+th/2,tw/4,th/1.5  
                ' tree top dark                 
                SetColor 0,55,0  
                DrawOval x2+tw/8,y2+th/10,tw/1.1,th/1.3  
                ' tree top   
                SetColor 0,190,0  
                DrawOval x2+tw/8+1,y2+th/10,tw/1.2-2,th/1.3  
                  
   
                ' highlight top   
                SetColor 200,255,200  
                DrawOval x2+tw/4+1,y2+th/5,tw/3,th/3  
                  
                End If  
   
           Next  
           Next  
           'grass  
           For Local y:Int=0 Until mh  
           For Local x:Int=0 Until mw  
                If grassmap[x][y] = 0 Then Continue                 
                Local x2:Int = x*tw  
                Local y2:Int = y*th  
                SetColor 80,230,20  
                DrawRect x2,y2,tw+1,th+1  
           Next  
           Next  
   
           'bridges  
           For Local y:Int=0 Until mh  
           For Local x:Int=0 Until mw  
                If bridgemap[x][y] = 0 Then Continue                 
                Local x2:Int = x*tw  
                Local y2:Int = y*th  
                SetColor 150,120,15  
                DrawRect x2,y2,tw+1,th+1  
                'plank  
                SetColor 200,170,20  
                DrawRect x2+tw/10,y2,tw/3,th+1  
                DrawRect x2+tw/1.8,y2,tw/3,th+1  
                'plank shadow and light  
                SetColor 240,200,200  
                DrawRect x2+tw/10,y2,1,th+1  
                DrawRect x2+tw/1.8,y2,1,th+1  
                SetColor 0,0,0  
                DrawRect x2+tw/10+tw/3,y2,1,th+1  
                DrawRect x2+tw/1.8+tw/3,y2,1,th+1  
           Next  
           Next  
   
   
           ' map pass 2 (shadow under trees/grass and highlight up water)            
           For Local y:Int=1 Until mh  
           For Local x:Int=0 Until mw  
                If map[x][y] = 0 Then Continue                 
                Local x2:Int = x*tw  
                Local y2:Int = y*th  
                'shadow under trees  
                If grassmap[x][y] = 1 And grassmap[x][y-1] = 0 And map[x][y] > numzones/3  
                SetColor 40,160,30  
                DrawRect x2+tw/4,y2,tw-th/2,th/3  
                End If  
                'shadow under water  
                If grassmap[x][y] = 0 And grassmap[x][y-1] = 1 And map[x][y] < numzones/3  
                SetColor 0,0,0  
                DrawRect x2,y2,tw+1,th/8  
                End If  
           Next  
           Next  
   
   
      End Method  
 End Class  
   
 Class MyGame Extends App  
      Field refresh:Int  
      Field mymap:map  
      Field plumps  
   Method OnCreate()  
     SetUpdateRate(1)  
     Seed = GetDate[4] * GetDate[5]  
              Local s:Int=Rnd(30,100)  
              If s<40 Then plumps = s/1.5 Else plumps = s*2  
        mymap = New map(DeviceWidth,DeviceHeight,s,s,plumps)  
           refresh = Millisecs()+3000  
   End Method  
   Method OnUpdate()  
        If Millisecs() > refresh   
              Local s:Float=Rnd(30,100)  
              If Rnd(10)<8 Then s = Rnd(20,40)  
                    If s<40 Then plumps = s/1.5 Else plumps = s*2  
             mymap = New map(DeviceWidth,DeviceHeight,s,s,plumps)  
              refresh = Millisecs()+3000  
        End If      
   End Method  
   Method OnRender()  
     Cls 0,0,0   
     SetColor 255,255,255  
     mymap.draw()  
   End Method  
 End Class  
   
   
 Function Main()  
   New MyGame()  
 End Function  

Thursday, November 2, 2017

Monkey-X - Generator - 2d Pixelart Potions - code example


 Import mojo  
   
 Class tile  
      Field width:Int,height:Int  
      Field map:Int[][]  
      Field map2:Int[][]  
   
      Method New(w:Int,h:Int)  
           Self.width = w  
           Self.height = h  
           map = New Int[width][]  
           map2 = New Int[width][]  
           For Local i:Int=0 Until width  
                map[i] = New Int[height]  
                map2[i] = New Int[height]  
           Next            
      End Method  
      ' Here we create the flasks or bottles  
      ' or what else.  
      Method generate()  
           Local x:Float=width/2  
           Local y:Float=height/4  
           Local angle:Int=0  
   
           While angle<200  
                angle+=Rnd(1,10)  
                For Local i:Int=0 Until 5  
                x+=Cos(angle)*.2  
                y+=Sin(angle)*.2  
                If x>=width Then x=width-1  
                If x<=0 Then x=1  
                If y>=height Then y=height-1  
                If y<=0 Then y=1  
                map[x][y] = 1  
                fillleftside(x-1,y)  
                Next  
   
           Wend  
           clearleftside()  
           mirrorrightside()  
           shaderightside()  
           shadecenter()  
           createbottlelight()  
           bottletop  
      End Method  
      Method bottletop()  
           Local x:Float=width/2  
           Local y:Float=2  
           Local angle:Int=0  
   
           While angle<200  
                angle+=Rnd(5,20)  
                For Local i:Int=0 Until 5  
                x+=Cos(angle)*.2  
                y+=Sin(angle)*.2  
                If x>=width Then x=width-1  
                If x<=0 Then x=1  
                If y>=height Then y=height-1  
                If y<=0 Then y=1  
                map2[x][y] = 1  
                fillleftsidetop(x-1,y)  
                Next  
   
           Wend  
           clearleftsidetop()  
           mirrorrightsidetop()  
           addbottleceiling()  
           darkshadebottletop()  
           bottletopbottomshade()  
           mergebottletop            
      End Method  
      Method bottletopbottomshade()  
           Local b:Int=0 'bottom y of bottletop  
           Local t:Int=0 'start y of bottletop  
           While map2[width/2][t] = 0  
                t+=1  
           Wend  
           b=t  
           While map2[width/2][b] <> 0  
                b+=1  
           Wend  
           For Local y:Int=b Until b-3 Step -1  
           For Local x:Int=0 Until width  
                If map2[x][y] = 1 Then map2[x][y+1] = 4  
           Next  
           Next            
      End Method  
      Method darkshadebottletop()  
           Local b:Int=0 'bottom y of bottletop  
           Local t:Int=0 'start y of bottletop  
           While map2[width/2][t] = 0  
                t+=1  
           Wend  
           b=t  
           While map2[width/2][b] <> 0  
                b+=1  
           Wend  
           For Local x:Int=0 Until width  
           For Local y:Int=t+3 Until b  
                If map2[x][y] = 6 Then map2[x][y] = 7  
           Next  
           Next  
      End Method  
      Method addbottleceiling()  
           For Local y:Int=1 Until height-1  
           For Local x:Int=0 Until width  
           If map2[x][y+1] = 5 And map2[x][y] = 0 Then map2[x][y] = 1 ; map2[x][y+1] = 6  
           Next  
           Next  
      End Method  
      Method fillleftsidetop(fx:Int,fy:Int)  
           For Local x:Int=fx Until 0 Step -1  
                map2[x][fy] = 5  
           Next  
           map2[fx][fy] = 6  
      End Method  
      Method mirrorrightsidetop()  
           For Local y:Int=0 Until height  
           For Local x:Int=0 Until width/2  
                map2[x][y] = map2[width-1-x][y]  
           Next  
           Next  
             
      End Method  
      Method clearleftsidetop()  
           For Local y:Int=0 Until height  
           For Local x:Int=0 Until width/2  
                map2[x][y] = 0  
           Next  
           Next  
      End Method  
   
   
      Method mergebottletop()  
           For Local y:Int=0 Until height  
           For Local x:Int=0 Until width  
                If map2[x][y] > 0  
                     map[x][y] = map2[x][y]  
                End If  
           Next  
           Next  
      End Method  
      Method createbottlelight()  
           For Local y:Int=height-height/2 Until height/2-height/4 Step -1  
           For Local x:Int=width/2 Until width  
                If map[x][y] = 1 Then   
                     map[x-5][y+5] = 1  
                End If  
           Next  
           Next  
      End Method  
      Method shadecenter()  
           Local sw:Int=0  
           For Local y:Int=height/1.7 Until height  
           For Local x:Int=0 Until width  
                If map[x][y] = 2  
                     If x Mod 2 = sw  
                     map[x][y] = 4  
                     End If  
                End If  
                  
           Next  
           If sw=1 Then sw=0 Else sw=1  
           Next            
      End Method  
      Method shaderightside()  
           For Local y:Int=0 Until height  
           For Local x:Int=0 Until width  
                If x<width/2  
                     If map[x][y] = 3 Then map[x][y] = 4  
                End If  
           Next  
           Next  
      End Method  
      Method mirrorrightside()  
           For Local y:Int=0 Until height  
           For Local x:Int=0 Until width/2  
                map[x][y] = map[width-1-x][y]  
           Next  
           Next  
             
      End Method  
      Method clearleftside()  
           For Local y:Int=0 Until height  
           For Local x:Int=0 Until width/2  
                map[x][y] = 0  
           Next  
           Next  
      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  
           map[fx][fy] = 3  
      End Method  
      Method draw(sx:Int,sy:Int,tw:Int,th:Int,r:Int,g:Int,b:Int)  
           Local x:Int  
           Local y:Int  
             
 '          For Local y:Int=0 Until height  
 '               SetColor ((255/height)*y)/2,100,100  
 '               DrawRect 0+sx,y+sy,width,1  
 '          Next  
   
           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 'white outline  
                     SetColor 170,170,170  
                End If  
                ' bottle color 2 = main 3 is light 4 is dark  
                If t = 2 Then  
                     'SetColor 255,0,0  
                     SetColor r,g,b  
                Elseif t = 3 Then 'light  
                     Local r2:Int=r+r/6  
                     Local g2:Int=g+g/6  
                     Local b2:Int=b+b/6  
                     If r2>255 Then r2=255  
                     If g2>255 Then g2=255  
                     If b2>255 Then b2=255  
                     'SetColor 255,150,150  
                     SetColor r2,g2,b2  
                Elseif t = 4 Then 'dark  
                     'SetColor 200,0,0  
                     Local r2:Int=r-r/4  
                     Local g2:Int=g-g/4  
                     Local b2:Int=b-b/4  
                     If r2<0 Then r2=0  
                     If g2<0 Then g2=0  
                     If b2<0 Then b2=0  
                     SetColor r2,g2,b2  
                End If  
                If t = 5 'bottle top color 6 is light 7 is dark  
                     SetColor 155,100,0  
                Elseif t=6  
                     SetColor 200,120,0                      
                Elseif t=7  
                     SetColor 100,70,0  
                End If  
                If t>0  
                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  
   Method OnCreate()  
        Seed = GetDate[4]*GetDate[5]  
     SetUpdateRate(1)  
     mytile = New tile(32,32)  
     mytile.generate()       
   
   End Method  
   Method OnUpdate()   
   End Method  
   Method OnRender()  
     Cls 110,110,110   
           For Local y:Int=0 Until DeviceHeight() Step 40  
           For Local x:Int=0 Until DeviceWidth() Step 40  
          mytile = New tile(32,32)  
          mytile.generate()       
                Local r:Int=Rnd(0,255)  
                Local g:Int=Rnd(0,255)  
                Local b:Int=Rnd(0,255)  
          mytile.draw(x,y,1,1,r,g,b)  
     Next  
     Next  
   End Method  
 End Class  
   
   
 Function Main()  
   New MyGame()  
 End Function  

Monkey-X - 2D Growing Slime Monster Mine - code example


 Import mojo  
   
 Global mapwidth:Int=200  
 Global mapheight:Int=100  
   
 '  
 ' This is a growing slime entity.  
 '   
 '  
 Class growslime  
      Field map:Int[][]  
      Field w:Float,h:Float  
      Field tw:Float,th:Float  
      Field openx:Stack<Int>  
      Field openy:Stack<Int>  
      Field slimetile:Int=10  
      Field slimestartx:Int,slimestarty:Int  
      Method New()  
           w = mymaptest.w * 2  
           h = mymaptest.h * 2  
           tw = 640 / w  
           th = 480 / h  
           map = New Int[w][]  
           For Local i:Int=0 Until w  
                map[i] = New Int[h]  
           Next  
           'copy the map from the game into this map  
           For Local y:Int=0 Until mymaptest.h  
           For Local x:Int=0 Until mymaptest.w  
           For Local y2:Int=0 Until 2  
           For Local x2:Int=0 Until 2  
                map[(x*2)+x2][(y*2)+y2] = mymaptest.map[x][y]  
           Next  
           Next  
           Next  
           Next  
           'create the active slime list  
           openx = New Stack<Int>  
           openy = New Stack<Int>  
           findslimestartpos()  
           openx.Push(slimestartx)  
           openy.Push(slimestarty)  
           map[slimestartx][slimestarty]=slimetile  
      End Method  
      Method findslimestartpos()  
           For Local y:Int=h-1 To 0 Step -1  
           For Local x:Int=0 Until w  
                If map[x][y] = 1 Then   
                     slimestartx = x  
                     slimestarty = y  
                     Return  
                End If  
           Next  
           Next  
      End Method  
      Method update(speed:String)  
           Local freq:Int  
           If speed = "slow" Then freq = 120 Else freq = 20  
           ' Expand Slime  
           For Local i:Int=0 Until openx.Length  
                If Rnd(freq) > 2 Then Continue  
                Local x2:Int=openx.Get(i)  
                Local y2:Int=openy.Get(i)  
                'bottom bleft or bright first  
                Local r:Int=Rnd(0,6)  
                If r=0 And y2+1<h And map[x2][y2+1] = 1 Then addslime(x2,y2+1) ; Continue  
                If r=1 And x2-1 >=0 And y2+1 <h And map[x2-1][y2+1] = 1 Then addslime(x2-1,y2+1) ; Continue  
                If r=2 And y2+1<h And map[x2+1][y2+1] = 1 Then addslime(x2+1,y2+1) ; Continue  
                ' left Or right Then  
                r = Rnd(0,2)  
                If r=0 And x2-1>=0 And map[x2-1][y2] = 1 Then addslime(x2-1,y2) ; Continue  
                If r=1 And x2+1<w And map[x2+1][y2] = 1 Then addslime(x2+1,y2) ; Continue  
                ' up lup and rup  
                r = Rnd(0,23)  
                If r=0 And y2-1>=0 And map[x2][y2-1] = 1 Then addslime(x2,y2-1);Continue  
                If r=1 And x2-1>=0 And y2-1>=0 And map[x2-1][y2-1] = 1 Then addslime(x2-1,y2-1);Continue  
                If r=2 And x2+1<w And y2-1>=0 And map[x2+1][y2-1] = 1 Then addslime(x2+1,y2-1);Continue  
           Next  
           ' Remove Obsolete slime  
           For Local i:Int=0 Until openx.Length  
                Local cnt:Int=0  
                For Local y:Int=-1 To 1  
                For Local x:Int=-1 To 1  
                     Local x2:Int=openx.Get(i)+x  
                     Local y2:Int=openy.Get(i)+y  
                     If x2<0 Or y2<0 Or x2>=w Or y2>=h Then   
                          cnt+=1  
                          Continue  
                     End If  
                     If map[x2][y2] = slimetile Then cnt+=1  
                Next  
                Next            
                If cnt=9 Then  
                     openx.Remove(i)  
                     openy.Remove(i)  
                End If  
           Next  
      End Method  
   
      Method addslime(sx:Int,sy:Int)  
           openx.Push(sx)  
           openy.Push(sy)  
           map[sx][sy] = slimetile  
      End Method  
   
      Method update_vine(speed:String)  
           Local freq:Int  
           If speed = "slow" Then freq = 200 Else freq = 20  
           ' Expand Slime  
           For Local i:Int=0 Until openx.Length  
                For Local y:Int=-1 To 1  
                For Local x:Int=-1 To 1  
                     If Rnd(freq)>2 Then Continue  
                     Local x2:Int=openx.Get(i)+x  
                     Local y2:Int=openy.Get(i)+y  
                     If x2<0 Or y2<0 Or x2>=w Or y2>=h Then Continue  
                     If map[x2][y2] = 1 Then  
                          openx.Push(x2)  
                          openy.Push(y2)  
                          map[x2][y2] = slimetile  
                     End If  
                Next  
                Next  
           Next  
           ' Remove Obsolete slime  
           For Local i:Int=0 Until openx.Length  
                Local cnt:Int=0  
                For Local y:Int=-1 To 1  
                For Local x:Int=-1 To 1  
                     Local x2:Int=openx.Get(i)+x  
                     Local y2:Int=openy.Get(i)+y  
                     If x2<0 Or y2<0 Or x2>=w Or y2>=h Then   
                          cnt+=1  
                          Continue  
                     End If  
                     If map[x2][y2] = slimetile Then cnt+=1  
                Next  
                Next            
                If cnt=9 Then  
                     openx.Remove(i)  
                     openy.Remove(i)  
                End If  
           Next  
      End Method  
      Method draw()  
           ' Draw the solid slimes ()  
     For Local y:Float=0 Until h  
     For Local x:Float=0 Until w  
       Local x1:Float=x*tw  
       Local y1:Float=y*th  
       If map[x][y] = slimetile  
         SetColor 20,200,10  
         DrawOval x1,y1,tw+1,th+1  
       End If        
     Next  
     Next  
   
      End Method  
 End Class  
   
 Class maptest  
   Field tw:Float,th:Float  
   Field w:Int,h:Int  
   'bottom x and y contain the coords of the next  
   'shaft to be created. center of room last pass  
   Field bottomy:Int  
   Field bottomx:Int  
   Field map:Int[][]  
   Method New(w:Int,h:Int)  
     Self.w = w  
     Self.h = h  
     tw = DeviceWidth()/w  
     th = DeviceHeight()/h  
     map = New Int[w][]  
     For Local i=0 Until w  
       map[i] = New Int[h]  
     Next  
     drawmaprect(0,0,w-1,15)  
     For Local i=0 Until h  
       map[1][i] = 0  
       map[w-2][i] = 0  
     Next  
     ' x,y,number of tunnels>>  
     makemine(w/2,15,Rnd(1,3))  
     makemine(bottomx,bottomy,Rnd(1,3))  
     If bottomy<(Float(mapheight)/2)  
       makemine(bottomx,bottomy,Rnd(1,3))  
     End If  
   End Method  
   Method makemine(x:Int,y:Int,depth:Int)  
     Local vy:Int=y  
     For Local mydepth=0 Until depth  
       Local d1:Int=Rnd(8,16)'depth  
       tunneldown(x,y,d1)  
       y+=d1  
       Local d2:Int=Rnd(1,4)'direction  
       If d2=1 Then   
         sidetunnel(x,y,"left")  
       End If  
       If d2=2 Then   
         sidetunnel(x,y,"right")  
       End If  
       If d2=3 Then   
         sidetunnel(x,y,"left")  
         sidetunnel(x,y,"right")  
       End If  
     Next  
     'For Local y1=vy Until bottomy+2  
     '  map[x][y1] = 2  
     ' Next  
   End Method  
   Method sidetunnel(x:Int,y:Int,d:String)  
     If d="left"  
       Local width:Int=Rnd(5,15)  
       drawmaprect(x-width+2,y,width,3)  
       Local roomw:Int=Rnd(5,15)  
       drawmaprect(x-width+2-roomw,y-1,roomw,5)  
       For Local x1=0 Until roomw/3  
         map[(x-width+2-roomw)+x1][y+4] = 3  
       Next  
       bottomx = x-width-(roomw/2)  
       bottomy = y  
     End If  
     If d="right"  
       Local width:Int=Rnd(5,15)  
       drawmaprect(x-1,y,width,3)  
       Local roomw:Int=Rnd(5,15)  
       drawmaprect(x+width,y-1,roomw,5)      
       For Local x1=roomw Until roomw/1.5 Step -1  
         map[(x+width)+x1][y+4] = 3  
       Next  
       bottomx = x+width+(roomw/2)        
       bottomy = y  
     End If  
   End Method  
   Method tunneldown(x:Int,y:Int,d:Int)  
     drawmaprect(x-2,y,4,d)  
   End Method  
   Method drawmaprect(x:Int,y:Int,w:Int,h:Int)  
     For Local y1=y To y+h  
     For Local x1=x To x+w  
       map[x1][y1] = 1  
     Next  
     Next      
   End Method  
   Method draw()  
     For Local y=0 Until h  
     For Local x=0 Until w  
       Local x1:Float=DeviceWidth()/Float(mapwidth)*Float(x)  
       Local y1:Float=DeviceHeight/Float(mapheight)*Float(y)  
       If map[x][y] = 1  
         SetColor 255,255,255          
         DrawRect x1,y1,tw+1,th+1  
       End If  
       If map[x][y] = 3  
         SetColor 200,200,10  
         DrawOval x1,y1,tw+1,th+1  
       End If        
     Next  
     Next  
   End Method  
 End Class  
   
 ' -----------------------------------------------------------------------------------------------  
   
 Global mymaptest:maptest  
 Global mygrowslime:growslime  
   
 Class MyGame Extends App  
   Field nmap:Int=0  
   Method OnCreate()  
     Local date := GetDate()  
     Seed = date[5]  
     SetUpdateRate(60)  
     restartgame  
   End Method  
   Method OnUpdate()    
     nmap+=1  
     If KeyDown(KEY_SPACE)=True Or nmap>3500  
       restartgame  
       nmap=0  
     End If  
     mygrowslime.update("fast")  
   End Method  
   Method OnRender()  
     Cls 0,0,0   
     mymaptest.draw()  
     mygrowslime.draw()  
     SetColor 255,255,0  
     DrawText "MonkeyX - Growing Slime in the Mines Example",20,0  
   End Method  
 End Class  
   
   
   
 Function Main()  
   New MyGame()  
 End Function  
   
   
 Function restartgame()  
   mymaptest = New maptest(mapwidth,mapheight)  
   mygrowslime = New growslime()  
 End Function  
   
 Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int)  
   Return Abs(x2-x1)+Abs(y2-y1)  
 End Function   
     
 Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int)  
   If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False  
   If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False  
   Return True  
 End Function  

Monkey-X - 2D Snake Style Water - code example


 'snake(style) 2d water  
 Import mojo  
   
 Global mapwidth:Int=200  
 Global mapheight:Int=100  
   
 Class watertest  
   Field map:Int[][]  
       Field w:Float,h:Float  
       Field tw:Float,th:Float  
      Field flowx:Int,flowy:Int  
      Field dir:String="down"  
   Method New()  
     Self.w = mymaptest.w*4  
     Self.h = mymaptest.h*4  
     Self.tw = 640/w  
     Self.th = 480/h  
   
     map = New Int[w][]  
     For Local i=0 Until w  
       map[i] = New Int[h]  
     Next  
     flowx = 10  
     flowy = 10  
           For Local y:Int=0 Until mymaptest.h  
           For Local x:Int=0 Until mymaptest.w  
                If mymaptest.map[x][y] = 1  
                For Local y2:Int=0 Until 4  
                For Local x2:Int=0 Until 4  
                     map[x*4+x2][y*4+y2] = 1  
                Next  
                Next  
                End If  
           Next  
           Next  
      End Method  
      Method update()  
           Local a:Bool=False  
           dir = "new"  
           If map[flowx][flowy+1] = 1 Then dir="down" ; a=True  
           If a=False And map[flowx+1][flowy] = 1 Then dir="right"; a=True  
           If a=False And map[flowx-1][flowy] = 1 Then dir="left" ; a = True  
           If a=False And map[flowx][flowy-1] = 1 Then dir="up" ; a = True  
             
           If dir="left" And map[flowx-2][flowy] = 10 Then map[flowx-2][flowy] = 1  
           If dir="right" And map[flowx+2][flowy] = 10 Then map[flowx+2][flowy] = 1            
   
             
   
           map[flowx][flowy]=10  
           If dir="left"   
           If map[flowx-1][flowy-1]=10 Then map[flowx-1][flowy-1]=1  
           Elseif dir="right"  
           If map[flowx+1][flowy-1]=10 Then map[flowx+1][flowy-1]=1  
           End If  
   
           Select dir  
                Case "up"  
                flowy-=1  
                Case "left"  
                flowx-=1  
                Case "right"  
                flowx+=1  
                Case "down"  
                flowy+=1                 
           End Select  
             
           If dir="new" Or Rnd(60*20) < 2 Then ' if the snake got stuck then  
                                ' find a new spot  
                dir = "done"  
                For Local y:Int=h-1 Until 1 Step -1  
                For Local x:Int=0 Until w  
                     If map[x][y] = 1 And map[x][y+1] = 10 Then  
                          flowx = x  
                          flowy = y  
                          Return  
                     End If  
                Next  
                Next  
           End If  
      End Method  
      Method draw()  
     For Local y:Int=0 Until h  
     For Local x:Int=0 Until w  
       Local x1:Float=x*tw  
       Local y1:Float=y*th  
       If map[x][y] = 10  
         SetColor 0,0,255          
         DrawRect x1,y1,tw+1,th+1  
       End If  
     Next  
     Next  
      End Method  
 End Class  
   
 Class maptest  
   Field tw:Float,th:Float  
   Field w:Int,h:Int  
   'bottom x and y contain the coords of the next  
   'shaft to be created. center of room last pass  
   Field bottomy:Int  
   Field bottomx:Int  
   Field map:Int[][]  
   Method New(w:Int,h:Int)  
     Self.w = w  
     Self.h = h  
     tw = DeviceWidth()/w  
     th = DeviceHeight()/h  
     map = New Int[w][]  
     For Local i=0 Until w  
       map[i] = New Int[h]  
     Next  
     drawmaprect(0,0,w-1,15)  
     For Local i=0 Until h  
       map[1][i] = 0  
       map[w-2][i] = 0  
     Next  
     ' x,y,number of tunnels>>  
     makemine(w/2,15,Rnd(1,3))  
     makemine(bottomx,bottomy,Rnd(1,3))  
     If bottomy<(Float(mapheight)/2)  
       makemine(bottomx,bottomy,Rnd(1,3))  
     End If  
   End Method  
   Method makemine(x:Int,y:Int,depth:Int)  
     Local vy:Int=y  
     For Local mydepth=0 Until depth  
       Local d1:Int=Rnd(8,16)'depth  
       tunneldown(x,y,d1)  
       y+=d1  
       Local d2:Int=Rnd(1,4)'direction  
       If d2=1 Then   
         sidetunnel(x,y,"left")  
       End If  
       If d2=2 Then   
         sidetunnel(x,y,"right")  
       End If  
       If d2=3 Then   
         sidetunnel(x,y,"left")  
         sidetunnel(x,y,"right")  
       End If  
     Next  
 '    For Local y1=vy Until bottomy+2  
  '      map[x][y1] = 2  
  '   Next  
   End Method  
   Method sidetunnel(x:Int,y:Int,d:String)  
     If d="left"  
       Local width:Int=Rnd(5,15)  
       drawmaprect(x-width+2,y,width,3)  
       Local roomw:Int=Rnd(5,15)  
       drawmaprect(x-width+2-roomw,y-1,roomw,5)  
       For Local x1=0 Until roomw/3  
         map[(x-width+2-roomw)+x1][y+4] = 3  
       Next  
       bottomx = x-width-(roomw/2)  
       bottomy = y  
     End If  
     If d="right"  
       Local width:Int=Rnd(5,15)  
       drawmaprect(x-1,y,width,3)  
       Local roomw:Int=Rnd(5,15)  
       drawmaprect(x+width,y-1,roomw,5)      
       For Local x1=roomw Until roomw/1.5 Step -1  
         map[(x+width)+x1][y+4] = 3  
       Next  
       bottomx = x+width+(roomw/2)        
       bottomy = y  
     End If  
   End Method  
   Method tunneldown(x:Int,y:Int,d:Int)  
     drawmaprect(x-2,y,4,d)  
   End Method  
   Method drawmaprect(x:Int,y:Int,w:Int,h:Int)  
     For Local y1=y To y+h  
     For Local x1=x To x+w  
       map[x1][y1] = 1  
     Next  
     Next      
   End Method  
   Method draw()  
     For Local y=0 Until h  
     For Local x=0 Until w  
       Local x1:Float=DeviceWidth()/Float(mapwidth)*Float(x)  
       Local y1:Float=DeviceHeight/Float(mapheight)*Float(y)  
       If map[x][y] = 1  
         SetColor 255,255,255          
         DrawRect x1,y1,tw+1,th+1  
       End If  
       If map[x][y] = 3  
         SetColor 200,200,10  
         DrawOval x1,y1,tw+1,th+1  
       End If        
     Next  
     Next  
   End Method  
 End Class  
   
 ' -----------------------------------------------------------------------------------------------  
   
 Global mymaptest:maptest  
 Global mywatertest:watertest  
   
 Class MyGame Extends App  
   Field nmap:Int=0  
   Method OnCreate()  
     Local date := GetDate()  
     Seed = date[5]  
     SetUpdateRate(60)  
     restartgame  
   End Method  
   Method OnUpdate()    
           For Local i:Int=0 Until 6  
     mywatertest.update()  
     Next        
           If levelfilled() Then restartgame  
   End Method  
   Method OnRender()  
     Cls 0,0,0   
     mymaptest.draw()  
     mywatertest.draw()  
     SetColor 255,255,0  
     DrawText "MonkeyX - 2d Mining map and snake style water.",20,0  
   End Method  
 End Class  
   
   
   
 Function Main()  
   New MyGame()  
 End Function  
   
 Function levelfilled:Bool()  
      If Rnd(120)>2 Then Return False  
      Local cnt:Int=0  
      For Local y:Int=10 Until 60  
      For Local x:Int= 0 Until mywatertest.w  
      If mywatertest.map[x][y] = 10 Then cnt+=1  
      If cnt>100 Then Return True  
      Next  
      Next  
   
      Return False  
 End Function  
   
 Function restartgame()  
   mymaptest = New maptest(mapwidth,mapheight)  
   mywatertest = New watertest()  
 End Function  
   
 Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int)  
   Return Abs(x2-x1)+Abs(y2-y1)  
 End Function   
     
 Function rectsoverlap:Bool(x1:Int, y1:Int, w1:Int, h1:Int, x2:Int, y2:Int, w2:Int, h2:Int)  
   If x1 >= (x2 + w2) Or (x1 + w1) <= x2 Then Return False  
   If y1 >= (y2 + h2) Or (y1 + h1) <= y2 Then Return False  
   Return True  
 End Function  

Monday, October 30, 2017

Monkey-X - Generator - Tileable Textured Stones - code example


 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  

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