Wiki
Clone wikiSpecGine / Pause
Adding pause menu
In this section we want to add option to pause game and select whether we want to continue it, start new game or return to main menu.
Pause Menu state
We start by creating empty state representing pause menu in file core/src/main/scala/PauseMenu.scala
.
#!scala package com.specdevs.ping import com.specdevs.specgine.states.MenuState class PauseMenu extends MenuState { def initialize() {} def create() {} def dispose() {} }
initialize
method of Ping
class.
#!scala def initialize() { //... addState(new PauseMenu, "PauseMenu", "Menus") }
Note that we add state called "PauseMenu"
to "Menus"
state group, so we are sure that we can safely use "defaultSkin"
.
Implementing Pause Menu
Like in MainMenu
implementation section, we start from creating screen for PauseMenu
.
Creating empty Pause screen
We create empty pause screen in file core/src/main/scala/PauseScreen.scala
.
#!scala package com.specdevs.ping import com.specdevs.specgine.states.gdx.MenuScreen class PauseScreen extends MenuScreen(width=Some(800), height=Some(480)) { def initialize() {} def create() {} def dispose() {} }
MainScreen
, we set width
and height
in constructor of PauseScreen
.
Now we add new screen to initialize
method of PauseMenu
.
#!scala def initialize() { addMenuScreen("Pause", new PauseScreen) }
Adding buttons to Pause screen
We want to have three buttons in pause menu. "Resume" button which will jump back to the currently played game, "New game" which will start
completely new game and "Quit to main menu" button for returning to MainMenu
. We place code implementation in create
method in of PauseScreen
.
#!scala //... import com.specdevs.specgine.assets.Asset import com.specdevs.specgine.assets.gdx.ImplicitSkinAsset import com.badlogic.gdx.scenes.scene2d.{Actor=>GdxActor} import com.badlogic.gdx.scenes.scene2d.ui.{Skin=>GdxSkin,TextButton=>GdxTextButton} import com.badlogic.gdx.scenes.scene2d.utils.{ChangeListener=>GdxChangeListener} import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.{ChangeEvent=>GdxChangeEvent} //... def create() { val skin = get[Asset,GdxSkin]("defaultSkin") val button = new GdxTextButton("Resume", skin) table.add(button).width(120).pad(10) button.addListener(new GdxChangeListener { def changed(event: GdxChangeEvent, actor: GdxActor) { popState() } }) table.row() val button1 = new GdxTextButton("New game", skin) table.add(button1).width(120).pad(10) button1.addListener(new GdxChangeListener { def changed(event: GdxChangeEvent, actor: GdxActor) { pushState("MainMenu") pushState("Play") } }) table.row() val button0 = new GdxTextButton("Quit to menu", skin) table.add(button0).width(120).pad(10) button0.addListener(new GdxChangeListener { def changed(event: GdxChangeEvent, actor: GdxActor) { pushState("MainMenu") } }) () } //...
Similar to MainMenu
, we first obtain defaultSkin
from "Menus"
group and next we add three buttons.
First button returns to currently played game by executing popStat
method. This will remove PauseState
from state stack
and the previous state, game state in this case, will be the current one. The second button will start completely new game by
executing pushState
method twice, firstly jumping to MainMenu
state and then to GameState
itself. Because MainMenu
state
is already on stack, executing pushState
method will pop all states that are on top of MainMenu
state until it becomes active.
Than we push GameState
on stack. Finally, the third button will move us to MainMenu
by executing pushState
method only once.
At this point we have nice PauseMenu
with some functionality, but we are not able to access it. Now we have to inform Play
class
that we want to jump to PauseMenu
if user click escape key. For any other device user can set any other key which will pause the game.
Pasuing the game
We need to adjust InputSystem
to process escape button from keyboard and back button from Android.
To do so we firstly override backUp
method and change end
method of InputSystem
so after all other keys
were processed, but before key queue was cleared we check whether escape key was clicked.
#!scala import com.badlogic.gdx.Input.{Keys=>GdxKeys} import com.specdevs.specgine.input.BackReceiver //... class InputSystem extends SingleEntitySystem with KeyReceiver with PointerReceiver with BackReceiver with Processor { //... override def backUp() = { keysQueue.enqueue((GdxKeys.ESCAPE, false)) true } override def end(dt: Float) { for ((key, state) <- keysQueue; if key==GdxKeys.ESCAPE && !state) { pushState("PauseMenu") } } }
PauseMenu
is a black screen with three buttons. We now want to improve the rendering system,
so PauseMenu
will be displayed on current game screen, but table and paddles will be rendered in gray colors.
Rendering frozen state
To render frozen game state we need to inform RenderSystem
that we are pausing the game. To do so first we need to change RenderSystem
and
Play
class. We first add public variable to RenderSystem
which will indicate whether we want to render frozen state and set it to false.
We also need to override resizeFrozen
method, because we render frozen scene and we need to make sure it was correctly resized.
#!scala //... class RenderSystem extends SingleEntitySystem with Renderer { //... private var frozen = false //... def renderFrozen(alpha: Float) { frozen = true renderAll(alpha) frozen = false } override def resizeFrozen(x: Int, y: Int) { resize(x, y) } }
Next we change RenderSystem
in Play
class to be a variable and later we override renderFrozen
method.
#!scala //... class Play extends GameState { private var rs: RenderSystem = null //... def intialize() { //... rs = new RenderSystem addSystem(rs) //... } override def renderFrozen(alpha: Float, simulationAlpha: Float) { rs.renderFrozen(simulationAlpha) } }
renderBackground
of PasueMenu
state. This method will inform StateManager
that it wants to render frozen game state as its background.
#!scala override def renderBackground(alpha: Float) { renderFrozenState(alpha) }
Now when we pause the game, the background of PasueMenu
will be the current image of played game. To indicate that we are pausing the game,
we will change rendered colors of table and paddles to be gray. We do so by changing renderPaddle
and renderTable
methods.
Rendering frozen paddle
#!scala private def renderPaddle(pos: Position, p: Paddle, c: Option[Color]) { //... if (frozen) { val gray = 0.21f*col.r + 0.71f*col.g + 0.07f*col.b renderer.setColor(gray, gray, gray, 1f) } else { renderer.setColor(col.r, col.g, col.b, 1f) } //... }
Rendering frozen table
#!scala private def renderTable(pos: Position, t: Table) { //... val tableColour = if (frozen) { Color(0.81f, 0.81f, 0.81f) } else { Color(0.5f, 1.0f, 0.5f) } //... }
PauseMenu
is displayed on grayed table and with gray paddles.
In next section we are going to add scores and winning screen to our game to make it
fully playable.
Having troubles with this step?
Here you can download project with all above steps completed.
Updated