Code Monkey home page Code Monkey logo

piximatters's Introduction

Pixi Matters

Game demo using PixiJS, MatterJS with Typescript in OOP. The project is compiled using Parcel.

Try the demo here

screen




Installing this example

First install NodeJS. Then install all required libraries in one go. (PixiJS, MatterJS, Typescript and Parcel)

npm install

Start development in a live server

npm run start

Build the project for publication

npm run build



Physics basics

In Game.ts we create a physics world. The physics world gets updated 60 times per second using Pixi's update loop. You can update your own sprites after the physics world has updated.

GAME.TS

import Matter from 'matter-js'

class Game {
    onLoaded(){
        this.engine = Matter.Engine.create()
    }
    update() {
        Matter.Engine.update(this.engine, 1000 / 60)
        // update your sprites 
        // ...
    }
}

Sprites classes can create a rigidBody at the same size as their sprite image. The rigidbody has to be added to the physics simulation. You can add a label, this will be useful later for collision detection.

Then, every frame, the sprite reads the position of its own rigidBody, to know where to draw itself on the canvas. In other words: MatterJS creates the physics simulation, and PixiJS draws the sprites on the canvas.

FISH.TS

class Fish extends PIXI.Sprite {
    constructor(texture:PIXI.Texture, game:Game) {
        super(texture)
        this.rigidBody = Matter.Bodies.rectangle(300, 30, 60, 60, {label:"Fish"}) //x,y,w,h
        Matter.Composite.add(game.engine.world, this.rigidBody)
    }
    update() {
        this.position.set(this.rigidBody.position.x, this.rigidBody.position.y)
        this.rotation = this.rigidBody.angle
    }
}

Now you can add a new Fish() to your game!

GAME.TS

class Game {
    myfish:Fish
    doneLoading(){
        this.myfish = new Fish(this.pixi.loader.resources["fish"].texture!, this)
        this.pixi.stage.addChild(myfish)
    }
    update(delta:number){
         Matter.Engine.update(this.engine, 1000 / 60)
         myfish.update()
    }
}



Moving

Rigidbodies automatically move and bounce because forces are applied to them (gravity, friction, bouncyness, and other forces). This results in a velocity (current movement) of the sprite. You can always check the velocity using console.log(this.rigidBody.velocity)

To move a physics sprite yourself, you can add a force that affects the rigidbody. You can also directly set the velocity of the rigidbody.

// apply a upward force (jump)
Matter.Body.applyForce(this.rigidBody, { x: this.rigidBody.position.x, y: this.rigidBody.position.y }, { x: 0, y: -0.25 })

// set velocity directly
Matter.Body.setVelocity(this.rigidBody, { x: 10, y: 10 })

Static elements have no forces applied to them, but can still collide with other physics elements. This is ideal for the ground and platforms.

this.rigidBody = Matter.Bodies.rectangle(450, 480, 900, 100, { isStatic: true, label:"Ground" })

If your object only has to move through player interaction (a player character), then you can set inertia to false.

 const playerOptions: Matter.IBodyDefinition = {
    inertia: Infinity,
    inverseInertia: Infinity,
    label: "Player"
}
this.rigidBody = Matter.Bodies.rectangle(600, 230, 75, 100, playerOptions)



Collision

The best part of a physics engine is that you get detailed collision detection:

class Game {
    onLoaded() {
        this.engine = Matter.Engine.create()
        Matter.Events.on(this.engine, 'collisionStart', (event) => this.onCollision(event))
    }
    onCollision(event: Matter.IEventCollision<Matter.Engine>) {
        let collision = event.pairs[0]
        let [bodyA, bodyB] = [collision.bodyA, collision.bodyB]
        console.log(`${bodyA.label} collides with ${bodyB.label}`)
    } 
}

Finding the sprite that collided

Collision detection returns only the rigidBody that collided, we have to find the sprite that uses this rigidbody:

findSpriteWithRigidbody(rb: Matter.Body) {
    return this.allSprites.find((sprite) => sprite.rigidBody === rb)
}

If you want certain items (for example coins in a mario game) not to collide with each other (but still collide with other items in the game), then you can add a Collision Filter




Hitbox

By making the rigidbody a different size than the sprite, you can create a custom hitbox.

// TEXTURE WIDTHxHEIGHT = 60 X 60 HITBOX WIDTHxHEIGHT = 30 X 30
this.rigidBody = Matter.Bodies.rectangle(15, 15, 30, 30, {label:"Fish"}) 
// draw the sprite with 15 pixels offset
this.position.set(this.rigidBody.position.x - 15, this.rigidBody.position.y - 15)

Drawing the hitbox

Just to be sure what's happening you can draw your hitbox using Pixi's drawing code.

constructor(texture: PIXI.Texture, game:Game) {
    let hitbox = new PIXI.Graphics()
    hitbox.lineStyle(2, 0x33FF33, 1)
    hitbox.drawRect(-30, -30, 60, 60) // x offset, y offset, width, height
    this.addChild(hitbox)
}

โš ๏ธ A hitbox could also be a circle. Or you can create a compound hitbox out of several rigidbodies. Finally there is the option of creating a hand-drawn hitbox with a physics editor.




Links




PixiJS demos

piximatters's People

Contributors

kokodoko avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

piximatters's Issues

Thank you!

Just wanted to say thank you for making and sharing this. Super helpful having an example of how to combine Pixi and Matter.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.