3
\$\begingroup\$

I've been working on a JS/HTML5 Game Engine. Right now I'm calling it DimSumJs, because like DimSum, isn't a full meal, my framework still runs too slowly to make a full game (it can only run about 400 "objects" despite before slowing down, it becomes very noticeable around 500 "objects"). It uses divs inside an iframe.

Any advice is welcome! Please don't tell me to use an already made game engine. This is sort of a project of mine and I want to actually finish it.

Just view resources with Google Chrome and you should be able to find the dimsum.js file

//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;
var GameWindow = window.frames[0];

var gl = setInterval("gameLoop();",15);

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

//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;
}
\$\endgroup\$
  • \$\begingroup\$ Have you tried setting the objects to null once your done using them? \$\endgroup\$ – Guvvy Aba Jan 9 '12 at 11:05
  • \$\begingroup\$ I'm looking for the best way to do so, right now I'm deactivating them, so they just take up memory, but none of their functions are called. Wouldn't setting to null just change the where the reference variable is pointing, or is it different in javascript? \$\endgroup\$ – 汤 若辰 Jan 9 '12 at 12:37
1
\$\begingroup\$

The biggest improvement i could give is getting rid of all the if oftype

replace with :

var enem1 = [];
function enem1Step()
{
    this.anim();    
    if (this.y > MASTER_HEIGHT){
        this.x = random()*(MASTER_WIDTH-64);
        this.y = -128;
        this.speed = 4 + random()*4;
    }
    if (this.objectTypeAt(0,0,"bullet")){
        this.hp--;
    }
    if (this.hp <= 0){
        this.x = random()*(MASTER_WIDTH-64);
        this.y = -128;
        this.speed = 4 + random()*4;
        this.hp = 25;
        return 100;
    }
    return 0;
}
for (var i = 0; i < 50; i++){
    var currentEnem = enem1[i] = new GameObject(random()*(MASTER_WIDTH-64),-random()*MASTER_HEIGHT,16,16,2,8,1,"enem1", "enemyship1.png");
    currentEnem.speed = 4 + random()*4;
    currentEnem.direction = 80 + random()*20;
    currentEnem.hp = 25;
    currentEnem.extend("enem");
    currentEnem.step = enem1Step;
}

etc. (for stars and bullets and enem2)

then

for(var i=0,currentObject = null; currentObject = GameObjects[i]; i++){

    if (currentObject.active ){
        currentObject.update();
        if( currentObject.step)
        {
            score += currentObject.step();
        }
    }

}
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Thanks, I'll try this when I get home from school. I'm glad you took a look at the game's source code, as well as the js file. I guess I implemented my own class wrong! \$\endgroup\$ – 汤 若辰 Jan 9 '12 at 12:39
  • \$\begingroup\$ My isType usage has gone down a huge amount! Thanks! \$\endgroup\$ – 汤 若辰 Jan 12 '12 at 0:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.