in development

who moved my cheese-y avatar?

My past games all used a first-person camera. For the next one, I’m using third person because I think it will help the player better understand who they are in the game world.

Yes, you’re a beach toy with wings. My apologies.

When I switched to the third person, the first thing I noticed was how jittery all the model motion became. I’d drag the mouse across the screen to change the yaw and all of my models would shake as if they were trying out a new dance step.

I traced the cause to how I was handling mouse events and camera rotation. My original first-person code established a mouse move event handler, which rotated the camera directly.

mouse: {
	x: 0,
	y: 0,
	down: false
},

onMouseMove: function(event) {
	var dx, dy;

	// if the left mouse button is down (i.e., mouse is dragging)
	if (mouse.down) {
		// generate mouse deltas
		dx = SPIN_RATE * (event.pageX - mouse.x);
		dy = SPIN_RATE * (event.pageY - mouse.y);
		// rotate camera yaw by dx and pitch by dy
		camera.turn(dx, dy);
	}
	// store off last mouse position
	mouse.x = event.pageX;
	mouse.y = event.pageY;
	return false;
}

Note that the degree of camera rotation is determined solely by the change in the mouse position. There’s no attempt to synchronize the rotation to the animation timings. This seemed to work okay in first person, but third person perspective reveals its flaws–very likely because now I have a fixed object sitting in front of the camera to compare the rest of the scene to.

The new code splits things up a little. Now, the mouse move handler only tracks changes to the mouse position.

mouse: {
	down: false,
	last: {
		x: 0,
		y: 0
	},
	next: {
		x: 0,
		y: 0
	}
},

onMouseMove: function(event) {
	// if left mouse button is down (i.e., mouse is dragging)
	if (mouse.down) {
		// store off "new" mouse position
		mouse.next.x = event.pageX;
		mouse.next.y = event.pageY;
	}
	return false;
}

In the player update function–which is called on every animation frame–I actually rotate the camera.

update: function() {
	var dt, dx, dy;

	// calculate number of seconds elapsed since last animation frame
	dt = SOAR.interval * 0.001;
	// calculate mouse deltas based on position AND time interval
	dx = 0.5 * dt * (mouse.next.x - mouse.last.x);
	dy = 0.5 * dt * (mouse.next.y - mouse.last.y);
	// rotate the camera
	camera.turn(dx, dy);
	// store off "new" position as "old" position
	mouse.last.x = mouse.next.x;
	mouse.last.y = mouse.next.y;

	... player position update ...

}

Camera rotation is much smoother. It’s still slightly clunky, as I’m computing deltas based on integer mouse positions rather than receiving them directly from the mouse driver. Hopefully, Mozilla’s Pointer Lock API will enter general usage before long.