Clusters: using Three for a 2D game

Clusters: https://harmlessfun.xyz/clusters

I’ve used Three to remake the old 1990s freeware game Stardust (which I also wrote, back in the day) as a web game Clusters. Items of possible interest to this forum:

  • I don’t use Sprite anywhere. I found it more flexible to use OrthogonalCamera and simple ‘tile sprites’ with a square Geometry and MeshBasicMaterial, letting me easily adjust the UVs, transparencies, color effects and such.
  • Did the starry background with a rotating PerspectiveCamera and a CubeTexture background, some fun zoom tricks by animating the camera’s FOV to ridiculous values like 1 or 179
  • Responsive design to work well on cell phones and iPads (which is why I added a ‘joystick’ to an otherwise keyboard-driven game)
  • Lot of interaction between HTML elements and multiple canvases, orchestrating key, mouse, and touch events
  • Sound using THREE.Audio

clusters-top

clusters-level

https://harmlessfun.xyz/clusters

6 Likes

so cool, good job

Awesome! Really love it!

are you using cubes for the platforms or the player sprite?, cause i would like to make a 2d game using three.js but i am unsure if i can use planes with pixel art as textures or i would be better to use cubes showing one of its faces.

do you have the repository of the project to look at.

I started with cubes, but of course that’s a bit wasteful as you’re never showing 5 of the 6 sides. Instead I found it easiest to make my own THREE.Geometry() with four vertices and two triangular faces – that is, a square. Here’s the code excerpt (in Typescript):

  private uvTopLeft = new THREE.Vector2();
  private uvTopRight = new THREE.Vector2();
  private uvBottomLeft = new THREE.Vector2();
  private uvBottomRight = new THREE.Vector2();
...
    this.geo = new THREE.Geometry();
    this.geo.vertices.push(new THREE.Vector3(0, 0, 0)); // bottom left
    this.geo.vertices.push(new THREE.Vector3(0, 1, 0)); // top left
    this.geo.vertices.push(new THREE.Vector3(1, 1, 0)); // top right
    this.geo.vertices.push(new THREE.Vector3(1, 0, 0)); // bottom right
    this.geo.faces.push(new THREE.Face3(2, 1, 0));
    this.geo.faceVertexUvs[0].push([this.uvTopRight, this.uvTopLeft, this.uvBottomLeft]);
    this.geo.faces.push(new THREE.Face3(0, 3, 2));
    this.geo.faceVertexUvs[0].push([this.uvBottomLeft, this.uvBottomRight, this.uvTopRight]);
    this.geo.computeFlatVertexNormals();

The point of those “uv” Vector2s is that they point back into the source image which is a THREE.MeshBasicMaterial. I can switch between the “tiles” of the image by changing the vectors.

and still the collisions and gravity you have in the game are for 2d right?