Search code examples
javascriptcode.org

Creating a sprite inside of setInterval


Using the setInterval function, I'm trying to create a sprite once every second on code.org using javascript, so my first version of the code looks like

setInterval( function() {
  createSprite(200,200,20,20)
}, 1000)

My problem is that putting setInterval inside of the Draw function causes it to not work properly and a sprite is created every tick after one second has passed, and when the setInterval is not put into function Draw it does not draw the sprite like I want it too.

One solution I have tried is putting the Draw function inside of setInterval but it is not recognized and gives the error message "Draw is defined, but it is not called in your program".

Is there a different version of setInterval that works inside of Draw function, a way to put Draw inside of setInterval successfully, a way to make the sprite show up even though it is outside Draw, or a different way to solve this problem?

Specifically what I'm looking for is to create a sprite once every second, have it show up on screen, be able to choose different velocities for each sprite each time a new one is spawned, and being able to put this function inside of an if function and still have it work as intended.

a piece of code showing something that partially works is shown here:

https://studio.code.org/projects/gamelab/ApXezLpMzV3TfEfHx1CrhFyuteYDSKWe_6Hx0NdJgnc

It works in the regards that it spawns a sprite every second, but if I try to assign one of the sprites that got spawned a velocity, It only works for the first one, as shown here:

https://studio.code.org/projects/gamelab/ApXezLpMzV3TfEfHx1CrhFyuteYDSKWe_6Hx0NdJgnc

the only way I think a solution could be made would be by declaring a class, and then creating a sprite of this class inside the setInterval function, but I do not know exactly how to do this.


Solution

  • See comments:

    // just a helper function to generate random velocities
    function random_in_range(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min }
    
    var monster = createSprite(200,200,20,20);
    monster.velocityX = 5;
    
    setInterval(function() {
      // as you needed to set velocity for a newly created sprite
      // you need to have this sprite as a variable
      var fireball = createSprite(monster.x,monster.y,4,4);
      // now you can set it's velocity
      fireball.velocityX = random_in_range(1,6);
      // basically that's it.
      // as you don't do anything else with a "fireball"
      // you can just forget about it, and you don't need to save it anywhere
    }, 1000);
    
    function draw() {
      background("white");
      createEdgeSprites();
      monster.bounceOff(edges);
      drawSprites();
    }
    

    The link with the working code


    Looking at your original code and your question I think that you may have some basic misconseptions about JS (sorry if I misjudged). Explained them in the comments to your code. I also added some lines to illustrate my points:

    var spawner = createSprite(200,200,20,20);
    var remember_spawner = spawner // ADDED
    // After a new sprite created it does't change 'spawner' variable
    createSprite(150,200,15,15).velocityY = 3; // ADDED
    console.log(remember_spawner === spawner) // ADDED // you see it's the same
    
    // you need to assign the newly created sprite to a variable
    // you can think of this as:
    // I need give them different names so that they can understand to whom am I taking to
    // and if you don't name them they won't listen to you at all
    var spawner2 = createSprite(100,200,10,10);  // ADDED
    spawner2.velocityY = 1  // ADDED // now you cat change velocity of another sprite
    console.log(spawner !== spawner2) // ADDED // and it is another sprite
    
    // var thing_to_be_spawned = createSprite(spawner.x,spawner.y,4,4);
      // You probably don't need this. And you don't use the variable anyway.
      // This sprite created at the same time as the spawner.
      // But if you need it, and you want it to move - change it's velocity (thing_to_be_spawned.velocityX = something) not the velocity of spawner
      // And it would be better if you'll name the function passed to setInterval
      // and call it instead of repeating it. Like so:
      // function fire() { ... } // define the function
      // fire() // call the function
      // setInterval(fire, 1000) // call the function every second
    
    setInterval(function(){
      console.log("This function executed every second") // ADDED
      console.log("Fire!") // ADDED
      createSprite(spawner.x,spawner.y,4,4);
      console.log("Done") // ADDED
    },1000);
    
    console.log("Next line executed only once") // ADDED
    spawner.velocityX=5;
    // The fact that it's placed after setInterval() does mean that
    // it will be executed after call to setInterval()
    // but it doesn't mean that it will be executed after the function passed to setInterval(). Let's call it fire(), shall we?
    // Actually, the fire() function will be called only after all the code in this file
    // And setInterval() is also called only once, only the fire() passed to it called every second
    
    function draw() { // Here you don't call draw() you only define it, so that code.org can call it whenever it wants
      // looking at the code draw function we can't tell when or how often it's called
      // it depends on the implementation details of code.org.
      // We can add console.log to find out
      console.log("Draw called") // ADDED
      background("white");
      createEdgeSprites();
      spawner.bounceOff(edges);
      drawSprites();
    }
    console.log("'fire()' not called yet") // ADDED
    

    Console logs can be seeing in Debug Console of studio.code.org. It opens with a click on Debug Commands. Use it! I mean console.log(). I could also say "use Debug Commands!" but debug is poorly implemented in studio.code.org and can be misleading... You should definitely give it a try, but your trust you should put in console.log().