1
\$\begingroup\$

I'm new in game development Phaser.. I'm trying out a code tutorial for a clicker game I browsed from Zenva and did a few adjustments with the images (along with the codes) but I can't help to notice that the monsters' images are all showing up and compiled to each other at the center of the canvas, while in the tutorial I saw, it should be one monster and each time you kill it by clicking, a different monster shows up.

enter image description here

var game = new Phaser.Game(800, 600, Phaser.AUTO, '');

game.state.add('play', {
preload: function() {
    this.game.load.image("preloadBackground","assets/misc/BackgroundPreload.png");

    this.game.load.image("amphisbaena", "assets/monsters/Amphisbaena.png");
    this.game.load.image("baba_yaga", "assets/monsters/Baba Yaga.png");
    this.game.load.image("banshee", "assets/monsters/Banshee.png");
    this.game.load.image("centaur", "assets/monsters/Centaur.png");
    this.game.load.image("cerberus", "assets/monsters/Cerberus.png");
    this.game.load.image("chimera", "assets/monsters/Chimera.png");
    this.game.load.image("chinese_dragon", "assets/monsters/Chinese Dragon.png");
    this.game.load.image("chupacabra", "assets/monsters/Chupacabra.png");
    this.game.load.image("european_dragon", "assets/monsters/European Dragon.png");
    this.game.load.image("frost_giant", "assets/monsters/Frost Giant.png");
    this.game.load.image("gargoyle", "assets/monsters/Gargoyle.png");
    this.game.load.image("griffin", "assets/monsters/Griffin.png");
    this.game.load.image("harpy", "assets/monsters/Harpy.png");
    this.game.load.image("hydra", "assets/monsters/Hydra.png");
    this.game.load.image("ifrit", "assets/monsters/Ifrit.png");
    this.game.load.image("krakken", "assets/monsters/Krakken.png");
    this.game.load.image("medusa", "assets/monsters/Medusa.png");
    this.game.load.image("mermaid", "assets/monsters/Mermaid.png");
    this.game.load.image("minotaur", "assets/monsters/Minotaur.png");
    this.game.load.image("santelmo", "assets/monsters/Santelmo.png");
    this.game.load.image("slime", "assets/monsters/Slime.png");
    this.game.load.image("sphinx", "assets/monsters/Sphinx.png");
    this.game.load.image("twrch_tryth", "assets/monsters/Twrch Tryth.png");
    this.game.load.image("wyvern", "assets/monsters/Wyvern.png");

    this.game.load.image('gold_coin', 'assets/misc/coin.png');
    this.game.load.image('health_img', 'assets/misc/Monster Health.png');

    this.game.load.image('dagger', 'assets/496_RPG_icons/W_Dagger002.png');
    this.game.load.image('swordIcon1', 'assets/496_RPG_icons/S_Sword15.png');


},
create: function() {
    var state = this;

    var background = this.game.add.image(game.world.X, game.world.Y, 'preloadBackground');
    var gcLogo = this.game.add.image(44, 28, 'gold_coin');
    var mon_healthLogo = this.game.add.image(28, 474, 'health_img');

    });

    var monsterData = [
        {name: 'Amphisbaena',       image: 'amphisbaena',       maxHealth: 5},
        {name: 'Baba Yaga',         image: 'baba_yaga',         maxHealth: 10},
        {name: 'Banshee',           image: 'banshee',           maxHealth: 10},
        {name: 'Centaur',           image: 'centaur',           maxHealth: 10},
        {name: 'Cerberus',          image: 'cerberus',          maxHealth: 10},
        {name: 'Chimera',           image: 'chimera',           maxHealth: 25},
        {name: 'Chinese Dragon',    image: 'chinese_dragon',    maxHealth: 40},
        {name: 'Chupacabra',        image: 'chupacabra',        maxHealth: 5},
        {name: 'European Dragon',   image: 'european_dragon',   maxHealth: 40},
        {name: 'Frost Giant',       image: 'frost_giant',       maxHealth: 30},
        {name: 'Gargoyle',          image: 'gargoyle',          maxHealth: 20},
        {name: 'Griffin',           image: 'griffin',           maxHealth: 20},
        {name: 'Harpy',             image: 'harpy',             maxHealth: 15},
        {name: 'Hydra',             image: 'hydra',             maxHealth: 20},
        {name: 'Ifrit',             image: 'ifrit',             maxHealth: 50},
        {name: 'Krakken',           image: 'krakken',           maxHealth: 40},
        {name: 'Medusa',            image: 'medusa',            maxHealth: 35},
        {name: 'Mermaid',           image: 'mermaid',           maxHealth: 15},
        {name: 'Minotaur',          image: 'minotaur',          maxHealth: 30},
        {name: 'Santelmo',          image: 'santelmo',          maxHealth: 5},
        {name: 'Slime',             image: 'slime',             maxHealth: 5},
        {name: 'Sphinx',            image: 'sphinx',            maxHealth: 15},
        {name: 'Twrch Tryth',       image: 'twrch_tryth',       maxHealth: 15},
        {name: 'Wyvern',            image: 'wyvern',            maxHealth: 20}
    ];
    this.monsters = this.game.add.group();

    var monster;
    monsterData.forEach(function(data) {
        // create a sprite for them off screen
        monster = state.monsters.create(state.game.world.centerX, state.game.world.centerY, data.image);
        // use the built in health component
        monster.health = monster.maxHealth = data.maxHealth;
        // center anchor
        monster.anchor.setTo(0.5);
        // reference to the database
        monster.details = data;

        //enable input so we can click it!
        monster.inputEnabled = true;
        monster.events.onInputDown.add(state.onClickMonster, state);

        // hook into health and lifecycle events
        monster.events.onKilled.add(state.onKilledMonster, state);
        monster.events.onRevived.add(state.onRevivedMonster, state);
    });

    // display the monster front and center
    this.currentMonster = this.monsters.getRandom();
    this.currentMonster.position.set(this.game.world.centerX, this.game.world.centerY);

    this.monsterInfoUI = this.game.add.group();
    this.monsterInfoUI.position.setTo(this.currentMonster.x - 240, this.currentMonster.y + 180);
    this.monsterNameText = this.monsterInfoUI.addChild(this.game.add.text(0, 0, this.currentMonster.details.name, {
        font: '38px Arial Black',
        fill: '#fff',
        strokeThickness: 4
    }));
    this.monsterHealthText = this.monsterInfoUI.addChild(this.game.add.text(0, 50, this.currentMonster.health + ' HP', {
        font: '32px Arial Black',
        fill: '#ff0000',
        strokeThickness: 4
    }));


onDPS: function() {
    if (this.player.dps > 0) {
        if (this.currentMonster && this.currentMonster.alive) {
            var dmg = this.player.dps / 10;
            this.currentMonster.damage(dmg);
            // update the health text
            this.monsterHealthText.text = this.currentMonster.alive ? Math.round(this.currentMonster.health) + ' HP' : 'DEAD';
        }
    }
},
onKilledMonster: function(monster) {
    // move the monster off screen again
    monster.position.set(this.game.world.centerX, this.game.world.centerY);

    var coin;
    // spawn a coin on the ground
    coin = this.coins.getFirstExists(false);
    coin.reset(this.game.world.centerX + this.game.rnd.integerInRange(-100, 100), this.game.world.centerY + 75);
    coin.goldValue = Math.round(this.level * 1.33);
    this.game.time.events.add(Phaser.Timer.SECOND * 3, this.onClickCoin, this, coin);

    this.levelKills++;

    if (this.levelKills >= this.levelKillsRequired) {
        this.level++;
        this.levelKills = 0;
    }

    this.levelText.text = 'Level: ' + this.level;
    this.levelKillsText.text = 'Kills: ' + this.levelKills + '/' + this.levelKillsRequired;

    // pick a new monster
    this.currentMonster = this.monsters.getRandom();
    // upgrade the monster based on level
    this.currentMonster.maxHealth = Math.ceil(this.currentMonster.details.maxHealth + ((this.level - 1) * 10.6));
    // make sure they are fully healed
    this.currentMonster.revive(this.currentMonster.maxHealth);
},
onRevivedMonster: function(monster) {
    monster.position.set(this.game.world.centerX, this.game.world.centerY);
    // update the text display
    this.monsterNameText.text = monster.details.name;
    this.monsterHealthText.text = monster.health + 'HP';
},
onClickMonster: function(monster, pointer) {
    // apply click damage to monster
    this.currentMonster.damage(this.player.clickDmg);

    // grab a damage text from the pool to display what happened
    var dmgText = this.dmgTextPool.getFirstExists(false);
    if (dmgText) {
        dmgText.text = this.player.clickDmg;
        dmgText.reset(pointer.positionDown.x, pointer.positionDown.y);
        dmgText.alpha = 1;
        dmgText.tween.start();
    }

    // update the health text
    this.monsterHealthText.text = this.currentMonster.alive ? this.currentMonster.health + ' HP' : 'DEAD';
}
});

game.state.start('play');

I removed a few codes to save space and to make it less confusing, the codes preload, create and update functions to run the game are shown at the bottom, here's the original code where I got it from:

enter image description here

var game = new Phaser.Game(800, 600, Phaser.AUTO, '');

game.state.add('play', {
    preload: function() {
        this.game.load.image('forest-back', 'assets/parallax_forest_pack/layers/parallax-forest-back-trees.png');
        this.game.load.image('forest-lights', 'assets/parallax_forest_pack/layers/parallax-forest-lights.png');
        this.game.load.image('forest-middle', 'assets/parallax_forest_pack/layers/parallax-forest-middle-trees.png');
        this.game.load.image('forest-front', 'assets/parallax_forest_pack/layers/parallax-forest-front-trees.png');

        this.game.load.image('aerocephal', 'assets/allacrost_enemy_sprites/aerocephal.png');
        this.game.load.image('arcana_drake', 'assets/allacrost_enemy_sprites/arcana_drake.png');
        this.game.load.image('aurum-drakueli', 'assets/allacrost_enemy_sprites/aurum-drakueli.png');
        this.game.load.image('bat', 'assets/allacrost_enemy_sprites/bat.png');
        this.game.load.image('daemarbora', 'assets/allacrost_enemy_sprites/daemarbora.png');
        this.game.load.image('deceleon', 'assets/allacrost_enemy_sprites/deceleon.png');
        this.game.load.image('demonic_essence', 'assets/allacrost_enemy_sprites/demonic_essence.png');
        this.game.load.image('dune_crawler', 'assets/allacrost_enemy_sprites/dune_crawler.png');
        this.game.load.image('green_slime', 'assets/allacrost_enemy_sprites/green_slime.png');
        this.game.load.image('nagaruda', 'assets/allacrost_enemy_sprites/nagaruda.png');
        this.game.load.image('rat', 'assets/allacrost_enemy_sprites/rat.png');
        this.game.load.image('scorpion', 'assets/allacrost_enemy_sprites/scorpion.png');
        this.game.load.image('skeleton', 'assets/allacrost_enemy_sprites/skeleton.png');
        this.game.load.image('snake', 'assets/allacrost_enemy_sprites/snake.png');
        this.game.load.image('spider', 'assets/allacrost_enemy_sprites/spider.png');
        this.game.load.image('stygian_lizard', 'assets/allacrost_enemy_sprites/stygian_lizard.png');

        this.game.load.image('gold_coin', 'assets/496_RPG_icons/I_GoldCoin.png');

        this.game.load.image('dagger', 'assets/496_RPG_icons/W_Dagger002.png');
        this.game.load.image('swordIcon1', 'assets/496_RPG_icons/S_Sword15.png');

        // build panel for upgrades
        var bmd = this.game.add.bitmapData(250, 500);
        bmd.ctx.fillStyle = '#9a783d';
        bmd.ctx.strokeStyle = '#35371c';
        bmd.ctx.lineWidth = 12;
        bmd.ctx.fillRect(0, 0, 250, 500);
        bmd.ctx.strokeRect(0, 0, 250, 500);
        this.game.cache.addBitmapData('upgradePanel', bmd);

        var buttonImage = this.game.add.bitmapData(476, 48);
        buttonImage.ctx.fillStyle = '#e6dec7';
        buttonImage.ctx.strokeStyle = '#35371c';
        buttonImage.ctx.lineWidth = 4;
        buttonImage.ctx.fillRect(0, 0, 225, 48);
        buttonImage.ctx.strokeRect(0, 0, 225, 48);
        this.game.cache.addBitmapData('button', buttonImage);

        // the main player
        this.player = {
            clickDmg: 1,
            gold: 50,
            dps: 0
        };

        // world progression
        this.level = 1;
        // how many monsters have we killed during this level
        this.levelKills = 0;
        // how many monsters are required to advance a level
        this.levelKillsRequired = 10;
    },
    create: function() {
        var state = this;

        this.background = this.game.add.group();
        // setup each of our background layers to take the full screen
        ['forest-back', 'forest-lights', 'forest-middle', 'forest-front']
            .forEach(function(image) {
                var bg = state.game.add.tileSprite(0, 0, state.game.world.width,
                    state.game.world.height, image, '', state.background);
                bg.tileScale.setTo(4,4);
            });

        this.upgradePanel = this.game.add.image(10, 70, this.game.cache.getBitmapData('upgradePanel'));
        var upgradeButtons = this.upgradePanel.addChild(this.game.add.group());
        upgradeButtons.position.setTo(8, 8);

        var upgradeButtonsData = [
            {icon: 'dagger', name: 'Attack', level: 0, cost: 5, purchaseHandler: function(button, player) {
                player.clickDmg += 1;
            }},
            {icon: 'swordIcon1', name: 'Auto-Attack', level: 0, cost: 25, purchaseHandler: function(button, player) {
                player.dps += 5;
            }}
        ];

        var button;
        upgradeButtonsData.forEach(function(buttonData, index) {
            button = state.game.add.button(0, (50 * index), state.game.cache.getBitmapData('button'));
            button.icon = button.addChild(state.game.add.image(6, 6, buttonData.icon));
            button.text = button.addChild(state.game.add.text(42, 6, buttonData.name + ': ' + buttonData.level, {font: '16px Arial Black'}));
            button.details = buttonData;
            button.costText = button.addChild(state.game.add.text(42, 24, 'Cost: ' + buttonData.cost, {font: '16px Arial Black'}));
            button.events.onInputDown.add(state.onUpgradeButtonClick, state);

            upgradeButtons.addChild(button);
        });

        var monsterData = [
            {name: 'Aerocephal',        image: 'aerocephal',        maxHealth: 10},
            {name: 'Arcana Drake',      image: 'arcana_drake',      maxHealth: 20},
            {name: 'Aurum Drakueli',    image: 'aurum-drakueli',    maxHealth: 30},
            {name: 'Bat',               image: 'bat',               maxHealth: 5},
            {name: 'Daemarbora',        image: 'daemarbora',        maxHealth: 10},
            {name: 'Deceleon',          image: 'deceleon',          maxHealth: 10},
            {name: 'Demonic Essence',   image: 'demonic_essence',   maxHealth: 15},
            {name: 'Dune Crawler',      image: 'dune_crawler',      maxHealth: 8},
            {name: 'Green Slime',       image: 'green_slime',       maxHealth: 3},
            {name: 'Nagaruda',          image: 'nagaruda',          maxHealth: 13},
            {name: 'Rat',               image: 'rat',               maxHealth: 2},
            {name: 'Scorpion',          image: 'scorpion',          maxHealth: 2},
            {name: 'Skeleton',          image: 'skeleton',          maxHealth: 6},
            {name: 'Snake',             image: 'snake',             maxHealth: 4},
            {name: 'Spider',            image: 'spider',            maxHealth: 4},
            {name: 'Stygian Lizard',    image: 'stygian_lizard',    maxHealth: 20}
        ];
        this.monsters = this.game.add.group();

        var monster;
        monsterData.forEach(function(data) {
            // create a sprite for them off screen
            monster = state.monsters.create(1000, state.game.world.centerY, data.image);
            // use the built in health component
            monster.health = monster.maxHealth = data.maxHealth;
            // center anchor
            monster.anchor.setTo(0.5, 1);
            // reference to the database
            monster.details = data;

            //enable input so we can click it!
            monster.inputEnabled = true;
            monster.events.onInputDown.add(state.onClickMonster, state);

            // hook into health and lifecycle events
            monster.events.onKilled.add(state.onKilledMonster, state);
            monster.events.onRevived.add(state.onRevivedMonster, state);
        });

        // display the monster front and center
        this.currentMonster = this.monsters.getRandom();
        this.currentMonster.position.set(this.game.world.centerX + 100, this.game.world.centerY + 50);

        this.monsterInfoUI = this.game.add.group();
        this.monsterInfoUI.position.setTo(this.currentMonster.x - 220, this.currentMonster.y + 120);
        this.monsterNameText = this.monsterInfoUI.addChild(this.game.add.text(0, 0, this.currentMonster.details.name, {
            font: '48px Arial Black',
            fill: '#fff',
            strokeThickness: 4
        }));
        this.monsterHealthText = this.monsterInfoUI.addChild(this.game.add.text(0, 80, this.currentMonster.health + ' HP', {
            font: '32px Arial Black',
            fill: '#ff0000',
            strokeThickness: 4
        }));

        this.dmgTextPool = this.add.group();
        var dmgText;
        for (var d=0; d<50; d++) {
            dmgText = this.add.text(0, 0, '1', {
                font: '64px Arial Black',
                fill: '#fff',
                strokeThickness: 4
            });
            // start out not existing, so we don't draw it yet
            dmgText.exists = false;
            dmgText.tween = game.add.tween(dmgText)
                .to({
                    alpha: 0,
                    y: 100,
                    x: this.game.rnd.integerInRange(100, 700)
                }, 1000, Phaser.Easing.Cubic.Out);

            dmgText.tween.onComplete.add(function(text, tween) {
                text.kill();
            });
            this.dmgTextPool.add(dmgText);
        }

        // create a pool of gold coins
        this.coins = this.add.group();
        this.coins.createMultiple(50, 'gold_coin', '', false);
        this.coins.setAll('inputEnabled', true);
        this.coins.setAll('goldValue', 1);
        this.coins.callAll('events.onInputDown.add', 'events.onInputDown', this.onClickCoin, this);

        this.playerGoldText = this.add.text(30, 30, 'Gold: ' + this.player.gold, {
            font: '24px Arial Black',
            fill: '#fff',
            strokeThickness: 4
        });

        // 100ms 10x a second
        this.dpsTimer = this.game.time.events.loop(100, this.onDPS, this);

        // setup the world progression display
        this.levelUI = this.game.add.group();
        this.levelUI.position.setTo(this.game.world.centerX, 30);
        this.levelText = this.levelUI.addChild(this.game.add.text(0, 0, 'Level: ' + this.level, {
            font: '24px Arial Black',
            fill: '#fff',
            strokeThickness: 4
        }));
        this.levelKillsText = this.levelUI.addChild(this.game.add.text(0, 30, 'Kills: ' + this.levelKills + '/' + this.levelKillsRequired, {
            font: '24px Arial Black',
            fill: '#fff',
            strokeThickness: 4
        }));
    },
    onDPS: function() {
        if (this.player.dps > 0) {
            if (this.currentMonster && this.currentMonster.alive) {
                var dmg = this.player.dps / 10;
                this.currentMonster.damage(dmg);
                // update the health text
                this.monsterHealthText.text = this.currentMonster.alive ? Math.round(this.currentMonster.health) + ' HP' : 'DEAD';
            }
        }
    },
    onUpgradeButtonClick: function(button, pointer) {
        // make this a function so that it updates after we buy
        function getAdjustedCost() {
            return Math.ceil(button.details.cost + (button.details.level * 1.46));
        }

        if (this.player.gold - getAdjustedCost() >= 0) {
            this.player.gold -= getAdjustedCost();
            this.playerGoldText.text = 'Gold: ' + this.player.gold;
            button.details.level++;
            button.text.text = button.details.name + ': ' + button.details.level;
            button.costText.text = 'Cost: ' + getAdjustedCost();
            button.details.purchaseHandler.call(this, button, this.player);
        }
    },
    onClickCoin: function(coin) {
        if (!coin.alive) {
            return;
        }
        // give the player gold
        this.player.gold += coin.goldValue;
        // update UI
        this.playerGoldText.text = 'Gold: ' + this.player.gold;
        // remove the coin
        coin.kill();
    },
    onKilledMonster: function(monster) {
        // move the monster off screen again
        monster.position.set(1000, this.game.world.centerY);

        var coin;
        // spawn a coin on the ground
        coin = this.coins.getFirstExists(false);
        coin.reset(this.game.world.centerX + this.game.rnd.integerInRange(-100, 100), this.game.world.centerY);
        coin.goldValue = Math.round(this.level * 1.33);
        this.game.time.events.add(Phaser.Timer.SECOND * 3, this.onClickCoin, this, coin);

        this.levelKills++;

        if (this.levelKills >= this.levelKillsRequired) {
            this.level++;
            this.levelKills = 0;
        }

        this.levelText.text = 'Level: ' + this.level;
        this.levelKillsText.text = 'Kills: ' + this.levelKills + '/' + this.levelKillsRequired;

        // pick a new monster
        this.currentMonster = this.monsters.getRandom();
        // upgrade the monster based on level
        this.currentMonster.maxHealth = Math.ceil(this.currentMonster.details.maxHealth + ((this.level - 1) * 10.6));
        // make sure they are fully healed
        this.currentMonster.revive(this.currentMonster.maxHealth);
    },
    onRevivedMonster: function(monster) {
        monster.position.set(this.game.world.centerX + 100, this.game.world.centerY + 50);
        // update the text display
        this.monsterNameText.text = monster.details.name;
        this.monsterHealthText.text = monster.health + 'HP';
    },
    onClickMonster: function(monster, pointer) {
        // apply click damage to monster
        this.currentMonster.damage(this.player.clickDmg);

        // grab a damage text from the pool to display what happened
        var dmgText = this.dmgTextPool.getFirstExists(false);
        if (dmgText) {
            dmgText.text = this.player.clickDmg;
            dmgText.reset(pointer.positionDown.x, pointer.positionDown.y);
            dmgText.alpha = 1;
            dmgText.tween.start();
        }

        // update the health text
        this.monsterHealthText.text = this.currentMonster.alive ? this.currentMonster.health + ' HP' : 'DEAD';
    }
});

game.state.start('play');

Anyone have an idea why it goes like that? Please feel free to share your thoughts, and thank you for stopping by! :D

\$\endgroup\$
1
\$\begingroup\$

Nevermind, guys. I fixed the problem.. the reason why all the images are showing at the center of the screen is because of the "this.monsters = this.game.add.group();" and the " monster = state.monsters.create(state.game.world.centerX, state.game.world.centerY, data.image);" code. Now, the "x" serves as the horizontal position of the images and it should be more than the value of the canvas to have the stacked images off the screen and look more like this instead.

enter image description here

Now the remainder is the monster that is clickable and respawns as a new monster from the group which is what I was going for, let me put it in this way.. It's like dealing a deck of cards, the table is the screen, the deck are the stacked images and the one card at the center of table is randomly picked from the rest is our card.. the deck of cards shouldn't be on the table or it would result as the problem that I had, what youd should do is to put the deck of cards away from the table so it wouldn't appear on the screen as stacked images leaving one card at the center of the table. now that I have learned my lesson.. I hope this would help others as well.. :D

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.