Navigation Menu

Skip to content

Commit

Permalink
refactored play state
Browse files Browse the repository at this point in the history
refactored end zone detection to generic 3d hotspot in Physics
added debug output DOM element
  • Loading branch information
stevehb committed Mar 23, 2012
1 parent a259d69 commit 5c7e061
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 82 deletions.
20 changes: 18 additions & 2 deletions racecar.html
Expand Up @@ -3,9 +3,18 @@
<script src="jquery-1.7.1.js"></script> <script src="jquery-1.7.1.js"></script>
<script src="Three.js"></script> <script src="Three.js"></script>
<script src="Stats.js"></script> <script src="Stats.js"></script>
<script src="tween.js"></script> <script src="Tween.js"></script>
<script src="THREEx.KeyboardState.js"></script> <script src="THREEx.KeyboardState.js"></script>
<script src="racecar.js"></script> <script src="racecar.js"></script>
<script src="rcPhysics.js"></script>
<script src="rcTitleState.js"></script>
<script src="rcPlayCountdownState.js"></script>
<script src="rcPlayRaceState.js"></script>
<script src="rcEndState.js"></script>
<script src="rcTrack.js"></script>
<script src="rcPlayer.js"></script>
<script src="rcRacer.js"></script>

<style type="text/css"> <style type="text/css">
body { body {
margin: 0px; margin: 0px;
Expand All @@ -25,7 +34,7 @@
position: absolute; position: absolute;
} }
#game-timer { #game-timer {
color:#00ff00; color: #ff0000;
display: none; display: none;
font-size: 48; font-size: 48;
margin: 4px; margin: 4px;
Expand All @@ -40,6 +49,12 @@
right: 0px; right: 0px;
top: 0px; top: 0px;
} }
.debug {
position: relative;
display: inline;
font-family: Helvetica,sans-serif;
font-size: 12px;
}
</style> </style>
</head> </head>
<body onload="init()"> <body onload="init()">
Expand All @@ -50,5 +65,6 @@
<img id="img-logo" src="img/logo.png" /> <img id="img-logo" src="img/logo.png" />
<img id="img-start" src="img/start.png" /> <img id="img-start" src="img/start.png" />
</div> </div>
<div class="debug" id="debug"></div>
</body> </body>
</html> </html>
28 changes: 15 additions & 13 deletions racecar.js
Expand Up @@ -23,31 +23,24 @@ function init() {
RC.scene = new THREE.Scene(); RC.scene = new THREE.Scene();
RC.log("creating camera: fov=" + RC.FOV + ", aspect=" + (RC.WIDTH/RC.HEIGHT)); RC.log("creating camera: fov=" + RC.FOV + ", aspect=" + (RC.WIDTH/RC.HEIGHT));
RC.camera = new THREE.PerspectiveCamera(RC.FOV, RC.WIDTH / RC.HEIGHT, 1, 10000); RC.camera = new THREE.PerspectiveCamera(RC.FOV, RC.WIDTH / RC.HEIGHT, 1, 10000);
RC.camera.position.set(0, 10, 0); RC.camera.position.set(0, 1.5, 0);
RC.camera.rotation.y = Math.PI; RC.camera.rotation.y = Math.PI;
RC.scene.add(RC.camera); RC.scene.add(RC.camera);
RC.renderer = new THREE.WebGLRenderer({ antialias: true, maxLights: RC.NLIGHTS }); RC.renderer = new THREE.WebGLRenderer({ antialias: true, maxLights: RC.NLIGHTS });
RC.renderer.setClearColorHex(0x223344, 1.0); RC.renderer.setClearColorHex(0x223344, 1.0);
RC.renderer.setSize(RC.WIDTH, RC.HEIGHT); RC.renderer.setSize(RC.WIDTH, RC.HEIGHT);
$("#canvas-container")[0].appendChild(RC.renderer.domElement); $("#canvas-container")[0].appendChild(RC.renderer.domElement);


// get additional codes, no waiting
$.ajaxSetup({ async : false });
$.getScript("rcPhysics.js");
$.getScript("rcTitleState.js");
$.getScript("rcPlayCountdownState.js");
$.getScript("rcPlayRaceState.js");
//$.getScript("rcEndState.js");
$.getScript("rcTrack.js");
$.getScript("rcPlayer.js");
$.getScript("rcRacer.js");
$.ajaxSetup({ async : true });

// create the title state, and start the updates // create the title state, and start the updates
RC.physics = new RC.Physics(); RC.physics = new RC.Physics();
RC.stateStack = new Array(); RC.stateStack = new Array();
RC.stateStack.push(new RC.TitleState()); RC.stateStack.push(new RC.TitleState());


// set up debug line
$(".debug").css({
"top": RC.HEIGHT + 10
});

RC.lastTime = new Date(); RC.lastTime = new Date();
RC.update(); RC.update();
} }
Expand All @@ -71,3 +64,12 @@ RC.update = function() {
RC.log = function(msg) { RC.log = function(msg) {
console.log("RC: " + msg); console.log("RC: " + msg);
}; };

RC.debug = (function() {
var info = ["", "", "", ""];

return function(pos, msg) {
info[pos] = msg;
$("#debug").text(info[1] + " " + info[2] + " " + info[3])
};
}());
75 changes: 47 additions & 28 deletions rcPhysics.js
Expand Up @@ -2,18 +2,19 @@ var RC = RC || {};


RC.Physics = function() { RC.Physics = function() {
this.objList = new Array(); this.objList = new Array();
this.hotspots = new Array(); this.hotcubeCallbacks = new Array();


this.makePhysical = function(obj) { this.makePhysical = function(obj) {
obj.momentum = new THREE.Vector3(0, 0, 0); obj.momentum = new THREE.Vector3(0, 0, 0);
obj.position = new THREE.Vector3(0, 0, 0); obj.position = new THREE.Vector3(0, 0, 0);
obj.rotation = new THREE.Vector3(0, 0, 0); obj.rotation = new THREE.Vector3(0, 0, 0);
obj.accumForce = new THREE.Vector3(0, 0, 0); obj.accumForce = new THREE.Vector3(0, 0, 0);
obj.friction = 0.0; obj.friction = 0.0;
obj.moveable = true;
}; };


this.addObject = function(obj) { this.addObject = function(obj) {
RC.log("adding object to physics"); //RC.log("adding object to physics");
this.objList.push(obj); this.objList.push(obj);
}; };


Expand Down Expand Up @@ -52,38 +53,56 @@ RC.Physics = function() {
obj.momentum.z += -Math.cos(obj.rotation.y) * (magnitude * obj.friction); obj.momentum.z += -Math.cos(obj.rotation.y) * (magnitude * obj.friction);
}; };


this.addHotspot2d = function(rect, callback) { this.resetRotation = function(obj, rotation) {
this.hotspots.push({ // reset rotation
"rect": rect, obj.rotation.y = rotation.y;
"callback": callback
}); // reset momentum
var magnitude = obj.momentum.length();
obj.momentum.multiplyScalar(0.0);
obj.momentum.x = -Math.sin(obj.rotation.y) * magnitude;
obj.momentum.z = -Math.cos(obj.rotation.y) * magnitude;

// and accumForce
magnitude = obj.accumForce.length();
obj.accumForce.multiplyScalar(0.0);
obj.accumForce.x = -Math.sin(obj.rotation.y) * magnitude;
obj.accumForce.z = -Math.cos(obj.rotation.y) * magnitude;
}; };


this.addHotcubeCallback = function(cube, obj, func) {
RC.log("adding callback for cube " + cube.name);
this.hotcubeCallbacks.push({
"cube" : cube,
"obj" : obj,
"func" : func
});
}

this.update = function(elapsed) { this.update = function(elapsed) {
var objRectPos = new THREE.Rectangle();
$.each(this.objList, function(idx, obj) { $.each(this.objList, function(idx, obj) {
// turn accumulated forces into momentum, // turn accumulated forces into momentum,
// then turn momentum into movement // then turn momentum into movement
obj.momentum.x += obj.accumForce.x * elapsed; if(obj.moveable) {
obj.momentum.z += obj.accumForce.z * elapsed; obj.momentum.x += obj.accumForce.x * elapsed;
obj.position.x += obj.momentum.x * elapsed; obj.momentum.z += obj.accumForce.z * elapsed;
obj.position.z += obj.momentum.z * elapsed; obj.position.x += obj.momentum.x * elapsed;
obj.accumForce.set(0, 0, 0); obj.position.z += obj.momentum.z * elapsed;
obj.accumForce.set(0, 0, 0);
}
});

// check hotcubes callbacks
$.each(this.hotcubeCallbacks, function(idx, callback) {
var cube = callback.cube;
var obj = callback.obj;
var pos = obj.position;


// trigger hotspots if(pos.x > cube.min.x && pos.x < cube.max.x &&
$.each(RC.physics.hotspots, function(idx, spot) { pos.y > cube.min.y && pos.y < cube.max.y &&
objRectPos.empty(); pos.z > cube.min.z && pos.z < cube.max.z) {
objRectPos.addPoint(obj.position.x, obj.position.z); callback.func(obj, cube);
if(spot.rect.intersects(objRectPos)) { }
RC.log("got a hit!");
spot.callback(spot.rect, obj);
} else {
//RC.log("no hit: spot=[" + spot.rect.getLeft() + "," + spot.rect.getTop() + "," +
// spot.rect.getRight() + "," + spot.rect.getBottom() + "] " +
// "obj=" + objRectPos.getLeft() + "," + objRectPos.getTop() + "," +
// objRectPos.getRight() + "," + objRectPos.getBottom() + "]");
}
});
}); });
}; };
}; };
28 changes: 22 additions & 6 deletions rcPlayCountdownState.js
Expand Up @@ -11,7 +11,11 @@ RC.PlayCountdownState = function() {
// set up timer, ready to countdown // set up timer, ready to countdown
var accumTime = 0; var accumTime = 0;
var timer = $("#game-timer"); var timer = $("#game-timer");
timer.text(this.COUNTDOWN_TIME.toFixed(2)); timer.text(this.COUNTDOWN_TIME.toFixed(0));
timer.css({
"left": (RC.WIDTH - timer.width()) / 2,
"top": (RC.HEIGHT - timer.height()) / 2
});


// create div to cover canvas, make it the background clear color, // create div to cover canvas, make it the background clear color,
// and fade it out to transparent // and fade it out to transparent
Expand All @@ -31,26 +35,38 @@ RC.PlayCountdownState = function() {
"background-color": rgbString "background-color": rgbString
}); });
$("#tmp-cover").show(); $("#tmp-cover").show();
$("#tmp-cover").fadeOut(3000, "linear", function() { $("#tmp-cover").fadeOut(2000, function() {
RC.log("activating count down"); RC.log("activating count down");
state = RC.PlayStateEnum.COUNTDOWN; state = RC.PlayStateEnum.COUNTDOWN;
timer.show(); timer.show();
$("#canvas-container").remove("#tmp-cover"); $("#canvas-container").remove("#tmp-cover");
}); });


// track & camera // set up track and racers
RC.track = new RC.Track(); RC.track = new RC.Track();
RC.camera.position.set(0, 10, 0); RC.player = new RC.Player();
RC.camera.rotation.y = Math.PI; RC.racers = new Array(RC.NRACERS);
RC.racers[0] = RC.player;
for(i = 1; i < RC.NRACERS; i++) {
RC.racers[i] = new RC.Racer(i);
}

// camera
RC.camera.position.copy(RC.player.position);
RC.camera.rotation.copy(RC.player.rotation);;


this.update = function(elapsed) { this.update = function(elapsed) {
if(state === RC.PlayStateEnum.COUNTDOWN) { if(state === RC.PlayStateEnum.COUNTDOWN) {
accumTime += elapsed; accumTime += elapsed;
var remaining = this.COUNTDOWN_TIME - accumTime; var remaining = this.COUNTDOWN_TIME - accumTime;
if(remaining > 0.0) { if(remaining > 0.0) {
timer.text(remaining.toFixed(2)); timer.text(remaining.toFixed(0));
} else { } else {
timer.text("0.00"); timer.text("0.00");
timer.animate({
"left": 0,
"top": 0
}, "fast");
RC.log("activating race"); RC.log("activating race");
RC.stateStack.pop(); RC.stateStack.pop();
RC.stateStack.push(new RC.PlayRaceState()); RC.stateStack.push(new RC.PlayRaceState());
Expand Down
34 changes: 22 additions & 12 deletions rcPlayRaceState.js
Expand Up @@ -8,17 +8,18 @@ RC.PlayRaceState = function() {
timer.text("0.00"); timer.text("0.00");


RC.track = RC.track || new RC.Track(); RC.track = RC.track || new RC.Track();

RC.player = RC.player || new RC.Player();
RC.camera.position.set(0, 10, 0); if(RC.racers.length !== RC.NRACERS) {
RC.camera.rotation.y = Math.PI; RC.racers.length = RC.NRACERS;

RC.racers[0] = RC.player;
RC.player = new RC.Player(); for(i = 1; i < RC.NRACERS; i++) {
RC.racers = new Array(RC.NRACERS); RC.racers[i] = new RC.Racer(i);
RC.racers[0] = RC.player; }
for(i = 1; i < RC.NRACERS; i++) {
RC.racers[i] = new RC.Racer(i);
} }


RC.camera.position.copy(RC.player.position);
RC.camera.rotation.copy(RC.player.rotation);

this.update = function(elapsed) { this.update = function(elapsed) {
accumTime += elapsed; accumTime += elapsed;
timer.text(accumTime.toFixed(2)); timer.text(accumTime.toFixed(2));
Expand All @@ -29,8 +30,17 @@ RC.PlayRaceState = function() {
} }
RC.physics.update(elapsed); RC.physics.update(elapsed);


RC.camera.position.x = RC.player.position.x; RC.camera.position.copy(RC.player.position);
RC.camera.position.z = RC.player.position.z; RC.camera.rotation.copy(RC.player.rotation);
RC.camera.rotation.y = RC.player.rotation.y;
RC.debug(1, " pos: [" + RC.player.position.x.toFixed(2) + "," +
RC.player.position.y.toFixed(2) + "," +
RC.player.position.z.toFixed(2) + "]");
RC.debug(2, " rotation=[" + RC.player.rotation.x.toFixed(2) + "," +
RC.player.rotation.y.toFixed(2) + ", " +
RC.player.rotation.z.toFixed(2) + "]");
RC.debug(3, " momentum=[" + RC.player.momentum.x.toFixed(2) + "," +
RC.player.momentum.y.toFixed(2) + ", " +
RC.player.momentum.z.toFixed(2) + "]");
} }
}; };
31 changes: 24 additions & 7 deletions rcPlayer.js
Expand Up @@ -20,13 +20,35 @@ RC.Player = function() {
this.TURN_SPEED = Math.PI / 2; this.TURN_SPEED = Math.PI / 2;
this.accelState = RC.RacerAccelStateEnum.DRIFT; this.accelState = RC.RacerAccelStateEnum.DRIFT;
this.turnState = RC.RacerTurnStateEnum.NOTURN; this.turnState = RC.RacerTurnStateEnum.NOTURN;
RC.log("making physical with RC.physics=" + RC.physics);
RC.physics.makePhysical(this); RC.physics.makePhysical(this);
RC.physics.addObject(this); RC.physics.addObject(this);
this.rotation.y = Math.PI; this.rotation.y = Math.PI;
this.position.set(0.0, 5.0, RC.END_ZONE_LENGTH); this.position.set(0.0, 1.5, RC.END_ZONE_LENGTH);
this.friction = 0.10; this.friction = 0.10;


this.lastEndZone = RC.TrackEndZoneEnum.NEAR;
this.lapCount = 0;

this.inEndZone = function(obj, cube) {
RC.log("player got end zone trigger (now lap " + obj.lapCount + ")");
RC.physics.resetRotation(obj, cube.resetVector);
if(cube.name === RC.TrackEndZoneEnum.NEAR.name) {
obj.position.z = RC.END_ZONE_LENGTH + 1;
} else if(cube.name === RC.TrackEndZoneEnum.FAR.name) {
obj.position.z = (RC.TRACK_LENGTH + RC.END_ZONE_LENGTH) - 1;
}
if(obj.lastEndZone !== cube) {
obj.lastEndZone = cube;
obj.lapCount++;
if(obj.lapCount >= RC.NLAPS) {
RC.log("player wins!");
// should probably push new EndState("win") here
}
}
};
RC.physics.addHotcubeCallback(RC.TrackEndZoneEnum.NEAR, this, this.inEndZone);
RC.physics.addHotcubeCallback(RC.TrackEndZoneEnum.FAR, this, this.inEndZone);

this.update = function(elapsed) { this.update = function(elapsed) {
// get acceleration and turning states from keyboard // get acceleration and turning states from keyboard
if(RC.keyboard.pressed("up")) { if(RC.keyboard.pressed("up")) {
Expand Down Expand Up @@ -75,10 +97,5 @@ RC.Player = function() {
RC.physics.dampenMomentum(this, this.DRAG_MULTIPLIER); RC.physics.dampenMomentum(this, this.DRAG_MULTIPLIER);
break; break;
} }

// check for end zone flip
//if(RC.track.inEndZone(this.position)) {
// this.rotation.y += Math.PI;
//}
}; };
}; };

0 comments on commit 5c7e061

Please sign in to comment.