Difference between revisions of "Tuto Gideros Game Template1 Part 7 Game"

From GiderosMobile
(wip)
 
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
__TOC__
 
__TOC__
 
== The Game Scene ==
 
== The Game Scene ==
This is going to be the last scene for our Gideros Game Template1 tutorial.
+
This is going to be the last scene for our Gideros Game Template1 tutorial. A quick and simple one because you may decide to organize your game differently.
  
This is going to be a quick and simple one because you may decide to organize your game differently.
+
'''Note: we will code the player actor in the next chapter'''
  
Usually, when I make games, prototypes, I put all my levels in one scene. When I change level I reload the game scene with a variable indicating the current level, eg.: currlevel = 1, 2, ...
+
Usually, when I make games and prototypes, I put all my levels in one scene. When I change levels I reload the '''Game''' scene with a variable indicating the current level, eg.: ''currlevel'' = 1, 2, ... and load the appropriate assets (graphics, sounds, ...).
  
For the reason cited above and for how long I have been using this kind of architecture, I decided to call the game Class: '''LevelX''' (please feel free to change it).
+
I have been using this kind of architecture for quite some time, instead of calling my game scenes Level1, Level2, ..., I decided to call it: '''LevelX'''.
  
Our '''Game''' scene (LevelX) will mainly consist of:
+
The '''Game''' scene ('''LevelX''') will mainly consist of:
 +
* a pause variable
 
* moving the mouse cursor out of the way :-)
 
* moving the mouse cursor out of the way :-)
* dividing our scene into layers (Sprite): background layer, fx layer, actors layer, foreground layer, ...
+
* arranging our graphics into layers: ''background'', ''actors'', ''foreground'', ...
* the game loop
+
* a game loop
  
== The Options scene code ==
+
It makes sense to create the file in the '''scenes''' folder. You can call the file ''levelX.lua'', and the code:
It makes sense to create the file in the '''scenes''' folder. You can call the file "''options.lua''". Here is the code:
 
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 +
LevelX = Core.class(Sprite)
 +
 +
local ispaused = false
 +
 +
function LevelX:init()
 +
-- move the cursor out of the way
 +
if not application:isPlayerMode() then
 +
local sw, sh = application:get("screenSize") -- the user's screen size!
 +
application:set("cursorPosition", sw, sh) -- 0, 0
 +
end
 +
-- layer sprites
 +
local mainlayer = Sprite.new() -- one Sprite to hold them all
 +
local bglayer = Sprite.new() -- background layer
 +
local bgfxlayer = Sprite.new() -- background fx layer
 +
local actorslayer = Sprite.new() -- actors layer
 +
local fgfxlayer = Sprite.new() -- foreground fx layer
 +
local fglayer = Sprite.new() -- foreground layer
 +
-- current level assets
 +
local bggfx, fggfx
 +
if g_currlevel == 1 then
 +
bggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight)
 +
fggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight/8)
 +
elseif g_currlevel == 2 then
 +
bggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight)
 +
elseif g_currlevel == 3 then
 +
bggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight)
 +
fggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight/16)
 +
end
 +
-- the player1
 +
self.player1 = Player1.new()
 +
-- position
 +
if bggfx then bggfx:setPosition(0+myappleft, 0+myapptop) end
 +
if fggfx then fggfx:setPosition(0+myappleft, myappheight+myapptop-fggfx:getHeight()) end
 +
self.player1.x = myappwidth/2+myappleft
 +
self.player1.y = myappheight/2+myapptop
 +
self.player1:setPosition(self.player1.x, self.player1.y)
 +
-- add children to corresponding layer
 +
if bggfx then bglayer:addChild(bggfx) end -- add the background graphics to the background layer if any
 +
if fggfx then fglayer:addChild(fggfx) end -- add the foreground graphics to the foreground layer if any
 +
actorslayer:addChild(self.player1)
 +
-- order
 +
mainlayer:addChild(bglayer) -- first the background layer
 +
mainlayer:addChild(bgfxlayer) -- then the background fx layer
 +
mainlayer:addChild(actorslayer) -- then the actors layer
 +
mainlayer:addChild(fgfxlayer) -- then the foreground fx layer
 +
mainlayer:addChild(fglayer) -- lastely the foreground layer
 +
-- the main sprite
 +
self:addChild(mainlayer) -- the only Sprite layer that needs to be added to to scene tree hierarchy!
 +
-- the game loop
 +
self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
 +
-- let's go
 +
self:myKeysPressed()
 +
end
 +
 +
-- game loop
 +
local dt
 +
function LevelX:onEnterFrame(e)
 +
if not ispaused then
 +
dt = e.deltaTime
 +
if self.player1.isleft and not self.player1.isright and self.player1.x > 0 then -- LEFT
 +
self.player1.vx = -self.player1.speed*dt
 +
self.player1.flip = -1
 +
elseif self.player1.isright and not self.player1.isleft and self.player1.x < myappwidth then -- RIGHT
 +
self.player1.vx = self.player1.speed*dt
 +
self.player1.flip = 1
 +
else -- IDLE
 +
self.player1.vx = 0
 +
end
 +
if self.player1.isup and not self.player1.isdown and self.player1.y > 0 then -- UP
 +
self.player1.vy = -self.player1.speed*dt
 +
elseif self.player1.isdown and not self.player1.isup and self.player1.y < myappheight then -- DOWN
 +
self.player1.vy = self.player1.speed*dt
 +
else
 +
self.player1.vy = 0
 +
end
 +
-- actions
 +
if self.player1.isactionpunch1 then
 +
self.player1.vx *= 0.5*dt -- you choose, magik XXX
 +
self.player1.vy *= 0.5*dt -- you choose, magik XXX
 +
elseif self.player1.isactionpunch2 then
 +
self.player1.vx *= 0.25*dt -- you choose, magik XXX
 +
self.player1.vy *= 0.25*dt -- you choose, magik XXX
 +
elseif self.player1.isactionpunch3 then
 +
self.player1.vx *= 0.1*dt -- you choose, magik XXX
 +
self.player1.vy *= 0.1*dt -- you choose, magik XXX
 +
end
 +
-- move and flip
 +
self.player1.x += self.player1.vx
 +
self.player1.y += self.player1.vy
 +
self.player1:setPosition(self.player1.x, self.player1.y)
 +
self.player1.sprite:setScale(self.player1.sx * self.player1.flip, self.player1.sy)
 +
end
 +
end
 +
 +
-- keys handler
 +
function LevelX:myKeysPressed()
 +
self:addEventListener(Event.KEY_DOWN, function(e) -- KEY_UP
 +
if e.keyCode == KeyCode.ESC or e.keyCode == KeyCode.BACK then self:gotoScene() end -- MENU
 +
if e.keyCode == KeyCode.P then ispaused = not ispaused print("is paused: "..tostring(ispaused)) end -- PAUSE
 +
-- modifier
 +
local modifier = application:getKeyboardModifiers()
 +
local alt = (modifier & KeyCode.MODIFIER_ALT) > 0
 +
if (not alt and e.keyCode == KeyCode.ENTER) then -- nothing here!
 +
elseif alt and e.keyCode == KeyCode.ENTER then -- SWITCH FULLSCREEN
 +
ismyappfullscreen = not ismyappfullscreen
 +
application:setFullScreen(ismyappfullscreen)
 +
end
 +
end)
 +
end
 +
 +
-- scenes navigation
 +
function LevelX:gotoScene()
 +
self:removeAllListeners()
 +
for i = stage:getNumChildren(), 1, -1 do
 +
stage:removeChildAt(i)
 +
end collectgarbage()
 +
stage:addChild(Transitions.new(Menu.new())) -- next scene
 +
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
== Code comments ==
 
== Code comments ==
Sometimes a key doesn't have a KeyCode visual, eg.: the arrow keys. The local ''keyNames'' variable will translate the KeyCode of a key to a more user friendly name.
+
We start by defining a ''ispaused'' to pause the game using the letter '''P''' on the keyboard.
  
 
=== init ===
 
=== init ===
In the ''init'' function we add:
+
We move the mouse cursor out of the way. Done!
* a title for the scene
 
* the sliders to set the game sound volume and difficulty
 
* the '''keys to control the player''' which can be remapped
 
  
We listen for any key that can be remapped and activate the remap key system when "clicked".
+
The main layer is the Parent of all the other layers, this way you could use the '''mainlayer''' Sprite as a camera, a viewport, ...:
 +
* mainlayer '''Sprite''' ''Parent''
 +
** bglayer '''Sprite''' ''Child''
 +
** bgfxlayer '''Sprite''' ''Child''
 +
** actorslayer '''Sprite''' ''Child''
 +
** fgfxlayer '''Sprite''' ''Child''
 +
** fglayer '''Sprite''' ''Child''
  
The keys are added to the ''btns'' table which serves the keyboard navigation system.
+
The graphics for our game are put in their corresponding layer as children of that layer.
  
We add the sliders listeners and will save any modified value to the user preference file.
+
Finally we choose the order to display the layers. Here the first layer to be drawn is the background layer and all the other layers will be drawn on top:
 +
* bglayer (drawn first)
 +
* bgfxlayer
 +
* actorslayer
 +
* fgfxlayer
 +
* fglayer (drawn last, on top of all the others)
  
The mouse listener will cancel any key remapping when clicked outside of a remappable key.
+
=== the game loop ===
 +
If the game is not in Pause mode it will execute what's inside it.
  
Finally we update our buttons visuals and we are ready to process any change to a slider value or a key remapping event.
+
=== keys handler ===
 
+
We listen to any key press and switch the state of the game, go back to the Menu scene, ...
=== key remapping ===
 
When we click on a remappable key (most of the buttons in this scene), the new value (KeyCode) will be assigned to that key. A friendly name will be displayed to show the change.
 
 
 
When the remapping is validated we save it to the user preference file.
 
 
 
=== buttons actions ===
 
The buttons will trigger different actions according to the button id. If it is a remappable key we activate the remap system, if it is the MENU button we go back to the Menu scene.
 
  
 
== Next? ==
 
== Next? ==
We hopefully have a good base for an '''Options''' scene. The final scene for this tutorial will be the '''Game''' scene.
+
Well, to test that everything works fine, we add a player :-)
 
 
  
Prev.: [[Tuto Gideros Game Template1 Part 6 Options]]
 
  
'''END'''
+
Prev.: [[Tuto Gideros Game Template1 Part 6 Options]]</br>
 +
'''Next: [[Tuto Gideros Game Template1 Part 8 Player]]'''
  
  
 
'''[[Tutorial - Gideros Game Template1]]'''
 
'''[[Tutorial - Gideros Game Template1]]'''
 
{{GIDEROS IMPORTANT LINKS}}
 
{{GIDEROS IMPORTANT LINKS}}

Latest revision as of 19:35, 27 October 2024

The Game Scene

This is going to be the last scene for our Gideros Game Template1 tutorial. A quick and simple one because you may decide to organize your game differently.

Note: we will code the player actor in the next chapter

Usually, when I make games and prototypes, I put all my levels in one scene. When I change levels I reload the Game scene with a variable indicating the current level, eg.: currlevel = 1, 2, ... and load the appropriate assets (graphics, sounds, ...).

I have been using this kind of architecture for quite some time, instead of calling my game scenes Level1, Level2, ..., I decided to call it: LevelX.

The Game scene (LevelX) will mainly consist of:

  • a pause variable
  • moving the mouse cursor out of the way :-)
  • arranging our graphics into layers: background, actors, foreground, ...
  • a game loop

It makes sense to create the file in the scenes folder. You can call the file levelX.lua, and the code:

LevelX = Core.class(Sprite)

local ispaused = false

function LevelX:init()
	-- move the cursor out of the way
	if not application:isPlayerMode() then
		local sw, sh = application:get("screenSize") -- the user's screen size!
		application:set("cursorPosition", sw, sh) -- 0, 0
	end
	-- layer sprites
	local mainlayer = Sprite.new() -- one Sprite to hold them all
	local bglayer = Sprite.new() -- background layer
	local bgfxlayer = Sprite.new() -- background fx layer
	local actorslayer = Sprite.new() -- actors layer
	local fgfxlayer = Sprite.new() -- foreground fx layer
	local fglayer = Sprite.new() -- foreground layer
	-- current level assets
	local bggfx, fggfx
	if g_currlevel == 1 then
		bggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight)
		fggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight/8)
	elseif g_currlevel == 2 then
		bggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight)
	elseif g_currlevel == 3 then
		bggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight)
		fggfx = Pixel.new(math.random(0xffffff), 1, myappwidth, myappheight/16)
	end
	-- the player1
	self.player1 = Player1.new()
	-- position
	if bggfx then bggfx:setPosition(0+myappleft, 0+myapptop) end
	if fggfx then fggfx:setPosition(0+myappleft, myappheight+myapptop-fggfx:getHeight()) end
	self.player1.x = myappwidth/2+myappleft
	self.player1.y = myappheight/2+myapptop
	self.player1:setPosition(self.player1.x, self.player1.y)
	-- add children to corresponding layer
	if bggfx then bglayer:addChild(bggfx) end -- add the background graphics to the background layer if any
	if fggfx then fglayer:addChild(fggfx) end -- add the foreground graphics to the foreground layer if any
	actorslayer:addChild(self.player1)
	-- order
	mainlayer:addChild(bglayer) -- first the background layer
	mainlayer:addChild(bgfxlayer) -- then the background fx layer
	mainlayer:addChild(actorslayer) -- then the actors layer
	mainlayer:addChild(fgfxlayer) -- then the foreground fx layer
	mainlayer:addChild(fglayer) -- lastely the foreground layer
	-- the main sprite
	self:addChild(mainlayer) -- the only Sprite layer that needs to be added to to scene tree hierarchy!
	-- the game loop
	self:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
	-- let's go
	self:myKeysPressed()
end

-- game loop
local dt
function LevelX:onEnterFrame(e)
	if not ispaused then
		dt = e.deltaTime
		if self.player1.isleft and not self.player1.isright and self.player1.x > 0 then -- LEFT
			self.player1.vx = -self.player1.speed*dt
			self.player1.flip = -1
		elseif self.player1.isright and not self.player1.isleft and self.player1.x < myappwidth then -- RIGHT
			self.player1.vx = self.player1.speed*dt
			self.player1.flip = 1
		else -- IDLE
			self.player1.vx = 0
		end
		if self.player1.isup and not self.player1.isdown and self.player1.y > 0 then -- UP
			self.player1.vy = -self.player1.speed*dt
		elseif self.player1.isdown and not self.player1.isup and self.player1.y < myappheight then -- DOWN
			self.player1.vy = self.player1.speed*dt
		else
			self.player1.vy = 0
		end
		-- actions
		if self.player1.isactionpunch1 then
			self.player1.vx *= 0.5*dt -- you choose, magik XXX
			self.player1.vy *= 0.5*dt -- you choose, magik XXX
		elseif self.player1.isactionpunch2 then
			self.player1.vx *= 0.25*dt -- you choose, magik XXX
			self.player1.vy *= 0.25*dt -- you choose, magik XXX
		elseif self.player1.isactionpunch3 then
			self.player1.vx *= 0.1*dt -- you choose, magik XXX
			self.player1.vy *= 0.1*dt -- you choose, magik XXX
		end
		-- move and flip
		self.player1.x += self.player1.vx
		self.player1.y += self.player1.vy
		self.player1:setPosition(self.player1.x, self.player1.y)
		self.player1.sprite:setScale(self.player1.sx * self.player1.flip, self.player1.sy)
	end
end

-- keys handler
function LevelX:myKeysPressed()
	self:addEventListener(Event.KEY_DOWN, function(e) -- KEY_UP
		if e.keyCode == KeyCode.ESC or e.keyCode == KeyCode.BACK then self:gotoScene() end -- MENU
		if e.keyCode == KeyCode.P then ispaused = not ispaused print("is paused: "..tostring(ispaused)) end -- PAUSE
		-- modifier
		local modifier = application:getKeyboardModifiers()
		local alt = (modifier & KeyCode.MODIFIER_ALT) > 0
		if (not alt and e.keyCode == KeyCode.ENTER) then -- nothing here!
		elseif alt and e.keyCode == KeyCode.ENTER then -- SWITCH FULLSCREEN
			ismyappfullscreen = not ismyappfullscreen
			application:setFullScreen(ismyappfullscreen)
		end
	end)
end

-- scenes navigation
function LevelX:gotoScene()
	self:removeAllListeners()
	for i = stage:getNumChildren(), 1, -1 do
		stage:removeChildAt(i)
	end collectgarbage()
	stage:addChild(Transitions.new(Menu.new())) -- next scene
end

Code comments

We start by defining a ispaused to pause the game using the letter P on the keyboard.

init

We move the mouse cursor out of the way. Done!

The main layer is the Parent of all the other layers, this way you could use the mainlayer Sprite as a camera, a viewport, ...:

  • mainlayer Sprite Parent
    • bglayer Sprite Child
    • bgfxlayer Sprite Child
    • actorslayer Sprite Child
    • fgfxlayer Sprite Child
    • fglayer Sprite Child

The graphics for our game are put in their corresponding layer as children of that layer.

Finally we choose the order to display the layers. Here the first layer to be drawn is the background layer and all the other layers will be drawn on top:

  • bglayer (drawn first)
  • bgfxlayer
  • actorslayer
  • fgfxlayer
  • fglayer (drawn last, on top of all the others)

the game loop

If the game is not in Pause mode it will execute what's inside it.

keys handler

We listen to any key press and switch the state of the game, go back to the Menu scene, ...

Next?

Well, to test that everything works fine, we add a player :-)


Prev.: Tuto Gideros Game Template1 Part 6 Options
Next: Tuto Gideros Game Template1 Part 8 Player


Tutorial - Gideros Game Template1