【问题标题】:"OOP" in canvas correct way画布中的“OOP”正确方式
【发布时间】:2018-09-30 06:02:01
【问题描述】:

我正在尝试使用我们不久前收到的糖代码在画布上绘制一些东西。我当然在使用 babel。我有两个问题。首先你可以在下面找到我的代码:

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

class Rectangle {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    draw() {
        ctx.beginPath();
        ctx.rect(this.x, this.y, 50, 50);
        ctx.fillStyle = "#000";
        ctx.fill();
        ctx.closePath();
    };

    move() {
        document.addEventListener('keydown', event => {
            if (event.keyCode === 37) {
                ctx.clearRect(0, 0, canvas.width, canvas.height)
                this.x--
                this.draw();
            }
            if (event.keyCode === 39) {
                ctx.clearRect(0, 0, canvas.width, canvas.height)
                this.x++
                this.draw();
            }
        })

    }
}


class Ball {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    draw() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, 10, 0, Math.PI*2);
        ctx.fillStyle = "#0095DD";
        ctx.fill();
        ctx.closePath();
    };
}


const rect = new Rectangle(130, 50);
const ball = new Ball(60, 40)

setInterval(() => {
    rect.draw();
    rect.move();
    ball.draw();
}, 100);

我做了两节课。一个是长方形,第二个是球。矩形是可以用箭头移动的。当我移动时,球会消失一秒钟,然后再次出现在屏幕上。在这种情况下我做错了什么?游戏流程应该如何正确显示? 第二个问题是:我怎样才能让这两个类相互交互?例如,我希望当矩形触摸球时,会出现简单的 console.log。谢谢

【问题讨论】:

  • 看看你的move()的实现和你对move()的调用
  • 在间隔函数内移动 clearRect 调用,在移动和绘制之前。我已经用一些 cmets 修改了你的示例,希望对您有所帮助:jsfiddle.net/Ld4mhu8s/1
  • 哎呀,你每 100 毫秒添加一个新的事件监听器......基础知识将在主循环中你做两件事:更新对象然后绘制它们。对于用户交互,他们应该在循环之外更新你的对象,但他们不应该调用任何绘图,你的主循环应该处理它。
  • @KamilStaszewski,因为缺少 itersects 函数的代码。您需要实施它,然后它才能工作。但这是艰苦的努力。建议使用一些现有的库(有很多好的 2D 画布引擎)。仅使用边界矩形来检测交叉点或仅硬编码您需要的交叉点的其他可能解决方案
  • 在实现碰撞检测时,这是一本不错的读物。 wildbunny.co.uk/blog/2011/04/20/collision-detection-for-dummies

标签: javascript canvas ecmascript-6 html5-canvas


【解决方案1】:

大部分代码都是你的。因为我更喜欢使用requestAnimationFrame,所以我为请求添加了一个标识符:let requestId = null;

矩形的move()方法只处理x的值,并将key作为一个属性。

我还编写了 frame 函数,用于逐帧构建动画。

function frame() {
  requestId = window.requestAnimationFrame(frame);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  rect.move(key);
  rect.draw();
  ball.draw();
}

keydown 上更改key 变量的值,取消当前动画,并调用frame 函数开始新动画。

我还添加了一个keyup 事件来停止按键动画。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
let key;
let requestId = null;

class Rectangle {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  draw() {
    ctx.beginPath();
    ctx.rect(this.x, this.y, 50, 50);
    ctx.fillStyle = "#000";
    ctx.fill();
    //ctx.closePath();
  }

  move(key) {
    if (key == 37) {
      this.x--;
    }
    if (key == 39) {
      this.x++;
    }
  }
}

class Ball {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  draw() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, 10, 0, Math.PI * 2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    //ctx.closePath();
  }
}

const rect = new Rectangle(130, 50);
const ball = new Ball(60, 40);

rect.draw();
ball.draw();

function frame() {
  requestId = window.requestAnimationFrame(frame);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  rect.move(key);
  rect.draw();
  ball.draw();
}


document.addEventListener("keydown", event => {
  if (requestId) {
    window.cancelAnimationFrame(requestId);
  }
  key = event.keyCode;
  frame();
});
document.addEventListener("keyup", event => {
  if (requestId) {
    window.cancelAnimationFrame(requestId);
  }
});
canvas{border:1px solid;}
<canvas id="myCanvas"></canvas>

PS:请看这篇文章requestAnimationFrame for Smart Animating

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    • 2020-10-07
    相关资源
    最近更新 更多