Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

10 years ago by Silent

Hello :)

I've read the docs, and as far as I understand you're supposed to call loadLevelDeferred() if you're in the middle of an update. Trouble is that if I use loadLevelDeferred() the engine will load the new level, blink the old level for just an instant, and then continue with the new level as if nothing happened. This doesn't happen if I use loadLevel(). Am I doing something wrong?

Thanks in advance :D

10 years ago by Joncom

What do you mean "blink the old level"?

Do you mean the current level disappears, then comes back for a brief moment, then disappears again, and then the new level loads?

10 years ago by Silent

It's kinda hard to explain, because it all happens very quickly -
The impression I'm getting is that the new level appears for a duration of 1 frame, then the old level appears for 1 frame, and then the new level loads normally and the game continues to run.

10 years ago by Joncom

Mind sharing main.js and file containing the call to .loadLevelDeferred?

10 years ago by Silent

Sure :)
I'm sorry if the code is messy, if you have any questions or any other files that you would like to take a look at feel free to ask.
The call to loadLevelDeferred() is being made in playerBatle.js in the leaveBattle() function.

main.js
ig.module( 
    'game.main' 
)
.requires(
    'impact.game',
    'impact.timer',

    'game.entities.player',
    'game.entities.uiIdle',
    'game.entities.item',

    'game.levels.start',
    'game.levels.potions',
    'game.levels.humanPortal',
    'game.levels.whiteLeaves',

    'game.levels.gateOne',

    'impact.debug.debug'
)
.defines(function () {

    MyGame = ig.Game.extend({

        maxWidth: 0,
        maxHeight: 0,

        // EntityPlayer.init() will set it to the current instance of EntityPlayer.
        player: null,

        // EntityPlayerBattle.init() will set it to the current instance of EntityPlayerBattle.
        playerBattle: null,

        // A refrence to the currently open dialog, EntityDialog.showDialog()
        // will set this.
        dialog: null,

        // This is used to let the inventory dialog know
        statVisible: false,

        // Are we dragging an item?
        dragging: undefined,

        // Are we waiting for our turn in battle?
        waiting: false,

        // Is the mouse on top of a spell?
        spellHover: null,

        // For battle mode
        topEnemy: {playerStats: undefined},
        bottomEnemy: {playerStats: undefined},
        selectedEnemy: null,
        rewards: {gold: 0, exp: 0},

        playerStats: {
            vel: {x: 0, y: 0},
            accel: {x: 0, y: 0},
            pos: {x: 80, y: 56},
            flip: true,

            teleport: -1,
            frozen: false,

            pType: 2,
            level: 1,
            gold: 75,

            hpPots: 5,
            mpPots: 5,

            str: 15,
            speed: 15,

            gate1: 0,
            gate2: 0,
            gate3: 0,

            hp: {now: 75, max: 75},
            mp: {now: 75, max: 75},
            eng: {now: 50, max: 50},
            exp: {now: 0, max: 50},
            shd: {now: 0, max: 0},

            // Inventory. 0 - 7 for items, rest is equipment.
            inv: new Array(12),
        },

        playerTimer: new ig.Timer,
        playerTimerCount: 0,

        getStats: function () {
            eqp = this.playerStats.inv;
            stats = {};
            
            getStat = function (stat) {
                val = 0;

                for(i = 8; i <= 11; i++) {

                    if(eqp[i] !== undefined) {

                        tmpStats = arrItems[eqp[i]].stats;

                        for(j = 0; j < tmpStats.length; j++) {

                            if(tmpStats[j].statName === stat) {
                                val += tmpStats[j].statValue;
                            }
                        }
                    }
                }

                return val;
            }

            stats.str   = ig.game.playerStats.str;
            stats.speed = ig.game.playerStats.speed;
            stats.atk   = getStat(itemStats.PHYSICAL_DAMAGE);

            return stats;
        },

        init: function() {
            
            ig.input.bind( ig.KEY.A, 'left'  );
            ig.input.bind( ig.KEY.D, 'right' );
            ig.input.bind( ig.KEY.W, 'up'    );
            ig.input.bind( ig.KEY.S, 'down'  );

            ig.input.bind( ig.KEY.SPACE, 'action' );
            ig.input.bind( ig.KEY.MOUSE1, 'click' );

            ig.input.bind( ig.KEY.I, 'info'  );

            this.mapItems();
            this.initPlayer();

            this.playerStats.inv[9] = 1;
            this.playerStats.inv[10] = 1;

            this.loadLevel( LevelStart );
        },

        update: function() {
            this.parent();
            
            var player = this.player;

            if(ig.input.pressed('info')) {
                console.clear();

                console.log("Top dead: " + this.topEnemy.playerStats.dead);
                console.log("Bottom dead: " + this.bottomEnemy.playerStats.dead);
            }


            // Check if the player is alive, and if he is,
            // make sure he doesn't go off-screen.
            if(player) {
                if(player.pos.x < 0) {
                    player.pos.x = 0;
                    player.accel.x = 0;
                    player.vel.x = 0;
                } else if( (player.pos.x + player.size.x) > this.maxWidth ) {
                    player.pos.x = this.maxWidth - player.size.x;
                    player.accel.x = 0;
                    player.vel.x = 0;
                }


                if(player.pos.y < 0) {
                    player.pos.y = 0;
                    player.accel.y = 0;
                    player.vel.y = 0;
                } else if( (player.pos.y + player.size.y) > this.maxHeight ) {
                    player.pos.y = this.maxHeight - player.size.y;
                    player.accel.y = 0;
                    player.vel.y = 0;
                }
            }
        },

        draw: function () {
            this.parent();

            if(this.dialog) {
                this.dialog.draw(true);

                if(this.dragging) {
                    this.dragging.draw(true);
                }
            }
        },

        loadLevel: function (level) {
            this.parent(level);

            // Corrects map size vars
            var sampleMap = ig.game.backgroundMaps[0]; 
            var tilesize = sampleMap.tilesize;
            this.maxWidth  = sampleMap.width * tilesize;
            this.maxHeight = sampleMap.height * tilesize;
        },


        initPlayer: function () {
            this.playerStats.pType = Math.floor((Math.random() * 4));

            switch (this.playerStats.pType) {

                // Warrior
                case 1:
                    this.playerStats.hp = {now: 85, max: 85};
                    this.playerStats.mp = {now: 65, max: 65};
                    this.playerStats.str   = 17;
                    this.playerStats.speed = 13;
                    break;

                // Seer
                case 2:
                    this.playerStats.mp = {now: 90, max: 90};
                    this.playerStats.speed = 13;
                    break;

                // Assassin
                case 3:
                    this.playerStats.hp = {now: 70, max: 70};
                    this.playerStats.mp = {now: 80, max: 80};
                    this.playerStats.str   = 13;
                    this.playerStats.speed = 17;
                    break;

                default:
                    break;
            }

            if(this.playerStats.pType == 2) {

                // Energy Knife
                this.playerStats.inv[0] = 2;
            } else {

                // Iron Knife
                this.playerStats.inv[0] = 1;
            }

            this.playerTimer.set(1);
        },


        mapItems: function () {
            for(i = 0; i < arrItems.length; i++) {
                arrItems[i].itemId = i;
            }
        }
    });


    // Start the Game with 60fps, a resolution of 160x120, scaled
    // up by a factor of 4
    ig.main( '#canvas', MyGame, 60, 160, 120, 4);
});

playerBattle.js
ig.module(
    'game.entities.playerBattle'
)
.requires(
    'impact.entity',
    'game.entities.npcBattle',
    'game.entities.uiBattle',
    'game.entities.battleMove',
    'game.entities.item',
    'game.levels.humanPortal',
    'game.levels.battleEnd'
)
.defines( function () {

    EntityPlayerBattle = ig.Entity.extend({
        
        collides: ig.Entity.COLLIDES.NEVER,

        size: {x: 8, y: 8},
        offset: {x: 4, y: 2},
        animSheet: new ig.AnimationSheet('media/chars_anim.png', 16, 10),

        gate: 1,
        idx: 0,
        speed: 80,
        flip: false,

        atk: 0,
        isInAtk: 0,
        atkCtr: 0,
        movingNow: null,

        
        init: function (x, y, settings) {
            this.parent(x, y, settings);

            if(ig.game.playerStats !== undefined) {
                this.idx = ig.game.playerStats.pType;
            }

            this.addAnim('stand', 1, [this.idx * 7]);
            this.addAnim('walk', 0.2, [this.idx * 7 + 1, this.idx * 7 + 2]);
            this.addAnim('attack1', 0.2, [this.idx * 7 + 3]);
            this.addAnim('attack2', 0.2, [this.idx * 7 + 4, this.idx * 7]);

            this.addAnim('attack3', 0.2, [this.idx * 7 + 5]);
            this.addAnim('attack4', 0.2, [this.idx * 7 + 6, this.idx * 7]);

            if(typeof ig.game.spawnEntity == "function")
            {
                ig.game.spawnEntity(EntityUiBattle, 0, 88, {gate: this.gate});
            }

            ig.game.playerBattle = this;

            ig.game.topEnemy.playerStats.dead = true;
            ig.game.bottomEnemy.playerStats.dead = true;
        },

        update: function () {
            this.parent();

            // Execute a battle move
            if(this.movingNow instanceof EntityBattleMove) {
                ig.game.waiting = true;
                if(this.movingNow.execute(this, ig.game.selectedEnemy) === true) {
                    this.movingNow = null;

                    // Make the enemies attack
                    if(ig.game.topEnemy instanceof EntityNpcBattle && ig.game.topEnemy.playerStats.dead === false) {
                        ig.game.topEnemy.attack();
                    } else if(ig.game.bottomEnemy instanceof EntityNpcBattle && ig.game.bottomEnemy.playerStats.dead === false) {
                        ig.game.bottomEnemy.attack();
                    }
                }
            } else if(ig.game.topEnemy.playerStats.dead === true
                && ig.game.bottomEnemy.playerStats.dead === true) {

                this.leaveBattle(dead = false);
            }

            // This takes care of decreasing energy in battle, but not HP / MP.
            // Read docs in player.js for more info.
            if(ig.game.playerTimer.delta() >= 0) {

                if(ig.game.playerStats.eng.now > 0 && !ig.game.playerStats.frozen) {
                    if(ig.game.playerTimerCount < 9) {
                        ig.game.playerTimerCount++;
                    } else {
                        ig.game.playerTimerCount = 0;
                        ig.game.playerStats.eng.now--;
                    }
                } else {
                    ig.game.playerTimerCount = 0;
                }

                ig.game.playerTimer.set(1);
            }

            if(ig.game.playerStats.dead === true) {
                this.leaveBattle(true);
            }

            this.currentAnim.flip.x = this.flip;
        },

        getStats: function () {
            return ig.game.getStats();
        },

        hit: function(dmg) {
            if(ig.game.playerStats.shd.now > 0) {
                ig.game.playerStats.shd.now -= dmg;
                if(ig.game.playerStats.shd.now < 0) {
                    ig.game.playerStats.shd.now = 0;
                }
            } else {
                ig.game.playerStats.hp.now -= dmg;
                if(ig.game.playerStats.hp.now <= 0) {
                    ig.game.playerStats.dead = true;
                }
            }
        },

        leaveBattle: function(dead) {

            ig.game.player.lightsNpc = null;
            ig.game.playerStats.teleport = 1;
            ig.game.waiting = false;
            ig.game.playerStats.vel = {x: 0, y: 0};
            ig.game.playerStats.accel = {x: 0, y: 0};
            ig.game.playerStats.shd.now = ig.game.playerStats.shd.max;

            // Defeat
            if(dead === true) {
                ig.game.playerStats.dead = false;
                ig.game.playerStats.hp.now = 5;
                ig.game.playerStats.mp.now = 5;
                ig.game.playerStats.eng.now = 5;

                if(this.gate === 1) {
                    ig.game.playerStats.pos.x = 76;
                    ig.game.loadLevel(LevelHumanPortal);
                } else {
                    // TODO
                }

            // Victory
            } else {
                ig.game.rewards.gold = 66;
                ig.game.rewards.exp  = ig.game.topEnemy.playerStats.exp + ig.game.bottomEnemy.playerStats.exp;
                ig.game.loadLevel(LevelBattleEnd);
            }
        }
    });

});

10 years ago by Joncom

First of all, you're not currently using loadLevelDeferred at all.
Might want to fix that first and foremost.

10 years ago by Silent

Oh whoops, my bad.
In playerBattle.js I replaced loadLevelDeferred() with loadLevel() until I find a solution because loadLevel() doesn't cause this issue.
I don't know, it works fine this way but I've read that it's bad to call loadLevel() in the middle of an update.

10 years ago by Joncom

Is it possible that more than one playerBattle entity exists at a given moment?
Is it possible that loadLevelDeferred is being called more than once consecutively?

10 years ago by Silent

That would be a no for both.

10 years ago by Joncom

Don't have a fix for you just yet.
But can you tell me, what is this line supposed to be doing:
this.leaveBattle(dead = false);?
It seems out of place, and so I wonder if it means what you think it does.
For starters, dead does not seem to be defined anywhere.
And if that's intentional, well, then you're creating a global variable.
Which could be OK, but for what you're doing it does seem unnecessary.

10 years ago by Silent

Umm it just passes false as a parameter

10 years ago by Joncom

Quote from Silent
Umm it just passes false as a parameter
Hmm. Not sure what the advantage to doing it that way is.
In fact, it comes at the disadvantage of creating a global variable.

This way would not:
this.leaveBattle(false);

This way would also not:
var dead = false;
this.leaveBattle(dead);

10 years ago by Silent

Perhaps I confused JS with Python :S
Python can have named arguments, I thought it was more readable this way. Thanks for pointing it out.

10 years ago by Joncom

No problem.
JavaScript doesn't have named arguments.
It's a cool idea though.

10 years ago by Joncom

I didn't see anything jump out that would make your game blink the way you say it does. However, there's a significant amount of stuff going on. To find the source of the glitchy behavior, I'd make sure I have a saved copy of the current state of the game. Then I'd begin tearing out chunks of code not needed. Keep going until the only thing you have left is the level loading and glitch. Though, I suspect you'll find the issue before you get that far...
Page 1 of 1
« first « previous next › last »