【问题标题】:HTML5 game functionHTML5游戏功能
【发布时间】:2016-01-17 22:41:18
【问题描述】:

我正在浏览 HTML5 游戏教程,并遇到了以下功能。谁能解释一下这个函数是如何工作的?

 var super_update = self.update;
    self.update = function(){
            super_update();
            self.attackCounter += self.atkSpd;
    }

我不确定您为什么需要这种类型的函数,逻辑似乎令人困惑。

为什么我们需要一个名为 super_update 的变量?

//------------------------- Full code -------------------//


Player = function(){
        var self = Actor('player','myId',50,40,30,5,20,20,'green',10,1);

        self.updatePosition = function(){
                if(self.pressingRight)
                        self.x += 10;
                if(self.pressingLeft)
                        self.x -= 10;  
                if(self.pressingDown)
                        self.y += 10;  
                if(self.pressingUp)
                        self.y -= 10;  


        var super_update = self.update;
        self.update = function(){
                super_update();
                if(self.hp <= 0){
                        var timeSurvived = Date.now() - timeWhenGameStarted;           
                        console.log("You lost! You survived for " + timeSurvived + " ms.");            
                        startNewGame();
                }
        }

        self.pressingDown = false;
        self.pressingUp = false;
        self.pressingLeft = false;
        self.pressingRight = false;
        return self;

}

Entity = function(type,id,x,y,spdX,spdY,width,height,color){
        var self = {
                type:type,
                id:id,
                x:x,
                y:y,
                spdX:spdX,
                spdY:spdY,
                width:width,
                height:height,
                color:color,
        };
        self.update = function(){
                self.updatePosition();
                self.draw();
        }
        self.draw = function(){
                ctx.save();
                ctx.fillStyle = self.color;
                ctx.fillRect(self.x-self.width/2,self.y-self.height/2,self.width,self.height);
                ctx.restore();
        }
        self.getDistance = function(entity2){   //return distance (number)
                var vx = self.x - entity2.x;
                var vy = self.y - entity2.y;
                return Math.sqrt(vx*vx+vy*vy);
        }

        self.updatePosition = function(){
                self.x += self.spdX;
                self.y += self.spdY;

                if(self.x < 0 || self.x > WIDTH){
                        self.spdX = -self.spdX;
                }
                if(self.y < 0 || self.y > HEIGHT){
                        self.spdY = -self.spdY;
                }
        }

        return self;
}



Actor = function(type,id,x,y,spdX,spdY,width,height,color,hp,atkSpd){
        var self = Entity(type,id,x,y,spdX,spdY,width,height,color);

        self.hp = hp;
        self.atkSpd = atkSpd;
        self.attackCounter = 0;
        self.aimAngle = 0;



        var super_update = self.update; // WHAT IS THIS FOR?
        self.update = function(){
                super_update();
                self.attackCounter += self.atkSpd;
        }


        self.performAttack = function(){
                if(self.attackCounter > 25){    //every 1 sec
                        self.attackCounter = 0;
                        generateBullet(self);
                }
        }



        return self;
}

【问题讨论】:

  • 缺少代码,请问您要解释哪部分代码?
  • 你在这里所拥有的会导致无限递归(正如你发布的那样)。
  • 如果你能给我们更多的代码来看看,这里会更容易解释发生了什么。
  • @JaredSmith 不,它没有。见jsbin

标签: javascript html html5-canvas


【解决方案1】:

首先,您没有链接所有代码。很可能在某处还有这样的一行:

var self = this;
// Stuff...

// Code you posted.

至于它是如何工作的……

链接的sn-p以var super_update = self.update;开头,在JavaScript中可以读作“将对象self的属性update的内容赋值给变量super_update

之所以起作用是因为 JavaScript 是一种面向对象的语言!下一行,self.update = function () { functionbody }; 正在使用给定的函数体创建一个函数对象,并将其分配给对象 self 的属性 update

现在,我确定您会问自己:“说明的顺序不重要吗?”在这种情况下......答案是“是的,但有一些警告”。 undefined/nullnumbers、booleans等原语都是按值传递的;对象和数组由非常类似于引用*的东西传递。由于function对象仍然是对象,它们不是按值传递的,因此每次调用super_update时,self.update的内容as self.update在赋值时已经存在执行。

现在,由于@JaredSmith 在原始问题的 cmets 中指出的原因,这将不起作用:存在无限递归的情况,或者方法调用自身而无法不这样做。您将self.update 分配给super_update,但在super_update 中调用self.update。因此,此代码将锁定它正在执行的页面。 这不是一件好事。我建议在self.update 函数中删除对super_update 的调用。

我确定您没有发布所有代码的另一个原因是,通常这种“分配行为”设置发生在 JavaScript 框架中,例如 three.js 或 angular...大概,不管是哪个那是你在做一个教程。而且,这就是这段代码的重点——将可配置的行为传递给一些预定义的代码,使其以自定义方式运行。

TL;DR: 在 JavaScript 中,函数可以分配给变量/属性并作为参数传递。您可以使用它来使现有代码表现出多态行为。

Super TL;DR:在 JavaScript 中,函数是语言的 first-class citizens

Super-Duper TL;DR:这个 sn-p:

var super_update = self.update;
self.update = function () {};

...就是所谓的闭包;这意味着super_update 被分配了self.update,因为它在分配时存在。 Closures are a useful topic you may want to read more on.(感谢@ankhzet 在这个答案的 cmets 中。)

*:我之所以说“与引用非常相似”,是因为 JavaScript 实际上没有通过引用/指针传递某些东西的概念 - JavaScript 是一种高级语言,因此不处理传递内存地址,确切地。这发生在 JavaScript 引擎内部。

【讨论】:

  • Super-Super TL;DR: self.update = function(){} 行为 ac closure,捕获对 super_update 的引用,无论它将来会怎样。
  • 确实如此,但这似乎是一个新手程序员发这个问题;我不想用闭包的概念给这个显然是 JavaScript 新手的程序员增加负担。他们正在使用它们,但现在我们正在谈论闭包,可能会意识到这一点。 ;)
  • 您好 Andrew,我已上传完整代码以供审核
猜你喜欢
  • 2014-10-02
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-01
  • 2018-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多