0.6.1 • Published 3 months ago

rge.js v0.6.1

Weekly downloads
-
License
MIT
Repository
github
Last release
3 months ago

Get Started

RGE.js is available to install on NPM as well as via CDN (jsDelivr).

npm i rge.js@latest

CDN:

<script type="module">
    import * as rgejs from "https://cdn.jsdelivr.net/npm/rge.js@latest/index.js"
    window.rgejs = rgejs;
</script>

RGE.js can be used in ANY browser environment which supports the canvas element. It works with HTML/CSS/JS and ReactJS, and likely works with other frameworks as well.

Compatibility

FrameworkCompatible?
HTML, CSS, JS
ReactJS
NextJS (CSR Components)
NextJS (SSR Components)
VueJSUntested
Svelte/SvelteKitUntested
AngularJSUntested

Warning❗️

As of right now, RGE.js is still in it's alpha phase and may have bugs/issues.

Documentation

RGE.js uses an Object Oriented paradigm. This means the RGE engine class and all Entities are objects and have to be handled as such.

Initialization with HTML/CSS/JS

In order to initialize RGE.js using HTML/CSS/JS, it is recommended to use the CDN install. rgejs will be added to the global window object, which can then be used in other module JS files.

Important!

Import all JS files which use RGE.js as a module. For example:

<script type="module" src="./script.js"></script>

At the top of all files, it is recommended to make a shorthand for the global rgejs object for simplicity.

const r = rgejs;

Starting the Engine

We will begin with the Engine object. This can be viewed as sort of the "Main Engine" behind RGE.js. When you first create a project, you will create a new instance of this object. Then, you will run start().

// First parameter is the id of the canvas which RGE will run on
// Second parameter is the target framerate.
const rge = new r.Engine('gameCanvas', 60);

rge.start()

Great! You have successfully initialized a new RGE project.

Initialization with ReactJS/NextJS

Initializing RGE.js with ReactJS or NextJS is a bit different than with plain HTML/CSS.

// Add "use client" at the top of the file if using NextJS.
// "use client"
import * as r from "rge.js";
import React, { useEffect, useRef } from "react";

export default function RgeCanvas() {
    const canvasRef = useRef(null);
    useEffect(() => {
        const canvasId = "gameCanvas";
        const targetFps = 60;
        
        const rge = new r.Engine(canvasId, targetFps);
        
        rge.start();

        return () => {
            rge.stop();
        };
    }, []);
    return (
        <>
            <canvas
                ref={canvasRef}
                id="gameCanvas"
                // Set your desired canvas size
                width={800}
                height={600}
            />
        </>
    )
}

Great! You have successfully initialized a new RGE project in React!

Entities

Entities can just be viewed as different components or elements, which each have unique properties. Certain entities can be controlled, have collision, be destroyed, etc.

An object called Entity exists already. Most pre-made entities are extensions of this object. Here is the basic structure of the Entity object:

class Entity {
    constructor(x, y) {
        this.x = x;
        this.y = y;
        this.isDestroyed = false;
        this.onClick = null;
    }

    // Abstract method to be defined by subclasses
    update() { }

    // Abstract method to be defined by subclasses
    render(ctx) { }

    destroy() {
        this.isDestroyed = true;
    }

    onClickHandler() {
        if (this.onClick) {
            // onClick should be defined by subclasses
            this.onClick();
        }
    }
}

Rect

One of the most used entities is Rect. This simply generates a Rectangle. Let's implement one.

// Creating new instance of a Rect
const rect = new r.Rect(x, y, width, height, "color")
// Adding the newly made Rect
rge.addEntity(rect)

This code will render a Rect to the canvas.

Rect is a very robust entity, and has many use cases. However first, we will go over the game tick.

Game Tick

RGE.js allows programmers to implement a tick() function to their code. This allows them to update, or re-render certain entities. This also allows collision detection code to be added. Let's learn how to create a game tick.

function tick() {
    // Update logic goes here.
    rect.update(newX, newY)
}

rge.setTickFunction(tick);

The update() function of rect rerenders the Rect at a new X and Y pos. Now, let's take a look at implementing collision by using this game tick.

Inputs

RGE.js supports inbuilt input detection and handling for both keyboard and mouse inputs.

Keyboard Inputs

RGE.js provides a natural and easy way to define keyboard input detection, and allows you to define commands for both keypresses and keyups (or key releases). Let's view some code.

rge.addKeyPressAction({
    'q': {
        press: () => {
            console.log("Q is pressed!")
        },
        release: () => {
            console.log("Q is released!")
        }
    },
    // ... remaining input handlers
})

Now you'll see that whenever you press the q key, it logs that it is pressed, and when you release it, the console will log that Q has been released. Let's take a look at a real-world scenario in which you can use this.

let x = 300;
let y = 200;
let dx = 0;
let dy = 0;

const demoRect = new r.Rect(x, y, 50, 50, "green");
rge.addEntity(demoRect);

rge.addKeyPressAction({
    'w': {
        press: () => {
            dy -= 5
        },
        release: () => {
            dy = 0
        }
    },
    'a': {
        press: () => {
            dx -= 5
        },
        release: () => {
            dx = 0
        }
    },
    's': {
        press: () => {
            dy += 5
        },
        release: () => {
            dy = 0
        }
    },
    'd': {
        press: () => {
            dx += 5
        },
        release: () => {
            dx = 0
        }
    },
})

function tick() {
    x += dx;
    y += dy;

    demoRect.update(x, y)
}

rge.setTickFunction(tick);
rge.start();

This code creates a Rect entity, and allows the user to control it by using WASD.

Mouse Inputs

RGE.js also tracks mouse clicks, and provides a utility to add an onClick function to certain Entities. By default, all entities which extend the Entity object have a click handler built in. Let's take a look at this.

// Initializing and registering Rect entity
const startBtn = new r.Rect(650, 500, 400, 100, "red")
rge.addEntity(startBtn)

// Adding an onClick function to the Entity
startBtn.onClick = () => {
    // Start Game logic here
    console.log("Start Button Clicked!")
}
// Register the click handler to the RGE object
rge.addMouseClickHandler(startBtn);

Great! As you can see, this allows Rect's to be turned into clickable buttons, which can be used to initialize games.

Mouse X and Mouse Y

RGE.js provides a utility to access the mouse's X and Y coordinates. (Works with mobile, but not recommended). Let's see an example of making a rect follow the mouse pointer.

let x = 0;
let y = 0;
const rect = new r.Rect(x, y, 50, 50, "red");
rge.addEntity(rect);

function tick() {
    // We do minus 25, since (0,0) is in the top left. This makes the rect centered in the mouse pointer.
    x = rge.mouseX - 25;
    y = rge.mouseY - 25;

    rect.update(x, y)
}

More Entities

Ellipses

Ellipses are also a very commonly used entity. Creating an ellipse is very similar to making a rect.

const ellipse = new r.Ellipse(x, y, radius, fillColor)
rge.addEntity(ellipse);

function tick() {
    ellipse.update(newX, newY, newColor);
}

Ellipses behave nearly identically to Rect's.

Collision Basics

Although collisions are traditionally a difficult thing to implement, RGE.js makes it very easy and intuitive. We will take a look at implementing collisions between different Rect entities.

Collisions in RGE.js versions > 0.0.5

const rect1 = new r.Rect(x, y, width, height, "red");
const rect2 = new r.Rect(x, y, width, height, "blue");

rge.addEntity(rect1);
rge.addEntity(rect2);

function tick() {
    if (rge.collideRectRect(rect1, rect2)) {
        // Logic for what happens after collision. In this case, we will destroy rect2.
        rge.destroyEntity(rect2);
    }
}

rge.setTickFunction(tick);

Collisions in RGE.js versions < 0.0.5

⚠️ Deprecated ⚠️
const rect1 = new r.Rect(x, y, width, height, "red");
const rect2 = new r.Rect(x, y, width, height, "blue");

rge.addEntity(rect1);
rge.addEntity(rect2);

function tick() {
    if (rect1.collidesWith(rect2)) {
        // Logic for what happens after collision. In this case, we will destroy rect2.
        rge.destroyEntity(rect2);
    }
}

rge.setTickFunction(tick);

Once rect2 is destroyed, it is removed from the canvas. Since we did not call an update() function to rect2 however, you may think that the rect2 variable will contain stale data about the non-existing rect. However, a value is stored inside the Rect object which states if it is destroyed or not. The collidesWith function checks if the object is destroyed or not before implementing the collision logic, so collision with destroyed entities can not occur.

Custom Entities

RGE.js provides a sensible set of premade entities which should suit the needs of most developers. However, if you wish to create your own entity, you are always able to do that.

Entities can be made by extending the Entity object (which we went over previously). How do we do this? Let's take a look at making custom Rect entity which has no collisions, and increments it's size every tick.

class MyCustomRectEntity extends Entity {
    constructor(x, y, width, height) {
        super(x, y);
        this.width = width;
        this.height = height;
    }

    update() {
        // Incrementing size every update call
        this.width = width+1;
        this.height = height+1;
    }

    render(context) {
        context.fillRect(this.x, this.y, this.width, this.height);
    }

    collisionLogic(otherRect) {
        // Opting out of collisions
        return false;
    }
}

// Using our new entity
const sizeIncreasingRect = new MyCustomRectEntity(50, 50, 300, 70)
rge.addEntity(sizeIncreasingRect)

function tick() {
    sizeIncreasingRect.update()
}

You can also directly extend premade entities. For example, instead of making a custom rect as an extension of Entity, you can simply extend Rect and modify some values.

0.4.9

4 months ago

0.4.8

4 months ago

0.4.5-beta

5 months ago

0.3.8

5 months ago

0.3.7

5 months ago

0.5.0

4 months ago

0.5.2

4 months ago

0.5.1

4 months ago

0.3.9

5 months ago

0.4.4

5 months ago

0.4.7

5 months ago

0.4.6

5 months ago

0.4.1

5 months ago

0.4.0

5 months ago

0.6.1

3 months ago

0.4.3

5 months ago

0.6.0

3 months ago

0.4.2

5 months ago

0.3.6

8 months ago

0.3.5

8 months ago

0.3.2

8 months ago

0.3.4

8 months ago

0.3.3

8 months ago

0.3.1

8 months ago

0.3.0-beta

8 months ago

0.3.0

8 months ago

0.2.9

8 months ago

0.2.6

8 months ago

0.2.8

8 months ago

0.2.5

8 months ago

0.2.3

8 months ago

0.2.2

8 months ago

0.2.4

8 months ago

0.2.1

9 months ago

0.2.0-alpha

9 months ago

0.1.9-alpha

9 months ago

0.1.8-alpha

9 months ago

0.1.6-beta

9 months ago

0.1.7

9 months ago

0.1.6-alpha

9 months ago

0.1.5

9 months ago

0.1.3

9 months ago

0.1.0

10 months ago

0.0.84

10 months ago

0.0.85

10 months ago

0.0.86

10 months ago

0.0.87

10 months ago

0.0.82

10 months ago

0.0.83

10 months ago

0.0.81

10 months ago

0.0.71

10 months ago

0.0.8

10 months ago

0.0.7

10 months ago

0.0.66

10 months ago

0.0.67

10 months ago

0.0.68

10 months ago

0.0.62

10 months ago

0.0.63

10 months ago

0.0.64

10 months ago

0.0.61

10 months ago

0.0.58

10 months ago

0.0.55

10 months ago

0.0.56

10 months ago

0.0.57

10 months ago

0.0.51

10 months ago

0.0.52

10 months ago

0.0.43

10 months ago

0.0.5

10 months ago

0.0.42

10 months ago

0.0.41

10 months ago

0.0.4

10 months ago

0.0.37

10 months ago

0.0.35

10 months ago

0.0.3

10 months ago

0.0.25

10 months ago

0.0.2

10 months ago

0.0.1

10 months ago