DEV Community

Cover image for TCJSgame v2 vs v3: What’s New and Why It Matters
Kehinde Owolabi
Kehinde Owolabi

Posted on

TCJSgame v2 vs v3: What’s New and Why It Matters

⚔️ TCJSgame v2 vs v3 — Accurate comparison, code diffs, and ratings

If you've been working with TCJSgame, you probably use v2 and are testing or migrating to v3. I dug into the actual v2 code and compared it to v3 changes. This article shows what changed, why it matters, and gives a numeric rating (out of 100) for each version across features, ease of use, and performance.


TL;DR

  • v2 is simple, compact, and easy to learn — excellent for small demos and prototypes.
  • v3 adds camera support, tilemaps, sprites, angle-based movement, and better utilities — a step toward a proper 2D engine.
  • Recommendation: For new projects start with v3. For tiny demos or compatibility needs, v2 still works.

1) Precise comparison (based on v2 code)

Loop & Timing

v2

  • Uses setInterval(() => this.updat(), 20) (~50 FPS).
  • Movement is pixels per frame, not time-based.

v3

  • Designed to work with requestAnimationFrame (rAF).
  • Supports delta-time (dt) so movement is pixels per second.
  • Compatible with the tcjsgame-perf.js extension for smoother gameplay.

Camera

v2

  • Camera class exists.
  • Display.updat() translates by -camera.x, -camera.y.

v3

  • Camera is integrated with scenes and tilemaps.
  • Works better with optimizations (culling, caching).

Components & Movement

v2

  • Component has speedX, speedY, gravity, bounce, physics, changeAngle.
  • move() is per-frame.
  • moveAngle() exists but less commonly used.

v3

  • Adds richer movement utilities: project, glideTo, accelerate, decelerate.
  • Designed to support dt-based movement for consistent speeds.

Tilemap & Sprites

v2

  • No TileMap.
  • Has a basic Sprite class for frame-based animation.

v3

  • New TileMap and Tile classes.
  • Tile collision, add/remove tiles, caching support.
  • Sprites integrate better with scenes.

Input & Mouse

v2

  • Handles keydown, keyup, mousedown, mouseup, touchstart, touchend.
  • Basic Mouse component exists.

v3

  • Improves pointer tracking.
  • Handles rotation and camera when checking clicks.

2) Side-by-side code snippets

A) Game Loop

v2

start(width = 480, height = 270) {
  this.canvas.width = width;
  this.canvas.height = height;
  document.body.insertBefore(this.canvas, document.body.childNodes[0]);
  this.interval = setInterval(() => this.updat(), 20);
  this.addEventListeners();
}

updat() {
  this.clear();
  this.context.save();
  this.context.translate(-this.camera.x, -this.camera.y);
  update(); // global update
  comm.forEach(c => { c.move(); c.update(this.context); });
  this.context.restore();
}
Enter fullscreen mode Exit fullscreen mode

v3

start(width = 480, height = 270) {
  this.canvas.width = width;
  this.canvas.height = height;
  document.body.insertBefore(this.canvas, document.body.childNodes[0]);
  this._lastTime = performance.now();
  requestAnimationFrame(this._loop.bind(this));
}

_loop(timestamp) {
  let dt = (timestamp - this._lastTime) / 1000;
  this._lastTime = timestamp;
  this.clear();
  this.context.save();
  this.context.translate(-this.camera.x, -this.camera.y);
  if (typeof update === "function") update(dt);
  comm.forEach(c => { c.move(dt); c.update(this.context); });
  this.context.restore();
  requestAnimationFrame(this._loop.bind(this));
}
Enter fullscreen mode Exit fullscreen mode

B) Component Movement

v2

move() {
  if (this.physics) {
    this.gravitySpeed += this.gravity;
    this.x += this.speedX;
    this.y += this.speedY + this.gravitySpeed;
  } else {
    this.x += this.speedX;
    this.y += this.speedY;
  }
}
Enter fullscreen mode Exit fullscreen mode

v3

move(dt = 1/60) {
  if (this.physics) {
    this.gravitySpeed += this.gravity * dt;
    this.x += this.speedX * dt;
    this.y += (this.speedY + this.gravitySpeed) * dt;
  } else {
    this.x += this.speedX * dt;
    this.y += this.speedY * dt;
  }
}
Enter fullscreen mode Exit fullscreen mode

C) Tilemap

v2
❌ None

v3

class TileMap {
  constructor(render, map, tile, width, height) { ... }
  show() { ... }
  tiles(id = 0) { ... }
  crashWith(obj, id = 0) { ... }
  add(id, tx, ty) { ... }
  remove(tx, ty) { ... }
}
Enter fullscreen mode Exit fullscreen mode

3) Ratings (0–100)

Engine Features Ease of Use Performance Final Score
v2 60 80 55 65/100
v3 88 75 80 81/100

Why v2 scores lower

  • Simple and easy to use, but lacks tilemaps and modern loop handling.
  • Performance suffers because it uses setInterval.

Why v3 scores higher

  • Adds TileMap, better camera, more movement utilities, and delta-time support.
  • Higher performance with requestAnimationFrame + perf extension.
  • Slightly harder to learn but worth it for serious projects.

Migration notes

  • Old code still works in v3 if you keep useDelta: false in the perf extension.
  • To upgrade, rewrite movement to use dt (pixels/second).
  • Use display.add(component, scene) and display.camera.follow(player) in v3.

Conclusion

  • v2 is great for quick prototypes and learning.
  • v3 is better for real games: smoother, faster, and feature-rich.
  • For best results: combine v3 with the tcjsgame-perf.js extension.

🚀 TCJSgame is evolving — and v3 is a huge step forward.

Top comments (0)