0

In my simple JavaScript/HTML 5 game I have what I believe is an update error that I don't know how to fix. The thing is there is no real error, its just not responding to the code as how I wanted it to. The problem is, I want a on screen GUI that displays the number of enemies killed on the map. So far I have just that with the GUI there. Here is a picture of the game:

https://i.sstatic.net/0rx4d.png [This shows 3 enemies on the screen, the GUI in the top right corner, and the player.]

Now the problem is whenever I kill an enemy the number should raise, but of course it doesn't. Here is my code:

window.addEventListener("load",function() {

var EKL1 = 0; // Enemies Killed Level 1

var Q = window.Q = Quintus()
        .include("Sprites, Scenes, Input, 2D, Anim, Touch, UI, TMX")
        .setup({ maximize: true })
        .controls().touch()

Q.Sprite.extend("Player",{

  init: function(p){

    this._super(p, {
      sprite: "player",
      sheet: "player",
      speed: 150,

      x: 410,
      y: 90

    });

    this.add('2d, platformerControls, animation');


    },
    step: function(dt){
      if(this.p.vx > 0){
        this.play("walk_right");
        this.p.direction = "right";
      } else if(this.p.vx < 0){
        this.play("walk_left");
        this.p.direction = "left";
      } else {
        this.play("stand_" + this.p.direction);// + this.p.direction > 0 ? "right" : "left");
      }

    }


});

Q.Sprite.extend("Enemy",{
  init: function(p) {
    this._super(p, { 
      sprite: "enemy",
      sheet: "enemy",
      vx: 100 
    });

    // Enemies use the Bounce AI to change direction 
    // whenver they run into something.
    this.add('2d, aiBounce');

    // Listen for a sprite collision, if it's the player,
    // end the game unless the enemy is hit on top
    this.on("bump.left,bump.right,bump.bottom",function(collision) {
      if(collision.obj.isA("Player")) { 
        //Q.stageScene("endGame",1, { label: "You Died" }); 
        collision.obj.destroy();
      }
    });

    // If the enemy gets hit on the top, destroy it
    // and give the user a "hop"
    this.on("bump.top",function(collision) {
      if(collision.obj.isA("Player")) { 
        this.destroy();
          collision.obj.p.vy = -300;
          //Increasing Enemies killed on destroy
          EKL1++;
        }
    });
  }
});

Q.scene("UIContainers", function(stage){
  var container = stage.insert(new Q.UI.Container({
      fill: "gray",
      border: 2,
      shadow: 3,
      shadowColor: "rgba(0,0,0,0.5)",
      y: Q.height/10,
      x: Q.width/1.25
    }));

   stage.insert(new Q.UI.Text({ 
      label: "Enemies killed: " + EKL1.toString(),
      color: "black",
      x: 0,
      y: 0
    }),container);

    container.fit(20,20);
});

Q.scene("level1", function(stage){
  stage.insert(new Q.Repeater({ asset: "background-wall.png", speedX: 0.5, speedY: 0.5 }));
  Q.stageScene("UIContainers", 1);

  stage.collisionLayer(new Q.TileLayer({ dataAsset: 'level.json', sheet: 'tiles' }));


  var player = stage.insert(new Q.Player());

  stage.insert(new Q.Enemy({ x: 700, y: 0 }));
  stage.insert(new Q.Enemy({ x: 800, y: 0 }));
  stage.insert(new Q.Enemy({ x: 500, y: 0 }));

  stage.add("viewport").follow(player);

});

Q.load("sprites.png, sprites.json, enemy.png, enemy.json, level.json, tiles.png, background-wall.png",  function(){
  Q.sheet("tiles","tiles.png", { tilew: 32, tileh: 32 });
  Q.compileSheets("sprites.png", "sprites.json");
  Q.compileSheets("enemy.png", "enemy.json");
  Q.animations("player", {
    walk_right: {frames: [0, 1, 2, 3], rate: 1 / 4, flip: false, loop: true }, 
    walk_left: {frames: [0, 1, 2, 3], rate: 1 / 4, flip:"x", loop: true },
    stand_right: {frames: [0], rate: 1 / 4, flip: false, loop: true},
    stand_left: {frames: [0], rate: 1 / 4, flip: "x", loop: true}


  });

  Q.stageScene("level1");
});




});

The code is of course written in JavaScript but it is run by the Quintus Gaming Engine which can be found here: http://html5quintus.com/

This is how I went about trying to get this to work, so I made a global variable called EKL1 (Enemies killed level 1) which returned/equaled 0. This global variable was accessed in the Enemy function at the bottom where the player to enemy collision takes place. It says if player hits top of enemy, enemy is destroyed. So what I did was I added this: EKL1++ inside the if statement on destroying the enemy. I converted this to a string and ran it to the console and it worked! I killed a enemy and it said 1, killed another then 2, and finally I killed the last one and it displayed 3. Now of course I had to implement this into the GUI on the screen. So what I did was I made a UIContainer function that would hold all my GUI's. I inserted a label onto the container as you can see then put the label text as:

"Enemies killed: " + EKL1.toString();

This converted without the need of a string variable, the integer to a string. I thought this would work, but when I killed a monster it didn't rise. I believe the reason for this is the container is drawn on the screen once, and so it doesn't update. Which means when I kill a monster it won't update the container. I don't know how to implement an update function or something to get this working properly.

If anyone knows the answer to fixing this please respond! I hope this isn't a problem that is to hard to fix.

Thanks for your time,

~Jackson Vandy

2 Answers 2

1

Your String "Enemies killed: " + ELK1.toString() will get evaluated, any changes to ELK after this evaluation to will have no effect on the label. But no worries, there's a solution. Quintus has a storage for 'game states', called Q.state. There's also some event handling, just in case your games state changes. I've added some code below, which should give you a rough direction on where to change your code.

var Q = // ...

// 1. after initialization of Q, create Q.state containing 'enemiesKilled'
Q.state.reset({
  enemiesKilled: 0
});

// ...

// 2. one change in your Enemy Sprite is needed...
Q.Sprite.extend("Enemy",{
  // ...
  this.on("bump.top",function(collision) {
    if(collision.obj.isA("Player")) { 
      this.destroy();
      collision.obj.p.vy = -300;

      // 3. increment your state variable
      Q.state.inc("enemiesKilled");
    }
  });
}

// ...

// 4. extend Q.UI.Text class...
Q.UI.Text.extend("EnemiesKilledLabel", {
  init: function(p) {
    this._super({
      label: "Enemies Killed: 0",
      // ...
    });

    // 5. add a listener for changes on your state...
    Q.state.on("change.enemiesKilled",this,"enemiesKilledChange");
  },

  // 6. ...and the handler
  enemiesKilledChange: function(enemiesKilled) {
    this.p.label = "Enemies Killed: " + enemiesKilled;
  }
};  
// ... etc.

Be aware to always use Q.state.set(...), Q.state.get(...) or convenience methods like Q.state.inc(...), so Quintus can fire the change.<state> event.

Best you have a look at http://html5quintus.com/guide/core.md, section "Game State".

Sign up to request clarification or add additional context in comments.

Comments

1

I am completely unfamiliar with Quintus so I'm not sure if this will work, but I took a look around their site and think I have a solution. Instead of dealing with the ELK string, I would work directly with the UI.Text component. Once you have that, you should be able to update the contained text accordingly.

//1) Add this at the top of your code block, where ELK is now. (In the global space)
var killedLabel = new Q.UI.Text({ 
  label: "Enemies killed: 0",
  color: "black",
  x: 0,
  y: 0
});

//2) When you define your scene, just add the previously created label reference.
stage.insert(killedLabel ,container);

//3) Later on in code....  Update the following code to use the label instead of ELK
//   If the enemy gets hit on the top, destroy it
//   and give the user a "hop"
this.on("bump.top",function(collision) {
  if(collision.obj.isA("Player")) { 
    this.destroy();
      collision.obj.p.vy = -300;
      //Increasing Enemies killed on destroy
      EKL1++;
      //Add this line....
      killedLabel.p.label = "Enemies Killed: " + ELK;
    }
});

I'd also like to add that if I were you, I would use a more robust/popular engine. Something like Construct 2 ( https://www.scirra.com/ ) or Impact.js.

Comments

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.