Diddy Tutorials - Simple Shoot 'em Up

Monkey Archive Forums/Monkey Tutorials/Diddy Tutorials - Simple Shoot 'em Up

therevills(Posted 2014) [#1]
Following on from the Screen Based Framework tutorial, let’s create a game with Diddy :)

Diddy has a Sprite class which has basic sprite based functionality to make coding games faster.

To load resources such as images and sounds, Diddy has a resource manager so you can store your images/sounds and retrieve them quickly and easily.

Let’s start by creating the folder structure for our new game:

DiddyShootEmUp\
	main.data\
		graphics\
		sounds\


When using the resource managers Diddy expects graphics to be in a graphics folder and sounds in a sounds folder.

Create the main file in DiddyShootEmUp called “main.monkey”, this file is the entry point for your game:

main.monkey
Strict

Import diddy

Function Main:Int()
	MyGame.GetInstance()
	Return True
End

Class MyGame Extends DiddyApp
	Global instance:MyGame = Null

	Method Create:Void()
		' set the virtual resolution
		SetScreenSize(800, 450, True)
	End
	
	Function GetInstance:MyGame()
		If instance = Null
			instance = New MyGame()
		End
		Return instance
	End
End 


I’m using the Singleton Pattern again for the MyGame class, in the future you could declare a font or something in here and refer to it via the GetInstance function.

The SetScreenSize takes in the virtual resolution you want for your game, width and height. Set the Boolean to be True if you want Diddy to look after the aspect ratio for you.

Let’s load some resources:

Strict

Import diddy

Function Main:Int()
	MyGame.GetInstance()
	Return True
End

Class MyGame Extends DiddyApp
	Global instance:MyGame = Null

	Method Create:Void()
		' set the virtual resolution
		SetScreenSize(800, 450, True) ' 16:9 ratio
		' load the resources
		LoadImages()
		LoadSounds()
	End
	
	Function GetInstance:MyGame()
		If instance = Null
			instance = New MyGame()
		End
		Return instance
	End
	
	Method LoadImages:Void()
		' load in an animation 64x64 with 7 frames
		images.LoadAnim("ship.png", 64, 64, 7)
		' load in a background image
		images.Load("background.png", "", false)
	End
	
	Method LoadSounds:Void()
		' load the sounds
		sounds.Load("boom3.ogg")
		sounds.Load("lazer.ogg")
	End
	
End


The “images” and “sounds” are resource managers within Diddy. When loading images Diddy will auto midhandle them, we don’t want the background to be midhandled so we set the Boolean to false. The resource managers are a hashmap with the name of the file as the key, but you can override the key if you want.

Copy the following files into the graphics folder:





Copy the following files into the sounds folder:

https://dl.dropboxusercontent.com/u/35103024/tutorials/boom3.ogg

https://dl.dropboxusercontent.com/u/35103024/tutorials/lazer.ogg

Time for some screens, create a new file called “titlescreen.monkey” and one called “gamescreen.monkey” – remember case is important in MonkeyX!

main.monkey
 Strict

Import diddy
Import titlescreen

Function Main:Int()
	MyGame.GetInstance()
	Return True
End

Class MyGame Extends DiddyApp
	Global instance:MyGame = Null

	Method Create:Void()
		' set the virtual resolution
		SetScreenSize(800, 450, True) ' 16:9 ratio
		' load the resources
		LoadImages()
		LoadSounds()
		Start(TitleScreen.GetInstance())
	End
	
	Function GetInstance:MyGame()
		If instance = Null
			instance = New MyGame()
		End
		Return instance
	End
	
	Method LoadImages:Void()
		' load in an animation 64x64 with 7 frames
		images.LoadAnim("ship.png", 64, 64, 7)
		' load in a background image
		images.Load("background.png", "", false)
	End
	
	Method LoadSounds:Void()
		' load the sounds
		sounds.Load("boom3.ogg")
		sounds.Load("lazer.ogg")
	End
	
End


titlescreen.monkey

Strict
Import main
Import gamescreen

Class TitleScreen Extends Screen
	Global instance:TitleScreen = Null
	
	Function GetInstance:TitleScreen()
		If instance = Null
			instance = New TitleScreen()
		End
		Return instance
	End
	
	Method New()
		name = "TitleScreen"
	End
	
	Method Start:Void()
		
	End
	
	Method Update:Void()
		If KeyHit(KEY_SPACE)
			FadeToScreen(GameScreen.GetInstance())
		End
	End
	
	Method Render:Void()
		Cls
		DrawText("Diddy Shoot'em Up!", SCREEN_WIDTH2, SCREEN_HEIGHT2, 0.5, 0.5)
		DrawText("Press Space to Play!", SCREEN_WIDTH2, SCREEN_HEIGHT2 + 50, 0.5, 0.5)
	End
		
End


Notice the SCREEN_WIDTH2 and SCREEN_HEIGHT2 variables, Diddy calculates half the screen dimensions and stores them in these variables for fast access.

gamescreen.monkey

 Strict

Import main
Import titlescreen

Class GameScreen Extends Screen
	Global instance:GameScreen = Null
	Field backgroundImage:GameImage
	
	Function GetInstance:GameScreen()
		If instance = Null
			instance = New GameScreen()
		End
		Return instance
	End

	Method New()
		name = "GameScreen"
	End
	
	Method Start:Void()
		' set the background image
		backgroundImage = diddyGame.images.Find("background")
	End
	
	Method Update:Void()
		If KeyHit(KEY_ESCAPE)
			FadeToScreen(TitleScreen.GetInstance())
		End
	End
	
	Method Render:Void()
		Cls
		backgroundImage.Draw(0, 0)
	End	
End


Run the game, you will have a title screen and a game screen.

Now for sprites :)

Create a new file called “gameobjects.monkey”, you can of course create multiple files with only one class in each, but for ease of reading I’m going to add them to this one file:

gameobjects.monkey

Strict

Import diddy

Class Player Extends Sprite
	Field score:Int = 0
	
	Method New(img:GameImage, x:Float, y:Float)
		Self.image = img
		Self.x = x
		Self.y = y
		Self.alpha = 1
		Self.SetHitBox(-img.image.HandleX(), -img.image.HandleY(), img.w, img.h)
		Self.visible = True
		Self.speedX = 8
	End
	
	Method Update:Void()
		' controls
		If KeyDown(KEY_LEFT)
			Self.x -= Self.speedX * dt.delta
		End
		If KeyDown(KEY_RIGHT)
			Self.x += Self.speedX * dt.delta
		End
		
		' boundary check
		If Self.x < Self.image.w2 Then Self.x = Self.image.w2
		If Self.x > SCREEN_WIDTH - Self.image.w2 Then Self.x = SCREEN_WIDTH - Self.image.w2
	End
End 


The “dt” variable is a global within Diddy so that you can access the built in Delta Timing class, this is to ensure that your movement is the same on all devices.

Better update gamescreen.monkey:

gamescreen.monkey

Strict

Import main
Import titlescreen
Import gameobjects

Class GameScreen Extends Screen
	Global instance:GameScreen = Null
	Field backgroundImage:GameImage
	Field player:Player
	
	Function GetInstance:GameScreen()
		If instance = Null
			instance = New GameScreen()
		End
		Return instance
	End

	Method New()
		name = "GameScreen"
	End
	
	Method Start:Void()
		' set the background image
		backgroundImage = diddyGame.images.Find("background")
		player = New Player(diddyGame.images.Find("ship"), SCREEN_WIDTH2, SCREEN_HEIGHT - 50)
		player.frame = 3
	End
	
	Method Update:Void()
		player.Update()
		
		If KeyHit(KEY_ESCAPE)
			FadeToScreen(TitleScreen.GetInstance())
		End
	End
	
	Method Render:Void()
		Cls
		backgroundImage.Draw(0, 0)
		player.Draw()
	End	
End


Now run the code, you should see your player’s ship on the screen and be able to move it using the cursor keys.

For bullets, alter gameobjects.monkey:

gameobjects.monkey
 Strict

Import diddy

Class Player Extends Sprite
	Field score:Int = 0
	Field lazerSnd:GameSound
	
	Method New(img:GameImage, x:Float, y:Float)
		Self.image = img
		Self.x = x
		Self.y = y
		Self.alpha = 1
		Self.SetHitBox(-img.image.HandleX(), -img.image.HandleY(), img.w, img.h)
		Self.visible = True
		Self.speedX = 8
		Self.lazerSnd = diddyGame.sounds.Find("lazer")
	End
	
	Method Update:Void()
		' controls
		If KeyDown(KEY_LEFT)
			Self.x -= Self.speedX * dt.delta
		End
		If KeyDown(KEY_RIGHT)
			Self.x += Self.speedX * dt.delta
		End
		If KeyHit(KEY_SPACE)
			Self.lazerSnd.Play()
			New Bullet(x, y)
		End
		
		' boundary check
		If Self.x < Self.image.w2 Then Self.x = Self.image.w2
		If Self.x > SCREEN_WIDTH - Self.image.w2 Then Self.x = SCREEN_WIDTH - Self.image.w2
	End
End

Class Bullet Extends Sprite
	Global list:List<Bullet> = New List<Bullet>
	
	Field w:Int
	Field h:Int
	
	Method New(x:Float, y:Float)
		Self.x = x
		Self.y = y
		Self.w = 10
		Self.h = 10
		Self.alpha = 1
		Self.SetHitBox(-w, -h, w, h)
		Self.speedY = 10
		list.AddLast(Self)
	End
	
	Method Draw:Void()
		DrawOval(x - w / 2, y - h / 2, w, h)
	End
	
	Method Update:Void()
		y -= speedY * dt.delta
		If y < - h
			Kill()
		End
	End
	
	Method Kill:Void()
		list.Remove(Self)
	End
	
	Function DrawAll:Void()
		For Local b:Bullet = EachIn list
			b.Draw()
		End
	End

	Function UpdateAll:Void()
		For Local b:Bullet = EachIn list
			b.Update()
		End
	End
		
End


And alter gamescreen.monkey:

 Strict

Import main
Import titlescreen
Import gameobjects

Class GameScreen Extends Screen
	Global instance:GameScreen = Null
	Field backgroundImage:GameImage
	Field player:Player
	
	Function GetInstance:GameScreen()
		If instance = Null
			instance = New GameScreen()
		End
		Return instance
	End

	Method New()
		name = "GameScreen"
	End
	
	Method Start:Void()
		' set the background image
		backgroundImage = diddyGame.images.Find("background")
		player = New Player(diddyGame.images.Find("ship"), SCREEN_WIDTH2, SCREEN_HEIGHT - 50)
		player.frame = 3
	End
	
	Method Update:Void()
		player.Update()
		Bullet.UpdateAll()
		
		If KeyHit(KEY_ESCAPE)
			FadeToScreen(TitleScreen.GetInstance())
		End
	End
	
	Method Render:Void()
		Cls
		backgroundImage.Draw(0, 0)
		Bullet.DrawAll()
		player.Draw()
	End	
End


That’ll do for now, you have a ship which can move and a bullet which you can fire.


Snader(Posted 2014) [#2]
Thank you for these diddy tutorials. I hope this will get you a lot of new users for the Diddy framework.


consty(Posted 2014) [#3]
Nice tutorials


okee(Posted 2014) [#4]
Hi, just trying out this demo but get an error in main.monkey
at approx line 32

---> Unable to find overload for LoadAnim(String,Int,Int,Int)

images.LoadAnim("ship.png", 64, 64, 7)


Asmodean(Posted 2014) [#5]
Unable to find overload for LoadAnim(String,Int,Int,Int)


Works fine for me.
Is it possible that you have a typo, a point instead of a comma? Something like images.LoadAnim("ship.png", 64, 64.7)


Paul - Taiphoz(Posted 2014) [#6]
mate you should think about doing that again as a video tut on youtube.


turizoft(Posted 2014) [#7]
Hi, I'm new to Monkey and therefore to Diddy. I have a couple of questions!

1. Do I need to use the Pro version of Monkey to run Diddy?
2. Does it replace Mojo or does it run alongside it?
3. What targets can my code run in when using Diddy?

Thanks a lot!


Paul - Taiphoz(Posted 2014) [#8]
No
No - Yes
All

There may be some compatibility issues if your using an older version of the Free monkey, just update both to the latest and you should be good to go. not a lot of time to do a proper reply, if you need more clarification just shout.