Чё как вообще?
#лайт
Этот пост просто расскажет о том, какие у меня сейчас текущие проекты и чё вообще с ними происходит, чтобы вам было веселее читать этот блог и следить за моими успехами.
1. #Encased.
Это проект, которым я занимаюсь на работе. Он представляет собой RPG в стиле первых Fallout, которую мы пилим на юнити. Всего у нас 3 программиста и пока полтора скриптера (возможно, скоро будет больше), где я за главного, поэтому здесь иногда проскакивают посты об архитектурных решениях Encased. Работаем уже почти год, успешно прошли кикстартер и движемся к раннему доступу. На данный момент поиграть ещё нельзя, но можете пока добавить игру в список желаемого.
2. #Judy.
Это мой личный проект. Игровой движок, названный мной женским именем, и по совместительству мой самый главный и многострадальный долгострой. Я писал его вечерами активно в 2015-2016 годах, а потом временно заморозил в пользу рабочих проектов, что затянулось вот уже на два года. Этим летом, когда я начинал блог, я анонсировал, что возвращаюсь к движку, но как-то не пошло. Но последние две недели я снова предпринимаю попытки находить на него время, и похоже, что на этот раз таки удастся войти в рабочую струю.
В Джуди я делал реально крутые по моему мнению штуки, о которых не стыдно рассказать. С другой стороны, за это время я изменил взгляд на некоторые вещи, поэтому оставайтесь на связи, будет интересно. Сами «алмазики» можно подглядеть на github. Как это часто бывает с пет-прожектами, код там зачастую не самый лучший в виду урывочности написания, но ставить звёзды и фоловить не стесняемся :)
3. #GitTern.
Идея написать очередной клиент для git, заточенный под конкретные нужды, у меня родилась в феврале, когда мы только начинали работать над Encased и пытались подружить художников с системой контроля версий. Задумка потеряла актуальность, когда мы всей компанией перешли на PlasticSCM, но для своих личных нужд я всё равно, само собой, буду использовать git. И теперь, когда мне нужно комитить из разных операционных систем (Judy кроссплатформенный движок), я волей-неволей возвращаюсь к этой идее. Думаю, в самое ближайшее время добью его до минимального функционала и пересяду на него. В отличие от движка, который я пока не решил делать свободным, GitTern полностью open-source по MIT лицензии.
4. #Ameba.
Aggregate MEssage BAr — это агрегатор популярных мессенджеров и ещё один проект, о начале работ над которым я радостно раструбил в блоге, но который, похоже, пока ещё какое-то время полежит на полке.
5. Английский.
В числе личных проектов я также решил перечислить занятия английским, поскольку это непосредственно связано с моей прокачкой в профессиональном смысле. Сейчас я три раза в неделю занимаюсь с преподавателем онлайн, читаю Кинга на бумаге и собираюсь переводить этот блог на английский на Medium.
6. Ключевые слова Shodan’а.
Ещё один важный для меня проект по самопрокачке — пройтись по ключевым словам Андрея Аксёнова. Это, конечно, не прямое руководство к действию, но отличные дорожные ориентиры, по которым я всё собираюсь начать заполнять пробелы в своих знаниях, но никак не начну. Может быть, кто-нибудь из читателей тоже заинтересуется, и вместе будет проще?
Обсудить
#лайт
Этот пост просто расскажет о том, какие у меня сейчас текущие проекты и чё вообще с ними происходит, чтобы вам было веселее читать этот блог и следить за моими успехами.
1. #Encased.
Это проект, которым я занимаюсь на работе. Он представляет собой RPG в стиле первых Fallout, которую мы пилим на юнити. Всего у нас 3 программиста и пока полтора скриптера (возможно, скоро будет больше), где я за главного, поэтому здесь иногда проскакивают посты об архитектурных решениях Encased. Работаем уже почти год, успешно прошли кикстартер и движемся к раннему доступу. На данный момент поиграть ещё нельзя, но можете пока добавить игру в список желаемого.
2. #Judy.
Это мой личный проект. Игровой движок, названный мной женским именем, и по совместительству мой самый главный и многострадальный долгострой. Я писал его вечерами активно в 2015-2016 годах, а потом временно заморозил в пользу рабочих проектов, что затянулось вот уже на два года. Этим летом, когда я начинал блог, я анонсировал, что возвращаюсь к движку, но как-то не пошло. Но последние две недели я снова предпринимаю попытки находить на него время, и похоже, что на этот раз таки удастся войти в рабочую струю.
В Джуди я делал реально крутые по моему мнению штуки, о которых не стыдно рассказать. С другой стороны, за это время я изменил взгляд на некоторые вещи, поэтому оставайтесь на связи, будет интересно. Сами «алмазики» можно подглядеть на github. Как это часто бывает с пет-прожектами, код там зачастую не самый лучший в виду урывочности написания, но ставить звёзды и фоловить не стесняемся :)
3. #GitTern.
Идея написать очередной клиент для git, заточенный под конкретные нужды, у меня родилась в феврале, когда мы только начинали работать над Encased и пытались подружить художников с системой контроля версий. Задумка потеряла актуальность, когда мы всей компанией перешли на PlasticSCM, но для своих личных нужд я всё равно, само собой, буду использовать git. И теперь, когда мне нужно комитить из разных операционных систем (Judy кроссплатформенный движок), я волей-неволей возвращаюсь к этой идее. Думаю, в самое ближайшее время добью его до минимального функционала и пересяду на него. В отличие от движка, который я пока не решил делать свободным, GitTern полностью open-source по MIT лицензии.
4. #Ameba.
Aggregate MEssage BAr — это агрегатор популярных мессенджеров и ещё один проект, о начале работ над которым я радостно раструбил в блоге, но который, похоже, пока ещё какое-то время полежит на полке.
5. Английский.
В числе личных проектов я также решил перечислить занятия английским, поскольку это непосредственно связано с моей прокачкой в профессиональном смысле. Сейчас я три раза в неделю занимаюсь с преподавателем онлайн, читаю Кинга на бумаге и собираюсь переводить этот блог на английский на Medium.
6. Ключевые слова Shodan’а.
Ещё один важный для меня проект по самопрокачке — пройтись по ключевым словам Андрея Аксёнова. Это, конечно, не прямое руководство к действию, но отличные дорожные ориентиры, по которым я всё собираюсь начать заполнять пробелы в своих знаниях, но никак не начну. Может быть, кто-нибудь из читателей тоже заинтересуется, и вместе будет проще?
Обсудить
Ещё раз курсы по геймдизайну
#реклама
Хотели записаться на курс геймдизайна, про который я рассказывал в октябре, но замотались и не успели? Что ж, у меня для вас хорошая новость: 23 января начнётся новый поток. Как раз отдохнёте маленечко в новогодние праздники, переведёте дух — и вперёд, врываться в индустрию!
Тот же четырёхмесячный курс от Skillfactory с упором на практику на всех этапах: от концепта и механики до монетизации и продвижения.
Тот же преподаватель — Руслан Казанцев, лид геймдизайнер финской студии BON Games с восьмилетним багажом опыта.
Но новая цена. В честь нового года действует скидочка 40% на весь курс.
Записаться по ссылочке: https://goo.gl/FGC6wS
#реклама
Хотели записаться на курс геймдизайна, про который я рассказывал в октябре, но замотались и не успели? Что ж, у меня для вас хорошая новость: 23 января начнётся новый поток. Как раз отдохнёте маленечко в новогодние праздники, переведёте дух — и вперёд, врываться в индустрию!
Тот же четырёхмесячный курс от Skillfactory с упором на практику на всех этапах: от концепта и механики до монетизации и продвижения.
Тот же преподаватель — Руслан Казанцев, лид геймдизайнер финской студии BON Games с восьмилетним багажом опыта.
Но новая цена. В честь нового года действует скидочка 40% на весь курс.
Записаться по ссылочке: https://goo.gl/FGC6wS
Скрипты в Encased 1.1
#код
Что-то у меня одновременно много людей заказали размещения, поэтому чтобы канал не превращался в сплошную рекламу, придётся делать посты почаще на этой неделе.
А давайте поговорим, например, про скрипты. С прошлого раза, когда я про них рассказывал, они претерпели некоторые изменения и это должно быть интересно. Напомню, что у нас скрипты — это экземпляры классов, унаследованных от Script, которые имеют функции Start() и Update(), могут содержать сериализуемые поля, которые выполняют роль эдаких «локальных переменных», а также скрипты умеют подписываться на различные события от сущностей в мире.
Предполагалось, что на события можно как подписываться, так и отписываться в реалтайме, а текущее состояние подписок также бы попадало в файл сохранения. И всё было бы хорошо, если бы не одно «но». Судя по вопросам и фиче-реквестам, которые я получал, оказалось, что скриптеры не понимают концепт подписок на интуитивном уровне.
Их основная идея была в том, что мы подписываемся на нужные события в Start и потом, по мере обработки событий, отписываемся от них или подписываемся на новые. При этом функция Start, разумеется, больше никогда не вызовется. Даже после нажатия Сохранить/Загрузить мы получим абсолютно то же состояние подписок, которое было до этого. Но скриптеры ожидают, что они могут сохраниться, добавить подписку в функции Start, загрузиться и обработать свежедобавленый эвент. Этой ситуации у нас пока не случилось, но я предвосхищаю, что мне бы пришёл вопрос «а нельзя ли сделать, чтобы после загрузки Start() отрабатывал ещё раз?». То, что тогда получится по 2 подписки и это вообще ломает всю концепцию скриптов, никого бы не смутило.
Такое поведение скриптеров может показаться глупым, но дело в том, что если что-то может быть понято неправильно, оно обязательно будет понято не так, а я не смогу со свечкой стоять над каждым скриптом в игре. Моя задача в первую очередь не в том, чтобы сделать крутую вещь в себе, а в том, чтобы поддержать удобный пайплайн для скриптеров. Поэтому от подписок в реалтайме пришлось отказаться. Все подписки теперь статичны и устанавливаются при инициализации скрипта. Причём ручное навешивание делегатов возможно теперь только в специально отведённой для этого функции и является запасным способом. А рекомендуемым способом теперь является простая пометка функций атрибутами.
Например, мы помечаем функцию атрибутом
что означает, что функция отработает, когда мы нажмём на рубильник в игре. LeverSwitch — это константа, содержащая уникальный guid рубильника, который доступен из скриптов, потому что у нас сделана кодогенерация констант (с поддержкой последующего переименования, разумеется).
Реальной отписки от этой функции причём не существует, но она эмулируется через проверку глобальной переменной внутри тела функции или с помощью атрибутов. Вроде таких:
или ещё проще
Последний вариант означает, что функция выполнится только один раз, а 0 нужен для уникальной пометки этой функции (чтобы можно было безопасно переименовать функцию и ничего не сломать). В пределах одного файла у других функций, соответственно будет OnlyOnce(1), OnlyOnce(2) и так далее.
На поверку оказывается, что если функция не вызывается по причине того, что на её запуске стоит тест переменной, которая в данный момент не включена, то это намного проще воспринимается скриптерами, чем функция, которая не вызывается, потому что на неё никто не подписывался в истории этого сейва. Так что такая модель выглядит более перспективной в плане поддержки игры и накатывания апдейтов. Посмотрим, как она покажет себя в бою, а пока всем счастливого рождества!
Обсудить
#код
Что-то у меня одновременно много людей заказали размещения, поэтому чтобы канал не превращался в сплошную рекламу, придётся делать посты почаще на этой неделе.
А давайте поговорим, например, про скрипты. С прошлого раза, когда я про них рассказывал, они претерпели некоторые изменения и это должно быть интересно. Напомню, что у нас скрипты — это экземпляры классов, унаследованных от Script, которые имеют функции Start() и Update(), могут содержать сериализуемые поля, которые выполняют роль эдаких «локальных переменных», а также скрипты умеют подписываться на различные события от сущностей в мире.
Предполагалось, что на события можно как подписываться, так и отписываться в реалтайме, а текущее состояние подписок также бы попадало в файл сохранения. И всё было бы хорошо, если бы не одно «но». Судя по вопросам и фиче-реквестам, которые я получал, оказалось, что скриптеры не понимают концепт подписок на интуитивном уровне.
Их основная идея была в том, что мы подписываемся на нужные события в Start и потом, по мере обработки событий, отписываемся от них или подписываемся на новые. При этом функция Start, разумеется, больше никогда не вызовется. Даже после нажатия Сохранить/Загрузить мы получим абсолютно то же состояние подписок, которое было до этого. Но скриптеры ожидают, что они могут сохраниться, добавить подписку в функции Start, загрузиться и обработать свежедобавленый эвент. Этой ситуации у нас пока не случилось, но я предвосхищаю, что мне бы пришёл вопрос «а нельзя ли сделать, чтобы после загрузки Start() отрабатывал ещё раз?». То, что тогда получится по 2 подписки и это вообще ломает всю концепцию скриптов, никого бы не смутило.
Такое поведение скриптеров может показаться глупым, но дело в том, что если что-то может быть понято неправильно, оно обязательно будет понято не так, а я не смогу со свечкой стоять над каждым скриптом в игре. Моя задача в первую очередь не в том, чтобы сделать крутую вещь в себе, а в том, чтобы поддержать удобный пайплайн для скриптеров. Поэтому от подписок в реалтайме пришлось отказаться. Все подписки теперь статичны и устанавливаются при инициализации скрипта. Причём ручное навешивание делегатов возможно теперь только в специально отведённой для этого функции и является запасным способом. А рекомендуемым способом теперь является простая пометка функций атрибутами.
Например, мы помечаем функцию атрибутом
[OnUsed(Guids.Levels.MagicBalls.LeverSwitch)]
что означает, что функция отработает, когда мы нажмём на рубильник в игре. LeverSwitch — это константа, содержащая уникальный guid рубильника, который доступен из скриптов, потому что у нас сделана кодогенерация констант (с поддержкой последующего переименования, разумеется).
Реальной отписки от этой функции причём не существует, но она эмулируется через проверку глобальной переменной внутри тела функции или с помощью атрибутов. Вроде таких:
[If(BunkerVariables.LiftEnabled)]
или ещё проще
[OnlyOnce(0)]
Последний вариант означает, что функция выполнится только один раз, а 0 нужен для уникальной пометки этой функции (чтобы можно было безопасно переименовать функцию и ничего не сломать). В пределах одного файла у других функций, соответственно будет OnlyOnce(1), OnlyOnce(2) и так далее.
На поверку оказывается, что если функция не вызывается по причине того, что на её запуске стоит тест переменной, которая в данный момент не включена, то это намного проще воспринимается скриптерами, чем функция, которая не вызывается, потому что на неё никто не подписывался в истории этого сейва. Так что такая модель выглядит более перспективной в плане поддержки игры и накатывания апдейтов. Посмотрим, как она покажет себя в бою, а пока всем счастливого рождества!
Обсудить
Надо больше инфы по ECS
#реклама
Как вы знаете, Entity Component System штука не новая, но переживает сейчас невиданный пик популярности. Если бы мы начинали делать Encased сегодня, я бы наверняка задействовал юнитёвую ECS, но год назад она была ещё сырой, и мне пришлось городить свою модульную систему. Впрочем, она только внешне напоминает ECS, но ей не является, поскольку ECS это в первую очередь про расположение данных в памяти и производительность, а у меня такой задачи не стояло. Зато стояли сроки. Но вот в своём движке я, возможно, напишу уже что-то более близкое к трушной реализации. Потому что кто, чёрт возьми, не хочет кайфовую штуку в своём движке? Пописать что-то клёвое губа у меня, знаете, не дура.
Так вот, прикиньте, оказывается, есть целый телеграмм-канал, целиком и полностью посвящённый одной только ECS. Единое место, где собираются все статьи и видео по теме. Если вы подумывали над тем, чтобы разобраться и научиться пользоваться, или даже написать свою реализацию, то вам непременно стоит подписаться: https://yangx.top/ecscomrade
#реклама
Как вы знаете, Entity Component System штука не новая, но переживает сейчас невиданный пик популярности. Если бы мы начинали делать Encased сегодня, я бы наверняка задействовал юнитёвую ECS, но год назад она была ещё сырой, и мне пришлось городить свою модульную систему. Впрочем, она только внешне напоминает ECS, но ей не является, поскольку ECS это в первую очередь про расположение данных в памяти и производительность, а у меня такой задачи не стояло. Зато стояли сроки. Но вот в своём движке я, возможно, напишу уже что-то более близкое к трушной реализации. Потому что кто, чёрт возьми, не хочет кайфовую штуку в своём движке? Пописать что-то клёвое губа у меня, знаете, не дура.
Так вот, прикиньте, оказывается, есть целый телеграмм-канал, целиком и полностью посвящённый одной только ECS. Единое место, где собираются все статьи и видео по теме. Если вы подумывали над тем, чтобы разобраться и научиться пользоваться, или даже написать свою реализацию, то вам непременно стоит подписаться: https://yangx.top/ecscomrade
Telegram
ECS Comrade
Welcome, comrade, to ECS Community! This channel is for those who study, create and develop projects based on a system of entities and components. All stuff for studying ECS are dropped here
Feedback: @ECSCBot
Chat: @ecschat
Feedback: @ECSCBot
Chat: @ecschat
Gamedev новости
#реклама
Что читать, пока ждёте очередной лонгпост от меня? А вот хотя бы свеженький канальчик с основными новостями индустрии, ссылками на полезные статьи и всяким таким прочим про геймдев. Коротко, но зато по делу и каждый день. Автор вообще топит за краткость, и меня просил много не писать, поэтому без лишних представлений, встречайте: @Game_Dev
#реклама
Что читать, пока ждёте очередной лонгпост от меня? А вот хотя бы свеженький канальчик с основными новостями индустрии, ссылками на полезные статьи и всяким таким прочим про геймдев. Коротко, но зато по делу и каждый день. Автор вообще топит за краткость, и меня просил много не писать, поэтому без лишних представлений, встречайте: @Game_Dev
Байка про кранчи и хаки
#лайт
Признаюсь честно, был очень велик соблазн в последнем посте 2018-го подвести какие-то итоги года. Но потом я подумал: да какие могут быть итоги календарного года в геймдеве? Итоги стоит подводить, когда завершён какой-то действительно важный этап или проект, а новый год для разработчика, что для лошади свадьба. Праздники для нас зачастую означают лишь дедлайн тематического обновления, что нередко перерастает в кранчи. Так что запах хвои и мандарин непременно навевает мне и о переработках.
В этом году конец года выдался спокойный, хотя я и планирую поработать немного на каникулах, но вот два года назад бой курантов чуть не застал меня в дебагере. Я был тогда в маленькой инди-команде и мы большой рождественский апдейт, планируемый к 25 декабря, выпустили только 30-го числа, а потому большую часть 31-го занимались мониторингом ошибок и хотфиксами. Мы закончили работать лишь в 22:00 (и я даже успел приехать на торжества), а у остальных ребят в другой таймзоне на часах было и вовсе 23:00. Забавно было потом читать комментарии игроков о том, почему апдейт, который в том числе добавлял шапки Санты, вышел в канун нового года, а не на рождество. Они даже нагуглили, что разработчики из России, а православное рождество отмечается 7 января, на чём и сошлись. Но мысль о том, что мы просто не успели к 25-му декабря, никому в голову даже не пришла.
Впрочем, байка будет не про это. Мысли о кранчах навеяли мне другой случай, это будет история о моём самом злостном хаке за всю карьеру игрового программиста. Я тогда ещё был зелёным студентом и профессионально работал меньше года на полставочки. А меня взяли и отправили сразу с места в С++, портировать одну из наших матч3-игр на первый iPad, который только что представил Стив Джобс в Сан-Франциско. Ну хотя как портировать? По сути заново переписать с Делфи на кресты. А я и то и другое до этого только в универе на лабах-то и видел по большому счёту. Благо хоть не в одиночку на проект бросили, а со старшим товарищем.
Цимес ситуации в том, что iPad анонсировали 27 января, а уже 3 апреля начинались его продажи; и те приложения, что успевали к открытию, получали огромные ништяки в плане фичеринга. И вот мы сидим в последнюю ночь, кранчуем. Уже, вроде, всё сделали, но остаётся один странный баг.
Среди всего прочего, я отвечал за человечков, которые ходят снизу игрового поля и уносят с него строительный материал, который вылетает с поля во время игры. Это была чисто декоративная функция, но добавляющая живости в игру. В конце каждого уровня выпадал большой камень, который тащить человечки могли только втроём. На скрине выше как раз запечатлен этот момент. Так вот, несмотря на то, что при падении этого камня на пол в коде было явно захардкожена цифра 3 для спауна новых работников, иногда почему-то из домика выходило только двое. Они подходили к камню и вечно стояли там без дела, дожидаясь третьего товарища, который почему-то не хотел выходить из дома.
Дело уже к третьему часу ночи, общими усилиями найти баг не можем, но версию нужно отгружать. Что делать? Ну, в общем, я просто беру и пишу костыль, что после спауна 3 человек, начинаю отсчитывать время, и если через 10 секунд камень не начали тащить, то я спауню ещё одного человечка, через 10 секунд ещё одного и так далее, до тех пор, пока камень не сдвинется с места… И это ушло в релиз.
На следующий день старший товарищ нашёл баг в моём коде. Разумеется, я просто по неопытности покараптил память, запихав длинную строчку в маленький массив. Мы исправили косяк в ближайшем апдейте, но то решение навсегда останется со мной, как самый злостный хак в карьере. А какой костыль у вас был самым диким? Поделитесь в комментариях.
#лайт
Признаюсь честно, был очень велик соблазн в последнем посте 2018-го подвести какие-то итоги года. Но потом я подумал: да какие могут быть итоги календарного года в геймдеве? Итоги стоит подводить, когда завершён какой-то действительно важный этап или проект, а новый год для разработчика, что для лошади свадьба. Праздники для нас зачастую означают лишь дедлайн тематического обновления, что нередко перерастает в кранчи. Так что запах хвои и мандарин непременно навевает мне и о переработках.
В этом году конец года выдался спокойный, хотя я и планирую поработать немного на каникулах, но вот два года назад бой курантов чуть не застал меня в дебагере. Я был тогда в маленькой инди-команде и мы большой рождественский апдейт, планируемый к 25 декабря, выпустили только 30-го числа, а потому большую часть 31-го занимались мониторингом ошибок и хотфиксами. Мы закончили работать лишь в 22:00 (и я даже успел приехать на торжества), а у остальных ребят в другой таймзоне на часах было и вовсе 23:00. Забавно было потом читать комментарии игроков о том, почему апдейт, который в том числе добавлял шапки Санты, вышел в канун нового года, а не на рождество. Они даже нагуглили, что разработчики из России, а православное рождество отмечается 7 января, на чём и сошлись. Но мысль о том, что мы просто не успели к 25-му декабря, никому в голову даже не пришла.
Впрочем, байка будет не про это. Мысли о кранчах навеяли мне другой случай, это будет история о моём самом злостном хаке за всю карьеру игрового программиста. Я тогда ещё был зелёным студентом и профессионально работал меньше года на полставочки. А меня взяли и отправили сразу с места в С++, портировать одну из наших матч3-игр на первый iPad, который только что представил Стив Джобс в Сан-Франциско. Ну хотя как портировать? По сути заново переписать с Делфи на кресты. А я и то и другое до этого только в универе на лабах-то и видел по большому счёту. Благо хоть не в одиночку на проект бросили, а со старшим товарищем.
Цимес ситуации в том, что iPad анонсировали 27 января, а уже 3 апреля начинались его продажи; и те приложения, что успевали к открытию, получали огромные ништяки в плане фичеринга. И вот мы сидим в последнюю ночь, кранчуем. Уже, вроде, всё сделали, но остаётся один странный баг.
Среди всего прочего, я отвечал за человечков, которые ходят снизу игрового поля и уносят с него строительный материал, который вылетает с поля во время игры. Это была чисто декоративная функция, но добавляющая живости в игру. В конце каждого уровня выпадал большой камень, который тащить человечки могли только втроём. На скрине выше как раз запечатлен этот момент. Так вот, несмотря на то, что при падении этого камня на пол в коде было явно захардкожена цифра 3 для спауна новых работников, иногда почему-то из домика выходило только двое. Они подходили к камню и вечно стояли там без дела, дожидаясь третьего товарища, который почему-то не хотел выходить из дома.
Дело уже к третьему часу ночи, общими усилиями найти баг не можем, но версию нужно отгружать. Что делать? Ну, в общем, я просто беру и пишу костыль, что после спауна 3 человек, начинаю отсчитывать время, и если через 10 секунд камень не начали тащить, то я спауню ещё одного человечка, через 10 секунд ещё одного и так далее, до тех пор, пока камень не сдвинется с места… И это ушло в релиз.
На следующий день старший товарищ нашёл баг в моём коде. Разумеется, я просто по неопытности покараптил память, запихав длинную строчку в маленький массив. Мы исправили косяк в ближайшем апдейте, но то решение навсегда останется со мной, как самый злостный хак в карьере. А какой костыль у вас был самым диким? Поделитесь в комментариях.
Гитхаб-счастье!
#лайт
Горячо любимый мною Microsoft, взявший в последние годы курс на опенсорс, продолжает меня радовать. Не так давно они возглавили крупнейший вэб-хостинг опенсорс-проектов GitHub, и на днях провели в нём первую крупную реформу: сменили тарифные планы.
Главное изменение касается бесплатных аккаунтов. Если раньше бесплатно можно было вести только публичные репозитории, то теперь можно создавать неограниченное количество приватных проектов до 3 пользователей. Напомню, что GitHub, в отличие от большинства аналогов, никак не ограничивает дисковое пространство, так что количество пользователей — это единственное условие. А трёх пользователей зачастую достаточно для современных инди-команд.
Конечно, приватные репозитории можно было заводить бесплатно и до этого на том же BitBucket, причём аж до 5 пользователей; но нововведение от GitHub — это счастье, прежде всего, для одиночек. Просто если вы программист и занимались когда-нибудь опенсорс разработкой, то у вас уже есть аккаунт и репозитории на GitHub. Если теперь вы решите пилить что-то коммерческое для себя, то вам не надо никуда ходить, можно завести приватный репозиторий здесь же. И даже можно в случае чего подключить к проекту художника или второго программиста.
Кстати, мало кто знает, но публичный репозиторий не означает, что проект опенсорный. Вам никто не мешает положить в репозиторий свою проприетарную лицензию. Более того, отсутствие какой-либо лицензии (что встречается повсеместно на гитхаб) по умолчанию оставляет все права на код за автором. Такой код можно просматривать, но нельзя копировать или перепродавать. Так что те, кто не боялся, что его код украдут, могли спокойно вести коммерческую разработку на гитхаб и до этого. Как, например, делал я. Между прочим, всем рекомендую завести публичные репозитории. Это отличное упражнение, позволяющее в короткие сроки избавиться от комплекса «здесь не прибрано», когда люди стесняются показывать неидеальный код, и в итоге вообще ничего никому не показывают.
А на картинке сверху моя плюшевая игрушка в виде маскота Github. Да, у меня и такая есть. Правда милота?
Обсудить
#лайт
Горячо любимый мною Microsoft, взявший в последние годы курс на опенсорс, продолжает меня радовать. Не так давно они возглавили крупнейший вэб-хостинг опенсорс-проектов GitHub, и на днях провели в нём первую крупную реформу: сменили тарифные планы.
Главное изменение касается бесплатных аккаунтов. Если раньше бесплатно можно было вести только публичные репозитории, то теперь можно создавать неограниченное количество приватных проектов до 3 пользователей. Напомню, что GitHub, в отличие от большинства аналогов, никак не ограничивает дисковое пространство, так что количество пользователей — это единственное условие. А трёх пользователей зачастую достаточно для современных инди-команд.
Конечно, приватные репозитории можно было заводить бесплатно и до этого на том же BitBucket, причём аж до 5 пользователей; но нововведение от GitHub — это счастье, прежде всего, для одиночек. Просто если вы программист и занимались когда-нибудь опенсорс разработкой, то у вас уже есть аккаунт и репозитории на GitHub. Если теперь вы решите пилить что-то коммерческое для себя, то вам не надо никуда ходить, можно завести приватный репозиторий здесь же. И даже можно в случае чего подключить к проекту художника или второго программиста.
Кстати, мало кто знает, но публичный репозиторий не означает, что проект опенсорный. Вам никто не мешает положить в репозиторий свою проприетарную лицензию. Более того, отсутствие какой-либо лицензии (что встречается повсеместно на гитхаб) по умолчанию оставляет все права на код за автором. Такой код можно просматривать, но нельзя копировать или перепродавать. Так что те, кто не боялся, что его код украдут, могли спокойно вести коммерческую разработку на гитхаб и до этого. Как, например, делал я. Между прочим, всем рекомендую завести публичные репозитории. Это отличное упражнение, позволяющее в короткие сроки избавиться от комплекса «здесь не прибрано», когда люди стесняются показывать неидеальный код, и в итоге вообще ничего никому не показывают.
А на картинке сверху моя плюшевая игрушка в виде маскота Github. Да, у меня и такая есть. Правда милота?
Обсудить
О трамвайчиках
#лайт
Давайте отдохнём немного от программирования и поговорим про трамвайчики. Все же любят поезда, да? Я решил побыть сегодня Ильёй Варламовым и поделиться путевыми наблюдениями об урбанистике.
Наверное, такое решение для трамвайных путей много, где встречается, но я увидел впервые в Касабланке. Здесь для трамваев проложены отдельные дороги, по которым машины не ездят. Не полосы, а именно отдельные дороги: даже если трамвайная и автомобильная дороги идут параллельно, они обязательно разделяются тротуаром, бордюром или посадкой деревьев. А вот трамвайная дорога от пешеходной зоны бордюром не отделяется!
Ограждения попросту не нужны, поскольку машин на этой дороге нет, а трамвай с рельс сойти не может. Для людей же получается огромный пешеходный проспект, который одинаково просто пересекать, как на своих двоих, так и на инвалидной коляске или велике. Да, велосипедисты используют трамвайные пути, как одну большую велодорожку, потому что почему бы и нет? Пешеходы, конечно, гуляют не по рельсам, а по тротуару, но если сравнивать с обычными улицами, то гораздо приятнее идти по визуально широкому проспекту, где или нет машин вовсе, или они спрятаны за полосой деревьев. Ни шума, ни выхлопных газов, хороший обзор на архитектуру и ощущение простора. Изредка проезжающие стильные трамваи на электротяге совсем не портят картину и не раздражают. Движутся они не очень быстро и уступают пешеходам. Словом, кайфово.
Вот такая заметка получилась. Немножко не формат, но больше такого можно читать у меня в твиттере. Там я, конечно, в основном просто старчески ворчу на всех и вся, но иногда и что-то интересное бывает. Ну и чатик как всегда работает.
#лайт
Давайте отдохнём немного от программирования и поговорим про трамвайчики. Все же любят поезда, да? Я решил побыть сегодня Ильёй Варламовым и поделиться путевыми наблюдениями об урбанистике.
Наверное, такое решение для трамвайных путей много, где встречается, но я увидел впервые в Касабланке. Здесь для трамваев проложены отдельные дороги, по которым машины не ездят. Не полосы, а именно отдельные дороги: даже если трамвайная и автомобильная дороги идут параллельно, они обязательно разделяются тротуаром, бордюром или посадкой деревьев. А вот трамвайная дорога от пешеходной зоны бордюром не отделяется!
Ограждения попросту не нужны, поскольку машин на этой дороге нет, а трамвай с рельс сойти не может. Для людей же получается огромный пешеходный проспект, который одинаково просто пересекать, как на своих двоих, так и на инвалидной коляске или велике. Да, велосипедисты используют трамвайные пути, как одну большую велодорожку, потому что почему бы и нет? Пешеходы, конечно, гуляют не по рельсам, а по тротуару, но если сравнивать с обычными улицами, то гораздо приятнее идти по визуально широкому проспекту, где или нет машин вовсе, или они спрятаны за полосой деревьев. Ни шума, ни выхлопных газов, хороший обзор на архитектуру и ощущение простора. Изредка проезжающие стильные трамваи на электротяге совсем не портят картину и не раздражают. Движутся они не очень быстро и уступают пешеходам. Словом, кайфово.
Вот такая заметка получилась. Немножко не формат, но больше такого можно читать у меня в твиттере. Там я, конечно, в основном просто старчески ворчу на всех и вся, но иногда и что-то интересное бывает. Ну и чатик как всегда работает.
Подробности про командную строку
#код
Запилил на днях по работе командную строку с проверкой синтаксиса и автодополнением и похвастался этим в чатике. Народ проявил интерес и поэтому рассказываю подробнее.
Нужна эта штука для двух вещей. Во-первых, сценаристы, собирающие диалоги в редакторе, должны иметь возможность проверять доступность вариантов ответа (например, реплика возможна только при заданном уровне интеллекта или после выполнения квеста), а также вызывать скрипты при ответах. Во-вторых, для разработки нужна классическая игровая консоль для ввода читов и отладки. Чтобы разом покрыть оба этих юзкейса нужно написать нехитрый интерпретатор строки. Разумеется, он не будет поддерживать все фишки C#, а только некоторый базовый сабсет, вроде функций, операторов и скобочек.
Теперь о реализации. Несмотря на кажущуюся сложность задачи, имплементация у меня до боли простая и занимает чуть более тысячи строк. Первый элемент системы — это, конечно, лексический анализатор. Который у меня в коде какого-то фига называется Parser (надо не забыть переименовать в Lexer, а то чё я, как наркоман). Лексер представляет собой одну единственную функцию-генератор, которая в цикле читает символы строки и возвращает по одной токены лексем, которыми могут быть:
Между лексемами могут быть пробелы, они игнорируются. Помимо типа, токен также хранит начало и длину фрагмента внутри входной строки (чтобы подсветить красным место, в котором произошла ошибка) и поле типа object для дополнительной информации: для value это считанное значение, для оператора — информация о том, какой конкретно оператор и т.п. Единственный нюанс, при чтении знака минус, нужно взглянуть на то, какой токен был перед этим: если значение, идентификатор или закрывающая скобка, то это оператор минус, в противном случае начало отрицательного числа.
Едем дальше. Непосредственно сам интерпретатор совмещённый с валидатором. Он у меня однопроходный, то есть я читаю очередь лексем слева направо и сразу же выполняю. Командная строка может выполнять только выражения. Выражение — это один или несколько операндов, разделённых операторами. Например,
или просто
Когда мы дошли до конца выражения (конец строки, запятая или закрывающая скобка), мы выполняем операторы в порядке их приоритета («схлопываем» по два операнда, пока не останется только один).
Операндом может выступать как значение, так и другое выражение в скобках. Поэтому если наткнёмся на открывающуюся скобку, то просто запускаем процесс парсинга вложенного выражения рекурсивно. И также операндом может выступать цепочка идентификаторов, типа такой:
В данном случае мы тоже выполняем всё последовательно. Сначала ищем объект среди глобальных. У меня разрешены только классы скриптов (считай, синглтоны) и enum’ы. Затем на каждый доступ через точку достаём через рефлекшн соответствующий member класса, а при вызове функции запускаем сперва вложенный парсинг выражений-аргументов через запятую.
Собственно, всё. Ну ещё есть оператор присваивания, который умеет вызывать сеттер для поля или свойства, но теперь точно всё.
Валидация происходит точно также, как и выполнение, только в «холостом» режиме: вместо честных вызовов функций и операторов, мы возвращаем объект-заглушку, которая знает какого типа должен быть результат. Этой информации достаточно, чтобы проверить весь синтаксис.
Автодополнение же сделано запуском валидации строки, в которую в определённом месте вставлен символ многоточие. При разборе
лексер вернёт не идентификатор «Pl», а специальную лексему типа Autocomplete «Pl...». Ну а синтаксический анализатор, если наткнётся на эту лексему там, где предполагается идентификатор, посмотрит, какие вообще есть варианты, и если что-то подходит, то бросит AutoCompleteException, содержащий остаток строки. Заменой выделенного текста на автодополненный вариант занимается уже гуишный контрол наверху.
#код
Запилил на днях по работе командную строку с проверкой синтаксиса и автодополнением и похвастался этим в чатике. Народ проявил интерес и поэтому рассказываю подробнее.
Нужна эта штука для двух вещей. Во-первых, сценаристы, собирающие диалоги в редакторе, должны иметь возможность проверять доступность вариантов ответа (например, реплика возможна только при заданном уровне интеллекта или после выполнения квеста), а также вызывать скрипты при ответах. Во-вторых, для разработки нужна классическая игровая консоль для ввода читов и отладки. Чтобы разом покрыть оба этих юзкейса нужно написать нехитрый интерпретатор строки. Разумеется, он не будет поддерживать все фишки C#, а только некоторый базовый сабсет, вроде функций, операторов и скобочек.
Теперь о реализации. Несмотря на кажущуюся сложность задачи, имплементация у меня до боли простая и занимает чуть более тысячи строк. Первый элемент системы — это, конечно, лексический анализатор. Который у меня в коде какого-то фига называется Parser (надо не забыть переименовать в Lexer, а то чё я, как наркоман). Лексер представляет собой одну единственную функцию-генератор, которая в цикле читает символы строки и возвращает по одной токены лексем, которыми могут быть:
Value (строки, числа, true и false),
Identifier,
Dot,
Comma,
OpenBracket,
ClosedBracket,
Operator,
AssignmentOperator,
EndOfLine
Между лексемами могут быть пробелы, они игнорируются. Помимо типа, токен также хранит начало и длину фрагмента внутри входной строки (чтобы подсветить красным место, в котором произошла ошибка) и поле типа object для дополнительной информации: для value это считанное значение, для оператора — информация о том, какой конкретно оператор и т.п. Единственный нюанс, при чтении знака минус, нужно взглянуть на то, какой токен был перед этим: если значение, идентификатор или закрывающая скобка, то это оператор минус, в противном случае начало отрицательного числа.
Едем дальше. Непосредственно сам интерпретатор совмещённый с валидатором. Он у меня однопроходный, то есть я читаю очередь лексем слева направо и сразу же выполняю. Командная строка может выполнять только выражения. Выражение — это один или несколько операндов, разделённых операторами. Например,
a + b * c + d
или просто
a
Когда мы дошли до конца выражения (конец строки, запятая или закрывающая скобка), мы выполняем операторы в порядке их приоритета («схлопываем» по два операнда, пока не останется только один).
Операндом может выступать как значение, так и другое выражение в скобках. Поэтому если наткнёмся на открывающуюся скобку, то просто запускаем процесс парсинга вложенного выражения рекурсивно. И также операндом может выступать цепочка идентификаторов, типа такой:
Foo.bar.foo(a + b, c).foo.bar
В данном случае мы тоже выполняем всё последовательно. Сначала ищем объект среди глобальных. У меня разрешены только классы скриптов (считай, синглтоны) и enum’ы. Затем на каждый доступ через точку достаём через рефлекшн соответствующий member класса, а при вызове функции запускаем сперва вложенный парсинг выражений-аргументов через запятую.
Собственно, всё. Ну ещё есть оператор присваивания, который умеет вызывать сеттер для поля или свойства, но теперь точно всё.
Валидация происходит точно также, как и выполнение, только в «холостом» режиме: вместо честных вызовов функций и операторов, мы возвращаем объект-заглушку, которая знает какого типа должен быть результат. Этой информации достаточно, чтобы проверить весь синтаксис.
Автодополнение же сделано запуском валидации строки, в которую в определённом месте вставлен символ многоточие. При разборе
GlobalVars.Pl…
лексер вернёт не идентификатор «Pl», а специальную лексему типа Autocomplete «Pl...». Ну а синтаксический анализатор, если наткнётся на эту лексему там, где предполагается идентификатор, посмотрит, какие вообще есть варианты, и если что-то подходит, то бросит AutoCompleteException, содержащий остаток строки. Заменой выделенного текста на автодополненный вариант занимается уже гуишный контрол наверху.
Курсы геймдизайна
#реклама
Знаете, чем занятия с живым человеком лучше самостоятельных? Помогает соблюдать регулярность и систематичность. Я вот перед новым годом писал, что занимаюсь английским с преподователем через вэбку и также собираюсь изучать темы по списку ключевых слов Андрея Аксёнова. И знаете что? По английскому у меня есть заметный прогресс, а ключевые слова я всё ещё собираюсь начать изучать.
И поэтому я не устану рекламировать курсы по геймдизайну от Skillfactory. Это отличный вариант для тех, кто всё собирается вкатиться в отрасль, но либо руки не доходят усесться плотно, либо не хватает систематизации. На этих курсах лид дизайнер финской BON Games объяснит и поможет вам пройти через все этапы геймдизайна: от разработки игровой мехаики до монетизации и планирования. Регулярные занятия каждую неделю в сочетании с активным участием класса и фидбеком от преподователя не дадут сбиться с ритма на протяжении всех 4 месяцев. А стартует всё это уже 11 февраля, так что записывайся сейчас: https://goo.gl/FGC6wS
#реклама
Знаете, чем занятия с живым человеком лучше самостоятельных? Помогает соблюдать регулярность и систематичность. Я вот перед новым годом писал, что занимаюсь английским с преподователем через вэбку и также собираюсь изучать темы по списку ключевых слов Андрея Аксёнова. И знаете что? По английскому у меня есть заметный прогресс, а ключевые слова я всё ещё собираюсь начать изучать.
И поэтому я не устану рекламировать курсы по геймдизайну от Skillfactory. Это отличный вариант для тех, кто всё собирается вкатиться в отрасль, но либо руки не доходят усесться плотно, либо не хватает систематизации. На этих курсах лид дизайнер финской BON Games объяснит и поможет вам пройти через все этапы геймдизайна: от разработки игровой мехаики до монетизации и планирования. Регулярные занятия каждую неделю в сочетании с активным участием класса и фидбеком от преподователя не дадут сбиться с ритма на протяжении всех 4 месяцев. А стартует всё это уже 11 февраля, так что записывайся сейчас: https://goo.gl/FGC6wS
SOLIDные рассуждения
#код
Месяц назад я твитнул, что, дескать, как только слышу от соискателя или работодателя в геймдеве что-нибудь про SOLID, так сразу автоматически помечаю их в своей голове как нубов, либо поехавших. С тех пор мне пришлось пару раз подискутировать на эту тему в разных уголках интернета, и я решил, что стоит уже это оформить в отдельный пост.
Понятно, что это своего рода упрощение и навешивание ярлыков, которое отражает ситуацию лишь до определённой точности, но оно взято не из воздуха, а основывается на наблюдениях за реальным положением дел. И главный мой тезис в том, что в геймдеве на реальных проектах принципами SOLID никто никогда не руководствуется. Соответственно, если человек декларирует их своими ценностями, то он либо новичок в области, начитавшийся умных слов и книжек, но ещё не нюхавший пороху как следует на практике; либо же, мягко говоря, довольно неординарный геймдевелопер. То есть наглухо поехавший с моей точки зрения.
Поехавшие, в свою очередь, делятся, на две основные категории. Первые — это люди, пришедшие из энтерпрайза. Я никогда в энтерпрайзе не работал, но похоже, что там написание абстрактного кода эволюционно более привлекательная стратегия. Я ничего против этого не имею, но когда эти люди приходят в геймдев, с ними бывает тяжело сработаться, так как это зачастую сплошное ООП головного мозга. Там, где типичный программист из кровавого энтерпрайза в рубашке с длинными рукавами заведёт десять интерфейсов и фабрику фабрик; типичный геймдевелопер в перепачканной пиццой футболке вооружится принципами KISS и YAGNI и удалит это всё нахрен, написав взамен простой и понятный класс, решающий конкретную задачу. Пусть и наплевав при этом на принцип открытости/закрытости, разделения интерфейсов и другие святая святых ООП. То есть, конечно, наверняка где-то в природе существуют игры, написанные полностью по канонам SOLID. Но, во-первых, я такого не встречал, а во-вторых, боюсь представить, что там за монструозная кодобаза, и не считаю это нормальным.
Вторая важная категория «поехавших», которую хотелось бы разобрать — это люди, утверждающие, что применяют принципы SOLID, но на самом деле этого не делающие. Их аргументация обычно сводится к тому, что солид следует применять не по всему проекту, а лишь в тех местах, где он подходит. Но тут налицо непонимание разницы между паттерном и принципом. Солид это не паттерн, а принцип. Ты либо стараешься следовать ему везде, либо это уже не солид.
Поясню. Вот есть DRY. Очень простой принцип о том, что надо стараться избегать копипаста. Конечно, где-то в коде могут быть отступления от этого правила, но если человек исповедует dry, то в какой-то момент он может посмотреть на некий участок кода, решить, что он недостаточно dry, и переписать его менее влажно. Не потому, что этот участок кода работал плохо, а только лишь потому, что он не соответствует принципам, по которым мы решили писать код. И это действительно происходит в реальных проектах. То же касается KISS и YAGNI. Но не SOLID. Не бывает такого, что чувак в геймдеве смотрит на код, и решает, что дай-ка я его перепишу, потому что он какой-то недостаточно солидный. Ну не бывает такого на практике. А если ты так не делаешь, значит, ты и не следуешь этому принципу. У тебя просто в случайных местах код написан в соответствии с его правилами, но ты ими на самом деле не руководствовался.
Вот так и получается, что если кто-то в геймдеве на полном серьёзе топит за SOLID, то для меня это или нуб или поехавший.
Обсудить
#код
Месяц назад я твитнул, что, дескать, как только слышу от соискателя или работодателя в геймдеве что-нибудь про SOLID, так сразу автоматически помечаю их в своей голове как нубов, либо поехавших. С тех пор мне пришлось пару раз подискутировать на эту тему в разных уголках интернета, и я решил, что стоит уже это оформить в отдельный пост.
Понятно, что это своего рода упрощение и навешивание ярлыков, которое отражает ситуацию лишь до определённой точности, но оно взято не из воздуха, а основывается на наблюдениях за реальным положением дел. И главный мой тезис в том, что в геймдеве на реальных проектах принципами SOLID никто никогда не руководствуется. Соответственно, если человек декларирует их своими ценностями, то он либо новичок в области, начитавшийся умных слов и книжек, но ещё не нюхавший пороху как следует на практике; либо же, мягко говоря, довольно неординарный геймдевелопер. То есть наглухо поехавший с моей точки зрения.
Поехавшие, в свою очередь, делятся, на две основные категории. Первые — это люди, пришедшие из энтерпрайза. Я никогда в энтерпрайзе не работал, но похоже, что там написание абстрактного кода эволюционно более привлекательная стратегия. Я ничего против этого не имею, но когда эти люди приходят в геймдев, с ними бывает тяжело сработаться, так как это зачастую сплошное ООП головного мозга. Там, где типичный программист из кровавого энтерпрайза в рубашке с длинными рукавами заведёт десять интерфейсов и фабрику фабрик; типичный геймдевелопер в перепачканной пиццой футболке вооружится принципами KISS и YAGNI и удалит это всё нахрен, написав взамен простой и понятный класс, решающий конкретную задачу. Пусть и наплевав при этом на принцип открытости/закрытости, разделения интерфейсов и другие святая святых ООП. То есть, конечно, наверняка где-то в природе существуют игры, написанные полностью по канонам SOLID. Но, во-первых, я такого не встречал, а во-вторых, боюсь представить, что там за монструозная кодобаза, и не считаю это нормальным.
Вторая важная категория «поехавших», которую хотелось бы разобрать — это люди, утверждающие, что применяют принципы SOLID, но на самом деле этого не делающие. Их аргументация обычно сводится к тому, что солид следует применять не по всему проекту, а лишь в тех местах, где он подходит. Но тут налицо непонимание разницы между паттерном и принципом. Солид это не паттерн, а принцип. Ты либо стараешься следовать ему везде, либо это уже не солид.
Поясню. Вот есть DRY. Очень простой принцип о том, что надо стараться избегать копипаста. Конечно, где-то в коде могут быть отступления от этого правила, но если человек исповедует dry, то в какой-то момент он может посмотреть на некий участок кода, решить, что он недостаточно dry, и переписать его менее влажно. Не потому, что этот участок кода работал плохо, а только лишь потому, что он не соответствует принципам, по которым мы решили писать код. И это действительно происходит в реальных проектах. То же касается KISS и YAGNI. Но не SOLID. Не бывает такого, что чувак в геймдеве смотрит на код, и решает, что дай-ка я его перепишу, потому что он какой-то недостаточно солидный. Ну не бывает такого на практике. А если ты так не делаешь, значит, ты и не следуешь этому принципу. У тебя просто в случайных местах код написан в соответствии с его правилами, но ты ими на самом деле не руководствовался.
Вот так и получается, что если кто-то в геймдеве на полном серьёзе топит за SOLID, то для меня это или нуб или поехавший.
Обсудить