如何使用javascript创建移动赛道?

问题描述:

我一直在尝试使用JavaScript和画布创建经典赛车游戏。如何使用javascript创建移动赛道?

这是JavaScript部分(car_race.js) 我能够创建一个正在移动的轨道,但它没有那么现实,因为它应该是。现在写出发生的事情是,如果一个边界条完全消失,那么只有它出现在画布的顶部。我想要做的是,当一个边界条从顶部到底部通过完整的画布时,我希望它从顶部恢复,并从画布的底部消失。任何人都可以帮我解决这个问题。

var carRaceTrack = document.getElementById('carraceCanvas'); 
 
var carRaceTrackContext = carRaceTrack.getContext('2d'); 
 
var boundryWidth = 10; 
 
var boundryHeight = 80; 
 
var boundryTopOffSet = 5; 
 
var boundryLeftOffSet = 402; 
 
var boundryPadding = 8; 
 

 
setInterval(draw, 0.5); 
 

 
var leftBoundry = []; 
 
var rightBoundry = []; 
 

 
for (x = 0; x < 6; x++) { 
 
    leftBoundry[x] = { 
 
    OffSet: 0, 
 
    topOffSet: 0, 
 
    width: 0, 
 
    height: 0 
 
    }; 
 
} 
 

 
for (x = 0; x < 6; x++) { 
 
    rightBoundry[x] = { 
 
    OffSet: 0, 
 
    topOffSet: 0, 
 
    width: 0, 
 
    height: 0 
 
    }; 
 
} 
 
var x = 5; 
 

 
function draw() { 
 
    drawCanvas(400, 0, carRaceTrack.width, carRaceTrack.height, 'black'); 
 
    x++; 
 
    if (x > carRaceTrack.height) { 
 
    x = boundryTopOffSet; 
 
    } 
 

 
    //drawBoundryandCanvas(boundryLeftOffSet, x, boundryWidth, boundryHeight, 'white'); 
 
    //drawBoundryandCanvas(boundryLeftOffSet, y, boundryWidth, boundryHeight, 'white'); 
 
    for (i = 0; i < leftBoundry.length; i++) { 
 
    leftBoundry[i].OffSet = boundryLeftOffSet; 
 
    leftBoundry[i].width = boundryWidth; 
 
    leftBoundry[i].height = boundryHeight; 
 
    if (i == 0) { 
 
     leftBoundry[i].topOffSet = x; 
 
    } else { 
 
     leftBoundry[i].topOffSet = leftBoundry[i - 1].topOffSet + boundryHeight + boundryPadding; 
 
    } 
 
    if (leftBoundry[i].topOffSet > carRaceTrack.height) { 
 
     leftBoundry[i].topOffSet = boundryTopOffSet; 
 
    } 
 
    //console.log(boundry[i].topOffSet); 
 
    drawBoundry(leftBoundry[i], 'white'); 
 
    } 
 

 
    for (i = 0; i < rightBoundry.length; i++) { 
 
    rightBoundry[i].OffSet = boundryLeftOffSet - 4 + 440; 
 
    rightBoundry[i].width = boundryWidth; 
 
    rightBoundry[i].height = boundryHeight; 
 
    if (i == 0) { 
 
     rightBoundry[i].topOffSet = x; 
 
    } else { 
 
     rightBoundry[i].topOffSet = rightBoundry[i - 1].topOffSet + boundryHeight + boundryPadding; 
 
    } 
 
    if (rightBoundry[i].topOffSet > carRaceTrack.height) { 
 
     rightBoundry[i].topOffSet = boundryTopOffSet; 
 
    } 
 
    //console.log(boundry[i].topOffSet); 
 
    drawBoundry(rightBoundry[i], 'white'); 
 
    } 
 

 
} 
 

 
function drawBoundry(x, elementColor) { 
 
    carRaceTrackContext.fillStyle = elementColor; 
 
    carRaceTrackContext.fillRect(x.OffSet, x.topOffSet, x.width, x.height); 
 
} 
 

 

 
function drawCanvas(posX, posY, width, height, elementColor) { 
 
    carRaceTrackContext.fillStyle = elementColor; 
 
    carRaceTrackContext.fillRect(posX, posY, width, height); 
 
}
This is the html part. Here i am creating canvas and using car_race.js file i am accessing canvas object. 
 

 
<html> 
 
<canvas id="carraceCanvas" width="850" height="550"></canvas> 
 
<script type="text/javascript" src="car_race.js"></script> 
 

 
</html>

需要双方(8,而不是6)更多的矩形,并允许顶一个具有负Y坐标,所以这是(部分)隐藏。

然后,当您将这些矩形向下移动时,检测您何时移动了一个这样的矩形的距离(加上填充):这意味着您已经可以返回到初始状态并重复。使用requestAnimationFrame而不是setInterval(毫秒数太小)。

这里是你的适应代码(我不能帮助解决拼写错误,使属性名称开始一个微不足道的):

var carRaceTrack = document.getElementById('carraceCanvas'); 
 
var carRaceTrackContext = carRaceTrack.getContext('2d'); 
 
var boundaryWidth = 10; 
 
var boundaryHeight = 80; 
 
var boundaryTopOffset = 5; 
 
var boundaryLeftOffset = 2; // for snippet purpose I reduced this. Original = 402 
 
var boundaryPadding = 8; 
 

 
window.requestAnimationFrame(draw); // better use this for animations 
 

 
var leftBoundary = []; 
 
var rightBoundary = []; 
 

 
for (x = 0; x < 8; x++) { // We need two more 
 
    leftBoundary[x] = { 
 
    offset: boundaryLeftOffset, 
 
    topOffset: 0, 
 
    width: boundaryWidth, 
 
    height: boundaryHeight 
 
    }; 
 
} 
 

 
for (x = 0; x < 8; x++) { 
 
    rightBoundary[x] = { 
 
    offset: boundaryLeftOffset - 4 + 440, 
 
    topOffset: 0, 
 
    width: boundaryWidth, 
 
    height: boundaryHeight 
 
    }; 
 
} 
 
var cycle = 0, 
 
    totalCycle = boundaryHeight + boundaryPadding; 
 

 
function draw() { 
 
    drawCanvas(boundaryLeftOffset-2, 0, carRaceTrack.width, carRaceTrack.height, 'black'); 
 
    // Use modulo operator for resetting to 0 when cycle is complete: 
 
    cycle = (cycle + 1) % totalCycle; 
 
    // Avoid code repetition: loop over the two boundary arrays: 
 
    for (boundary of [leftBoundary, rightBoundary]) { 
 
     for (i = 0; i < boundary.length; i++) { 
 
      // Note that we put the first one at a negative coordinate! 
 
      boundary[i].topOffset = cycle + (i-1) * totalCycle; 
 
      drawBoundary(boundary[i], 'white'); 
 
     } 
 
    } 
 
    // Repeat 
 
    window.requestAnimationFrame(draw); 
 
} 
 

 
function drawBoundary(x, elementColor) { 
 
    carRaceTrackContext.fillStyle = elementColor; 
 
    carRaceTrackContext.fillRect(x.offset, x.topOffset, x.width, x.height); 
 
} 
 

 

 
function drawCanvas(posX, posY, width, height, elementColor) { 
 
    carRaceTrackContext.fillStyle = elementColor; 
 
    carRaceTrackContext.fillRect(posX, posY, width, height); 
 
}
<canvas id="carraceCanvas" width="450" height="550"></canvas>

注意,我适应左偏移量,所以它更适合这个片段。

+0

@Kaiido,最后一个确实很快就消失了。将数量从7增加到8来解决这个问题。我将离开'setInterval',因为OP对此毫无疑问。如果一个像素的移动速度如此之慢,那么使用'window.requestAnimationFrame()'并不能真正增加好处。 – trincot

+0

啊是的,我完全忽略了小数。替换为'window.requestAnimationFrame()',这是更好的选择。感谢您强调这一点! – trincot

+0

感谢帮助trincot –