Monday, December 14, 2015

Monkey-X - Maze Generator - code example


I think I fixed the previous mistakes in the maze generator.

Import mojo

Global maxwidth:Int=60
Global maxheight:Int=40

Class maze
    Field map:Bool[][]
    Field w:Int,h:Int
    Field dirx:Int[] = [0,1,0,-1]
    Field diry:Int[] = [-1,0,1,0]
    Field rd:Int
    Method New(w:Int,h:Int,rd:Int)
        Self.w = w
        Self.h = h
        map = New Bool[w][]
        For Local i = 0 Until w
            map[i] = New Bool[h]
        Next
        Self.rd=rd
        makemaze
    End Method
    Method makemaze()
        Local count:Int=0
        For Local i=0 Until w*h
            Local x = 2 + (Int(((w - 2) * Rnd) / 2) * 2)
            Local y = 2 + (Int(((h - 2) * Rnd) / 2) * 2)            
            If count=0 Then map[x][y] = True
            Local dir:Int=Rnd(0,4)            
               If map[x][y] = True
                While spacetaken(x+(dirx[dir]*2),y+(diry[dir]*2)) = False
                   map[x][y] = True
                   map[x+dirx[dir]][y+diry[dir]] = True
                   x+=dirx[dir]
                   y+=diry[dir]
                   If Rnd(0,rd) < rd/10 Then
                       dir=Rnd(0,4)
                   End If
                   Wend
            End If
        Next
    End Method
    Method spacetaken:Bool(x:Int,y:Int)
        If x>-1 And y>-1 And x<w And y<h
            Return map[x][y]
        End If
        Return True
    End Method
    Method draw()        
        Local tw:Float=DeviceWidth()/Float(w)
        Local th:Float=DeviceHeight()/Float(h)
        For Local y=0 Until h
        For Local x=0 Until w
            If map[x][y] = False
                Local d:Int                
                Local dx:Int=x*tw
                Local dy:Int=y*th                
                d = distance(dx,dy,320,200)
                d=d/2.5
                SetColor 255-d,(255-d)/2,(255-d)/2
                DrawRect dx,dy,tw+1,th+1
            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

Global mymaze:maze = New maze(    maxwidth,
                                maxheight,
                                Rnd(0,40))
                                
Class MyGame Extends App
    Field w:Int,h:Int
    Field rd:Int
    field cnt:Int
    Method OnCreate()
        SetUpdateRate(10)
        Local date := GetDate()
        ' set the random seed to
        ' current second
        Seed = date[5]        
    End Method
    Method OnUpdate()   
        cnt+=1
           If KeyHit(KEY_RIGHT) Or cnt>30
               cnt=0
            w = Rnd(20,maxwidth)
            h = Rnd(15,maxheight)
            rd = Rnd(0,40)
            If Rnd(0,10) < 3
                w=Rnd(50,200)
                h=Rnd(50,150)
            End If
            mymaze = New maze(w,h,rd)
        End If
    End Method
    Method OnRender()
        Cls 0,0,0 
        mymaze.draw
        SetColor 0,0,0
        DrawRect 0,0,DeviceWidth()/2,15
        SetColor 255,255,255
        DrawText     "Maze width :"+w+
                    " height "+h+
                    " and rdness "+
                    rd,10,0
    End Method
End Class


Function Main()
    New MyGame()
End Function

Monkey-X - Another Map generator (failed maze generator) - code example


Import mojo


Class maze
    Field map:Bool[][]
    Field w:Int,h:Int
    Field dirx:Int[] = [0,1,0,-1]
    Field diry:Int[] = [-1,0,1,0]
    Field rd:Int
    Field ds:int
    Method New(w:Int,h:Int,rd:Int,ds:Int)
        Self.w = w
        Self.h = h
        map = New Bool[w][]
        For Local i = 0 Until w
            map[i] = New Bool[h]
        Next
        Self.rd=rd
        Self.ds=ds
        makemaze
    End Method
    Method makemaze()
        Local count:Int=0
        For Local i=0 Until (w*h)/ds
            Local x = 2 + (Int(((w - 2) * Rnd) / 2) * 2)
            Local y = 2 + (Int(((h - 2) * Rnd) / 2) * 2)            
            If count=0 Then map[x][y] = True
            Local dir:Int=Rnd(0,4)            
               While spacetaken(x+(dirx[dir]*2),y+(diry[dir]*2)) = False
                   If Rnd(rd)<10 Then dir=Rnd(0,4)
                While spacetaken(x+(dirx[dir]*2),y+(diry[dir]*2)) = True
                       dir=Rnd(0,4)
                   Wend
                   map[x][y] = True
                   map[x+dirx[dir]][y+diry[dir]] = True
                   x+=dirx[dir]
                   y+=diry[dir]
            Wend
        Next
    End Method
    Method spacetaken:Bool(x:Int,y:Int)
        If x>-1 And y>-1 And x<w And y<h
            Return map[x][y]
        End If
        Return True
    End Method
    Method draw()
        Local tw:Float=DeviceWidth()/Float(w)
        Local th:Float=DeviceHeight()/Float(h)
        For Local y=0 Until h
        For Local x=0 Until w
            If map[x][y] = True
                SetColor 255,255,255
                DrawRect x*tw,y*th,tw+1,th+1
            End If
        Next
        Next
    End Method
End Class

Global mymaze:maze = New maze(    Rnd(15,60),
                                Rnd(15,60),
                                Rnd(0,100),
                                Rnd(1,20))

Class MyGame Extends App
    Field time:Int=0
    Field w:Int,h:Int
    Field rd:Int
    Field ds:Int
    Method OnCreate()
        SetUpdateRate(10)
        Local date := GetDate()
        ' set the random seed to
        ' current second
        Seed = date[5]        
    End Method
    Method OnUpdate()        
        time+=1
        If time>10
            w = Rnd(15,60)
            h = Rnd(15,60)
            rd = Rnd(0,100)
            ds = Rnd(1,20)
            mymaze = New maze(w,h,rd,ds)
            time=0
        End If
    End Method
    Method OnRender()
        Cls 0,0,0 
        mymaze.draw
        SetColor 0,0,0
        DrawRect 0,0,DeviceWidth(),15
        SetColor 255,255,255
        DrawText     "Maze width :"+w+
                    " height "+h+
                    " and rdness "+
                    rd+" and ds "+ds,10,0
    End Method
End Class


Function Main()
    New MyGame()
End Function

Sunday, December 13, 2015

Monkey-X - Sidefilling Heightmap method - Code Example


This code creates a drawing by drawing lines into the screen and increasing the image by one value on one side of the line. I saw this on a tutorial site once. I can't really remember if I did all the steps.

Import mojo

Class openlist
    Field x:Int,y:Int
    Method New(x:Int,y:Int)
        Self.x = x
        Self.y = y
    End Method
End Class


Class heightmap
    Field ol:List<openlist> = New List<openlist>
    Field h:Int,w:Int
    ' hold the heightmap
    Field hmap:Int[][]
    'hold the fillmap
    Field fmap:Int[][]
    Field x3:Int,y3:Int
    Field x4:Int,y4:Int
    Method New(w:Int,h:Int)
        Self.w = w
        Self.h = h
        hmap = New Int[w][]
        fmap = New Int[w][]
        For Local i = 0 Until w
            hmap[i] = New Int[h]
            fmap[i] = New Int[h]            
        Next
        makeheightmap        
    End Method
    Method makeheightmap()
        For Local i=0 Until 255
        Local startside:Int
        Local endside:Int
         Local exitloop:Bool=False
         While exitloop = False
             endside = Rnd(1,5)
             startside = Rnd(1,5)
             If endside<>startside Then
                 exitloop = True
             End If
         Wend         
         x3=Rnd(w)
         y3=Rnd(h)
         x4=Rnd(w)
         y4=Rnd(h)
         Select startside
             Case 1
             y3=0
             Case 2
             x3=w-1
             Case 3
             y3=h-1
             Case 4
             x3=0
         End Select
         Select endside
             Case 1
             y4=0
             Case 2
             x4=w-1
             Case 3
             y4=h-1
             Case 4
             x4=0
         End Select
         clearfmap()
         line(x3,y3,x4,y4)
         fillfmap()
         addhmap()
        Next
    End Method
    Method addhmap()
        For Local y=0 Until h
        For Local x=0 Until w
            hmap[x][y]+=fmap[x][y]
        Next
        Next
    End Method
    Method fillfmap()
        Local exitloop:Bool=False
        Local x1:Int,y1:Int
        While exitloop = False
            x1=Rnd(w)
            y1=Rnd(h)
            If fmap[x1][y1] = 0
                exitloop = True
            End If
        Wend
        ol.Clear
        ol.AddLast(New openlist(x1,y1))
        fmap[x1][y1]=1
        While ol.IsEmpty() = False
            For Local i:=Eachin ol

                Local tx:Int=i.x
                Local ty:Int=i.y
                
                If tx-1>-1
                If fmap[tx-1][ty] = 0
                    ol.AddLast(New openlist(tx-1,ty))
                    fmap[tx-1][ty] = 1
                End If
                End If

                If tx+1<w
                If fmap[tx+1][ty] = 0
                    ol.AddLast(New openlist(tx+1,ty))
                    fmap[tx+1][ty] = 1
                End If
                End If

                If ty-1>-1
                If fmap[tx][ty-1] = 0
                    ol.AddLast(New openlist(tx,ty-1))
                    fmap[tx][ty-1] = 1
                End If
                End If
                
                If ty+1<h
                If fmap[tx][ty+1] = 0
                    ol.AddLast(New openlist(tx,ty+1))
                    fmap[tx][ty+1] = 1
                End If
                End If
                ol.Remove i 
            Next
        Wend
    End Method
    Method line:Void(x1:Int,y1:Int,x2:Int,y2:Int)
        Local dx:Int, dy:Int, sx:Int, sy:Int, e:Int
         dx = Abs(x2 - x1)
          sx = -1
          If x1 < x2 Then sx = 1      
          dy = Abs(y2 - y1)
          sy = -1
          If y1 < y2 Then sy = 1
          If dx < dy Then 
              e = dx / 2 
          Else 
              e = dy / 2          
          End If
          Local exitloop:Bool=False
          While exitloop = False
            fmap[x1][y1] = 1
            If x1 = x2 
                If y1 = y2
                    exitloop = True
                End If
            End If
            If dx > dy Then
                x1 += sx ; e -= dy 
                  If e < 0 Then e += dx ; y1 += sy
            Else
                y1 += sy ; e -= dx 
                If e < 0 Then e += dy ; x1 += sx
            Endif
          Wend
    End Method
    Method clearfmap()
        For Local y=0 Until h
        For Local x=0 Until w
            fmap[x][y] = 0
        Next
        Next
    End Method
    Method draw()
        Local sx:Float=DeviceWidth()/Float(w)
        Local sy:Float=DeviceHeight()/Float(h)
        For Local y=0 Until h
        For Local x=0 Until w
            Local g:Int=hmap[x][y]
            SetColor g/1.5,g/1.5,g
            DrawRect x*sx,y*sy,sx+1,sy+1
        Next
        Next
    End Method
End Class

Global myhmap:heightmap = New heightmap(100,100)

Class MyGame Extends App
    Field refreshtime:Int=0
    Method OnCreate()
        SetUpdateRate(10)
    End Method
    Method OnUpdate()
        refreshtime+=1
        If refreshtime>10
            myhmap = New heightmap(100,100)
            refreshtime=0
        End If
    End Method
    Method OnRender()
        Cls 0,0,0 
        SetColor 255,255,255
        myhmap.draw
    End Method
End Class


Function Main()
    New MyGame()
End Function

Monday, December 7, 2015

Monkey-X - RPG - Scrolling platformer - Mining.- Game Template


' version 7-12-2015.
' Template.
' Scrolling platformer with RPG features.
' Based on the scrolling platformer with vines
' template on my Monkey-X blog.
'
' The mapwidth variables can be set to large(200+) or 
' small(100*100) maps. There will be multiple mines
' placed and populated if there is enough space for them
' on the map. (This version runs fast enough on low
' end laptops with maps up to 320*240 - there currently
' is no LOD implemented.)
'
' Game :
' Travel down/explore the mine.
' Has mining eggs feature. Hunting for meat.
' Monsters lay eggs. Only one monster hatches from a egg
' if there are no other monsters nearby.
' Monsters/breeders do not attack.
' You can pick up the eggs. Kill the monsters for meat.
' You can place an egg on the ground and a monster could be
' hatched.
' Eggs can also spawn Deathwings and they attack/hurt you.
' You have health and if zero restarts the game.
' p - Place egg on the ground.
' t - Pick up egg from the ground.
' Space - Attack with spear.
' curs left/right/up - move and jump.
' 
' Thinking of adding automated machine gun nests that you 
' can place/move around and they kill the flying monsters.
'
' Mood of the game at the moment is : 
' Monsters live in an old abandoned mining area. You can 
' mine meat/eggs to make a profit. Monsters
' have been seen flying nearby mines attacking people.
'
'
Import mojo

Const mapwidth:Int=100
Const mapheight:Int=100
Const tilewidth:Int=32
Const tileheight:Int=32
Global mapx:Int=0
Global mapy:Int=0
Global mapsx:Int=0
Global mapsy:Int=0
Global maxdeathwings:Int=10

Class maptest
    Field tw:Int,th:Int
    Field w:Int,h: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
        Local x:Int=32
        While x<w-48
            makemine(x,15,Rnd(4,h/15))
            x+=Rnd(48,64)
        Wend
    End Method
    Method makemine(x:Int,y:Int,depth:Int)
        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")
           If d2=2 Then sidetunnel(x,y,"right")
           If d2=3 Then 
            sidetunnel(x,y,"left")
               sidetunnel(x,y,"right")
           End If
           Next
           For Local y1=0 Until y
               map[x][y1] = 2
           Next
    End Method
    Method sidetunnel(x:Int,y:Int,d:String)
        If d="left"
            Local width:Int=Rnd(5,10)
            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
                eggs.AddLast( New egg((x-width+2-roomw)+x1,y+4) )
            Next
'            a.AddLast(    New agent(    ((x-width+2-roomw))*tilewidth,
'                                    (y+4)*tileheight) )
        End If
        If d="right"
            Local width:Int=Rnd(5,10)
            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
                eggs.AddLast( New egg((x+width)+x1,y+4) )
            Next            
'            a.AddLast( New agent(     (x+width+2)*tilewidth,
'                                     (y+4)*tileheight ))
        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
            If map[x][y] = 1
                SetColor 255,255,255
                DrawRect x*tw,y*th,tw,th
            End If
            If map[x][y] = 3
                SetColor 200,200,10
                DrawOval x*tw,y*th,tw,th
            End If            
        Next
        Next
    End Method
End Class

Class spear
    Field x:Float,y:Float
    Field w:Int=20
    Field h:Int=4
    Field d:String
    Field incx:Float
    Field active:Bool    
    Method New(x:Int,y:Int,d:String)
        Self.x = x
        Self.y = y
        Self.d = d
        incx = 3
        active = True
    End Method
    Method update()
        If active = False Then Return
        w+=incx
        incx-=0.5
        If     incx > 0
            killcreature
        End If
        If incx < -3 Then active = False
    End Method
    Method killcreature()
        For Local i:=Eachin dw
            If d="left" 
                If rectsoverlap(    i.x,i.y,32,32,
                                    x-32,y,32,32)
                    i.remove = True
                    myinven.meat+=1
                End If
            Else
                If rectsoverlap(    i.x,i.y,32,32,
                                    x+32,y,32,32)
                    i.remove = True
                    myinven.meat+=1
                End If
            End If
        Next

        For Local i:=Eachin a            
            If d="left" 
                If rectsoverlap(    i.x,i.y,32,32,
                                    x-32,y,32,32)
                    i.remove = True
                    myinven.meat+=1
                End If
            Else
                If rectsoverlap(    i.x,i.y,32,32,
                                    x+32,y,32,32)
                    i.remove = True
                    myinven.meat+=1
                End If
            End If
        Next
        For Local i:=Eachin a
            If i.remove=True
                a.Remove i
            End If
        Next
    End Method
    Method draw()
        If active = True
            SetColor 200,100,0
            If d = "right"
                DrawRect x+32,y+8,w,h
            Else
                DrawRect x-w,y+8,w,h    
            End If
        End If
    End Method
End Class

Class player    
    Field x:Float=0
    Field y:Float=0
    Field w:Int=32
    Field h:Int=32
    Field incy:Float=0
    Field isjumping:Bool = False
    Field facing:Int '0 = left , 1 = right
    Field jumpofvine:Bool=False
    Field jumpofvinetimeout:Int
    Field health:Int=10
    Method update()
        Local ox:Int=x
        Local oy:Int=y
        If pvc(0,0) = False Or jumpofvine = True Then regularmode
        If pvc(0,0) = True 
            If jumpofvine = False
                vinemode
            End If
        End If
        If KeyHit(KEY_SPACE)
            Local md:String
            If facing = 0 Then 
                md="left" 
            Else
                md="right"
            End If
            myspear = New spear(p.x,p.y,md)
        End If
        If KeyHit(KEY_T)
            Local offx:Int
            If p.facing=0 Then 
                offx=0
            Else
                offx=32
            End If
               Local cx = (p.x+offx)/tilewidth+mapx
            Local cy = (p.y)/tileheight+mapy
            If mymaptest.map[cx][cy] = 3
                mymaptest.map[cx][cy] = 1
                myinven.eggs+=1
                For Local i:=Eachin eggs
                    If i.x = cx And
                        i.y = cy
                        i.remove = True
                    End If
                Next
                For Local i:=Eachin eggs
                    If i.remove=True
                        eggs.Remove i
                    End If
                Next
            End If
        End If
        If KeyHit(KEY_P)
            If myinven.eggs > 0
               Local cx = (p.x)/tilewidth+mapx
            Local cy = (p.y)/tileheight+mapy
            If mymaptest.map[cx][cy] = 1
                mymaptest.map[cx][cy] = 3
                eggs.AddLast(New egg(cx,cy))
            End If            
            End If
            myinven.eggs-=1
        End If
    End Method
    Method movea(x1:Int,y1:Int)
        For Local i:=Eachin a
            i.x+=x1
            i.y+=y1
        Next
        For Local i:=Eachin dw
            i.x+=x1
            i.y+=y1
        Next        
    End Method
    Method vinemode()
        isjumping = False
        incy=0
        If KeyDown(KEY_J)
            jumpofvine = True
            jumpofvinetimeout = Millisecs() + 1000
            isjumping = True
            incy=-4
        End If
        If KeyDown(KEY_UP)
            For Local i=0 Until 4
                If pvc(0,0) = True And ptc(0,-1) = False
                    y-=1
                End If
            Next
        End If
        If KeyDown(KEY_DOWN)
            For Local i=0 Until 4
                If pvc(0,0) = True And ptc(0,1) = False
                    y+=1
                End If
            Next
        End If
        If KeyDown(KEY_LEFT)
            For Local i=0 Until 4
                If pvc(0,0) = True And ptc(-1,0) = False
                    x-=1
                    facing=0
                End If
            Next
        End If
        If KeyDown(KEY_RIGHT)
            For Local i=0 Until 4
                If pvc(0,0) = True And ptc(1,0) = False
                    x+=1
                    facing = 1
                End If
            Next
        End If
    End Method
    Method regularmode()        
        If jumpofvine = True
            If Millisecs() > jumpofvinetimeout Then jumpofvine=False
        End If
        'Left and Right movement
        If KeyDown(KEY_RIGHT)
            For Local i=0 Until 4 ' move with 4 pixels at a time
                If ptc(1,0) = False
                    x+=1
                    facing = 1
                End If
            Next
        End If
        If KeyDown(KEY_LEFT)
            For Local i=0 Until 4
                If ptc(-1,0) = False
                    x-=1
                    facing = 0
                End If
            Next
        End If
        'player gravity part
        'if in the air and not in jump
        If isjumping = False
            If ptc(0,1) = False
                isjumping=True
                incy=0
            End If
        End If
        ' jump
        If KeyDown(KEY_UP)
            If isjumping = False
                isjumping = True
                incy=-4
            End If
        End If
        ' if we are in a jump/falling down
        If isjumping=True
            If incy>=0 'if we are going down
                If incy<4 Then incy+=.1
                For Local i=0 Until(incy)
                    If ptc(0,1) = False
                        y+=1
                    Else
                        isjumping = False
                    End If
                Next
            End If
            If incy<0 'if we are going up
                incy+=.1
                For Local i=0 Until Abs(incy)
                    If ptc(0,-1) = False
                        y-=1
                    Else
                        incy=0
                    End If
                Next
            End If
        End If    
    End Method
    Method draw()
        SetColor 255,255,0
        DrawRect x,y,w,h
    End Method
End Class

Class deathwing
    Field x:Int,y:Int
    Field w:Int,h:Int
    Field state:String
    Field remove:Bool=False
    Field lasthurt:Int=Millisecs()
    
    Method New(x:Int,y:Int)
        Self.x = x
        Self.y = y
        w = 32
        h = 32
        state = "flyup"
    End Method
    Method update()    
        hurtplayer    
        Local x1:Int = ((Self.x-mapsx+16)/tilewidth)+mapx
        Local y1:Int = ((Self.y)/tileheight)+mapy
        canattack
        Select state
            Case "attack"
                If p.x < x Then x-=1
                If p.y < y Then y-=1
                If p.x > x Then x+=1
                If p.y > y Then y+=1
            Case "flyup"                
                ' if high enough
                If y1<12 Then 
                    If Rnd(10)<5                    
                        state="flyleft"                        
                        Else
                        state="flyright"
                    End If                
                End If
                'if can fly up
                If mymaptest.map[x1][y1-2] = 1
                    y-=1
                Else
                    If Rnd(10)<5
                        state="flyleft"
                        Else
                        state="flyright"
                    End If                
                End If                
            Case "flyleft"
                If mymaptest.map[x1][y1] = 1
                    x-=1
                Else
                    state="flyright"
                End If
                If Rnd(150)<5
                    If canflyup(x1+2,y1) = True
                        state="flyup"
                    End If
                Elseif Rnd(150)>140
                    If canflydown(x1+2,y1) = True
                        state="flydown"
                    End If
                End If
            Case "flyright"
                If mymaptest.map[x1+2][y1] = 1
                    x+=1
                Else                
                    state="flyleft"
                End If
                If Rnd(150)<5 Then
                    If canflyup(x1,y1) = True
                        state="flyup"
                    End If
                Elseif Rnd(150)>140
                    If canflydown(x1,y1) = True
                        state="flydown"
                    End If
                End If
            Case "flydown"
                If mymaptest.map[x1][y1+1] = 1
                    y+=1
                    Else
                    state="flyup"
                End If
        End Select
    End Method
    Method hurtplayer()
        If lasthurt<Millisecs()
            lasthurt = Millisecs()+600
            If rectsoverlap(p.x,p.y,32,32,x,y,32,32)
                p.health-=1
            End If
        End If
    End Method
    Method canattack()
        If state="attack"
        If distance(p.x,p.y,x,y) > 32
            If Rnd(10)<5 Then
                state="flyright"
            Else
                state="flyleft"
            End    If            
        End If
        End If
        If rectsoverlap(p.x-16,p.y-16,96,96,x-16,y-16,96,96)
            state="attack"
        End If
    End Method
    Method canflydown:Bool(x1:Int,y1:Int)
        For Local y2=y1 To y1+5
            If mymaptest.map[x1][y2] <> 1 Then
                Return False
            End If
        Next
        Return True        
    End Method
    Method canflyup:Bool(x1:Int,y1:Int)
        If y1<14 Then Return False
        For Local y2=y1 To y1-5 Step -1
            If mymaptest.map[x1][y2] <> 1 Then
                Return False
            End If
        Next
        Return True        
    End Method
    Method draw()
        SetColor 0,250,20
        DrawOval x,y,w,h
        SetColor 255,255,255
    End Method
End Class

Class agent
    Field x:Int,y:Int
    Field w:Int,h:Int
    Field state:String
    Field remove:Bool=False
    Method New(x:Int,y:Int)
        Self.x = x
        Self.y = y
        w = 32
        h = 32
        state="right"
    End Method
    Method update()
        Local x1:Int = ((Self.x-mapsx+16)/tilewidth)+mapx
        Local y1:Int = ((Self.y)/tileheight)+mapy
        Select state
            Case "right"
            If mymaptest.map[x1+2][y1] = 0 Or
                mymaptest.map[x1+2][y1+1] = 1 Then
                state="left"
                Else
                x+=1
            End If
            Case "left"
            If mymaptest.map[x1][y1] = 0 Or
                mymaptest.map[x1][y1+1] = 1 Then
                state="right"
                Else 
                x-=1
            End If
        End Select
        If Rnd(1500)<2
            Local placeegg:Bool=True
            For Local i:=Eachin eggs
                If i.x = x1 And i.y = y1
                    placeegg=False
                End If
            Next
            If placeegg = True
                If mymaptest.map[x1][y1] = 1
                mymaptest.map[x1][y1] = 3
                eggs.AddLast(New egg(x1,y1) )
                End If
            End If
        End If
    End Method
    Method draw()
        SetColor 255,0,0
        DrawRect x,y,w,h
        SetColor 255,255,255
    End Method
End Class

Class egg
    Field x:Int,y:Int
    Field hatch:Bool=False
    Field remove:Bool=False
    Method New(x:Int,y:Int)
        Self.x = x
        Self.y = y
    End Method
End Class

Class inventory
    Field eggs:Int=0
    Field meat:Int=0
    Method New()
    End Method
    Method draw()
        SetColor 0,0,0
        DrawRect     0,DeviceHeight()-64,
                    DeviceWidth(),64
        SetColor 255,255,255
        DrawText "Eggs :"+eggs,10,DeviceHeight()-40
        DrawText "Meat :"+meat,10,DeviceHeight()-20
        DrawText "Health :"+p.health,100,DeviceHeight()-40
        DrawText "This game template might be updated if I get inspired",DeviceWidth()/3,DeviceHeight()-60
        DrawText "or if there are lots of hits on it. So check this",DeviceWidth()/3,DeviceHeight()-40
        DrawText "link in the future.",DeviceWidth()/3,DeviceHeight()-20
    End Method
End Class

' -----------------------------------------------------------------------------------------------

Global myinven:inventory = New inventory
Global mymaptest:maptest
Global p:player
Global a:List<agent> = New List<agent>
Global dw:List<deathwing> = New List<deathwing>
Global eggs:List<egg> = New List<egg>
Global myspear:spear = New spear

Class MyGame Extends App

    Method OnCreate()
        SetUpdateRate(60)
        restartgame
    End Method
    Method OnUpdate()    
        If p.health < 0 Or
            KeyHit(KEY_F1)
            restartgame
        End If
        p.update    
        alignmap
        For Local i:=Eachin a
            i.update
        Next
        For Local i:=Eachin dw
            i.update
            If i.remove = True 
                dw.Remove i
            End If
        Next        
        egghatch()
        myspear.update
    End Method
    Method OnRender()
        Cls 0,0,0 
        drawmap
        For Local i:=Eachin a
            i.draw
        Next
        For Local i:=Eachin dw
            i.draw
        Next
        myspear.draw
        p.draw        
        SetColor 0,0,0
        DrawRect 0,0,DeviceWidth(),50
        SetColor 255,255,255
        myinven.draw
        DrawText "Use Cursor left/right to move, cursor up to jump. Travel down the mine and mine eggs/meat.",0,0
        DrawText "Space to attack. t to take egg. p to place egg. Monsters spawn from eggs.",0,16
        DrawText "Monsters lay eggs. M - Show map.",0,32
        If KeyDown(KEY_M) Then
            Cls 0,0,0
            mymaptest.draw
        End If
    End Method
End Class



Function Main()
    New MyGame()
End Function

Function egghatch()
    'hatch deathwing
    For Local z=0 Until 2                    
        Local ax:Int=Rnd(mapwidth)
        Local ay:Int=Rnd(mapheight)
        If mymaptest.map[ax][ay] = 3
        If countdeathwings()<maxdeathwings    
            dw.AddLast( New deathwing(    (ax*tilewidth)-
                                        (mapx*tilewidth),
                                        (ay*tileheight)-
                                        (mapy*tileheight)+
                                        (mapsy) ) )        
            For Local i:=Eachin eggs
                If i.x = ax
                If i.y = ay
                    i.remove = True
                End If
                End If
            Next
            mymaptest.map[ax][ay]  = 1
            For Local i:=Eachin eggs
                If i.remove = True
                    eggs.Remove i
                End If
            Next                
            Exit
        End If
        End If
    Next
    'hatch breeder
    For Local z=0 Until mapwidth/2
        Local ax:Int=Rnd(mapwidth)
        Local ay:Int=Rnd(mapheight)
        If mymaptest.map[ax][ay] = 3
            For Local i:=Eachin eggs
            If i.x = ax And i.y = ay
                i.hatch = True
                For Local ii:=Eachin a
                    Local x1:Int = ((ii.x-mapsx+16)/tilewidth)+mapx
                    Local y1:Int = ((ii.y)/tileheight)+mapy

                    If distance(i.x,i.y,x1,y1) < 15 
                        i.hatch = False            
                    End If
                Next
            End If
            Next            
        End If        
    Next
    For Local i:=Eachin eggs
        If i.hatch = True
            mymaptest.map[i.x][i.y] = 1
            If Rnd(10) > 3  'hatch monster
                a.AddLast( New     agent(     (i.x*tilewidth)-
                                        (mapx*tilewidth),
                                        (i.y*tileheight)-
                                        (mapy*tileheight)+
                                        (mapsy) ) )
            End If
            i.remove = True
            For Local ii:=Eachin eggs
            If i<>ii
                If distance(i.x,i.y,ii.x,ii.y) < 10
                    ii.hatch=False
                End If
            End If
            Next
        End If
    Next
    For Local i:=Eachin eggs
        If i.remove = True Then
            eggs.Remove i
        End If
    Next
End Function

Function countdeathwings:Int()
    Local cnt:Int=0
    For Local i:=Eachin dw
        cnt+=1
    Next
    Return cnt
End Function

Function alignmap:Bool()
        For Local i=0 Until 4
        If p.x > DeviceWidth / 2
            If mapx+20 < mapwidth-1
                mapsx-=1
                If mapsx < 0 Then 
                    mapsx = 31
                    mapx += 1
                Endif
                p.x-=1
                p.movea(-1,0)
            End If
        End If
        Next

        For Local i=0 Until 4
        If p.x < DeviceWidth / 2
            If mapx > 0
                mapsx+=1
                If mapsx > 31 Then 
                    mapsx = 0
                    mapx -= 1
                Endif
                p.x+=1
                p.movea(1,0)
            End If
        End If
        Next
        ' scrolling down
        For Local i=0 Until 16
        If p.y > DeviceHeight / 2
            If mapy+14 < mapheight-1
                mapsy-=1
                If mapsy < 0 Then 
                    mapsy = 31
                    mapy += 1
                Endif
                p.y-=1
                p.movea(0,-1)
            End If
        End If
        Next
        ' scrolling up
        For Local i=0 Until 16
        If p.y < DeviceHeight / 2
            If mapy > 0
                mapsy+=1
                If mapsy > 31 Then 
                    mapsy = 0
                    mapy -= 1
                Endif
                p.y+=1
                p.movea(0,1)
            End If
        End If
        Next
End Function

'player collide with solid blocks true/false
Function ptc:Bool(offsetx:Int=0,offsety:Int=0)
    Local cx = (p.x+offsetx)/tilewidth+mapx
    Local cy = (p.y+offsety)/tileheight+mapy
    For Local y2=cy-1 Until cy+4
    For Local x2=cx-1 Until cx+4
        If x2>=0 And x2<mapwidth And y2>=0 And y2<mapheight
            If mymaptest.map[x2][y2] = 0
                Local x3 = (x2-mapx)*tilewidth-32+mapsx
                Local y3 = (y2-mapy)*tileheight+mapsy
                If rectsoverlap(p.x+offsetx,p.y+offsety,p.w,p.h,x3,y3,tilewidth,tileheight) = True
                    Return True
                End If
            End If
        End If
    Next
    Next
    Return False
End Function

'player collide with vines blocks true/false
Function pvc:Bool(offsetx:Int=0,offsety:Int=0)
    Local cx = (p.x+offsetx)/tilewidth+mapx
    Local cy = (p.y+offsety)/tileheight+mapy
    For Local y2=cy-1 Until cy+4
    For Local x2=cx-1 Until cx+4
        If x2>=0 And x2<mapwidth And y2>=0 And y2<mapheight
            If mymaptest.map[x2][y2] = 2
                Local x3 = (x2-mapx)*tilewidth-32+mapsx
                Local y3 = (y2-mapy)*tileheight+mapsy
                If rectsoverlap(p.x+offsetx,p.y+offsety,p.w,p.h,x3,y3,tilewidth,tileheight) = True
                    Return True
                End If
            End If
        End If
    Next
    Next
    Return False
End Function

Function drawmap:Void()
    For Local y=0 To 14
    For Local x=0 To 20
        Local x1 = ((x*tilewidth)+mapsx)-tilewidth
        Local y1 = ((y*tileheight)+mapsy)
        Select mymaptest.map[x+mapx][y+mapy]
            Case 0'Wall
            SetColor 100,100,100
            DrawRect x1,y1,tilewidth,tileheight
            Case 2'vine
            SetColor 10,100,10
            DrawRect x1,y1,tilewidth,tileheight
            Case 3'coin
            SetColor 200,200,10
            DrawOval x1+4,y1+4,tilewidth-8,tileheight-4
          End Select
     Next
     Next
     
End Function

Function restartgame()
    a.Clear()
    dw.Clear()
    eggs.Clear()
    mapx=0
    mapy=0
    mapsx=0
    mapsy=0
    mymaptest = New maptest(mapwidth,mapheight)
    p = New player
    p.x+=64
    p.movea(64,0)

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

Friday, December 4, 2015

Monkey-X - 2d Map Generator (Mazelike) - code example


This mazelike generator works like this. It finds a free position on the map and then build a wall there if there is space there. A wall can change directions while it is being created.

Import mojo

' This class holds the map.
' mapmaker selects a random pos in the map
' and then builds a wall there if there is space.
Class maptest
    Field tw:Int,th:Int
    Field w:Int,h: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
        makemap        
    End Method
    'make the map
    Method makemap()
        Local exitloop:Bool=False
        Local exitcount:Int=0
        While exitloop = False
            Local x:Int=Rnd(0,w)
            Local y:Int=Rnd(0,h)
            If mappartisfree(x,y) = True
                exitcount=0
                ' dir = direction 1 to 4
                ' dis = distance of wall
                Local dir:Int=Rnd(1,5)
                Local dis:Int=Rnd(4,10)
                makewall(x,y,dir,dis)
            Else
                exitcount+=1
            End If
            If exitcount>200 Then exitloop=True
        Wend
    End Method
    ' this method makes the walls
    Method makewall(x:Int,y:Int,dir:Int,dis:Int)
        ' px and py hold the wall and is drawn
        ' onto the map when the complete wall
        ' fits on the map.
        Local px:Int[dis]
        Local py:Int[dis]
        For Local i=0 Until dis
            px[i] = x
            py[i] = y
            Select dir
                Case 1;y-=1
                Case 2;x+=1
                Case 3;y+=1
                Case 4;x-=1
            End Select
            If Rnd(0,3) < 1 Then dir=Rnd(1,5)
            ' stay inside bounds or exit
            If x<0 Or x>=w Or y<0 Or y>=h Then Return
            ' if map position taken then exit
            If mappartisfree(x,y) = False Then Return
        Next
        ' here the wall is added to the map
        For Local i=0 Until dis
            map[px[i]][py[i]] = 1
        Next
    End Method
    ' check if the area around x,y is no wall
    Method mappartisfree:Bool(x,y)
        For Local y1=-1 To 1
        For Local x1=-1 To 1
            If x+x1>-1 And x+x1<w
            If y+y1>-1 And y+y1<h
                If map[x+x1][y+y1] = 1
                    Return False
                End If
            End If
            End If
        Next
        Next
        Return True
    End Method
    Method draw()
        SetColor 255,255,255
        For Local y=0 Until h
        For Local x=0 Until w
            If map[x][y] = 1
                DrawRect x*tw,y*th,tw,th
            End If
        Next
        Next
    End Method
End Class

Global mymaptest:maptest

Class MyGame Extends App
    Field mytime:Int
    Method OnCreate()
        SetUpdateRate(60)
        mymaptest = New maptest(Rnd(20,50),Rnd(15,30))
    End Method
    Method OnUpdate()  
        mytime+=1
        If KeyHit(KEY_SPACE) Or mytime>180
            mytime=0
            mymaptest = New maptest(Rnd(20,50),Rnd(15,30))
        End If      
    End Method
    Method OnRender()
        Cls 0,0,0 
        SetColor 255,255,255
        mymaptest.draw
        SetColor 255,255,255
        DrawText "Monkey-X - Map generator - mazelike (if space then place)",10,10
    End Method
End Class


Function Main()
    New MyGame()
End Function

Monkey-X - Filled Balls, WritePixels/CreateImage/Class - code example


I saw a certain kind of icon on my ipad and had the idea to make this kind of image in Monkey- In the code images are created that look like some kind of rainbow balls. They are drawn to the screen.

Import mojo

Class filledballs
    Field myc:Int=0 'oval color
    Field x:Int,y:Int
    Field w:Int,h:Int
    Field im:Image
    Field pixels:Int[]
    Method New(x:Int,y:Int,w:Int,h:Int,c:Int)
        Self.x = x
        Self.y = y
        Self.w = w
        Self.h = h
        myc=c
        pixels = New Int[w*h]
        im = CreateImage(w,h,1,Image.MidHandle)
        For Local i=0 Until im.Width()*im.Height()
            pixels[i] = $00000000
        Next
        Local i2:Int=0
        For Local i=(w/2)-1 To 1 Step -1
            Local col:Int=0
            Select myc
                Case 0;col=argb(i2,i2,i2,255)
                Case 1;col=argb(i2,0,i2,255)
                Case 2;col=argb(i2,i2,0,255)
                Case 3;col=argb(i2,0,0,255)
                Case 4;col=argb(0,i2,i2,255)
                Case 5;col=argb(0,0,i2,255)
                Case 6;col=argb(0,i2,0,255)
            End Select
            drawo(w/2,w/2,i,col)
            i2+=255/(w/2)
        Next
        im.WritePixels(pixels, 0, 0, w, h, 0)
    End Method
    Method drawo(x1,y1,radius,col)
        For Local y2=-radius To radius
        For Local x2=-radius To radius
            If (y2*y2+x2*x2) <= radius*radius+radius*0.8
                Local x3 = x2+x1
                Local y3 = y2+y1
                Local pc = y3*im.Width()+x3
                If pc>=0 And pc < im.Width()*im.Height()
                    pixels[pc] = col
                End If
            End If
        Next
        Next      
    End Method
    Function argb:Int(r:Int, g:Int, b:Int ,alpha:Int=255)
        Return (alpha Shl 24) | (r Shl 16) | (g Shl 8) | b          
    End Function     
    Method draw()
        DrawImage im,x,y
    End Method
End Class

Global myfball:List<filledballs> = New List<filledballs>

Class MyGame Extends App

    Method OnCreate()
        SetUpdateRate(60)
        For Local y=0 To DeviceHeight() Step 64
        For Local x=0 To DeviceWidth() Step 64
            myfball.AddLast(New filledballs(x,y,64,64,Rnd(0,7)))
        Next
        Next
        For Local x=0 To DeviceWidth()+96 Step 96
            myfball.AddLast(New filledballs(x,100,96,96,Rnd(07)))
        Next
    End Method
    Method OnUpdate()        
    End Method
    Method OnRender()
        Cls 0,0,0 
        For Local i:=Eachin myfball
            i.draw
        Next
        SetColor 0,0,0
        DrawRect 0,100,DeviceWidth(),20
        SetColor 255,255,255
        DrawText "MonkeyX - Filled balls, WritePixels/CreateImage",10,105
    End Method
End Class


Function Main()
    New MyGame()
End function