2.2.2 Cycle 2

Design

Objectives

In this development cycle my main aim is to create characters that move and interact with keyboard inputs as well as giving them collision properties to interact with the existing map from Cycle 1. I aim for the characters also to have sprites that change depending on the user input and how they respond to the movement.

Usability Features

Key Variables

Variable Name
Use

velocity(X,Y)

The speed assigned to the player when key inputs are pressed determining how fast they move

player / faune

Variable that stores all of the information and properties about the character.

left, right, up, down

Stores the information about keyboard inputs allowing them to be assigned to player movement

config

Stores information about the game resolution, physics and other data to start the game correctly.

Pseudocode

// create config and information about the games properties
config
    height: 1120
    width: 640
    physics: no gravity
    scene: preloader, game
end object

// initialise variables and attributes for the game
procedure create
    player = generatePlayer
    camera.follow(player)
    player.collideWorldBounds = true
    
    
    // create the variables for the keyboard input values
    left = key bind for left arrow key
    right = key bind for right arrow key
    up = key bind for arrow key
    down = key bind for down key
    
    // what the character should do upon given keyboard inputs
    if (input = up) {
        velocity.x = 0
        velocity.y = -velocity
        this.player.animations.play('up');
    
    if (input = down) {
        velocity.x = 0
        velocity.y = -velocity
        this.player.animations.play('down');
    
    if (input = left) {
        velocity.x = -velocity
        velocity.y = 0
        this.player.animations.play('left');
        
    if (input = right) {
        velocity.x = -velocity
        velocity.y = 0
        this.player.animations.play('right');
        
    // stationary    
    if (input = none) {
        velocity.x = 0
        velocity.y = 0
        this.player.animations.play('standing');
    
end procedure

Development

Outcome

Lots of the parts of the code such as the index.html file remain the same in this second cycle but most of the change will take place in the game.ts file since that contains most of the player and world attributes. I have also separated out parts of the code into their own files such as the Preloading features to make the game.ts and main.ts less crowded and easier to read.

import Phaser from "phaser";

export default class Preloader extends Phaser.Scene
{
    constructor()
    {
        super('preloader')
    }
// Preloading now loads sprites for the character and the JSON
// that has information on the frames to work with the animations 
    preload()
    {
        this.load.image('tiles', 'tiles/Serene_Village_16x16_extruded.png');
        this.load.tilemapTiledJSON('mainmap', 'tiles/mainmaptest.json');
        this.load.atlas('faune', 'character/faune.png', 'character/faune.json')
    } 

    create()
    {
        this.scene.start('game')
    }
}

Challenges

Throughout this development cycle I faced many challenges since I now had to work with new aspects such as player inputs as well as responding collision to the character. Problems arose when trying to create these aspects of the game due to some outdated functions and documentation regarding the phaser library. An example of this I found was the way layers with collisions in Phaser used to be initialised by createStaticLayer.map('name', tileset)

However my solution to this old outdated function was to instead initialise the layers as their own independent variables by writing const name = map.createLayer('name', tileset). This also was useful later on when trying to group different layers that needed collision together for more readable code. Another problem I had with this development cycle was trying to get the camera to follow the camera but then not go outside the boundaries I had set. For some reason the game boundaries were not being set to the pixel measurements I had provided so having to find a workaround for this was quite difficult.

Testing

Evidence for testing

Tests

Test
Instructions
What I expect
What actually happens
Pass/Fail

1

Run code

Character should appear on screen on top of the map

Character texture not loaded with texture frame missing

Fail

2

Press keys / WASD

The player should respond by moving around the screen in the given direction

As expected

Pass

3

Press arrow keys

Characters sprite to change to a different corresponding animation

Character's sprite was half cut off implying the amount the sprite needs to change was too much or too little

Fail

4

Move character into an object with collision properties

Character to stop moving and not get past the object or wall

As expected

Pass

After this I went back to work out why the sprite issues weren't working and was due to the increments of how the image sprite stages were going up, to fix this I changed them from decimal increments to integer stages.

game.ts
   //Changing the border to size to feel more responsive 
    this.faune = this.physics.add.sprite(480, 235, 'faune', 'walk-down-3.png')
    this.faune.body.setSize(this.faune.width * 0.5, this.faune.height * 0.7)

    this.anims.create({
        key: 'faune-idle-down',
        frames: [{ key: 'faune', frame: 'walk-down-3.png'}]
    })

    this.anims.create({
        key: 'faune-idle-up',
        frames: [{ key: 'faune', frame: 'walk-up-3.png'}]
    })

    this.anims.create({
        key: 'faune-idle-side',
        frames: [{ key: 'faune', frame: 'walk-side-3.png'}]
    })
    

// Changing the animations to go up in integers that correspond with the correct frames of the animation
    this.anims.create({ 
        key: 'faune-run-down',
        frames: this.anims.generateFrameNames('faune', {start: 1, end: 8, prefix: 'run-down-', suffix: '.png'}),
        repeat: -1,
        frameRate: 15

    })

    this.anims.create({ 
        key: 'faune-run-up',
        frames: this.anims.generateFrameNames('faune', {start: 1, end: 8, prefix: 'run-up-', suffix: '.png'}),
        repeat: -1,
        frameRate: 15

    })

    this.anims.create({ 
        key: 'faune-run-side',
        frames: this.anims.generateFrameNames('faune', {start: 1, end: 8, prefix: 'run-side-', suffix: '.png'}),
        repeat: -1,
        frameRate: 15

    })
    

    update(t: number, dt: number){
        if (!this.cursors || !this.faune)
        {
            return
        }
        const speed = 100;
        if (this.cursors.left?.isDown)
        {
            this.faune.anims.play('faune-run-side', true)
            this.faune.setVelocity(-speed, 0)
            this.faune.scaleX = -1
            this.faune.body.offset.x = 24
        }
        else if (this.cursors.right?.isDown)
        {
            this.faune.anims.play('faune-run-side', true)
            this.faune.setVelocity(speed, 0)
            this.faune.scaleX = 1
            this.faune.body.offset.x = 8

        }
        else if (this.cursors.up?.isDown) {
            this.faune.anims.play('faune-run-up', true)
            this.faune.setVelocity(0, -speed)
        }

        else if (this.cursors.down?.isDown) {
            
            this.faune.anims.play('faune-run-down', true)
            this.faune.setVelocity(0, speed)
        }
        else
        {
            const parts = this.faune.anims.currentAnim.key.split('-')
            parts[1] = 'idle'
            this.faune.anims.play(parts.join('-'))
            this.faune.setVelocity(0, 0)
        }

    }
}

Tests

Test
Instructions
What I expect
What actually happens
Pass/Fail

1

Run code

Character should appear on screen on top of the map

As expected

Pass

2

Press keys / WASD

The player should respond by moving around the screen in the given direction

As expected

Pass

3

Press arrow keys

Characters sprite to change to a different corresponding animation

As expected

Pass

4

Move character into an object with collision properties

Character to stop moving and not get past the object or wall

As expected

Pass

Here is a video of me demonstrating working character movements on a map made for testing and demonstrating working collisions too through debugging the player hitbox to make it more visual.

Last updated