1

this might be really obvious, but I'm a complete coding beginner... can somebody tell me why this only executes the function with main(5)? And how could I change it so that main(2) executes after main(1), etc? Thanks!

for (var k = 1; k < 6; k++){
  main(k);
}

edit: sorry, this is the definition of main! I'm trying to animate a bunch of squares using a canvas

var main = function (speed) {
    Enemy.prototype.update = function () {
        var tx = 650 - this.x;
        var ty = 250 - this.y;
        var dist = Math.sqrt(tx * tx + ty * ty);
        this.velx = (tx / dist) * speed;
        this.vely = (ty / dist) * speed;

        if (dist > 0) {
            this.x += this.velx;
            this.y += this.vely;
        }
    };

    Enemy.prototype.isOnEnemy = function (x, y) {
        return (x >= this.x && x < this.x + 25 && // 25 = width
        y >= this.y && y < this.y + 25); // 25 = height
    };

    Enemy.prototype.render = function () {
        context.fillStyle = 'rgba(255,255,255,' + this.transparency + ')';
        context.fillRect(this.x, this.y, 25, 25);
    };

    var enemies = [];
    for (var i = 0; i < 10; i++) {
        // random numbers from 0 (inclusive) to 100 (exclusive) for example:
        var randomX = Math.random() * 896;
        var randomY = Math.random() * 1303;
        console.log(randomX);
        console.log(randomY);
        if (randomX > 100 && randomX < 1200) {
            if (randomX % 2 === 0) {
                randomX = 140;
            } else {
                randomX = 1281;
            }
        }
        if (randomY > 100 && randomY < 75) {
            if (randomY % 2 === 0) {
                randomY = 15;
            } else {
                randomY = 560;
            }
        }
        var enemy = new Enemy(randomX, randomY, 0, 0, 1);
        enemies.push(enemy);
    }
    for (var i = 0; i < 15; i++) {
        // random numbers from 0 (inclusive) to 100 (exclusive) for example:
        var randomX = Math.random() * 200;
        var randomY = Math.random() * 403;
        console.log(randomX);
        console.log(randomY);
        if (randomX > 100 && randomX < 1200) {
            if (randomX % 2 === 0) {
                randomX = 140;
            } else {
                randomX = 1281;
            }
        }
        if (randomY > 100 && randomY < 75) {
            if (randomY % 2 === 0) {
                randomY = 15;
            } else {
                randomY = 560;
            }
        }
        var enemy = new Enemy(randomX, randomY, 0, 0, 1);
        enemies.push(enemy);
    }

    context.canvas.onmousemove = function (e) {
        var rect = this.getBoundingClientRect(),
            x = e.clientX - rect.left,
            y = e.clientY - rect.top,
            i = 0;

        for (; i < enemies.length; i++) {
            if (enemies[i].isOnEnemy(x, y)) {
                enemies[i].transparency = 0;
            }
        }
    };

    function render() {
        context.clearRect(0, 0, canvas.width, canvas.height);
        for (var i = 0; i < enemies.length; i++) {
            var one = enemies[i];
            one.update();
            one.render();
        }
        requestAnimationFrame(render);
    }
    render();
};
6
  • 1
    I think you are doing some async task in main function, can you post the definition of main? Commented Apr 20, 2015 at 3:32
  • 1
    That's a proper loop. It will loop 5 times, and pass 1 - 5 as arguments to main(). Need more information. See: jsfiddle.net/2bpd002o Commented Apr 20, 2015 at 3:35
  • Even if all instructions inside the function main are defered, with that loop, main will be properly called with each values of k. Commented Apr 20, 2015 at 3:39
  • 1
    Enemy.prototype can only retain 1 each of update, isOnEnemy, etc. Each call to main() is redefining these, overriding and discarding any previous definitions, affecting all existing new Enemy() instances. And, the last set of them knows speed to be 5. Commented Apr 20, 2015 at 3:39
  • Thank you! I'm not sure how prototype works :/ Is there a way to do what I want without changing the way I implement the rest of my code? Commented Apr 20, 2015 at 3:44

2 Answers 2

1

The issue is with the definitions for Enemy.prototype.update, etc.

Each call to main() is defining these, but the prototype can only retain 1 of each. So, after the first, each call to main() discards and overrides the previous definitions.

The Enemy.prototype is the object that each new Enemy() inherits from (ref: MDN: Inheritance and the prototype chain). This makes it useful for shared properties and methods that don't change from one instance to another.

Since the speed is the only change, you can likely have the instances keep their own value, allowing the methods to be the same for all of them. Also allowing you define them once outside of main().

Enemy.prototype.update = function () {
    // ...
    this.velx = (tx / dist) * this.speed; // <---
    this.vely = (ty / dist) * this.speed; // <---
    // ...
};

// ...

var main = function (speed) {
    // ...
        var enemy = new Enemy(randomX, randomY, 0, 0, 1);
        enemy.speed = speed; // <---
        enemies.push(enemy);
    // ...
};

If you can modify other code slightly ("without changing the way I implement the rest of my code"), you can modify the constructor to accept and assign the speed:

function Enemy(speed, x, y, ...) {
    this.speed = speed;
    this.x = x;
    this.y = y;
    // ...
}
var enemy = new Enemy(speed, randomX, randomY, 0, 0, 1);
enemies.push(enemy);
Sign up to request clarification or add additional context in comments.

1 Comment

thanks! That actually makes a lot of sense to me; when I change it though, it's still the same problem... did I make a mistake in my code? jsfiddle.net/01hcbd9v
0

You can create a closure in an immediately invoked function to preserve the value that is sent to main...

for (var k = 1; k < 6; k++){
  (function(i) {
    main(i);
  })(k);
}

2 Comments

Sorry, it's still the same problem :/ it's only running once with main(5)
Yeah, I can see that now. check out the comment by @JonathanLonowski above for a better solution...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.