1 回答

TA贡献1786条经验 获得超11个赞
您需要相对于 ITS 位置渲染汽车。此外,您可以在其 RENDER 中进行旋转。
下面的更改将处理汽车的旋转,但您有更大的问题。我会花时间投资学习向量的工作原理。位置、速度和加速度都应该是提供向量数学的二维向量,例如加法和乘法。
此外,为您的汽车提供一个初始角度,以便它最初以正确的方式呈现。您的加速和减速似乎也混淆了。
function Car(map, x, y) {
this.map = map;
this.x = x;
this.y = y;
this.angle = 0; // IMPORTANT
this.width = map.tsize;
this.height = map.tsize;
this.image = Loader.getImage('car');
}
Car.speed = 0;
Car.acceleration = 0;
Car.friction = 5;
Car.moveAngle = 0;
Car.maxSpeed = 500;
Car.forward = 'FORWARD';
Car.backward = 'BACKWARD';
Car.left = 'LEFT';
Car.right = 'RIGHT';
// Render relative to car...
Car.prototype.render = function(ctx) {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
ctx.restore();
};
Game.update = function (delta) {
var dirx = 0;
var diry = 0;
if (Keyboard.isDown(Keyboard.LEFT)) {
this._rotate(dirx, Car.left)
}
else if (Keyboard.isDown(Keyboard.RIGHT)) {
this._rotate(dirx, Car.right)
}
else if (Keyboard.isDown(Keyboard.UP)) {
this._rotate(dirx, Car.up)
diry = accelerate(diry, Car.forward);
}
else if (Keyboard.isDown(Keyboard.DOWN)) {
this._rotate(dirx, Car.down)
diry = accelerate(diry, Car.backward);
}
else {
decelerate();
}
this.car.move(delta, dirx, diry);
this.camera.update();
};
Game._rotate = function(dirx, direction) {
let angleInDegrees = 0;
switch (direction) {
case 'UP':
angleInDegrees = 0;
break;
case 'RIGHT':
angleInDegrees = 90;
break;
case 'DOWN':
angleInDegrees = 180;
break;
case 'LEFT':
angleInDegrees = 270;
break;
}
this.car.angle = angleInDegrees * (Math.PI / 180);
}
Game.render = function () {
// draw map background layer
this._drawLayer(0);
this.car.render(this.ctx);
// draw map top layer
this._drawLayer(1);
};
矢量图
这是一个使用向量的例子。
loadImage('https://i.stack.imgur.com/JY7ai.png')
.then(function(img) {
main(img);
})
function main(img) {
let game = new Game({
canvas: document.querySelector('#viewport')
});
let car = new Car({
img: img,
imgRadiansOffset : -Math.PI / 2,
position: new Victor(game.canvas.width, game.canvas.height).divide(new Victor(2, 2)),
velocity: new Victor(0, -1),
showBorder: true
});
game.addLayer(car);
game.start();
}
class Game {
constructor(options) {
Object.assign(this, Game.defaultOptions, options);
if (this.canvas != null) {
Object.assign(this, {
width: this.canvas.width,
height: this.canvas.height
});
this.addListeners();
}
}
addLayer(layer) {
this.layers.push(layer);
layer.parent = this;
}
start() {
this.id = setInterval(() => {
this.render();
}, 1000 / this.rate); // frames per second
}
render() {
let ctx = this.canvas.getContext('2d');
ctx.clearRect(0, 0, this.width, this.height);
this.layers.forEach(layer => layer.render(ctx));
}
addListeners() {
if (this.canvas != null) {
window.addEventListener('keydown', (e) => {
this.handleKeyDown(e.keyCode);
});
window.addEventListener('keyup', (e) => {
this.handleKeyUp(e.keyCode);
});
}
}
handleKeyDown(keyCode) {
this.layers.forEach(layer => {
layer.update(keyCode !== this.lastKeyCode ? keyCode : null);
});
this.lastKeyCode = keyCode;
}
handleKeyUp(keyCode) {
this.layers.forEach(layer => {
layer.update(this.lastKeyCode); // calls reset...
});
}
}
Game.defaultOptions = {
id: null,
rate: 30,
layers: [],
canvas: null,
width: 0,
height: 0
};
class Car {
constructor(options) {
Object.assign(this, Car.defaultOptions, options);
if (this.img != null) {
Object.assign(this, {
width: this.img.width,
height: this.img.height
});
}
}
render(ctx) {
ctx.save();
ctx.translate(this.position.x, this.position.y);
ctx.rotate(this.velocity.angle() - this.imgRadiansOffset);
ctx.drawImage(this.img, -this.width / 2, -this.height / 2, this.width, this.height);
if (this.showBorder) {
ctx.strokeStyle = '#C00';
ctx.setLineDash([4, 8]);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.rect(-this.width / 2, -this.height / 2, this.width, this.height);
ctx.stroke();
}
ctx.restore();
}
update(keyCode) {
if (keyCode != null) this.changeDirection(keyCode);
this.position.add(this.velocity.add(this.acceleration));
this.detectCollision();
}
detectCollision() {
let xMin = this.width / 2, xMax = this.parent.width - xMin;
let yMin = this.height / 2, yMax = this.parent.height - yMin;
if (this.position.x < xMin) this.position.x = xMin;
if (this.position.x > xMax) this.position.x = xMax;
if (this.position.y < yMin) this.position.y = yMin;
if (this.position.y > yMax) this.position.y = yMax;
}
changeDirection(keyCode) {
switch (keyCode) {
case 37:
this.reset(new Victor(-1, 0)); // LEFT
break;
case 38:
this.reset(new Victor(0, -1)); // UP
break;
case 39:
this.reset(new Victor(1, 0)); // RIGHT
break;
case 40:
this.reset(new Victor(0, 1)); // DOWN
break;
}
}
reset(dirVect) {
this.velocity = new Victor(this.speedFactor, this.speedFactor).multiply(dirVect);
this.acceleration = new Victor(this.accelFactor, this.accelFactor).multiply(dirVect);
}
}
Car.defaultOptions = {
position: new Victor(0, 0),
width: 0,
height: 0,
img: null,
imgRadiansOffset: 0,
velocity: new Victor(0, 0),
acceleration: new Victor(0, 0),
showBorder: false,
speedFactor: 3, // Velocity scalar
accelFactor: 1 // Acceleration scalar
};
function loadImage(url) {
return new Promise(function(resolve, reject) {
var img = new Image;
img.onload = function() {
resolve(this)
};
img.onerror = img.onabort = function() {
reject("Error loading image")
};
img.src = url;
})
}
#viewport {
border: thin solid grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/victor/1.1.0/victor.min.js"></script>
<canvas id="viewport" width="400" height="160"></canvas>
添加回答
举报