Пару недель назад, просматривая темы в ветке программирования на C# наткнулся на этот пост. Там парень сделал игру за несколько часов про гонки для своего друга. Так вот, мне никогда не доводилось делать гонки. Немного подумав, пришел к выводу собственно почему бы не создать? Поскольку AshotOneShot, а так звали автора той темы писал гоночки на WinForm, то я чем я хуже? Давайте поэтапно расскажу, что у меня в итоге вышло за несколько вечеров и пару ночей. Для начала 2 скрина, было стало. Было Стало Да, основные ассеты и структуру меню, я взял у AshotOneShot. Все остальные ассеты, в плане музыки и пропов нашел в интернете, либо сделал сам. К слову, касаемо кода. Его писал полностью самостоятельно. Копипаст кусков кода с форумов тут нет. Сурсы и билд. Не буду ходить вокруг да около. Тем кому гитхаб нафиг не нужон, вот архив с билдом Ссылка на VirusTotal Сразу про баги. Тестировал на Win10, вроде все работает. Тестировал на серваках, была бесконечная загрузка. В общем, если у кого, что криво работает фидбэкните пожалуйста. Небольшой DevLog. Думаю нет смысла здесь писать стены кода и расписывать каждую строчку кода, зачем она и почему. Если народу будет интересно в чем сомневаюсь, могу записать видео, где рассказать прямо подробно, как что работает. =D А так, лучше расскажу в общих чертах, что сделал, какие были интересные моменты. Структура проекта. Основным классом проекта является Game он же UsrControl. В нем описана общая логика поведения игры. Есть таймер на 16 тиков (16 милесекунд в таймере дают 60 фпс). Основные надписи, функция репэйнта (о ней чуть позже), обработка стэйт машин, функция инициализации игры и на этом все. Дальше логику отдельных элементов уже реализуют контроллеры и менеджеры. Так же вторым основным классом приложения является сама форма, где прописаны первичные инициализации, а так же управление меню. Само меню построено на юзер контролах и в нем ничего сложного нет.) Вот собственно и вся игр. Отрисовка и анимации. В этот раз я решил написать 2 класса, которые потом надо бы обернуть в библиотеку, это AnimationManager и AnimationSprite В чем собственно проблема анимаций при отрисовке на Graphics, а в том, что фрэймы надо отрисовывать непосредственно со в общем апдейте (тик таймера). Поэтому я в очередной раз наваял 2 простеньких класса, собственно сам объект анимированного спрайта и ее мененджер. Однако, наконец-то я сделал все более менее по уму и отрисовка спрайтов происходит по z-index, и вся отрисовываемая графика в игре построена на AnimationSprite. В итоге функуия репэйнта сократилась до одного цикла с linq запросом на сортировку. Как по мне это неплохой подход. К слову, в этом же проекте я решил немного поработать с пост обработкой. В целом ничего сложного, просто в фотошопе наваял 2 пост эффекта, но разница чувствуется. RTX Off RTX On Искусственный интеллект. Впервые мне довелось писать ии с нуля да еще и для гонок. Ранее я делал ии только для пошаговых игр, либо использовал уже готовые апи или коды. Запрограммировать поведение машины противника оказалось не так сложно, но при этом есть и свои подводные камни. Логика противника примерно следующая: Если игрок сзади, то всегда перекрывать проезд с собой и быть на одной линии Если игрок впереди, то включать буст для того, чтобы догнать и пытаться быть не на одной линии Если противник обгоняет, то уступать ему первенство через раз Вроде ничего сложного, но алгоритмы поведения, честно у меня получились немного кривые, однако это придает больше фана и непредсказуймости, поэтому не баг, а фича.) За ии отвечает в проекте класс EnemyAi. Работа с музыкой. На самом деле это первый раз, когда я делаю игру на WinForm и добавляю полноценную музыку и звуки в игру. В целом, они принесли много подводных камней и к слову именно из-за них у вас может не запускаться проект. Нет, с самими звуками работать не сложно, но их нужно так организовать, чтобы они могли проигрываться парралельно. В WinForm нет корутин, а обертывать WindowsMediaPlayer в отдельный поток учитывая, что он сам по себе работает в отдельном потоке довольно странно. Поэтому в проекте есть например 2 полностью одинаковых класса MusicManager и VoiceManager, которые банально нужны для многоканальности звука. Так же звуки машин пришлось подгружать в оперативную память сразу при запуске. К слову, поэтому в игре есть загрузка при запуске. В общем, если кто шарит за то, как грамотнее оформлять звуки на шарпах, можете поделиться скилом?) Ах да, моя лень не позволила мне сделать нормальное управление звуком, поэтому громкость и отключение звука регулировать тут. :З Мега регулировка громкости Банальщина Систему коллизий, основные объекты, стэйт машины и прочее мне уже доводилось делать ни один раз, как на формах, так и на других платформах или игровых движках. Однако и среди них нашлось пара забавных моментов. Например, в этом проекте точкой отсчета является авто игрока, поэтому на самом деле игрок стоит на месте и все элементы игры движутся относительно него, путем вычитания и сложения скоростей.) Да, да прямо как корабль из футурамы, который по факту стоял на месте и двигал вселенную.) Решил сделать парочку пропов. Например следы от торможения. Работает вроде более менее неплохо. Следы В целом, больше ничего такого интересного вспомнить не могу.) Зачем это все? Вы наверное думаете, а нафига вообще делать игры на вин формах? Можно же сделать игру на нормальном движке и выглядеть она будет в 1000 раз лучше, плюс можно выложить на те же мобилки или хтмл 5, срубив еще при этом шекелей. Да и АшотВанШот сделал игру за пару часов ради 500 рублей. Потому что, склепать свою игру на движке, где все механики работают из коробки сможет любой, а вот клепать игры на платформах, которые для этого не предназначены это очень крутой экспириенс. Так лучше понимаешь, как устроены игры в целом. Как работают те же коллизии, потоки и почему игры имеют те или иные алгоритмы или структуры. Поэтому считайте это небольшим челенджем и проверкой знаний программирования.) В общем, на этом все. Как говорится всем удачи, денег, дачи.)
Сам писал? Посмотрел код стайл, он отличается, сначала вижу венгерскую нотацию, camelCase потом under_score, очень странно такое видеть в коде одном проекте и разных классах. Про солид я думаю затирать ненужно
Soiakp, Да, сам. Просто, как раз эксперементировал с нэймингом и искал разные ресурсы, это все же небольшой пет проект, а не продакшн. :) Что самое интересное, в разных местах пишут про разные общепризнанные стандарты. Просто у C# есть еще свои стандарты и в итоге какая-то путаница. Но в целом думаю в будущем буду придерживаться венгерского стандарта.
itstranger, Почти на каждом интерпрайсе, да и в различных микро гейм студиях используют венгерску. Приватные поля _camalCase, Публичные PascalCase. Методы PascalCase. Так вполне удобнее и ошибку допустить будет сложнее.
Soiakp, В целом да, согласен. В этом проекте я ее и придерживался. Единственное что не подлежит венгерской нотации, это методы, они через _. Вообще, согласен с вами, надо переименовать. Они правда выбиваются из общего стиля кода.)