Issues

Throughout the project I have created issues in order to keep track of progress.

Background Issue

This issue explaines everything that I did with the background for my project.

Migrating to OOP Issue

This issue explaines the work I did while trying to migrate my code to OOP. Never got it to work and had to approch with a new strategy.

Integrating with Mr. Mort's code Issue

This issue shows how I started integrating my code into Mr. Mort's code and the challenges that came with it.

Creating the background

Creating the background for our game was a pretty simple task but I still had some troubles with it.

The first struggle I had was when I drew the background. I needed the top and the bottom of the background to match so there would be a smooth transition in the game. To do this I had to copy the top part of the background and paste it at the bottom so I could see where I needed to draw so it would line up.

For the code to create the background I first made a canvas that had the width and height the background was going to be. I also made sure to add the link.src so the file could be found in order to actually see the background.

<canvas id="canvas" width="500" height="700"></canvas>
<script>
    //create empty canvas
    let canvas = document.getElementById("canvas");
    let c = canvas.getContext("2d");
    var bgImage = new Image();
    bgImage.src = "/Gabbb/images/Stone_Background.jpg";

Then I made variables for 3 different backgrounds. Each of which had the same dimensions, but were always in different places. I made one ubove the canvas that would move down into the canvas. One in the middle that would move off the canvas. And one below that canvas that would move back to the top. I used the logic to create a cycle that would keep these backgrounds always moving. I used if statements to detect when the bottom background needed to be moved back up to the top.

<canvas id="canvas" width="500" height="700"></canvas>
<script>
    //create empty canvas
    let canvas = document.getElementById("canvas");
    let c = canvas.getContext("2d");
    var bgImage = new Image();
    bgImage.src = "/Gabbb/images/Stone_Background.jpg";
    bgImage.onload = function () {
        //set up backgrounds
        var bg1 = {
            width: 500,
            height: 1000,
            x: 0,
            y: 0
        }
        var bg2 = {
            width: 500,
            height: 1000,
            x: 0,
            y: -1000
        }
        var bg3 = {
            width: 500,
            height: 1000,
            x: 0,
            y: -2000
        }

I then created an interval to move each background down 3 pixles every 50 milliseconds. That would update the postion of the backgrounds before drawing them back onto the canvas.

<canvas id="canvas" width="500" height="700"></canvas>
<script>
    //create empty canvas
    let canvas = document.getElementById("canvas");
    let c = canvas.getContext("2d");
    var bgImage = new Image();
    bgImage.src = "/Gabbb/images/Stone_Background.jpg";
    bgImage.onload = function () {
        //set up backgrounds
        var bg1 = {
            width: 500,
            height: 1000,
            x: 0,
            y: 0
        }
        var bg2 = {
            width: 500,
            height: 1000,
            x: 0,
            y: -1000
        }
        var bg3 = {
            width: 500,
            height: 1000,
            x: 0,
            y: -2000
        }
        var interval = setInterval(function() {
            bg1.y +=3;
            bg2.y +=3;
            bg3.y +=3;
            if (bg1.y == 2000) {
                bg1.y = 0;
            }
            if (bg2.y == 1000) {
                bg2.y = -1000;
            }
            if (bg3.y == 0) {
                bg3.y = -2000;
            }
            c.drawImage(bgImage, bg1.x, bg1.y)
            c.drawImage(bgImage, bg2.x, bg2.y)
            c.drawImage(bgImage, bg3.x, bg3.y)
        }, 50);
    };
</script>

Left, Right, and Idle

First I needed to add some variables I could set true or false in order to know when Link would be moving right, right, or Idle.

let isMovingLeft = false;
let isMovingRight = false;
let isIdle = true;

I then added a funtion to move the character left and a funtion to move it right. The funcitons sets the moving variable to true and the idle variable to false. Then it sets the max frame and the Y frame within the sprite so the animation will be correct. Same thing for the idle funtion except it only sets the idle variable to true and sets the max frame and the Y frames.

function moveLeft() {
    isMovingLeft = true;
    isIdle = false;
    frameY = 5;
    maxFrame = 9;
}
// Function to handle moving right when d is pressed
function moveRight() {
    isMovingRight = true;
    isIdle = false;
    frameY = 7;
    maxFrame = 9;
}
// Function to handle idle
function idle() {
    isIdle = true;
    frameY = 0;
    maxFrame = 2;
}

In order to call these funtions I added a key down window listener to see when the a key was pressed for left, d for right, and nothing for idle. Depeding on the key that was pressed it would call the specific function.

window.addEventListener('keydown', (event) => {
    if (event.key === ' ') {
        jump();
    } else if (event.key === 'a') {
        moveLeft();
    } else if (event.key === 'd') {
        moveRight();
    }
});

I then had to make sure Link would stop moving once no key was being pressed and would go to the idle animation. So I added a keyup window listener to see when each key was lifted. If the a key was lifted it would make the moving left variable false and the idle variable ture. Same for the right.

window.addEventListener('keyup', (event) => {
    if (event.key === 'a') {
        idle();
        isMovingLeft = false;
    } else if (event.key === 'd') {
        idle();
        isMovingRight = false;
    }
})

Finally I added an if statement in the game loop function that would add pixles when the moving right variable is true and subtract pixles when the moving left variable is true. This makes the character move left and right on the screen.

if (isMovingLeft) {
    spriteX -= 10;
}
if (isMovingRight) {
    spriteX += 10;
}

I had one bug where if you jumped and then moved and then let go of the jump key, you would be moving in the idle animation. I fixed this by simply getting rid of the part of the key up if statement that made it so if no keys were pressed it would be idle. This made it impossible for Link to idle unless the a or d keys were lifted.

Migrating to OOP part 1

First thing I did was make a new js file to store a character class. In this class I put everything a basic character would need like the variables for the spritesheet, the dimestions, and everything for movement.

export class Character {
    constructor(spriteURL, spritewidth, spriteheight, x, y, jump, gravity, maxFrame, movementSpeed) {
        this.frameX = 0;
        this.frameY = 0;
        this.maxFrame = maxFrame;
        this.spriteX = x;
        this.spriteY = y;
        this.spritewidth = spritewidth;
        this.spriteheight = spriteheight;
        this.isMovingLeft = false;
        this.isMovingRight = false;
        this.isJumping = false;
        this.isIdle = true;
        this.spriteImage = new Image();
        this.spriteImage.src = spriteURL;
        this.spriteVelocityY = 0;
        this.gravity = gravity;
        this.jumpStrength = jump;
        this.movementSpeed = movementSpeed;
    }
};

In my main file I created a variable to store all of link attributes which I used the character class to create. I had trouble understanding how the constructor worked but it’s actually pretty simple. Each slot in the constructer corresponds to the variable you set it too.

var Link = new Character('/Gabbb/images/linksprites.png', 96, 104, 100, 400 - 104, -10, .5, 2, 10);

I then had to change every variable in the file to the variables I used in the class by adding a Link. in front of it. After doing that my code didn’t work. I reviewed everything and made sure all the variables were right and the constructor was right and I had all the same stuff the main file had execpt just integrated. After overlooking everything many times and asking chatGPT I still couldn’t get it to work. I asked Mr. Mort and we decided to restart by using Mr. Morts Alien World code.

<body>
    <canvas id="gameCanvas" width="800" height="400"></canvas>
    <script type="module">
        import { Character } from '/Gabbb/assets/js/Character.js'
        var Link = new Character('/Gabbb/images/linksprites.png', 96, 104, 100, 400 - 104, -10, .5, 2, 10);
        // Get the canvas and its 2D rendering context
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        // Load the background image
        const backgroundImage = new Image();
        backgroundImage.src = '/Gabbb/images/park.jpg';
        // Function to update sprite animation
        function updateSpriteAnimation() {
            if (Link.frameX < Link.maxFrame) {
                Link.frameX++;
            } else {
                Link.frameX = 0;
            }
        }
        // Function to handle jumping when spacebar is pressed
        function jump() {
            if (!Link.isJumping) {
                Link.spriteVelocityY = Link.jumpStrength;
                Link.isJumping = true;
            }
        }
        // Function to handle moving left when a is pressed
        function moveLeft() {
            Link.isMovingLeft = true;
            Link.isIdle = false;
            Link.frameY = 5;
            Link.maxFrame = 9;
        }
        // Function to handle moving right when d is pressed
        function moveRight() {
            Link.isMovingRight = true;
            Link.isIdle = false;
            Link.frameY = 7;
            Link.maxFrame = 9;
        }
        // Function to handle idle
        function idle() {
            Link.isIdle = true;
            Link.frameY = 0;
            Link.maxFrame = 2;
        }
        // Event listener for key downs
        window.addEventListener('keydown', (event) => {
            if (event.key === ' ') {
                jump();
            } else if (event.key === 'a') {
                moveLeft();
            } else if (event.key === 'd') {
                moveRight();
            }
        });
        // Event listener for key ups
        window.addEventListener('keyup', (event) => {
            if (event.key === 'a') {
                idle();
                Link.isMovingLeft = false;
            } else if (event.key === 'd') {
                idle();
                Link.isMovingRight = false;
            }
        })
        // Game loop
        let framesPerSecond = 30;
        function gameLoop() {
            // Draw the background image
            ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
            // Update sprite position based on key down left and right
            if (Link.isMovingLeft) {
                Link.spriteX -= Link.movementSpeed;
            }
            if (Link.isMovingRight) {
                Link.spriteX += Link.movementSpeed;
            }
            // Update the sprite position based on gravity
            Link.spriteVelocityY += Link.gravity;
            Link.spriteY += Link.spriteVelocityY;
            // Check if the sprite has landed
            if (Link.spriteY >= canvas.height - Link.spriteHeight) {
                Link.spriteY = canvas.height - Link.spriteHeight;
                Link.spriteVelocityY = 0;
                Link.isJumping = false;
            }
            // Draw the current sprite frame
            ctx.drawImage(
                Link.spriteImage,
                Link.frameX * Link.spriteWidth, // Adjust the X-coordinate of the frame within the sprite sheet
                Link.frameY * Link.spriteHeight, // The Y-coordinate within the sprite sheet (assuming Y is always 0 for frames)
                Link.spriteWidth, // Width of the frame
                Link.spriteHeight, // Height of the frame
                Link.spriteX, // X-coordinate where the frame is drawn on the canvas
                Link.spriteY, // Y-coordinate where the frame is drawn on the canvas
                Link.spriteWidth, // Width of the frame when drawn on the canvas
                Link.spriteHeight // Height of the frame when drawn on the canvas
            );
            // Update sprite animation
            updateSpriteAnimation();
            // Keeps loop running
            setTimeout(function() {
            requestAnimationFrame(gameLoop);
            }, 1000 / framesPerSecond);
        }
        gameLoop();
    </script>
</body>

Migrating to OOP part 2

I first downloaded all of Mr. Morts project into my repository.

I then changed the link to the background. I also added all the logic for the background into the background class.

Reflection

This trimester has been super fun and I loved working on all the different things. I learned a lot about markdown, html, and javascript. Learned the syntax for markdown, learned lots of tags in html, and learned lots of different things in javascript like variables, classes, if statements, and overall just how to code different things. I learned how to use draw and update functions and call them within a loop in order to get animations and movement and different things working. I really like functions because I don’t have to rewrite code and it makes the file a lot simpler and more organized. In trimester 2 I really look forward to diving deeper into collisions and hitboxes. I didn’t really do much with collisions this trimester and want to understand how to make different components in a game work with each other. I want to learn how to build a hitbox around a character and use that in order to help with collisions. I also want to work on OOP a lot more. Maybe starting with it next trimester will make it easier to wrap my head around. Overall this trimester was a great learning experiance and I had lot of fun coding with my team. We made some great memories and I hope they’re in my class next year!