Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Space Invaders not moving in unison (Javascript)

Firstly, I'm new to programming and Stackoverflow scares me, but I've tried to contain all the relevant code and to explain my problem well. I have seen many other posts regarding people attempting to make Space Invaders clones and even specifically the "invaders" not moving in unison. However, these posts have not solved my problem and I would be really grateful if someone could point out where I may have gone wrong.

The prototype is available here. Full code here

Code contains comments of me trying to dumb down the code :). I am using the "processing.js" library but this shouldn't hinder anyone from understanding my code.

My specific problem is that the invaders' behaviour when moving on the X axis is not consistent and they do not always move at the same time. At first it seems like everything is fine (minus the very first invader being a bit laggy) but over time the behaviour becomes erratic and they start to move out of line.

I actually understand the flaw in my logic already, but I do not know how to solve it. However, before I explain..

I load the space invaders into a 2d array like so:

var enemies = [];
    for(var i = 0; i < ROWS; i++) {
        var newRow = [];
        for(var y = 0; y < COLS; y++){
            newRow.push(new Enemy(y * 40 + 40, i * 30));
        }
        enemies.push(newRow);
    }

My enemy class is:

   var Enemy = function(x,y) {
        this.height = 30;
        this.width = 30;
        this.x = x;
        this.y = y;
        this.speed = 15;
    };

    Enemy.prototype.draw = function() {
         image(invader, this.x, this.y, this.width, this.height);
    };

They are drawn and moved in the "draw" (basically processing.js's version of "update") loop. Like so:

for(var i = 0; i < enemies.length; i++) {
     var enemy = enemies[i]
     for(var y = 0; y < enemy.length; y++){
         enemy[y].draw();
         enemy[y].move();
         enemy[y].fire();

     }
 }

Then (where the problem most likely is) I handle movement like so:

    Enemy.prototype.move = function(){
    if(nextAlienMove > millis()){
        return; 
    }
    for(var i = 0; i < enemies.length; i++) {
        var enemy = enemies[i]
        for(var y = 0; y < enemy.length; y++){
            var len = enemies[i].length - 1;
            if(enemies[i][len].x >= width - enemies[i][len].width) {
                this.speed = -15;
            } else if(enemies[i][0].x <= 0) {
                this.speed = 15;
            }
            enemy[y].x += this.speed;      


        }
    }
     nextAlienMove = millis() + alienDelay;


};

Now, I believe/know that the problem is I am interating through the arrays and checking the first and last item to monitor the X position. Therefore, there will be some lag between the program changing the direction and with it finding an object that meets the criteria of the if/else statement. (I hope that makes sense).

I have thought of somehow creating a column object with its own independent X and Y axis and to contain the invaders in there. That way I do not need to rely on individual "invaders" triggering the if/else statement's criteria. However, does anyone know another/easier approach or a different gap in my logic?

like image 605
swhizzle Avatar asked Nov 01 '22 04:11

swhizzle


1 Answers

Try something like this — http://codepen.io/sergdenisov/pen/WvxwBE.

var draw = function() {
    background(0);
    player.draw();
    player.fire();

    var isNeedToMove = nextAlienMove <= millis();
    if (isNeedToMove) {
        var speed;
        if (maxX >= width - ENEMY_WIDTH) {
            speed = -15;
            maxX = 0;
        } else if (minX <= 0) {
            speed = 15;
            minX = width;
        }
    }

    for (var i = 0; i < enemies.length; i++) {
        var enemy = enemies[i];
        for (var y = 0; y < enemy.length; y++) {
            if (isNeedToMove) {
                enemy[y].move(speed);
            }
            enemy[y].draw();
            enemy[y].fire();
        }
    }

    if (isNeedToMove) {
        nextAlienMove = millis() + alienDelay;
    }

    ...
}

Enemy.prototype.move = function(speed) {
    if (speed) {
        this.speed = speed;
    }
    this.x += this.speed;
    minX = Math.min(minX, this.x);
    maxX = Math.max(maxX, this.x);
};
like image 156
sergdenisov Avatar answered Nov 09 '22 17:11

sergdenisov