Пишем игру для 3DS

Свою игру для 3ds я написал еще давно и иногда в роликах мелькали кадры прототипа. Это было примерно 2 года назад и тогда я взял первое попавшееся решение, лишь бы быстрее показать, что на эту консоль тоже можно делать игры. И вы не поверите, но по прошествии времени оказалось, что движков под эту платформу больше не стало. Навскидку можно вспомнить привычный unity, который без особых проблем ставится, но скомпилированный проект на железке завести пока не получается, хотя на форумах пишут, что у кого-то вышло. Если получится это сделать, то я расскажу про это, а пока что давайте напишем игру для 3ds с Любовью.

Love 2d

Любовь 2D (love 2d) - это фреймворк для разработки игр под различные привычные платформы. Большим плюсом является написание программ на языке lua, который достаточно простой и понятный, в итоге этот фреймворк и не самый известный, но на нем делают даже коммерческие игры, которые можно найти в steam, некоторые даже с отличными показателями продаж. Изначально love2d затачивался под именно двухмерную графику, но уже есть дополнения, которые позволяют грузить и 3d графику. Простыми словами, даже вне написания игры для 3ds, вполне можно попробовать сделать что-то свое. И эта статья будет отчасти прикладным уроком, где я от и до быстро покажу все моменты создания игры, а если вас это заинтересует, то без проблем сможете повторить, а дальше почерпнуть сведения из уроков и wiki фреймворка.

Пишем игру для 3DS

Создание игры на этом фреймворке мне честно очень напомнило программирование в детстве, когда приходилось каждый объект рисовать и двигать без помощи всяких модных вещей, которые дает современный игровой движок. Тут нет своего ide, то есть так называемой "среды разработки", потому код писать можно там, где вам удобно, я для этого использую npp, а графику рисовать в любом графическом редакторе. И тут нет редакторов уровней или каких-то физических движков, даже реализацию анимированного спрайта надо писать самому. Но при этом есть возможность либо скачать код с форума разработчиков, либо сделать реализацию именно так, как вы хотите.

Ставим devkitPro

Пишем игру для 3DS

Традиционно, я использую 10ю винду, для того, чтобы появилась возможность разрабатывать приложения под системы nintendo, надо скачать и установить devkitPro, он почти все сделает автоматически. На вики заявляется, что с помощью этого проекта можно писать игры под разные платформы, начиная с game boy advance, продолжая GameCube, Wii, Nintendo DS, Nintendo Switch и некоторых других. Из этого списка мне еще интересно глянуть на wii, с инфой для этой консоли я пока разбираюсь. После установки devkitPro сам настроит все переменные в системе и самое важное, появится возможность компилировать проекты из командной строки командой make.

Hello World!

Прежде чем сделать надо, нам понадобится несколько вещей. Для начала, возьмем фреймворк lovepotion версии 1.08. Самая свежая версия 2.0 и я беру более старую потому, что у нее чуть больше функционал конкретно для 3ds. Мне очень нравится, что есть возможность компилировать сразу в cia, что в новой версии убрали. Я чуть позже разберусь с этим, пока что пользуемся проверенным методом.

И давайте сперва создадим папку Hello World, внутри которой создадим папку game, где создадим текстовый файл main.lua и впишем туда простой код, который вызывает отрисовку текста на экране с определенными координатами.

function love.draw() love.graphics.print("Hello World!", 200, 200) end

Если бы мы делали игру для PC, то тут надо было бы скачать фреймворк love2d, взять папку game и перетянуть ее на исполняемый файл и посмотреть как работает программа, либо же прописать к love.exe путь к папке game (love.exe e:\2ds\HelloWorld4\game), после чего игра запустится.

Но так как у нас цель сделать Homebrew под 3ds, то поступаем чуть иначе, кидаем в папку два файла, первый - lovePotion.elf, это скомпилированный фреймворк, а так же файл для сборки Makefile, внутри которого расписано как и что собирать. После этого через консоль набираем make и проект компилируется в 3dsx файл.

Пишем игру для 3DS

Тестируем проект

Теперь достаточно важный момент. Если вы смотрели мои ролики по разработке игр на другие платформы, то там собранную игру надо было кидать на реальное устройство и проверять его работу. Где-то это было удобно, как с xbox360 и делалось автоматически, а на той же ps vita было так себе. Скомпилировал, пересобрал, кинул на реальное устройство, установил, запустил, проверил, в общем, нудятина. Кстати, в одном из следующих видео я расскажу про инструменты для работы с psvita, которые жизнь упрощают, а вот с 3ds работа чуть упрощается сразу.

Пишем игру для 3DS

Дело в том, что давно и успешно развивается эмулятор citra, который поддерживает множество коммерческих игр и если у вас мощный комп, то играть можно во что угодно и с отличным разрешением. Нам же эмулятор поможет тестировать написанную нами программу. Скачиваем, запускаем, выбираем "файл-загрузить файл" и выбираем созданный 3dsx и убеждаемся, что все работает нормально.

Если же нам требуется cia файл, то тут надо в папку докинуть файлы, содержащие баннер, описание программы и утилиты, которые собирают итоговый пакет. Для удобства я их упаковал в архив, который можно найти в подписи к ролику. Теперь для компиляции набираем make cia и получаем нужный файл, который так же можно проверить в Цитре. Сразу скажу небольшую особенность - если изменить код и заново собрать cia файл, то он перезапишется, если же 3dsx, то компилятор будет ругаться и надо ранее скомпилированную программу удалить. Для решения это проблемы можно создать batник, куда прописать несколько команд, уменьшающие лишние телодвижения. При установке cia файлов в Citra, игра будет переписываться автоматически.

Пишем игру для 3DS

Теперь чуть углубимся в то, что мы сделали. Внутри стандартной функции love.draw мы вывели текст в определенных координатах на первом экране. Чтобы вывести на другом, нам надо четко обозначить на каком экране что рисовать. Делается это с помощью команды setScreen, где top - это верхний экран, а bottom - нижний. У экранов разные размеры, у верхнего 400×240 px, у нижнего 320×240. Для удобства отладки давайте нарисуем эти границы на экране, после этого в Цитре их будет видно. Рисуем с помощью линий. Саму справку по коду можно взять с wiki, там же есть пометки, что появилось в более поздних версиях.

function love.draw() --this is comment love.graphics.setScreen("top") love.graphics.print("Hello World!", 0, 0) love.graphics.line( 0, 0, 400, 0) love.graphics.line( 400, 0, 400, 240) love.graphics.line( 0, 240, 400, 240) love.graphics.line( 0, 0, 0, 240) --pad and ball love.graphics.rectangle("fill", 10, pad1_y - 50, 10, 100) love.graphics.rectangle("fill", 400-20, pad2_y - 50, 10, 100) love.graphics.circle("fill", ball.x, ball.y, 5) --[[ this is comment too this is comment too too ]] love.graphics.setScreen("bottom") love.graphics.print("Have no fear.", 320/2-50, 240/2-20) love.graphics.print("Turic is here.", 320/2-50, 240/2+20) love.graphics.line( 0, 0, 320, 0) love.graphics.line( 320, 0, 320, 240) love.graphics.line( 0, 240, 320, 240) love.graphics.line( 0, 0, 0, 240) end
Пишем игру для 3DS

Чуть усложняем игру

И самое простое, что сейчас можно сделать - это подобие пинг-понга, для этого заводим переменную ball, в функции update производим вычисления, а потом в функции draw рисуем круг. Для полноты картины еще надо добавить две площадки, которые управляются с помощью кнопок вверх\вниз и X\B. И надо не забыть назначить эти клавиши в настройке управления эмулятора. И стоит отметить, что при добавлении функций setScreen, мы уже теряем возможность проверять проект на основной версии love2d, так как о множестве экранов он просто не знает.

Пишем игру для 3DS
local isDown = love.keyboard.isDown local bool = { [true] = 1, [false] = 0 } local pad1_y = 0 local pad2_y = 0 local speed = 3 local ball = { x = 100, y = 100, vx = -speed, vy = speed } local p01 = 0; local p02 = 0; function love.update(dt) pad1_y = pad1_y + (bool[isDown"down"] - bool[isDown"up"]) * 7 pad2_y = pad2_y + (bool[isDown"b"] - bool[isDown"x"]) * 7 ball.x = ball.x + ball.vx ball.y = ball.y + ball.vy if math.abs(ball.y) >= 240-5 then ball.vy = -ball.vy end if math.abs(ball.y) <= 0+5 then ball.vy = -ball.vy end if ball.x < 20 and ball.x > 0 and math.abs(pad1_y - ball.y) < 60 then ball.vx = -ball.vx end if ball.x > 380 and ball.x < 400 and math.abs(pad2_y - ball.y) < 60 then ball.vx = -ball.vx end if math.abs(ball.x) <= 0+5 then ball.vx = -ball.vx end if math.abs(ball.x) >= 400-5 then ball.vx = -ball.vx end end function love.draw() --this is comment love.graphics.setScreen("top") love.graphics.print("Hello World!", 0, 0) love.graphics.line( 0, 0, 400, 0) love.graphics.line( 400, 0, 400, 240) love.graphics.line( 0, 240, 400, 240) love.graphics.line( 0, 0, 0, 240) --pad and ball love.graphics.rectangle("fill", 10, pad1_y - 50, 10, 100) love.graphics.rectangle("fill", 400-20, pad2_y - 50, 10, 100) love.graphics.circle("fill", ball.x, ball.y, 5) --[[ this is comment too this is comment too too ]] love.graphics.setScreen("bottom") love.graphics.print("Have no fear.", 320/2-50, 240/2-20) love.graphics.print("Turic is here.", 320/2-50, 240/2+20) love.graphics.line( 0, 0, 320, 0) love.graphics.line( 320, 0, 320, 240) love.graphics.line( 0, 240, 320, 240) love.graphics.line( 0, 0, 0, 240) end

Вот так примерно раньше игры писались с помощью кружков, линий и всего такого. Но фреймворк позволяет и грузить изображения. Для этого сперва загрузим их в load, а затем рисовать в нужном месте. Таким образом можно сделать и фон, и преобразить объекты на сцене и привести до нормального вида.

function love.load() myImg = love.graphics.newImage("img.png") end function love.draw() love.graphics.draw(myImg, 200, 200) end

И эту игру можно усложнять, добавляя разные экраны, меню, компьютерный интеллект и тому подобное. Если полистать справку фреймворка, то он позволяет сделать многие вещи, плюс, есть много написанных плагинов, вплоть до трехмерной графики. Так глубоко я не вникал, не было такой цели, но сама возможность интересная.

Пишем игру для 3DS

Тестируем на реальном устройстве

Пишем игру для 3DS

После теста в Citra осталось запустить на реальном устройстве. Я скомпилировал все в cia, закинул по сети и установил как обычную игру. Стоит отметить, что тут нет никаких особых проблем или пляски с бубном, которая есть при работе с unity на 3ds. Там при компиляции приложение подписывается ключом разработчика, которое на ретейловой консоли не запускается, либо надо переподписать, либо в настройках luma поставить возможность запуска dev-приложений, из-за чего могут быть проблемы с запуском обычных игр. Работая же с Love Potion таких проблем нет, все ставится в пару кликов.

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

116116
9 комментариев

Как круто! Большое спасибо за текст

4
Ответить

Не думал, что когда-либо наткнусь на ролик по этой теме.
Мало того, что 3DS, так еще и написание своего хомбрю.

3
Ответить

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

3
Ответить

А есть какой-нибудь движок на C++?

1
Ответить

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

2
Ответить

У виртуального аватара Орка Подкастера и то больше эмоций на лице...
А так, читать приятней чем смотреть. 

1
Ответить

а кто то знает еще что то подобное?

Ответить