Saturday, January 26, 2013

Wrapping Three.js Ghosts for Physijs Players

‹prev | My Chain | next›

I continue to explore a platform-based game for possible inclusion in 3D Game Programming for Kids.


This Three.js + Physijs game seems like it might appeal to kids. I still need to ensure that the game is a fit for the book. It needs to somewhat short—too much typing is never a good idea. It needs to introduce new concepts or aspects of programming and / or gaming. Most importantly, it needs to be playable.

Currently, it is still missing a few things to make it playable. Chief among them is boundary conditions. In mobile games like Doodle Jump, the sides of the screen wrap. This seems like it may be prohibitively difficult to accomplish in a kids' book. Still, I would like to see if I can make it work. But first, a fallback.

I make fixed walls on the sides of the screen to hold the player in the game area:
  function makeWall(x)  {
    var wall = new Physijs.BoxMesh(
      new THREE.CubeGeometry(350, 5000, 100),
      Physijs.createMaterial(
        new THREE.MeshBasicMaterial({color: 0x000000}), 0.2, 1.0    
      ),
      0 
    );
    wall.position.x = x;
    return wall;
  }
  scene.add(makeWall(width/-2));
  scene.add(makeWall(width/2));
This seems like the solution that I would use in the book. It re-uses existing concepts and works:


I don't think it is possible for a thing to be in two places at once in Three.js and it almost certainly violates the laws of physics in Physijs. So if I want to try a wraparound solution, I think I need to "fake" it. That is, until a player is either fully on one side or the other, I need a ghost to appear on the opposite side.

For my ghost, I create a non-physical (i.e. Three.js) object:
  var ghost = new THREE.Mesh(
    new THREE.CubeGeometry(50, 75, 5),
    new THREE.MeshNormalMaterial()      
  );
  ghost.visible = false;
  scene.add(ghost);
I start it invisible because it should only show when the player nears the boundary. For the boundary check, I add a call to animateGhost() in the main animate() function:
  function animate() {
    requestAnimationFrame(animate);
    scene.simulate(); // run physics

    animateGhost();
    renderer.render(scene, camera);
  }
  animate();
To get started with animating the ghost, I start with just a single side boundary, the left / negative X. I also start the animation short of the actual side—two thirds of the way there. This should make it easier to see it in action:
  function animateGhost() {
    if (player.position.x > width/-3) {
      ghost.visible = false; 
      return;
    }
    ghost.visible = true;
    ghost.position.y = player.position.y;
    ghost.position.x = width/3 - (width/-3 - player.position.x);
  }
If the player is more than a third away from the left wall, then the ghost is invisible and animateGhost() does nothing else. Otherwise the ghost is shown and it mirror the player's position on the other side of the screen.

And it actually works:


I can see where this is going. At some point, I would need to swap the ghost and the actual player (using the dirty position trick from last night for the Physijs player). I would also need to be able to perform the inverse. I am reasonably confident that I could make that work, but this does seem too complicated for a kid's game.

For now, I think it best to stick with the black borders. Tomorrow I will move forward with the remainder of the game by adding the ability for the camera to move up along with the player.

(the code so far)

Day #642

No comments:

Post a Comment