As the the beta for 3D Game Programming for Kids draws near, I have been reviewing the content. One thing that I realized was that that the game that I have been building is tentatively scheduled to go after the JavaScript objects introduction. I do not plan on going heavy with the object oriented coding for this book, but it still seems like something that I have to at least touch on.
With that in mind, I should try to find some opportunity for object oriented coding in the platformer game that I have been trying to build:
My initial thought is to convert the ramps from their current functional approach:
function makeRamp(x, y, rotation) {
var ramp = new Physijs.ConvexMesh(
new THREE.CubeGeometry(50, 500, 10),
Physijs.createMaterial(
new THREE.MeshBasicMaterial({color:0x0000cc}), 0.2, 1.0
),
0
);
ramp.rotation.set(0, 0, rotation);
ramp.position.set(x, y, 0);
return ramp;
}
var ramp1 = makeRamp(0.4*width/2, -height/2 + 25, -Math.PI/4);
scene.add(ramp1);
var ramp2 = makeRamp(-0.3*width/2, 0, Math.PI/3);
scene.add(ramp2);
This can be rewritten as: var Ramp = function(x, y, rotation) {
this.mesh = new Physijs.ConvexMesh(
new THREE.CubeGeometry(50, 500, 10),
Physijs.createMaterial(
new THREE.MeshBasicMaterial({color:0x0000cc}), 0.2, 1.0
),
0
);
this.setPosition(x,y);
this.setRotation(rotation);
};
Ramp.prototype.setRotation = function(rotation) {
this.mesh.rotation.set(0,0,rotation);
};
Ramp.prototype.setPosition = function(x, y) {
this.mesh.position.set(x, y, 0);
};
This class can then be invoked in much the same way as the factory function: var ramp1 = new Ramp(0.4*width/2, -height/2 + 25, -Math.PI/4);
scene.add(ramp1.mesh);
var ramp2 = new Ramp(-0.3*width/2, 0, Math.PI/3);
scene.add(ramp2.mesh);
Admittedly, that is not a significant reduction in the amount of code. It is a bit cleaner. What can really improve in this approach is the event handling. Previously, I had to rely on document event handlers: var active_ramp, mouse_x, mouse_y;
document.addEventListener("mousedown", function(event) {
//console.log(event.clientX);
//console.log(event.clientY);
mouse_x = event.clientX;
mouse_y = event.clientY;
var position = new THREE.Vector3(
event.clientX - width/2,
height/2 - event.clientY,
500
);
var vector = new THREE.Vector3(0, 0, -1);
var ray = new THREE.Ray(position, vector);
var intersects = ray.intersectObject(ramp1);
if (intersects.length > 0) active_ramp = ramp1;
intersects = ray.intersectObject(ramp2);
if (intersects.length > 0) active_ramp = ramp2;
});
The disadvantage of this approach is the need to manually check all ramps. With an OO approach, each ramp is responsible for checking if it has been clicked: Ramp.prototype.onClick = function(event) {
this.mouse_x = event.clientX;
this.mouse_y = event.clientY;
var position = new THREE.Vector3(
event.clientX - width/2,
height/2 - event.clientY,
500
);
var vector = new THREE.Vector3(0, 0, -1);
var ray = new THREE.Ray(position, vector);
var intersects = ray.intersectObject(this.mesh);
this.isActive = (intersects.length > 0);
};
That's not a heck of a lot cleaner, but it does accomplish the goal of forcing each instance to check if it is being clicked. Really, I need to move just about all of that out into a more general click handler (or get the DOM event library working again). The only thing in there that is specific to the ramps being moved around is the isActive
setting. I will worry about generalizing another night. For now, I get it working with some simple event document event listeners in the Ramp constructor:
var Ramp = function(x, y, rotation) {
// ...
var that = this;
document.addEventListener("mousedown", function(e){that.onClick(e);});
document.addEventListener("mousemove", function(e){that.onDrag(e);});
document.addEventListener("mouseup", function(e){that.onDrop(e);});
};
Ew. I am definitely going to need to rethink this. It does work—I can again click and drag ramps around the screen. But I had hoped to avoid a scoping discussion in a kid's introduction book, but here I am forced to fall back to a that = this
scope hack. I am unsure if this means that I should be writing my own DOM events library or if I ought to go back to retry some of the existing solutions. For now, I call it a night. At least it's a night with a working implementation.
(the code so far)
Day #648
No comments:
Post a Comment