About Monkey 2 › Forums › Monkey 2 Code Library › Platformer Example
Tagged: Platform Template Platformer
This topic contains 7 replies, has 5 voices, and was last updated by Skaruts 8 months, 1 week ago.
-
AuthorPosts
-
January 27, 2018 at 10:05 pm #13290Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245Namespace plattyapp#Import "<std>"#Import "<mojo>"#Import "assets/dave.png"#Import "assets/cubes.png"#Import "assets/level1.txt"Using std..Using mojo..Class Platty Extends WindowGlobal LevelData:String[]Global LevelArray:Int[,]Field imgDave:Image[]Field floorTiles2:Image[]Field cDave:DaveMethod New( title:String="Platty",width:Int=512, height:Int=960, flags:WindowFlags=Null )Super.New( title,width,height,flags )Local sr:StreamimgDave = LoadSpriteSheet("asset::dave.png", 27, 64, 64, True, 1)floorTiles2 = LoadSpriteSheet("asset::cubes.png", 7, 64, 64)For Local xi:Int = 0 Until 27imgDave[xi].Handle = New Vec2f(0.5,0)NextLevelArray = New Int[ 8,12 ]LevelData = New String[1]sr = Stream.Open("asset::level1.txt", "r")LevelData[0] = sr.ReadString()Local tempx:Int = -1Local tempy:Int = 0For Local xi:Int = 0 To LevelData[0].Lengthtempx += 1If tempx > 7tempx = 0tempy +=1If tempy > 11 Then ExitEndifLevelArray[ tempx,tempy ] = Int(LevelData[0].Mid(xi, 1))NextFor Local x:Int = 0 Until 8For Local y:Int = 0 Until 12If LevelArray[ x,y ] = 2Local xi:Int = GetX(x)Local yi:Int = GetY(y)If Not cDave Then cDave = New Dave( imgDave , xi, 640, 5, 1 )EndifNextNextLevelData = New String[50]EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()canvas.Clear(Color.Black)For Local x:Int = 0 Until 8For Local y:Int = 0 Until 12If LevelArray[ x,y ] = 1canvas.DrawImage(floorTiles2[6], x * 64, y * 64)EndifNextNextIf cDave <> NullFor Local d:Dave = Eachin Dave.dListd.Draw(canvas)NextEndifIf cDave <> NullFor Local d:Dave = Eachin Dave.dListd.Update()NextEndifEndEndFunction Main()New AppInstanceNew PlattyApp.Run()EndClass DaveGlobal dList:List<Dave>Global timer:Int = Millisecs()Global frame:Int = 1Field x:FloatField y:FloatField sp:FloatField direction:IntField image:Image[]Field canJump:Int = 1Field isJumping:Int = 0Field jumpHeight:Float = 10Field isFalling:Int = 1Field gravity:Float = 0.45Method New ( img:Image[], xl:Float, yl:Float, speed:Float, direc:Int)If dList = Null Then dList = New List<Dave>Self.x = xlSelf.y = ylSelf.direction = direcSelf.image = imgSelf.sp = speeddList.Add(Self)EndMethod Update()If Keyboard.KeyHit(Key.Space) And canJump = 1'direction = 3'frame = 12isJumping = 1canJump = 0EndifIf isJumping = 1y = y - jumpHeightjumpHeight = jumpHeight - gravityIf jumpHeight <= 0isFalling = 1isJumping = 0jumpHeight = 12EndifEndifIf isFalling = 1y += jumpHeightjumpHeight = jumpHeight + gravityIf Platty.LevelArray[ x / 64, y / 64 + 1] = 1If ( y Mod 64 ) < jumpHeight * 2y = y - ( y Mod 64 )isFalling = 0canJump = 1jumpHeight = 12EndifEndifEndifIf isFalling = 0 And isJumping = 0If Platty.LevelArray[x / 64, y / 64 + 1] <> 1isFalling = 1EndifEndifIf x >= 64 + 32If Keyboard.KeyDown(Key.Left) And Not Keyboard.KeyDown(Key.Right)x -= spIf Keyboard.KeyHit(Key.Left)direction = 0timer = Millisecs()frame = 6EndifIf Millisecs() > timer + 40frame +=1If frame = 10 Then frame = 6timer = Millisecs()EndifEndifEndifIf x <= 512 - 96If Keyboard.KeyDown(Key.Right) And Not Keyboard.KeyDown(Key.Left)x += spIf Keyboard.KeyHit(Key.Right)direction = 1timer = Millisecs()frame = 6EndifIf Millisecs() > timer + 40frame +=1If frame = 10 Then frame = 6timer = Millisecs()EndifEndifEndifEndMethod Draw(canvas:Canvas)If direction = 0canvas.DrawImage(image[frame], x, y, Null, -1, 1)Elseif direction = 1canvas.DrawImage(image[frame], x, y, Null, 1, 1)EndifEndEnd ClassFunction GetX:Float(x:Float)Return x * 64End FunctionFunction GetY:Float(y:Float)Return y * 64End FunctionFunction LoadSpriteSheet:Image[] ( path:String, numFrames:Int, cellWidth:Int, cellHeight:Int, filter:Bool = True, preScale:Float = 1.0, padding:Int = 0, border:Int = 0 )Local atlasTexture := Texture.Load( path, Null )Assert( atlasTexture, " ~n ~nGameGraphics: Image " + path + " not found.~n ~n" )Local imgs := New Image[ numFrames ]Local atlasImg := New Image( atlasTexture )'If Not filter Then atlasImg.TextureFilter = TextureFilter.NearestLocal paddedWidth:= cellWidth + ( padding * 2 )Local paddedHeight:= cellHeight + ( padding * 2 )Local columns:Int = ( atlasImg.Width - border - border ) / paddedWidthFor Local i:= 0 Until numFramesLocal col := i Mod columnsLocal x := ( col * paddedWidth ) + padding + borderLocal y := ( ( i / columns ) * paddedHeight ) + padding + borderimgs[i] = New Image( atlasImg, New Recti( x , y, x + cellWidth, y + cellHeight ) )imgs[i].Scale = New Vec2f( preScale, preScale )NextatlasImg = NullReturn imgsEndJanuary 28, 2018 at 1:18 am #13299
Nice little example Amon 🙂
It runs too fast on my PC, so I needed to add a timer to slow it down.
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250Namespace plattyapp#Import "<std>"#Import "<mojo>"#Import "assets/dave.png"#Import "assets/cubes.png"#Import "assets/level1.txt"Using std..Using mojo..Class Platty Extends WindowGlobal LevelData:String[]Global LevelArray:Int[,]Field imgDave:Image[]Field floorTiles2:Image[]Field cDave:DaveField timer:Timer ' ADDED TIMER!Method New( title:String="Platty",width:Int=512, height:Int=960, flags:WindowFlags=Null )Super.New( title,width,height,flags )Local sr:StreamimgDave = LoadSpriteSheet("asset::dave.png", 27, 64, 64, True, 1)floorTiles2 = LoadSpriteSheet("asset::cubes.png", 7, 64, 64)For Local xi:Int = 0 Until 27imgDave[xi].Handle = New Vec2f(0.5,0)NextLevelArray = New Int[ 8,12 ]LevelData = New String[1]sr = Stream.Open("asset::level1.txt", "r")LevelData[0] = sr.ReadString()Local tempx:Int = -1Local tempy:Int = 0For Local xi:Int = 0 To LevelData[0].Lengthtempx += 1If tempx > 7tempx = 0tempy +=1If tempy > 11 Then ExitEndifLevelArray[ tempx,tempy ] = Int(LevelData[0].Mid(xi, 1))NextFor Local x:Int = 0 Until 8For Local y:Int = 0 Until 12If LevelArray[ x,y ] = 2Local xi:Int = GetX(x)Local yi:Int = GetY(y)If Not cDave Then cDave = New Dave( imgDave , xi, 640, 5, 1 )EndifNextNextLevelData = New String[50]timer = New Timer(60, OnUpdate) ' NEW TIMER RUNNING AT 60FPSEndMethod OnUpdate() ' MOVED LOGIC TO ONUPDATEIf cDave <> NullFor Local d:Dave = Eachin Dave.dListd.Update()NextEndifEndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()canvas.Clear(Color.Black)For Local x:Int = 0 Until 8For Local y:Int = 0 Until 12If LevelArray[ x,y ] = 1canvas.DrawImage(floorTiles2[6], x * 64, y * 64)EndifNextNextIf cDave <> NullFor Local d:Dave = Eachin Dave.dListd.Draw(canvas)NextEndifEndEndFunction Main()New AppInstanceNew PlattyApp.Run()EndClass DaveGlobal dList:List<Dave>Global timer:Int = Millisecs()Global frame:Int = 1Field x:FloatField y:FloatField sp:FloatField direction:IntField image:Image[]Field canJump:Int = 1Field isJumping:Int = 0Field jumpHeight:Float = 10Field isFalling:Int = 1Field gravity:Float = 0.45Method New ( img:Image[], xl:Float, yl:Float, speed:Float, direc:Int)If dList = Null Then dList = New List<Dave>Self.x = xlSelf.y = ylSelf.direction = direcSelf.image = imgSelf.sp = speeddList.Add(Self)EndMethod Update()If Keyboard.KeyHit(Key.Space) And canJump = 1'direction = 3'frame = 12isJumping = 1canJump = 0EndifIf isJumping = 1y = y - jumpHeightjumpHeight = jumpHeight - gravityIf jumpHeight <= 0isFalling = 1isJumping = 0jumpHeight = 12EndifEndifIf isFalling = 1y += jumpHeightjumpHeight = jumpHeight + gravityIf Platty.LevelArray[ x / 64, y / 64 + 1] = 1If ( y Mod 64 ) < jumpHeight * 2y = y - ( y Mod 64 )isFalling = 0canJump = 1jumpHeight = 12EndifEndifEndifIf isFalling = 0 And isJumping = 0If Platty.LevelArray[x / 64, y / 64 + 1] <> 1isFalling = 1EndifEndifIf x >= 64 + 32If Keyboard.KeyDown(Key.Left) And Not Keyboard.KeyDown(Key.Right)x -= spIf Keyboard.KeyHit(Key.Left)direction = 0timer = Millisecs()frame = 6EndifIf Millisecs() > timer + 40frame +=1If frame = 10 Then frame = 6timer = Millisecs()EndifEndifEndifIf x <= 512 - 96If Keyboard.KeyDown(Key.Right) And Not Keyboard.KeyDown(Key.Left)x += spIf Keyboard.KeyHit(Key.Right)direction = 1timer = Millisecs()frame = 6EndifIf Millisecs() > timer + 40frame +=1If frame = 10 Then frame = 6timer = Millisecs()EndifEndifEndifEndMethod Draw(canvas:Canvas)If direction = 0canvas.DrawImage(image[frame], x, y, Null, -1, 1)Elseif direction = 1canvas.DrawImage(image[frame], x, y, Null, 1, 1)EndifEndEnd ClassFunction GetX:Float(x:Float)Return x * 64End FunctionFunction GetY:Float(y:Float)Return y * 64End FunctionFunction LoadSpriteSheet:Image[] ( path:String, numFrames:Int, cellWidth:Int, cellHeight:Int, filter:Bool = True, preScale:Float = 1.0, padding:Int = 0, border:Int = 0 )Local atlasTexture := Texture.Load( path, Null )Assert( atlasTexture, " ~n ~nGameGraphics: Image " + path + " not found.~n ~n" )Local imgs := New Image[ numFrames ]Local atlasImg := New Image( atlasTexture )'If Not filter Then atlasImg.TextureFilter = TextureFilter.NearestLocal paddedWidth:= cellWidth + ( padding * 2 )Local paddedHeight:= cellHeight + ( padding * 2 )Local columns:Int = ( atlasImg.Width - border - border ) / paddedWidthFor Local i:= 0 Until numFramesLocal col := i Mod columnsLocal x := ( col * paddedWidth ) + padding + borderLocal y := ( ( i / columns ) * paddedHeight ) + padding + borderimgs[i] = New Image( atlasImg, New Recti( x , y, x + cellWidth, y + cellHeight ) )imgs[i].Scale = New Vec2f( preScale, preScale )NextatlasImg = NullReturn imgsEndAnd by doing so you can see a little bug which sometimes makes “Dave” float upwards…
January 28, 2018 at 7:38 am #13312Heya, Cheers. 🙂
Ahh, that’s a silly bug. Fixed, I think. Change the code below by adding a canJump = 0 after isFalling = 1.
Monkey12345If isFalling = 0 And isJumping = 0If Platty.LevelArray[x / 64, y / 64 + 1] <> 1isFalling = 1EndifEndifNew code
Monkey123456If isFalling = 0 And isJumping = 0If Platty.LevelArray[x / 64, y / 64 + 1] <> 1isFalling = 1canJump = 0EndifEndifJanuary 29, 2018 at 6:03 pm #13336Nice. The movement feels good.
I think I now also figured out how to use assets. I have not used those before in Monkey2.
January 30, 2018 at 7:48 am #13347@pakz I cheat, put everything in an assests folder and just use:
Monkey1#Import "assets/"Which will copy over all the assets 🙂
June 14, 2018 at 2:35 pm #14842Is there a way to render a portion of an image without having to create new ones, as you do in the LoadSpriteSheet function?
imgs[i] = New Image( atlasImg, New Recti( x , y, x + cellWidth, y + cellHeight ) )
June 14, 2018 at 10:34 pm #14845Is there a way to render a portion of an image without having to create new ones, as you do in the LoadSpriteSheet function?
There are versions of Canvas.DrawRect that have a source image parameter, eg:Â DrawRect( x,y,w,h,srcimage:Image,srcx,srcy,srcw,srch )
June 15, 2018 at 12:12 am #14846Which way do you think would be faster?
Because now that I’m thinking about it, I suppose the amount of draw calls will be the same.
(I would use this for a terminal emulator, for a classical roguelike.)
-
AuthorPosts
You must be logged in to reply to this topic.