javascripthtmldomcraftyjs

Changing text in crafty.js


I have two variables (the enemies and players helath) that change when a certain event happens, the problem is that I dont know how to change text, or remove text, so I cant change the displayed health on the screen (currently I am just placing the new health ontop of the old one). Here is the relevant component.

//player character during combat
//This also controls player input during combat and resolves most of the combat
//Will display and take inputs for quesions eventually
Crafty.c('BattlePlayer', {
init:function() {
var OpPos = 1;
var HealthPas = 100 + ',' + 100;
var FightOver = false;
//Displays options for the first time with attack selected
this.requires('Actor, spr_BattlePlayer, SpriteAnimation, Keyboard')
.bind('KeyDown', function () { if (this.isDown('SPACE')) Crafty.scene('World');})
.bind('KeyDown', function () { if (this.isDown('ENTER')) HealthPas =    this.BattleSelect(OpPos, HealthPas, FightOver);})
.bind('KeyDown', function () { if (this.isDown('S')) if (OpPos < 3){OpPos = OpPos +  1}; this.MenuMove(OpPos); })
.bind('KeyDown', function () { if (this.isDown('W')) if (OpPos > 1) {OpPos = OpPos - 1}; this.MenuMove(OpPos); });


Crafty.e('2D, DOM, Text')
.attr({ x: 200, y: 150 })
.text(100);

Crafty.e('2D, DOM, Text')
.attr({ x: 200, y: 100 })
.text(100);

Crafty.e('AttackSel').at(3,8);
Crafty.e('DefendUnsel').at(3,13);
Crafty.e('RunUnsel').at(3,18);

var MenuPos = 1;    

},
//function for displaying what option is currently selected
MenuMove: function(OpPos) {
switch (OpPos)
{
case 1:
//Attack case
Crafty.e('AttackSel').at(3,8);
Crafty.e('DefendUnsel').at(3,13);
Crafty.e('RunUnsel').at(3,18);
break;

case 2:
//Defend case
Crafty.e('AttackUnsel').at(3,8);
Crafty.e('DefendSel').at(3,13);
Crafty.e('RunUnsel').at(3,18);
break;

case 3:
//Run case
Crafty.e('AttackUnsel').at(3,8);
Crafty.e('DefendUnsel').at(3,13);
Crafty.e('RunSel').at(3,18);
break;

default:
//Incorrect input case
Crafty.e('AttackUnsel').at(3,8);
Crafty.e('DefendUnsel').at(3,13);
Crafty.e('RunUnsel').at(3,18);
}
},

//function for carrying out battle options
//Within this function Num[0] represents players health and Nums[1] represents the Enemy Health.
BattleSelect: function(OpPos, HealthPas, FightOver) {
var Nums = HealthPas.split(',');
Crafty.e('2D, DOM, Text')
.attr({ x: 200, y: 150 })
.text(Nums[0]);

switch (OpPos)
{
case 1:
//Attack case
if (FightOver == false)
{
Nums[1] = Nums[1] - 20;
Crafty.e('2D, DOM, Text')
.attr({ x: 200, y: 100 })
.text(Nums[1]);
Crafty.audio.play('attack');
this.EndCheck(Nums[0], Nums[1], FightOver);
Nums[0] = Nums[0] - 10;
}
break;

case 2:
//Heal case
//as this was originaly a string, minus 1 to change it to an integer
Nums[0] = Nums[0] - 1 + 21;
this.EndCheck(Nums[0], Nums[1], FightOver);
break;

case 3:
//Run case
//switch checks what room the player is in the transport them back there
switch (Location)
{
case 1:
Crafty.scene('World');
break;

case 2:
Crafty.scene('HubWorld');
break;

case 3:
Crafty.scene('Yr10Tp1');
break;

case 3.1:
Crafty.scene('Yr10Tp1_1');
break;

case 3.11:
Crafty.scene('Yr10Tp1_1.1');
break;

case 3.12:
Crafty.scene('Yr10Tp1_1.2');
break;

case 3.2:
Crafty.scene('Yr10Tp1_2');
break;

case 3.3:
Crafty.scene('Yr10Tp1_1.3');
break;

case 4:
Crafty.scene('Yr10Tp2');
break;

case 5:
Crafty.scene('Yr10Tp3');
break;

case 6:
Crafty.scene('Yr11Tp1');
break;

case 7:
Crafty.scene('Yr11Tp2');
break;

case 8:
Crafty.scene('Yr11Tp3');
break;

default:
Crafty.scene('World');
}

default:
this.EndCheck(Nums[0], Nums[1]);
Nums[0] = Nums[0] - 10;
}
HealthPas = Nums[0] + ',' + Nums[1];
return HealthPas;
},

//function to check for winning conditions
EndCheck : function(PlayerHealth, EnemyHealth, FightOver)
{

if (EnemyHealth < 1)
    {
    FightOver = true;
    monsterBeat = true;
    }
else if (PlayerHealth < 1)
    {
    FightOver = true;
    }

if (FightOver == true)
{
Crafty.e('2D, DOM, Text')
.attr({ x: 500, y: 150 })
.text('Victory!');
}
return FightOver;   
},
});

Solution

  • Make sure to look at the documentation for text.

    To set the text directly, you just call the text method of the entity. So whenever the base property changes, you could do this -- either by calling the method directly, or setting up an "UpdateHealth" event.

    So, a text component might look like this:

    Crafty.e('2D, DOM, Text')
      .attr({ x: 200, y: 150 })
      .text(Nums[0]);
      .bind("UpdatePlayerHealth", function(health){this.text(health)});
    

    And then when the player took damage, it would trigger that event with code that looks something like this:

    Crafty.trigger("UpdatePlayerHealth", this.health);
    

    The advantage of using events like this is that you don't need to carry around a reference to the text object, and you could modify other aspects of the game when a player's health changed.

    If you wanted, you could pass more info in the event by using an object, such as:

    Crafty.trigger("UpdatePlayerHealth", {health: this.health, damage: damageValue});
    

    (Although of course you'd also need to adjust the bound function on the text display, since it would be passed an object rather than just a number.)