разработка сетевых игр
HTML5, Typescript, PIXI.js
Привет, я Юра Дорогой и это мой блог о разработке игр и не только
Пару недель назад я взялся за изучение Golang и в качестве пробы пера меня опять затянуло в gamedev. Задача простая: написать онлайновую игру, которая будет устойчива к читерам, производительная, масштабируемая и стабильная. Там должна быть авторизация, трекинг пользовательской статистики, корованы и колижен детекшен
HTML5, Typescript, PIXI.js
Я взял свой старый движок (на PIXI.js, sounds.js и nape physics) и переписал его на Typescript. TS - это очень интересно, но есть свои недостатки. Во-первых это require-js, во-вторых нужно для подключаемых библиотек искать их typings файл, который не всегда можно найти и еще это очень мягкая типизация. Можно типизировать, а можно писать declare any, как тебе угодно

На TS я написал модненький асинхронный интерфейс на функциях первого класса, с которым можно делать так:
var o: DynamicObject = new DynamicObject();
o.wait(1).die().call(function (){o.addBlood()}).apply();

//или так

o.onCollide(typeWall).die().apply();
Это очень удобный способ выражения асинхронных и синхронных скриптов. Меня осенило, что такого рода скрипты, скорее всего начальных состояний, удобно использовать в редакторе уровней и даже обучить им левел дизайнера

Для этого я написал интерфейс Contextable и класс Context для генерации оберток
interface Contextable {
    context:Context;
    call(milliseconds: number, func: Function)
    wait(milliseconds: number)
    apply()
}

class Context {
    c:Context;
    static globalID: number = 0;
    id: number = 0;
    f:Function = () => {}

    nextF(cb: (end: Function) => any) {
        var con = this;
        return function () {
            //all the previous goes here
            if (con.c)
                con.c.f.bind(con.c);
            cb(con.f);
        };
    }

    constructor (prev: Context, prevF:(end: Function) => any) {
        this.c = prev;
        this.id = Context.globalID;
        Context.globalID++;
        if (prevF)
            this.c.f = this.nextF(prevF);
    }
}
Интересного тут только Context.nextF - функция, которая перезаворачивает функцию f предыдущего контекста и вызывает себя. Теперь все классы могут воплощать Contextable, например загрузчик уровней, или игровые объекты. Это очень просто, например вот так
call(milliseconds, func) { 
        this.context = new Context(this.context, (next: Function) => {
            setTimeout(() => {
                func();
                next();
            }, milliseconds);
       });

        return this;
    }
У такого функционального подхода есть недостаток. Нужно не забывать вызывать функцию apply, чтобы запустить самый актуальный контекст.
По всем вопросам, ddearcj@gmail.com
Made on
Tilda