B4J Tutorial [BANanoCreateJS] Beginning HTML5 games with CreateJS

Mashiane

Expert
Licensed User
Ola

BANanoCreateJS

This is one of my bucket list things I've been wanting to look at, game development. So I have been looking for a simple js library to use.

As the lib BANanoCreateJS is not finished (we have a long way to go, really) and this is just a first attempt at this, I have never ever developed a game before so this is a learning curve that we can experience as we go along and perhaps help each other solve some issues with this. I'm sure there are people who know how to do this with eyes closed. ;)

So I spent a couple of hours yesterday reading and practicing and was just able to get my dancing butterflies working. On the code one will notice that just above the BANano version of the code, there is a commented javascript version so that we get the drift. Some of the things there I cant even explain myself so you will have to experience it for yourself.

When it comes to games, there is a lot apparently that one has to look at, for example
  • FPS - frames per second.
  • Collision Detection
  • Events
  • The stages
  • Resources - music, images etc
To mention a few things, here is what the butterflies are doing...


The CreateJS lib is available here. Its defined as...

A suite of modular libraries and tools which work together or independently to enable rich interactive content on open web technologies via HTML5.

Hopefully this can be a community project. The intention is to explore the canvas in parallel exploring the CreateJS library whilst working on this pet project. Oh yes, there are game engines that I found via google that one does not even have to code, but hey, let the adventure begin!

Ta!

NB: You might want to clear the cache of your internet browser if you make any changes to the code.
 
Last edited:

Mashiane

Expert
Licensed User
Let's simplify things a little. Let's create a stage (where our game will run), add three butterflies at different co-ordinates, after 1 second we move the position of the second butterfly.

GamesLesson1.gif


First we need to define all our variables / resources to use in the game in process_globals...

B4X:
'Static code module
Sub Process_Globals
    Private game As BANanoCreateJS
    Private BANano As BANano  'ignore
    Private bf1 As BANanoObject
    Private bf2 As BANanoObject
    Private bf3 As BANanoObject
End Sub
We then call init to create our canvas and the stage so that we can start adding our game resources as soon as the game is started and ready.

B4X:
Sub Init
    game.Initialize(Me, "body", "canvas", 1000, 800, "", CreateMap("border": "black solid 1px"))
    'add resources to the manifest for the game
    game.AddManifest("butterfly", "./assets/butterfly.png")
    'start the game at 60 frames per second
    game.Start(60)
End Sub
We have a butterfly picture that we will use on the stage, so lets add it to the 'manifest' so that its ready whenever we need it. We then start the game at 60 frames per second. This will fire the game_ready event.

On game_ready (the stage is set), lets add the characters, i.e. butterflies.

B4X:
Sub game_ready
    'the game is ready, lets create the objects to play with
    Log("game_ready")
    'get resource from manifest
    Dim img As BANanoObject = game.getManifest("butterfly")
    'add 3 images to the canvas
    bf1 = game.NewBmp(img)
    bf2 = game.NewBmp(img)
    bf3 = game.NewBmp(img)
    'set the locations
    game.SetX(bf2, 200)
    game.SetX(bf3, 400)
    'add the images to the stage
    game.AddChildren(Array(bf1,bf2,bf3))
    'update the game to ensure our objects are showing
    game.Update
    'after 1 second, move the butterfly
    BANano.Window.SetTimeout(BANano.CallBack(Me, "movebutterfly", Null), 1000)
End Sub
We get the butterfly image from the 'manifest' / 'memory' and use that to create 3 butterflies for the stage using createjs methods. We also set the X positions of the butterflies, being 200, and 400 for the 2nd and 3rd butterfly.

We then use the AddChild method to add each of the elements to the stage and then 'refresh' the stage by calling game.update.

This will just create images on the canvas without any type of action. So we want the second butterfly to move after 1 second, so we fire the SetTimeOut method to call the 'movebutterfly' method.

B4X:
Sub moveButterFly
    'get the last position of butterfly Y pos
    Dim bf2Y As Long = game.GetY(bf2)
    'increment it by 200
    bf2Y = bf2Y + 200
    'set the new position
    game.SetY(bf2,bf2Y)
    'update the game
    game.update
End Sub
The movebutterfly method reads the last position of butterfly 2 and moves it down the stage. Each time we have a change to the object we need to update the stage after setting all properties.

Lol. For a while there I started to think about the Romeo and Juliet play I watched. This is starting to make sense when I look at it from an acting perspective. There is a stage, there are actors, they follow a script, move, cry, collide etc. ;)

We will add more functionality to this as we go along. Enjoy!
 

Attachments

Mashiane

Expert
Licensed User
Introducing Tweening

In out last example we made a demo using SetTimeOut and just moved the butterfly to a Y position without any animation. With tweening we can do better.

This lesson demonstrates the following process

1. Draw your butterfly image.
2. Create a timer that would execute until a desired increment is reached.
3. At each interval, clear your butterfly graphics.
4. Redraw your butterfly with a new, slightly incremented y value.
5. Check if the number of ticks Or desired butterfly y position is reached.
6. Clear your timer.

So here we want the Y position of the image to be 100, when the image is added, its position is 0 in this case. We will use Tweening to do the steps 1 - 6.

GamesLesson2.gif


This is achieved with..

B4X:
Sub game_ready
    'get the image from loaded resources
    Dim img As BANanoObject = game.getManifest("butterfly")
    'create a new bitmap
    bf1 = game.NewBmp(img)
    'add it to the stage
    game.AddChild(bf1)
    'update the stage
    game.update
    
    'get the object you want to animate, remove it, change position, redraw in new position
    'animation should run for 1 second
    game.Tween_Get(bf1,False)
    'change the properties you need
    Dim toPos As Map = CreateMap()
    'y should be current position + 100
    Dim y As Long = game.IncrementY(bf1,100)
    toPos.Put("y", y)
    'animation should be exactly 1 second
    game.Tween_To2(toPos, 1000)
End Sub

Sub game_update
    'Log("game_update on each tick")
    Dim y As Long = game.GetY(bf1)
    Log(y)
    'refresh the game each time the tick fires
    game.update
End Sub
So within 1 second, the butterfly Y position should be moved to 100 paces. So

1. We get the image to animate
2. We change the properties of the image
3. We move the image to the new position within 1 second.
4. Each time the ticker fires, it calls game_update, so there we can process the stage update to reflect the new changes.

NB: As this is a lib in development, some things are being added as we go along and some things will change. Each lesson code comes with new changes and anything changed will be reflected.

NB: Please first clear the browser cache to run this example.
 

Attachments

Mashiane

Expert
Licensed User
Lesson 3 - 9

Our lesson 2 introduced us to tweening, a process of having to be able with just a few calls one is able to redraw their images. Lessons 3 - 9 takes one through tweening (using wait) and also a tweening callback that can be ran when the tweening is complete.

Lesson 3: Demonstrating another tweening property. We change the alpha property of the image to make it fade into the stage..

GamesLesson03.gif


Lesson 4: Demonstrating Tweening Wait i.e. before an image animates, wait for some millisecords for it to fire. Notice the delay with the animation start up.

GamesLesson04.gif


Lesson 5: Dancing Butterflies - a more detailed easier example explaining the concept

GamesLesson05.gif


Lesson 6: Now that we have seen how animation and tweening works, lets look at how to add shapes to the stage with some shapes. We have been adding pngs before. We end up animating one at the center of it.

GamesLesson06.gif


Lesson 7: Let's create a bouncing ball. It happens to be yellow!

GamesLesson07.gif


Lesson 8: Let's create a UI widget, a progress bar, this can be used when your game is loading and preparing to load.

GamesLesson8.gif


Lesson 9: Now that we know how to create shapes and load images to our stage, lets add some events. We have added a mouseover and mouseout events to our circle.

GamesLesson9.gif


Soon we will be looking at sprites and other things and eventually developing a game.

Watch this space. #Excited4Days
 

Attachments

Mashiane

Expert
Licensed User
Our first HTML5 game, ColorDrop

Color Drop is a simple color-matching game where the player must drop each game piece in the correct slot by matching their colors.
  • Four square slots are displayed on the top of the screen.
  • Four blocks are randomly placed on the bottom of the screen, each with a color that matches a slot at the top of the screen.
  • The player must drag each block into its corresponding slot, which is accomplished by matching their colors.
  • If a player drops it in the wrong slot, the block will animate back to where it was grabbed.
  • If a player drops it in the correct slot, it should animate to snap in place of the slot.
  • Once the player fills all four slots, alert the user that they have won the game.


ColorDrop.gif
 

Attachments

Mashiane

Expert
Licensed User
Lesson 11: Events & No Ticking

In lesson 11, we take a look at the creating a circle on the stage, add an event so that when the circle is clicked it moves to the mouse position. We also add a mouse_up event to the stage so that when the mouse is clicked within the stage, the circle moves directly there.

For this lesson we are not tweening and we are not using FPS to run a tick. Simply by updating the stage the changes made are updated when we click.

CircleClick.gif


The code is rather simple

On int, we prepare the game so that its ready for us to add the display objects.

B4X:
Sub Init
    'create the canvas and the stage for the game to be created
    game.Initialize(Me, "body", "canvas", 1000, 800, "", CreateMap("border": "black solid 1px"))
    'prepare the stage
    game.Prepare
End Sub
this generates a game_ready event where we add our circle..

B4X:
Sub game_ready
    Dim e As BANanoEvent
    game.OnMouseUp(BANano.CallBack(Me,"game_mouseup",Array(e)))
    'create a circle within a parent game
    circle.Initialize2(game)
    'fill color red
    circle.graphics.beginFill("red")
    'x = 0, y = 0, radius = 50
    circle.graphics.drawCircle(0, 0, 50)
    'set the x & y
    circle.setx(100)
    circle.sety(100)
    circle.Add
    game.Update
   
    'add click event to circle
    circle.OnClick(BANano.CallBack(Me, "circle_click", Array(e)))
End Sub
We add a mouseup event to the game to detect when a user clicks the game area
We add a circle using Initialize2 this time (this automatically links the object to the game) and specify the shape properties
After we have added the circle to the game with .Add we update the game stage and then add a click event to the circle.

When the circle is clicked, we read its X (axis) position, increment that by 10px and then update the circle position and also update the stage.

B4X:
'fire when clicked
Sub circle_click(e As BANanoEvent)
    Log("circle_click")
    'get the shape from the event
    Dim clickedShape As CreateJSShape = game.GetEventShape(e)
    'get the x position
    Dim x As Int = clickedShape.GetX
    x = x + 10
    clickedShape.SetX(X)
    game.update
End Sub
Now, when the stage is clicked anywhere, we want to move the circle to that xy point.

B4X:
Sub game_mouseup(e As BANanoEvent)
    'get the stage point, this returns x & y
    Dim pt As CreateJSPoint = game.GetStagePoint(e)
    'set the circle points
    circle.SetX(pt.x)
    circle.SetY(pt.y)
    game.update
End Sub
We use .GetStagePoint to get the X/Y position at where the mouse pointer rested. You will note this is derived from the BANanoEvent object. We get the point and then set the circle position for x and y and then update the stage.

Ta!

PS: Some improvements were made to ColorDrop for ease of use. This is part of this code. This included assigning a BANanoObject back to CreateJSShape.
 

Attachments

Mashiane

Expert
Licensed User
Lesson 12: We look at drag and drop where one can drag and drop an image. This uses another event handler for the shape.

Lesson12DnD.gif


Lesson 13: We add the tweening to the shape class this time around. This makes it a better implementation than directly to the game class.

Lesson13DropOut.gif


Lesson 14: We explore transforming images using the .SetTransform method

Lesson14SetTransform.gif


See code in the next lesson...
 

Mashiane

Expert
Licensed User
Lesson 15: SpriteSheets

This is just an introduction to the spritesheets and their functionality. So we get to get grant running. We have created CreateJSSprite, CreateJSSpriteSheet and CreateJSAnimation classes for this.

The SpriteSheet

sprite.png


From this sprite-sheet we create an animation for running and jumping.

Lesson15SpriteSheet.gif


We define the SpriteSheet and the grant Sprite.

B4X:
Private ss As CreateJSSpriteSheet
    Private grant As CreateJSSprite
On game_ready, we create the spritesheet to make the game work.

B4X:
Sub game_ready
    ss.Initialize("ss").AddImage("./assets/grant.png")
    'height of each sprite, width, registrations, count
    ss.SetRegX(82)
    ss.SetHeight(292)
    ss.SetCount(64)   ' the number of image frames in the sprite
    ss.SetRegY(0)
    ss.SetWidth(165)   ' the width of each image
    ss.SetFrameRate(30)  ' the frame rate
    'animation, starting sprite, ending sprite, next animation, speed
    ss.AddSimpleAnimation("run", 0, 25, "run", 1.5)   ' specify the animation, the start and ending image and the speed
    ss.AddSimpleAnimation("jump", 26, 63, "run", -1)
    'build the sprite to make it available to the game
    ss.BuildSpriteSheet
    '
    'create the sprite and add it to the stage
    grant.Initialize(ss, "grant", "run")
    grant.setx(game.getcanvaswidth / 2)
    grant.sety(22)
    game.AddSprite(grant)
    '
    game.Start(30)
End Sub
 

Attachments

Mashiane

Expert
Licensed User
Detecting keyboard events

In this lesson we detect keyup, keyleft, keyright, keydown movements.

When you initialize a game, there are two events that are created, keyup and keydown. To trap these on your module, you add..

KeyPress.gif



B4X:
Sub game_keydown(e as bananoevent)
End Sub
and

B4X:
Sub game_keyup(e as bananoevent)
End Sub
One then is able to detect the keys and then perform some actions.

in pgLesson21, we do this with...

B4X:
Sub game_keydown(e As BANanoEvent)
    Select Case e.KeyCode
    Case game.ARROW_KEY_LEFT
        Log("move left")
    Case game.ARROW_KEY_UP
        Log("move up")
    Case game.ARROW_KEY_RIGHT
        Log("move right")
    Case game.ARROW_KEY_DOWN
        Log("move down")          
    End Select
End Sub
Ensure the focus is on the canvas first.

TA!

PS: Post on #1 updated with source code...
 
Last edited:

Mashiane

Expert
Licensed User
Taking again from the previous example, we create a paddle for a game. We move the paddle from left to right.

Paddle.gif


We prepare the stage and when the game is ready we create the paddle.

B4X:
Sub game_ready
    'build the game elements
    padel.Initialize
    padel.SetWidth(100)
    padel.graphics.BeginFill("#0000FF")
    padel.Graphics.drawRect(0, 0, padel.GetWidth, 20)
    padel.SetX(0)
    padel.SetNextX(0)
    padel.SetY(game.GetCanvasHeight - 20)
    game.addChild(padel.Shape)
    'start the game, this raises, game_update
    game.Start(60)
End Sub
During the game execution, we trap the keypress events for left and right buttons.

B4X:
'move padel
Sub game_keydown(e As BANanoEvent)
    Select Case e.KeyCode
        Case game.ARROW_KEY_LEFT
            leftKeyDown = True
        Case game.ARROW_KEY_RIGHT
            rightKeyDown = True
    End Select
End Sub

'stop padel
Sub game_keyup(e As BANanoEvent)
    Select Case e.KeyCode
        Case game.ARROW_KEY_LEFT
            leftKeyDown = False
        Case game.ARROW_KEY_RIGHT
            rightKeyDown = False
    End Select
End Sub
The game has been started at 60 frames per second, so each time a tick fires, the game_update method is executed.

B4X:
'each time a tick runs
Sub game_update
    'get the current position of the shape
    Dim nextX As Int = padel.GetX
    'the left key has been pressed
    If leftKeyDown Then
        nextX = padel.GetX - 10
        'ensure we dont over-run the stage
        If nextX < 0 Then
            nextX = 0
        End If
    else if rightKeyDown Then
        'if right is pressed, we get the current position
        'increment it by 10 and set it as the next position
        nextX = padel.GetX + 10
        'get the canvas width and ensure that the nextpos is within stage
        If (nextX > game.GetCanvasWidth - padel.GetWidth) Then
            nextX = game.GetCanvasWidth - padel.GetWidth
        End If
    End If
    'set the next position
    padel.SetNextX(nextX)
    'move the paddle to the next position
    padel.SetX(padel.GetNextX)
    'execute the stage update
    game.update
End Sub
 

Mashiane

Expert
Licensed User
We created a Game Over screen in our previous post, let's use the DOMElement object of CreateJS now and create a tweening 'instructions' screen.

Instructions.gif


We add a gameholder to the body of the page. This time we render the canvas of the game to another div and use a DOMElement to use the instructions on the game. This then means we can render any html element to our game as we need.

B4X:
Sub game_ready
    Dim el As CreateJSDOMElement
    el.Initialize("instructions")
    el.SetAlpha(0)
    el.SetRegX(200)
    el.SetX(game.GetCanvasWidth / 2)
    game.addChild(el.DOMElement)
    '
    game.Tween_Get(el.DOMElement,False)
    game.Tween_Wait(1000)
    game.tween_to3(CreateMap("y": 40, "alpha": 1), 2000, game.Ease_QuadOut)
    game.Start(60)
End Sub
The instructions are just basic HTML with some styles applied to it.

Ta!
 
Top