Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

refactored play state

refactored end zone detection to generic 3d hotspot in Physics
added debug output DOM element
  • Loading branch information...
commit 5c7e06194059ede0eea3bf9843a5f77bdd7accfd 1 parent a259d69
@stevehb authored
View
20 racecar.html
@@ -3,9 +3,18 @@
<script src="jquery-1.7.1.js"></script>
<script src="Three.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="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">
body {
margin: 0px;
@@ -25,7 +34,7 @@
position: absolute;
}
#game-timer {
- color:#00ff00;
+ color: #ff0000;
display: none;
font-size: 48;
margin: 4px;
@@ -40,6 +49,12 @@
right: 0px;
top: 0px;
}
+ .debug {
+ position: relative;
+ display: inline;
+ font-family: Helvetica,sans-serif;
+ font-size: 12px;
+ }
</style>
</head>
<body onload="init()">
@@ -50,5 +65,6 @@
<img id="img-logo" src="img/logo.png" />
<img id="img-start" src="img/start.png" />
</div>
+ <div class="debug" id="debug"></div>
</body>
</html>
View
28 racecar.js
@@ -23,7 +23,7 @@ function init() {
RC.scene = new THREE.Scene();
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.position.set(0, 10, 0);
+ RC.camera.position.set(0, 1.5, 0);
RC.camera.rotation.y = Math.PI;
RC.scene.add(RC.camera);
RC.renderer = new THREE.WebGLRenderer({ antialias: true, maxLights: RC.NLIGHTS });
@@ -31,23 +31,16 @@ function init() {
RC.renderer.setSize(RC.WIDTH, RC.HEIGHT);
$("#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
RC.physics = new RC.Physics();
RC.stateStack = new Array();
RC.stateStack.push(new RC.TitleState());
+ // set up debug line
+ $(".debug").css({
+ "top": RC.HEIGHT + 10
+ });
+
RC.lastTime = new Date();
RC.update();
}
@@ -71,3 +64,12 @@ RC.update = function() {
RC.log = function(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])
+ };
+}());
View
75 rcPhysics.js
@@ -2,18 +2,19 @@ var RC = RC || {};
RC.Physics = function() {
this.objList = new Array();
- this.hotspots = new Array();
+ this.hotcubeCallbacks = new Array();
this.makePhysical = function(obj) {
obj.momentum = new THREE.Vector3(0, 0, 0);
obj.position = new THREE.Vector3(0, 0, 0);
obj.rotation = 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) {
- RC.log("adding object to physics");
+ //RC.log("adding object to physics");
this.objList.push(obj);
};
@@ -52,38 +53,56 @@ RC.Physics = function() {
obj.momentum.z += -Math.cos(obj.rotation.y) * (magnitude * obj.friction);
};
- this.addHotspot2d = function(rect, callback) {
- this.hotspots.push({
- "rect": rect,
- "callback": callback
- });
+ this.resetRotation = function(obj, rotation) {
+ // reset rotation
+ obj.rotation.y = rotation.y;
+
+ // 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) {
- var objRectPos = new THREE.Rectangle();
$.each(this.objList, function(idx, obj) {
// turn accumulated forces into momentum,
// then turn momentum into movement
- obj.momentum.x += obj.accumForce.x * elapsed;
- obj.momentum.z += obj.accumForce.z * elapsed;
- obj.position.x += obj.momentum.x * elapsed;
- obj.position.z += obj.momentum.z * elapsed;
- obj.accumForce.set(0, 0, 0);
+ if(obj.moveable) {
+ obj.momentum.x += obj.accumForce.x * elapsed;
+ obj.momentum.z += obj.accumForce.z * elapsed;
+ obj.position.x += obj.momentum.x * elapsed;
+ 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
- $.each(RC.physics.hotspots, function(idx, spot) {
- objRectPos.empty();
- objRectPos.addPoint(obj.position.x, obj.position.z);
- 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() + "]");
- }
- });
+ if(pos.x > cube.min.x && pos.x < cube.max.x &&
+ pos.y > cube.min.y && pos.y < cube.max.y &&
+ pos.z > cube.min.z && pos.z < cube.max.z) {
+ callback.func(obj, cube);
+ }
});
};
};
View
28 rcPlayCountdownState.js
@@ -11,7 +11,11 @@ RC.PlayCountdownState = function() {
// set up timer, ready to countdown
var accumTime = 0;
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,
// and fade it out to transparent
@@ -31,26 +35,38 @@ RC.PlayCountdownState = function() {
"background-color": rgbString
});
$("#tmp-cover").show();
- $("#tmp-cover").fadeOut(3000, "linear", function() {
+ $("#tmp-cover").fadeOut(2000, function() {
RC.log("activating count down");
state = RC.PlayStateEnum.COUNTDOWN;
timer.show();
$("#canvas-container").remove("#tmp-cover");
});
- // track & camera
+ // set up track and racers
RC.track = new RC.Track();
- RC.camera.position.set(0, 10, 0);
- RC.camera.rotation.y = Math.PI;
+ RC.player = new RC.Player();
+ 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) {
if(state === RC.PlayStateEnum.COUNTDOWN) {
accumTime += elapsed;
var remaining = this.COUNTDOWN_TIME - accumTime;
if(remaining > 0.0) {
- timer.text(remaining.toFixed(2));
+ timer.text(remaining.toFixed(0));
} else {
timer.text("0.00");
+ timer.animate({
+ "left": 0,
+ "top": 0
+ }, "fast");
RC.log("activating race");
RC.stateStack.pop();
RC.stateStack.push(new RC.PlayRaceState());
View
34 rcPlayRaceState.js
@@ -8,17 +8,18 @@ RC.PlayRaceState = function() {
timer.text("0.00");
RC.track = RC.track || new RC.Track();
-
- RC.camera.position.set(0, 10, 0);
- RC.camera.rotation.y = Math.PI;
-
- RC.player = new RC.Player();
- 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);
+ RC.player = RC.player || new RC.Player();
+ if(RC.racers.length !== RC.NRACERS) {
+ RC.racers.length = RC.NRACERS;
+ 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) {
accumTime += elapsed;
timer.text(accumTime.toFixed(2));
@@ -29,8 +30,17 @@ RC.PlayRaceState = function() {
}
RC.physics.update(elapsed);
- RC.camera.position.x = RC.player.position.x;
- RC.camera.position.z = RC.player.position.z;
- RC.camera.rotation.y = RC.player.rotation.y;
+ RC.camera.position.copy(RC.player.position);
+ RC.camera.rotation.copy(RC.player.rotation);
+
+ 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) + "]");
}
};
View
31 rcPlayer.js
@@ -20,13 +20,35 @@ RC.Player = function() {
this.TURN_SPEED = Math.PI / 2;
this.accelState = RC.RacerAccelStateEnum.DRIFT;
this.turnState = RC.RacerTurnStateEnum.NOTURN;
- RC.log("making physical with RC.physics=" + RC.physics);
RC.physics.makePhysical(this);
RC.physics.addObject(this);
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.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) {
// get acceleration and turning states from keyboard
if(RC.keyboard.pressed("up")) {
@@ -75,10 +97,5 @@ RC.Player = function() {
RC.physics.dampenMomentum(this, this.DRAG_MULTIPLIER);
break;
}
-
- // check for end zone flip
- //if(RC.track.inEndZone(this.position)) {
- // this.rotation.y += Math.PI;
- //}
};
};
View
37 rcTrack.js
@@ -4,13 +4,30 @@ RC.Track = function() {
// create track mesh and add to scene
this.totalLength = RC.TRACK_LENGTH + (RC.END_ZONE_LENGTH * 2);
this.geom = new THREE.PlaneGeometry(RC.TRACK_WIDTH, this.totalLength, 10, 10);
- RC.log("created track with w=" + RC.TRACK_WIDTH + ", l=" + this.totalLength);
+ RC.log("created track geometry: w=" + RC.TRACK_WIDTH + ", l=" + this.totalLength);
this.material = new THREE.MeshLambertMaterial({ color: "0xffffff"});
this.mesh = new THREE.Mesh(this.geom, this.material);
this.mesh.rotation.x = (-Math.PI / 2);
this.mesh.position.z = this.totalLength / 2;
RC.scene.add(this.mesh);
+ // create 'hotcubes'
+ var halfWidth = RC.TRACK_WIDTH / 2;
+ RC.TrackEndZoneEnum = {
+ NEAR : {
+ min : new THREE.Vector3(-halfWidth, 0, 0),
+ max : new THREE.Vector3(halfWidth, 20, RC.END_ZONE_LENGTH),
+ name : "nearEndZone",
+ resetVector : new THREE.Vector3(0, Math.PI, 0)
+ },
+ FAR : {
+ min : new THREE.Vector3(-halfWidth, 0, this.totalLength - RC.END_ZONE_LENGTH),
+ max : new THREE.Vector3(halfWidth, 20, this.totalLength),
+ name : "farEndZone",
+ resetVector : new THREE.Vector3(0, 0, 0)
+ }
+ };
+
// create wireframe blocks and add to scene
var nBlocks = 100;
var i, zOffset, leftGeom, righGeom, leftMesh, rightMesh;
@@ -24,7 +41,11 @@ RC.Track = function() {
rightMesh = new THREE.Mesh(rightGeom, tmpMat);
rightMesh.position.set(RC.TRACK_WIDTH/2 + 10, 10, zOffset);
- // TODO: add to physics for collisions
+ leftMesh.moveable = false;
+ RC.physics.addObject(leftMesh);
+ rightMesh.moveable = false;;
+ RC.physics.addObject(rightMesh);
+
RC.scene.add(leftMesh);
RC.scene.add(rightMesh);
}
@@ -40,16 +61,4 @@ RC.Track = function() {
light.position.set(0, 30, zCoord);
RC.scene.add(light);
}
-
- // add endzones hotspots to physics
- var ezNear = new THREE.Rectangle(), ezFar = new THREE.Rectangle();
- ezNear.set(0, RC.END_ZONE_LENGTH, RC.TRACK_WIDTH, 0);
- ezFar.set(0, this.totalLength, RC.TRACK_WIDTH, this.totalLength - RC.END_ZONE_LENGTH);
- RC.physics.addHotspot2d(ezNear, this.triggerEndZone);
- RC.physics.addHotspot2d(ezFar, this.triggerEndZone);
-
-
- this.triggerEndZone = function(rect, obj) {
- RC.log("obj " + obj + " hit the hotspot [" + rect.getLeft() + "," + rect.getTop() + "," + rect.getRight() + "," + rect.getBottom() + "]");
- };
};
Please sign in to comment.
Something went wrong with that request. Please try again.