二维游戏中的相机运动

问题描述 投票:0回答:1

我真的很想知道如何在html和javascript中进行二维摄像头的移动,所以我写了这段代码,它只是一个字符和一个块,这样我就可以测试摄像头的移动是否正常。这是我的代码。

var c = document.getElementById("screen");
var ctx = c.getContext("2d");
var rightPressed;
var leftPressed;
var x = (c.width - 75) / 2;
var speed = 10;

function block() {
  ctx.fillStyle = "#fff";
  ctx.fillRect(390, 225, 80, 25);
}

function character() {
  ctx.fillStyle = "#00f"
  ctx.fillRect(x, 250, 50, 50);
}

function keyUpHandler(event) {
  if (event.keyCode == 37) {
    leftPressed = false;
  } else if (event.keyCode == 39) {
    rightPressed = false;
  }
}

function keyDownHandler(event) {
  if (event.keyCode == 37) {
    leftPressed = true;
  } else if (event.keyCode == 39) {
    rightPressed = true;
  }
}

document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("keydown", keyDownHandler, false);

function draw() {
  ctx.clearRect(0, 0, c.width, c.height);
  block();
  character();

  if (rightPressed && (x + 50) < c.width) {
    x += speed;
  } else if (leftPressed && x > 0) {
    x -= speed;
  }

  requestAnimationFrame(draw);
}

requestAnimationFrame(draw);
#screen {
  display: block;
  margin: auto;
  background-color: #0f0;
  border: 2px solid black;
}

#headline {
  text-align: center;
}
<h1 id="headline">2d Camera movement</h1>
<canvas id="screen" width="500" height="300"></canvas>

有没有人知道如何做到这一点,那么请告诉我,如果你能把它放到这段代码中就更好了:)

javascript html 2d
1个回答
1
投票

我创建了两个类,一个是 Game 和a Ball. 当玩家按下左键或右键时,球会移动。

小球知道自己的位置和速度,游戏不关心。

只要告诉球根据游戏的当前状态更新就可以了。


我从这里改编了一大段代码。

"快速提示:如何在JavaScript中制作游戏循环?"

我添加了ES6类,矢量支持和动态游戏元素支持。


演示

const canvasTxt = window.canvasTxt.default;

const KeyCodeMap = {
  37: 'left',
  38: 'up',
  39: 'right',
  40: 'down',
  65: 'left',
  68: 'right',
  83: 'down',
  87: 'up'
};

Object.assign(canvasTxt, {
  align: 'left',
  vAlign: 'top',
  font: 'monospace',
  fontSize: 24
});

const main = () => {
  Game.DEBUG = true; // Enable global DEBUG mode.

  const ctx = document.getElementById('screen').getContext('2d');
  const game = new Game(ctx);

  game.gameElements.push(...[
    new Ball({
      speed: new Victor(10, 0),
      position: new Victor(game.getWidth() / 2, game.getHeight() / 2),
      color: 'red',
      size: 20
    }),
    new Ball({
      speed: new Victor(20, 0),
      position: new Victor(game.getWidth() / 2, game.getHeight() / 4),
      color: 'green',
      size: 30
    }),
    new Ball({
      speed: new Victor(20, 50),
      position: new Victor(100, 140),
      color: 'cyan',
      size: 25
    }),
  ]);

  game.redraw();
};


class Ball {
  constructor(options) {
    let opts = Object.assign({}, Ball.defaultOptions, options);
    this.position = opts.position;
    this.speed = opts.speed;
    this.size = opts.size;
    this.color = opts.color;
  }
  update(container, state) {
    if (state.pressedKeys.left && !state.pressedKeys.right) {
      this.position.subtract(this.speed);
    }
    if (state.pressedKeys.right && !state.pressedKeys.left) {
      this.position.add(this.speed);
    }
    this.checkBounds(container); // Make sure object is in-bounds...
  }
  checkBounds(container) {
    if (this.position.x > container.width) {
      this.position.x = 0;
    }
    if (this.position.x < 0) {
      this.position.x = container.width;
    }
    if (this.position.y > container.height) {
      this.position.y = 0;
    }
    if (this.position.y < 0) {
      this.position.y = container.height;
    }
  }
  draw(ctx) {
    ctx.save();
    ctx.beginPath();
    ctx.arc(this.position.x, this.position.y, this.size / 2, 0, 2 * Math.PI, false);
    ctx.fillStyle = this.color;
    ctx.fill();
    //ctx.lineWidth = 1;
    //ctx.strokeStyle = '#000000';
    ctx.stroke();
    ctx.restore();
  }
}
Ball.defaultOptions = {
  position: new Victor(0, 0),
  speed: new Victor(0, 0),
  size: 1,
  color: '#FFFFFF'
};

class Game {
  constructor(ctx) {
    this.ctx = ctx;
    this.gameElements = [];
    this.resize();
    this.state = {
      pressedKeys: {} // Capture key pressed
    };
    this.__lastRender = 0;
    this.__animationId = null;

    window.onresize = (e) => this.resize(e);
    document.addEventListener('click', (e) => this.clickHandler(e), false);
    document.addEventListener('keyup', (e) => this.keyUpHandler(e), false);
    document.addEventListener('keydown', (e) => this.keyDownHandler(e), false);
  }

  clickHandler(e) {
    this.isRunning() ? this.pause() : this.run(); // Pause, if running
  }

  keyUpHandler(event) {
    let key = KeyCodeMap[event.keyCode];
    delete this.state.pressedKeys[key];
  }

  keyDownHandler(event) {
    let key = KeyCodeMap[event.keyCode];
    if (key) this.state.pressedKeys[key] = true;
  }

  getWidth() {
    return this.ctx.canvas.width;
  }

  getHeight() {
    return this.ctx.canvas.height;
  }

  resize(event) {
    this.ctx.canvas.width = window.innerWidth * 2
    this.ctx.canvas.height = window.innerHeight * 2
  }

  update(progress) {
    this.gameElements.forEach(gameElement => gameElement.update(this.ctx.canvas, this.state));
  }

  redraw() {
    this.ctx.clearRect(0, 0, this.getWidth(), this.getHeight());
    this.gameElements.forEach(gameElement => gameElement.draw(this.ctx));

    if (Game.DEBUG) {
      this.__renderDebugText(this.ctx);
    }
  }

  /* @private */ __renderDebugText(ctx) {
    ctx.save();
    let text = 'DEBUG OUTPUT:\n\n' + JSON.stringify(Object.assign({
      running: this.isRunning()
    }, this.state), null, 2);
    let offset = { x: 16, y: 16 };
    let bounds = { width: 280,  height: 320 };
    ctx.fillStyle = 'rgba(16, 16, 16, 0.8)';
    ctx.fillRect(offset.x, offset.y, bounds.width, bounds.height);
    ctx.lineWidth = 1;
    ctx.strokeStyle = '#333';
    ctx.strokeRect(offset.x, offset.y, bounds.width, bounds.height);
    ctx.fillStyle = '#FFF';
    canvasTxt.drawText(ctx, text, offset.x + 4, offset.y + 4, bounds.width, bounds.height);
    ctx.restore();
  }

  loop(timestamp) {
    this.update(timestamp - this.__lastRender);
    this.redraw();
    this.__lastRender = timestamp;
    this.__animationId = window.requestAnimationFrame((ts) => this.loop(ts));
  }

  isRunning() {
    return this.__animationId != null;
  }

  run() {
    this.__animationId = window.requestAnimationFrame((ts) => this.loop(ts));
  }

  pause() {
    cancelAnimationFrame(this.__animationId);
    this.__animationId = null;
    this.redraw();
  }
}
Game.DEBUG = false; // Default is off

main();
html,
body {
  margin: 0;
  padding: 0;
}

canvas {
  background: #000;
  height: 100%;
  width: 100%;
  display: block
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/victor/1.1.0/victor.min.js"></script>
<script src="https://unpkg.com/[email protected]/build/index.js"></script>
<canvas id="screen" />
© www.soinside.com 2019 - 2024. All rights reserved.