I made a post today, asking how to know which part of my js is laggy.
I got answered and did performance tests with the Firefox built-in tool and then the performance.now()
function. The results are correct : less than 2ms for the draw()
function executed every 10ms.
So now I'm wondering, if the draw()
function is executed normally and does not provide lag, why do cars not move in a fluid way ?
Here's my complete code :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>car trafic</title>
<style>
*{
margin: 0;
position: absolute;
}
#background{
z-index: 1;
}
#cars{
z-index: 2;
}
</style>
</head>
<body>
<p id='debug'></p>
<canvas id="background"></canvas>
<canvas id="cars"></canvas>
<script type="text/javascript">
// BACKGROUND CANVAS -------------------------------------------
var background = document.getElementById("background");
background.height=window.innerHeight;
background.width=window.innerWidth;
var bkg=background.getContext("2d");
//--------------------------------------------------------------
// ANIMATED CANVAS ------------------------------------------------
var anim = document.getElementById("cars");
anim.height=window.innerHeight;
anim.width=window.innerWidth;
var anm=anim.getContext("2d");
// -------------------------------------------------------------
// VARIABLES ------------------------------------------
var width = anim.width;
var height = anim.height;
var numCars = 10;
var numRoads = 7;
if(width/numRoads/2<height/numRoads/2){
var roadWidth = ~~(width/numRoads/2);
} else {
var roadWidth = ~~(height/numRoads/2);
}
var klaxon = new Audio('res/sounds/klaxon.wav');
//------------------------------------------------------------------
// CROSSROAD LIST -----------------------------------
var roads = [];
for(i=0;i<numRoads+2;i++){
for(j=0;j<numRoads+2;j++){
var create = getRandomInt(3);
if(create>0){
roads.push([~~(width/(numRoads+1)*j),~~(height/(numRoads+1)*i),1])
} else {
roads.push([~~(width/(numRoads+1)*j),~~(height/(numRoads+1)*i),0])
}
}
}
// ------------------------------------------------------------
// TURN LIST -----------------------------------------
var turns = [];
var roadLength = roads.length;
for(i=0;i<roadLength;i++){
var road = roads[i];
if(road[2]==1){
if(i>numRoads+1 && (i+1)%(numRoads+2)!=0 && (i)%(numRoads+2)!=0 && i<roadLength-(numRoads+2)){
var rightbot = [~~(road[0]+roadWidth/4),~~(road[1]+roadWidth/4),0,0,0,0];
var righttop = [~~(road[0]+roadWidth/4),~~(road[1]-roadWidth/4),0,0,0,0];
var leftbot = [~~(road[0]-roadWidth/4),~~(road[1]+roadWidth/4),0,0,0,0];
var lefttop = [~~(road[0]-roadWidth/4),~~(road[1]-roadWidth/4),0,0,0,0];
if(roads[i+1][2]==1){
var right = true;
rightbot[3] = 1;
leftbot[3] = 1;
lefttop[4] = 1;
leftbot[3] = 1;
rightbot[2] = 1;
righttop[5] = 1;
}
if(roads[i-1][2]==1){
var left = true;
righttop[5] = 1;
lefttop[5] = 1;
lefttop[4] = 1;
leftbot[3] = 1;
rightbot[2] = 1;
righttop[5] = 1;
}
if(roads[i+(numRoads+2)][2]==1){
var bot = true;
lefttop[4] = 1;
leftbot[4] = 1;
lefttop[4] = 1;
leftbot[3] = 1;
rightbot[2] = 1;
righttop[5] = 1;
}
if(roads[i-(numRoads+2)][2]==1){
var top = true;
rightbot[2] = 1;
righttop[2] = 1;
lefttop[4] = 1;
leftbot[3] = 1;
rightbot[2] = 1;
righttop[5] = 1;
}
turns.push(rightbot,righttop,leftbot,lefttop);
}
}
}
//----------------------------------------------------------------------------------
// SPAWNPOINT LIST --------------------------------------------------
var spawnPoints = [];
for(i=1;i<roadLength;i++){
if(i!=(numRoads+1) && i!=(roadLength) && i!=(roadLength-1) && i!=(roadLength-(numRoads+2))){
var road = roads[i];
if(road[2]==1){
if(i<numRoads+1 && roads[i+numRoads+2][2]==1){
var spawnPoint = [~~(road[0]-roadWidth/4),~~(road[1]),"bot"];
spawnPoints.push(spawnPoint);
} else if(((i+1)%(numRoads+2))==0 && roads[i-1][2]==1){
var spawnPoint = [~~(road[0]),~~(road[1]-roadWidth/4),"left"];
spawnPoints.push(spawnPoint);
} else if(i>=(numRoads+2)){
if(i>roadLength-(numRoads+2) && roads[i-(numRoads+2)][2]==1){
var spawnPoint = [~~(road[0]+roadWidth/4),~~(road[1]),"top"];
spawnPoints.push(spawnPoint);
} else if(i<roadLength){
if((i)%(numRoads+2)==0 && roads[i+1][2]==1){
var spawnPoint = [~~(road[0]),~~(road[1]+roadWidth/4),"right"];
spawnPoints.push(spawnPoint);
}
}
}
}
}
}
//---------------------------------------------------------------------------
// BACKGROUND GEN ------------------------------------------------------
bkg.beginPath();
bkg.fillStyle = 'green';
bkg.rect(0,0,width,height);
bkg.fill();
for(i=0;i<roadLength;i++){
var road = roads[i];
if(road[2]==1){
if(i>numRoads+1 && (i+1)%(numRoads+2)!=0 && i<roadLength-(numRoads+2)){
if(roads[i+1][2]==1){
bkg.beginPath();
bkg.fillStyle = 'grey';
bkg.rect(road[0]-roadWidth/2,road[1]-roadWidth/2,roads[i+1][0]-road[0]+roadWidth,roadWidth);
bkg.fill();
}
}
if((i+1)%(numRoads+2)!=0 && i<roadLength-(numRoads+2) && (i)%(numRoads+2)!=0){
if(roads[i+numRoads+2][2]==1){
bkg.beginPath();
bkg.fillStyle = 'grey';
bkg.rect(road[0]-roadWidth/2,road[1]-roadWidth/2,roadWidth,roads[i+numRoads+2][1]-road[1]+roadWidth);
bkg.fill();
}
}
}
}
for(i=0;i<roadLength;i++){
var road = roads[i];
if(road[2]==1){
if(i>numRoads+1 && (i+1)%(numRoads+2)!=0 && i<roadLength-(numRoads+2)){
if(roads[i+1][2]==1){
bkg.beginPath();
bkg.setLineDash([5, 3]);
bkg.strokeStyle = 'white';
bkg.moveTo(road[0],road[1]);
bkg.lineTo(roads[i+1][0],roads[i+1][1]);
bkg.stroke();
bkg.fill();
}
}
if((i+1)%(numRoads+2)!=0 && i<roadLength-(numRoads+2) && (i)%(numRoads+2)!=0){
if(roads[i+numRoads+2][2]==1){
bkg.beginPath();
bkg.setLineDash([5, 3]);
bkg.strokeStyle = 'white';
bkg.moveTo(road[0],road[1]);
bkg.lineTo(roads[i+numRoads+2][0],roads[i+numRoads+2][1]);
bkg.stroke();
bkg.fill();
}
}
}
}
//-----------------------------------------------------------------------------------------
// CAR CLASS ---------------------------------------------------------------------------
function Car(){
this.size = ~~(roadWidth/4);
var rand = getRandomInt(spawnPoints.length);
try {
var initDir = spawnPoints[rand][2];
} catch {
location.reload();
}
this.x = spawnPoints[rand][0];
this.y = spawnPoints[rand][1];
switch(initDir){
case "right":
this.dir = 0;
break;
case "bot":
this.dir = (Math.PI)/2;
break;
case "top":
this.dir = -(Math.PI)/2;
break;
case "left":
this.dir = (Math.PI);
break;
}
this.timer = 0;
this.speedRand = 2+Math.random();
this.dx = Math.cos(this.dir)*(2+this.speedRand);
this.dy = Math.sin(this.dir)*(2+this.speedRand);
this.col = "red";
//this.col = '#'+(~~(Math.random()*16777215).toString(16);
}
// -----------------------------------------------------------------------------------------
// CAR LIST INIT ---------------------------------------------------------------
var cars = [];
for(i = 0 ; i < numCars ; i++){
var car = new Car();
cars.push(car);
}
//-----------------------------------------------------------------------------------------
var backRect = document.getElementById("background");
var intervalTurns = roadWidth/15;
var turnsLength = turns.length;
// DRAW UPDATE ----------------------------------------------------------------------------
function draw(){
// if(getRandomInt(50)==1){
// var car = new Car();
// cars.push(car);
// }
anm.globalAlpha = 0.1;
anm.drawImage(backRect,0,0);
anm.globalAlpha = 1;
var carsLength = cars.length;
for(i = 0; i < cars.length ; i++){
var car = cars[i];
anm.fillStyle=car.col;
anm.beginPath();
car.x = ~~(car.x+car.dx);
car.y = ~~(car.y+car.dy);
anm.rect(~~(car.x-car.size/2), ~~(car.y-car.size/2), car.size, car.size);
anm.fill();
if(car.timer==0){
for(j=0;j<turnsLength;j++){
var turn = turns[j];
if(car.x<turn[0]+intervalTurns && car.x>turn[0]-intervalTurns && car.y<turn[1]+intervalTurns && car.y>turn[1]-intervalTurns){
var possibleTurns = [];
for(i=2;i<turnsLength;i++){
if(turn[i]==1){
possibleTurns.push(i);
}
}
var change = getRandomInt(possibleTurns.length);
var newDir = possibleTurns[change];
switch(newDir){
case 2:
car.dir = -(Math.PI)/2;
car.dx = Math.cos(car.dir)*(2+car.speedRand);
car.dy = Math.sin(car.dir)*(2+car.speedRand);
break;
case 5:
car.dir = Math.PI;
car.dx = Math.cos(car.dir)*(2+car.speedRand);
car.dy = Math.sin(car.dir)*(2+car.speedRand);
break;
case 4:
car.dir = (Math.PI)/2;
car.dx = Math.cos(car.dir)*(2+car.speedRand);
car.dy = Math.sin(car.dir)*(2+car.speedRand);
break;
case 3:
car.dir = 0;
car.dx = Math.cos(car.dir)*(2+car.speedRand);
car.dy = Math.sin(car.dir)*(2+car.speedRand);
break;
}
car.timer = 3;
break;
}
}
} else if(car.timer > 0){
car.timer-=1;
}
if(car.x<0 || car.x>width || car.y<0 || car.y>height){
var rand = getRandomInt(spawnPoints.length);
try {
var initDir = spawnPoints[rand][2];
} catch {
location.reload();
}
car.x = spawnPoints[rand][0];
car.y = spawnPoints[rand][1];
//cars.splice(i,1);
switch(initDir){
case "right":
car.dir = 0;
car.dx = Math.cos(car.dir)*(2+car.speedRand);
car.dy = Math.sin(car.dir)*(2+car.speedRand);
break;
case "bot":
car.dir = (Math.PI)/2;
car.dx = Math.cos(car.dir)*(2+car.speedRand);
car.dy = Math.sin(car.dir)*(2+car.speedRand);
break;
case "top":
car.dir = -(Math.PI)/2;
car.dx = Math.cos(car.dir)*(2+car.speedRand);
car.dy = Math.sin(car.dir)*(2+car.speedRand);
break;
case "left":
car.dir = (Math.PI);
car.dx = Math.cos(car.dir)*(2+car.speedRand);
car.dy = Math.sin(car.dir)*(2+car.speedRand);
break;
}
}
}
}
//---------------------------------------------------------------------------------------
setInterval(draw, 10);
// KEYBINDS ------------------------------------------------------------------------
document.body.onkeyup = function(e){
if(e.keyCode == 32){
klaxon.play();
}
}
//-------------------------------------------------------------------------------
function getRandomInt(max) {
return ~~(Math.random() * max);
}
</script>
</body>
</html>
I tried to floor every position of every object so it would be easier to display for the browser but it didn't change anything.
I know my code isn't really readable, so if you have an question or anything ask me, I'll be happy to answer you.
Thanks and have a good day :)