Разработка на коленке

"тут должна быть красивая цитата о программировании"

Змейка на Phaser3

2018-12-02 19:40

Snake preview

Просто очередная змейка на Phaser3 с графикой в стиле pixelart.

По мере поедания фиолетовых яблок появляются не только новые яблоки, но и камни, столкновение с которыми убивает змейку.

Из интересного - забавный механизм смены головы и хвоста, если нажать кнопку, противоположную текущему направлению движения. Работает примерно так:

reverse() {
    const inverse = {
        up: 'down',
        down: 'up',
        left: 'right',
        right: 'left',
    };

    this.snake = this.snake.reverse();
    this.snake.forEach(s => {
        s.direction = inverse[s.direction];
    });
    this.direction = this.snake[this.snake.length - 1].direction;
}

Спрайты

Пальмы вышли странновато, а вот камень мне нравится.

Snake sprites

Игра

Snake game

Исходники

https://gitlab.com/grigoriytretyakov/phaser3-snake

Sparkling Tail, постмортем

2018-11-02 00:30

Sparkling Tail preview

История этой игры началась в далёком 2013 году. Тогда я (ещё на python+pygame) сделал игрушку, где персонажем был Sparkling Tail. Этот зверёк мне так понравился, что уже позже, в 2014, я решил сделать новую игру с его участием, но уже браузерную версию (раз, два). Однако тогда у меня так и не дошли руки закончить игрушку. И вот спустя ещё 3 года, теперь уже в конце 2018 я решил довести до конца задуманную тогда игру. И дело не в том, что идея игры мне не давала покоя (ничего особенного в ней нет), мне нравился сам герой.

Правила игры довольно просты - уклоняться от летящих на тебя штуковин. Камни просто бьют по голове и смещают в сторону, если вылетел за границы экрана - умер. Колючки убивают сразу.

Когда я снова засел за эту игру, то придумал целый набор разных каменюк, а также разные способы движения. Но уже после добавления камней и шипов с тремя типами движения понял, что игра не настолько интересна, чтобы продолжать её развивать. Бросать разработку на половине пути тоже не хотелось, поэтому я доделал игру с той механикой, что уже была запрограммирована. Так что пусть всё остаётся как есть.

Игра

Sparkling Tail game

Исходники

https://gitlab.com/grigoriytretyakov/sparklingtail-ng

Geometric memory для тех, кто любит цвета

2018-10-19 23:54

"Geometric memory" - это вариация игры на память, только нужно запоминать не разные фигурки, а разное расположение цветов в одних и тех же формах. Всего в игре три разных геометрических фигуры: квадрат, треугольник и круг.

Geometric memory preview 2

Для раскраски фигур используется 3 цвета, плюс ещё один для фона. Цвет рамки совпадает с последним цветом из палитры, фактически, это тот цвет, который больше всего контрастирует с фоном.

В какой именно палитре играть, можно выбрать на стартовом экране.

Geometric memory

Когда только взялся за разработку, то хотел сделать игру, где бы мне не пришлось много рисовать, либо искать наборы картинок. С самого начала хотел сделать автогенерацию. Сперва думал о небольшом наборе рисованных элементов, которые потом можно комбинировать. А потом случайно попробовал сгенерировать простые геометрические фигуры и вложить одну в другую. Получилось интересно.

Самым важным было подобрать политры сочетающихся друг с другом цветов. Поскольку я не художник, то решил посмотреть, что на эту тему пишут те, кто рисует в PixelArt. Обычно, в таких рисунках используется ограниченное количество цветов, что мне и нужно было. В одной из статей нашёл описание, как создавать свои палитры и набор примеров, которые взял в свою игру.

Исходники

https://gitlab.com/grigoriytretyakov/geometric-memory

Игра

Кликнув по картинке, можно попробовать найти разницу между этим двумя квадратами.

Geometric memory game

Bouncing zombie на Phaser 3

2018-10-07 18:54

Bouncing zombie desktop

Разглядывая иллюстрации в комиксе "Я ненавижу страну чудес", подумал, что очень красочно выглядит сцена борьбы с зомби, отлично подобраны цвета и замечательно нарисованы персонажи (ещё осознал, что комиксы мне нравятся, хотя я не знаю, как их правильно читать). Глядя на эту красоту, решил в игре про воюющих квадратиков сделать злодеев зомби, которых должен был бы побеждать бесстрашный герой.

В этом прототипе нужно как можно дольше продержаться, уклоняясь от столкновений с зомби, а для борьбы использовать снаряд из света. Проблема в том, что снаряд один и его нужно ловить обратно для повторного броска, а зомби ещё и пытается от него уклоняться (иногда - успешно).

Управлять - стрелками или WAD, для выстрела - пробел. На тачскрине тоже играть можно: свайпами меняем направление или прыгаем, а стрелять просто нажатием на экран.

Эволюция персонажей

В финальном варианте игры персонажи не такие, как я их создавал в первом варианте. Сперва я думал сделать просто прыгающие квадраты, а уже потом под влиянием комикса сделал из врагов (frags) зомби. Так у зелёного врага в глазах появились крестики. Потом я попытался сделать глаза более выразительными, а тело зомби деформированным.

Bouncing zombie

Bouncing zombie

Bouncing zombie

Помимо этого мне захотелось сделать так, чтобы во время прыжка у героя менялось положение зрачка. Только во время игры это почти не заметно из-за высокой скорости движения. Поэтому я прикрутил смену направления взгляда и для стартовой кнопки:

pointerMove(pointer) {
    let frame = pointer.position.x < this.startButton.x ? 0 : 3;

    let offset = 1;
    if (pointer.position.y > (this.startButton.y + this.startButton.height)) {
        offset = 2;
    }
    else if (pointer.position.y < (this.startButton.y - this.startButton.height)) {
        offset = 0;
    }

    frame += offset;

    this.startButton.setFrame(frame);
}

Мобильные устройства

Так это выглядит на экране моего телефона:

Bouncing zombie mobile

А так это смотрится, если экран повернуть вертикально:

Bouncing zombie mobile vertical

Код для ресайза и для управления с тачскрина взял из книги "HTML5 Cross Platform Game Development Using Phaser 3", которую написал Emanuele Feronato (https://www.emanueleferonato.com/).

Исходники и игра

Исходники https://gitlab.com/grigoriytretyakov/phaser3-bouncing-frags

Играть можно там, или кликнув по зомби:

bouncing zombie game

Гонки на phaser3 + matterjs

2018-08-22 22:50
phaser3-racing-car-preview

Чем мне нравится разработка игр в качестве хобби, так это возможностью менять геймплей по ходу разработки, не опасаясь, что это кому-нибудь сломает бизнес-модель.

Сперва я думал сделать так, чтобы машинка собирала разбросанные шины в центре поля, а людей и конусы сбивать было нельзя. Но потом оказалось, что гораздо веселее как раз таки сбивать конусы, а о людях вообще не заботиться. Потом сделал так, чтобы люди были кем-то вроде дорожных работников, которые поднимают сваленные конусы. Что самое интересное, обычного рандомного движения для людей оказалось достаточно, а писать ИИ не понадобилось, и без него играть порой сложно.

В итоге получилась игра, в которой нужно кататься машинкой по полю, сбивать конусы, а заодно отпихивать ремонтников подальше от конусов, потому что эти вредные рабочие совсем не боятся столкновений.

Matter

Аркадный физический движок мне не подошёл, потому что его модель работы AABB создавала проблемы даже в шутере, так как вращается там только картинка, а не тело целиком.

Код

В плане кода в этот раз вместо наследования для объектов стал использовать агрегирование, в связке с phaser это оказалось удобнее, чем расширение классов:

class Cone {
    constructor(scene, x, y) {
        this.UP = 'cone1';
        this.DOWN = 'cone2';

        this.isUp = true;

        this.scene = scene;

        this.body = this.scene.matter.add.image(x, y, this.UP);

        this.body.body.label = 'cone';

        this.body.body.cone = this;

        this.body.setScale(0.5);
    }

    up () {
        this.isUp = true;
        this.body.setTexture('cone1');
    }

    down () {
        this.isUp = false;
        this.body.setTexture('cone2');
    }
};

Агрегация даёт возможность строить свою иерархию, а объекты движка использовать для рисования и физики. Впрочем, здесь наверняка сказывается моё плохое знание третьей версии фазера, которая отличается от второй, плюс новая физика.

Ну и ещё пришлось разбираться, как работает детект столкновений, если их несколько. Для нормальной обработки нужно перебрать все пары столкнувшихся тел:

createCollisions() {
    this.matter.world.on('collisionstart', (event) => {
        event.pairs.forEach(pair => {
            const { bodyA, bodyB  } = pair;

            if (bodyA.label === 'car' && bodyB.label === 'cone') {
                bodyB.cone.down();
            }
            else if (bodyA.label === 'cone' && bodyB.label === 'car') {
                bodyA.cone.down();
            }
            else if (bodyA.label === 'man' && bodyB.label === 'cone') {
                bodyB.cone.up();
            }
            else if (bodyA.label === 'cone' && bodyB.label === 'man') {
                bodyA.cone.up();
            }
        });

        if (this.cones.filter(cone => cone.isUp).length === 0) {
            this.scene.start('GameOver');
        }
    });
}

Ссылка на игру

deathworld game

Ресурсы

В этот раз решил не рисовать графику, а взять на http://opengameart.org/

Исходники

Исходный код там - Исходники