JS OOP Assets

GameEnv
|   ├── Attributes:
│   |   ├── levels
│   |   ├── gameObjects
|   │   └── canvas
|   |
|   ├── Purpose: 
│   |    ├── update: updates objects, draws objects on canvas
│   |    ├── destroy: destroys all gameObjects in reverse order
│   |    └── canvas: creates canvas, sets bounds, resizes canvas
│
├── GameObject
|   └── Allows for collision detecton, animation, and resizing
│       ├── Player: animates, controls with wasd
│       ├── Background: fit to screen, scrolling 
│       └── Platform: fixed to bottom, scrolling
│
├── GameLevel
│   ├── Attributes:
│   |   ├── playerAssets
│   |   ├── backgroundAssets
│   |   ├── platformAssets
│   |   └── objectAssets
|   |
│   └── Methods: 
│   |    ├── load: loads "new" GameObject created from assets
│   |    ├── loads player, platform, background
|   |    └── possibly changes player speed, object speed, etc.
|
└── GameControl
│   ├── Methods: 
|   |    ├── gameLoop: keeps game running, main "backbone" in code
|   |    ├── destroy: destroys objects from previous levels
│   |    └── transitionToLevel: destroys and creates objects for game 

Mr. Mort’s code below

Game Environment

GameEnv is the overarching environment class that holds the game levels, game objects, and manages environment updates.

class GameEnv {
    // defined and current game levels
    static levels = [];
    static currentLevel = null;

    // active Game Objects
    static gameObjects = [];

    // initialize for Game Environment 
    static initialize() {
        // store width and height based on screen size
        this.setTop();
        this.setBottom(); 

        // ...
    }

    // resize Game Objects
    static resize() {
        this.initialize();  // Update dimensions

        // Call the sizing method on all game objects
        for (var gameObj of GameEnv.gameObjects){
            gameObj.size();
        }
    }

    // gameLoop method to update Game Objects
    static update() {
        // Update game state, including all game objects
        for (const gameObject of this.gameObjects) {
            gameObject.update();
            gameObject.draw();
        }
    }

}

GameObject

GameObject is the base class for all objects in the game. It contains common attributes and methods.

// Common attributes, methods, prototype methods for all objects in the Game.
class GameObject {
    constructor(canvas, config) {
        this.x = config.x;
        this.y = config.y;
        this.canvas = canvas;
        this.ctx = canvas.getContext('2d');
        this.image = config.image;
        this.frame = config.frame;
        this.width = config.width;
        this.height = config.height;
        this.aspect_ratio = this.width / this.height;
        this.speedRatio = config.speedRatio;
        this.speed = GameEnv.gameSpeed * this.speedRatio;
        this.collisionWidth = 0;
        this.collisionHeight = 0;
        this.collisionData = {};
        GameObject.gameObjects.push(this);
    }

    destroy() {
        const index = GameObject.gameObjects.indexOf(this);
        if (index !== -1) {
            // Remove the canvas from the DOM
            this.canvas.parentNode.removeChild(this.canvas);
            GameObject.gameObjects.splice(index, 1);
        }
    }

    update() { }
    draw() { }
    size() { }
    isCollision(object) { }
    collisionAction(object) { }
    handleCollision(object) {
        if (this.isCollision(object)) {
            this.collisionAction(object);
        }
    }
}

Player

Player is a class specific to the player character, extending GameObject and adding properties like speed, jump height, etc.

// Create a class specifically for the player character, extending the GameObject class.
class Player extends GameObject {
    constructor(canvas, config) {
        super(canvas, config);
        this.speed = config.speed;
        this.jumpHeight = config.jumpHeight;
        this.health = config.health;

        // Set up event listeners for user input
        document.addEventListener('keydown', this.handleKeyDown.bind(this));
        document.addEventListener('keyup', this.handleKeyUp.bind(this));
    }

    handleKeyDown(event) {
        // Handle key down events (e.g., move left or right, jump)
        switch (event.key) {
            case 'ArrowLeft':
                this.moveLeft();
                break;
            case 'ArrowRight':
                this.moveRight();
                break;
            case 'Space':
                this.jump();
                break;
            // Handle other keys as needed
        }
    }

    handleKeyUp(event) {
        // Handle key up events (e.g., stop moving)
        switch (event.key) {
            case 'ArrowLeft':
            case 'ArrowRight':
                this.stopMoving();
                break;
            // Handle other keys as needed
        }
    }

    moveLeft() { /* Implement left movement logic */ }
    moveRight() { /* Implement right movement logic */ }
    stopMoving() { /* Implement stop movement logic */ }
    jump() { /* Implement jump logic */ }
    attack() { /* Implement attack logic */ }
}

Platform

Platform is a class for platforms that the player can stand on, extending GameObject.

// Create a class for platforms that the player can stand on.
class Platform extends GameObject {
    constructor(canvas, config) {
        super(canvas, config);

    }
    // Additional platform-specific methods or properties
}

Game Level

GameLevel stores the assets and attributes specific to a particular level. It has properties like background, platforms, player, …

// Store the assets and attributes of the Game at the specific GameLevel.
class GameLevel {
    constructor(tag) {
        this.tag = tag;
        this.backgroundImg = null;
        this.platformImg = null;
        this.playerImg = null;
        this.isComplete = null; // function that determines if level is complete
    }

    setBackgroundFile(file) {
        this.backgroundImg = file;
    }

    // ...

    setIsComplete(callBack) {
        this.isComplete = callBack;  // callBack is function to test for level completion
    }

    // Load level data
    load() { /* Load level data */ }

    // ...

    // Add a GameLevel to the array levels
    static create(tag, backgroundFile, platformFile, playerFile, isComplete) {
        const newLevel = new GameLevel(tag);
        newLevel.setBackgroundFile(backgroundFile);
        newLevel.setPlatformFile(platformFile);
        newLevel.setPlayerFile(playerFile);
        newLevel.setIsComplete(isComplete);
        GameEnv.levels.push(newLevel);
    }


}

Game Control

The gameLoop and the setup and teardown between game levels

const GameControl = {

    // Level transition method (destroy then newlevel)
    async transitionToLevel(newLevel) {
        this.inTransition = true;

        // Destroy existing game objects
        GameEnv.destroy();

        // Load GameLevel objects
        await newLevel.load();
        GameEnv.currentLevel = newLevel;

        // Trigger a resize to redraw canvas elements
        window.dispatchEvent(new Event('resize'));
        // Update invert property, twice means same as before
        toggleCanvasEffect.dispatchEvent(new Event('click'));
        toggleCanvasEffect.dispatchEvent(new Event('click'));

        this.inTransition = false;
    },

    // Game control loop
    gameLoop() {
        // Turn game loop off during transitions
        if (!this.inTransition) {

            // Get current level
            GameEnv.update();
            const currentLevel = GameEnv.currentLevel;

            // currentLevel is defined
            if (currentLevel) {
                // run the isComplete callback function
                if (currentLevel.isComplete && currentLevel.isComplete()) {
                    const currentIndex = GameEnv.levels.indexOf(currentLevel);
                    // next index is in bounds
                    if (currentIndex !== -1 && currentIndex + 1 < GameEnv.levels.length) {
                        // transition to the next level
                        this.transitionToLevel(GameEnv.levels[currentIndex + 1]);
                    } 
                }
            // currentLevel is null, (ie start or restart game)
            } else {
                // transition to beginning of game
                this.transitionToLevel(GameEnv.levels[0]);
            }
        }

        // recycle gameLoop, aka recursion
        requestAnimationFrame(this.gameLoop.bind(this));  
    },

};