Games [BANanoPhaser] Basic Phaser Games Development with BANano

Mashiane

Expert
Licensed User
Longtime User
Ola

Download BANanoPhaser

Phaser is a popular game framework that enables one to quickly build games for the web. To do this we will make some assumptions

1. You are comfortable with JavaScript
2. You are comfortable with BANano esp BANanoObject class.

Related Threads

Star Catcher - game basics
Dino Dash - sounds, tiles, logos, game restart, scrolling effect.
Approximately - resource loading progress, using external fonts, scaling game.

Game 1: BreakOut

This has been ported from this StackAbuse article and it provides a nice introduction of how phaser and games kinda work. We are not reharshing anything here you can read the article in parallel with the code in this thread. With this game, only the basic Phaser implementation has been built just to build this game.

PhaserBreakOut.gif


For anyone willing to start creating games with Phaser, you can do so in BANanao with BANanoPhaser. This is rather a massive library so we just cover the basics here to get you going.

With comments, the code for this game is just about 240 lines of code. To develop this game we are using Phaser 3. This will introduce one to Phaser.

We need to remember 3 things here, 1. Preload (this for loading our game assets to the cache), 2. Create (this for where we create the actual game) and 3. Update (this is where movement, animation in the game happens and how we control that)

So our game has such callback subs to control how everything works.
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
1. We have some global variables that we need to define first that are accessible across the game.

B4X:
Sub Process_Globals
    Private BANano As BANano
    Private body As BANanoElement
    Private game As BANanoPhaser
    Private gameDiv As BANanoElement
    
    'global variables
    Private player As BANanoObject
    Private ball As BANanoObject
    Private violetBricks As BANanoObject
    Private yellowBricks As BANanoObject
    Private redBricks As BANanoObject
    '
    Private gameStarted As Boolean = False
    Private openingText As BANanoObject
    Private gameOverText As BANanoObject
    Private playerWonText As BANanoObject
    '
    Private Scene As PhaserScene
    
End Sub

  • We have a player - i.e. the paddle
  • We have a ball that we will hit
  • We have some assortements of bricks
  • We also have Start text, game over and game won text
 

Mashiane

Expert
Licensed User
Longtime User
2. We initialize the game, build up the code for the 3 methods, preload, create and update and then start the game.

We create a div inside the body where we will render the game. The code has been commented as much as possible to give us an idea of what is happening.

B4X:
Sub Init
    'set the body of the page
    body = BANano.GetElement("#body")
    body.SetStyle(BANano.ToJson(CreateMap("margin":"0 auto","padding":"0","width":"100%", "height":"100%")))
    body.Empty
    'add the div to set the game in
    'we will use inline style
    gameDiv = body.Append($"<div id="game"></div>"$).Get("#game")
    gameDiv.SetStyle(BANano.ToJson(CreateMap("margin": "10px auto", "padding": "0", "width": "800px", "height": "640px")))
    'lets set up the game
    'initialze the game, use game element and set size
    game.Initialize
    'The Type can be Phaser.CANVAS, Phaser.WEBGL Or Phaser.AUTO. AUTO means that
    'Phaser will Try To render with WebGL, And fall back To Canvas If it fails
    game.SetTypeAuto(True)
    'element to inject the game in
    game.SetParent("game")
    game.SetWidth(800)
    game.SetHeight(640)
    'Ensure the canvas is resized to fit the parent div's dimensions
    game.SetScaleMode(game.ScaleModeRESIZE)
    'Center the game canvas both horizontally and vertically within the parent
    game.SetScaleAutoCenter(game.ScaleCenterCENTER_BOTH)
    'The physics engine determines how objects interact with the world. Phaser
    'supports three physics engines out of the box: arcade, impact and matter.
    ' Arcade is understood to be the simplest one to implement
    game.SetPhysicsDefault("arcade")
    game.SetPhysicsArcadeGravity(False)
    
    'create a scene there can be multiple scenes in the same game
    Scene = game.CreateScene("breakout")
    'steps in the game scene to execute
    Scene.SetOnPreload(Me, "onPreLoad")
    Scene.SetOnCreate(Me, "onCreate")
    Scene.SetOnUpdate(Me, "onUpdate")
    game.SetScene(Scene.Scene)
    '
    game.Start
End Sub

Next we look at the callback methods that make the game tick / work!
 

Mashiane

Expert
Licensed User
Longtime User
3. Preload Resources.

resources.png


There are some resources that we will use in our game, we have to preload these so that they are available in our game world!.

B4X:
' The function loads assets as Phaser begins to run the Scene. The images are
' loaded as key value pairs, we reference the assets by their keys of course
 Sub onPreload
    Log("preloading...")
    Scene.SceneLoadImage("ball", "./assets/ball_32_32.png")
    Scene.SceneLoadImage("paddle", "./assets/paddle_128_32.png")
    Scene.SceneLoadImage("brick1", "./assets/brick1_64_32.png")
    Scene.SceneLoadImage("brick2", "./assets/brick2_64_32.png")
    Scene.SceneLoadImage("brick3", "./assets/brick3_64_32.png")
End Sub
 

Mashiane

Expert
Licensed User
Longtime User
4. We now create the game... this involves placing the bricks, ball, paddle etc. This sub will also have some callback for when the paddle collides with the ball and the ball collides with the brick and the respective logic.

B4X:
' We create our game world in this function. The initial state of our game is
' defined here. We also set up our physics rules here
' Coordinates start at 0,0 from the top left
' As we move rightward, the x value increases
' As we move downward, the y value increases.
  
Sub onCreate
    Log("creating...")
    'add a sprite
    player = Scene.PhysicsAddSprite(400, 600, "paddle")
    ball = Scene.PhysicsAddSprite(400, 565, "ball")
    'add sprite grounds
    violetBricks = Scene.PhysicsAddGroup("brick1", 9, 80, 140, 70, True)
    yellowBricks = Scene.PhysicsAddGroup("brick2", 9, 80, 90, 70, True)
    redBricks = Scene.PhysicsAddGroup("brick3", 9, 80, 40, 70, True)
    'Manage key presses
      Scene.CreateCursorKeys
    'Ensure that the player and ball can't leave the screen
    Scene.SetCollideWorldBounds(player, True)
    Scene.SetCollideWorldBounds(ball, True)
    'The bounce ensures that the ball retains its velocity after colliding with an object.
    Scene.SetBounceXY(ball, 1, 1)
    ' Disable collision with the bottom of the game world. This needs to be added so the ball falls to the bottom, which means that the game is over
    Scene.SetPhysicsWorldCheckCollisionDown(False)
    'Add collision for the bricks
    Dim currentBall As BANanoObject
    Dim currentPlayer As BANanoObject
    Dim cbHitBrick As BANanoObject = BANano.CallBack(Me, "hitBrick", Array(currentBall, currentPlayer))
    Scene.PhysicsAddCollider5(ball, violetBricks, cbHitBrick, Null, Scene.Scene)
    Scene.PhysicsAddCollider5(ball, yellowBricks, cbHitBrick, Null, Scene.scene)
    Scene.PhysicsAddCollider5(ball, redBricks, cbHitBrick, Null, Scene.scene)
    'Make the player immovable
    Scene.SetImmovable(player, True)
    'Add collision for the player
    Dim cbhitPlayer As BANanoObject = BANano.CallBack(Me, "hitPlayer", Array(currentBall, currentPlayer))
    Scene.PhysicsAddCollider5(ball, player, cbhitPlayer, Null, Scene.scene)
    'Create opening text
    Dim txtX As Int = Scene.PhysicsWorldBoundsWidth / 2
    Dim txtY As Int = Scene.PhysicsWorldBoundsHeight / 2
    '
    openingText = Scene.SceneAddText(txtX, txtY, "Press SPACE to Start", _
    CreateMap("fontFamily": "Monaco, Courier, monospace", "fontSize": "50px", "fill": "#fff"))
    'The origin of the text object is at the top left, change the origin to the center so it can be properly aligned
    Scene.SetOrigin(openingText, 0.5)
    ' Create game over text
    gameOverText = Scene.SceneAddText(txtX, txtY, "Game Over", _
    CreateMap("fontFamily": "Monaco, Courier, monospace", "fontSize": "50px", "fill": "#fff"))
    Scene.SetOrigin(gameOverText, 0.5)
    'Make it invisible Until the player loses
    Scene.SetVisible(gameOverText, False)
    'Create the game won text
    playerWonText = Scene.SceneAddText(txtX, txtY, "You won!", _
    CreateMap("fontFamily": "Monaco, Courier, monospace", "fontSize": "50px", "fill": "#fff"))
    Scene.SetOrigin(playerWonText, 0.5)
    'make invisible until the player wins
    Scene.SetVisible(playerWonText, False)
End Sub
 

Mashiane

Expert
Licensed User
Longtime User
5. Running the game. This happens during the FPS (frames per second execution / ticking)

Here a check of whether the game is over or a game is won happens. This also enables one to press space bar to start the game.

B4X:
'happens during the game loop phase
Sub onUpdate
    'Log("updating...")
    'check if the game is over
    Dim isOver As Boolean = isGameOver
    Dim IsWon As Boolean = isGameWon
    '
    If isOver Then
        Scene.SetVisible(gameOverText, True)
        Scene.DisableBody(ball, True, True)
    else if IsWon Then
        Scene.SetVisible(playerWonText, True)
        Scene.DisableBody(ball, True, True)
    Else
        'Put this in so that the player doesn't move if no key is being pressed
        Scene.BodySetVelocityX(player, 0)
        'check the cursor and move the velocity accordingly, with arcade we adjust velocity for movement
        'to maniputing xy values directly
        If Scene.LeftIsDown Then
            Scene.BodySetVelocityX(player, -350)
        Else if Scene.RightIsDown Then
            Scene.BodySetVelocityX(player, 350)   
        End If
        'the game starts only when the user presses the spacebar
        If gameStarted = False Then
            'the ball should follow the paddle while the user selects to start
            Dim px As Int = Scene.GetX(player)
            Scene.SetX(ball, px)
            '
            If Scene.SpaceIsDown Then
                gameStarted = True
                Scene.SetVelocityY(ball, -200)
                Scene.SetVisible(openingText, False)
            End If
        End If
    End If
End Sub
 

Toky Olivier

Active Member
Licensed User
Longtime User
Thank you for your work. Very good one. Is it possible one day to use it with B4A (for example with the webview)? Will the performance be good?
 

Mashiane

Expert
Licensed User
Longtime User
Game 4: Emitters (Phaser 0.2)

This is code from the Phaser site that demostrates emitters.

Emitters.gif


The game code is simple enough.

B4X:
Sub onPreload
    Scene.load.image("sky", "./assets/space3.png")
    Scene.load.image("logo", "./assets/phaser3-logo.png")
    Scene.load.image("red", "./assets/red.png")
End Sub

Sub onCreate
    Scene.add.image(400, 300, "sky")
    Dim particles As PhaserObject = Scene.add.particles("red")
    Dim emitter As PhaserObject = Scene.ToPhaserObject(particles.createEmitter(100, 1, 0, "NORMAL"))
    Dim logo As PhaserObject = Scene.physics.add.image(400, 100, "logo")
    logo.setVelocity(100, 200)
    logo.setBounceXY(1, 1)
    logo.setCollideWorldBounds(True)
    emitter.startFollow(logo)
End Sub

See the Emitters folder in the Github
 
Last edited:
Top