javascript - 如何加速我的 Javascript 游戏引擎

标签 javascript html

最近,我一直在研究 JS/HTML5 游戏引擎。现在我称之为 DimSumJs,因为像 DimSum不是一顿完整的饭菜,我的框架仍然运行太慢而无法制作完整的游戏(它只能运行大约 250 个“对象”,尽管在减慢之前,它在 300 个“对象”左右变得非常明显)。它在 iframe 内使用 div。

示例游戏可在 http://pandamochi.x10.bz 获取。

只需使用google chrome查看资源,您应该能够找到dimsum.js文件

//DimSumJS - Open Source Game Engine
//DimSumJS (C) Ruochen Tang
//Can be used commerically, but please give credit
//Constants
var RIGHTKEY = 37;
var UPKEY = 38;
var LEFTKEY = 39;
var DOWNKEY = 40;
var SPACEKEY = 32;
var MASTER_WIDTH = 480;
var MASTER_HEIGHT = 600;

var Game = window.frames[0].document.body;
Game.setAttribute("width",MASTER_WIDTH + "px");
Game.setAttribute("height",MASTER_HEIGHT + "px");
var gl = setInterval("gameLoop();",15);

//Global Vars
var keyDown = new Array();
for (var i = 0; i < 256; i++){
    keyDown[i] = false;
}
var gameState = 1;

//Settings
Game.style.backgroundColor = "#000";

//Key
processKeyEvent = function(event){
        // MSIE hack
        if (window.event)
        {
            event = window.event;
        }

        keyDown[event.keyCode] = true;      
};

releaseKey = function(event){
    // MSIE hack
        if (window.event)
        {
            event = window.event;
        }

    keyDown[event.keyCode] = false;
}
Game.onkeydown = processKeyEvent;
Game.onkeyup = releaseKey;


var GameObjects = new Array();

function GameObject(xx, yy, w, h, i, inc, gs, name, img){

    GameObjects.push(this);

    this.width = w;
    this.height = h;
    this.index = i;
    this.currIndex = 0;
    this.increment = inc;
    this.currInc = 0;
    this.x = xx;
    this.y = yy;
    this.depth = 0;
    this.objType = name;
    this.image = img;
    this.xScale = 1;
    this.yScale = 1;
    this.scaleString = "scale(" + this.xScale + "," + this.yScale + ")";
    this.speed = 0;
    this.direction = 0;
    this.gravity = 0;
    this.gravityDirection = 0;
    this.active = true;
    this.visible = true;
    this.bindToRoom = false;
    this.text = "";
    this.color = "#FFF";
    this.gameState = gs;

    this.div = document.createElement("div");
    this.div.className=this.objType;
    this.div.style.position="absolute";
    this.div.style.left= this.x + "px";
    this.div.style.top= this.y + "px";
    this.div.style.width= this.width + "px";    
    this.div.style.height= this.height + "px";  
    this.div.style.backgroundImage = "url(images/" + this.image + ")";

    this.div.style[getTransformProperty(this.div)] = this.scaleString;

    Game.appendChild(this.div);
    this.isDiv = true;
    this.classChanged = false;

    this.move = move;
    this.anim = anim;
    this.setScale = setScale;
    this.checkCollisionAt = checkCollisionAt;
    this.objectAt = objectAt;
    this.objectTypeAt = objectTypeAt;
    this.toggleActive = toggleActive;
    this.extend = extend;
    this.unextend = unextend;
    this.isType = isType;
    this.update = update;


    function move(xx,yy){
        this.x += xx;
        this.y += yy;
    }

    function anim(){
        this.currInc += 1;
        if (this.currInc >= this.increment){
            this.currInc -= this.increment;
            this.currIndex += 1;
            if (this.currIndex >= this.index){
                this.currIndex -= this.index;
            }

        }

    }
    function extend(type) {
        this.objType += " " + type;
        this.classChanged = true;
    }

    function unextend(type) {
        this.objType = this.objType.replace( /(?:^|\s)type(?!\S)/ , '' );
        this.classChanged = true;
    }

    function isType(type) {
            return ((' ' + this.objType + ' ').indexOf(' ' + type + ' ') > -1);
    }

    function setScale(xx,yy){
        this.xScale = xx;
        this.yScale = yy;
        this.scaleString = "scale(" + this.xScale + "," + this.yScale + ")";    
    }


    function checkCollisionAt(xx,yy,other){
        //Check For Collision
        xx += this.x;
        yy += this.y;

        if ((xx + this.width > other.x) && (xx < other.x + other.width) && (yy + this.height > other.y) && (yy < other.y + other.height)){
            return true;
        }
        else{
            return false;
        }
    }

    function objectAt(xx,yy,solid){
        //Loop All Objects
        for (var i = 0; i < GameObjects.length; i++){
            if (GameObjects[i] != this && this.isDiv){
                if (this.checkCollisionAt(xx,yy,GameObjects[i])){
                    console.log(i);
                    return true;
                }
            }           
        }
        return false;
    }

    function objectTypeAt(xx,yy,type){
        //Loop All Objects
        for (var i = 0; i < GameObjects.length; i++){
            if (GameObjects[i] != this && GameObjects[i].isType(type) && this.isDiv){
                if (this.checkCollisionAt(xx,yy,GameObjects[i])){
                    return true;
                }
            }
        }
        return false;
    }

    function toggleActive(a){
        this.visible = a;
        this.update();
        this.active = a;
    }

    function update(){      
        if ((this.active == false || this.gameState != gameState) && this.isDiv){
            this.isDiv = false;
            Game.removeChild(this.div);
            return;
        }
        else if(!this.isDiv){
            this.isDiv = true;
            Game.appendChild(this.div);
        }

        this.div.style.display = "inline";

        if (this.speed != 0){
            this.x += this.speed*Math.cos(this.direction*Math.PI/180);
            this.y += this.speed*Math.sin(this.direction*Math.PI/180);
        }

        if (this.bindToRoom == true){
            if (this.x < 0){
                this.x = 0;
            }

            if (this.y < 0){
                this.y = 0;
            }

            if (this.x > MASTER_WIDTH-this.width){
                this.x = MASTER_WIDTH-this.width;
            }

            if (this.y > MASTER_HEIGHT-this.height){
                this.y = MASTER_HEIGHT-this.height;
            }
        }

        if (!this.visible && this.isDiv){
            this.isDiv = false;
            Game.removeChild(this.div);
            return;
        }
        if (this.classChanged){
            this.div.className = this.objType;
        }

        this.div.style.zIndex = this.depth;

        this.div.style.color = this.color;
        this.div.innerHTML = this.text;

        this.div.style.left= this.x + "px";
        this.div.style.top= this.y + "px";

        this.div.style[getTransformProperty(this.div)] = this.scaleString;
        this.div.style.backgroundPosition = this.currIndex * this.width +"px 0";


    }
}
function getTransformProperty(element) {

    // Note that in some versions of IE9 it is critical that
    // msTransform appear in this list before MozTransform
    // By ZachAstronaut

    var properties = [
        'transform',
        'WebkitTransform',
        'msTransform',
        'MozTransform',
        'OTransform'
    ];
    var p;
    while (p = properties.shift()) {
        if (typeof element.style[p] != 'undefined') {
            return p;
        }
    }
    return false;
}

现在,每当一个对象不在当前游戏状态、变得不活动或不可见时,我都会从游戏的 iframe 中删除该 div。我进行了检查以确保不在 update() 函数中运行任何不必要的脚本。有什么办法可以提高我的速度吗?

最佳答案

您熟悉分析器吗? Google Chrome其中包括一个相当不错的。当我运行您的程序并开始对其进行分析时,Chrome 报告您对 isType 的定义非常昂贵。

function isType(type) {
    return this.objType && new RegExp("(^|\\s)" + type + "(\\s|$)").test(this.objType);
} 

果然,这个很贵。动态构建正则表达式的成本可能很高。

为了避免这种成本,如果可以的话,请从 isType 中取出正则表达式的定义。假设类型集是固定的,您可以预先计算顶层所有类型的正则表达式,将它们存储在一个对象中,然后进行简单的查找以获取预先计算的正则表达式。如果您事先不知道它们,您仍然可以缓存之前调用 isType 的正则表达式。

var priorTypeRegexps = {};
function isType(type) {
    var aRegexp;
    if (! priorTypeRegexps[type]) {
        priorTypeRegexps[type] = new RegExp("(^|\\s)" + type + "(\\s|$)");
    }
    aRegexp = priorTypeRegexps[type];        
    return this.objType && aRegexp.test(this.objType);
} 

关于javascript - 如何加速我的 Javascript 游戏引擎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8781236/

相关文章:

javascript - 有和/或没有类型的 AWS DynamoDB 数据?

javascript - AngularJS 根据所选项目从 json 中动态填充详细信息

javascript - Bootstrap 4 在单击外部/其他单选按钮时删除折叠

javascript - 有没有一种工具可以在部署时自动缩小 html 文件中引用的所有 javascript 文件?

javascript - 如何防止输入 Ctrl S 时弹出 OS "Save As"对话框

javascript - IE9 无法加载响应式布局

javascript - 如何使 css 列环绕一个切口

javascript - 滚动上的停靠菜单 - 可能需要 JavaScript

html - 如何将按钮向右移动?

javascript - 尝试为数组中的每个项目创建一个新的 json 对象