Evgeniy

Missing childeren elements at an element of group after move

Recommended Posts

Hi all,

I build simple word match game:

Скриншот 2016-05-18 06.47.01.png


http://woa.troinof.ru/

 

If you play game you can see that elements not always disappear, for some reason after selected element removed and other moved down his children element disappear:

Скриншот 2016-05-18 07.00.25.png

and must be:

Скриншот 2016-05-18 07.06.57.png

 

It happends after letter moves.

 

Bug step by step:

 

Step 1:

step_1.png

 

Step 2 (all good):

step_2.png

 

Step 3 ( repeat step 2):

step_3.png

 

Result step 3 ( FAIL ):

Скриншот 2016-05-18 06.47.01.png

 

I dont't understand where i made mistake.

 

Fanks for attention:

 

Source code: http://woa.troinof.ru/bc.tar

Source code ( board.ts ):

///<reference path="../def/require.d.ts"/>
///<reference path="../def/lodash.d.ts"/>

///<reference path="../game.ts"/>
///<reference path="../boot.ts"/>

define(['phaser', 'lodash'],function(Phaser, _) {

    class Board {
        game: any;
        letters: any;
        tileWidth: number;
        tileHeight: number;
        userSelect: any = [];
        word: string = '';

        btnExit: any;
        btnHelp: any;
        btnSound: any;
        btnMusic: any;
        btnCoin: any;

        movesCounter: any;
        userCoin: number = 250;
        userScore: any;

        coinCountLabel: any;

        levelTheme: any;
        hoverSound: any;
        tileMoveSound: any;

        letterGrid: any = [
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
            [null, null, null, null, null, null, null, null],
        ];

        constructor(game: any) {
            this.game = game;
            this.tileWidth       = this.game.cache.getImage('field').width;
            this.tileHeight      = this.game.cache.getImage('field').height;
            this.tileMoveSound   = this.game.add.audio('tile_move');
            this.hoverSound      = this.game.add.audio('tile_select');

            // Саундтрек игровой комнаты
            this.levelTheme = this.game.add.audio('level_theme', 1, true).play();

            // Создаем кнопку выхода и назначаем обработчик
            this.btnExit = this.game.add.button(5, this.game.height - 80, 'btn_exit', this.exit, this, 1, 0, 2, 0);
            this.btnExit.input.useHandCursor = true;
            this.btnExit.onOverSound = this.hoverSound;

            // Создаем кнопку подсказки и назначаем обработчик
            this.btnHelp = this.game.add.button(this.game.width - 81, this.game.height - 80, 'btn_help', this.help, this, 1, 0, 2, 0);
            this.btnHelp.input.useHandCursor = true;
            this.btnHelp.onOverSound = this.hoverSound;

            // Создаем кнопку вкл/вкл звуков и назначаем обработчик
            this.btnSound = this.game.add.button(100, this.game.height - 45, 'btn_sound', this.toggleSound, this, 1, 0, 2, 0);
            this.btnSound.input.useHandCursor = true;
            this.btnSound.onOverSound = this.hoverSound;

            // Создаем кнопку вкл/вкл музыки и назначаем обработчик
            this.btnMusic = this.game.add.button(150, this.game.height - 45, 'btn_music', this.toggleMusic, this, 1, 0, 2, 0);
            this.btnMusic.input.useHandCursor = true;
            this.btnMusic.onOverSound = this.hoverSound;

            // Индикатор монет
            this.btnCoin = this.game.add.button(this.game.width - 164, -5, 'btn_coin', this.buyCoin, this, 1, 0, 2, 0);
            this.btnCoin.input.useHandCursor = true;
            this.btnCoin.onOverSound = this.hoverSound;

            this.coinCountLabel = this.game.add.text(70, 23, this.userCoin, {font: "bold 32px Arial", fill: "#EEFF9C"});
            this.btnCoin.addChild(this.coinCountLabel);
        }

        toggleSound() {
            this.hoverSound.mute    = this.hoverSound.mute ? false : true;
            this.tileMoveSound.mute = this.tileMoveSound.mute ? false : true;
        }

        toggleMusic() {
            this.levelTheme.mute = this.levelTheme.mute ? false : true;
        }

        buyCoin() {
            alert('покупка монет');
        }

        /** Заполняем доску буквами - на данный момент не испльзуется */
        initTiles() {
            let self = this;

            for (let i = 0; i < self.letterGrid.length; i++) {

                for (let j = 0; j < self.letterGrid.length; j++) {
                    let tile = self.addLetterTile(i, j);

                    self.letterGrid[i][j] = tile;
                }
            }
        }

        addLetterTile(x: number, y: number) {}

        resetTile() {
            // Проходим циклом по каждой колонке начиная слева
            for(let i = 0; i < this.letterGrid.length; i++) {
                // Проходим циклом по каждой букве снизу вверх
                for(let j = this.letterGrid[i].length - 1; j > 0; j--) {

                    // Если область пустая, но область выше нет, смещаем на одну вниз
                    if(this.letterGrid[i][j] === null && this.letterGrid[i][j-1] !== null) {
                        let tempTile = this.letterGrid[i][j-1];

                        // Меняем буквы местами
                        this.letterGrid[i][j]   = tempTile;
                        this.letterGrid[i][j-1] = null;

                        // Добавим анимацию перемещения
                        this.moveDown(tempTile, j);

                        // Перемещаем указатель снова вверх для повторного прохода массива
                        // Примечание: мы не указываем this.letterGrid[i].length - 1 так как данное значение уже будет изменено
                        // В данный момент мы в конце цикла
                        // Данная процедура будет повторятся до тех пор пока в данном массиве все null значения
                        // небудут перемещенны вверх
                        j = this.letterGrid[i].length;
                    }
                }
            }

            // Звук падения камней
            this.tileMoveSound.play();
        }

        exit() {
            alert('You leave the room');
        }

        help() {
            alert('Подсказка');
        }


        moveDown(letter: any, position: number) {
            let tw = this.game.add.tween(letter);

            tw.to({y: (LETTER_SIZE_SPACED * position) + (LETTER_SIZE_SPACED / 2) + 150}, 600, Phaser.Easing.Bounce.Out, true);
        }

        fillTile() {}

        // Deprecated
        fill() {
            let letterIndex: number = 0,
                letterContainer: any,
                letter: any,
                ground: any,
                time: any = new Date();

            // Создаем группу которая будет содержать буквы
            this.letters = this.game.add.group();
            this.letters.enableBody = true;

            for(let i = 0; i < BOARD_COLS; i++) {

                // Заполняем массив буквами
                for (let j = 0; j < BOARD_ROWS; j++) {
                    letterIndex     = Math.floor(Math.random() * (31 - 0));

                    letterContainer = this.letters.create(
                        i * LETTER_SIZE_SPACED + (LETTER_SIZE_SPACED / 2) + 200,
                        j * LETTER_SIZE_SPACED + (LETTER_SIZE_SPACED / 2) + 150,
                        'field'
                    );

                    // Устанавливаем точку объекту по центру
                    // для выравнивания текста и анимации
                    letterContainer.anchor.setTo(0.5, 0.5);

                    // Устанавливаем стартовый размер в 0
                    letterContainer.scale = {
                        type: 25,
                        x: 0.4,
                        y: 0.4
                    };

                    letter = this.game.add.text(
                              0,
                              0,
                              ALPHABET[letterIndex], {
                                  font: "bold 38px Arial",
                                  fill: "#5E1400",

                                  // Выравние текста по центру
                                  boundsAlignH: "center",
                                  boundsAlignV: "middle"
                              });

                    // Генерируем уникальный id для каждой буквы
                    letter.uid = (Math.random() * time.getTime()).toFixed();

                    // Обработка событий мышки на буквах
                    letter.inputEnabled = true;

                    letter.events.onInputDown.add(this.selectLetter, this);
                    letter.events.onInputOver.add(this.hoverLetter, this);

                    // Запоминаем позицию буквы на карте
                    letterContainer.gridPosition = {
                        y: i,
                        x: j
                    };

                    // Устанавливаем границы контейнера буквы
                    letter.setTextBounds(0, 0, 0, 0);

                    // Помещаем букву в контейнер с фоном
                    letterContainer.addChild(letter);

                    // fill board letterGrid
                    this.letterGrid[i][j] = letterContainer;

                    // Анимация появления буквы
                    this.game.add.tween(letterContainer.scale).to({x: 1, y: 1}, 700, Phaser.Easing.Bounce.Out, true);
                }
            }
        }

        /**
         * Change letter state
         *
         * @param {obect} letter - obect contain leter
         * @param {letter} state - letter state ( normal, selected, active)
         */
        changeLetterState(letter: any, state: string) {
            let tw: any;

            switch(state) {
                case 'select':
                    // Меняем цвет и фон буквы
                    letter.parent.loadTexture('field_active');
                    letter.fill = '#ffffff';

                    // Заносим букву в список выделенных и запускаем анимацию нажатия
                    // tw = this.game.add.tween(letter.parent.scale).from({x: 0.2, y: 0.2}, 400, Phaser.Easing.Bounce.Out, true);

                    this.word += letter.text;
                    break;

                    default:
                        break;
            }

        }

        /**
         * Устанавливаем флаг нажатия когда пользователь кликнул по тайлу
         *
         * @public
         * @param {obect} - contain letter obect
         */
        selectLetter(letter: any) {
            this.hoverSound.play();

            // Заносим букву в выбранные
            this.userSelect.push(letter.parent);

            // Меняем состояние буквы
            this.changeLetterState(letter, 'select');
        }

        /** Проверяем значение тайла когда курсор над ним */
        hoverLetter(letter: any) {
            this.hoverSound.play();

            // Проверяем нажата ли кнопка мышки и есть ли ходы у игрока
            this.game.input.activePointer.isDown && this.game.userMoves > 0 && (() => {
                // Заносим букву в выбранные
                this.userSelect.push(letter.parent);

                // Меняем состояние буквы
                this.changeLetterState(letter, 'select');
            })();
        }

        /** Снимаем флаг нажатия когда пользователь отпустил клавишу */
        removeSelectedLetter(letter:any) {
            let el: any,
                tw: any,
                tile: any;


            if(this.userSelect.length > 1) {
                this.debugDrawletterGrid();

                while (!!this.userSelect.length) {
                    tile = this.userSelect.shift();

                    ((sprite: any) => {
                        let position = sprite.gridPosition;

                        this.letterGrid[position.y][position.x] = null;

/*
                        tw = this.game.add.tween(sprite.scale);
                        tw.to({x: 0, y: 0}, 500, Phaser.Easing.Bounce.Out);
                        tw.start();

                        tw.onComplete.add(() => {*/
                            sprite.destroy();
                        /*});*/
                    })(tile);

                    this.game.userScore = this.game.userScore + 20;
                }

                this.userScore.text    = this.game.userScore;
                this.movesCounter.text = --this.game.userMoves;

                this.resetTile();
                this.debugDrawletterGrid();
            }

        }

        debugDrawletterGrid() {
            var str: string = '',
                letterObj: any = '';

            for (var i = 0; i < BOARD_COLS ; i++) {
                str = '';
                for (var j = 0; j < BOARD_ROWS; j++) {
                    letterObj = this.letterGrid[j][i];
                    if(!_.isNull(letterObj)) {
                        if(letterObj.children.length && ('_text' in letterObj.children[0])) {
                            str += '| ' + letterObj.children[0]._text + ' ';
                            console.info(letterObj);
                        } else {
                            str += '| letter not exist';
                            console.info(letterObj);
                        }
                    } else {
                        str += '| ' + letterObj + ' ';
                    }
                }
                console.info(str);
            }
            console.info('-----------------------------');
        }
    }

    return Board;
});

Game.ts:

/// <reference path="def/p2.d.ts" />
/// <reference path="def/pixi.d.ts" />
/// <reference path="def/phaser.d.ts" />
/// <reference path="def/require.d.ts" />

/// <reference path="class/board.ts"/>


define(['phaser', 'class/board'], function(Phaser, Board) {

    /** Start dictionary */
    var dictionary = [
            "нож",
            "стул",
            "стол",
            "карандаш",
            "паж"
        ],
        guessing = false;

    /**
     * Class representing game Wisdom of Atlantis
     */
    class WisdomOfAtlantis {
        game: Phaser.Game;
        self: any;
        guessing: boolean = false;
        board: any;

        constructor() {
            this.game = new Phaser.Game(GAME_ROOM_WIDTH, GAME_ROOM_HEIGHT, Phaser.AUTO, 'game-container', { preload: this.preload, create: this.create, update: this.update });
            this.game.userScore = 0;
            this.game.userMoves = 15;
        }

        /** Load game assets */
        preload() {

            // Фон для игровой комнаты
            this.game.load.image('game_room', '../img/bg/game_room.jpg');

            // Фон игровых плиток (normal, hover, active)
            this.game.load.image('field', '../img/bg/field_normal.png');
            this.game.load.image('field_active', '../img/bg/field_active.png');

            // Кнопка выхода
            this.game.load.spritesheet('btn_exit', '../img/controls/buttons/exit.png', 76, 72, 3, 0, 10);

            // Кнопка подсказки
            this.game.load.spritesheet('btn_help', '../img/controls/buttons/help.png', 76, 72, 3, 0, 10);

            // Кнопка вкл/вкл звук
            this.game.load.spritesheet('btn_sound', '../img/controls/buttons/sound.png', 46, 42, 3, 0, 10);

            // Кнопка вкл/вкл музыку
            this.game.load.spritesheet('btn_music', '../img/controls/buttons/music.png', 46, 42, 3, 0, 10);

            // Индикатор монет
            this.game.load.spritesheet('btn_coin', '../img/controls/buttons/coin.png', 166, 84, 3);

            // Загружаем звуки и музыку
            this.game.load.audio('level_theme', '../audio/theme/level_v1.mp3');
            this.game.load.audio('tile_select', '../audio/effect/click.ogg');
            this.game.load.audio('tile_move', '../audio/effect/move.ogg');
            this.game.load.audio('add_score', '../audio/effect/addscore.ogg');
        }

        /** Set game settings */
        create() {
            // Фон игровой комнаты
            this.game.add.image(0, 0, 'game_room');

            // Обрабатываем нажатие мыши
            this.game.input.onDown.add(() => {
                this.guessing = true;
            });

            this.game.input.onUp.add(() => {
                this.guessing = false;
            });

            // Создаем доску
            this.board = new Board(this.game);

            // Счетчик ходов
            this.board.movesCounter = this.game.add.text(55, 45, this.game.userMoves, {font: "bold 68px Arial", fill: "#EEFF9C", boundsAlignH: "center", boundsAlignV: "middle"});
            this.board.userScore = this.game.add.text((this.game.width / 2) + 50, this.game.height - 40, this.game.userScore, {font: "bold 38px Arial", fill: "#EEFF9C", boundsAlignH: "center", boundsAlignV: "middle"});

            this.game.add.text(63, 30, 'Xоды', {
                font: "bold 24px Arial",
                fill: "#EEFF9C",
                boundsAlignH: "center",
                boundsAlignV: "middle"
            });

            // Заполняем доску буквами
            this.board.fill();
        }

        /** Check game state and processing of a condition of game objects */
        update() {
            if (!this.guessing) {
                this.board.removeSelectedLetter();
            }
        }
    }


    return WisdomOfAtlantis;
});

 

 

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.