在 JavaScript 中模拟汽车旋转

我想在我正在设计的游戏中模拟汽车在新方向上的旋转和运动。


根据以下答案,在 HTML5 画布元素中,您不能旋转单个元素。


运动本身发生在此功能中,我希望车辆移动但整个画布移动(尝试按左和右)。我不知道如何旋转汽车。


Game._rotate = function(dirx, direction) {

  this.ctx.translate(200,200);

}

根据本教程,我只能通过旋转画布来旋转汽车本身。我希望旋转和运动来模拟以下内容:https ://oseiskar.github.io/js-car/ 。


代码本身在这里:https ://plnkr.co/edit/K5X8fMhUlRLhdeki 。


MMTTMM
浏览 298回答 1
1回答

Qyouu

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

相关分类

JavaScript