Created
January 1, 2012 01:08
-
-
Save richtaur/1545853 to your computer and use it in GitHub Desktop.
Racing simulation sent in by one of the listeners of our HTML5 game dev podcast
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Car Racer</title> | |
<meta charset="utf-8"> | |
<script type="text/javascript" src="js/jquery-1.7.1.min.js"></script> | |
<script type="text/javascript"> | |
$(document).ready(function() { | |
var then = Date.now(); | |
function init() { | |
setInterval(main, 20); | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* CANVAS | |
*/ | |
function canvas() | |
{ | |
// *** Private vars | |
var canvas = document.getElementById("race-track"); | |
var ctx = canvas.getContext("2d"); | |
var canvasWidth = ctx.canvas.clientWidth; | |
var canvasHeight = ctx.canvas.clientHeight; | |
// *** Add public pointer | |
this.getCtx = getCtx; | |
this.getCanvasWidth = getCanvasWidth; | |
this.getCanvasHeight = getCanvasHeight; | |
// *** Private -> public | |
function getCtx () { | |
return ctx; | |
} | |
// *** Private -> public | |
function getCanvasWidth () { | |
return canvasWidth; | |
} | |
// *** Private -> public | |
function getCanvasHeight () { | |
return canvasHeight; | |
} | |
// *** Public | |
this.clear = function() { | |
ctx.clearRect(0, 0, canvasWidth, canvasHeight); | |
} | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* MAIN | |
*/ | |
function main() | |
{ | |
var now = Date.now(); | |
var fps = 1000 / (now - then); | |
update(); | |
render(fps); | |
then = now; | |
}; | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* RENDER | |
*/ | |
function update(modifier) | |
{ | |
// *** Calculatge the cars new x,y pos | |
car1.calcPos(modifier); | |
// *** Get the current tile the car is on | |
currentTileArray = car1.getTile(trackObj.tileWidth(), trackObj.tileHeight()); | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* DRAW | |
*/ | |
function render(fps) | |
{ | |
// *** Clear canvas | |
canvas.clear(); | |
// *** Draw/render map | |
renderMap(trackObj); | |
// *** Draw the car | |
car1.drawCar(ctx); | |
// *** Draw the car | |
hud(ctx, fps); | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* Draw Map | |
*/ | |
function renderMap(mapObj) | |
{ | |
var rgt = mapObj.data(); | |
for (matrixY in rgt) { | |
for (matrixX in rgt[matrixY]) { | |
var matrixArray = rgt[matrixY][matrixX].split(','); | |
var x = matrixArray[1]; | |
var y = matrixArray[0]; | |
var sx = (x-1) * mapObj.tileWidth(); | |
var sy = (y-1) * mapObj.tileHeight(); | |
var dx = (matrixX) * mapObj.tileWidth(); | |
var dy = (matrixY) * mapObj.tileHeight(); | |
ctx.drawImage(mapObj.mapTilesImg(), sx, sy, mapObj.tileWidth(), mapObj.tileHeight(), dx, dy, mapObj.tileWidth(), mapObj.tileHeight()); | |
} | |
} | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* Cars | |
*/ | |
function car(x, y, degrees, carObj) | |
{ | |
var MAX_TORQUE = carObj.max_torque; //(cause the car to spin out if value is reached (see IF statement below)) //1 | |
var MAX_ACCEL = carObj.max_speed; // px. per frame. squared (maximum speed) //1 | |
var TURN_RADIUS = carObj.turn_radius; // px (The smaller this number is, the sharper the turn the car will make.) | |
var DRAG = carObj.drag; // ratio (the larger the value, the faster the car loses speed) | |
var spinDrag = 0.2; | |
// *** Initialise | |
var xPos = x; | |
var yPos = y; | |
var _turn = 0; // 1, 0, -1 | |
var _accel = 0; // 1, 0, -1 | |
var _rotation = degrees; | |
var xVel = 0; // px. per frame (point) | |
var yVel = 0; | |
var heading = degrees; // radians | |
var spin = 0; // radians per frame | |
var spinImpact = 0; | |
// *** Car image | |
var carImage = new Image(); // Create new img element | |
carImage.src = carObj.image; // Set source path | |
var rightKey = false; | |
var leftKey = false; | |
var upKey = false; | |
var downKey = false; | |
this.drawCar = function(ctx) { | |
// *** Draw car (find center) | |
var transX = xPos-(carImage.width/2); | |
var transY = yPos-(carImage.height/2); | |
ctx.save(); | |
ctx.translate(transX, transY); | |
// *** Rotate car | |
ctx.rotate(heading); | |
ctx.translate(-xPos, -yPos); | |
ctx.drawImage(carImage, transX, transY); | |
ctx.restore(); | |
} | |
this.calcPos = function() { | |
// *** Add drag. Slows car down when not accelerating (also reduces spin) | |
xVel *= (1 - DRAG); | |
yVel *= (1 - DRAG); | |
spinImpact *= spinDrag; | |
if ( Math.abs(spinImpact) <= 1 ) { | |
spinImpact = 0; | |
} | |
// *** Direction | |
heading = (_rotation * Math.PI / 180); | |
// *** Add acceleration | |
xVel += MAX_ACCEL * _accel * Math.sin(heading) //* modifier; | |
yVel -= MAX_ACCEL * _accel * Math.cos(heading) //* modifier; | |
var velMag = Math.sqrt(xVel * xVel + yVel * yVel); | |
spin = velMag / TURN_RADIUS * _turn; // something like (_turn * 3) is good for simulating oil slip | |
/* calculate torque (turning the car changes the direction it travels). | |
* "First we calculate how much the velocity will change to get the car moving in the direction | |
* it is pointed. I'm calling this value torque" | |
*/ | |
var torqueX = 0; | |
var torqueY = 0; | |
var newHeading = heading + spin + spinImpact; | |
torqueX = Math.sin(newHeading) * velMag - xVel; | |
torqueY = -Math.cos(newHeading) * velMag - yVel; | |
var torqueMag = Math.sqrt(Math.pow(torqueX,2) + Math.pow(torqueY,2)); | |
// *** Limit torque, so the car will "spin out" if turning too fast | |
if (torqueMag > MAX_TORQUE) { | |
torqueX = MAX_TORQUE * torqueX / torqueMag; | |
torqueY = MAX_TORQUE * torqueY / torqueMag; | |
} | |
// *** Apply torque to velocity | |
xVel += torqueX; | |
yVel += torqueY; | |
// *** Set the new position and values | |
xPos += xVel; | |
yPos += yVel; | |
heading = newHeading; | |
_rotation = heading * 180 / Math.PI; | |
} | |
// *** Setters and getters | |
this.forwardOn = function (value) { _accel = 1; } | |
this.forwardOff = function (value) { _accel = 0; } | |
this.reverseOn = function (value) { _accel = -1; } | |
this.reverseOff = function (value) { _accel = 0; } | |
this.rightTurnOn = function (value) { _turn = 1 } | |
this.rightTurnOff = function (value) { _turn = 0 } | |
this.leftTurnOn = function (value) { _turn = -1; } | |
this.leftTurnOff = function (value) { _turn = 0; } | |
this.setX = function (x) { xPos = x; } | |
this.setY = function (y) { yPos = y; } | |
this.setDirection = function (degreesx) { direction = degreesx; } | |
this.setSpeed = function (speed) { speed = speed; } | |
this.getX = function () { return xPos; } | |
this.getY = function () { return yPos; } | |
this.getDirection = function () { return direction; } | |
this.getSpeed = function () { return speed; } | |
this.getTile = function (tileWidth, tileHeight) { | |
var tileX = Math.ceil(xPos / tileWidth); | |
var tileY = Math.ceil(yPos / tileHeight); | |
} | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* Draw HUD | |
*/ | |
function hud(ctx, fps) | |
{ | |
ctx.fillStyle = "rgb(250, 250, 250)"; | |
ctx.font = "24px Helvetica"; | |
ctx.textAlign = "left"; | |
ctx.textBaseline = "top"; | |
ctx.fillText("FPS: " + fps, 32, 32); | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* Keys | |
*/ | |
function onKeyDown(evt) | |
{ | |
switch (evt.keyCode) { | |
case 38: // Up arrow | |
car1.forwardOn(); | |
break; | |
case 40: // Down arrow | |
car1.reverseOn(); | |
break; | |
case 37: // Left arrow | |
car1.leftTurnOn(); | |
break; | |
case 39: // Right arrow | |
car1.rightTurnOn(); | |
break; | |
} | |
} | |
function onKeyUp(evt) | |
{ | |
switch (evt.keyCode) { | |
case 38: // Up arrow | |
car1.forwardOff(); | |
break; | |
case 40: // Down arrow | |
car1.reverseOff(); | |
break; | |
case 37: // Left arrow | |
car1.leftTurnOff(); | |
break; | |
case 39: // Right arrow | |
car1.rightTurnOff(); | |
break; | |
} | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* MAPS | |
*/ | |
var track1 = { | |
tileset: "images/tileset-g-100.jpg", | |
tileWidth: 128, | |
tileHeight: 128, | |
startTile: '3,1', | |
startFacing: 'n', | |
rgt: [ ['2,1', '1,2', '4,4', '1,2', '4,2', '2,2'], | |
['4,3', '5,4', '7,1', '7,1', '13,4', '4,1'], | |
['3,4', '7,1', '7,3', '7,1', '2,1', '6,2'], | |
['1,1', '15,1', '7,1', '7,2', '4,1', '7,1'], | |
['6,1', '1,2', '4,2', '1,4', '6,2', '7,1'] | |
], | |
trackMarkers: ['1,1', '1,6', '3,6', '4,5', '5,5', '5,1'] | |
} | |
function track(track) // CAN PROBABLY REMOVE THIS AND METHOD setStartPos CAN BE PART OF RENDER MAP. | |
{ | |
var mapTilesImg = new Image(); | |
mapTilesImg.src = track.tileset; | |
this.mapTilesImg = function() { | |
return mapTilesImg; | |
} | |
this.tileset = function() { | |
return track.tileset; | |
} | |
this.tileWidth = function() { | |
return track.tileWidth; | |
} | |
this.tileHeight = function() { | |
return track.tileHeight; | |
} | |
this.data = function() { | |
return track.rgt; | |
} | |
this.trackMarkers = function() { | |
return track.trackMarkers; | |
} | |
this.setStartPos = function() | |
{ | |
var startTileArray = track.startTile.split(','); | |
var startTileX = startTileArray[1]; | |
var startTileY = startTileArray[0]; | |
var startX = (startTileX * track.tileWidth) - (track.tileWidth/2); | |
var startY = (startTileY * track.tileHeight) - (track.tileHeight/2) | |
var rotation = 0; | |
switch (track.startFacing) { | |
case 'n': | |
startY += 50; | |
rotation = 0; | |
break; | |
case 's': | |
startY -= (50 - 34); // 34 is the length of the car | |
rotation = 180; | |
break; | |
case 'w': | |
startX += 50; | |
rotation = 270; | |
break; | |
case 'e': | |
startX -= (50 - 20); | |
rotation = 90; | |
break; | |
} | |
// *** Stored as x,y | |
return posArray = [startX, startY, rotation]; | |
} | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* CARS | |
*/ | |
var car1 = { | |
image: "images/carred.png", | |
max_speed: 0.5, | |
max_torque: 0.4, | |
turn_radius: 100, | |
drag: 0.05 | |
} | |
var car2 = { | |
image: "images/carred.png", | |
max_speed: 0.4, | |
max_torque: 0.5, | |
turn_radius: 90, | |
drag: 0.05 | |
} | |
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* | |
* RUN | |
*/ | |
// *** Create the canvas object | |
var canvas = new canvas(); | |
// *** Get the canvas | |
var ctx = canvas.getCtx(); | |
// *** Clear canvas | |
canvas.clear(); | |
// *** Create map object | |
var trackObj = new track(track1); | |
x = trackObj.setStartPos()[0]; | |
y = trackObj.setStartPos()[1]; | |
direction = trackObj.setStartPos()[2]; | |
// *** Create car object | |
car1 = new car(x, y, direction, car1); | |
// *** Run | |
init(); | |
// *** Bind keys | |
$(document).keydown(onKeyDown); | |
$(document).keyup(onKeyUp); | |
}); | |
</script> | |
</head> | |
<body> | |
<canvas id="race-track" width="768" height="640" style="border:1px solid black;"></canvas> | |
</body> | |
</html> |
this does not work
It does not work
didnt work :(
Yes, empty field showing up. too bad
hi
HI
It ain't work
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
can i get tileset-g-100.jpg and carred.png ?