Basic structure

Two main parts:

  • The game part (PIXI & Matter)
  • The other stuff part (Sapper)

The game includes: game.ts,game_config.ts & the bunch of game objects inside /src/game folder

  • game.ts specifies the basic layout: a canvas container & the game objects
    
    new Container({
    	view: canvas, // the canvas element to draw the game on
    	builder: (app, { topId, bottomId }) => [
    		new Background(app),
    		new Ball({ app: app, name: 'ball', onCollisionCallback: (otherBody) => ... }),
    		new Paddle({ app: app, name: 'paddle-top' }),
    		new Paddle({ app: app, name: 'paddle-bottom' })
    	]
    })
    			
  • game_config.ts contains defaults for canvas width, height & physics stuff such as friction, inertia...
  • Game objects should extends src/game/app/GameObject.ts parent class & be included in game.ts
    
    class Ball extends GameObject // basic
    class Ball extends Materialized(GameObject) // "materialize" it and include in physics world, trigger onCollisionCallback
    class Ball extends Interactive(Materialized(GameObject)) // subscribe to key press events
    			
  • There are two game loops (exposed as update(_delta: time) & fixedUpdate(_delta: time))
    • update() does not have FPS cap, there more refresh rate your monitor have, the lower _delta goes
    • fixedUpdate() have FPS cap of 60FPS, _delta will stay closely to 1.0 as it can; you should put logics & physics-related codes inside this loop (this is to prevents having objects on 144Hz monitor move more quickly than a 60Hz one)
  • Some already-made interfaces that a Game object can implements to simplify codes
    
    // A game object can implement "Shapeable" interface & "requiredGraphics" method,
    // it requires a PIXI Graphics instance to draw onto the canvas stage
    class Ball extends GameObject implements Shapeable {
      requireGraphics(): Graphics {
        const [x, y, radius] = [100, 100, 6]
        //draw a circle
        return new Graphics().beginFill(0xFFFFFF).drawCircle(x, y, radius).endFill()
      }
    }
    			

The other stuffs (such as this block of texts) are handled by Svelte

To bridge events generated from canvas to Svelte components, we can use EventEmitter