A module for creating simple 2D games using object oriented programming. Utilizes the HTML Canvas API for rendering.
Made for the in 2024 as a part of the course 1dv610 at Linnaeus University.
- Usage
- Class Definition
The game engine needs access to a canvas element on the screen for rendering. It also needs to be passed an object that extends the GameObject class. This will function as the starting scene or level.
A scene also has to have at least one gameObject with a camera as a child in order for the rendering to work. properly.
Below is a simple example of a game where you have a box, and a player that can move using the WASD keys. Since the player inherits from CollisionBody, and the box inherits from StaticCollisionBody, they can collide with one another, preventing the player from passing through the box.
// index.ts
import { Level1 } from "./scenes/Level1";
import { GameEngine } from "jf-canvas-game-engine";
const canvas = document.querySelector("canvas") as CanvasHtmlElement;
// The scene for the first level.
const level1 = new Level1();
const gameEngine = new GameEngine(canvas, level1);
gameEngine.start();
// src/scenes/Level1.ts
import { GameObject, Vector2D } from "jf-canvas-game-engine";
import Player from "../gameObjects/Player";
import Box from "../gameObjects/Box";
export class Level1 extends GameObject {
constructor() {
super(new Vector2D(0, 0));
// Add a cat to the scene
const player = new Player(new Vector2D(100, 100), "Jonathan", "orange");
this.addChild(player);
// Add a box to the scene
const box = new Box(new Vector2D(200, 200), 50, 50, "green");
this.addChild(box);
}
}
// src/gameObjects/Player.ts
import {
GameContext,
CollisionBody,
RectangleCollisionShape,
Vector2D,
Camera,
} from "jf-canvas-game-engine";
import { Bullet } from "./Bullet";
export default class Player extends CollisionBody {
#name: string;
#color: string | CanvasPattern | CanvasGradient;
#width: number = 50;
#height: number = 50;
#camera: Camera;
#velocity = new Vector2D(0, 0);
constructor(
position: Vector2D,
name: string,
color: string | CanvasPattern | CanvasGradient
) {
const width = 50;
const height = 50;
super(
position,
new RectangleCollisionShape(
// centers the collisionShape on the player
new Vector2D(-width / 2, -height / 2),
width,
height
)
);
this.#name = name;
this.#color = color;
this.#camera = new Camera(new Vector2D(0, 0));
this.addChild(this.#camera);
//sets the active camera to the one followingthe player
GameContext.getInstance().setActiveCamera(this.#camera);
}
process(delta: number) {
this.#handleMovement(delta);
}
#handleMovement(delta: number) {
// move when pressing wasd
const gameContext = GameContext.getInstance();
const speed = 1000;
if (gameContext.isPressed("w")) {
this.#velocity = this.#velocity.add(new Vector2D(0, -speed));
}
if (gameContext.isPressed("a")) {
this.#velocity = this.#velocity.add(new Vector2D(-speed, 0));
}
if (gameContext.isPressed("s")) {
this.#velocity = this.#velocity.add(new Vector2D(0, speed));
}
if (gameContext.isPressed("d")) {
this.#velocity = this.#velocity.add(new Vector2D(speed, 0));
}
// apply the movement
this.position = this.position.add(this.#velocity.multiply(delta));
// reset velocity
this.#velocity = new Vector2D(0, 0);
}
render(ctx: CanvasRenderingContext2D) {
// render a rectangle with the players size and color with the players position in the center
ctx.fillStyle = this.#color;
ctx.fillRect(
this.globalPosition.x - this.#width / 2,
this.globalPosition.y - this.#height / 2,
this.#width,
this.#height
);
}
}
// src/gameObjects/Box.ts
import {
RectangleCollisionShape,
StaticCollisionBody,
Vector2D,
} from "jf-canvas-game-engine";
export default class Box extends StaticCollisionBody {
#width: number;
#height: number;
#color: string | CanvasPattern | CanvasGradient;
constructor(
position: Vector2D,
width: number,
height: number,
color: string | CanvasPattern | CanvasGradient
) {
super(
position,
new RectangleCollisionShape(new Vector2D(0, 0), width, height)
);
this.#color = color;
this.#width = width;
this.#height = height;
}
render(ctx: CanvasRenderingContext2D) {
ctx.fillStyle = this.#color;
ctx.fillRect(
this.globalPosition.x,
this.globalPosition.y,
this.#width,
this.#height
);
}
}
Since game objects inherit from EventTarget, they can add listeners to each other. This can be used to create custom events and logic, keeping objects as decoupled as possible.
If you decide to use composition to create game objects, you can add a GameObject as a child to another GameObject. This will make the child object move with the parent object. This can be useful for creating complex objects that are made up of multiple parts. It is a good idea to keep references to the children of your object if you need to communicate between them, just remember that components need to be added to the parent objects children in order to be rendered.
Inherits: none
The main class for the game engine. This class is responsible for starting the game loop and rendering the game.
Parameters:
-
canvas
: The html canvas element in where the game is rendered. -
scene
: The game object that should be active at game start. -
options
: Options that can be passed to affect the game engine on start. options:-
debug
: boolean. If the fps counter should be rendered or not.
-
start the game loop.
Returns: void
stops the game loop. NOT IMPLEMENTED!
Returns: void
Gets the html canvas element in where the game is rendered.
Returns: HTMLCanvasElement
Inherits: none
A singleton that holds the context of the game.
Gets the singleton instance of the GameContext.
Returns: GameContext
Sets the game engine.
Parameters:
-
gameEngine
: The game engine to set.
Returns: void
Calculates the center of the canvas.
Returns: Vector2D | null
Calculates the left position of the canvas.
Returns: number | null
Calculates the top position of the canvas.
Returns: number | null
Sets the active camera.
Parameters:
-
camera
: The camera to set as active.
Returns: void
Gets the active camera's position.
Returns: Vector2D | null
Gets the camera transformation.
Returns: Vector2D | null
Checks if the given camera is the active camera.
Parameters:
-
camera
: The camera to check.
Returns: boolean
Checks if the mouse is clicked.
Returns: boolean
Gets the click data.
Returns: ClickData | null
Clears the input data (click and key press data).
Returns: void
Checks if the given key is pressed.
Parameters:
-
key
: The key to check.
Returns: boolean
Checks if the given key was just pressed.
Parameters:
-
key
: The key to check.
Returns: boolean
Notifies the game engine to navigate to the given scene.
Parameters:
-
scene
: The scene to navigate to.
Returns: void
Inherits: EventTarget GameObject is an Abstract class.
The super class for all objects in a scene. Other classes extend this to add functionality.
Parameters:
-
position
: The starting position of the game object.
Gets the parent GameObject if one exists, otherwise null.
Returns: GameObject
Adds a child to this objects children.
Parameters:
-
child
: The GameObject to add as child.
Returns: void
Removes a child from this objects children.
Parameters:
-
child
: The GameObject child to remove.
Returns: void
Gets all children of this GameObject recursively. meaning the children of the children and so on.
Returns: GameObject[]
Gets the position of the GameObject.
Returns: Vector2D
Sets the position of the GameObject. Parameters:
-
position
: The new position.
Returns: void
Gets the global position of the GameObject. The global position is the position of the GameObject relative to the root GameObject.
Returns: Vector2D
Called every frame by the game engine. !!!DO NOT OVERRIDE!!!
Parameters:
-
delta
: The time in milliseconds since the last frame.
Returns: void
Called every frame by the game engine. This should be overridden by the user to add custom logic.
-
delta
: The time in milliseconds since the last frame.
Returns: void
Called every frame by the game engine. !!!DO NOT OVERRIDE!!!
Parameters:
-
ctx
: The rendering context of the canvas element.
Returns: void
Called every frame by the game engine. This should be overridden by the user to add custom rendering logic.
-
ctx
: The rendering context of the canvas element.
Returns: void
Removes the GameObject from its parents children. Calls onRemove to clean up the GameObject.
Returns: void
Called when the GameObject is removed from the game. calls removeEventListeners and calls onRemove on all children.
Returns: void
Removes the event listeners from this object. Should be overridden by the user to remove custom event listeners.
Returns: void
Inherits: none
Represents a 2D vector.
Creates a new Vector2D
instance.
Parameters:
-
x
: The x component of the vector. -
y
: The y component of the vector.
Gets the x component of the vector.
Returns: number
Gets the y component of the vector.
Returns: number
Adds a vector to this vector and returns the result.
Parameters:
-
v
: The vector to add.
Returns: Vector2D
Subtracts a vector from this vector and returns the result.
Parameters:
-
v
: The vector to subtract.
Returns: Vector2D
Multiplies the vector by a scalar and returns the result.
Parameters:
-
scalar
: The scalar to multiply the vector by.
Returns: Vector2D
Divides the vector by a scalar and returns the result.
Parameters:
-
scalar
: The scalar to divide the vector by.
Returns: Vector2D
Gets the magnitude of the vector.
Returns: number
Normalizes the vector and returns the result.
Returns: Vector2D
Gets the dot product of this vector and another vector.
Parameters:
-
v
: The other vector.
Returns: number
Gets the angle between this vector and another vector.
Parameters:
-
v
: The other vector.
Returns: number
Gets the distance between this vector and another vector.
Parameters:
-
v
: The other vector.
Returns: number
Inherits: GameObject < EventTarget
Represents a collision body that can collide and with other collision bodies and be moved by them.
constructor(position: Vector2D, collisionShape: CollisionShape, collisionLayers: CollisionLayers = new CollisionLayers())
Parameters:
-
position
: The position of the collision body. -
collisionShape
: The shape of the collision body. -
collisionLayers
: The collision layers of the collision body.
Gets the collision shape of the CollisionBody
.
Returns: CollisionShape
Gets the collision layers of the CollisionBody
.
Returns: CollisionLayers
Checks if this CollisionBody
is colliding with another CollisionBody
.
Parameters:
-
other
: The otherCollisionBody
to check against.
Returns: boolean
Handles the collision with another CollisionBody
.
Parameters:
-
other
: The otherCollisionBody
to handle the collision with.
Returns: void
Inherits: CollisionBody < GameObject < EventTarget
Represents a static collision body that cannot be moved by other collision bodies.
constructor(position: Vector2D, collisionShape: CollisionShape, collisionLayers: CollisionLayers = new CollisionLayers())
Parameters:
-
position
: The position of the collision body. -
collisionShape
: The shape of the collision body. -
collisionLayers
: The collision layers of the collision body.
Inherits: none
CollisionShape is an Abstract class.
Represents a shape that can be used for collision detection.
Parameters:
-
position
: The position of the collision shape.
Gets the global position of the collision shape.
Returns: Vector2D
Sets the parent of the collision shape.
Parameters:
-
parent
: The parent CollisionBody object.
Returns: void
Abstract method. To be implemented by subclasses.
Checks if this collision shape intersects with another collision shape.
Parameters:
-
other
: The other collision shape to check against.
Returns: boolean
Abstract method. To be implemented by subclasses.
Gets the intersection vector between this collision shape and another collision shape.
Parameters:
-
other
: The other collision shape to get the intersection vector with.
Returns: Vector2D
Inherits: CollisionShape
Represents a rectangle collision shape.
Parameters:
-
position
: The position of the rectangle. -
width
: The width of the rectangle. -
height
: The height of the rectangle.
Inherits: CollisionBody < GameObject < EventTarget
Represents an area that can be used for collision detection.
constructor(position: Vector2D, collishinShape: CollisionShape, collisionLayers: CollisionLayers = new CollisionLayers())
Parameters:
-
position
: The position of the area. -
collisionShape
: The shape of the area. -
collisionLayers
: The collision layers of the area.
Gets the collision bodies that are colliding with this area.
Returns: CollisionBody[]
Inherits: none
Represents the collision layers of a collision body. There are 5 layers in total. By default only the first layer is active.
Sets the active layer.
Parameters:
-
layer
: The layer to set as active. Must be between 1 and 5.
Returns: void
Gets the active layers.
Returns: number[]
Check if this CollisionLayers overlaps with another CollisionLayers, meaning that they share at least one common layer.
Parameters:
-
other
: The other CollisionLayers to check against.
Returns: boolean
Inherits: GameObject
Represents a camera that can be used to follow a game object.
Parameters:
-
position
: The position of the camera.
Inherits: none
Represents the data of a click event.
Parameters:
-
position
: The position of the click event.
Gets the position of the click event.
Returns: Vector2D
Gets the global position of the click event.
Returns: Vector2D
Inherits: GameObject < EventTarget
Represents a GameObject that can optionally be rendered with a fixed position on the screen, regardless of the camera position.
Parameters:
-
position
: The position of the UiObject. -
fixed
: If the UiObject should be fixed on the screen.
Inherits: UiObject < GameObject < EventTarget
Represents a UI object that is used to display information to the user. Currently not fully implemented.
constructor(position: Vector2D, fixed: boolean, width: number, height: number, color: string | CanvasPattern | CanvasGradient, borderOptions: BorderOptions
Parameters:
-
position
: The position of the panel. -
fixed
: If the panel should be fixed on the screen. -
width
: The width of the panel. -
height
: The height of the panel. -
color
: The color of the panel. -
borderOptions
: The border options of the panel.
Inherits: none
Represents the options for the border of a panel.
Parameters:
-
color
: The color of the border. -
width
: The width of the border. -
radius
: The radius of the border.