【问题标题】:Canvas simple game DRY refactoringCanvas 简单游戏 DRY 重构
【发布时间】:2015-10-25 01:44:37
【问题描述】:

我是这个网站的日常读者,但不经常是作家。由于我学习 JavaScript 已经有几个星期了,所以我制作了一个基于少量对象的小画布/JS 交叉游戏,我正在努力改进它。游戏非常简单:可以看完整代码并在这里玩:https://jsfiddle.net/vhrqb5xb/1/ 在这里:http://codepen.io/Pggo/pen/NGyQXK

    // The car variable 
    var Car = {}

    // How I create it
    var resetCar = function () {

      Car.x = 300 + (Math.random() * (canvas.width-600));
      Car.y = -10

    };


    // How it's drawn
    function drawCar(){

      ctx.beginPath();
      ctx.rect(Car.x,Car.y,32,32);
      ctx.fillStyle = 'white';
      ctx.fill();
      Car.y += Math.random() * 80

      if (Car.y > canvas.height){
        resetCar();
      };

    }


    // How game is reseit if player touch car
    function drawTouchCar(){

    // Evaluate coordonates of both objects, reset of touch
    if (
      player.x <= (Car.x + 32)
      && Car.x <= (player.x + 10)
      && player.y <= (Car.y + 30) &&
      Car.y <= (player.y + 10)
      ){
    ++numberOfDeaths; // +1 Die
    resetPlayer();
    }
    // if player pass arival line
    if(player.x > (canvas.width - 170 )){
      resetPlayer();
    ++numberOfWins; // +1 Win
    }
    }

现在,我使用的技巧是我有一个快速的车速来渲染它,它看起来好像不止一个,但我的游戏只依赖一个对象,汽车。我希望能够动态添加更多汽车(而不是通过创建自己的 car2 对象)。为了使用原型创建我的对象,我进行了研究和几次尝试,我能够轻松创建更多对象,但我的问题是我无法访问它们的 x 和 y 属性来使用它的碰撞功能。

所以,问题来了,我应该如何处理以实现实际对象汽车的原型,该原型可以动态创建新的汽车对象并返回它们的 x 和 y 属性,以便我可以在我的碰撞函数中重用它。实际上,我只是想了解一下,因为我被卡住了,但我并不是在寻找开箱即用的可行解决方案。

提前感谢您的回复,祝您生活愉快

【问题讨论】:

    标签: javascript canvas html5-canvas prototype


    【解决方案1】:

    创建对象的方法有很多种。每种方法都有其优点和缺点。

    最快的方法是使用对象工厂添加 hoc 以根据需要创建未命名的对象。此方法创建最快的代码。

    var drawCar = function () { // function to draw a car;
        ctx.beginPath();
        // "this" is the car object and should be bound to a car object
        ctx.rect(this.x, this.y, 32, 32);
        ctx.fillStyle = 'red';
        ctx.fill();
        // do your test to see if car is over the line
        // and call
        this.reset(); // to reset the car
    }
    
    var resetCar = function () {
        // car reset function TODO add your reset code
    }
    
    var carFactory = function () { // creates add hoc unnamed car objects
        var car = {}; // create a new object;
        car.x = 0; // give it properties
        car.y = 0;
        // add the reset function to the car and bind it to the new car
        car.reset = resetCar.bind(car);
        car.draw = drawCar.bind(car); // same for draw
        car.reset(); // reset the car ready to go;
        return car; // return the new car
    }
    
    var testCar = function (car) { // function to test if car hits player
        if (
            player.x <= (car.x + 32) // access the car position by its x and y properties
             && car.x <= (player.x + 10)
             && player.y <= (car.y + 30) &&
            car.y <= (player.y + 10)) {
            ++numberOfDeaths; // +1 Die
            resetPlayer();
        }
    }
    
    var car1 = carFactory(); // create a new car
    var car2 = carFactory(); // and another;
    
    var mainLoop() { // called once every frame
        car1.draw();
        car2.draw();
        testCar(car1);
        testCar(car2);
        // TODO the other stuff
    }
    

    接下来是正式的方法,它稍微慢一些,因为引擎盖下发生了更多的事情(可以这么说)

    function Car() {
        // "this" is bound automatic to the car object with the call new Car()
        // the car also is a named type in Javascript
        this.x = 0;
        this.y = 0;
        this.reset(); // reset the new car
    
        // "this" is returned here automatically like in the factory but in this 
        // case you dont have to type it in 
    }
    
    // add draw to the car prototype
    Car.prototype.draw = function () { // function to draw a car;
        ctx.beginPath();
        ctx.rect(this.x, this.y, 32, 32);
        ctx.fillStyle = 'red';
        ctx.fill();
        // this.reset(); // to reset the car
    }
    
    // add reset to the car prototype
    Car.prototype.reset = function () {
        // car reset function TODO add your reset code }
    }
    
    var testCar = function (car) { // function to test if car hits player
        if (
            player.x <= (car.x + 32) // access the car position by its x and y properties
             && car.x <= (player.x + 10)
             && player.y <= (car.y + 30) &&
            car.y <= (player.y + 10)) {
            ++numberOfDeaths; // +1 Die
            resetPlayer();
        }
    }
    var car1 = new Car(); // create a new car
    var car2 = new Car(); // and another;
    
    
    var mainLoop() { // called once every frame
        car1.draw();
        car2.draw();
        testCar(car1);
        testCar(car2);
    }
    

    您还可以使用class 在 ECMAScript 6 中创建汽车。您还可以在 Car 函数中声明所有原型,从而允许您使用闭包来添加隐藏属性。制造新车稍微慢一点,但运行新车稍微快一点..

    如果您想要绝对控制,您可以直接使用 Object 方法,允许您创建具有可写、可枚举、可配置选项的属性,您可以创建 getter 和 setter,您可以冻结对象和更多的整个堆。就我个人而言,我把这些东西留给了大师。

    希望这会有所帮助。

    【讨论】:

    • 完全有帮助,如果你有兴趣看看我在发现你的答案之前想出了什么,这里是一个指向实际版本的链接:codepen.io/Pggo/pen/NGyQXK非常感谢你的时间和有用的回答,在接下来的几个小时里,我会花时间仔细研究这个,但它似乎充满了好主意。
    猜你喜欢
    • 2012-08-30
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 2011-01-17
    • 1970-01-01
    相关资源
    最近更新 更多