'Based on the game Legend of Pandora.
Import mojo Global tilewidth:Int=10 Global tileheight:Int=10 Class map Field tilewidth:Float Field tileheight:Float Field mapwidth:Int Field mapheight:Int Field screenwidth:Int Field screenheight:Int Field map:Int[][] Method New( screenwidth:Int, screenheight:Int, mapwidth:Int, mapheight:Int) Self.screenwidth = screenwidth Self.screenheight = screenheight Self.mapwidth = mapwidth Self.mapheight = mapheight Self.tilewidth = Float(screenwidth)/Float(mapwidth) Self.tileheight = Float(screenheight)/Float(mapheight) map = New Int[mapwidth][] For Local i=0 Until mapwidth map[i] = New Int[mapheight] Next map[mapwidth/2][mapheight/2] = 3 ' 3 is a door makemap End Method Method makemap() Local timeout:Int While timeout<(mapwidth*mapheight)*20 timeout+=1 Local x:Int=Rnd(11,mapwidth-11) Local y:Int=Rnd(11,mapheight-11) If map[x][y] = 3 makeroom(x,y) End If Wend 'here we turn doors into walls 'if they should be walls For Local y1=1 Until mapheight-1 For Local x1=1 Until mapwidth-1 If map[x1][y1] = 3 Local cnt:Int=0 For Local y2=y1-1 To y1+1 For Local x2=x1-1 To x1+1 If map[x2][y2] = 2 Then cnt+=1 Next Next If cnt>3 Then map[x1][y1] = 2 End If Next Next 'here we turn doors into walls if they ' touch tiles that are nothing (0) For Local y1=1 Until mapheight-1 For Local x1=1 Until mapwidth-1 If map[x1][y1] = 3 Local cnt:Int=0 For Local y2=y1-1 To y1+1 For Local x2=x1-1 To x1+1 If map[x2][y2] = 0 Then cnt+=1 Next Next If cnt>0 Then map[x1][y1] = 2 End If Next Next 'here we turn the doors into floors For Local y1=0 Until mapheight For Local x1=0 Until mapwidth If map[x1][y1] = 3 Then map[x1][y1] = 1 Next Next End Method Method makeroom(x:Int,y:Int) Local side:String If map[x][y-1] = 0 side="up" Elseif map[x+1][y] = 0 side="right" Elseif map[x][y+1] = 0 side="down" Elseif map[x-1][y] = 0 side="left" End If Local w:Int=Rnd(5,10) Local h:Int=Rnd(5,10) If side="up" Local x1:Int=x-w/2 Local y1:Int=y-h If roomfits(x1,y1,w,h) insertroom(x1,y1,w,h+1) 'door up map[x1+Rnd(2,w-2)][y1] = 3 ' door right map[x1+w-1][y1+Rnd(2,h-2)] = 3 'door left map[x1][y1+Rnd(2,h-2)] = 3 End If End If If side="right" Local x1:Int=x+1 Local y1:Int=y-h/2 If roomfits(x1,y1,w,h) insertroom(x1-1,y1,w,h) 'door up map[x1+Rnd(2,w-2)][y1] = 3 'door down map[x1+Rnd(2,w-2)][y1+h-1] = 3 ' door right map[x1+w-2][y1+Rnd(2,h-2)] = 3 End If End If If side="left" Local x1:Int=x-w Local y1:Int=y-h/2 If roomfits(x1,y1,w,h) insertroom(x1,y1,w+1,h) 'door up map[x1+Rnd(2,w-2)][y1] = 3 'door down map[x1+Rnd(2,w-2)][y1+h-1] = 3 'door left map[x1][y1+Rnd(2,h-2)] = 3 End If End If If side="down" Local x1:Int=x-w/2 Local y1:Int=y+1 If roomfits(x1,y1,w,h) insertroom(x1,y1-1,w,h) 'door down map[x1+Rnd(2,w-2)][y1+h-2] = 3 'door left map[x1][y1+Rnd(2,h-2)] = 3 ' door right map[x1+w-1][y1+Rnd(2,h-2)] = 3 End If End If End Method Method insertroom(x,y,w,h) For Local y2=y Until y+h For Local x2=x Until x+w If map[x2][y2] <> 3 Then map[x2][y2] = 2 Next Next For Local y2=y+1 Until y+h-1 For Local x2=x+1 Until x+w-1 map[x2][y2] = 1 Next Next End Method Method roomfits(x:Int,y:Int,w:Int,h:Int) For Local y1=y Until y+h For Local x1=x Until x+w If map[x1][y1] = 1 Then Return False Next Next Return True End Method Method draw() For Local y=0 Until mapheight For Local x=0 Until mapwidth Select map[x][y] Case 0 Case 1'floor SetColor 100,100,100 DrawRect x*tilewidth, y*tileheight, tilewidth+1, tileheight+1 Case 2'wall SetColor 200,200,200 DrawRect x*tilewidth, y*tileheight, tilewidth+1, tileheight+1 Case 3'wall SetColor 244,244,0 DrawRect x*tilewidth, y*tileheight, tilewidth+1, tileheight+1 End Select Next Next End Method End Class Class enemy Field x:Float,y:Float Field ms:Float 'movement speed Field w:Int=mymap.tilewidth-8 Field h:Int=mymap.tileheight-8 Field hp:Int Field hpceil:Int Field direction:String="up" ' left/right/up/down Field current:Bool=False 'if being updated Field deleteme:Bool=False Method New() ' find a spot to place the new enemy Local exitloop:Bool=False Local cnt:Int=0 While exitloop=False exitloop = True Local nx = Rnd(50,640-50) Local ny = Rnd(50,480-50) Local mx:Int=nx/mymap.tilewidth Local my:Int=ny/mymap.tileheight If mymap.map[mx][my] <> 1 Then exitloop = False For Local i:=Eachin myenemy If distance(nx,ny,i.x,i.y) < 30 Or distance(myplayer.x,myplayer.y,nx,ny) < 250-cnt exitloop = False End If Next If exitloop = True Then x = nx y = ny End If cnt+=1 Wend ' Here we set the movement speed ms = Rnd(.1,.5) ' Here we set the hitpoints hp = Rnd(1,50) ' the ceiling is what he has or had at start (powerbar) hpceil = hp End Method Method update() current=True ' store the old location Local oldx:Float=x Local oldy:Float=y ' move the enemy towards the player If collide(x+1,y) = False And x < myplayer.x Then x+=ms direction = "right" End If If collide(x-1,y) = False And x > myplayer.x Then x-=ms direction = "left" End If If collide(x,y+1) = False And y < myplayer.y Then y+=ms direction = "down" End If If collide(x,y-1) = False And y > myplayer.y Then y-=ms direction = "up" End If untangle() current=False End Method ' if the enemies are inside of each other ' then move them apart Method untangle() For Local i:=Eachin myenemy If i.current=False If distance(i.x,i.y,x,y) < w Local a:Int a = getangle(i.x,i.y,x,y) Local nx:Float=x Local ny:Float=y nx += Cos(a)*1 ny += Sin(a)*1 Local mx:Int=nx/mymap.tilewidth Local my:Int=ny/mymap.tileheight If mymap.map[mx][my] = 1 x = nx y = ny End If End If End If Next End Method Method draw() SetColor 255,255,0 DrawOval x-w/2,y-w/2,w,w 'powerbar Local current:Float=(Float(w)/Float(hpceil))*hp SetColor 0,0,0 DrawRect x-w/2,y+w/2,w,5 SetColor 255,0,0 DrawRect x-w/2,y+1+w/2,current,3 End Method Method collide:Bool(xx:Int,yy:Int) For Local i:=Eachin myenemy If i.current = False If distance(xx,yy,i.x,i.y) < w Then Return True End If Next Local mx:Int=xx/mymap.tilewidth Local my:Int=yy/mymap.tileheight If mymap.map[mx][my] <> 1 Then Return true Return False End Method Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Local dx = x2 - x1 Local dy = y2 - y1 Return ATan2(dy,dx)+360 Mod 360 End Function End Class Class player Field x:Float,y:Float Field w:Int=mymap.tilewidth-8 Field h:Int=mymap.tileheight-8 Field wx:Int,wy:Int Field direction:String="up" ' up/left/down/right Field weapondamage:Int=3 Field swing:Bool=False Field swingcountdown:Int=0 Method New() Local exitloop:Bool=False While exitloop = False x = Rnd(640) y = Rnd(480) Local mx:Int=x/mymap.tilewidth Local my:Int=y/mymap.tileheight If mymap.map[mx][my] = 1 Then exitloop = True Wend direction = "up" End Method Method update() updatecontrols() weaponenemies() End Method Method weaponenemies() If swing = False Then Return For Local i:=Eachin myenemy If distance(i.x,i.y,wx,wy) < w+5 'make sure the weapon does not hit throught ' walls Local mx:Int=wx/mymap.tilewidth Local my:Int=wy/mymap.tileheight If mymap.map[mx][my] <> 1 Then Exit 'distance with the enemy Local a:Int=getangle(wx,wy ,i.x,i.y) For Local ww:Int=0 Until w Local nx:Float=i.x Local ny:Float=i.y nx += Cos(a) * 1 ny += Sin(a) * 1 Local mx:Int=nx/mymap.tilewidth Local my:Int=ny/mymap.tileheight If mymap.map[mx][my] = 1 Then i.x = nx i.y = ny Else Exit End If Next i.hp -= weapondamage If i.hp<1 Then i.deleteme = True End If Next End Method Method updatecontrols() ' store the location of the player Local oldx:Int=x Local oldy:Int=y 'handle the movement If collide(x+1,y)=False And KeyDown(KEY_RIGHT) Then x+=1 direction = "right" swing=False End If If collide(x-1,y)=False And KeyDown(KEY_LEFT) Then x-=1 direction = "left" swing=False End If If collide(x,y-1)=False And KeyDown(KEY_UP) Then y-=1 direction = "up" swing=False End If If collide(x,y+1)=False And KeyDown(KEY_DOWN) Then y+=1 direction = "down" swing=False End If 'Handle the weapon If swing = False If KeyDown(KEY_SPACE) Then swing=True If direction = "left" Then wx=x-w ; wy=y If direction = "right" Then wx=x+w ; wy=y If direction = "up" Then wx=x ; wy=y-h If direction = "down" Then wx=x ; wy=y+h swingcountdown = 20 End If Else swingcountdown-=1 If swingcountdown<0 Then swing=False End If End Method ' collide with map Method collide:Bool(xx:Int,yy:Int) Local mx:Int=xx/mymap.tilewidth Local my:Int=yy/mymap.tileheight If mymap.map[mx][my] <> 1 Then Return True Return False End Method Method draw() SetColor 255,100,0 DrawOval x-w/2,y-w/2,w,w If swing = True 'where does the swing graphic get drawn DrawOval wx-w/2,wy-w/2,w,w End If End Method Function getangle:Int(x1:Int,y1:Int,x2:Int,y2:Int) Local dx = x2 - x1 Local dy = y2 - y1 Return ATan2(dy,dx)+360 Mod 360 End Function Function distance:Int(x1:Int,y1:Int,x2:Int,y2:Int) Return Abs(x2-x1)+Abs(y2-y1) End Function End Class Global myplayer:player Global myenemy:List<enemy> = New List<enemy> Global mymap:map Class MyGame Extends App Method OnCreate() SetUpdateRate(60) mymap = New map(640,480,30,30) myplayer = New player() 'For Local i:=0 Until 10 ' myenemy.AddLast(New enemy()) 'Next End Method Method OnUpdate() myplayer.update() ' update the enemies For Local i:=Eachin myenemy i.update() Next ' if enemy hitpoint below 1 then remove him from list For Local i:=Eachin myenemy If i.deleteme = True Then myenemy.Remove(i) Next If myenemy.IsEmpty Local ms:Int=Rnd(30,36) mymap = New map(640,480,ms,ms) myplayer = New player() Local ecnt:Int=Rnd(2,10) For Local i:=0 Until ecnt myenemy.AddLast(New enemy()) Next End If End Method Method OnRender() Cls 0,0,0 mymap.draw() For Local i:=Eachin myenemy i.draw() Next myplayer.draw() SetColor 255,255,255 DrawText "Player vs Monsters on Random map",0,0 DrawText "Space = Weapon , Cursor l/r/u/d = movement",0,20 End Method End Class Function Main() New MyGame() End Function
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.