Yupoong

Struggling with some things

Recommended Posts

Hello readers and helpers,

I am working quite a lot on my game but I struggle with some things like:

1) 

I spawn my enemies in 5rows from the top to the bottom and they also walk down already. My problem is that they spawn with 5 and go down with 5 at the same time, I want that the enemies spawn at a different time (random time)

The code that I used to spawn 5enemies in a row at the top and let them walk down.

   for (var i =0 ;i < 800 / 40 ;i++) {
        var sprite= game.add.sprite(20 + (i * 170), 32,"enemysheet");
        sprite.scale.setTo(3);
        enemies.add(sprite);
        var walk = sprite.animations.add('walk');
        sprite.animations.play('walk', 20, true);
        sprite.body.velocity.y = 100;
    }

2) 

My second problem is that when 5 enemies are killed that I want to go to a new level where more enemies will come. But how do i do this? (With new states with all my code and changes for the more enemies ?) ---> This doesn't look clean I think

-----------------------------------------------------------------------------------------------------------------------------------------

Thank you for helping in advance guys, I appreciate it.

Share this post


Link to post
Share on other sites

1) Take a bit of time to think about the logic of what you want to achieve:

* Spawn 5 enemies -> create them and position in a row

* Delay starting their march down the screen

You have the first bit taken care of (I'm ignoring the fact you're spawning 20 enemies in your code snippet), you just need to add some delay to when they start walking:

setTimeout(function () {
  sprite.body.velocity.y = 100
}, Math.random() * 1000)

This is probably the simplest way to do it, although you might run in to some issues with what sprite is at the time it gets called, a simple solution is to use a closure to ensure that the reference is what you intend (yes, this touches on closure and no its not the simplest concept in JS, but it is a crucial one):

function spawnEnemy (x) {
  var sprite= game.add.sprite(x, y, 'enemysheet')
  sprite.scale.setTo(3)
  enemies.add(sprite)
  
  sprite.animations.add('walk')
  sprite.animations.play('walk', 20, true)
  
  setTimeout(function () {
    sprite.body.velocity.y = 100
  }, Math.random() * 1000)
}

function spawnEnemies () {
  for (var i =0 ;i < 800 / 40 ;i++) {
    spawnEnemy(20 + (i * 170), 32)
  }
}

Something like this traps `sprite` within the closure of the function and a new closure is created for each function call (I've used your code, which creates 20, spaced out across the x dimension), as the `sprite` variable is trapped in a closure, when the callback we pass to setTimeout is triggered it has access to the sprite object you want.

If you actually want to delay spawning each enemy then simply move the setTimeout code to wrap the spawnEnemy function and set the velocity when you create the sprite.

2) This is more involved depending on exactly what you want to do but somewhere you are destroying each of those sprites (presumably a fired bullet kills them and also when they hit the bottom of the screen) so you just need to keep track and when the required number (5) of deaths has been registered you restart the state, which should (I'm not a Phaser expert) fire your create function again, which likely calls the spawnEnemies function which restarts things.

Try to get a handle on the fact that a function, when called, does something. This thing that it does can be repeated. Whilst that sentence sounds simple you have complexity when you start adding state to the mix, this is where we move in to the realm of pure functions (or idempotency). The problem is that ideally you want you functions to always do the same thing, if your function is pure then it takes inputs, manipulates them and produces an output, it does not touch anything that is not an input, however, with most OOP patterns this isn't a primary concern (it should be, but isn't) so you often end up touching stuff outside of the scope of a function, now you have a problem because you can't be sure on the state of that stuff on the outside so you need to account for it.

This is maybe a bit theoretical, to start with just get the idea that a function is some code that can be run when you want something to happen and that each time you call that function the something happens. In the case here we've created a spawnEnemies function that always creates some sprites and adds them to the game. You can call this function whenever you like and it'll create you some enemies.

Extrapolating this out, whenever you start a new level you call some function, maybe called `init` (or `create`) that initialises the level, this function can either tear down any existing state (if it exists) or maybe you have another function called `destroy` which deletes a level. Either way you have mechanisms for resetting or starting a level so you can watch for certain conditions (all enemies dying) and restart things by calling functions.

Share this post


Link to post
Share on other sites

Ok so first of all thank you for your reply, i try to understand everything you say so i'm gonna ask some things to clear it if that's ok.

1)

I'm gonna write a short code with your code here so i can put it into my code to know if everything is on the right place:

var gameState = {
    
preload: function(){
   
}

create: function(){
    spawnEnemies();       
}

update: function(){

}

function spawnEnemy (x) {
  var sprite= game.add.sprite(x, y, 'enemysheet');
  sprite.scale.setTo(3);
  enemies.add(sprite);
  
  sprite.animations.add('walk');
  sprite.animations.play('walk', 20, true);
  
  setTimeout(function () {
    sprite.body.velocity.y = 100;
  }, Math.random() * 1000);
}

function spawnEnemies () {
  for (var i =0 ;i < 800 / 40 ;i++) {
    spawnEnemy(20 + (i * 170), 32);
  }
}

I think you mean this with your code, i just put your code like this and call it in the create? Also it creates sprites at a random time or how fast will it go?

 

2)

This part is hard to understand, I understand what you mean with your functions so i can make a new state like:

var level1State = {

preload: function(){

},

create: function(){
    spawnEnemies();     
},

update: function(){

},

}

function spawnEnemy (x) {
  var sprite= game.add.sprite(x, y, 'enemysheet')
  sprite.scale.setTo(3)
  enemies.add(sprite)
  
  sprite.animations.add('walk')
  sprite.animations.play('walk', 20, true)
  
  setTimeout(function () {
    sprite.body.velocity.y = 100
  }, Math.random() * 1000)
}

function spawnEnemies () {
  for (var i =0 ;i < 800 / 40 ;i++) {
    spawnEnemy(20 + (i * 170), 32)
  }
}

With the same code, well the changes of the enemies ofcourse? and then run the level1 after my mainmenuState ?

 

I'm a beginner in javascript and phaser so i'm really trying to understand you haha, thanks for the help by the way.

Share this post


Link to post
Share on other sites

1) Yep I think that should work, it requires game to be global, which it sounds like you've done (avoiding globals is usually a good thing but in this case you're in total control of your code so you can keep track of the global game object fairly easily, there are other concerns but you don't need to worry about it yet). The `Math.random() * 1000`  creates a random number between 0 and 1000, you pass this to setTimeout as the delay so you should see all your sprites start moving at random times over a second (1000ms), potentially this could mean they all fire very close to each but thats just how random works, you could get smarter here and stagger it differently, but, well, thats up to you and what you need.

2) I'd have to mock out a quick project to know how Phaser handles states, at a high level you just pass it a load of states (which have lifecycle methods like update and create) and you tell Phaser to run a state right? When you change states you run something like Phaser.State.run('main') or something right? The thing that I would be concerned about is when you tell it to run a state that it is already running, does Phaser just follow your instruction to the letter or does it try to be clever and say 'I'm already in that state so I'm not going to start it again'.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.