<?xml version="1.0" encoding="utf-8"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Форум программистов и сисадминов Киберфорум - Блоги - Блог 8Observer8. Автор 8Observer8</title>
		<link>https://www.cyberforum.ru/blogs/416874/</link>
		<description>КиберФорум - форум программистов, системных администраторов, администраторов баз данных, компьютерный форум, форум по электронике и бытовой технике, обсуждение софта. Бесплатная помощь в решении задач по программированию и наукам, решение проблем с компьютером, операционными системам</description>
		<language>ru</language>
		<lastBuildDate>Fri, 21 Aug 2026 16:03:17 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>60</ttl>
		<image>
			<url>https://www.cyberforum.ru//cyberstatic.net/images/misc/rss.jpg</url>
			<title>Форум программистов и сисадминов Киберфорум - Блоги - Блог 8Observer8. Автор 8Observer8</title>
			<link>https://www.cyberforum.ru/blogs/416874/</link>
		</image>
		<item>
			<title>Установка MinGW GCC 16.2 и CMake</title>
			<link>https://www.cyberforum.ru/blogs/416874/11070.html</link>
			<pubDate>Mon, 10 Aug 2026 16:23:08 GMT</pubDate>
			<description>VK Видео: 
 
https://vkvideo.ru/video-240781534_456239017 
 
YouTube: 
 
eY5-5PyI9NM 
 
Текстовая...</description>
			<content:encoded><![CDATA[<div>VK Видео:<br />
<br />
<iframe src="https://vkvideo.ru/video_ext.php?oid=-240781534&amp;id=456239017&amp;hd=1" width="640" height="360" allow="encrypted-media; fullscreen; picture-in-picture; screen-wake-lock;" frameborder="0" allowfullscreen></iframe><br />
<br />
YouTube:<br />
<br />
<iframe width="640" height="360" src="https://www.youtube.com/embed/eY5-5PyI9NM" frameborder="0" allowfullscreen></iframe><br />
<br />
<a rel="nofollow noopener noreferrer" href="http://localhost:8080/tutorials/tools/mingw/setup-mingw/?lang=ru" target="_blank" title="http://localhost:8080/tutorials/tools/mingw/setup-mingw/?lang=ru">Текстовая версия</a></div>

]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/11070.html</guid>
		</item>
		<item>
			<title>Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt</title>
			<link>https://www.cyberforum.ru/blogs/416874/10852.html</link>
			<pubDate>Sun, 05 Apr 2026 11:38:04 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Среду разработки Qt...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: <a rel="nofollow noopener noreferrer" href="https://github.com/qt-creator/qt-creator" target="_blank" title="https://github.com/qt-creator/qt-creator">https://github.com/qt-creator/qt-creator</a>, где можно скачать установщик, на вкладке Releases: <a rel="nofollow noopener noreferrer" href="https://github.com/qt-creator/qt-creator/releases" target="_blank" title="https://github.com/qt-creator/qt-creator/releases">https://github.com/qt-creator/qt-creator/releases</a><br />
<br />
Занимает Qt Creator всего примерно 600 МБайт на жёстком диске, в отличае, например, от Visual Studio, которая занимает примерно 2 GB + для C/C++ разработки в VS потребуются ещё инструменты, что займёт 10-15 GB. Для Qt Creator нужен MinGW - это примерно 700 MB и CMake - это примерно 100 MB, что всё вместе примерно 1.5 GB. Qt Creator потребляет мало оперативной памяти - от 50 МБ. В целом Qt Creator нагружает систему намного меньше, чем VS или даже VSCode. В Qt Creator ничего не нужно настраивать. Qt Creator автоматически найдёт путь к CMake/bin и MinGW/bin, которые должны быть в вашей переменной окружения PATH.<br />
<br />
Эта среда программирования тоже может открывать CMake-проекты, как и VS, простым открыванием файла CMakeLists.txt. Допустим, у вас есть CMake-проект. Вы можете открыть этот CMake-проект в Qt Creator, выбрав в меню: <code class="inlinecode">File</code> &gt; <code class="inlinecode">Open File or Project...</code> &gt; выберите ваш <code class="inlinecode">CMakeLists.txt</code>. Ваш CMake-проект откроется в Qt Creator. Вы можете ставить точки останова и выполнять программу по шагам.<br />
<br />
<h2>Используемые инструменты</h2><br />
<br />
<ul><li><b>Qt Creator</b> - это специализированная кроссплатформенная интегрированная среда разработки (IDE), созданная специально для работы с фреймворком Qt, но подходящая и для обычной разработки на C и C++</li>
<li><b>MinGW</b> (сокращение от Minimalist GNU for Windows) - это набор программных инструментов с открытым исходным кодом, который позволяет компилировать приложения, написанные на языках C и C++, для работы в операционной системе Windows. По сути, это порт популярного компилятора GCC (GNU Compiler Collection) и набора утилит GNU (таких как make) под Windows</li>
<li><b>CMake</b> - это кроссплатформенная система автоматизации сборки программного обеспечения. Важно понимать, что CMake сам по себе не является компилятором. Это &quot;генератор генераторов&quot; или мета-система сборки</li>
</ul><br />
<h2>Установка MinGW</h2><br />
<br />
<ul><li>Скачайте MinGW GCC любой актуальной версии на странице: <a rel="nofollow noopener noreferrer" href="https://winlibs.com/" target="_blank" title="https://winlibs.com/">https://winlibs.com/</a></li>
<li>Например, я скачал <a rel="nofollow noopener noreferrer" href="https://github.com/brechtsanders/winlibs_mingw/releases/download/13.1.0-16.0.5-11.0.0-ucrt-r5/winlibs-x86_64-posix-seh-gcc-13.1.0-mingw-w64ucrt-11.0.0-r5.zip" target="_blank" title="https://github.com/brechtsanders/winlibs_mingw/releases/download/13.1.0-16.0.5-11.0.0-ucrt-r5/winlibs-x86_64-posix-seh-gcc-13.1.0-mingw-w64ucrt-11.0.0-r5.zip">MinGW GCC 13.1</a>, выбрав этот архив:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11853&amp;a= mp;d=1775388765" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Извлеките архив в текущую папку, например, в корень диска C</li>
<li>Переименуйте извлечённую папку. Например, дайте ей имя <code class="inlinecode">mingw64_13.1</code></li>
<li>Зайдите в папку <code class="inlinecode">mingw64_13.1/bin</code> и скопируйте путь <code class="inlinecode">C:\mingw64_13.1\bin</code></li>
<li>Добавьте путь <code class="inlinecode">C:\mingw64_13.1\bin</code> в переменную окружения PATH</li>
</ul><br />
<h2>Установка CMake</h2><br />
<br />
<ul><li>Скачайте и установите <a rel="nofollow noopener noreferrer" href="https://github.com/Kitware/CMake/releases" target="_blank" title="https://github.com/Kitware/CMake/releases">CMake</a>. Ищите <code class="inlinecode">cmake-x.x.x-windows-x86_64.msi</code> в списке</li>
<li>Нажимайте кнопки <code class="inlinecode">Next</code> &gt; <code class="inlinecode">Next</code> &gt; <code class="inlinecode">Finish</code></li>
<li>Откройте консоль (CMD) и проверьте запускается ли CMake:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="648896650"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="648896650" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--version</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Если CMake не найден, то добавьте путь к <code class="inlinecode">C:\Program Files\CMake\bin</code> в переменную окружения PATH</li>
</ul><br />
<h2>Установка Qt Creator</h2><br />
<br />
<ul><li>Скачайте установщик Qt Creator по ссылке: <a rel="nofollow noopener noreferrer" href="https://github.com/qt-creator/qt-creator/releases" target="_blank" title="https://github.com/qt-creator/qt-creator/releases">https://github.com/qt-creator/qt-creator/releases</a> Листайте вниз до раздела <code class="inlinecode">Assets</code> и ищите установщик <code class="inlinecode">qtcreator-windows-x64-msvc-x.y.z.msi</code>, где <code class="inlinecode">x.y.z</code> - это версия Qt Creator</li>
<li>После первого запуска Qt Creator автоматически найдёт пути к MinGW и CMake, которые были добавлены в переменную окружения PATH</li>
</ul><br />
<h2>Создаём первый CMake-проект на C или C++</h2><br />
<br />
Создадим простой CMake-проект в Qt Creator с нуля<br />
<br />
Примечание. Если у вас уже есть CMake-проект на C или C++, то есть у вас есть проект с <code class="inlinecode">CMakeLists.txt</code>, то вы можете его открыть в Qt, выбрав в меню: <code class="inlinecode">File</code> &gt; <code class="inlinecode">Open File or Project...</code> &gt; выберите ваш <code class="inlinecode">CMakeLists.txt</code><br />
<br />
<ul><li>Запустите Qt Creator</li>
<li>Выберите в меню: <code class="inlinecode">File</code> &gt; <code class="inlinecode">New Project...</code></li>
<li>Слева выберите <code class="inlinecode">Non-Qt Project</code>, а справа выберите либо проект для C, либо проект для С++:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11842&amp;a= mp;d=1775387228" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>После нажатия на кнопку <code class="inlinecode">Choose...</code> вам нужно будет дать название проекту и указать папку, где будет создан проект:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11843&amp;d=1775387432" rel="Lightbox" id="attachment11843" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11843&amp;thumb=1&amp;d=1775387432" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 43b32262-a515-4ccb-a5a9-36e8a5aba1ab.png
Просмотров: 83
Размер:	7.5 Кб
ID:	11843" style="margin: 5px" /></a></li>
<li>После нажатия на кнопку <code class="inlinecode">Next</code> нужно оставить <code class="inlinecode">CMake</code> и нажать на кнопку <code class="inlinecode">Next</code>:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11844&amp;d=1775387557" rel="Lightbox" id="attachment11844" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11844&amp;thumb=1&amp;d=1775387557" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 9ca5b7d5-4c37-4f18-aa9c-0153e637d72d.png
Просмотров: 100
Размер:	5.6 Кб
ID:	11844" style="margin: 5px" /></a></li>
<li>Поставьте галочки <code class="inlinecode">Debug</code> и <code class="inlinecode">Release</code> и нажмите на кнопку <code class="inlinecode">Next</code>:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11845&amp;d=1775387710" rel="Lightbox" id="attachment11845" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11845&amp;thumb=1&amp;d=1775387710" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 40353598-e9f8-41e3-8e9d-8a98a112c6c3.png
Просмотров: 79
Размер:	33.9 Кб
ID:	11845" style="margin: 5px" /></a></li>
<li>Далее, нажмите на кнопку <code class="inlinecode">Finish</code>:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11846&amp;d=1775387790" rel="Lightbox" id="attachment11846" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11846&amp;thumb=1&amp;d=1775387790" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: bfd2e060-75ab-40e9-a473-638eed5cf5b0.png
Просмотров: 78
Размер:	15.2 Кб
ID:	11846" style="margin: 5px" /></a></li>
<li>Будет создан проект:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11847&amp;d=1775387907" rel="Lightbox" id="attachment11847" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11847&amp;thumb=1&amp;d=1775387907" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 8b0b6f02-df4e-428c-902e-fcdd2a56ba17.png
Просмотров: 80
Размер:	16.4 Кб
ID:	11847" style="margin: 5px" /></a></li>
<li>Вы можете собрать его запустить его на исполнение, нажав на кнопку в форме зелёного треугольника в нижнем левом углу экрана:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11848&amp;d=1775388047" rel="Lightbox" id="attachment11848" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11848&amp;thumb=1&amp;d=1775388047" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 8b62c5da-34fe-46a4-a4e6-35d82316ae39.png
Просмотров: 60
Размер:	7.1 Кб
ID:	11848" style="margin: 5px" /></a></li>
<li>Либо, вы можете поставить точку останова, кликнув рядом с номером строки:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11849&amp;d=1775388142" rel="Lightbox" id="attachment11849" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11849&amp;thumb=1&amp;d=1775388142" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 5a72eff7-6523-4f70-b4e0-a99d459bbd4b.png
Просмотров: 71
Размер:	9.2 Кб
ID:	11849" style="margin: 5px" /></a></li>
<li>Нажмите на зелёный треугольник с жуком, чтобы запустить режим отладки:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11850&amp;d=1775388245" border="0" alt="Название: 002b2a23-a398-4a6d-96e7-e159c506bb7a.png
Просмотров: 790

Размер: 7.7 Кб" style="margin: 5px" /></li>
<li>Программа запустится и остановится на строке, где вы поставили точку останова:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11851&amp;d=1775388334" rel="Lightbox" id="attachment11851" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11851&amp;thumb=1&amp;d=1775388334" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 5bd78d55-df2c-4d4a-9a27-d83b40998ae1.png
Просмотров: 66
Размер:	10.1 Кб
ID:	11851" style="margin: 5px" /></a></li>
<li>Нажимайте клавишу <code class="inlinecode">F10</code> (Step over) или <code class="inlinecode">F11</code> (Step Into), чтобы выполнять строку за строкой. &quot;Step Over&quot; - не заходит в функцию, а &quot;Step Into&quot; заходит в функцию</li>
<li>На нижней панели есть кнопки для продолжения выполнения программы до следующей точки останова, для остановки отладки и т. д.:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11852&amp;d=1775388690" border="0" alt="Название: 44c8ddd6-ff90-4bbf-a7d6-9bd267fa83e7.png
Просмотров: 776

Размер: 1.6 Кб" style="margin: 5px" /></li>
</ul><br />
Если хотите собирать проекты из консоли и набирать код в Sublime Text 4 (или Notepad++), то перейдите на инструкцию: <a href="https://www.cyberforum.ru/blogs/416874/10793.html">Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE</a><br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11853&amp;d=1775388765" rel="Lightbox" id="attachment11853" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11853&amp;thumb=1&amp;d=1775388765" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 955cd552-4bfb-488d-ada5-9fbc88b3508e.png
Просмотров: 907
Размер:	17.7 Кб
ID:	11853" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11842&amp;d=1775387228" rel="Lightbox" id="attachment11842" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11842&amp;thumb=1&amp;d=1775387228" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 81270c5d-ff5f-45e2-9b01-cbf4b82e5f70.png
Просмотров: 936
Размер:	19.4 Кб
ID:	11842" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>

]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10852.html</guid>
		</item>
		<item>
			<title>SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++</title>
			<link>https://www.cyberforum.ru/blogs/416874/10815.html</link>
			<pubDate>Tue, 24 Mar 2026 03:18:09 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Финальные проекты на Си...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Финальные проекты на Си и на C++:<br />
<br />
<ul><li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11811&amp;d=1774322222">finish-text-sdl3-c.zip</a></li>
<li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11812&amp;d=1774322222">finish-text-sdl3-cpp.zip</a></li>
</ul><br />
Результат:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11801&amp;a= mp;d=1774048407" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
Напишем программу с нуля, которая выводит текст на русском с помощью библиотеки SDL3_ttf и рисует отрезками равносторонний треугольник.<br />
<br />
<h2>Установка инструментов</h2><br />
<br />
<ul><li>Установите CMake и MinGW 13.1 по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10793.html">Установка CMake и MinGW 13.1</a></li>
<li>Скачайте следующие архивы библиотек:<ul><li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11783&amp;d=1773919892">SDL3-devel-3.4.2-mingw.zip</a></li>
<li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11784&amp;d=1773919892">SDL3-3.4.2-win32-x64.zip</a></li>
<li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11785&amp;d=1773919892">SDL3_ttf-devel-3.2.2-mingw.zip</a></li>
<li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11786&amp;d=1773919892">SDL3_ttf-3.2.2-win32-x64.zip</a></li>
</ul></li>
<li>Извлеките содержимое архивов выше в какую-нибудь общую папку, например, с именем &quot;libs&quot; на C:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11787&amp;a= mp;d=1773920267" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Примечание. Эти архивы я скачал с официальных репозиториев на вкладках Release: <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2" target="_blank" title="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2">SDL3 3.4.2</a> и <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL_ttf/releases/tag/release-3.2.2" target="_blank" title="https://github.com/libsdl-org/SDL_ttf/releases/tag/release-3.2.2">SDL3_ttf 3.2.2</a>. Я сократил глубину вложенность папок в архивах со словом &quot;devel&quot; в имени.</li>
<li>Пути к папкам с &quot;win32-x64&quot; в именах нужно добавить в переменную окружения Path. В этих папках лежат SDL3.dll и SDL3_ttf.dll. Добавьте пути к этим папкам в Path:<ul><li>C:\libs\SDL3-3.4.2-win32-x64</li>
<li>C:\libs\SDL3_ttf-3.2.2-win32-x64</li>
</ul></li>
<li>Установите редактор кода или IDE, например: Notepad++ или VSCode. Я использую Sublime Text 4 и Qt Creator</li>
</ul><br />
<h2>Настройка и запуск стартового проекта</h2><br />
<br />
<ul><li>Скачайте стартовый проект: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11796&amp;d=1773943491">start-text-sdl3-c.zip</a></li>
<li>Примечание. Этот стартовый проект был создан по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/2953.html">Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++</a></li>
<li>Извлеките пример из архива:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11789&amp;d=1773925075" border="0" alt="Название: 7ea1de96-8017-4103-bafb-7724a2bed04f.png
Просмотров: 636

Размер: 3.0 Кб" style="margin: 5px" /></li>
<li>Код стартового примера:<br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="557592664"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="557592664" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Использовать функции обратного вызова вместо main()</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
&nbsp;
<span class="co1">// Мы будем использовать этот рендерер для рисования в этом окне каждый кадр</span>
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="co1">// Эта функция запускается один раз при старте</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Рендерер SDL3&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">300</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="co1">// Продолжаем работу программы</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается, когда происходит новое событие (ввод мыши, нажатие клавиш и т.д.)</span>
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// Завершаем программу, сообщая ОС об успехе</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="co1">// Продолжаем работу программы</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается один раз за кадр и является сердцем программы</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">38</span><span class="sy0">,</span> <span class="nu0">43</span><span class="sy0">,</span> <span class="nu0">51</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Цвет заливки холста</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Начинаем с чистого холста - заливаем холст указанным выше цветов</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим результат на экран</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="co1">// Продолжаем работу программы</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается один раз при завершении работы</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL3 автоматически освободит все ресурсы подсистем (окна, рендереры) при выходе</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="983950591"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="983950591" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-text-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">17</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD_REQUIRED ON<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это будет app.exe, а</span>
<span class="co0"># в вебе было бы app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-mingw/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как &quot;обязательно&quot; или &quot;требуется&quot;</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>config-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="860573645"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="860573645" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win ^
-DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div>build-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="736895816"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="736895816" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> dist\win
cmake <span class="re5">--build</span> .
<span class="kw3">cd</span> ..\..</pre></td></tr></table></div></td></tr></tbody></table></div>run-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="365827969"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="365827969" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">dist\win\app</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку примера в каком-нибудь текстовом редакторе - например, в <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">Sublime Text 4</a> (ST4), Notepad++, VS Code и т.д. В ST4 можно открыть проекта, набрав в консоли из папки проекта: &quot;subl .&quot; (без ковычек). Либо откройте проект в <a rel="nofollow noopener noreferrer" href="https://github.com/qt-creator/qt-creator/releases" target="_blank" title="https://github.com/qt-creator/qt-creator/releases">Qt Creator</a> - для этого в левом верхнем углу Qt Creator нажмите &quot;Fire&quot; &gt; &quot;Open File or Project...&quot; и выберите файл &quot;CMakeLists.txt&quot; из папки скаченного проекта</li>
<li>Откройте файл &quot;CMakeLists.txt&quot; и убедитесь, что путь к библиотеке SDL3 такой же как у вас и при необходимости измените его на ваш путь:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="667411040"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="667411040" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-mingw/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте консоль в текущей папке и поочерёдно введите команды для конфигурирования, сборки и запуска EXE:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="998572787"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="998572787" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">config-exe
build-exe
run-exe</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Будет запущено приложение, которое создаёт окно с помощью библиотеки SDL3 и заливает холст заданным цветом с помощью SDL3 Renderer:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11792&amp;a= mp;d=1773925673" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Мы настроили и протестировали корректный запуск стартового примера</li>
</ul><br />
<h2>Подключение библиотеки SDL3_ttf</h2><br />
<br />
<ul><li>Откройте файл &quot;CMakeLists.txt&quot; в редакторе кода</li>
<li>Добавьте создание переменной SDL3_ttf_DIR с значением пути, куда вы распаковали архив &quot;SDL3_ttf-devel-3.2.2-mingw&quot;:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="635582226"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="635582226" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_ttf_DIR <span class="st0">&quot;C:/libs/SDL3_ttf-devel-3.2.2-mingw/lib/cmake/SDL3_ttf&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте команду find_package для SDL3_ttf:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="273034126"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="273034126" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Загружаем настройки пакетов (параметры компиляции и пути к заголовкам)</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_ttf REQUIRED<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте привязку библиотеки SDL3_ttf к своему приложению:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="828577888"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="828577888" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Привязываем библиотеки к нашему приложению</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3_ttf::SDL3_ttf SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В результате получается следующий файл &quot;CMakeLists.txt&quot;:<br />
<br />
CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="590784699"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="590784699" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>finish-text-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">17</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD_REQUIRED ON<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это будет app.exe, а</span>
<span class="co0"># в вебе было бы app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-mingw/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_ttf_DIR <span class="st0">&quot;C:/libs/SDL3_ttf-devel-3.2.2-mingw/lib/cmake/SDL3_ttf&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как &quot;обязательно&quot; или &quot;требуется&quot;</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_ttf REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3_ttf::SDL3_ttf SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Загрузка TTF-файла и вывод текста на холст</h2><br />
<br />
<ul><li>Скачайте бесплатный шрифт: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11794&amp;d=1773928600">LiberationSans-Regular.zip</a></li>
<li>Примечание. Шрифт был взять по <a rel="nofollow noopener noreferrer" href="https://github.com/liberationfonts/liberation-fonts/releases/tag/2.1.5" target="_blank" title="https://github.com/liberationfonts/liberation-fonts/releases/tag/2.1.5">ссылке</a></li>
<li>Извлеките архив с файлом шрифта в новую папку &quot;assets/fonts&quot; внутри проекта</li>
<li>Откройте в редакторе кода файл &quot;src/main.c&quot;</li>
<li>Подключите заголовок &quot;SDL_ttf.h&quot; в начале файла:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="296874209"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="296874209" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Использовать функции обратного вызова вместо main()</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_ttf/SDL_ttf.h&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После создания переменной-указателя &quot;renderer&quot; добавьте переменную-указатель &quot;textTexture&quot; для текстуры, на которую будет рисоваться текст</li>
<li>Сразу, чтобы не забыть освободить ресурс, добавьте удаление текстуры в функцию SDL_AppQuit() и добавьте завершить работу SDL3_ttf:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="231421886"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="231421886" style="height: 222px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Эта функция запускается один раз при завершении работы</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; TTF_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL3 автоматически освободит все ресурсы подсистем (окна, рендереры) при выходе</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppInit() после вызова SDL_Init() добавьте инициализацию библиотеки SDL3_ttf:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="355011819"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="355011819" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Эта функция запускается один раз при старте</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>TTF_Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize TTF: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После вызова функции включения вертикальной синхронизации SDL_SetRenderVSync() добавьте код загрузки файла-шрифта и создания текстуры для текста:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="457977985"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="457977985" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; TTF_Font <span class="sy0">*</span>font <span class="sy0">=</span> TTF_OpenFont<span class="br0">&#40;</span><span class="st0">&quot;assets/fonts/LiberationSans-Regular.ttf&quot;</span><span class="sy0">,</span> <span class="nu0">28</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>font<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;TTF_OpenFont failed: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_Color textColor <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_Color<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">245</span><span class="sy0">,</span> <span class="nu0">240</span><span class="sy0">,</span> <span class="nu0">220</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> TTF_RenderText_Blended<span class="br0">&#40;</span>font<span class="sy0">,</span> <span class="st0">&quot;Равносторонний треугольник&quot;</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> textColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; texture <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; TTF_CloseFont<span class="br0">&#40;</span>font<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В цикле рисования, то есть в функции SDL_AppIterate(), добавьте код рисования текста:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="362254480"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="362254480" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="de1"><pre class="de1"><span class="co1">// Эта функция запускается один раз за кадр и является сердцем программы</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Устанавливаем позицию, в которой хотим нарисовать текст</span>
&nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> <span class="nu0">10</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаем прямоугольник для хранения размеров текстуры</span>
&nbsp; &nbsp; SDL_FRect rect<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetTextureSize<span class="br0">&#40;</span>textTexture<span class="sy0">,</span> <span class="sy0">&amp;</span>rect.<span class="me1">w</span><span class="sy0">,</span> <span class="sy0">&amp;</span>rect.<span class="me1">h</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; rect.<span class="me1">x</span> <span class="sy0">=</span> x<span class="sy0">;</span>
&nbsp; &nbsp; rect.<span class="me1">y</span> <span class="sy0">=</span> y<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Очищаем экран</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">38</span><span class="sy0">,</span> <span class="nu0">43</span><span class="sy0">,</span> <span class="nu0">51</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Цвет заливки холста</span>
&nbsp; &nbsp; <span class="co1">// Начинаем с чистого холста - заливаем холст указанным выше цветов</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Отрисовываем текст</span>
&nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> textTexture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>rect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим результат на экран</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="co1">// Продолжаем работу программы</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Запустите сборку командой &quot;build-exe&quot; и запустите приложение командой &quot;run-exe&quot;. Текст выводится на экран:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11795&amp;a= mp;d=1773931709" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Текущий код для вывода текста:<br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="467766419"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="467766419" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Использовать функции обратного вызова вместо main()</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_ttf/SDL_ttf.h&gt;</span>
&nbsp;
<span class="co1">// Мы будем использовать этот рендерер для рисования в этом окне каждый кадр</span>
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="co1">// Эта функция запускается один раз при старте</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>TTF_Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize TTF: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Рендерер SDL3&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">300</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; TTF_Font <span class="sy0">*</span>font <span class="sy0">=</span> TTF_OpenFont<span class="br0">&#40;</span><span class="st0">&quot;assets/fonts/LiberationSans-Regular.ttf&quot;</span><span class="sy0">,</span> <span class="nu0">28</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>font<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;TTF_OpenFont failed: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_Color textColor <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_Color<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">245</span><span class="sy0">,</span> <span class="nu0">240</span><span class="sy0">,</span> <span class="nu0">220</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> TTF_RenderText_Blended<span class="br0">&#40;</span>font<span class="sy0">,</span> <span class="st0">&quot;Равносторонний треугольник&quot;</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> textColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; textTexture <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="co1">// Продолжаем работу программы</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается, когда происходит новое событие (ввод мыши, нажатие клавиш и т.д.)</span>
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// Завершаем программу, сообщая ОС об успехе</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="co1">// Продолжаем работу программы</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается один раз за кадр и является сердцем программы</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Устанавливаем позицию, в которой хотим нарисовать текст</span>
&nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> <span class="nu0">10</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаем прямоугольник для хранения размеров текстуры</span>
&nbsp; &nbsp; SDL_FRect rect<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetTextureSize<span class="br0">&#40;</span>textTexture<span class="sy0">,</span> <span class="sy0">&amp;</span>rect.<span class="me1">w</span><span class="sy0">,</span> <span class="sy0">&amp;</span>rect.<span class="me1">h</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; rect.<span class="me1">x</span> <span class="sy0">=</span> x<span class="sy0">;</span>
&nbsp; &nbsp; rect.<span class="me1">y</span> <span class="sy0">=</span> y<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Очищаем экран</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">38</span><span class="sy0">,</span> <span class="nu0">43</span><span class="sy0">,</span> <span class="nu0">51</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Цвет заливки холста</span>
&nbsp; &nbsp; <span class="co1">// Начинаем с чистого холста - заливаем холст указанным выше цветов</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Отрисовываем текст</span>
&nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> textTexture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>rect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим результат на экран</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="co1">// Продолжаем работу программы</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается один раз при завершении работы</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; TTF_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL3 автоматически освободит все ресурсы подсистем (окна, рендереры) при выходе</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
Далее, два бонусных примера, которые сгенерировал ИИ Gemini.<br />
<br />
<h2>Рисуем координатные оси и правильный треугольник</h2><br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11799&amp;a= mp;d=1774043972" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="875820393"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="875820393" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Использовать функции обратного вызова вместо main()</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_ttf/SDL_ttf.h&gt;</span>
&nbsp;
<span class="co1">// Мы будем использовать этот рендерер для рисования в этом окне каждый кадр</span>
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> TTF_Font <span class="sy0">*</span>font <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="co1">// Текстуры для подписей вершин</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>coordTextures<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#123;</span> NULL<span class="sy0">,</span> NULL<span class="sy0">,</span> NULL <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Вспомогательная функция для создания текстуры из строки</span>
SDL_Texture<span class="sy0">*</span> CreateTextTexture<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*</span> text<span class="sy0">,</span> SDL_Color color<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> TTF_RenderText_Blended<span class="br0">&#40;</span>font<span class="sy0">,</span> text<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> color<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_Texture <span class="sy0">*</span>tex <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> tex<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается один раз при старте</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>TTF_Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize TTF: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Рендерер SDL3&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">300</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; TTF_Font <span class="sy0">*</span>font <span class="sy0">=</span> TTF_OpenFont<span class="br0">&#40;</span><span class="st0">&quot;assets/fonts/LiberationSans-Regular.ttf&quot;</span><span class="sy0">,</span> <span class="nu0">28</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>font<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;TTF_OpenFont failed: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_Color textColor <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_Color<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">245</span><span class="sy0">,</span> <span class="nu0">240</span><span class="sy0">,</span> <span class="nu0">220</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> TTF_RenderText_Blended<span class="br0">&#40;</span>font<span class="sy0">,</span> <span class="st0">&quot;Равносторонний треугольник&quot;</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> textColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; textTexture <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; TTF_CloseFont<span class="br0">&#40;</span>font<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="co1">// Продолжаем работу программы</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается, когда происходит новое событие (ввод мыши, нажатие клавиш и т.д.)</span>
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// Завершаем программу, сообщая ОС об успехе</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="co1">// Продолжаем работу программы</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается один раз за кадр и является сердцем программы</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">int</span> winW<span class="sy0">,</span> winH<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>winW<span class="sy0">,</span> <span class="sy0">&amp;</span>winH<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Очистка экрана</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">38</span><span class="sy0">,</span> <span class="nu0">43</span><span class="sy0">,</span> <span class="nu0">51</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Отрисовка текста (в обычных координатах: Y вниз)</span>
&nbsp; &nbsp; <span class="kw4">float</span> tw<span class="sy0">,</span> th<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetTextureSize<span class="br0">&#40;</span>textTexture<span class="sy0">,</span> <span class="sy0">&amp;</span>tw<span class="sy0">,</span> <span class="sy0">&amp;</span>th<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_FRect textRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="br0">&#40;</span>winW <span class="sy0">-</span> tw<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> <span class="nu17">20.0f</span><span class="sy0">,</span> tw<span class="sy0">,</span> th <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> textTexture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>textRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Центр координат: середина по X, и чуть ниже текста по Y</span>
&nbsp; &nbsp; <span class="kw4">float</span> originX <span class="sy0">=</span> winW <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> originY <span class="sy0">=</span> winH <span class="sy0">/</span> <span class="nu17">2.0f</span> <span class="sy0">+</span> <span class="nu17">40.0f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Вспомогательная функция для перевода наших координат в экранные</span>
&nbsp; &nbsp; <span class="co1">// Экранное_X = originX + наш_X</span>
&nbsp; &nbsp; <span class="co1">// Экранное_Y = originY - наш_Y (минус, так как в SDL Y растет вниз, а нам нужно вверх)</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Рисуем оси</span>
&nbsp; &nbsp; <span class="co1">// Ось X</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">180</span><span class="sy0">,</span> <span class="nu0">80</span><span class="sy0">,</span> <span class="nu0">80</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> originX <span class="sy0">-</span> <span class="nu0">150</span><span class="sy0">,</span> originY<span class="sy0">,</span> originX <span class="sy0">+</span> <span class="nu0">150</span><span class="sy0">,</span> originY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Ось Y</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">80</span><span class="sy0">,</span> <span class="nu0">180</span><span class="sy0">,</span> <span class="nu0">80</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> originX<span class="sy0">,</span> originY <span class="sy0">+</span> <span class="nu0">100</span><span class="sy0">,</span> originX<span class="sy0">,</span> originY <span class="sy0">-</span> <span class="nu0">120</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Рисуем правильный треугольник</span>
&nbsp; &nbsp; <span class="kw4">float</span> a <span class="sy0">=</span> <span class="nu17">150.0f</span><span class="sy0">;</span> <span class="co1">// Сторона треугольника</span>
&nbsp; &nbsp; <span class="kw4">float</span> h <span class="sy0">=</span> a <span class="sy0">*</span> SDL_sqrtf<span class="br0">&#40;</span><span class="nu17">3.0f</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> r_in <span class="sy0">=</span> h <span class="sy0">/</span> <span class="nu17">3.0f</span><span class="sy0">;</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Расстояние от центра до основания</span>
&nbsp; &nbsp; <span class="kw4">float</span> r_out <span class="sy0">=</span> <span class="nu17">2.0f</span> <span class="sy0">*</span> h <span class="sy0">/</span> <span class="nu17">3.0f</span><span class="sy0">;</span> <span class="co1">// Расстояние от центра до вершины</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Координаты вершин относительно центра (0,0), где Y смотрит вверх</span>
&nbsp; &nbsp; SDL_FPoint trianglePoints<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> originX <span class="sy0">-</span> a <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> originY <span class="sy0">+</span> r_in <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// Лево-низ (в SDL это +r_in, т.к. экранный Y вниз)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> originX <span class="sy0">+</span> a <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> originY <span class="sy0">+</span> r_in <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// Право-низ</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> originX<span class="sy0">,</span> originY <span class="sy0">-</span> r_out <span class="br0">&#125;</span><span class="sy0">,</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Вершина (в SDL это -r_out, чтобы была вверху)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> originX <span class="sy0">-</span> a <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> originY <span class="sy0">+</span> r_in <span class="br0">&#125;</span> &nbsp;<span class="co1">// Замыкаем</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">245</span><span class="sy0">,</span> <span class="nu0">240</span><span class="sy0">,</span> <span class="nu0">220</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Светло-кремовый</span>
&nbsp; &nbsp; SDL_RenderLines<span class="br0">&#40;</span>renderer<span class="sy0">,</span> trianglePoints<span class="sy0">,</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// Эта функция запускается один раз при завершении работы</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; TTF_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL3 автоматически освободит все ресурсы подсистем (окна, рендереры) при выходе</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div><h2>Подписи координат вершин треугольника</h2><br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11801&amp;a= mp;d=1774048407" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="542745485"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="542745485" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_ttf/SDL_ttf.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> TTF_Font <span class="sy0">*</span>font <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>coordTextures<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#123;</span> NULL<span class="sy0">,</span> NULL<span class="sy0">,</span> NULL <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">float</span> TRIANGLE_A <span class="sy0">=</span> <span class="nu17">280.0f</span><span class="sy0">;</span> <span class="co1">// Длина стороны треугольника</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">float</span> AXIS_X_LEN <span class="sy0">=</span> <span class="nu17">200.0f</span><span class="sy0">;</span> <span class="co1">// Половина длины оси X</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">float</span> AXIS_Y_LEN <span class="sy0">=</span> <span class="nu17">180.0f</span><span class="sy0">;</span> <span class="co1">// Длина осей вверх/вниз</span>
&nbsp;
SDL_Texture <span class="sy0">*</span>CreateTextTexture<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>text<span class="sy0">,</span> SDL_Color color<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> TTF_RenderText_Blended<span class="br0">&#40;</span>font<span class="sy0">,</span> text<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> color<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_Texture <span class="sy0">*</span>tex <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> tex<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>TTF_Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Увеличили окно для большого треугольника</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Рендерер SDL3&quot;</span><span class="sy0">,</span> <span class="nu0">500</span><span class="sy0">,</span> <span class="nu0">500</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Загружаем шрифт с базовым размером</span>
&nbsp; &nbsp; font <span class="sy0">=</span> TTF_OpenFont<span class="br0">&#40;</span><span class="st0">&quot;assets/fonts/LiberationSans-Regular.ttf&quot;</span><span class="sy0">,</span> <span class="nu0">20</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>font<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_Color titleColor <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">245</span><span class="sy0">,</span> <span class="nu0">240</span><span class="sy0">,</span> <span class="nu0">220</span><span class="sy0">,</span> <span class="nu0">255</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_Color coordColor <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">200</span><span class="sy0">,</span> <span class="nu0">200</span><span class="sy0">,</span> <span class="nu0">200</span><span class="sy0">,</span> <span class="nu0">255</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаем заголовок</span>
&nbsp; &nbsp; TTF_SetFontSize<span class="br0">&#40;</span>font<span class="sy0">,</span> <span class="nu0">28</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; textTexture <span class="sy0">=</span> CreateTextTexture<span class="br0">&#40;</span><span class="st0">&quot;Равносторонний треугольник&quot;</span><span class="sy0">,</span> titleColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Рассчитываем и создаем подписи координат</span>
&nbsp; &nbsp; TTF_SetFontSize<span class="br0">&#40;</span>font<span class="sy0">,</span> <span class="nu0">20</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Размер для координат</span>
&nbsp; &nbsp; <span class="kw4">float</span> h <span class="sy0">=</span> TRIANGLE_A <span class="sy0">*</span> SDL_sqrtf<span class="br0">&#40;</span><span class="nu17">3.0f</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> r_in <span class="sy0">=</span> h <span class="sy0">/</span> <span class="nu17">3.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> r_out <span class="sy0">=</span> <span class="nu17">2.0f</span> <span class="sy0">*</span> h <span class="sy0">/</span> <span class="nu17">3.0f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">char</span> buf<span class="br0">&#91;</span><span class="nu0">64</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Лево-низ</span>
&nbsp; &nbsp; <span class="kw3">sprintf</span><span class="br0">&#40;</span>buf<span class="sy0">,</span> <span class="st0">&quot;(%.1f, %.1f)&quot;</span><span class="sy0">,</span> <span class="sy0">-</span>TRIANGLE_A <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> <span class="sy0">-</span>r_in<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; coordTextures<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">=</span> CreateTextTexture<span class="br0">&#40;</span>buf<span class="sy0">,</span> coordColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Право-низ</span>
&nbsp; &nbsp; <span class="kw3">sprintf</span><span class="br0">&#40;</span>buf<span class="sy0">,</span> <span class="st0">&quot;(%.1f, %.1f)&quot;</span><span class="sy0">,</span> TRIANGLE_A <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> <span class="sy0">-</span>r_in<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; coordTextures<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">=</span> CreateTextTexture<span class="br0">&#40;</span>buf<span class="sy0">,</span> coordColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Верх</span>
&nbsp; &nbsp; <span class="kw3">sprintf</span><span class="br0">&#40;</span>buf<span class="sy0">,</span> <span class="st0">&quot;(0.0, %.1f)&quot;</span><span class="sy0">,</span> r_out<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; coordTextures<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span> <span class="sy0">=</span> CreateTextTexture<span class="br0">&#40;</span>buf<span class="sy0">,</span> coordColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">int</span> winW<span class="sy0">,</span> winH<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>winW<span class="sy0">,</span> <span class="sy0">&amp;</span>winH<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">38</span><span class="sy0">,</span> <span class="nu0">43</span><span class="sy0">,</span> <span class="nu0">51</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Отрисовка заголовка</span>
&nbsp; &nbsp; <span class="kw4">float</span> tw<span class="sy0">,</span> th<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetTextureSize<span class="br0">&#40;</span>textTexture<span class="sy0">,</span> <span class="sy0">&amp;</span>tw<span class="sy0">,</span> <span class="sy0">&amp;</span>th<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_FRect textRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="br0">&#40;</span>winW <span class="sy0">-</span> tw<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> <span class="nu17">20.0f</span><span class="sy0">,</span> tw<span class="sy0">,</span> th <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> textTexture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>textRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Оси координат</span>
&nbsp; &nbsp; <span class="kw4">float</span> originX <span class="sy0">=</span> winW <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> originY <span class="sy0">=</span> winH <span class="sy0">/</span> <span class="nu17">2.0f</span> <span class="sy0">+</span> <span class="nu17">50.0f</span><span class="sy0">;</span> <span class="co1">// Центр системы координат</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">180</span><span class="sy0">,</span> <span class="nu0">80</span><span class="sy0">,</span> <span class="nu0">80</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Мягкий красный</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> originX <span class="sy0">-</span> AXIS_X_LEN<span class="sy0">,</span> originY<span class="sy0">,</span> originX <span class="sy0">+</span> AXIS_X_LEN<span class="sy0">,</span> originY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">80</span><span class="sy0">,</span> <span class="nu0">180</span><span class="sy0">,</span> <span class="nu0">80</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Мягкий зеленый</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> originX<span class="sy0">,</span> originY <span class="sy0">+</span> AXIS_Y_LEN<span class="sy0">,</span> originX<span class="sy0">,</span> originY <span class="sy0">-</span> AXIS_Y_LEN<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Расчет точек треугольника</span>
&nbsp; &nbsp; <span class="kw4">float</span> h <span class="sy0">=</span> TRIANGLE_A <span class="sy0">*</span> SDL_sqrtf<span class="br0">&#40;</span><span class="nu17">3.0f</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> r_in <span class="sy0">=</span> h <span class="sy0">/</span> <span class="nu17">3.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> r_out <span class="sy0">=</span> <span class="nu17">2.0f</span> <span class="sy0">*</span> h <span class="sy0">/</span> <span class="nu17">3.0f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_FPoint pts<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> originX <span class="sy0">-</span> TRIANGLE_A <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> originY <span class="sy0">+</span> r_in <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> originX <span class="sy0">+</span> TRIANGLE_A <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> originY <span class="sy0">+</span> r_in <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> originX<span class="sy0">,</span> originY <span class="sy0">-</span> r_out <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> originX <span class="sy0">-</span> TRIANGLE_A <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span> originY <span class="sy0">+</span> r_in <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">245</span><span class="sy0">,</span> <span class="nu0">240</span><span class="sy0">,</span> <span class="nu0">220</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderLines<span class="br0">&#40;</span>renderer<span class="sy0">,</span> pts<span class="sy0">,</span> <span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Отрисовка подписей</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> <span class="nu0">3</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> cw<span class="sy0">,</span> ch<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTextureSize<span class="br0">&#40;</span>coordTextures<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">,</span> <span class="sy0">&amp;</span>cw<span class="sy0">,</span> <span class="sy0">&amp;</span>ch<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Увеличили отступ (offset), чтобы крупный текст не налипал на вершины</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> offset <span class="sy0">=</span> <span class="nu17">15.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_FRect cRect <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">x</span> <span class="sy0">-</span> cw <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pts<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">y</span> <span class="sy0">+</span> <span class="br0">&#40;</span>i <span class="sy0">==</span> <span class="nu0">2</span> <span class="sy0">?</span> <span class="sy0">-</span>ch <span class="sy0">-</span> offset <span class="sy0">:</span> offset<span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cw<span class="sy0">,</span> ch
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> coordTextures<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>cRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> <span class="nu0">3</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>coordTextures<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; TTF_CloseFont<span class="br0">&#40;</span>font<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; TTF_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="589666176"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="589666176" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>finish-zoom-text-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это будет app.exe, а</span>
<span class="co0"># в вебе было бы app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">17</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD_REQUIRED ON<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-mingw/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_ttf_DIR <span class="st0">&quot;C:/libs/SDL3_ttf-devel-3.2.2-mingw/lib/cmake/SDL3_ttf&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как &quot;обязательно&quot; или &quot;требуется&quot;</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_ttf REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3_ttf::SDL3_ttf SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>config-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="925578561"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="925578561" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win ^
-DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div>build-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="985368193"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="985368193" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> dist\win
cmake <span class="re5">--build</span> .
<span class="kw3">cd</span> ..\..</pre></td></tr></table></div></td></tr></tbody></table></div>run-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="931793292"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="931793292" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">dist\win\app</pre></td></tr></table></div></td></tr></tbody></table></div>
			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11787&amp;d=1773920267" rel="Lightbox" id="attachment11787" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11787&amp;thumb=1&amp;d=1773920267" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: a565eb29-8960-4c0c-a0ff-0ec0b5a204e3.png
Просмотров: 708
Размер:	6.4 Кб
ID:	11787" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11792&amp;d=1773925673" rel="Lightbox" id="attachment11792" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11792&amp;thumb=1&amp;d=1773925673" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: f3e96ab3-fc40-4975-ace3-e756d6e4dbb4.png
Просмотров: 710
Размер:	3.6 Кб
ID:	11792" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11795&amp;d=1773931709" rel="Lightbox" id="attachment11795" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11795&amp;thumb=1&amp;d=1773931709" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 2209237c-1029-4462-a4a3-5f2ff14115b8.png
Просмотров: 695
Размер:	7.3 Кб
ID:	11795" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11799&amp;d=1774043972" rel="Lightbox" id="attachment11799" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11799&amp;thumb=1&amp;d=1774043972" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: b17e11af-3200-4ff8-bbbb-854d899aef29.png
Просмотров: 679
Размер:	9.2 Кб
ID:	11799" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11801&amp;d=1774048407" rel="Lightbox" id="attachment11801" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11801&amp;thumb=1&amp;d=1774048407" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: a9f8e10b-76f9-4e27-b5fd-a01418a0883a.png
Просмотров: 9761
Размер:	18.0 Кб
ID:	11801" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11783&amp;d=1773919892">SDL3-devel-3.4.2-mingw.zip</a> (2.65 Мб, 94 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11784&amp;d=1773919892">SDL3-3.4.2-win32-x64.zip</a> (1.10 Мб, 76 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11785&amp;d=1773919892">SDL3_ttf-devel-3.2.2-mingw.zip</a> (2.63 Мб, 95 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11786&amp;d=1773919892">SDL3_ttf-3.2.2-win32-x64.zip</a> (979.6 Кб, 93 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11794&amp;d=1773928600">LiberationSans-Regular.zip</a> (206.0 Кб, 55 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11797&amp;d=1773943776">start-text-sdl3-c.zip</a> (3.0 Кб, 52 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11811&amp;d=1774322222">finish-text-sdl3-c.zip</a> (210.0 Кб, 273 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11812&amp;d=1774322222">finish-text-sdl3-cpp.zip</a> (210.1 Кб, 262 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10815.html</guid>
		</item>
		<item>
			<title>SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++</title>
			<link>https://www.cyberforum.ru/blogs/416874/10813.html</link>
			<pubDate>Mon, 16 Mar 2026 22:23:38 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Финальные проекты на Си...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Финальные проекты на Си и на C++:<br />
<br />
<ul><li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11773&amp;d=1773704355">finish-rectangles-sdl3-c.zip</a></li>
<li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11774&amp;d=1773704355">finish-rectangles-sdl3-cpp.zip</a></li>
</ul><br />
Результат:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11775&amp;a= mp;d=1773704784" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
<h2>Настройка окружения</h2><br />
<br />
<ul><li>Установите CMake и MinGW 13.1 по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10793.html">Установка CMake и MinGW 13.1</a></li>
<li>Скачайте библиотеку SDL3 по ссылке: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11755&amp;d=1773692460">SDL3-devel-3.4.2-mingw.zip</a></li>
<li>Примечание. Эту библиотеку в собранном виде я скачал <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2" target="_blank" title="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2">по этой ссылке</a> с официальной страницы со сборками под разные платформы. Но я немного сократил путь к вложенным папкам</li>
<li>Скачайте архив с динамической библиотекой SDL3.dll: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11756&amp;d=1773692460">SDL3-3.4.2-win32-x64.zip</a></li>
<li>Примечание. Этот архив я скачал <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2" target="_blank" title="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2">по этой ссылке</a> с официальной страницы.</li>
<li>Извлеките содержимое архивов выше в какую-нибудь общую папку, например, с именем &quot;libs&quot; на C:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11752&amp;d=1773692299" border="0" alt="Название: a03ecbb7-dfa0-490c-88ca-2d40a00425ba.png
Просмотров: 1201

Размер: 4.1 Кб" style="margin: 5px" /></li>
<li>Путь к SDL3.dll (C:\libs\SDL3-3.4.2-win32-x64) добавьте в переменную окружения Path:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11753&amp;d=1773692356" border="0" alt="Название: f794393d-3419-460a-879b-06355f53c4e0.png
Просмотров: 1196

Размер: 8.0 Кб" style="margin: 5px" /></li>
<li>Примечание 1. Диалоговое окно с Path можно открыть, если нажать Win + R и набрать команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="876304912"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="876304912" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">sysdm.cpl ,<span class="nu0">3</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. &quot;,3&quot; означает, что будет открыта третья вкладка в диалоговом окне настроек:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11754&amp;a= mp;d=1773692430" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Нажмите на кнопку &quot;Environment Variables...&quot; и добавьте скопированный путь в Path</li>
</ul><br />
<h2>Создание проекта</h2><br />
<br />
<ul><li>Скачайте стартовый проект: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11767&amp;d=1773699057">start-rectangles-sdl3-c.zip</a></li>
<li>Примечание. Этот стартовый проект был создан по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/2953.html">Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++</a></li>
<li>Извлеките пример из архива:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11757&amp;d=1773693380" border="0" alt="Название: bf0460df-840a-4524-97a2-cf9b1a6318a3.png
Просмотров: 1197

Размер: 3.0 Кб" style="margin: 5px" /></li>
<li>Откройте папку примера в каком-нибудь текстовом редакторе - например, в Sublime Text 4, Notepad++, VS Code и т.д.</li>
<li>Откройте файл &quot;CMakeLists.txt&quot; и убедитесь, что путь к библиотеке SDL3 такой же как у вас и при необходимости измените его на ваш путь:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="430200930"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="430200930" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-mingw/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте консоль в текущей папке и поочерёдно введите команды для конфигурирования, сборки и запуска EXE:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="486479532"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="486479532" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">config-exe
build-exe
run-exe</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Будет запущено приложение. Мы протестировали корректный запуск стартового примера</li>
</ul><br />
<h2>Добавляем прямоугольники на холст</h2><br />
<br />
Официальный репозиторий SDL3 содержит примеры рисования в папке <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/tree/0bbbf3d43b0fd47c338715ac077e303a14e6f9e4/examples/renderer" target="_blank" title="https://github.com/libsdl-org/SDL/tree/0bbbf3d43b0fd47c338715ac077e303a14e6f9e4/examples/renderer">examples/renderer</a><br />
<br />
<ul><li>Откройте файл по ссылке: <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/blob/0bbbf3d43b0fd47c338715ac077e303a14e6f9e4/examples/renderer/05-rectangles/rectangles.c" target="_blank" title="https://github.com/libsdl-org/SDL/blob/0bbbf3d43b0fd47c338715ac077e303a14e6f9e4/examples/renderer/05-rectangles/rectangles.c">examples/renderer/05-rectangles/rectangles.c</a></li>
<li>Комментарии в этом файле на английском языке. Переведём комментарии на русский с помощью ИИ. Например, откройте промпт Gemini. Напишите следующий текст в промпт (после текста вставьте скопированный код):<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">Переведи комментарии на русский, но код не меняй. Не переводи вывод в консоль. Вот код:</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table></li>
<li>Здесь мы можем может изучать пример по переведённым на русский комментариям. Там нужно найти в примере строчку, где рисуется прямоугольник командой SDL_RenderFillRect() и посмотреть, как она вызывается - с какими параметрами:<br />
<br />
src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="476716659"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="476716659" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
</pre></td><td class="de1"><pre class="de1"><span class="coMULTI">/*</span>
<span class="coMULTI">&nbsp;* Этот пример создает окно и рендерер SDL, а затем рисует </span>
<span class="coMULTI">&nbsp;* несколько прямоугольников в каждом кадре.</span>
<span class="coMULTI">&nbsp;*</span>
<span class="coMULTI">&nbsp;* Этот код является общественным достоянием. Смело используйте его в любых целях!</span>
<span class="coMULTI">&nbsp;*/</span>
&nbsp;
<span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 &nbsp;/* использовать колбэки вместо main() */</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
&nbsp;
<span class="coMULTI">/* Мы будем использовать этот рендерер для отрисовки в этом окне каждый кадр. */</span>
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="co2">#define WINDOW_WIDTH 640</span>
<span class="co2">#define WINDOW_HEIGHT 480</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз при старте. */</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_SetAppMetadata<span class="br0">&#40;</span><span class="st0">&quot;Example Renderer Rectangles&quot;</span><span class="sy0">,</span> <span class="st0">&quot;1.0&quot;</span><span class="sy0">,</span> <span class="st0">&quot;com.example.renderer-rectangles&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;examples/renderer/rectangles&quot;</span><span class="sy0">,</span> WINDOW_WIDTH<span class="sy0">,</span> WINDOW_HEIGHT<span class="sy0">,</span> SDL_WINDOW_RESIZABLE<span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_SetRenderLogicalPresentation<span class="br0">&#40;</span>renderer<span class="sy0">,</span> WINDOW_WIDTH<span class="sy0">,</span> WINDOW_HEIGHT<span class="sy0">,</span> SDL_LOGICAL_PRESENTATION_LETTERBOX<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем работу программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается, когда происходит новое событие (ввод мыши, нажатие клавиш и т.д.). */</span>
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* завершаем программу, сообщая ОС об успехе. */</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем работу программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз за кадр и является сердцем программы. */</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_FRect rects<span class="br0">&#91;</span><span class="nu0">16</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> Uint64 now <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">int</span> i<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* заставим прямоугольники увеличиваться и уменьшаться в течение нескольких секунд. */</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> direction <span class="sy0">=</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>now <span class="sy0">%</span> <span class="nu0">2000</span><span class="br0">&#41;</span> <span class="sy0">&gt;=</span> <span class="nu0">1000</span><span class="br0">&#41;</span> <span class="sy0">?</span> <span class="nu17">1.0f</span> <span class="sy0">:</span> <span class="sy0">-</span><span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> scale <span class="sy0">=</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>now <span class="sy0">%</span> <span class="nu0">1000</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu0">500</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">500.0f</span><span class="br0">&#41;</span> <span class="sy0">*</span> direction<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* как вы можете видеть здесь, рендеринг рисует поверх того, что было нарисовано ранее. */</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* черный, непрозрачный */</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* начинаем с чистого холста. */</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* Прямоугольники состоят из набора координат X и Y, а также ширины и</span>
<span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp;высоты. (0, 0) — это верхний левый угол окна, и чем больше числа, тем</span>
<span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp;ниже и правее уходит точка. Это не совсем то, как работает геометрия, но это</span>
<span class="coMULTI">&nbsp; &nbsp; &nbsp; &nbsp;стандарт для 2D-графики. */</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* Давайте нарисуем один прямоугольник (точнее, квадрат). */</span>
&nbsp; &nbsp; rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">x</span> <span class="sy0">=</span> rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">y</span> <span class="sy0">=</span> <span class="nu0">100</span><span class="sy0">;</span>
&nbsp; &nbsp; rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">w</span> <span class="sy0">=</span> rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">h</span> <span class="sy0">=</span> <span class="nu0">100</span> <span class="sy0">+</span> <span class="br0">&#40;</span><span class="nu0">100</span> <span class="sy0">*</span> scale<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* красный, непрозрачный */</span>
&nbsp; &nbsp; SDL_RenderRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* Теперь давайте нарисуем несколько прямоугольников одним вызовом функции. */</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span>i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> <span class="nu0">3</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> size <span class="sy0">=</span> <span class="br0">&#40;</span>i<span class="sy0">+</span><span class="nu0">1</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu17">50.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">w</span> <span class="sy0">=</span> rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">h</span> <span class="sy0">=</span> size <span class="sy0">+</span> <span class="br0">&#40;</span>size <span class="sy0">*</span> scale<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">x</span> <span class="sy0">=</span> <span class="br0">&#40;</span>WINDOW_WIDTH <span class="sy0">-</span> rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">w</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu0">2</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* центрируем. */</span>
&nbsp; &nbsp; &nbsp; &nbsp; rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">y</span> <span class="sy0">=</span> <span class="br0">&#40;</span>WINDOW_HEIGHT <span class="sy0">-</span> rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">h</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu0">2</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* центрируем. */</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* зеленый, непрозрачный */</span>
&nbsp; &nbsp; SDL_RenderRects<span class="br0">&#40;</span>renderer<span class="sy0">,</span> rects<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* рисуем три прямоугольника за раз */</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* это были контуры прямоугольников. Вы также можете рисовать *заполненные* прямоугольники! */</span>
&nbsp; &nbsp; rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">x</span> <span class="sy0">=</span> <span class="nu0">400</span><span class="sy0">;</span>
&nbsp; &nbsp; rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">y</span> <span class="sy0">=</span> <span class="nu0">50</span><span class="sy0">;</span>
&nbsp; &nbsp; rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">w</span> <span class="sy0">=</span> <span class="nu0">100</span> <span class="sy0">+</span> <span class="br0">&#40;</span><span class="nu0">100</span> <span class="sy0">*</span> scale<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">h</span> <span class="sy0">=</span> <span class="nu0">50</span> <span class="sy0">+</span> <span class="br0">&#40;</span><span class="nu0">50</span> <span class="sy0">*</span> scale<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* синий, непрозрачный */</span>
&nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>rects<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* ...а также заполнить целую пачку прямоугольников сразу... */</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span>i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> SDL_arraysize<span class="br0">&#40;</span>rects<span class="br0">&#41;</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> w <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span>WINDOW_WIDTH <span class="sy0">/</span> SDL_arraysize<span class="br0">&#40;</span>rects<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> h <span class="sy0">=</span> i <span class="sy0">*</span> <span class="nu17">8.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">x</span> <span class="sy0">=</span> i <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">y</span> <span class="sy0">=</span> WINDOW_HEIGHT <span class="sy0">-</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">w</span> <span class="sy0">=</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rects<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">h</span> <span class="sy0">=</span> h<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* белый, непрозрачный */</span>
&nbsp; &nbsp; SDL_RenderFillRects<span class="br0">&#40;</span>renderer<span class="sy0">,</span> rects<span class="sy0">,</span> SDL_arraysize<span class="br0">&#40;</span>rects<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* выводим всё это на экран! */</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем работу программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз при завершении работы. */</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="coMULTI">/* SDL сама очистит за нами окно и рендерер. */</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Временно удалите код из &quot;src/main.c&quot; и замените его на код выше</li>
<li>Соберите проект командой &quot;build-exe&quot; и запустите EXE командой &quot;run-exe&quot;. Будет показана анимация из заполненных и пустых прямоугольников:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11760&amp;a= mp;d=1773695126" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>После тестирования официального примера верните обратно код стартового примера нажатием на Ctrl+Z</li>
<li>В стартовом примере вывод ошибок в консоль на русском. Лучше выводить на английском, чтобы во консоли гарантировано отображалось без проблем с кодировкой. Замените вывод на английский:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="660650453"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="660650453" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Прямоугольники на SDL3&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">300</span><span class="sy0">,</span> SDL_WINDOW_RESIZABLE<span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Мы можем посмотреть, как рисуются прямоугольники в запущенном примере и повторить, но сначала удалите код из стартового примера, который меняет цвет фона:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="815891979"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="815891979" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">double</span> now <span class="sy0">=</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu16">1000.0</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* конвертируем миллисекунды в секунды. */</span>
&nbsp; &nbsp; <span class="coMULTI">/* выбираем цвет для кадра, который будем рисовать. Трюк с синусоидой заставляет цвета плавно сменять друг друга. */</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> red <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> green <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now <span class="sy0">+</span> SDL_PI_D <span class="sy0">*</span> <span class="nu0">2</span> <span class="sy0">/</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> blue <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now <span class="sy0">+</span> SDL_PI_D <span class="sy0">*</span> <span class="nu0">4</span> <span class="sy0">/</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColorFloat<span class="br0">&#40;</span>renderer<span class="sy0">,</span> red<span class="sy0">,</span> green<span class="sy0">,</span> blue<span class="sy0">,</span> SDL_ALPHA_OPAQUE_FLOAT<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* новый цвет, полная непрозрачность. */</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Вместо этого кода напечатайте строку кода, которая вы:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="590059142"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="590059142" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">SDL_SetRenderDrawColorFloat<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu17">0.2f</span><span class="sy0">,</span> <span class="nu17">0.2f</span><span class="sy0">,</span> <span class="nu17">0.2f</span><span class="sy0">,</span> SDL_ALPHA_OPAQUE_FLOAT<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте код рисования двух прямоугольников:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="912270353"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="912270353" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="de1"><pre class="de1"><span class="coMULTI">/* Эта функция запускается один раз за кадр и является сердцем программы. */</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColorFloat<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu17">0.2f</span><span class="sy0">,</span> <span class="nu17">0.2f</span><span class="sy0">,</span> <span class="nu17">0.2f</span><span class="sy0">,</span> SDL_ALPHA_OPAQUE_FLOAT<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* очищаем окно цветом отрисовки. */</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_FRect rect1<span class="sy0">;</span>
&nbsp; &nbsp; rect1.<span class="me1">x</span> <span class="sy0">=</span> <span class="nu0">100</span><span class="sy0">;</span>
&nbsp; &nbsp; rect1.<span class="me1">y</span> <span class="sy0">=</span> <span class="nu0">50</span><span class="sy0">;</span>
&nbsp; &nbsp; rect1.<span class="me1">w</span> <span class="sy0">=</span> <span class="nu0">200</span><span class="sy0">;</span>
&nbsp; &nbsp; rect1.<span class="me1">h</span> <span class="sy0">=</span> <span class="nu0">60</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>rect1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_FRect rect2<span class="sy0">;</span>
&nbsp; &nbsp; rect2.<span class="me1">x</span> <span class="sy0">=</span> <span class="nu0">50</span><span class="sy0">;</span>
&nbsp; &nbsp; rect2.<span class="me1">y</span> <span class="sy0">=</span> <span class="nu0">200</span><span class="sy0">;</span>
&nbsp; &nbsp; rect2.<span class="me1">w</span> <span class="sy0">=</span> <span class="nu0">100</span><span class="sy0">;</span>
&nbsp; &nbsp; rect2.<span class="me1">h</span> <span class="sy0">=</span> <span class="nu0">50</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>rect2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* выводим свежеочищенный результат на экран. */</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем работу программы! */</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Измените метаданные в начале функции SDL_AppInit():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="552011307"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="552011307" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="coMULTI">/* Эта функция запускается один раз при старте. */</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_SetAppMetadata<span class="br0">&#40;</span><span class="st0">&quot;Example Renderer Rectangles&quot;</span><span class="sy0">,</span> <span class="st0">&quot;1.0&quot;</span><span class="sy0">,</span> <span class="st0">&quot;com.example.renderer-rectangles&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выставите размер окна поменьше, чем было раньше в функции создания окна:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="847349864"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="847349864" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Прямоугольники на SDL3&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">300</span><span class="sy0">,</span> SDL_WINDOW_RESIZABLE<span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_SetRenderLogicalPresentation<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">300</span><span class="sy0">,</span> SDL_LOGICAL_PRESENTATION_LETTERBOX<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Соберите проект командой &quot;build-exe&quot; и запустите EXE командой &quot;run-exe&quot;. Выводится два прямоугольника с разными координатами, размерами и разных цветов:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11775&amp;a= mp;d=1773704784" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Если вы откроете &quot;Диспетчер задач&quot;, то вы увидите большую нагрузку на GPU если у вас интегрированная карта:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11763&amp;a= mp;d=1773697058" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Чтобы существенно на порядок снизить нагрузку на GPU включим вертикальную синхронизацию после команды создания окна:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="373076728"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="373076728" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Результат - GPU загружен значительно меньше, как и CPU:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11764&amp;a= mp;d=1773697281" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
</ul><br />
<h2>Сборка в Release</h2><br />
<br />
В отладочном режиме мы показываем консоль, но в Release режиме её нужно скрывать и показывать только окно. Первым шагом убираем консоль.<br />
<br />
<ul><li>Отключаем показ консоли. Для этого открываем файл &quot;CMakeLists.txt&quot; и добавляем WIN32 здесь:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="375502482"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="375502482" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">add_executable<span class="br0">&#40;</span>app WIN32<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>EXE собранный в Debug режиме весит 83.6 KB (лежим этот EXE в папке &quot;dist/win&quot;)</li>
<li>Открываем файл &quot;config-exe.bat&quot; и меняем Debug на Release:<br />
<br />
config-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="973424468"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="973424468" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win ^
-DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Проводим конфигурирование командой &quot;config-exe&quot; и сборку командой &quot;build-exe&quot; и мы видим, что в папке &quot;dist/win&quot; лежит EXE весом 62.3 KB</li>
<li>Чтобы распространять программу, нужно к EXE подложить SDL3.dll весом 2.66 MB. Эта DLL лежит в папке &quot;C:\libs\SDL3-3.4.2-win32-x64&quot;, которую мы добавили в Path</li>
<li>Для разработки, лучше использовать режим Debug, то есть после сборки в релиз лучше вернуть настройку в config-exe.bat обратно в Debug:<br />
<br />
config-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="634921951"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="634921951" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win ^
-DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Сборка созданного примера в Qt Creator</h2><br />
<br />
<ul><li>Скачайте и установите Qt Creator: <a rel="nofollow noopener noreferrer" href="https://github.com/qt-creator/qt-creator/releases" target="_blank" title="https://github.com/qt-creator/qt-creator/releases">https://github.com/qt-creator/qt-creator/releases</a></li>
<li>Запустите Qt Creator, набрав в поиске программ &quot;Qt Creator&quot;</li>
<li>В левом верхнем углу нажмите &quot;Fire&quot; &gt; &quot;Open File or Project...&quot;</li>
<li>В открывшемся диалоговом окне перейдите в папку &quot;start-rectangles-sdl3-c&quot; и выберите файл &quot;CMakeLists.txt&quot;</li>
<li>Проект будет открыт в Qt Creator. Вы может запустить проект на выполнение нажав зелёный треугольник в левом нижнем углу</li>
<li>Поставьте точку остановка, кликнув мышкой слева от номера строки кода и нажмите зелёный треугольник с жуком в левом нижнем углу. Запустится отладка по шагам. Вы можете нажимать кнопки на панели инструментов - например, кнопку для выполнения кода без захода внутрь функции или с заходом внутрь функции</li>
</ul><br />
<h2>Переделываем C-проект в C++-проект</h2><br />
<br />
<ul><li>Сделайте копию папки проекта выше и переименуйте папку, написав на конце названия &quot;-cpp&quot; вместо &quot;-с&quot;, например: &quot;start-rectangles-sdl3-cpp&quot;</li>
<li>В этом новом проекте удалите папку &quot;dist&quot;, если вы собирали проект командами: &quot;config-exe&quot; и &quot;build-exe&quot;</li>
<li>Удалите папку &quot;build&quot;, если вы собирали проект до копирования папки с помощью Qt Creator</li>
<li>Откройте папку &quot;start-rectangles-sdl3-cpp&quot; в каком-нибудь редакторе кода, например, в Sublime Text 4, Nodepad++, либо в IDE Qt Creator (&quot;File&quot; &gt; &quot;Open File or Project&quot; -&gt; выберите файл &quot;CMakeLists.txt&quot;)</li>
<li>В редакторе кода или IDE откройте файл &quot;CMakeLists.txt&quot; для редактирования</li>
<li>Измените имя проекта в строке:<br />
<br />
Было:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="21383311"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="21383311" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">project<span class="br0">&#40;</span>start-rectangles-sdl3-c<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="802146166"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="802146166" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">project<span class="br0">&#40;</span>start-rectangles-sdl3-cpp<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Замените стандарт C на стандарт C++:<br />
<br />
Было:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="646515905"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="646515905" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">17</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD_REQUIRED ON<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="991544889"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="991544889" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Устанавливаем стандарт C++</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_CXX_STANDARD <span class="nu0">20</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_CXX_STANDARD_REQUIRED ON<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Измените расширение файла исходного кода:<br />
<br />
Было:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="757751698"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="757751698" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="794546450"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="794546450" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.cpp
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Переименуйте файл &quot;src/main.c&quot; в &quot;src/main.cpp&quot;<br /></li>
<li>Введите следующие команды в консоли для конфигурирования, сборки и запуска EXE:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="359350375"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="359350375" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">config-exe
build-exe
run-exe</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11754&amp;d=1773692430" rel="Lightbox" id="attachment11754" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11754&amp;thumb=1&amp;d=1773692430" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 875a7959-f639-4ee2-bed7-13522da5ed63.png
Просмотров: 1288
Размер:	21.9 Кб
ID:	11754" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11760&amp;d=1773695126" rel="Lightbox" id="attachment11760" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11760&amp;thumb=1&amp;d=1773695126" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: official-rectangles-sdl3-c.gif
Просмотров: 1261
Размер:	82.5 Кб
ID:	11760" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11763&amp;d=1773697058" rel="Lightbox" id="attachment11763" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11763&amp;thumb=1&amp;d=1773697058" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 7397d784-5833-40e4-a36c-5745db0ca9db.png
Просмотров: 1281
Размер:	5.2 Кб
ID:	11763" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11764&amp;d=1773697281" rel="Lightbox" id="attachment11764" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11764&amp;thumb=1&amp;d=1773697281" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 35e66aa4-abb2-408f-8e42-6f8730ff826c.png
Просмотров: 1261
Размер:	5.3 Кб
ID:	11764" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11775&amp;d=1773704784" rel="Lightbox" id="attachment11775" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11775&amp;thumb=1&amp;d=1773704784" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: f2a6f6ef-b884-4306-b1f9-2d2f1d3e59b5.png
Просмотров: 10983
Размер:	4.2 Кб
ID:	11775" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11755&amp;d=1773692460">SDL3-devel-3.4.2-mingw.zip</a> (2.65 Мб, 272 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11756&amp;d=1773692460">SDL3-3.4.2-win32-x64.zip</a> (1.10 Мб, 132 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11767&amp;d=1773699057">start-rectangles-sdl3-c.zip</a> (3.6 Кб, 117 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11773&amp;d=1773704355">finish-rectangles-sdl3-c.zip</a> (3.5 Кб, 267 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11774&amp;d=1773704355">finish-rectangles-sdl3-cpp.zip</a> (3.5 Кб, 268 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10813.html</guid>
		</item>
		<item>
			<title>SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++</title>
			<link>https://www.cyberforum.ru/blogs/416874/2953.html</link>
			<pubDate>Tue, 10 Mar 2026 11:45:46 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Финальные проекты на Си...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Финальные проекты на Си и на C++:<ul><li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11723&amp;d=1773143126">hello-sdl3-c.zip</a></li>
<li><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11724&amp;d=1773143126">hello-sdl3-cpp.zip</a></li>
</ul><br />
Результат:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11726&amp;a= mp;d=1773143591" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<ul><li>Установите CMake и MinGW 13.1 по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10793.html">Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE</a></li>
<li>Скачайте библиотеку SDL3 по ссылке: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11718&amp;d=1773139606">SDL3-devel-3.4.2-mingw.zip</a></li>
<li>Примечание. Эту библиотеку в собранном виде я скачал <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2" target="_blank" title="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2">по этой ссылке</a> с официальной страницы со сборками под разные платформы. Но я немного сократил путь к вложенным папкам</li>
<li>Скачайте архив с динамической библиотекой SDL3.dll: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11727&amp;d=1773221305">SDL3-3.4.2-win32-x64.zip</a></li>
<li>Примечание. Этот архив я скачал <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2" target="_blank" title="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2">по этой ссылке</a> с официальной страницы.</li>
<li>Извлеките содержимое архивов выше в какую-нибудь общую папку, например, с именем &quot;libs&quot; на C:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11728&amp;d=1773221444" border="0" alt="Название: 09df8734-bd0c-407e-a1e5-31e4a642593e.png
Просмотров: 1845

Размер: 4.1 Кб" style="margin: 5px" /></li>
<li>Путь к SDL3.dll (C:\libs\SDL3-3.4.2-win32-x64) добавьте в переменную окружения Path:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11729&amp;d=1773221628" border="0" alt="Название: 36086b8e-abaf-467a-8a2b-552b0c553ec7.png
Просмотров: 1833

Размер: 8.0 Кб" style="margin: 5px" /></li>
<li>Примечание. Диалоговое окно с Path можно открыть, если нажать Win + R и набрать команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="135759113"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="135759113" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">sysdm.cpl ,<span class="nu0">3</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;,3&quot; означает, что будет открыта третья вкладка в диалоговом окне настроек:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11731&amp;a= mp;d=1773222538" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Создайте новую пустую папку под названием &quot;hello-sdl3-c&quot;</li>
<li>Откройте эту папку в текстовом редакторе - например, в Sublime Text 4, Notepad++, VS Code и т.д.</li>
<li>Создайте внутри этой папки файл &quot;CMakeLists.txt&quot; и скопируйте в него следующий код:<br />
<br />
CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="130511675"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="130511675" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>hello-world-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это app.exe, а в вебе было бы app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В проекте создайте папку &quot;src&quot;, а в папке &quot;src&quot; файл &quot;main.c&quot;</li>
<li>Перейдите <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/blob/0bbbf3d43b0fd47c338715ac077e303a14e6f9e4/examples/renderer/01-clear/clear.c" target="_blank" title="https://github.com/libsdl-org/SDL/blob/0bbbf3d43b0fd47c338715ac077e303a14e6f9e4/examples/renderer/01-clear/clear.c">по этой ссылке</a> на официальный пример &quot;clear.c&quot; и скопируйте содержимое файла &quot;clear.c&quot;</li>
<li>Вставьте содержимое файла &quot;clear.c&quot; в промпт ИИ, например, Gemini и попросите в промпте:<br />
<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">Переведи комментарии на русский не меняя код</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table></li>
<li>Скопируйте полученный код и вставьте его в файл &quot;src/main.c&quot;<br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="505830761"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="505830761" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
</pre></td><td class="de1"><pre class="de1"><span class="coMULTI">/*</span>
<span class="coMULTI">&nbsp;* Этот пример создает окно и рендерер SDL, а затем очищает</span>
<span class="coMULTI">&nbsp;* окно разным цветом каждый кадр, так что в итоге вы получите окно,</span>
<span class="coMULTI">&nbsp;* цвет которого плавно меняется.</span>
<span class="coMULTI">&nbsp;*</span>
<span class="coMULTI">&nbsp;* Этот код является общественным достоянием. Используйте его для любых целей!</span>
<span class="coMULTI">&nbsp;*/</span>
&nbsp;
<span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 &nbsp;/* использовать функции обратного вызова вместо main() */</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
&nbsp;
<span class="coMULTI">/* Мы будем использовать этот рендерер для рисования в этом окне каждый кадр. */</span>
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз при старте. */</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_SetAppMetadata<span class="br0">&#40;</span><span class="st0">&quot;Example Renderer Clear&quot;</span><span class="sy0">,</span> <span class="st0">&quot;1.0&quot;</span><span class="sy0">,</span> <span class="st0">&quot;com.example.renderer-clear&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Не удалось инициализировать SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;examples/renderer/clear&quot;</span><span class="sy0">,</span> <span class="nu0">640</span><span class="sy0">,</span> <span class="nu0">480</span><span class="sy0">,</span> SDL_WINDOW_RESIZABLE<span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Не удалось создать окно/рендерер: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_SetRenderLogicalPresentation<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">640</span><span class="sy0">,</span> <span class="nu0">480</span><span class="sy0">,</span> SDL_LOGICAL_PRESENTATION_LETTERBOX<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем работу программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается, когда происходит новое событие (ввод мыши, нажатие клавиш и т.д.). */</span>
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* завершаем программу, сообщая ОС об успехе. */</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем работу программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз за кадр и является сердцем программы. */</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">double</span> now <span class="sy0">=</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu16">1000.0</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* конвертируем миллисекунды в секунды. */</span>
&nbsp; &nbsp; <span class="coMULTI">/* выбираем цвет для кадра, который будем рисовать. Трюк с синусоидой заставляет цвета плавно сменять друг друга. */</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> red <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> green <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now <span class="sy0">+</span> SDL_PI_D <span class="sy0">*</span> <span class="nu0">2</span> <span class="sy0">/</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> blue <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now <span class="sy0">+</span> SDL_PI_D <span class="sy0">*</span> <span class="nu0">4</span> <span class="sy0">/</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColorFloat<span class="br0">&#40;</span>renderer<span class="sy0">,</span> red<span class="sy0">,</span> green<span class="sy0">,</span> blue<span class="sy0">,</span> SDL_ALPHA_OPAQUE_FLOAT<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* новый цвет, полная непрозрачность. */</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* очищаем окно цветом отрисовки. */</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* выводим свежеочищенный результат на экран. */</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем работу программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз при завершении работы. */</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="coMULTI">/* SDL сама очистит окно и рендерер за нас. */</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Здесь вы можете копировать функции и строки кода в ИИ, например, в Gemini и просить объяснить простыми словами, что делает код. Читайте комментарии в коде выше. Код в итоге покажет окно, а фон холста будет плавно менять цвет. На официальном репозитории много примеров для начинающих в папке <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/tree/main/examples" target="_blank" title="https://github.com/libsdl-org/SDL/tree/main/examples">examples</a>, которые необходимо изучать с помощью ИИ, а чтобы ИИ вам доходчиво объяснял, просите его объяснять простыми словами<br /></li>
<li>Перейдите в папку &quot;C:\libs&quot; и скопируйте следующий путь:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11722&amp;a= mp;d=1773142102" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br /></li>
<li>Вставьте этот пусть в файл &quot;CMakeLists.txt&quot;, создав переменную SDL3_DIR, и замените обратные косые черты на прямые, вот так:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="95426876"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="95426876" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-mingw/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте команду поиска библиотеки и команду для линковки:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="141051948"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="141051948" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В итоге получился файл:<br />
<br />
CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="224729437"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="224729437" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>hello-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это будет app.exe, а в вебе было бы app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-mingw/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте консоль в папке проекта и введите команду конфигурирования проекта:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="339906779"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="339906779" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win -DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div>, где элементы команды означают следующее:<br />
<ul><li>cmake - команда CMake</li>
<li>-G &quot;MinGW Makefiles&quot; - используем MinGW</li>
<li>-S . - указываем, что источник &quot;Source&quot;, то есть файл CMakeLists.txt находится в текущей папке</li>
<li>-B dist/win - указываем куда сохранять конфигурационные файлы и для этого мы указываем, что нужно создать папку &quot;dist/win&quot;</li>
<li>-DCMAKE_BUILD_TYPE=Debug - указываем, что сборка будет отладочная. Она больше чем Release, но Debug собирается быстрее (хотя для Desktop разницы в скорости сборки для маленьких проектов нет, а для WebAssembly разница огромная - пара секунд для Debug и 15 и более секунд на Release)</li>
</ul></li>
<li>Введите команды для сборки приложения в EXE:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="937930678"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="937930678" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> dist\win</pre></td></tr></table></div></td></tr></tbody></table></div><div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="56880809"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="56880809" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--build</span> .</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создан EXE с именем &quot;app.exe&quot;. Для его запуска здесь же в открытой консоли введите команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="375705565"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="375705565" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">app</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Появится окно, где фон холста будет плавно переливаться разными цветами</li>
<li>Примечание. Теперь вы можете менять код и сохранять на Ctrl+S, а в консоли достаточно будет нажать кнопку-стрелку вверх, чтобы выбрать команду &quot;cmake --build .&quot; и нажать Enter. Команда конфигурирования выполняется только один раз. Если вы куда-то перенесёте папку &quot;hello-world-c&quot; или переименуете её, то нужно будет удалить папку &quot;dist&quot; и сделать конфигурирование снова той же командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="432681992"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="432681992" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win -DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создайте три батника, чтобы проще было делать конфигурирование, сборку и запуск приложения:<br />
<br />
config-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="643079098"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="643079098" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win -DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div>build-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="996344940"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="996344940" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> dist\win
cmake <span class="re5">--build</span> .
<span class="kw3">cd</span> ..\..</pre></td></tr></table></div></td></tr></tbody></table></div>run-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="128843714"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="128843714" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">dist\win\app</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Теперь можно набирать очень быстро команды:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="113367682"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="113367682" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-exe</pre></td></tr></table></div></td></tr></tbody></table></div><div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="341588540"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="341588540" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-exe</pre></td></tr></table></div></td></tr></tbody></table></div><div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="472379442"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="472379442" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">run-exe</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После первого запуска команд их можно выбирать клавишами-стрелками в CMD. Например, изменили что-то в коде и клавишами-стрелками в CMD выбрали &quot;build-exe&quot;, а после сборки выбрали &quot;run-exe&quot;</li>
</ul><br />
<h2>Сборка созданного примера в Qt Creator</h2><br />
<br />
<ul><li>Скачайте и установите Qt Creator версии 18 <a rel="nofollow noopener noreferrer" href="https://github.com/qt-creator/qt-creator/releases/tag/v18.0.2" target="_blank" title="https://github.com/qt-creator/qt-creator/releases/tag/v18.0.2">по ссылке</a>. Установщик вы найдёте в списке &quot;Assets&quot;</li>
<li>Запустите Qt Creator, набрав в поиске программ &quot;Qt Creator&quot;</li>
<li>В левом верхнем углу нажмите &quot;Fire&quot; &gt; &quot;Open File or Project...&quot;</li>
<li>В открывшемся диалоговом окне перейдите в папку &quot;hello-sdl3-c&quot; и выберите файл &quot;CMakeLists.txt&quot;</li>
<li>Проект будет открыт в Qt Creator. Вы может запустить проект на выполнение нажав зелёный треугольник в левом нижнем углу</li>
<li>Поставьте точку остановка, кликнув мышкой слева от номера строки кода и нажмите зелёный треугольник с жуком в левом нижнем углу. Запустится отладка по шагам. Вы можете нажимать кнопки на панели инструментов - например, кнопку для выполнения кода без захода внутрь функции или с заходом внутрь функции</li>
</ul><br />
<h2>Переделываем Си-проект в C++</h2><br />
<br />
<ul><li>Сделайте копию папки &quot;hello-sdl3-c&quot; и переименуйте её в &quot;hello-sdl3-cpp&quot;</li>
<li>В этом новом проекте удалите папку &quot;dist&quot;</li>
<li>Откройте папку &quot;hello-sdl3-cpp&quot; в каком-нибудь редакторе кода, например, в Sublime Text 4, Nodepad++, либо в IDE Qt Creator (&quot;File&quot; &gt; &quot;Open File or Project&quot; -&gt; выберите файл &quot;CMakeLists.txt&quot;)</li>
<li>В редакторе кода или IDE откройте файл &quot;CMakeLists.txt&quot; для редактирования</li>
<li>Измените имя проекта в строке:<br />
<br />
Было:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="439973769"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="439973769" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">project<span class="br0">&#40;</span>hello-sdl3-c<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="155756366"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="155756366" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">project<span class="br0">&#40;</span>hello-sdl3-cpp<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Замените стандарт Си на стандарт C++:<br />
<br />
Было:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="766320723"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="766320723" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="991754380"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="991754380" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Устанавливаем стандарт C++</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_CXX_STANDARD <span class="nu0">20</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_CXX_STANDARD_REQUIRED ON<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Измените расширение файла исходного кода:<br />
<br />
Было:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="372947113"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="372947113" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="750930327"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="750930327" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.cpp
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Переименуйте файл &quot;src/main.c&quot; в &quot;src/main.cpp&quot;<br /></li>
<li>Введите следующие команды в консоли для конфигурирования, сборки и запуска EXE:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="67065571"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="67065571" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">config-exe
build-exe
run-exe</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11722&amp;d=1773142102" rel="Lightbox" id="attachment11722" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11722&amp;thumb=1&amp;d=1773142102" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: a2d347ce-9382-4c0d-a70f-8666085a43be.png
Просмотров: 2144
Размер:	13.1 Кб
ID:	11722" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11726&amp;d=1773143591" rel="Lightbox" id="attachment11726" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11726&amp;thumb=1&amp;d=1773143591" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 4a444142-1d78-44be-8afd-29efeeb6cd07.png
Просмотров: 13282
Размер:	3.7 Кб
ID:	11726" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11731&amp;d=1773222538" rel="Lightbox" id="attachment11731" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11731&amp;thumb=1&amp;d=1773222538" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 6d0de7c9-7ddd-4680-a00b-27392beb656b.png
Просмотров: 1922
Размер:	21.9 Кб
ID:	11731" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11718&amp;d=1773139606">SDL3-devel-3.4.2-mingw.zip</a> (2.65 Мб, 230 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11723&amp;d=1773143126">hello-sdl3-c.zip</a> (3.4 Кб, 293 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11724&amp;d=1773143126">hello-sdl3-cpp.zip</a> (3.4 Кб, 287 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11727&amp;d=1773221305">SDL3-3.4.2-win32-x64.zip</a> (1.10 Мб, 152 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/2953.html</guid>
		</item>
		<item>
			<title>Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE</title>
			<link>https://www.cyberforum.ru/blogs/416874/10793.html</link>
			<pubDate>Tue, 10 Mar 2026 10:07:03 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) | English version: C/C++...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a> | English version: <a rel="nofollow noopener noreferrer" href="https://ivan-enzhaev.github.io/tutorials/tools/mingw/setup-mingw/" target="_blank" title="https://ivan-enzhaev.github.io/tutorials/tools/mingw/setup-mingw/">C/C++ Development Environment Setup (MinGW and CMake)</a><br />
<br />
<b>Видео-версия процесса установки:</b><br />
<br />
<i>В этом видео я показываю базовый процесс подготовки среды: скачивание и распаковка MinGW 13.1, установка CMake и проверка их работы через командную строку. Это визуальное дополнение к первым разделам данного пошагового руководства.</i><br />
<br />
<iframe width="640" height="360" src="https://www.youtube.com/embed/rHXl_gcJ8Zc" frameborder="0" allowfullscreen></iframe><br />
<br />
MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и MinGW. Для набора кода будем использовать: либо легковесный редактор кода Sublime Text 4, либо IDE Qt Creator Community - для отладки кода по шагам, либо можете скачать любой другой редактор кода, например, VSCode. Можете использовать легковесный редактор кода Nodepad++. Qt Creator Community устанавливается отдельно от фреймворка Qt из общедоступного репозитория на GitHub: <a rel="nofollow noopener noreferrer" href="https://github.com/qt-creator/qt-creator" target="_blank" title="https://github.com/qt-creator/qt-creator">https://github.com/qt-creator/qt-creator</a> - установщики разных версий находятся на вкладке Release<br />
<br />
<h2>Установка системы сборки CMake</h2><br />
<br />
<ol style="list-style-type: decimal"><li>Скачайте и установите <a rel="nofollow noopener noreferrer" href="https://github.com/Kitware/CMake/releases" target="_blank" title="https://github.com/Kitware/CMake/releases">CMake</a>. Ищите <code class="inlinecode">cmake-x.x.x-windows-x86_64.msi</code> в списке</li>
<li>Нажимайте кнопки <code class="inlinecode">Next</code> &gt; <code class="inlinecode">Next</code> &gt; <code class="inlinecode">Finish</code></li>
<li>Откройте консоль (CMD) и проверьте запускается ли CMake:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="372452941"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="372452941" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--version</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Если CMake не найден, то добавьте путь к <code class="inlinecode">C:\Program Files\CMake\bin</code> в переменную окружения PATH</li>
</ol><br />
<h2>Установка MinGW 13.1</h2><br />
<br />
<ul><li>Перейдите по ссылке: <a rel="nofollow noopener noreferrer" href="https://winlibs.com/" target="_blank" title="https://winlibs.com/">https://winlibs.com/</a></li>
<li>Прокрутите страницу вниз и найдите пункт &quot;GCC 13.1.0 (with POSIX threads)&quot;</li>
<li>Найдите подпункт &quot;without LLVM/Clang/LLD/LLDB&quot;</li>
<li>Нажмите на ссылку <a rel="nofollow noopener noreferrer" href="https://github.com/brechtsanders/winlibs_mingw/releases/download/13.1.0-16.0.5-11.0.0-ucrt-r5/winlibs-x86_64-posix-seh-gcc-13.1.0-mingw-w64ucrt-11.0.0-r5.zip" target="_blank" title="https://github.com/brechtsanders/winlibs_mingw/releases/download/13.1.0-16.0.5-11.0.0-ucrt-r5/winlibs-x86_64-posix-seh-gcc-13.1.0-mingw-w64ucrt-11.0.0-r5.zip">Zip archive</a>:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11716&amp;a= mp;d=1773133993" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Скаченный архив лучше извлечь в корень диска C, выбрав &quot;Extract Here&quot; (Извлечь сюда), чтобы на диске C была папка &quot;mingw64&quot;</li>
<li>Переименуйте &quot;mingw64&quot; в &quot;mingw64_13.1&quot;</li>
<li>Добавьте путь к папке &quot;C:\mingw64_13.1\bin&quot; в переменную окружения Path</li>
<li>Примечание. Диалоговое окно с Path можно открыть, если нажать Win + R и набрать команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="79026258"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="79026258" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">sysdm.cpl ,<span class="nu0">3</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;,3&quot; означает, что будет открыта третья вкладка в диалоговом окне настроек:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11730&amp;a= mp;d=1773222437" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Проверьте, что MinGW доступен. Для этого откройте новую консоль, чтобы не неё загрузилась актуальная переменная среды Path. Открыть консоль можно через Win + R и ввода команды:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="668920892"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="668920892" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmd</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В открывшемся терминале введите команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="638761671"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="638761671" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw2">gcc</span> <span class="re5">--version</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Будет выведена версия GCC - 13.1.0:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="291115699"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="291115699" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw2">gcc</span> <span class="br0">&#40;</span>MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders<span class="br0">&#41;</span> 13.1.0
Copyright <span class="br0">&#40;</span>C<span class="br0">&#41;</span> <span class="nu0">2023</span> Free Software Foundation, Inc.
This is <span class="kw2">free</span> software; see the <span class="kw3">source</span> <span class="kw1">for</span> copying conditions. &nbsp;There is NO
warranty; not even <span class="kw1">for</span> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Сборка &quot;Hello World!&quot; примера на Си из консоли</h2><br />
<br />
<ul><li>Создайте где-нибудь новую пустую папку под названием &quot;hello-world-c&quot;</li>
<li>Откройте эту папку в текстовом редакторе - например, в Sublime Text 4, Notepad++ или VS Code</li>
<li>Создайте внутри этой папки файл &quot;CMakeLists.txt&quot; и скопируйте в него следующий код:<br />
<br />
CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="731183047"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="731183047" style="height: 270px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>hello-world-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C. Этот код обязательно должен быть до вызова add_executable(app)</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD_REQUIRED ON<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это будет app.exe, а в вебе было бы app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В проекте создайте папку &quot;src&quot;, а в папке &quot;src&quot; файл &quot;main.c&quot; и скопируйте в него код:<br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="920718513"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="920718513" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1"><span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">int</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Hello World!<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте консоль в папке проекта и введите команду конфигурирования проекта:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="409298130"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="409298130" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win -DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div>, где элементы команды означают следующее:<br />
<ul><li>cmake - команда CMake</li>
<li>-G &quot;MinGW Makefiles&quot; - используем MinGW</li>
<li>-S . - указываем, что источник &quot;Source&quot;, то есть файл CMakeLists.txt находится в текущей папке</li>
<li>-B dist/win - указываем куда сохранять конфигурационные файлы и для этого мы указываем, что нужно создать папку &quot;dist/win&quot;</li>
<li>-DCMAKE_BUILD_TYPE=Debug - указываем, что сборка будет отладочная. Она больше чем Release, но Debug собирается быстрее (хотя для Desktop разницы в скорости сборки для маленьких проектов нет, а для WebAssembly разница огромная - пара секунд для Debug и 15 и более секунд на Release)</li>
</ul></li>
<li>Введите команды для сборки приложения в EXE:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="304560854"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="304560854" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> dist\win</pre></td></tr></table></div></td></tr></tbody></table></div><div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="368875022"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="368875022" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--build</span> .</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создан EXE с именем &quot;app.exe&quot;. Для его запуска здесь же в открытой консоли введите команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="267642507"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="267642507" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">app</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В консоль будет выведен текст &quot;Hello World!&quot;</li>
<li>Примечание. Теперь вы можете менять код и сохранять на Ctrl+S, а в консоли достаточно будет нажать кнопку-стрелку вверх, чтобы выбрать команду &quot;cmake --build .&quot; и нажать Enter. Команда конфигурирования выполняется только один раз. Если вы куда-то перенесёте папку &quot;hello-world-c&quot; или переименуете её, то нужно будет удалить папку &quot;dist&quot; и сделать конфигурирование снова той же командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="990852279"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="990852279" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win -DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создайте три батника, чтобы проще было делать конфигурирование, сборку и запуск приложения:<br />
<br />
config-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="996804976"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="996804976" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">-G</span> <span class="st0">&quot;MinGW Makefiles&quot;</span> <span class="re5">-S</span> . <span class="re5">-B</span> dist<span class="sy0">/</span>win -DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div>build-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="516866874"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="516866874" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> dist\win
cmake <span class="re5">--build</span> .
<span class="kw3">cd</span> ..\..</pre></td></tr></table></div></td></tr></tbody></table></div>run-exe.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="145453271"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="145453271" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">dist\win\app</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Теперь можно набирать очень быстро команды:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="59181184"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="59181184" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-exe</pre></td></tr></table></div></td></tr></tbody></table></div><div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="520880405"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="520880405" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-exe</pre></td></tr></table></div></td></tr></tbody></table></div><div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="361924214"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="361924214" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">run-exe</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После первого запуска команд их можно выбирать клавишами-стрелками в CMD. Например, изменили что-то в коде и клавишами-стрелками в CMD выбрали &quot;build-exe&quot;, а после сборки выбрали &quot;run-exe&quot;</li>
</ul><br />
<h2>Сборка &quot;Hello World!&quot; примера в Qt Creator</h2><br />
<br />
Примечание. Пошаговая инструкция для установки Qt Creator: <a href="https://www.cyberforum.ru/blogs/416874/10852.html">Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt</a><br />
<br />
<ul><li>Скачайте и установите Qt Creator версии 18 <a rel="nofollow noopener noreferrer" href="https://github.com/qt-creator/qt-creator/releases/tag/v18.0.2" target="_blank" title="https://github.com/qt-creator/qt-creator/releases/tag/v18.0.2">по ссылке</a>. Установщик вы найдёте в списке &quot;Assets&quot;</li>
<li>Запустите Qt Creator, набрав в поиске программ &quot;Qt Creator&quot;</li>
<li>В левом верхнем углу нажмите &quot;File&quot; &gt; &quot;Open File or Project...&quot;</li>
<li>В открывшемся диалоговом окне перейдите в папку &quot;hello-world-c&quot; и выберите файл &quot;CMakeLists.txt&quot;</li>
<li>Проект будет открыт в Qt Creator. Вы может запустить проект на выполнение нажав зелёный треугольник в левом нижнем углу</li>
<li>Поставьте точку остановка, кликнув мышкой слева от номера строки кода и нажмите зелёный треугольник с жуком в левом нижнем углу. Запустится отладка по шагам. Вы можете нажимать кнопки на панели инструментов - например, кнопку для выполнения кода без захода внутрь функции или с заходом внутрь функции</li>
</ul><br />
<h2>Переделываем Си-проект в C++</h2><br />
<br />
<ul><li>Сделайте копию папки &quot;hello-world-c&quot; и переименуйте её в &quot;hello-world-cpp&quot;</li>
<li>В этом новом проекте удалите папку &quot;dist&quot;</li>
<li>Откройте папку &quot;hello-world-cpp&quot; в каком-нибудь редакторе кода, например, в Sublime Text 4, Nodepad++, либо в IDE Qt Creator (&quot;File&quot; &gt; &quot;Open File or Project&quot; -&gt; выберите файл &quot;CMakeLists.txt&quot;)</li>
<li>В редакторе кода или IDE откройте файл &quot;CMakeLists.txt&quot; для редактирования</li>
<li>Измените имя проекта в строке:<br />
<br />
Было:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="212394640"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="212394640" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">project<span class="br0">&#40;</span>hello-world-c<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="620141263"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="620141263" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">project<span class="br0">&#40;</span>hello-world-cpp<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Замените стандарт Си на стандарт C++:<br />
<br />
Было:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="334092653"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="334092653" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD_REQUIRED ON<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="776853351"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="776853351" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Устанавливаем стандарт C++</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_CXX_STANDARD <span class="nu0">20</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_CXX_STANDARD_REQUIRED ON<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Измените расширение файла исходного кода:<br />
<br />
Было:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="783034848"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="783034848" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="55644844"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="55644844" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.cpp
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Переименуйте файл &quot;src/main.c&quot; в &quot;src/main.cpp&quot;<br /></li>
<li>Введите следующие команды в консоли для конфигурирования, сборки и запуска EXE:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="625093592"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="625093592" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">config-exe
build-exe
run-exe</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11716&amp;d=1773133993" rel="Lightbox" id="attachment11716" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11716&amp;thumb=1&amp;d=1773133993" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 8fae67f8-8b25-4ae3-9046-a15581dcbe56.png
Просмотров: 2079
Размер:	17.7 Кб
ID:	11716" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11730&amp;d=1773222437" rel="Lightbox" id="attachment11730" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11730&amp;thumb=1&amp;d=1773222437" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 6d0de7c9-7ddd-4680-a00b-27392beb656b.png
Просмотров: 1843
Размер:	21.9 Кб
ID:	11730" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11720&amp;d=1773140574">hello-world-c.zip</a> (1.6 Кб, 96 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11721&amp;d=1773140574">hello-world-cpp.zip</a> (1.7 Кб, 99 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10793.html</guid>
		</item>
		<item>
			<title>Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование</title>
			<link>https://www.cyberforum.ru/blogs/416874/7724.html</link>
			<pubDate>Thu, 05 Mar 2026 14:37:28 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Финальная демка в...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
<a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/examples/threejs/orbit-controls-threejs-js/" target="_blank" title="https://8observer8.github.io/examples/threejs/orbit-controls-threejs-js/">Финальная демка в браузере</a> работает на Desktop и мобильных браузерах. Итоговый код: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11711&amp;d=1772738282">orbit-controls-threejs-js.zip</a>. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем, перемещайте камеру двумя пальцами и делайте зум щипком.<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11696&amp;a= mp;d=1772646403" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /> <img src="https://8observer8.github.io/examples/threejs/orbit-controls-threejs-js/qr-code.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
Вращение камеры происходит с помощью зажатой левой кнопки мыши. Панорамирование, то есть перенос камеры - с помощью зажатой правой кнопки мыши. Приближение и отдаление камеры - с помощью вращения или зажатого колёсика мыши.<br />
<br />
<h2>Установка редактора кода и ПО для локального сервера</h2><br />
<br />
<ul><li>Установите какой-нибудь редактор кода, например, в Notepad++ или в Sublime Text 4 (ST4): <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a></li>
<li>Установите Node.js для запуска локального сервера: <a rel="nofollow noopener noreferrer" href="https://nodejs.org/en/download" target="_blank" title="https://nodejs.org/en/download">https://nodejs.org/en/download</a></li>
<li>Примечание. После установки Node.js из консоли будет доступен менеджер пакетов NPM</li>
<li>Откройте терминал (командную строку), например, на Windows 10 можно в поиске программ ввести CMD и выбрать &quot;Run as administrator&quot; - &quot;Запустить от администратора&quot;</li>
<li>В консоле введите команду для установки локального сервера:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="317898663"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="317898663" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i http-server <span class="re5">-g</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Установите js-beautify, чтобы форматировать код из консоли:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="738572895"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="738572895" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i js-beautify <span class="re5">-g</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. О том, как использовать js-beautify можно прочитать здесь: <a href="https://www.cyberforum.ru/blogs/416874/8437.html">Консольные команды для форматирования исходного кода на C, C++, C#, Java, JavaScript, HTML и CSS. Сортировка пакетов на Python</a></li>
</ul><br />
<h2>Пишем код по шагам</h2><br />
<br />
<ul><li>Создайте пустую папку, например, с именем &quot;orbit-controls-threejs-js&quot;</li>
<li>Откройте эту папку в редакторе кода, например, в Sublime Text 4 (ST4). Проще всего добавить ST4 в системную Path на Windows 10. Если не знаете, как добавить путь к EXE программы в Path, то спросите у ИИ, например, у Gemini: &quot;Как добавить путь к Sublime Text 4 в Path&quot;. Тогда можно будет в CMD из созданной папки набрать:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="64123054"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="64123054" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">subl .</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создайте файл index.html и наберите &quot;html&quot; и нажмите Tab и будет сгенерирован код:<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="652130360"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="652130360" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">title</span><span class="sy0">&gt;&lt;/</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">html</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Можете отформатировать код командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="942357628"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="942357628" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">js-beautify <span class="re5">-n</span> <span class="sy0">*</span>.html <span class="re5">-b</span> <span class="st0">&quot;collapse, preserve-inline&quot;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После этой команды код будет отформатирован:<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="259695272"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="259695272" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">title</span><span class="sy0">&gt;&lt;/</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">html</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Найдём ссылки на библиотеку Three.js. Перейдите по ссылке: <a rel="nofollow noopener noreferrer" href="https://cdn.jsdelivr.net" target="_blank" title="https://cdn.jsdelivr.net">https://cdn.jsdelivr.net</a>, прокрутите страницу немного вниз и наберите в поиске: three.js</li>
<li>Перейдите по первой ссылке в поиске:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11697&amp;a= mp;d=1772652515" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Кликните по ссылке &quot;Files&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11698&amp;a= mp;d=1772652625" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Кликните по папке &quot;build&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11699&amp;a= mp;d=1772652828" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Найдите строку с &quot;three.module.min.js&quot; и эту нажмите кнопку для копирования URL:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11700&amp;a= mp;d=1772654173" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Добавьте следующий код с &quot;importmap&quot; в &quot;index.html&quot; и вставьте скопированный URL:<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="206704122"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="206704122" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">title</span><span class="sy0">&gt;&lt;/</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;importmap&quot;</span><span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;imports&quot;</span><span class="sy0">:</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;three&quot;</span><span class="sy0">:</span> <span class="st0">&quot;https://cdn.jsdelivr.net/npm/three@0.183.2/build/three.module.min.js&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">html</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Благодаря &quot;importmap&quot; мы можем в файлах .js импортировать Three.js командой:<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="654749845"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="654749845" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw5">import</span> <span class="sy0">*</span> as THREE from <span class="st0">&quot;three&quot;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В файле &quot;index.html&quot; внутри тега &lt;body&gt; добавьте тег холста с id=&quot;renderCanvas&quot;:<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="887574656"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="887574656" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">canvas</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;renderCanvas&quot;</span><span class="sy0">&gt;&lt;/</span><span class="kw2">canvas</span><span class="sy0">&gt;</span></span>
&nbsp;
&nbsp; &nbsp; <span class="sc-1">&lt;!-- ... --&gt;</span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте подключение файла &quot;./js/index.js&quot;, который мы добавим позже:<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="368928947"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="368928947" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">title</span><span class="sy0">&gt;&lt;/</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">canvas</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;renderCanvas&quot;</span><span class="sy0">&gt;&lt;/</span><span class="kw2">canvas</span><span class="sy0">&gt;</span></span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;importmap&quot;</span><span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;imports&quot;</span><span class="sy0">:</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;three&quot;</span><span class="sy0">:</span> <span class="st0">&quot;https://cdn.jsdelivr.net/npm/three@0.183.2/build/three.module.min.js&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;module&quot;</span> <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./js/index.js&quot;</span><span class="sy0">&gt;</span><span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">html</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создайте в папку &quot;js&quot;, а в папке &quot;js&quot; создайте файл &quot;index.js&quot;</li>
<li>Протестируем запуск приложения. Добавьте в &quot;index.js&quot; строку вывода &quot;Hello World!&quot; в консоль браузера:<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="82320218"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="82320218" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">console.<span class="me1">log</span><span class="br0">&#40;</span><span class="st0">&quot;Hello World!&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В консоле введите команду для запуска локального сервера:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="294652623"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="294652623" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Будет выведен список адресов для браузера, например у меня:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="724915593"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="724915593" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>192.168.1.65:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Если у вас телефон подключён по Wi-Fi, то введите в браузере телефона адрес: 192.168.1.65:8080</li>
<li>Перейдите в Chrome (или Edge) и нажмите &quot;Ctrl+Shift+J&quot; для открытия консоли браузера. Если у вас Firefox, то погуглите, как открыть консоль в Firefox</li>
<li>Введите в адресной строке браузера следующий адрес и после этого нажмите Enter:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="258863651"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="258863651" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В консоли вы увидите &quot;Hello World!&quot;</li>
<li>Примечание. Если вы что-то меняете в проекте и хотите перезапустить приложение в браузере, то обновляйте страницу с очисткой Cache - правой кнопкой по кнопке перезагрузки и выберите: &quot;Empty Cache and Hard Reload&quot;</li>
<li>Откройте файл &quot;index.js&quot; и добавьте следующий код, который импортирует библиотеки Three.js, создаёт три функции: main(), init(), animate(), создаёт рисовальщик (renderer), сцену (scene) и камеру (camera):<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="100748842"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="100748842" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="de1"><pre class="de1"><span class="kw5">import</span> <span class="sy0">*</span> as THREE from <span class="st0">&quot;three&quot;</span><span class="sy0">;</span>
&nbsp;
let renderer<span class="sy0">,</span> scene<span class="sy0">,</span> camera<span class="sy0">;</span>
&nbsp;
<span class="kw1">function</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; animate<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
window.<span class="me1">onload</span> <span class="sy0">=</span> main<span class="sy0">;</span>
&nbsp;
<span class="kw1">function</span> init<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">const</span> canvas <span class="sy0">=</span> document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">&quot;renderCanvas&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; renderer <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">WebGLRenderer</span><span class="br0">&#40;</span><span class="br0">&#123;</span> antialias<span class="sy0">:</span> <span class="kw2">true</span><span class="sy0">,</span> canvas <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">setSize</span><span class="br0">&#40;</span>window.<span class="me1">innerWidth</span><span class="sy0">,</span> window.<span class="me1">innerHeight</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">setPixelRatio</span><span class="br0">&#40;</span>window.<span class="me1">devicePixelRatio</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; scene <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">Scene</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; scene.<span class="me1">background</span> <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">Color</span><span class="br0">&#40;</span>0x222222<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; camera <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">PerspectiveCamera</span><span class="br0">&#40;</span><span class="nu0">45</span><span class="sy0">,</span> window.<span class="me1">innerWidth</span> <span class="sy0">/</span> window.<span class="me1">innerHeight</span><span class="sy0">,</span> <span class="nu0">0.1</span><span class="sy0">,</span> <span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; camera.<span class="me1">position</span>.<span class="kw1">set</span><span class="br0">&#40;</span><span class="nu0">5</span><span class="sy0">,</span> <span class="nu0">5</span><span class="sy0">,</span> <span class="nu0">10</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">function</span> animate<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; requestAnimationFrame<span class="br0">&#40;</span>animate<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">render</span><span class="br0">&#40;</span>scene<span class="sy0">,</span> camera<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Обновите страницу браузера и вы увидите холст тёмно-серого цвета</li>
<li>Уберём полосы прокрутки со страницы и растянем холст. Для этого создайте папку &quot;css&quot; в корне проекта и в папке &quot;css&quot; добавьте файл &quot;style.css&quot;:<br />
<div class="codeblock"><table class="css"><thead><tr><td colspan="2" id="737081128"  class="head">CSS</td></tr></thead><tbody><tr class="li1"><td><div id="737081128" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1">body<span class="sy0">,</span>
html <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">100%</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">100%</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">#renderCanvas</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">100%</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">100%</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте подключение файла &quot;css/style.css&quot; в файле &quot;index.html&quot;. Для этого вы можете внутри тега &lt;head&gt; набрать &quot;link&quot; (без ковычек) и нажать Tab и написать в свойстве href=&quot;&quot; путь к файлу &quot;./css/style.css&quot; следующим образом и добавьте текст &quot;Examples&quot; в тег &lt;title&gt;:<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="630136129"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="630136129" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw0">link</span> <span class="kw3">rel</span><span class="sy0">=</span><span class="st0">&quot;stylesheet&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text/css&quot;</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;./css/style.css&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>Example<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Обновите страницу браузера и теперь вы видите, что холст растянут на всю клиентскую область браузера и полос прокрутки нет. Текущий код:<br />
<br />
index.html<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="5232368"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="5232368" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw0">link</span> <span class="kw3">rel</span><span class="sy0">=</span><span class="st0">&quot;stylesheet&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text/css&quot;</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;./css/style.css&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>Example<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">canvas</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;renderCanvas&quot;</span><span class="sy0">&gt;&lt;/</span><span class="kw2">canvas</span><span class="sy0">&gt;</span></span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;importmap&quot;</span><span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;imports&quot;</span><span class="sy0">:</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;three&quot;</span><span class="sy0">:</span> <span class="st0">&quot;https://cdn.jsdelivr.net/npm/three@0.183.2/build/three.module.min.js&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;module&quot;</span> <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./js/index.js&quot;</span><span class="sy0">&gt;</span><span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">html</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div>js/index.js<br />
<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="513986069"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="513986069" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="de1"><pre class="de1"><span class="kw5">import</span> <span class="sy0">*</span> as THREE from <span class="st0">&quot;three&quot;</span><span class="sy0">;</span>
&nbsp;
let renderer<span class="sy0">,</span> scene<span class="sy0">,</span> camera<span class="sy0">;</span>
&nbsp;
<span class="kw1">function</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; animate<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
window.<span class="me1">onload</span> <span class="sy0">=</span> main<span class="sy0">;</span>
&nbsp;
<span class="kw1">function</span> init<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">const</span> canvas <span class="sy0">=</span> document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">&quot;renderCanvas&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; renderer <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">WebGLRenderer</span><span class="br0">&#40;</span><span class="br0">&#123;</span> antialias<span class="sy0">:</span> <span class="kw2">true</span><span class="sy0">,</span> canvas <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">setSize</span><span class="br0">&#40;</span>window.<span class="me1">innerWidth</span><span class="sy0">,</span> window.<span class="me1">innerHeight</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">setPixelRatio</span><span class="br0">&#40;</span>window.<span class="me1">devicePixelRatio</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; scene <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">Scene</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; scene.<span class="me1">background</span> <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">Color</span><span class="br0">&#40;</span>0x222222<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; camera <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">PerspectiveCamera</span><span class="br0">&#40;</span><span class="nu0">45</span><span class="sy0">,</span> window.<span class="me1">innerWidth</span> <span class="sy0">/</span> window.<span class="me1">innerHeight</span><span class="sy0">,</span> <span class="nu0">0.1</span><span class="sy0">,</span> <span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; camera.<span class="me1">position</span>.<span class="kw1">set</span><span class="br0">&#40;</span><span class="nu0">5</span><span class="sy0">,</span> <span class="nu0">5</span><span class="sy0">,</span> <span class="nu0">10</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">function</span> animate<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; requestAnimationFrame<span class="br0">&#40;</span>animate<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">render</span><span class="br0">&#40;</span>scene<span class="sy0">,</span> camera<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>css/style.css<br />
<br />
<div class="codeblock"><table class="css"><thead><tr><td colspan="2" id="250414974"  class="head">CSS</td></tr></thead><tbody><tr class="li1"><td><div id="250414974" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1">body<span class="sy0">,</span>
html <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">100%</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">100%</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">#renderCanvas</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">100%</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">100%</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Добавляем библиотеку OrbitControls.js и рисование кубика средствами Three.js</h2><br />
<br />
<ul><li>Найдём ссылки на библиотеку OrbitControls.js. Перейдите по ссылке: <a rel="nofollow noopener noreferrer" href="https://cdn.jsdelivr.net" target="_blank" title="https://cdn.jsdelivr.net">https://cdn.jsdelivr.net</a>, прокрутите страницу немного вниз и наберите в поиске: three.js</li>
<li>Перейдите по первой ссылке в поиске:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11697&amp;a= mp;d=1772652515" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Кликните по ссылке &quot;Files&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11698&amp;a= mp;d=1772652625" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Кликните по папке &quot;examples&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11702&amp;a= mp;d=1772717682" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Кликните по папке &quot;jsm&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11703&amp;a= mp;d=1772717704" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Кликните по папке &quot;controls&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11704&amp;a= mp;d=1772717881" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Скопируйте URL, нажав на кнопку:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11705&amp;a= mp;d=1772717980" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Откройте файл &quot;index.html&quot; и вставьте URL, создав новую строку подключения для OrbitControls.js:<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="656840241"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="656840241" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw0">link</span> <span class="kw3">rel</span><span class="sy0">=</span><span class="st0">&quot;stylesheet&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text/css&quot;</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;./css/style.css&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>Example<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">canvas</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;renderCanvas&quot;</span><span class="sy0">&gt;&lt;/</span><span class="kw2">canvas</span><span class="sy0">&gt;</span></span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;importmap&quot;</span><span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;imports&quot;</span><span class="sy0">:</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;three&quot;</span><span class="sy0">:</span> <span class="st0">&quot;https://cdn.jsdelivr.net/npm/three@0.183.2/build/three.module.min.js&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;orbit-controls&quot;</span><span class="sy0">:</span> <span class="st0">&quot;https://cdn.jsdelivr.net/npm/three@0.183.2/examples/jsm/controls/OrbitControls.js&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;module&quot;</span> <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./js/index.js&quot;</span><span class="sy0">&gt;</span><span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">html</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте файл index.js и добавьте импортирование библиотеки OrbitControls.js:<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="215902937"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="215902937" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw5">import</span> <span class="br0">&#123;</span> OrbitControls <span class="br0">&#125;</span> from <span class="st0">&quot;orbit-controls&quot;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте глобальные переменные &quot;controls&quot; и &quot;cube&quot; к уже имеющимся:<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="902343798"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="902343798" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">let renderer<span class="sy0">,</span> scene<span class="sy0">,</span> camera<span class="sy0">,</span> controls<span class="sy0">,</span> cube<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции init() после создания камеры добавьте код создания &quot;controls&quot;, передав в конструктор OrbitControls() ссылку на камеру и ссылку на &lt;canvas&gt;:<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="972989237"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="972989237" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; controls <span class="sy0">=</span> <span class="kw1">new</span> OrbitControls<span class="br0">&#40;</span>camera<span class="sy0">,</span> renderer.<span class="me1">domElement</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; controls.<span class="me1">enableDamping</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span> <span class="co1">// Smooth movement</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Далее добавьте код создания геометрии и материала куба и добавьте куб на сцену командой scene.add(cube):<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="156844692"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="156844692" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw1">const</span> geometry <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">BoxGeometry</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="sy0">,</span> <span class="nu0">2</span><span class="sy0">,</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">const</span> material <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">MeshStandardMaterial</span><span class="br0">&#40;</span><span class="br0">&#123;</span> color<span class="sy0">:</span> 0x00ff88 <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; cube <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">Mesh</span><span class="br0">&#40;</span>geometry<span class="sy0">,</span> material<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; scene.<span class="me1">add</span><span class="br0">&#40;</span>cube<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте на сцену два источника света - направленный свет, как Солнце и окружающий свет:<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="975279222"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="975279222" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw1">const</span> directionalLight <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">DirectionalLight</span><span class="br0">&#40;</span>0xffffff<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; directionalLight.<span class="me1">position</span>.<span class="kw1">set</span><span class="br0">&#40;</span><span class="nu0">5</span><span class="sy0">,</span> <span class="nu0">4</span><span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; scene.<span class="me1">add</span><span class="br0">&#40;</span>directionalLight<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">const</span> ambientLight <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">AmbientLight</span><span class="br0">&#40;</span>0xffffff<span class="sy0">,</span> <span class="nu0">0.4</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; scene.<span class="me1">add</span><span class="br0">&#40;</span>ambientLight<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте команду controls.update() в функцию animate():<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="794300727"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="794300727" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1"><span class="kw1">function</span> animate<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; requestAnimationFrame<span class="br0">&#40;</span>animate<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; controls.<span class="me1">update</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">render</span><span class="br0">&#40;</span>scene<span class="sy0">,</span> camera<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавим функцию onWindowResize(), которая должна вызываться при изменении клиентской области окна браузера, чтобы при изменении соотношения сторон клиентской области окна браузера не деформировались объекты на сцене:<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="782226560"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="782226560" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1"><span class="kw1">function</span> onWindowResize<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; camera.<span class="me1">aspect</span> <span class="sy0">=</span> window.<span class="me1">innerWidth</span> <span class="sy0">/</span> window.<span class="me1">innerHeight</span><span class="sy0">;</span>
&nbsp; &nbsp; camera.<span class="me1">updateProjectionMatrix</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">setSize</span><span class="br0">&#40;</span>window.<span class="me1">innerWidth</span><span class="sy0">,</span> window.<span class="me1">innerHeight</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавим в main() строку настройки &quot;window.onresize = onWindowResize&quot;, чтобы функция onWindowResize() вызывалась при изменении размера клиентской области окна браузера:<br />
<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="681640202"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="681640202" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1"><span class="kw1">function</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; window.<span class="me1">onresize</span> <span class="sy0">=</span> onWindowResize<span class="sy0">;</span>
&nbsp; &nbsp; animate<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Получается следующий код:<br />
<br />
js/index.js<br />
<br />
<div class="codeblock"><table class="javascript"><thead><tr><td colspan="2" id="254996885"  class="head">JavaScript</td></tr></thead><tbody><tr class="li1"><td><div id="254996885" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
</pre></td><td class="de1"><pre class="de1"><span class="kw5">import</span> <span class="sy0">*</span> as THREE from <span class="st0">&quot;three&quot;</span><span class="sy0">;</span>
<span class="kw5">import</span> <span class="br0">&#123;</span> OrbitControls <span class="br0">&#125;</span> from <span class="st0">&quot;orbit-controls&quot;</span><span class="sy0">;</span>
&nbsp;
let renderer<span class="sy0">,</span> scene<span class="sy0">,</span> camera<span class="sy0">,</span> controls<span class="sy0">,</span> cube<span class="sy0">;</span>
&nbsp;
<span class="kw1">function</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; window.<span class="me1">onresize</span> <span class="sy0">=</span> onWindowResize<span class="sy0">;</span>
&nbsp; &nbsp; animate<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
window.<span class="me1">onload</span> <span class="sy0">=</span> main<span class="sy0">;</span>
&nbsp;
<span class="kw1">function</span> init<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">const</span> canvas <span class="sy0">=</span> document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">&quot;renderCanvas&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; renderer <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">WebGLRenderer</span><span class="br0">&#40;</span><span class="br0">&#123;</span> antialias<span class="sy0">:</span> <span class="kw2">true</span><span class="sy0">,</span> canvas <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">setSize</span><span class="br0">&#40;</span>window.<span class="me1">innerWidth</span><span class="sy0">,</span> window.<span class="me1">innerHeight</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">setPixelRatio</span><span class="br0">&#40;</span>window.<span class="me1">devicePixelRatio</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; scene <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">Scene</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; scene.<span class="me1">background</span> <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">Color</span><span class="br0">&#40;</span>0x222222<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; camera <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">PerspectiveCamera</span><span class="br0">&#40;</span><span class="nu0">45</span><span class="sy0">,</span> window.<span class="me1">innerWidth</span> <span class="sy0">/</span> window.<span class="me1">innerHeight</span><span class="sy0">,</span> <span class="nu0">0.1</span><span class="sy0">,</span> <span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; camera.<span class="me1">position</span>.<span class="kw1">set</span><span class="br0">&#40;</span><span class="nu0">5</span><span class="sy0">,</span> <span class="nu0">5</span><span class="sy0">,</span> <span class="nu0">10</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; controls <span class="sy0">=</span> <span class="kw1">new</span> OrbitControls<span class="br0">&#40;</span>camera<span class="sy0">,</span> renderer.<span class="me1">domElement</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; controls.<span class="me1">enableDamping</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span> <span class="co1">// Smooth movement</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">const</span> geometry <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">BoxGeometry</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="sy0">,</span> <span class="nu0">2</span><span class="sy0">,</span> <span class="nu0">2</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">const</span> material <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">MeshStandardMaterial</span><span class="br0">&#40;</span><span class="br0">&#123;</span> color<span class="sy0">:</span> 0x00ff88 <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; cube <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">Mesh</span><span class="br0">&#40;</span>geometry<span class="sy0">,</span> material<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; scene.<span class="me1">add</span><span class="br0">&#40;</span>cube<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">const</span> directionalLight <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">DirectionalLight</span><span class="br0">&#40;</span>0xffffff<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; directionalLight.<span class="me1">position</span>.<span class="kw1">set</span><span class="br0">&#40;</span><span class="nu0">5</span><span class="sy0">,</span> <span class="nu0">4</span><span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; scene.<span class="me1">add</span><span class="br0">&#40;</span>directionalLight<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">const</span> ambientLight <span class="sy0">=</span> <span class="kw1">new</span> THREE.<span class="me1">AmbientLight</span><span class="br0">&#40;</span>0xffffff<span class="sy0">,</span> <span class="nu0">0.4</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; scene.<span class="me1">add</span><span class="br0">&#40;</span>ambientLight<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">function</span> animate<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; requestAnimationFrame<span class="br0">&#40;</span>animate<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; controls.<span class="me1">update</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">render</span><span class="br0">&#40;</span>scene<span class="sy0">,</span> camera<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">function</span> onWindowResize<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; camera.<span class="me1">aspect</span> <span class="sy0">=</span> window.<span class="me1">innerWidth</span> <span class="sy0">/</span> window.<span class="me1">innerHeight</span><span class="sy0">;</span>
&nbsp; &nbsp; camera.<span class="me1">updateProjectionMatrix</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; renderer.<span class="me1">setSize</span><span class="br0">&#40;</span>window.<span class="me1">innerWidth</span><span class="sy0">,</span> window.<span class="me1">innerHeight</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Скопируйте проект на бесплатный хостинг, например, на GitHub Pages и он будет доступен по ссылка, например: <a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/examples/threejs/orbit-controls-threejs-js/" target="_blank" title="https://8observer8.github.io/examples/threejs/orbit-controls-threejs-js/">ссылка</a></li>
<li>Финальный проект: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11711&amp;d=1772738282">orbit-controls-threejs-js.zip</a></li>
</ul><br />
<h2>Подключение библиотек локально</h2><br />
<br />
Вы можете не зависеть от работы сайта <a rel="nofollow noopener noreferrer" href="https://www.jsdelivr.com/" target="_blank" title="https://www.jsdelivr.com/">https://www.jsdelivr.com/</a> в случае, если сайт по каким-то причинам будет недоступен. Вы можете скопировать файлы на свой хостинг, например, на GitHub Pages. Сейчас файл скачивают в кэш браузера по ссылкам:<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="302078016"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="302078016" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;importmap&quot;</span><span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;imports&quot;</span><span class="sy0">:</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;three&quot;</span><span class="sy0">:</span> <span class="st0">&quot;https://cdn.jsdelivr.net/npm/three@0.183.2/build/three.module.min.js&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;orbit-controls&quot;</span><span class="sy0">:</span> <span class="st0">&quot;https://cdn.jsdelivr.net/npm/three@0.183.2/examples/jsm/controls/OrbitControls.js&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Вы можете у себя в корне хостинга создать папку &quot;libs&quot;, а в ней папку &quot;three@0.183.2&quot; и далее уже в этой новой папке &quot;three@0.183.2&quot; создать две папки: &quot;build&quot; и &quot;examples&quot; и т.д. То есть вы создаёте у себя на хостинге папки, где будут храниться два файла: three.module.min.js и OrbitControls.js При этом лучше сохранить туже самую иерархию папок:<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="193926539"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="193926539" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;importmap&quot;</span><span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;imports&quot;</span><span class="sy0">:</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;three&quot;</span><span class="sy0">:</span> <span class="st0">&quot;/libs/three@0.183.2/build/three.module.min.js&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;orbit-controls&quot;</span><span class="sy0">:</span> <span class="st0">&quot;/libs/three@0.183.2/examples/jsm/controls/OrbitControls.js&quot;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div><b>Важно!</b> В папку &quot;build&quot; помимо файла &quot;three.module.min.js&quot; нужно скопировать файл &quot;three.core.min.js&quot;, который можно найти на <a rel="nofollow noopener noreferrer" href="https://www.jsdelivr.com" target="_blank" title="https://www.jsdelivr.com">https://www.jsdelivr.com</a><br />
<br />
У вас проекте будет три файла в папке &quot;libs&quot;. Два файла в папке &quot;build&quot;:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11707&amp;a= mp;d=1772720862" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
И одни файл в папке &quot;controls&quot;:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11708&amp;a= mp;d=1772720965" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
Получился такой проект с включёнными в него библиотеками: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11712&amp;d=1772738282">orbit-controls-threejs-js-plus-libs.zip</a><br />
<br />
Когда вы вводите в консоль команду для запуска локального сервера:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="95244711"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="95244711" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div>, то выводится список адресов для браузера, например у меня:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="366144285"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="366144285" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>192.168.1.65:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div>Если у вас телефон подключён по Wi-Fi, то введите в браузере телефона адрес: 192.168.1.65:8080, чтобы протестировать управление камерой в мобильном браузере. Одним пальцев - вращение камеры. Двумя пальцами - перемещение камеры, и увеличение уменьшение - щипком.<br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11696&amp;d=1772646403" rel="Lightbox" id="attachment11696" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11696&amp;thumb=1&amp;d=1772646403" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: orbit-controls-threejs-js.gif
Просмотров: 11787
Размер:	321.8 Кб
ID:	11696" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11697&amp;d=1772652515" rel="Lightbox" id="attachment11697" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11697&amp;thumb=1&amp;d=1772652515" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 85064bec-84b4-4956-8f8e-c44ff24eb498.png
Просмотров: 1778
Размер:	21.4 Кб
ID:	11697" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11698&amp;d=1772652625" rel="Lightbox" id="attachment11698" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11698&amp;thumb=1&amp;d=1772652625" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 120f0383-433f-49fc-9a50-2766f48536a7.png
Просмотров: 1793
Размер:	9.6 Кб
ID:	11698" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11699&amp;d=1772652828" rel="Lightbox" id="attachment11699" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11699&amp;thumb=1&amp;d=1772652828" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 72489d28-eab6-4793-beb6-392cac13637e.png
Просмотров: 1786
Размер:	14.6 Кб
ID:	11699" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11700&amp;d=1772654173" rel="Lightbox" id="attachment11700" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11700&amp;thumb=1&amp;d=1772654173" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 77864069-5ba6-4111-aeeb-f9e64d42ee54.png
Просмотров: 1777
Размер:	12.2 Кб
ID:	11700" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11702&amp;d=1772717682" rel="Lightbox" id="attachment11702" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11702&amp;thumb=1&amp;d=1772717682" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 3adc9175-c9d3-495f-8aaa-0095b1f8efd0.png
Просмотров: 1791
Размер:	12.5 Кб
ID:	11702" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11703&amp;d=1772717704" rel="Lightbox" id="attachment11703" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11703&amp;thumb=1&amp;d=1772717704" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 82af4fee-34ef-4b94-b717-01e6feb8d932.png
Просмотров: 1783
Размер:	15.6 Кб
ID:	11703" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11704&amp;d=1772717881" rel="Lightbox" id="attachment11704" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11704&amp;thumb=1&amp;d=1772717881" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 8a9b7c42-72c5-4872-864d-255fa571c7bf.png
Просмотров: 1777
Размер:	22.9 Кб
ID:	11704" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11705&amp;d=1772717980" rel="Lightbox" id="attachment11705" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11705&amp;thumb=1&amp;d=1772717980" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: cc585296-8298-4b66-aea1-4c62aa559efe.png
Просмотров: 1763
Размер:	21.6 Кб
ID:	11705" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11707&amp;d=1772720862" rel="Lightbox" id="attachment11707" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11707&amp;thumb=1&amp;d=1772720862" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 01ca7cdb-8fad-4edd-8b8e-d0f6291a1b4d.png
Просмотров: 1762
Размер:	3.2 Кб
ID:	11707" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11708&amp;d=1772720965" rel="Lightbox" id="attachment11708" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11708&amp;thumb=1&amp;d=1772720965" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 3b1431b2-b417-441e-954f-a8a4bbe37c2e.png
Просмотров: 1771
Размер:	3.1 Кб
ID:	11708" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11711&amp;d=1772738282">orbit-controls-threejs-js.zip</a> (2.1 Кб, 274 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11712&amp;d=1772738282">orbit-controls-threejs-js-plus-libs.zip</a> (192.4 Кб, 99 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/7724.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D</title>
			<link>https://www.cyberforum.ru/blogs/416874/10758.html</link>
			<pubDate>Tue, 03 Mar 2026 21:03:02 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Финальная демка в...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
<a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/wasm/finish-sync-physics-sprites-sdl3-c/" target="_blank" title="https://8observer8.github.io/wasm/finish-sync-physics-sprites-sdl3-c/">Финальная демка в браузере</a>. Итоговый код: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11695&amp;d=1772571691">finish-sync-physics-sprites-sdl3-c.zip</a><br />
<br />
На первой гифке отладочные линии отключены, а на второй включены:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11694&amp;d= =1772571466" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /> <img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11693&amp;d= =1772570780" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
Вспомогательные линии нужны только для разработки и отладки, а пользователь не должен их видеть. Пользователь должен видеть спрайты, а линии будут скрыты. Во время отладки будет рисовать линии поверх спрайтов. Спрайты должны рисоваться по тем же координатам и с теми же углами поворота, как и коллайдеры. Box2D имеет специальные функции для считывания координат и углов поворота физических тел, то есть коллайдеров.<br />
<br />
<h2>Подключение библиотек к стартовому примеру</h2><br />
<br />
<ul><li>Скачайте пример: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11683&amp;d=1772488307">start-sync-physics-sprites-sdl3-c.zip</a></li>
<li>Примечание 1. Стартовый пример написан по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10755.html">Подключение Box2D v3, физика и отрисовка коллайдеров</a></li>
<li>Примечание 2. Разница только в одной строке в файле CMakeLists.txt, где вместо SDL 3.4.0 подключается более новая версия SDL 3.4.2:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="961457377"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="961457377" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Так выглядит код стартового примера:<br />
<br />
CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="348825526"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="348825526" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-sync-physics-sprites-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>box2d_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>box2d REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE box2d::box2d SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="471233152"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="471233152" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="co2">#define TIME_STEP (1.0f / 60.0f)</span>
<span class="co2">#define MAX_FRAME_TIME 0.25f</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">float</span> accumulator <span class="sy0">=</span> <span class="nu17">0.0f</span><span class="sy0">;</span>
<span class="kw4">static</span> Uint64 last_ticks <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu17">9.8f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Floor</span>
&nbsp; &nbsp; b2BodyDef floorBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId floorBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon floorShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef floorShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId floorShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Square</span>
&nbsp; &nbsp; b2BodyDef squareBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">201</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">100</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId squareBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon squareShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef squareShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId squareShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- DESKTOP ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">which</span> <span class="sy0">!=</span> SDL_TOUCH_MOUSEID<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>btnName <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">button</span> <span class="sy0">==</span> SDL_BUTTON_LEFT<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="st0">&quot;Левая&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Правая&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s кнопка (Мышь): x=%.0f, y=%.0f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> btnName<span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">x</span><span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- MOBILE / WASM (Touch) ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelX <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelY <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Проверяем количество пальцев на устройстве (touchId берем из события)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> numFingers <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTouchFingers<span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>tfinger.<span class="me1">touchID</span><span class="sy0">,</span> <span class="sy0">&amp;</span>numFingers<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numFingers <span class="sy0">&lt;=</span> <span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Левая кнопка (Тап 1 пальцем): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Правая кнопка (Тап несколькими): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Uint64 current_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> frameTime <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>current_ticks <span class="sy0">-</span> last_ticks<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">1000.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> current_ticks<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>frameTime <span class="sy0">&gt;</span> MAX_FRAME_TIME<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frameTime <span class="sy0">=</span> MAX_FRAME_TIME<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; accumulator <span class="sy0">+=</span> frameTime<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>src/debug-drawer.h<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="395190632"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="395190632" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
</pre></td><td class="de1"><pre class="de1"><span class="co2">#ifndef DEBUG_DRAWER_H</span>
<span class="co2">#define DEBUG_DRAWER_H</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
&nbsp;
<span class="kw2">extern</span> SDL_Renderer <span class="sy0">*</span>renderer<span class="sy0">;</span>
<span class="kw2">extern</span> <span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format<span class="sy0">;</span>
<span class="kw2">extern</span> <span class="kw4">float</span> ppm<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">void</span> drawSolidPolygon<span class="br0">&#40;</span>b2Transform transform<span class="sy0">,</span>
&nbsp; &nbsp; <span class="kw4">const</span> b2Vec2 <span class="sy0">*</span>vertices<span class="sy0">,</span> <span class="kw4">int</span> vertexCount<span class="sy0">,</span>
&nbsp; &nbsp; <span class="kw4">float</span> radius<span class="sy0">,</span> b2HexColor color<span class="sy0">,</span> <span class="kw4">void</span> <span class="sy0">*</span>context<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>radius<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>context<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Extract RGB</span>
&nbsp; &nbsp; Uint8 r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetRGB<span class="br0">&#40;</span>color<span class="sy0">,</span> format<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>r<span class="sy0">,</span> <span class="sy0">&amp;</span>g<span class="sy0">,</span> <span class="sy0">&amp;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Draw a collider rectangle with lines</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> vertexCount<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> next_index <span class="sy0">=</span> <span class="br0">&#40;</span>i <span class="sy0">+</span> <span class="nu0">1</span> <span class="sy0">==</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="nu0">0</span> <span class="sy0">:</span> i <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p0 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>next_index<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x0 <span class="sy0">=</span> p0.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y0 <span class="sy0">=</span> p0.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x1 <span class="sy0">=</span> p1.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y1 <span class="sy0">=</span> p1.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> x0<span class="sy0">,</span> y0<span class="sy0">,</span> x1<span class="sy0">,</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Tip: Draw orientation line ---</span>
&nbsp; &nbsp; <span class="co1">// Compute polygon center</span>
&nbsp; &nbsp; <span class="kw4">float</span> cx <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> cy <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> vertexCount<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; cx <span class="sy0">+=</span> p.<span class="me1">x</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; cy <span class="sy0">+=</span> p.<span class="me1">y</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; cx <span class="sy0">=</span> <span class="br0">&#40;</span>cx <span class="sy0">/</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; cy <span class="sy0">=</span> <span class="br0">&#40;</span>cy <span class="sy0">/</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Midpoint of second edge (vertex[1] → vertex[2])</span>
&nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 p2 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> mx <span class="sy0">=</span> <span class="br0">&#40;</span>p1.<span class="me1">x</span> <span class="sy0">+</span> p2.<span class="me1">x</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu17">0.5f</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> my <span class="sy0">=</span> <span class="br0">&#40;</span>p1.<span class="me1">y</span> <span class="sy0">+</span> p2.<span class="me1">y</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu17">0.5f</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw center → edge midpoint line (acts like &quot;direction tip&quot;)</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> cx<span class="sy0">,</span> cy<span class="sy0">,</span> mx<span class="sy0">,</span> my<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">void</span> drawSolidCircle<span class="br0">&#40;</span>b2Transform transform<span class="sy0">,</span> <span class="kw4">float</span> radius<span class="sy0">,</span>
&nbsp; &nbsp; b2HexColor color<span class="sy0">,</span> <span class="kw4">void</span> <span class="sy0">*</span>context<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>radius<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>context<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> angle <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">int</span> numberOfSegments <span class="sy0">=</span> <span class="nu0">20</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> angleStep <span class="sy0">=</span> <span class="nu0">360</span>.<span class="me1">f</span> <span class="sy0">/</span> numberOfSegments<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Extract RGB</span>
&nbsp; &nbsp; Uint8 r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetRGB<span class="br0">&#40;</span>color<span class="sy0">,</span> format<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>r<span class="sy0">,</span> <span class="sy0">&amp;</span>g<span class="sy0">,</span> <span class="sy0">&amp;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Draw a collider rectangle with lines</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">cos</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">sin</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 p0 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> x<span class="sy0">,</span> y <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> x0 <span class="sy0">=</span> p0.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y0 <span class="sy0">=</span> p0.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; angle <span class="sy0">+=</span> angleStep<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> numberOfSegments<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">cos</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">sin</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> x<span class="sy0">,</span> y <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x1 <span class="sy0">=</span> p1.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y1 <span class="sy0">=</span> p1.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> x0<span class="sy0">,</span> y0<span class="sy0">,</span> x1<span class="sy0">,</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; x0 <span class="sy0">=</span> x1<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; y0 <span class="sy0">=</span> y1<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; angle <span class="sy0">+=</span> angleStep<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>angle <span class="sy0">&gt;=</span> <span class="nu0">360</span>.<span class="me1">f</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; angle <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Tip: Draw orientation line ---</span>
&nbsp; &nbsp; <span class="co1">// Circle center</span>
&nbsp; &nbsp; b2Vec2 c <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> cx <span class="sy0">=</span> c.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> cy <span class="sy0">=</span> c.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Direction = transform applied to (radius, 0)</span>
&nbsp; &nbsp; b2Vec2 orient <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> radius<span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> ox <span class="sy0">=</span> orient.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> oy <span class="sy0">=</span> orient.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw center → orientation marker</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> cx<span class="sy0">,</span> cy<span class="sy0">,</span> ox<span class="sy0">,</span> oy<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co2">#endif // DEBUG_DRAWER_H</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Результатом стартового примеря являеются: падающие круговой и квадратный коллайдер и статическая платформа:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11684&amp;d=1772489367" border="0" alt="Название: finish-box2d-v3-wasm-sdl3-c.gif
Просмотров: 1504

Размер: 387.2 Кб" style="margin: 5px" /></li>
<li>Запустим стартовый пример, а для этого скачаем и подключим библиотеки SDL3 и Box2D</li>
<li>Откройте папку со стартовым примером в какой-нибудь редакторе кода, например, в Notepad++ или в Sublime Text 4 (ST4): <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a></li>
<li>Скачайте библиотеку SDL3 для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11685&amp;d=1772489611">SDL3-devel-3.4.2-wasm.zip</a></li>
<li>Скачайте библиотеку Box2D v3 для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11686&amp;d=1772489617">box2d-3.1.1-wasm.zip</a></li>
<li>Извлеките содержимое архив выше в какую-нибудь новую общую папку, например, с именем &quot;libs&quot; на какой-нибудь диск, например, на C:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11687&amp;d=1772489973" border="0" alt="Название: f7ed3a1f-0d5e-4e03-9aaa-ee8163534e78.png
Просмотров: 1511

Размер: 4.1 Кб" style="margin: 5px" /></li>
<li>Откройте папку &quot;SDL3-devel-3.4.2-wasm&quot;, перейдите в &quot;lib/cmake/SDL3&quot; и скопируйте абсолютный путь:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11688&amp;a= mp;d=1772490011" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br /></li>
<li>В файле CMakeLists.txt стартового примера замените в переменной SDL3_DIR путь на свой, который скопировали выше:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="760717219"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="760717219" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку &quot;box2d-3.1.1-wasm&quot;, перейдите в &quot;lib/cmake/box2d&quot; и скопируйте абсолютный путь:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11689&amp;a= mp;d=1772490050" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br /></li>
<li>Замените в переменной box2d_DIR путь на свой, если необходимо:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="530396017"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="530396017" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>По следующей инструкции проведём тестовую сборку, чтобы убедиться, что библиотеки подключены и пример работает</li>
</ul><br />
<h2>Тестовая сборка и тестовый запуск стартового примера в браузере на локальном хостинге</h2><br />
<br />
<ul><li>Откройте консоль (CMD) в корне стартового примера. Для этого можете просто в адресной строке папки (там где путь) написать &quot;cmd&quot; (без кавычек) и нажать Enter</li>
<li>В CMD введите команду для конфигурирования:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="581923432"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="581923432" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;config-web&quot; - это имя bash-файла (батника), который находится в корне папки стартового примера</li>
<li>В CMD введите команду сборки проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="843243255"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="843243255" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Собранные файлы (app.js и app.wasm) будут скопированы в папку &quot;public/js&quot; (папка &quot;public&quot; лежит в корне проекта)</li>
<li>В корне проекта запустите локальный сервер командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="885599199"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="885599199" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Будут выведены адреса:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="436849694"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="436849694" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>192.168.1.65:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 2. Адрес 192.168.1.65:8080 можно использовать для запуска приложения на мобильном устройстве, если у вас есть Wi-Fi - просто вводите этот адрес в браузере мобильного устройства и приложение запустится. Если интересен запуск на мобильном устройстве, то пройдите пошаговую инструкцию: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a></li>
<li>Откройте новую вкладку в браузере. Если у вас Chrome или Edge, то нажмите Ctrl+Shift+J, чтобы открыть консоль браузера для контроля вывода информации. Если у вас FireFox, то нажмите Ctrl+Shift+K</li>
<li>Перейдите по адресу:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="803817901"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="803817901" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Обновлять страницу после повторной сборки проекта лучше с очисткой кэша браузера. Для этого (обязательно с открытой консолью браузера) в браузере Chrome нужно найти в левом верхнем углу браузера кнопку обновления страницы (круговая стрелка), нажать по ней правой кнопкой мыши и выбрать &quot;Empty Cache and Hard Reload&quot;</li>
<li>Мы убедились, что тестовый пример запускается нормально. Если вы что-то меняете в коде (в файлах main.c или CMakeLists.txt), то достаточно ввести команду для сборки build-web (в CMD нажать стрелку-вверх и Enter) и обновить вкладку в браузере. Удобнее всего, чтобы локальный хостинг был запущен в одном окне CMD, а сборку делать в другом окне CMD</li>
</ul><br />
<h2>Загружаем спрайты в наше приложение</h2><br />
<br />
На сайте Kenney (<a rel="nofollow noopener noreferrer" href="https://kenney.nl" target="_blank" title="https://kenney.nl">https://kenney.nl</a>) большое количество бесплатных паков с изображениями для игр.<br />
<br />
<ul><li>Скачайте следующий пак под названием Physics со спрайтами и тайлами на сайте Kenney: <a rel="nofollow noopener noreferrer" href="https://kenney.nl/assets/physics-assets" target="_blank" title="https://kenney.nl/assets/physics-assets">https://kenney.nl/assets/physics-assets</a></li>
<li>Примечание. На случай, если ссылка выше не открывается, то я прикрепил пак Kenney архивом: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11690&amp;d=1772532028">kenney_physics-assets.zip</a> (2.46 MB)</li>
<li>В корне стартового примера создайте папку &quot;assets&quot;, а в ней папку &quot;sprites&quot;</li>
<li>Скопируйте в папку &quot;assets/sprites&quot; следующие файлы спрайтов:<ul><li>kenney_physics-assets/PNG/Aliens/alienGreen_square.png</li>
<li>kenney_physics-assets/PNG/Aliens/alienYellow_round.png</li>
<li>kenney_physics-assets/PNG/Other/grass.png</li>
</ul><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11692&amp;a= mp;d=1772538028" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Откройте файл CMakeLists.txt в редакторе кода и скопируйте в него (в конец файла) код для встраивания всех трёх файлов изображений в файл &quot;app.wasm&quot;:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="549139728"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="549139728" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Встраиваем изображения в файл app.wasm</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>EMSCRIPTEN<span class="br0">&#41;</span>
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span><span class="st0">&quot;app&quot;</span> PRIVATE <span class="st0">&quot;SHELL:--embed-file <span class="es1">\&quot;</span><span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/sprites/alienGreen_square.png@/assets/sprites/alienGreen_square.png<span class="es1">\&quot;</span>&quot;</span><span class="br0">&#41;</span> 
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET <span class="st0">&quot;app&quot;</span> APPEND PROPERTY LINK_DEPENDS <span class="st0">&quot;<span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/sprites/alienGreen_square.png&quot;</span><span class="br0">&#41;</span>
&nbsp;
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span><span class="st0">&quot;app&quot;</span> PRIVATE <span class="st0">&quot;SHELL:--embed-file <span class="es1">\&quot;</span><span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/sprites/alienYellow_round.png@/assets/sprites/alienYellow_round.png<span class="es1">\&quot;</span>&quot;</span><span class="br0">&#41;</span> 
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET <span class="st0">&quot;app&quot;</span> APPEND PROPERTY LINK_DEPENDS <span class="st0">&quot;<span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/sprites/alienYellow_round.png&quot;</span><span class="br0">&#41;</span>
&nbsp;
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span><span class="st0">&quot;app&quot;</span> PRIVATE <span class="st0">&quot;SHELL:--embed-file <span class="es1">\&quot;</span><span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/sprites/grass.png@/assets/sprites/grass.png<span class="es1">\&quot;</span>&quot;</span><span class="br0">&#41;</span> 
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET <span class="st0">&quot;app&quot;</span> APPEND PROPERTY LINK_DEPENDS <span class="st0">&quot;<span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/sprites/grass.png&quot;</span><span class="br0">&#41;</span>
endif<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Файлы изображений добавлены в проект. Таким же образом вы можете добавлять и другие файлы: звуковые файлы, файлы шрифтов, XML/JSON-файлы и т.д.</li>
<li>Откройте файл src/main.c в редакторе кода</li>
<li>Добавьте три глобальные переменные для хранения текстур:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="554332867"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="554332867" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>alien_green_square_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>alien_yellow_round_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>grass_texture <span class="sy0">=</span> NULL<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Сразу же, чтобы не забыть освободить ресурсы, перейдём в конец файла &quot;main.c&quot; и добавим код удаления текстур перед завершением программы, в функцию SDL_AppQuit():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="898193646"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="898193646" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>alien_green_square_texture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>alien_green_square_texture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; alien_green_square_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>alien_yellow_round_texture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>alien_yellow_round_texture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; alien_yellow_round_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>grass_texture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>grass_texture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; grass_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Перед функцией инициализации SDL_AppInit() добавьте функцию загрузки текстуры:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="319914863"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="319914863" style="height: 222px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="de1"><pre class="de1">SDL_Texture<span class="sy0">*</span> LoadTexture<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*</span> path<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_Surface<span class="sy0">*</span> surface <span class="sy0">=</span> SDL_LoadPNG<span class="br0">&#40;</span>path<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>surface<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Load failed (%s): %s&quot;</span><span class="sy0">,</span> path<span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_Texture<span class="sy0">*</span> texture <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> texture<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте следующий год загрузки файлов-текстур в теле функции инициализации, то есть в теле функции SDL_AppInit() после функции SDL_SetRenderVSync():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="488911143"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="488911143" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; alien_green_square_texture <span class="sy0">=</span> LoadTexture<span class="br0">&#40;</span><span class="st0">&quot;./assets/sprites/alienGreen_square.png&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; alien_yellow_round_texture <span class="sy0">=</span> LoadTexture<span class="br0">&#40;</span><span class="st0">&quot;./assets/sprites/alienYellow_round.png&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; grass_texture <span class="sy0">=</span> LoadTexture<span class="br0">&#40;</span><span class="st0">&quot;./assets/sprites/grass.png&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppIterate() добавьте код вывода изображения для тестового запуска после функции SDL_RenderClear(), до перед функций b2World_Draw(), чтобы в будущем отладочные линии коллайдеров рисовались поверх текстуры:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="112540944"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="112540944" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// ..</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_FRect srcRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">70</span><span class="sy0">,</span> <span class="nu0">70</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_FRect destRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">150</span><span class="sy0">,</span> <span class="nu0">250</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> alien_green_square_texture<span class="sy0">,</span> <span class="sy0">&amp;</span>srcRect<span class="sy0">,</span> <span class="sy0">&amp;</span>destRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Сделайте сборку проекта командой &quot;build-web&quot; и обновите страницу браузера</li>
<li>Мы видим, что изображение выводится, а отладочные линии коллайдеров выводятся поверх изображения:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11691&amp;d=1772537671" border="0" alt="Название: 023c18f4-590d-4bbe-842c-8ff0995c2d70.png
Просмотров: 1489

Размер: 4.4 Кб" style="margin: 5px" /></li>
</ul><br />
<h2>Синхронизация спрайтов SDL3 и тел Box2D</h2><br />
<br />
Нам нужно выводить спрайты с теми же координатами и углами повотора, что и тела (коллайдеры). У Box2D есть специальные функции для того, чтобы считать координаты тела (коллайдера): b2Body_GetTransform() и угла: b2Rot_GetAngle(). Найдите эти функции через поиск в правом верхнем углу в официальной документации: <a rel="nofollow noopener noreferrer" href="https://box2d.org/documentation/" target="_blank" title="https://box2d.org/documentation/">https://box2d.org/documentation/</a>, чтобы привыкать работать с документаций.<br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Вот что по этому поводу написал Gemini</div>
				   <div class="spoiler-body">
					   <br />
Для того чтобы спрайт «приклеился» к физическому телу, нам нужно в каждом кадре спрашивать у Box2D: «Где сейчас находится тело и под каким углом оно повернуто?».<br />
<br />
Вот пошаговый план, как это внедрить в ваш код.<br />
<ol style="list-style-type: decimal"><li><b>Как получить данные из Box2D</b>. В Box2D версии 3.0 (которую вы используете) позиция и поворот извлекаются через функцию b2Body_GetTransform.<ul><li><b>Позиция:</b> Извлекается в метрах, поэтому умножаем на ppm.</li>
<li><b>Угол:</b> Извлекается в радианах. Для SDL_RenderTextureRotated нам нужно перевести их в градусы.</li>
</ul></li>
<li><b>Изменения в коде</b>. Чтобы не загромождать SDL_AppIterate, лучше всего создать вспомогательную функцию для отрисовки. Добавьте эту функцию перед SDL_AppIterate:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="308684574"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="308684574" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> RenderBody<span class="br0">&#40;</span>b2BodyId bodyId<span class="sy0">,</span> SDL_Texture<span class="sy0">*</span> texture<span class="sy0">,</span> <span class="kw4">float</span> width<span class="sy0">,</span> <span class="kw4">float</span> height<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// 1. Получаем трансформацию тела из Box2D</span>
&nbsp; &nbsp; b2Transform transform <span class="sy0">=</span> b2Body_GetTransform<span class="br0">&#40;</span>bodyId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 pos <span class="sy0">=</span> transform.<span class="me1">p</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> angleRadians <span class="sy0">=</span> b2Rot_GetAngle<span class="br0">&#40;</span>transform.<span class="me1">q</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; 
&nbsp; &nbsp; <span class="co1">// 2. Конвертируем метры в пиксели и радианы в градусы</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerX <span class="sy0">=</span> pos.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerY <span class="sy0">=</span> pos.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> angleDegrees <span class="sy0">=</span> angleRadians <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">180.0f</span> <span class="sy0">/</span> SDL_PI_F<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 3. Определяем прямоугольник отрисовки</span>
&nbsp; &nbsp; <span class="co1">// SDL рисует от верхнего левого угла, поэтому смещаем координаты на половину размера</span>
&nbsp; &nbsp; SDL_FRect destRect <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerX <span class="sy0">-</span> <span class="br0">&#40;</span>width <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerY <span class="sy0">-</span> <span class="br0">&#40;</span>height <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; width<span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; height
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 4. Отрисовка с учетом поворота</span>
&nbsp; &nbsp; <span class="co1">// NULL в качестве центра означает вращение вокруг центра destRect</span>
&nbsp; &nbsp; SDL_RenderTextureRotated<span class="br0">&#40;</span>renderer<span class="sy0">,</span> texture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>destRect<span class="sy0">,</span> <span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>angleDegrees<span class="sy0">,</span> NULL<span class="sy0">,</span> SDL_FLIP_NONE<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li><b>Обновляем переменные</b>. Чтобы функция RenderBody могла дотянуться до ID тел, сделайте их статическими (перенесите из SDL_AppInit в начало файла к остальным static переменным):<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="62001022"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="62001022" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> b2BodyId floorBodyId<span class="sy0">;</span>
<span class="kw4">static</span> b2BodyId squareBodyId<span class="sy0">;</span>
<span class="kw4">static</span> b2BodyId circleBodyId<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li><b>Обновляем цикл отрисовки</b>. Теперь в SDL_AppIterate замените ваш тестовый блок отрисовки на вызов новой функции:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="42969409"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="42969409" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// ... (код обновления физики остается прежним) ...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Очистка экрана</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Рисуем спрайты поверх физических тел</span>
&nbsp; &nbsp; <span class="co1">// Размеры берем те же, что задавали при создании коллайдеров (умноженные на 2, т.к. b2MakeBox берет полуобхват)</span>
&nbsp; &nbsp; RenderBody<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> grass_texture<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">20</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; RenderBody<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> alien_green_square_texture<span class="sy0">,</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; RenderBody<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> alien_yellow_round_texture<span class="sy0">,</span> <span class="nu0">40</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">40</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// диаметр = радиус 20 * 2</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Если нужно видеть линии коллайдеров для проверки - оставляем:</span>
&nbsp; &nbsp; <span class="co1">// b2World_Draw(worldId, &amp;debugDrawer);</span>
&nbsp;
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ol><br />
<b>Почему это работает:</b><br />
<ul><li><b>Центрирование:</b> Box2D считает позицию тела по его центру масс. SDL по умолчанию рисует от угла. Мы вычитаем width / 2, чтобы &quot;центр&quot; картинки совпал с &quot;центром&quot; физического объекта.</li>
<li><b>Синхронизация:</b> Поскольку RenderBody вызывается сразу после b2World_Step, визуальная картинка никогда не будет отставать от физики.</li>
<li><b>Вращение:</b> SDL_RenderTextureRotated — это мощная функция SDL3, которая берет на себя всю математику поворота текстуры на GPU.</li>
</ul><br />

				   </div>
			   </div><br />
<ul><li>Используем код Gemini выше. Добавьте функцию RenderBody() перед SDL_AppIterate():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="996445466"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="996445466" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> RenderBody<span class="br0">&#40;</span>b2BodyId bodyId<span class="sy0">,</span> SDL_Texture <span class="sy0">*</span>texture<span class="sy0">,</span> <span class="kw4">float</span> width<span class="sy0">,</span> <span class="kw4">float</span> height<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// 1. Получаем трансформацию тела из Box2D</span>
&nbsp; &nbsp; b2Transform transform <span class="sy0">=</span> b2Body_GetTransform<span class="br0">&#40;</span>bodyId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 pos <span class="sy0">=</span> transform.<span class="me1">p</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> angleRadians <span class="sy0">=</span> b2Rot_GetAngle<span class="br0">&#40;</span>transform.<span class="me1">q</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 2. Конвертируем метры в пиксели и радианы в градусы</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerX <span class="sy0">=</span> pos.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerY <span class="sy0">=</span> pos.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> angleDegrees <span class="sy0">=</span> angleRadians <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">180.0f</span> <span class="sy0">/</span> SDL_PI_F<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 3. Определяем прямоугольник отрисовки</span>
&nbsp; &nbsp; <span class="co1">// SDL рисует от верхнего левого угла, поэтому смещаем координаты на половину размера</span>
&nbsp; &nbsp; SDL_FRect destRect <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerX <span class="sy0">-</span> <span class="br0">&#40;</span>width <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerY <span class="sy0">-</span> <span class="br0">&#40;</span>height <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; width<span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; height
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 4. Отрисовка с учетом поворота</span>
&nbsp; &nbsp; <span class="co1">// NULL в качестве центра означает вращение вокруг центра destRect</span>
&nbsp; &nbsp; SDL_RenderTextureRotated<span class="br0">&#40;</span>renderer<span class="sy0">,</span> texture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>destRect<span class="sy0">,</span> <span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>angleDegrees<span class="sy0">,</span> NULL<span class="sy0">,</span> SDL_FLIP_NONE<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Идентификаторы тел делаем глобальными:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="343727066"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="343727066" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> b2BodyId floorBodyId<span class="sy0">;</span>
<span class="kw4">static</span> b2BodyId squareBodyId<span class="sy0">;</span>
<span class="kw4">static</span> b2BodyId circleBodyId<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Не забудьте удалить b2BodyId перед floorBodyId, squareBodyId и circleBodyId в функции SDL_AppInit()</li>
<li>Добавьте код рисования пола плиткой перед SDL_AppIterate():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="253631636"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="253631636" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> RenderFloorTiled<span class="br0">&#40;</span>b2BodyId bodyId<span class="sy0">,</span> SDL_Texture <span class="sy0">*</span>texture<span class="sy0">,</span> <span class="kw4">float</span> floorWidth<span class="sy0">,</span> <span class="kw4">float</span> floorHeight<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// 1. Получаем позицию из Box2D (в метрах)</span>
&nbsp; &nbsp; b2Vec2 pos <span class="sy0">=</span> b2Body_GetPosition<span class="br0">&#40;</span>bodyId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 2. Переводим координаты центра из метров в пиксели</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerX <span class="sy0">=</span> pos.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerY <span class="sy0">=</span> pos.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 3. Целевой прямоугольник для отрисовки всего пола</span>
&nbsp; &nbsp; SDL_FRect dstRect <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerX <span class="sy0">-</span> <span class="br0">&#40;</span>floorWidth <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerY <span class="sy0">-</span> <span class="br0">&#40;</span>floorHeight <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; floorWidth<span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; floorHeight
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 4. Вызываем исправленную функцию с 5 аргументами (добавлен 1.0f как масштаб)</span>
&nbsp; &nbsp; <span class="co1">// Параметры: renderer, texture, src_rect (NULL = вся текстура), scale, dst_rect</span>
&nbsp; &nbsp; SDL_RenderTextureTiled<span class="br0">&#40;</span>renderer<span class="sy0">,</span> texture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="nu17">1.0f</span><span class="sy0">,</span> <span class="sy0">&amp;</span>dstRect<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppIterate() измените и добавьте код таким образом:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="15358329"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="15358329" style="height: 286px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_FRect srcRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">70</span><span class="sy0">,</span> <span class="nu0">70</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_FRect destRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">150</span><span class="sy0">,</span> <span class="nu0">250</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Рисуем ПОЛ плиткой (Tiled)</span>
&nbsp; &nbsp; RenderFloorTiled<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> grass_texture<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">20</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Рисуем спрайты поверх физических тел</span>
&nbsp; &nbsp; <span class="co1">// Размеры берем те же, что задавали при создании коллайдеров (умноженные на 2, т.к. b2MakeBox берет полуобхват)</span>
&nbsp; &nbsp; RenderBody<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> alien_green_square_texture<span class="sy0">,</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; RenderBody<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> alien_yellow_round_texture<span class="sy0">,</span> <span class="nu0">40</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">40</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// диаметр = радиус 20 * 2</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Читайте комментарии в коде</li>
<li>Текущий код в src/main.c:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="481934489"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="481934489" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="co2">#define TIME_STEP (1.0f / 60.0f)</span>
<span class="co2">#define MAX_FRAME_TIME 0.25f</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>alien_green_square_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>alien_yellow_round_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>grass_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">float</span> accumulator <span class="sy0">=</span> <span class="nu17">0.0f</span><span class="sy0">;</span>
<span class="kw4">static</span> Uint64 last_ticks <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> b2BodyId floorBodyId<span class="sy0">;</span>
<span class="kw4">static</span> b2BodyId squareBodyId<span class="sy0">;</span>
<span class="kw4">static</span> b2BodyId circleBodyId<span class="sy0">;</span>
&nbsp;
SDL_Texture <span class="sy0">*</span>LoadTexture<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>path<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_LoadPNG<span class="br0">&#40;</span>path<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>surface<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Load failed (%s): %s&quot;</span><span class="sy0">,</span> path<span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_Texture <span class="sy0">*</span>texture <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> texture<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; alien_green_square_texture <span class="sy0">=</span> LoadTexture<span class="br0">&#40;</span><span class="st0">&quot;./assets/sprites/alienGreen_square.png&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; alien_yellow_round_texture <span class="sy0">=</span> LoadTexture<span class="br0">&#40;</span><span class="st0">&quot;./assets/sprites/alienYellow_round.png&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; grass_texture <span class="sy0">=</span> LoadTexture<span class="br0">&#40;</span><span class="st0">&quot;./assets/sprites/grass.png&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu17">9.8f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Floor</span>
&nbsp; &nbsp; b2BodyDef floorBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Половина ширины 150, половина высоты 10. Итого весь бокс 300x20 пикселей.</span>
&nbsp; &nbsp; b2Polygon floorShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef floorShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId floorShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Square</span>
&nbsp; &nbsp; b2BodyDef squareBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">201</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">100</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon squareShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef squareShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId squareShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- DESKTOP ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">which</span> <span class="sy0">!=</span> SDL_TOUCH_MOUSEID<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>btnName <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">button</span> <span class="sy0">==</span> SDL_BUTTON_LEFT<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="st0">&quot;Левая&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Правая&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s кнопка (Мышь): x=%.0f, y=%.0f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> btnName<span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">x</span><span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- MOBILE / WASM (Touch) ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelX <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelY <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Проверяем количество пальцев на устройстве (touchId берем из события)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> numFingers <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTouchFingers<span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>tfinger.<span class="me1">touchID</span><span class="sy0">,</span> <span class="sy0">&amp;</span>numFingers<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numFingers <span class="sy0">&lt;=</span> <span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Левая кнопка (Тап 1 пальцем): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Правая кнопка (Тап несколькими): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> RenderBody<span class="br0">&#40;</span>b2BodyId bodyId<span class="sy0">,</span> SDL_Texture <span class="sy0">*</span>texture<span class="sy0">,</span> <span class="kw4">float</span> width<span class="sy0">,</span> <span class="kw4">float</span> height<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// 1. Получаем трансформацию тела из Box2D</span>
&nbsp; &nbsp; b2Transform transform <span class="sy0">=</span> b2Body_GetTransform<span class="br0">&#40;</span>bodyId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 pos <span class="sy0">=</span> transform.<span class="me1">p</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> angleRadians <span class="sy0">=</span> b2Rot_GetAngle<span class="br0">&#40;</span>transform.<span class="me1">q</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 2. Конвертируем метры в пиксели и радианы в градусы</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerX <span class="sy0">=</span> pos.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerY <span class="sy0">=</span> pos.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> angleDegrees <span class="sy0">=</span> angleRadians <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">180.0f</span> <span class="sy0">/</span> SDL_PI_F<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 3. Определяем прямоугольник отрисовки</span>
&nbsp; &nbsp; <span class="co1">// SDL рисует от верхнего левого угла, поэтому смещаем координаты на половину размера</span>
&nbsp; &nbsp; SDL_FRect destRect <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerX <span class="sy0">-</span> <span class="br0">&#40;</span>width <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerY <span class="sy0">-</span> <span class="br0">&#40;</span>height <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; width<span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; height
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 4. Отрисовка с учетом поворота</span>
&nbsp; &nbsp; <span class="co1">// NULL в качестве центра означает вращение вокруг центра destRect</span>
&nbsp; &nbsp; SDL_RenderTextureRotated<span class="br0">&#40;</span>renderer<span class="sy0">,</span> texture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>destRect<span class="sy0">,</span> <span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>angleDegrees<span class="sy0">,</span> NULL<span class="sy0">,</span> SDL_FLIP_NONE<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> RenderFloorTiled<span class="br0">&#40;</span>b2BodyId bodyId<span class="sy0">,</span> SDL_Texture <span class="sy0">*</span>texture<span class="sy0">,</span> <span class="kw4">float</span> floorWidth<span class="sy0">,</span> <span class="kw4">float</span> floorHeight<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// 1. Получаем позицию из Box2D (в метрах)</span>
&nbsp; &nbsp; b2Vec2 pos <span class="sy0">=</span> b2Body_GetPosition<span class="br0">&#40;</span>bodyId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 2. Переводим координаты центра из метров в пиксели</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerX <span class="sy0">=</span> pos.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> centerY <span class="sy0">=</span> pos.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 3. Целевой прямоугольник для отрисовки всего пола</span>
&nbsp; &nbsp; SDL_FRect dstRect <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerX <span class="sy0">-</span> <span class="br0">&#40;</span>floorWidth <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; centerY <span class="sy0">-</span> <span class="br0">&#40;</span>floorHeight <span class="sy0">/</span> <span class="nu17">2.0f</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; floorWidth<span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; floorHeight
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// 4. Вызываем исправленную функцию с 5 аргументами (добавлен 1.0f как масштаб)</span>
&nbsp; &nbsp; <span class="co1">// Параметры: renderer, texture, src_rect (NULL = вся текстура), scale, dst_rect</span>
&nbsp; &nbsp; SDL_RenderTextureTiled<span class="br0">&#40;</span>renderer<span class="sy0">,</span> texture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="nu17">1.0f</span><span class="sy0">,</span> <span class="sy0">&amp;</span>dstRect<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Uint64 current_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> frameTime <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>current_ticks <span class="sy0">-</span> last_ticks<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">1000.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> current_ticks<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>frameTime <span class="sy0">&gt;</span> MAX_FRAME_TIME<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frameTime <span class="sy0">=</span> MAX_FRAME_TIME<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; accumulator <span class="sy0">+=</span> frameTime<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_FRect srcRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">70</span><span class="sy0">,</span> <span class="nu0">70</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_FRect destRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">150</span><span class="sy0">,</span> <span class="nu0">250</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Рисуем ПОЛ плиткой (Tiled)</span>
&nbsp; &nbsp; RenderFloorTiled<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> grass_texture<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">20</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Рисуем спрайты поверх физических тел</span>
&nbsp; &nbsp; <span class="co1">// Размеры берем те же, что задавали при создании коллайдеров (умноженные на 2, т.к. b2MakeBox берет полуобхват)</span>
&nbsp; &nbsp; RenderBody<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> alien_green_square_texture<span class="sy0">,</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; RenderBody<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> alien_yellow_round_texture<span class="sy0">,</span> <span class="nu0">40</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">40</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// диаметр = радиус 20 * 2</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>alien_green_square_texture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>alien_green_square_texture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; alien_green_square_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>alien_yellow_round_texture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>alien_yellow_round_texture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; alien_yellow_round_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>grass_texture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>grass_texture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; grass_texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После сборки командой &quot;build-web&quot; и обновления вкладки браузера вы увидите, что графика рисуется внутри коллайдеров:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11693&amp;d=1772570780" border="0" alt="Название: finish-sync-physics-sprites-sdl3-c-debug-draw.gif
Просмотров: 16280

Размер: 153.3 Кб" style="margin: 5px" /></li>
<li>Для production нужно отключить рисование коллайдеров, то есть закомментировать эту строку:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="933813750"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="933813750" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// b2World_Draw(worldId, &amp;debugDrawer);</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Коллайдеры скрыты:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11694&amp;d=1772571466" border="0" alt="Название: finish-sync-physics-sprites-sdl3-c.gif
Просмотров: 16314

Размер: 156.7 Кб" style="margin: 5px" /></li>
<li>Для сборки в Release поменяйте Debug на Release в файле config-web.bat<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="850934583"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="850934583" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Размер сборки в Release:<ul><li>app.js - 185 KB</li>
<li>app.wasm - 916 KB</li>
</ul></li>
<li>Выполните команды в консоле: &quot;config-web&quot; и &quot;build-web&quot;. Теперь папку &quot;public&quot; вы можете загрузить на бесплатный хостинг: GitHub Pages, Firebase и т.д.</li>
<li>Итоговый код: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11695&amp;d=1772571691">finish-sync-physics-sprites-sdl3-c.zip</a></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11688&amp;d=1772490011" rel="Lightbox" id="attachment11688" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11688&amp;thumb=1&amp;d=1772490011" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 94c24eb3-f142-4548-86f7-8cf4236c00e5.png
Просмотров: 1542
Размер:	12.5 Кб
ID:	11688" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11689&amp;d=1772490050" rel="Lightbox" id="attachment11689" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11689&amp;thumb=1&amp;d=1772490050" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: c92c8509-a6a5-4679-a466-c82eff7e4ec2.png
Просмотров: 1539
Размер:	9.1 Кб
ID:	11689" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11692&amp;d=1772538028" rel="Lightbox" id="attachment11692" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11692&amp;thumb=1&amp;d=1772538028" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 9df82320-e0f3-42f7-92c6-c97caac14db6.png
Просмотров: 1551
Размер:	14.3 Кб
ID:	11692" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11683&amp;d=1772488307">start-sync-physics-sprites-sdl3-c.zip</a> (6.7 Кб, 133 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11685&amp;d=1772489611">SDL3-devel-3.4.2-wasm.zip</a> (1.22 Мб, 87 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11686&amp;d=1772489617">box2d-3.1.1-wasm.zip</a> (149.2 Кб, 111 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11690&amp;d=1772532028">kenney_physics-assets.zip</a> (2.46 Мб, 79 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11695&amp;d=1772571691">finish-sync-physics-sprites-sdl3-c.zip</a> (16.5 Кб, 240 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10758.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий</title>
			<link>https://www.cyberforum.ru/blogs/416874/4561.html</link>
			<pubDate>Mon, 02 Mar 2026 14:15:43 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Финальная демка в...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
<a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/wasm/finish-collision-events-sdl3-c/" target="_blank" title="https://8observer8.github.io/wasm/finish-collision-events-sdl3-c/">Финальная демка в браузере</a>. Итоговый код: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11681&amp;d=1772460580">finish-collision-events-sdl3-c.zip</a> Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем.<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11680&amp;a= mp;d=1772460536" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /> <img src="https://8observer8.github.io/wasm/finish-collision-events-sdl3-c/qr/code.png" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
Одним из самый важных элементов большинства игр является обработка событий коллизий и идентификация объектов между которыми произошла коллизия. Конечно, Box2D имеет встроенные средства для обработки событий коллизий. Пошагово создадим пример, где главный герой будет касаться трёх стен по очереди, на экран будет выводиться текст, показывающий до какой стены дотронулся ГГ.<br />
<br />
<h2>Подключение библиотек к стартовому примеру</h2><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте пример: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11663&amp;d=1772443369">start-collision-events-sdl3-c.zip</a>, который мы создали пошагово по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10757.html">Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами</a></li>
<li>Примечание. В пошаговой инструкции выше использовалась SDL 3.4.0, а мы подключим более новую версию SDL3 3.4.2</li>
<li>Так выглядит код стартового примера:<br />
<br />
src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="560619662"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="560619662" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="co2">#define TIME_STEP (1.0f / 60.0f)</span>
<span class="co2">#define MAX_FRAME_TIME 0.25f</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">float</span> accumulator <span class="sy0">=</span> <span class="nu17">0.0f</span><span class="sy0">;</span>
<span class="kw4">static</span> Uint64 last_ticks <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">typedef</span> <span class="kw4">struct</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; bool up<span class="sy0">;</span>
&nbsp; &nbsp; bool down<span class="sy0">;</span>
&nbsp; &nbsp; bool left<span class="sy0">;</span>
&nbsp; &nbsp; bool right<span class="sy0">;</span>
<span class="br0">&#125;</span> Keys<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> Keys keys <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
b2BodyId circleBodyId<span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">float</span> playerSpeed <span class="sy0">=</span> <span class="nu0">5</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> bool is_mobile <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_SIZE <span class="sy0">=</span> <span class="nu0">60</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_GAP <span class="sy0">=</span> <span class="nu0">5</span><span class="sy0">;</span>
<span class="kw4">static</span> SDL_FRect btnUp<span class="sy0">,</span> btnDown<span class="sy0">,</span> btnLeft<span class="sy0">,</span> btnRight<span class="sy0">;</span>
&nbsp;
<span class="co2">#ifdef __EMSCRIPTEN__</span>
<span class="co2">#include &lt;emscripten.h&gt;</span>
<span class="co1">// This JavaScript function returns true if the user agent matches mobile devices</span>
EM_JS<span class="br0">&#40;</span>bool<span class="sy0">,</span> is_mobile_browser<span class="sy0">,</span> <span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// We use the RegExp constructor to avoid using / / slashes which confuse Clang</span>
&nbsp; &nbsp; &nbsp; &nbsp; var filter <span class="sy0">=</span> new RegExp<span class="br0">&#40;</span><span class="st0">'iPhone|iPad|iPod|Android'</span><span class="sy0">,</span> <span class="st0">'i'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> filter.<span class="me1">test</span><span class="br0">&#40;</span>navigator.<span class="me1">userAgent</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#endif</span>
&nbsp;
<span class="kw4">void</span> updateButtonLayout<span class="br0">&#40;</span><span class="kw4">int</span> w<span class="sy0">,</span> <span class="kw4">int</span> h<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Positioning squares in a cross pattern at the bottom-left</span>
&nbsp; &nbsp; <span class="kw4">float</span> startX <span class="sy0">=</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> startY <span class="sy0">=</span> h <span class="sy0">-</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">*</span> <span class="nu0">3</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; btnUp <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnLeft <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX<span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnRight <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnDown <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Platform detection</span>
<span class="co2">#ifdef __EMSCRIPTEN__</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> is_mobile_browser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#elif defined(__ANDROID__) || defined(__IPHONEOS__)</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
<span class="co2">#endif</span>
&nbsp;
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Is Mobile: %s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> is_mobile <span class="sy0">?</span> <span class="st0">&quot;Yes&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;No&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Initial Layout</span>
&nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; updateButtonLayout<span class="br0">&#40;</span>w<span class="sy0">,</span> h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> friction <span class="sy0">=</span> <span class="nu17">0.1f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Top wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef topWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">20.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId topWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon topWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef topWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId topWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>topWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Left wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef leftWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">120</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">230</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId leftWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon leftWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef leftWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId leftWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>leftWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Right wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef rightWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">280</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">285</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId rightWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon rightWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef rightWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId rightWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>rightWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">250</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">fixedRotation</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Touch handling</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_UP <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_MOTION<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> tx <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> ty <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; bool pressed <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">!=</span> SDL_EVENT_FINGER_UP<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Point pt <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>tx<span class="sy0">,</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>ty <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Check rectangles (Manual check since FRect is float)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">+</span> btnUp.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">+</span> btnUp.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">+</span> btnDown.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">+</span> btnDown.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">+</span> btnLeft.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">+</span> btnLeft.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">+</span> btnRight.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">+</span> btnRight.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> keyboard<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; b2Vec2 velocity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">up</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">down</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">right</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; b2Body_SetLinearVelocity<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> velocity<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; keyboard<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; Uint64 current_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> frameTime <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>current_ticks <span class="sy0">-</span> last_ticks<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">1000.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> current_ticks<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>frameTime <span class="sy0">&gt;</span> MAX_FRAME_TIME<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frameTime <span class="sy0">=</span> MAX_FRAME_TIME<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; accumulator <span class="sy0">+=</span> frameTime<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Render Touch UI only if mobile/web</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>is_mobile<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawBlendMode<span class="br0">&#40;</span>renderer<span class="sy0">,</span> SDL_BLENDMODE_BLEND<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Semi-transparent white</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnUp<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnDown<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnLeft<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnRight<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>src/debug-drawer.h<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="527981862"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="527981862" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
</pre></td><td class="de1"><pre class="de1"><span class="co2">#ifndef DEBUG_DRAWER_H</span>
<span class="co2">#define DEBUG_DRAWER_H</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
&nbsp;
<span class="kw2">extern</span> SDL_Renderer <span class="sy0">*</span>renderer<span class="sy0">;</span>
<span class="kw2">extern</span> <span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format<span class="sy0">;</span>
<span class="kw2">extern</span> <span class="kw4">float</span> ppm<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">void</span> drawSolidPolygon<span class="br0">&#40;</span>b2Transform transform<span class="sy0">,</span>
&nbsp; &nbsp; <span class="kw4">const</span> b2Vec2 <span class="sy0">*</span>vertices<span class="sy0">,</span> <span class="kw4">int</span> vertexCount<span class="sy0">,</span>
&nbsp; &nbsp; <span class="kw4">float</span> radius<span class="sy0">,</span> b2HexColor color<span class="sy0">,</span> <span class="kw4">void</span> <span class="sy0">*</span>context<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>radius<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>context<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Extract RGB</span>
&nbsp; &nbsp; Uint8 r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetRGB<span class="br0">&#40;</span>color<span class="sy0">,</span> format<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>r<span class="sy0">,</span> <span class="sy0">&amp;</span>g<span class="sy0">,</span> <span class="sy0">&amp;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Draw a collider rectangle with lines</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> vertexCount<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> next_index <span class="sy0">=</span> <span class="br0">&#40;</span>i <span class="sy0">+</span> <span class="nu0">1</span> <span class="sy0">==</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="nu0">0</span> <span class="sy0">:</span> i <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p0 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>next_index<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x0 <span class="sy0">=</span> p0.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y0 <span class="sy0">=</span> p0.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x1 <span class="sy0">=</span> p1.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y1 <span class="sy0">=</span> p1.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> x0<span class="sy0">,</span> y0<span class="sy0">,</span> x1<span class="sy0">,</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Tip: Draw orientation line ---</span>
&nbsp; &nbsp; <span class="co1">// Compute polygon center</span>
&nbsp; &nbsp; <span class="kw4">float</span> cx <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> cy <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> vertexCount<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; cx <span class="sy0">+=</span> p.<span class="me1">x</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; cy <span class="sy0">+=</span> p.<span class="me1">y</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; cx <span class="sy0">=</span> <span class="br0">&#40;</span>cx <span class="sy0">/</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; cy <span class="sy0">=</span> <span class="br0">&#40;</span>cy <span class="sy0">/</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Midpoint of second edge (vertex[1] → vertex[2])</span>
&nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 p2 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> mx <span class="sy0">=</span> <span class="br0">&#40;</span>p1.<span class="me1">x</span> <span class="sy0">+</span> p2.<span class="me1">x</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu17">0.5f</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> my <span class="sy0">=</span> <span class="br0">&#40;</span>p1.<span class="me1">y</span> <span class="sy0">+</span> p2.<span class="me1">y</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu17">0.5f</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw center → edge midpoint line (acts like &quot;direction tip&quot;)</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> cx<span class="sy0">,</span> cy<span class="sy0">,</span> mx<span class="sy0">,</span> my<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">void</span> drawSolidCircle<span class="br0">&#40;</span>b2Transform transform<span class="sy0">,</span> <span class="kw4">float</span> radius<span class="sy0">,</span>
&nbsp; &nbsp; b2HexColor color<span class="sy0">,</span> <span class="kw4">void</span> <span class="sy0">*</span>context<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>radius<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>context<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> angle <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">int</span> numberOfSegments <span class="sy0">=</span> <span class="nu0">20</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> angleStep <span class="sy0">=</span> <span class="nu0">360</span>.<span class="me1">f</span> <span class="sy0">/</span> numberOfSegments<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Extract RGB</span>
&nbsp; &nbsp; Uint8 r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetRGB<span class="br0">&#40;</span>color<span class="sy0">,</span> format<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>r<span class="sy0">,</span> <span class="sy0">&amp;</span>g<span class="sy0">,</span> <span class="sy0">&amp;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Draw a collider rectangle with lines</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">cos</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">sin</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 p0 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> x<span class="sy0">,</span> y <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> x0 <span class="sy0">=</span> p0.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y0 <span class="sy0">=</span> p0.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; angle <span class="sy0">+=</span> angleStep<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> numberOfSegments<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">cos</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">sin</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> x<span class="sy0">,</span> y <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x1 <span class="sy0">=</span> p1.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y1 <span class="sy0">=</span> p1.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> x0<span class="sy0">,</span> y0<span class="sy0">,</span> x1<span class="sy0">,</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; x0 <span class="sy0">=</span> x1<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; y0 <span class="sy0">=</span> y1<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; angle <span class="sy0">+=</span> angleStep<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>angle <span class="sy0">&gt;=</span> <span class="nu0">360</span>.<span class="me1">f</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; angle <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Tip: Draw orientation line ---</span>
&nbsp; &nbsp; <span class="co1">// Circle center</span>
&nbsp; &nbsp; b2Vec2 c <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> cx <span class="sy0">=</span> c.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> cy <span class="sy0">=</span> c.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Direction = transform applied to (radius, 0)</span>
&nbsp; &nbsp; b2Vec2 orient <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> radius<span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> ox <span class="sy0">=</span> orient.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> oy <span class="sy0">=</span> orient.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw center → orientation marker</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> cx<span class="sy0">,</span> cy<span class="sy0">,</span> ox<span class="sy0">,</span> oy<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co2">#endif // DEBUG_DRAWER_H</span></pre></td></tr></table></div></td></tr></tbody></table></div>CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="336990099"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="336990099" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu16">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start<span class="sy0">-</span>collision<span class="sy0">-</span>events<span class="sy0">-</span>sdl3<span class="sy0">-</span>c<span class="br0">&#41;</span>
&nbsp;
<span class="co2"># Задаем название будущего приложения (в Windows это был бы app.exe, а в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co2"># Устанавливаем стандарт C</span>
set<span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co2"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="co2"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
set<span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
set<span class="br0">&#40;</span>box2d_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co2"># Проверяем наличие библиотек в системе</span>
<span class="co2"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co2"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>box2d REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co2"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE box2d<span class="sy0">::</span><span class="me2">box2d</span> SDL3<span class="sy0">::</span><span class="me2">SDL3</span><span class="br0">&#41;</span>
&nbsp;
<span class="co2"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.<span class="me1">c</span>
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Напомню, что результатом этого стартового примера являются перемещение главного героя с помощью клавиш WASD (и клавиш стрелок) на в браузерах на Desktop и при запуске на мобильных браузерах появляется простейший джойстик из 4-х кнопок, которые мы рисуем квадратами. Запустить демку можно <a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/wasm/finish-player-movement-sdl3-c/" target="_blank" title="https://8observer8.github.io/wasm/finish-player-movement-sdl3-c/">по этой ссылке</a><br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11664&amp;a= mp;d=1772444075" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br /></li>
<li>Запустим стартовый пример, а для этого скачаем и подключим библиотеки SDL3 и Box2D, а так же мы скачаем и подключим библиотеки FreeType и SDL3_ttf для вывода текста</li>
<li>Откройте папку со стартовым примером в какой-нибудь редакторе кода, например, в Notepad++ или в Sublime Text 4 (ST4): <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a></li>
<li>Скачайте библиотеку SDL3 для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11665&amp;d=1772444384">SDL3-devel-3.4.2-wasm.zip</a></li>
<li>Скачайте библиотеку Box2D v3 для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11666&amp;d=1772444396">box2d-3.1.1-wasm.zip</a></li>
<li>Скачайте библиотеку FreeType для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11667&amp;d=1772444406">freetype-2.14.1-wasm</a></li>
<li>Скачайте библиотеку SDL3_ttf для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11668&amp;d=1772444416">SDL3_ttf-devel-3.2.2-wasm.zip</a></li>
<li>Извлеките содержимое архив выше в какую-нибудь новую общую папку, например, с именем &quot;libs&quot; на какой-нибудь диск, например, на C. Таким образом, создайте на диске C папку &quot;lib&quot;, скопируйте в неё архивы и извлеките их в текущую папку:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11672&amp;d=1772445036" border="0" alt="Название: d238d741-b2ce-42a4-88d7-8e0196845580.png
Просмотров: 1765

Размер: 5.7 Кб" style="margin: 5px" /><br /></li>
<li>Откройте папку &quot;SDL3-devel-3.4.2-wasm&quot;, перейдите в &quot;lib/cmake/SDL3&quot; и скопируйте абсолютный путь:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11673&amp;a= mp;d=1772447043" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br /></li>
<li>В файле CMakeLists.txt стартового примера замените в переменной SDL3_DIR путь на свой, который скопировали выше:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="145786655"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="145786655" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку &quot;box2d-3.1.1-wasm&quot;, перейдите в &quot;lib/cmake/box2d&quot; и скопируйте абсолютный путь:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11674&amp;a= mp;d=1772447152" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br /></li>
<li>Замените в переменной box2d_DIR путь на свой:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="296529608"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="296529608" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Проделайте почти тоже самое для подключения библиотек FreeType и SDL3_ttf, то есть сначала копируйте пути:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11676&amp;d=1772447936" border="0" alt="Название: 744b6134-fd50-4eaa-a765-972879110569.png
Просмотров: 1748

Размер: 8.0 Кб" style="margin: 5px" /><br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11677&amp;a= mp;d=1772448103" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br /></li>
<li>А потом копируйте пути в CMakeLists.txt, создавая соответствующую переменную с суффиксом _DIR, но обратите внимание, что для FreeType нужно создать переменные FREETYPE_INCLUDE_DIRS и FREETYPE_LIBRARY и изменить пути, как показано в коде:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="426066824"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="426066824" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>FREETYPE_INCLUDE_DIRS <span class="st0">&quot;C:/libs/freetype-2.14.1-wasm/include&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>FREETYPE_LIBRARY <span class="st0">&quot;C:/libs/freetype-2.14.1-wasm/lib/libfreetype.a&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_ttf_DIR <span class="st0">&quot;C:/libs/SDL3_ttf-devel-3.2.2-wasm/lib/cmake/SDL3_ttf&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В итоге получается такой код подключения файлов библиотек:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="202146005"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="202146005" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>box2d_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>FREETYPE_INCLUDE_DIRS <span class="st0">&quot;C:/libs/freetype-2.14.1-wasm/include&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>FREETYPE_LIBRARY <span class="st0">&quot;C:/libs/freetype-2.14.1-wasm/lib/libfreetype.a&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_ttf_DIR <span class="st0">&quot;C:/libs/SDL3_ttf-devel-3.2.2-wasm/lib/cmake/SDL3_ttf&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После команды find_package(box2d REQUIRED) добавим аналогичную команду для SDL3_ttf:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="635799133"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="635799133" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>box2d REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_ttf REQUIRED<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте SDL3_ttf::SDL3_ttf в настройку линковки:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="140429476"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="140429476" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE box2d::box2d SDL3_ttf::SDL3_ttf SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>По следующей инструкции проведём тестовую сборку, чтобы убедиться, что библиотеки подключены и пример работает</li>
</ul><br />
<h2>Тестовая сборка и тестовый запуск стартового примера в браузере на локальном хостинге</h2><br />
<br />
<ul><li>Откройте консоль (CMD) в корне стартового примера. Для этого можете просто в адресной строке папки (там где путь) написать &quot;cmd&quot; (без кавычек) и нажать Enter</li>
<li>В CMD введите команду для конфигурирования:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="709831996"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="709831996" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;config-web&quot; - это имя bash-файла (батника), который находится в корне папки стартового примера</li>
<li>В CMD введите команду сборки проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="777844386"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="777844386" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Собранные файлы (app.js и app.wasm) будут скопированы в папку &quot;public/js&quot; (папка &quot;public&quot; лежит в корне проекта)</li>
<li>В корне проекта запустите локальный сервер командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="662218292"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="662218292" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Будут выведены адреса:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="304976706"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="304976706" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>192.168.1.65:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 2. Адрес 192.168.1.65:8080 можно использовать для запуска приложения на мобильном устройстве, если у вас есть Wi-Fi - просто вводите этот адрес в браузере мобильного устройства и приложение запустится. Если интересен запуск на мобильном устройстве, то пройдите пошаговую инструкцию: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a></li>
<li>Откройте новую вкладку в браузере. Если у вас Chrome или Edge, то нажмите Ctrl+Shift+J, чтобы открыть консоль браузера для контроля вывода информации. Если у вас FireFox, то нажмите Ctrl+Shift+K</li>
<li>Перейдите по адресу:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="935214669"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="935214669" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Обновлять страницу после повторной сборки проекта лучше с очисткой кэша браузера. Для этого (обязательно с открытой консолью браузера) в браузере Chrome нужно найти в левом верхнем углу браузера кнопку обновления страницы (круговая стрелка), нажать по ней правой кнопкой мыши и выбрать &quot;Empty Cache and Hard Reload&quot;</li>
<li>Мы убедились, что тестовый пример запускается нормально. Если вы что-то меняете в коде (в файлах main.c или CMakeLists.txt), то достаточно ввести команду для сборки build-web (в CMD нажать стрелку-вверх и Enter) и обновить вкладку в браузере. Удобнее всего, чтобы локальный хостинг был запущен в одном окне CMD, а сборку делать в другом окне CMD</li>
</ul><br />
<h2>Что такое userData и как использовать</h2><br />
<br />
userData - это возможность к каждому объекты прикрепить пользовательские данные. В нашем случае к каждому объекты прикрепим имя. Это нужно для того, чтобы при возникновении события коллизии между двумя объектами мы могли определить по именам - между какими двумя объектами произошла коллизия и таким образом идентифицировать объекты. Добавим userData с именами объектов по следующей инструкции:<br />
<br />
<ul><li>В файле src/main.c найдите код создания создания коллайдера верхней стены:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="53926140"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="53926140" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Top wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef topWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">20.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId topWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon topWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef topWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId topWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>topWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В конце блока с фигурными скобками добавьте имя для верхней стены:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="461877487"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="461877487" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Top wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// ...</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>topWallShapeId<span class="sy0">,</span> <span class="st0">&quot;top_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Тоже самое проделайте для боковых стен и для для коллайдера главного героя. В итоге получился следующий код:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="25385058"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="25385058" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Top wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef topWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">20.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId topWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon topWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef topWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId topWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>topWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>topWallShapeId<span class="sy0">,</span> <span class="st0">&quot;top_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Left wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef leftWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">120</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">230</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId leftWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon leftWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef leftWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId leftWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>leftWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>leftWallShapeId<span class="sy0">,</span> <span class="st0">&quot;left_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Right wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef rightWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">280</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">285</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId rightWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon rightWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef rightWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId rightWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>rightWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>rightWallShapeId<span class="sy0">,</span> <span class="st0">&quot;right_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">250</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">fixedRotation</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>circleShapeId<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Теперь у каждого объекта на сцене есть своё имя. Это имя мы будет использовать, чтобы понять какие два коллайдера столкнулись и какой коллайдер является коллайдером главного героя, а какой является определённой стеной</li>
</ul><br />
<h2>Обработчик событий коллизий</h2><br />
<br />
Для удобства организации кода, обработчики событий коллизий будем писать в отдельном файле с именем &quot;contact-listener.h&quot;<br />
<br />
<ul><li>Создайте новый файл с именем &quot;contact-listener.h&quot; в папке &quot;src&quot;. Скопируйте следующий код в файл &quot;contact-listener.h&quot;:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="194866751"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="194866751" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
</pre></td><td class="de1"><pre class="de1"><span class="co2">#ifndef CONTACT_LISTENER_H</span>
<span class="co2">#define CONTACT_LISTENER_H</span>
&nbsp;
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;string.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &lt;stdbool.h&gt;</span>
&nbsp;
<span class="kw4">typedef</span> <span class="kw4">struct</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">char</span> text<span class="br0">&#91;</span><span class="nu0">128</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; bool dirty<span class="sy0">;</span>
<span class="br0">&#125;</span> ContactListenerData<span class="sy0">;</span>
&nbsp;
<span class="co1">// Call this every frame after stepping the world</span>
<span class="kw4">void</span> ProcessContactEvents<span class="br0">&#40;</span>b2WorldId worldId<span class="sy0">,</span> ContactListenerData <span class="sy0">*</span>listener<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; b2ContactEvents events <span class="sy0">=</span> b2World_GetContactEvents<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Begin contacts ---</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> events.<span class="me1">beginCount</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2ContactBeginTouchEvent event <span class="sy0">=</span> events.<span class="me1">beginEvents</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameA <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdA</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameB <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdB</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameA<span class="br0">&#41;</span> nameA <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameB<span class="br0">&#41;</span> nameB <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>wallName <span class="sy0">=</span> <span class="kw3">strcmp</span><span class="br0">&#40;</span>nameA<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span> <span class="sy0">?</span> nameB <span class="sy0">:</span> nameA<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">snprintf</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="sy0">,</span> <span class="kw4">sizeof</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;Begin contact with %s&quot;</span><span class="sy0">,</span> wallName<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; listener<span class="sy0">-&gt;</span>dirty <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- End contacts ---</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> events.<span class="me1">endCount</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2ContactEndTouchEvent event <span class="sy0">=</span> events.<span class="me1">endEvents</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameA <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdA</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameB <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdB</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameA<span class="br0">&#41;</span> nameA <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameB<span class="br0">&#41;</span> nameB <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>wallName <span class="sy0">=</span> <span class="kw3">strcmp</span><span class="br0">&#40;</span>nameA<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span> <span class="sy0">?</span> nameB <span class="sy0">:</span> nameA<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">snprintf</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="sy0">,</span> <span class="kw4">sizeof</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;End contact with %s&quot;</span><span class="sy0">,</span> wallName<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; listener<span class="sy0">-&gt;</span>dirty <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co2">#endif // CONTACT_LISTENER_H</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Функцию ProcessContactEvents() в коде выше нужно будет вызывать в главном цикле приложения сразу после вызова b2World_Step(), то есть после каждого тика физического мира</li>
<li>Комментарии к тому, что происходит внутри функции ProcessContactEvents(). Я не будут расписывать это сам построчно. Я предлагаю скопировать весь этот код в Gemini и написать ему перед скопированным кодом &quot;Объясни простыми словами для начинающего, что происходит в следующем коде&quot;:<br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Вот что мне выдал Gemini</div>
				   <div class="spoiler-body">
					   <br />
<br />
Этот код — типичный обработчик столкновений для физического движка <b>Box2D</b> (версия 3.x). Если говорить совсем просто: это «уши» твоей игры, которые слушают, когда один объект касается другого, и записывают это событие текстом.<br />
<br />
Давай разберем его по частям.<br />
<ol style="list-style-type: decimal"><li><b>Структура данных (Контейнер для информации)</b><br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="967253761"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="967253761" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw4">typedef</span> <span class="kw4">struct</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">char</span> text<span class="br0">&#91;</span><span class="nu0">128</span><span class="br0">&#93;</span><span class="sy0">;</span> <span class="co1">// Сюда запишем сообщение, например: &quot;Начало контакта с lef_wall&quot;</span>
&nbsp; &nbsp; bool dirty<span class="sy0">;</span> &nbsp; &nbsp; <span class="co1">// Флаг-сигнал: &quot;Эй, текст изменился, обнови его на экране!&quot;</span>
<span class="br0">&#125;</span> ContactListenerData<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Эта структура нужна, чтобы передавать информацию о столкновениях из физического мира в графическую часть игры (например, чтобы вывести надпись в углу экрана).<br /></li>
<li>Главная функция: ProcessContactEvents<br />
<br />
Она работает в два этапа: обрабатывает начало касания и конец касания.<br />
<br />
<b>Этап А: Начало касания (Begin contacts)</b><br />
<br />
Когда два объекта ударяются друг о друга, Box2D создает событие.<br />
<ol style="list-style-type: decimal"><li><b>Получение имен:</b> Код берет два объекта (shapeIdA и shapeIdB) и спрашивает: &quot;Как вас зовут?&quot;. Имена хранятся в UserData.</li>
<li><b>Логика &quot;Кто не игрок?&quot;:</b> Программа ищет объект &quot;player&quot;. Если первый объект — игрок, значит нам интересно имя второго. Так мы узнаем, обо что именно ударился игрок (о стену, о врага и т.д.).<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="119707463"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="119707463" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>wallName <span class="sy0">=</span> <span class="kw3">strcmp</span><span class="br0">&#40;</span>nameA<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span> <span class="sy0">?</span> nameB <span class="sy0">:</span> nameA<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Запись: Текст &quot;Начало контакта с [Имя]&quot; копируется в буфер, а флаг dirty ставится в true.</li>
</ol><br />
<b>Этап Б: Конец касания (End contacts)</b><br />
<br />
Здесь происходит ровно то же самое, но в момент, когда объекты разлетаются в разные стороны. Текст меняется на &quot;End contact with...&quot;.</li>
</ol><br />
<b>Как это работает визуально</b><br />
<br />
Представь, что у тебя есть круг (Player) и квадрат (Box).<br />
<ol style="list-style-type: decimal"><li>Как только круг касается края квадрата, срабатывает первый цикл for, и в listener-&gt;text попадает фраза: <b>&quot;Begin contact with Box&quot;</b>.</li>
<li>Пока они соприкасаются, ничего не происходит.</li>
<li>Как только круг отлетает от квадрата, срабатывает второй цикл, и текст меняется на: <b>&quot;End contact with Box&quot;</b>.</li>
</ol><br />
<b>Важные нюансы для новичка</b><br />
<ul><li>#ifndef / #define: Это «защита от дурака». Она гарантирует, что если ты случайно подключишь этот файл в нескольких местах, компилятор не сойдет с ума от дубликатов.</li>
<li>snprintf: Это безопасный способ склеить строку и переменную. Она следит, чтобы текст не вылез за пределы выделенных 128 байт (чтобы программа не &quot;сломалась&quot;).</li>
<li>b2World_GetContactEvents: Важно помнить, что в Box2D 3.0 события нужно запрашивать самому каждый кадр, они не прилетают автоматически.</li>
</ul><br />

				   </div>
			   </div></li>
<li>Вы можете копировать отдельные строки кода или несколько строк кода и просить Gemini подробнее объяснить</li>
<li>Откройте файл &quot;src/main.c&quot;</li>
<li>Добавьте подключение файла &quot;contact-listener.h&quot;:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="180200359"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="180200359" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="co2">#include &quot;contact-listener.h&quot;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте глобальную переменную &quot;contactData&quot;:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="322098156"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="322098156" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> ContactListenerData contactData<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppInit() после кода вывода значения гравитации в консоль добавьте код инициализации структуры &quot;contactData&quot;:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="704167631"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="704167631" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw3">strcpy</span><span class="br0">&#40;</span>contactData.<span class="me1">text</span><span class="sy0">,</span> <span class="st0">&quot;Коснитесь стены&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; contactData.<span class="me1">dirty</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppIterate() после вызова b2World_Step() добавьте вызов ProcessContactEvents():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="52038596"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="52038596" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Read contact events immediately</span>
&nbsp; &nbsp; &nbsp; &nbsp; ProcessContactEvents<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>contactData<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавим в консоль вывод текста при срабатывании события начала контакта в файле &quot;contact-listener.h&quot;. В обоих цикла (&quot;Begin contacts&quot; и &quot;End contacts&quot;) добавьте строку вывода текста после функций snprintf():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="836164767"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="836164767" style="height: 270px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// --- Begin contacts ---</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> events.<span class="me1">beginCount</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// ...</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- End contacts ---</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> events.<span class="me1">endCount</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// ...</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Сверьте код:<br />
<br />
src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="655477972"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="655477972" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &quot;contact-listener.h&quot;</span>
&nbsp;
<span class="co2">#define TIME_STEP (1.0f / 60.0f)</span>
<span class="co2">#define MAX_FRAME_TIME 0.25f</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
<span class="kw4">static</span> ContactListenerData contactData<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">float</span> accumulator <span class="sy0">=</span> <span class="nu17">0.0f</span><span class="sy0">;</span>
<span class="kw4">static</span> Uint64 last_ticks <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">typedef</span> <span class="kw4">struct</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; bool up<span class="sy0">;</span>
&nbsp; &nbsp; bool down<span class="sy0">;</span>
&nbsp; &nbsp; bool left<span class="sy0">;</span>
&nbsp; &nbsp; bool right<span class="sy0">;</span>
<span class="br0">&#125;</span> Keys<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> Keys keys <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
b2BodyId circleBodyId<span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">float</span> playerSpeed <span class="sy0">=</span> <span class="nu0">5</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> bool is_mobile <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_SIZE <span class="sy0">=</span> <span class="nu0">60</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_GAP <span class="sy0">=</span> <span class="nu0">5</span><span class="sy0">;</span>
<span class="kw4">static</span> SDL_FRect btnUp<span class="sy0">,</span> btnDown<span class="sy0">,</span> btnLeft<span class="sy0">,</span> btnRight<span class="sy0">;</span>
&nbsp;
<span class="co2">#ifdef __EMSCRIPTEN__</span>
<span class="co2">#include &lt;emscripten.h&gt;</span>
<span class="co1">// This JavaScript function returns true if the user agent matches mobile devices</span>
EM_JS<span class="br0">&#40;</span>bool<span class="sy0">,</span> is_mobile_browser<span class="sy0">,</span> <span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// We use the RegExp constructor to avoid using / / slashes which confuse Clang</span>
&nbsp; &nbsp; &nbsp; &nbsp; var filter <span class="sy0">=</span> new RegExp<span class="br0">&#40;</span><span class="st0">'iPhone|iPad|iPod|Android'</span><span class="sy0">,</span> <span class="st0">'i'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> filter.<span class="me1">test</span><span class="br0">&#40;</span>navigator.<span class="me1">userAgent</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#endif</span>
&nbsp;
<span class="kw4">void</span> updateButtonLayout<span class="br0">&#40;</span><span class="kw4">int</span> w<span class="sy0">,</span> <span class="kw4">int</span> h<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Positioning squares in a cross pattern at the bottom-left</span>
&nbsp; &nbsp; <span class="kw4">float</span> startX <span class="sy0">=</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> startY <span class="sy0">=</span> h <span class="sy0">-</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">*</span> <span class="nu0">3</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; btnUp <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnLeft <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX<span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnRight <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnDown <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Platform detection</span>
<span class="co2">#ifdef __EMSCRIPTEN__</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> is_mobile_browser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#elif defined(__ANDROID__) || defined(__IPHONEOS__)</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
<span class="co2">#endif</span>
&nbsp;
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Is Mobile: %s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> is_mobile <span class="sy0">?</span> <span class="st0">&quot;Yes&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;No&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Initial Layout</span>
&nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; updateButtonLayout<span class="br0">&#40;</span>w<span class="sy0">,</span> h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw3">strcpy</span><span class="br0">&#40;</span>contactData.<span class="me1">text</span><span class="sy0">,</span> <span class="st0">&quot;Коснитесь стены&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; contactData.<span class="me1">dirty</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> friction <span class="sy0">=</span> <span class="nu17">0.1f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Top wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef topWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">20.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId topWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon topWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef topWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId topWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>topWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>topWallShapeId<span class="sy0">,</span> <span class="st0">&quot;top_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Left wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef leftWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">120</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">230</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId leftWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon leftWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef leftWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId leftWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>leftWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>leftWallShapeId<span class="sy0">,</span> <span class="st0">&quot;left_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Right wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef rightWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">280</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">285</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId rightWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon rightWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef rightWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId rightWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>rightWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>rightWallShapeId<span class="sy0">,</span> <span class="st0">&quot;right_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">250</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">fixedRotation</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>circleShapeId<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Touch handling</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_UP <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_MOTION<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> tx <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> ty <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; bool pressed <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">!=</span> SDL_EVENT_FINGER_UP<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Point pt <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>tx<span class="sy0">,</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>ty <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Check rectangles (Manual check since FRect is float)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">+</span> btnUp.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">+</span> btnUp.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">+</span> btnDown.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">+</span> btnDown.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">+</span> btnLeft.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">+</span> btnLeft.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">+</span> btnRight.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">+</span> btnRight.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> keyboard<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; b2Vec2 velocity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">up</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">down</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">right</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; b2Body_SetLinearVelocity<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> velocity<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; keyboard<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; Uint64 current_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> frameTime <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>current_ticks <span class="sy0">-</span> last_ticks<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">1000.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> current_ticks<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>frameTime <span class="sy0">&gt;</span> MAX_FRAME_TIME<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frameTime <span class="sy0">=</span> MAX_FRAME_TIME<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; accumulator <span class="sy0">+=</span> frameTime<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Read contact events immediately</span>
&nbsp; &nbsp; &nbsp; &nbsp; ProcessContactEvents<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>contactData<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Render Touch UI only if mobile/web</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>is_mobile<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawBlendMode<span class="br0">&#40;</span>renderer<span class="sy0">,</span> SDL_BLENDMODE_BLEND<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Semi-transparent white</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnUp<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnDown<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnLeft<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnRight<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>src/contact-listener.h<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="226414444"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="226414444" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
</pre></td><td class="de1"><pre class="de1"><span class="co2">#ifndef CONTACT_LISTENER_H</span>
<span class="co2">#define CONTACT_LISTENER_H</span>
&nbsp;
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;string.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &lt;stdbool.h&gt;</span>
&nbsp;
<span class="kw4">typedef</span> <span class="kw4">struct</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">char</span> text<span class="br0">&#91;</span><span class="nu0">128</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; bool dirty<span class="sy0">;</span>
<span class="br0">&#125;</span> ContactListenerData<span class="sy0">;</span>
&nbsp;
<span class="co1">// Call this every frame after stepping the world</span>
<span class="kw4">void</span> ProcessContactEvents<span class="br0">&#40;</span>b2WorldId worldId<span class="sy0">,</span> ContactListenerData <span class="sy0">*</span>listener<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; b2ContactEvents events <span class="sy0">=</span> b2World_GetContactEvents<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Begin contacts ---</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> events.<span class="me1">beginCount</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2ContactBeginTouchEvent event <span class="sy0">=</span> events.<span class="me1">beginEvents</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameA <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdA</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameB <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdB</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameA<span class="br0">&#41;</span> nameA <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameB<span class="br0">&#41;</span> nameB <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>wallName <span class="sy0">=</span> <span class="kw3">strcmp</span><span class="br0">&#40;</span>nameA<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span> <span class="sy0">?</span> nameB <span class="sy0">:</span> nameA<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">snprintf</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="sy0">,</span> <span class="kw4">sizeof</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;Начало контакта с %s&quot;</span><span class="sy0">,</span> wallName<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; listener<span class="sy0">-&gt;</span>dirty <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- End contacts ---</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> events.<span class="me1">endCount</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2ContactEndTouchEvent event <span class="sy0">=</span> events.<span class="me1">endEvents</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameA <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdA</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameB <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdB</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameA<span class="br0">&#41;</span> nameA <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameB<span class="br0">&#41;</span> nameB <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>wallName <span class="sy0">=</span> <span class="kw3">strcmp</span><span class="br0">&#40;</span>nameA<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span> <span class="sy0">?</span> nameB <span class="sy0">:</span> nameA<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">snprintf</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="sy0">,</span> <span class="kw4">sizeof</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;Конец контакта с %s&quot;</span><span class="sy0">,</span> wallName<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; listener<span class="sy0">-&gt;</span>dirty <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co2">#endif // CONTACT_LISTENER_H</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После сборки проекта командой &quot;build-web&quot; и обновления вкладки браузера вы можете, управляя главным героем, касаться стен и видеть вывод в консоль - когда произошёл контакт со стеной, имя стены и когда произошёл разрыв контакта со стеной:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="314850619"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="314850619" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">Begin contact with left_wall
End contact with left_wall
Begin contact with right_wall
End contact with right_wall
Begin contact with top_wall
End contact with top_wall</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Вывод текста на холст при контакте со стенами</h2><br />
<br />
Используем библиотеку SDL3_ttf, чтобы выводить текст на холст при событиях коллизий<br />
<br />
<ul><li>Скачайте бесплатный шрифт TTF: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11678&amp;d=1772455990">LiberationSans-Regular.zip</a></li>
<li>Примечание. Бесплатный файл шрифта был взят по <a rel="nofollow noopener noreferrer" href="https://github.com/liberationfonts/liberation-fonts/releases/tag/2.1.5" target="_blank" title="https://github.com/liberationfonts/liberation-fonts/releases/tag/2.1.5">ссылке</a>)</li>
<li>В корне проекта создайте папку &quot;assets&quot;, а в внутри этой папки создайте папку &quot;fonts&quot;</li>
<li>Перенесите извлечённый файл LiberationSans-Regular.ttf в папку &quot;assets/fonts&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11679&amp;d=1772456207" border="0" alt="Название: 0b3bbfca-a05e-4866-a3d9-9cb4985a81dd.png
Просмотров: 1745

Размер: 3.6 Кб" style="margin: 5px" /></li>
<li>Откройте файл CMakeLists.txt и скопируйте код для загрузки TTF файла в конец файла CMakeLists.txt:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="707728979"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="707728979" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">if <span class="br0">&#40;</span>EMSCRIPTEN<span class="br0">&#41;</span>
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span>&quot;app&quot; PRIVATE &quot;SHELL:--embed-file $<span class="br0">&#123;</span>CMAKE_CURRENT_SOURCE_DIR<span class="br0">&#125;</span>/assets/fonts/LiberationSans-Regular.ttf@/assets/fonts/LiberationSans-Regular.ttf&quot;<span class="br0">&#41;</span>
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET &quot;app&quot; APPEND PROPERTY LINK_DEPENDS &quot;$<span class="br0">&#123;</span>CMAKE_CURRENT_SOURCE_DIR<span class="br0">&#125;</span>/assets/fonts/LiberationSans-Regular.ttf&quot;<span class="br0">&#41;</span>
endif<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Таким образом можно загружать любые ассеты: картинки, звуки, XML или JSON -файлы и т.д. - просто копируйте код выше и меняйте пути</li>
<li>Откройте файл &quot;src/main.c&quot; и в начале файла добавьте подключение SDL3_ttf:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="581330061"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="581330061" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="co2">#include &lt;SDL3_ttf/SDL_ttf.h&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте глобальные переменные &quot;textTexture&quot;, &quot;font&quot; и &quot;textRect&quot;:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="55743083"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="55743083" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> TTF_Font <span class="sy0">*</span>font <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_FRect textRect<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Чтобы не забыть освободить ресурсы &quot;textTexture&quot; и &quot;font&quot;. В функции SDL_AppQuit() добавьте удаление текстуры и шрифта:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="834230100"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="834230100" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>font<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; TTF_CloseFont<span class="br0">&#40;</span>font<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; font <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppInit() добавьте инициализацию библиотеки SDL3_ttf после после инициализации библиотеки SDL3, то есть после вызова функции SDL_Init():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="940307054"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="940307054" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Initialize the TTF library</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>TTF_Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize TTF: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Перед инициализаций структуры &quot;contactData&quot; добавьте код открытия файла шрифта:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="905561509"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="905561509" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; font <span class="sy0">=</span> TTF_OpenFont<span class="br0">&#40;</span><span class="st0">&quot;./assets/fonts/LiberationSans-Regular.ttf&quot;</span><span class="sy0">,</span> <span class="nu0">28</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>font<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;TTF_OpenFont failed: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppIterate() перед вызовом функции SDL_SetRenderDrawColor() добавьте, который обновляет текстуру с текстом, когда текст обновился:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="793075745"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="793075745" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// --- Update text only when dirty ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>contactData.<span class="me1">dirty</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Destroy old texture</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Color textColor <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Render text to surface</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> TTF_RenderText_Blended<span class="br0">&#40;</span>font<span class="sy0">,</span> contactData.<span class="me1">text</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">strlen</span><span class="br0">&#40;</span>contactData.<span class="me1">text</span><span class="br0">&#41;</span><span class="sy0">,</span> textColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>surface<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Create texture from surface</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textTexture <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Get texture size</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTextureSize<span class="br0">&#40;</span>textTexture<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Set text rectangle</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textRect.<span class="me1">x</span> <span class="sy0">=</span> <span class="nu17">50.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textRect.<span class="me1">y</span> <span class="sy0">=</span> <span class="nu17">50.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textRect.<span class="me1">w</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span>w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textRect.<span class="me1">h</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span>h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; contactData.<span class="me1">dirty</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После вызова функции b2World_Draw() добавьте код рисования текстуры с текстом:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="151787836"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="151787836" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// --- Render text every frame ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> textTexture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>textRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Сравните свой код со следующим рабочим кодом, если возникнут ошибки:<br />
<br />
CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="502070489"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="502070489" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-collision-events-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>box2d_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>FREETYPE_INCLUDE_DIRS <span class="st0">&quot;C:/libs/freetype-2.14.1-wasm/include&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>FREETYPE_LIBRARY <span class="st0">&quot;C:/libs/freetype-2.14.1-wasm/lib/libfreetype.a&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_ttf_DIR <span class="st0">&quot;C:/libs/SDL3_ttf-devel-3.2.2-wasm/lib/cmake/SDL3_ttf&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>box2d REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_ttf REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE box2d::box2d SDL3_ttf::SDL3_ttf SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span>
&nbsp;
<span class="kw1">if</span> <span class="br0">&#40;</span>EMSCRIPTEN<span class="br0">&#41;</span>
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span><span class="st0">&quot;app&quot;</span> PRIVATE <span class="st0">&quot;SHELL:--embed-file <span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/fonts/LiberationSans-Regular.ttf@/assets/fonts/LiberationSans-Regular.ttf&quot;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET <span class="st0">&quot;app&quot;</span> APPEND PROPERTY LINK_DEPENDS <span class="st0">&quot;<span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/fonts/LiberationSans-Regular.ttf&quot;</span><span class="br0">&#41;</span>
endif<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="680826517"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="680826517" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_ttf/SDL_ttf.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &quot;contact-listener.h&quot;</span>
&nbsp;
<span class="co2">#define TIME_STEP (1.0f / 60.0f)</span>
<span class="co2">#define MAX_FRAME_TIME 0.25f</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
<span class="kw4">static</span> ContactListenerData contactData<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> TTF_Font <span class="sy0">*</span>font <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_FRect textRect<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">float</span> accumulator <span class="sy0">=</span> <span class="nu17">0.0f</span><span class="sy0">;</span>
<span class="kw4">static</span> Uint64 last_ticks <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">typedef</span> <span class="kw4">struct</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; bool up<span class="sy0">;</span>
&nbsp; &nbsp; bool down<span class="sy0">;</span>
&nbsp; &nbsp; bool left<span class="sy0">;</span>
&nbsp; &nbsp; bool right<span class="sy0">;</span>
<span class="br0">&#125;</span> Keys<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> Keys keys <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
b2BodyId circleBodyId<span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">float</span> playerSpeed <span class="sy0">=</span> <span class="nu0">5</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> bool is_mobile <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_SIZE <span class="sy0">=</span> <span class="nu0">60</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_GAP <span class="sy0">=</span> <span class="nu0">5</span><span class="sy0">;</span>
<span class="kw4">static</span> SDL_FRect btnUp<span class="sy0">,</span> btnDown<span class="sy0">,</span> btnLeft<span class="sy0">,</span> btnRight<span class="sy0">;</span>
&nbsp;
<span class="co2">#ifdef __EMSCRIPTEN__</span>
<span class="co2">#include &lt;emscripten.h&gt;</span>
<span class="co1">// This JavaScript function returns true if the user agent matches mobile devices</span>
EM_JS<span class="br0">&#40;</span>bool<span class="sy0">,</span> is_mobile_browser<span class="sy0">,</span> <span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// We use the RegExp constructor to avoid using / / slashes which confuse Clang</span>
&nbsp; &nbsp; &nbsp; &nbsp; var filter <span class="sy0">=</span> new RegExp<span class="br0">&#40;</span><span class="st0">'iPhone|iPad|iPod|Android'</span><span class="sy0">,</span> <span class="st0">'i'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> filter.<span class="me1">test</span><span class="br0">&#40;</span>navigator.<span class="me1">userAgent</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#endif</span>
&nbsp;
<span class="kw4">void</span> updateButtonLayout<span class="br0">&#40;</span><span class="kw4">int</span> w<span class="sy0">,</span> <span class="kw4">int</span> h<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Positioning squares in a cross pattern at the bottom-left</span>
&nbsp; &nbsp; <span class="kw4">float</span> startX <span class="sy0">=</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> startY <span class="sy0">=</span> h <span class="sy0">-</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">*</span> <span class="nu0">3</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; btnUp <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnLeft <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX<span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnRight <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnDown <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Initialize the TTF library</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>TTF_Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize TTF: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Platform detection</span>
<span class="co2">#ifdef __EMSCRIPTEN__</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> is_mobile_browser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#elif defined(__ANDROID__) || defined(__IPHONEOS__)</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
<span class="co2">#endif</span>
&nbsp;
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Is Mobile: %s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> is_mobile <span class="sy0">?</span> <span class="st0">&quot;Yes&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;No&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Initial Layout</span>
&nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; updateButtonLayout<span class="br0">&#40;</span>w<span class="sy0">,</span> h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp;
&nbsp;
&nbsp; &nbsp; font <span class="sy0">=</span> TTF_OpenFont<span class="br0">&#40;</span><span class="st0">&quot;./assets/fonts/LiberationSans-Regular.ttf&quot;</span><span class="sy0">,</span> <span class="nu0">28</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>font<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;TTF_OpenFont failed: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw3">strcpy</span><span class="br0">&#40;</span>contactData.<span class="me1">text</span><span class="sy0">,</span> <span class="st0">&quot;Коснитесь стены&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; contactData.<span class="me1">dirty</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> friction <span class="sy0">=</span> <span class="nu17">0.1f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Top wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef topWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">20.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId topWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon topWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef topWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId topWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>topWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>topWallShapeId<span class="sy0">,</span> <span class="st0">&quot;top_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Left wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef leftWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">120</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">230</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId leftWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon leftWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef leftWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId leftWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>leftWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>leftWallShapeId<span class="sy0">,</span> <span class="st0">&quot;left_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Right wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef rightWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">280</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">285</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId rightWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon rightWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef rightWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId rightWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>rightWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>rightWallShapeId<span class="sy0">,</span> <span class="st0">&quot;right_wall&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">250</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">fixedRotation</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// User data</span>
&nbsp; &nbsp; b2Shape_SetUserData<span class="br0">&#40;</span>circleShapeId<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Touch handling</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_UP <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_MOTION<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> tx <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> ty <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; bool pressed <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">!=</span> SDL_EVENT_FINGER_UP<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Point pt <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>tx<span class="sy0">,</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>ty <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Check rectangles (Manual check since FRect is float)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">+</span> btnUp.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">+</span> btnUp.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">+</span> btnDown.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">+</span> btnDown.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">+</span> btnLeft.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">+</span> btnLeft.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">+</span> btnRight.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">+</span> btnRight.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> keyboard<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; b2Vec2 velocity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">up</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">down</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">right</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; b2Body_SetLinearVelocity<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> velocity<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; keyboard<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; Uint64 current_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> frameTime <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>current_ticks <span class="sy0">-</span> last_ticks<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">1000.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> current_ticks<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>frameTime <span class="sy0">&gt;</span> MAX_FRAME_TIME<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frameTime <span class="sy0">=</span> MAX_FRAME_TIME<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; accumulator <span class="sy0">+=</span> frameTime<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Read contact events immediately</span>
&nbsp; &nbsp; &nbsp; &nbsp; ProcessContactEvents<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>contactData<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Update text only when dirty ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>contactData.<span class="me1">dirty</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Destroy old texture</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Color textColor <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Render text to surface</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> TTF_RenderText_Blended<span class="br0">&#40;</span>font<span class="sy0">,</span> contactData.<span class="me1">text</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">strlen</span><span class="br0">&#40;</span>contactData.<span class="me1">text</span><span class="br0">&#41;</span><span class="sy0">,</span> textColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>surface<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Create texture from surface</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textTexture <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Get texture size</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTextureSize<span class="br0">&#40;</span>textTexture<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Set text rectangle</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textRect.<span class="me1">x</span> <span class="sy0">=</span> <span class="nu17">30.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textRect.<span class="me1">y</span> <span class="sy0">=</span> <span class="nu17">50.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textRect.<span class="me1">w</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span>w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textRect.<span class="me1">h</span> <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span>h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; contactData.<span class="me1">dirty</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Render text every frame ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> textTexture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>textRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Render Touch UI only if mobile/web</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>is_mobile<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawBlendMode<span class="br0">&#40;</span>renderer<span class="sy0">,</span> SDL_BLENDMODE_BLEND<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Semi-transparent white</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnUp<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnDown<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnLeft<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnRight<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>textTexture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; textTexture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>font<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; TTF_CloseFont<span class="br0">&#40;</span>font<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; font <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>src/contact-listener.h<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="711843458"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="711843458" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
</pre></td><td class="de1"><pre class="de1"><span class="co2">#ifndef CONTACT_LISTENER_H</span>
<span class="co2">#define CONTACT_LISTENER_H</span>
&nbsp;
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;string.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &lt;stdbool.h&gt;</span>
&nbsp;
<span class="kw4">typedef</span> <span class="kw4">struct</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">char</span> text<span class="br0">&#91;</span><span class="nu0">128</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; &nbsp; bool dirty<span class="sy0">;</span>
<span class="br0">&#125;</span> ContactListenerData<span class="sy0">;</span>
&nbsp;
<span class="co1">// Call this every frame after stepping the world</span>
<span class="kw4">void</span> ProcessContactEvents<span class="br0">&#40;</span>b2WorldId worldId<span class="sy0">,</span> ContactListenerData <span class="sy0">*</span>listener<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; b2ContactEvents events <span class="sy0">=</span> b2World_GetContactEvents<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Begin contacts ---</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> events.<span class="me1">beginCount</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2ContactBeginTouchEvent event <span class="sy0">=</span> events.<span class="me1">beginEvents</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameA <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdA</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameB <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdB</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameA<span class="br0">&#41;</span> nameA <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameB<span class="br0">&#41;</span> nameB <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>wallName <span class="sy0">=</span> <span class="kw3">strcmp</span><span class="br0">&#40;</span>nameA<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span> <span class="sy0">?</span> nameB <span class="sy0">:</span> nameA<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">snprintf</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="sy0">,</span> <span class="kw4">sizeof</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;Начало контакта с %s&quot;</span><span class="sy0">,</span> wallName<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; listener<span class="sy0">-&gt;</span>dirty <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- End contacts ---</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> events.<span class="me1">endCount</span><span class="sy0">;</span> i<span class="sy0">++</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2ContactEndTouchEvent event <span class="sy0">=</span> events.<span class="me1">endEvents</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameA <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdA</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>nameB <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span><span class="br0">&#41;</span>b2Shape_GetUserData<span class="br0">&#40;</span>event.<span class="me1">shapeIdB</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameA<span class="br0">&#41;</span> nameA <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>nameB<span class="br0">&#41;</span> nameB <span class="sy0">=</span> <span class="st0">&quot;unknown&quot;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>wallName <span class="sy0">=</span> <span class="kw3">strcmp</span><span class="br0">&#40;</span>nameA<span class="sy0">,</span> <span class="st0">&quot;player&quot;</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="nu0">0</span> <span class="sy0">?</span> nameB <span class="sy0">:</span> nameA<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">snprintf</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="sy0">,</span> <span class="kw4">sizeof</span><span class="br0">&#40;</span>listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">&quot;Конец контакта с %s&quot;</span><span class="sy0">,</span> wallName<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; listener<span class="sy0">-&gt;</span>dirty <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> listener<span class="sy0">-&gt;</span>text<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co2">#endif // CONTACT_LISTENER_H</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Итоговый проект в архиве: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11681&amp;d=1772460580">finish-collision-events-sdl3-c.zip</a></li>
<li>Скомпилируйте проект командой &quot;build-web&quot; и обновите страницу браузера по адресу localhost:8080</li>
<li>Вы увидите результат работы программы: <a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/wasm/finish-collision-events-sdl3-c/" target="_blank" title="https://8observer8.github.io/wasm/finish-collision-events-sdl3-c/">демка в браузере</a><br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11680&amp;a= mp;d=1772460536" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
</ul><br />
<h2>Сборка приложения в Release</h2><br />
<br />
<ul><li>Откройте файл &quot;config-web.bat&quot; и измените &quot;Debug&quot; на &quot;Release&quot;:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="514627645"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="514627645" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команду конфигурирования в консоли:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="899039772"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="899039772" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команду компиляции в консоли:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="74700018"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="74700018" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Содержимое папки &quot;public&quot; вы можете загрузить на какой-нибудь бесплатный хостинг. Например, на GitHub Pages или Firebase</li>
<li>Вес приложения в Release:<ul><li>app.js - 185 KB</li>
<li>app.wasm - 1.78 MB</li>
</ul></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11664&amp;d=1772444075" rel="Lightbox" id="attachment11664" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11664&amp;thumb=1&amp;d=1772444075" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: e7bf756b-507f-4f04-baa6-a3324a400077.png
Просмотров: 1819
Размер:	2.0 Кб
ID:	11664" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11673&amp;d=1772447043" rel="Lightbox" id="attachment11673" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11673&amp;thumb=1&amp;d=1772447043" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 57dbceff-46da-40c7-aa54-c50078e1864e.png
Просмотров: 1807
Размер:	12.5 Кб
ID:	11673" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11674&amp;d=1772447152" rel="Lightbox" id="attachment11674" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11674&amp;thumb=1&amp;d=1772447152" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: f15e5863-b692-4a6b-8cb4-1bd622ae8e68.png
Просмотров: 1795
Размер:	9.1 Кб
ID:	11674" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11677&amp;d=1772448103" rel="Lightbox" id="attachment11677" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11677&amp;thumb=1&amp;d=1772448103" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 7e494e53-39f7-42b8-8668-9823a8b5719a.png
Просмотров: 1793
Размер:	13.5 Кб
ID:	11677" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11680&amp;d=1772460536" rel="Lightbox" id="attachment11680" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11680&amp;thumb=1&amp;d=1772460536" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: finish-collision-events-sdl3-c.gif
Просмотров: 17162
Размер:	26.7 Кб
ID:	11680" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11663&amp;d=1772443369">start-collision-events-sdl3-c.zip</a> (7.7 Кб, 130 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11665&amp;d=1772444384">SDL3-devel-3.4.2-wasm.zip</a> (1.22 Мб, 76 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11666&amp;d=1772444396">box2d-3.1.1-wasm.zip</a> (149.2 Кб, 68 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11667&amp;d=1772444406">freetype-2.14.1-wasm.zip</a> (553.5 Кб, 75 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11668&amp;d=1772444416">SDL3_ttf-devel-3.2.2-wasm.zip</a> (62.0 Кб, 65 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11678&amp;d=1772455990">LiberationSans-Regular.zip</a> (206.0 Кб, 62 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11681&amp;d=1772460580">finish-collision-events-sdl3-c.zip</a> (215.7 Кб, 233 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/4561.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten</title>
			<link>https://www.cyberforum.ru/blogs/416874/10795.html</link>
			<pubDate>Fri, 27 Feb 2026 17:31:00 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Недавно вышла версия...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Недавно вышла версия 3.4.2 библиотеки SDL3. <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2" target="_blank" title="https://github.com/libsdl-org/SDL/releases/tag/release-3.4.2">На странице официальной релиза</a> доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. Однако там отсутствуют сборки для Emscripten (Wasm). Это связано с тем, что для Web-платформы критически важно, чтобы SDL3 была скомпилирована той же версией SDK (emsdk), которая используется в самом проекте. В отличие от Android, MinGW или Visual Studio, здесь это необходимо для гарантии бинарной совместимости и стабильности приложения, поэтому сборка библиотеки делегируется конечному разработчику.<br />
<br />
Примечание от Gemini:<br />
<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">В экосистеме C++ остро стоит проблема ABI (Application Binary Interface): разные версии компиляторов могут по-разному располагать объекты в памяти, что делает их несовместимыми на уровне бинарных файлов. Однако, поскольку SDL3 написана на чистом C, она обладает стабильным ABI. Это позволяет библиотеке, собранной в MinGW 11.2, беспроблемно работать в проекте, который компилируется более свежей версией, например MinGW 12.2, без необходимости пересборки самой SDL. В мире чистого C бинарная совместимость (ABI) между версиями одного и того же семейства компиляторов сохраняется в обе стороны.</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table><h2>Сборка библиотеки SDL3 из исходников с помощью Emscripten 4.0.15 и CMake</h2><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте архив с исходниками: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11633&amp;d=1772280542">SDL3-3.4.2.zip</a></li>
<li>Примечание. Свежий архив с исходниками можно скачать по этой ссылке: <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/releases" target="_blank" title="https://github.com/libsdl-org/SDL/releases">https://github.com/libsdl-org/SDL/releases</a></li>
<li>Откройте консоль (CMD) от имени администратора. Например, на Windows 10 в поиске программ наберите &quot;cmd&quot; (без ковычек) и кликните &quot;Run as administrator&quot;. Из консоли перейдите в папку &quot;SDL3-3.4.2&quot; с помощью команды &quot;cd&quot;, например:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="714158796"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="714158796" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> C:\libs\SDL3-3.4.2</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Скопируйте в консоль следующую команду и по желанию измените адрес папку, куда будет установлена SDL3:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="478381392"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="478381392" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_INSTALL_PREFIX=<span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm&quot;</span> -DCMAKE_BUILD_TYPE=MinSizeRel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После того, как скопировали команду выше в консоль, нажмите Enter. Произойдёт конфигурирование библиотеки перед сборкой</li>
<li>Примечание. Кратко, что означают элементы команды выше:<ul><li>Ключ &quot;-S&quot; означает &quot;Source folder&quot;, то есть &quot;папка-источник&quot;. После &quot;-S&quot; идёт точка, которая означает, что источник - это текущая папка, где должен находиться файл CMakeLists.txt.</li>
<li>Ключ &quot;-B&quot; - это &quot;Build folder&quot;, то есть папка куда будут сохранены нужные файлы для сборки, а в нашем случае после ключа &quot;-В&quot; идёт название папки &quot;dist&quot;, то есть будет создана новая папка с именем &quot;dist&quot;, где будут автоматически созданы файлы для сборки после этапа конфигурирования</li>
<li>Опция -DCMAKE_INSTALL_PREFIX=&quot;C:/libs/SDL3-devel-3.4.2-wasm&quot; задаёт путь, куда будет установлена библиотека. Эту папку самом создавать не нужно - она будет создана автоматически на этапе установки библиотеки</li>
<li>Опция DCMAKE_BUILD_TYPE=MinSizeRel задаёт тип сборки и этот тип называется MinSizeRel (Minimum Size Release), то есть минимальный размер библиотеки собранной в релиз</li>
</ul></li>
<li>Вводим команду для сборки, где в включе -j8 указывает количество потоков процессора:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="29999022"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="29999022" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--build</span> dist <span class="re5">-j8</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команду установки библиотеки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="665757978"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="665757978" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--install</span> dist</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После установки все необходимые файлы для разработки веб-приложений на C, C++, SDL3 и сборки в Wasm будут скопированы в папку &quot;C:/libs/SDL3-devel-3.4.2-wasm&quot;. У меня получилась следующая сборка: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11643&amp;d=1772313769">SDL3-devel-3.4.2-wasm.zip</a></li>
<li>Запустите приложение &quot;Hello World&quot; по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10736.html">Сборка C/C++ проекта из консоли</a></li>
</ul><br />
<h2>Сборка библиотеки Box2D из исходников с помощью Emscripten 4.0.15 и CMake</h2><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте архив с исходниками: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11644&amp;d=1772313786">box2d-3.1.1.zip</a></li>
<li>Откройте консоль (CMD) от имени администратора. Например, на Windows 10 в поиске программ наберите &quot;cmd&quot; (без ковычек) и кликните &quot;Run as administrator&quot;. Из консоли перейдите в папку &quot;box2d-3.1.1&quot; с помощью команды &quot;cd&quot;, например:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="615670382"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="615670382" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> C:\libs\box2d-3.1.1</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Скопируйте в консоль следующую команду и по желанию измените адрес папку, куда будет установлена Box2D:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="821708348"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="821708348" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_INSTALL_PREFIX=<span class="st0">&quot;C:/libs/box2d-3.1.1-wasm&quot;</span> -DCMAKE_BUILD_TYPE=MinSizeRel -DBOX2<span class="re2">D_SAMPLES</span>=OFF -DBOX2<span class="re2">D_UNIT_TESTS</span>=OFF</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После того, как скопировали команду выше в консоль, нажмите Enter. Произойдёт конфигурирование библиотеки перед сборкой</li>
<li>Примечание. Кратко, что означают элементы команды выше:<ul><li>Ключ &quot;-S&quot; означает &quot;Source folder&quot;, то есть &quot;папка-источник&quot;. После &quot;-S&quot; идёт точка, которая означает, что источник - это текущая папка, где должен находиться файл CMakeLists.txt.</li>
<li>Ключ &quot;-B&quot; - это &quot;Build folder&quot;, то есть папка куда будут сохранены нужные файлы для сборки, а в нашем случае после ключа &quot;-В&quot; идёт название папки &quot;dist&quot;, то есть будет создана новая папка с именем &quot;dist&quot;, где будут автоматически созданы файлы для сборки после этапа конфигурирования</li>
<li>Опция -DCMAKE_INSTALL_PREFIX=&quot;C:/libs/box2d-3.1.1-wasm&quot; задаёт путь, куда будет установлена библиотека. Эту папку самом создавать не нужно - она будет создана автоматически на этапе установки библиотеки</li>
<li>Опция -DCMAKE_BUILD_TYPE=MinSizeRel задаёт тип сборки и этот тип называется MinSizeRel (Minimum Size Release), то есть минимальный размер библиотеки собранной в релиз</li>
<li>Опция -DBOX2D_SAMPLES=OFF отключает сборку примеров</li>
<li>Опция -DBOX2D_UNIT_TESTS=OFF отключает юнит-тесты</li>
</ul></li>
<li>Вводим команду для сборки, где в включе -j8 указывает количество потоков процессора:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="577269337"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="577269337" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--build</span> dist <span class="re5">-j8</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команду установки библиотеки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="912203755"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="912203755" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--install</span> dist</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После установки все необходимые файлы для разработки веб-приложений на C, C++, Box2D и сборки в Wasm будут скопированы в папку &quot;C:/libs/box2d-3.1.1-wasm&quot;. У меня получилась следующая сборка: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11646&amp;d=1772314236">box2d-3.1.1-wasm.zip</a></li>
<li>Проверьте сборку на простом примере по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10755.html">Подключение Box2D v3, физика и отрисовка коллайдеров</a></li>
</ul><br />
<h2>Сборка библиотеки FreeType из исходников с помощью Emscripten 4.0.15 и CMake</h2><br />
<br />
Для вывода текста с шрифтом TTF необходима FreeType. FreeType нужна для сборки SDL3_ttf<br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте архив с исходниками: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11651&amp;d=1772385552">freetype-VER-2-14-1.zip</a></li>
<li>Примечание. Свежий архив с исходниками можно скачать <a rel="nofollow noopener noreferrer" href="https://github.com/freetype/freetype/tags" target="_blank" title="https://github.com/freetype/freetype/tags">по этой ссылке</a></li>
<li>Откройте консоль (CMD) от имени администратора. Например, на Windows 10 в поиске программ наберите &quot;cmd&quot; (без ковычек) и кликните &quot;Run as administrator&quot;. Из консоли перейдите в папку &quot;freetype-VER-2-14-1&quot; с помощью команды &quot;cd&quot;, например:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="907185297"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="907185297" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> C:\libs\freetype-VER-<span class="nu0">2</span>-<span class="nu0">14</span>-<span class="nu0">1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Скопируйте в консоль следующую команду и по желанию измените адрес папку, куда будет установлена FreeType:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="325390831"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="325390831" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_INSTALL_PREFIX=<span class="st0">&quot;C:/libs/freetype-2.14.1-wasm&quot;</span> -DCMAKE_BUILD_TYPE=MinSizeRel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После того, как скопировали команду выше в консоль, нажмите Enter. Произойдёт конфигурирование библиотеки перед сборкой</li>
<li>Примечание. Кратко, что означают элементы команды выше:<ul><li>Ключ &quot;-S&quot; означает &quot;Source folder&quot;, то есть &quot;папка-источник&quot;. После &quot;-S&quot; идёт точка, которая означает, что источник - это текущая папка, где должен находиться файл CMakeLists.txt.</li>
<li>Ключ &quot;-B&quot; - это &quot;Build folder&quot;, то есть папка куда будут сохранены нужные файлы для сборки, а в нашем случае после ключа &quot;-В&quot; идёт название папки &quot;dist&quot;, то есть будет создана новая папка с именем &quot;dist&quot;, где будут автоматически созданы файлы для сборки после этапа конфигурирования</li>
<li>Опция -DCMAKE_INSTALL_PREFIX=&quot;C:/libs/freetype-2.14.1&quot; задаёт путь, куда будет установлена библиотека. Эту папку самом создавать не нужно - она будет создана автоматически на этапе установки библиотеки</li>
<li>Опция DCMAKE_BUILD_TYPE=MinSizeRel задаёт тип сборки и этот тип называется MinSizeRel (Minimum Size Release), то есть минимальный размер библиотеки собранной в релиз</li>
</ul></li>
<li>Вводим команду для сборки, где в включе -j8 указывает количество потоков процессора:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="236769376"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="236769376" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--build</span> dist <span class="re5">-j8</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команду установки библиотеки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="727003564"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="727003564" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--install</span> dist</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После установки все необходимые файлы будут скопированы в папку &quot;C:/libs/freetype-2.14.1-wasm&quot;. У меня получилась следующая сборка: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11653&amp;d=1772385552">freetype-2.14.1-wasm.zip</a></li>
<li>FreeType используется для сборки SDL3_ttf по следующей инструкции</li>
</ul><br />
<h2>Сборка библиотеки SDL3_ttf из исходников с помощью Emscripten 4.0.15 и CMake</h2><br />
<br />
Как показано будет ниже, в команде конфигурирования нужно будет указать пути к библиотеке FreeType.<br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте архив с исходниками: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11654&amp;d=1772385791">SDL3_ttf-3.2.2.zip</a></li>
<li>Примечание. Свежий архив с исходниками можно скачать по этой ссылке: <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL_ttf/releases" target="_blank" title="https://github.com/libsdl-org/SDL_ttf/releases">https://github.com/libsdl-org/SDL_ttf/releases</a></li>
<li>Откройте консоль (CMD) от имени администратора. Например, на Windows 10 в поиске программ наберите &quot;cmd&quot; (без ковычек) и кликните &quot;Run as administrator&quot;. Из консоли перейдите в папку &quot;SDL3_ttf-3.2.2&quot; с помощью команды &quot;cd&quot;, например:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="700658158"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="700658158" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> C:\libs\SDL3_ttf-3.2.2</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Внутри папки создайте файл с именем &quot;config-web.bat&quot; и скопируйт следующее содержимое в созданный файл:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="713155927"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="713155927" style="height: 174px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist ^
&nbsp; -DCMAKE_INSTALL_PREFIX=C:<span class="sy0">/</span>libs<span class="sy0">/</span>SDL3_ttf-devel-3.2.2-wasm ^
&nbsp; -DSDL3<span class="re2">_DIR</span>=<span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span> ^
&nbsp; -DFREETYPE_INCLUDE_DIR_freetype2=C:<span class="sy0">/</span>libs<span class="sy0">/</span>freetype-2.14.1-wasm<span class="sy0">/</span>include ^
&nbsp; -DFREETYPE_INCLUDE_DIR_ft2<span class="re2">build</span>=C:<span class="sy0">/</span>libs<span class="sy0">/</span>freetype-2.14.1-wasm<span class="sy0">/</span>include<span class="sy0">/</span>freetype2 ^
&nbsp; -DFREETYPE_LIBRARY_DEBUG=C:<span class="sy0">/</span>libs<span class="sy0">/</span>freetype-2.14.1-wasm<span class="sy0">/</span>lib<span class="sy0">/</span>libfreetype.a ^
&nbsp; -DFREETYPE_LIBRARY_RELEASE=C:<span class="sy0">/</span>libs<span class="sy0">/</span>freetype-2.14.1-wasm<span class="sy0">/</span>lib<span class="sy0">/</span>libfreetype.a ^
&nbsp; -DCMAKE_BUILD_TYPE=MinSizeRel ^
&nbsp; -DSDLTTF_SAMPLES=OFF</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В консоли введите команду &quot;config-web&quot; (без кавычек - это имя батника) и нажмите Enter. Произойдёт конфигурирование библиотеки перед сборкой.</li>
<li>Примечание. Кратко, что означают элементы команды выше:<ul><li>Ключ &quot;-S&quot; означает &quot;Source folder&quot;, то есть &quot;папка-источник&quot;. После &quot;-S&quot; идёт точка, которая означает, что источник - это текущая папка, где должен находиться файл CMakeLists.txt.</li>
<li>Ключ &quot;-B&quot; - это &quot;Build folder&quot;, то есть папка куда будут сохранены нужные файлы для сборки, а в нашем случае после ключа &quot;-В&quot; идёт название папки &quot;dist&quot;, то есть будет создана новая папка с именем &quot;dist&quot;, где будут автоматически созданы файлы для сборки после этапа конфигурирования</li>
<li>Опция -DCMAKE_INSTALL_PREFIX=&quot;C:/libs/&quot;SDL3_ttf-3.2.2-wasm&quot; задаёт путь, куда будет установлена библиотека. Эту папку самом создавать не нужно - она будет создана автоматически на этапе установки библиотеки</li>
<li>Опция -DSDL3_DIR=&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3 - путь к SDL3, которую вы собрали по инструкции ранее</li>
<li>Следующие опции задают пути к файлам, собранной ранее библиотеки FreeType:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="209956051"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="209956051" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">&nbsp; -DFREETYPE_INCLUDE_DIR_freetype2=C:<span class="sy0">/</span>libs<span class="sy0">/</span>freetype-2.14.1-wasm<span class="sy0">/</span>include ^
&nbsp; -DFREETYPE_INCLUDE_DIR_ft2<span class="re2">build</span>=C:<span class="sy0">/</span>libs<span class="sy0">/</span>freetype-2.14.1-wasm<span class="sy0">/</span>include<span class="sy0">/</span>freetype2 ^
&nbsp; -DFREETYPE_LIBRARY_DEBUG=C:<span class="sy0">/</span>libs<span class="sy0">/</span>freetype-2.14.1-wasm<span class="sy0">/</span>lib<span class="sy0">/</span>libfreetype.a ^
&nbsp; -DFREETYPE_LIBRARY_RELEASE=C:<span class="sy0">/</span>libs<span class="sy0">/</span>freetype-2.14.1-wasm<span class="sy0">/</span>lib<span class="sy0">/</span>libfreetype.a ^</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Опция DCMAKE_BUILD_TYPE=MinSizeRel задаёт тип сборки и этот тип называется MinSizeRel (Minimum Size Release), то есть минимальный размер библиотеки собранной в релиз</li>
</ul></li>
<li>Вводим команду для сборки, где в включе -j8 указывает количество потоков процессора:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="313490812"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="313490812" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--build</span> dist <span class="re5">-j8</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команду установки библиотеки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="900506006"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="900506006" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--install</span> dist</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После установки все необходимые файлы для разработки веб-приложений на C, C++, SDL3 и сборки в Wasm будут скопированы в папку &quot;C:/libs/SDL3-devel-3.4.2-wasm&quot;. У меня получилась следующая сборка: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11656&amp;d=1772385791">SDL3_ttf-devel-3.2.2-wasm.zip</a></li>
<li>Запустите приложение &quot;Hello World&quot; по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10737.html">Вывод текста со шрифтом TTF с помощью SDL3_ttf</a></li>
</ul><br />
<h2>Сборка библиотеки SDL3_mixer из исходников с помощью Emscripten 4.0.15 и CMake</h2><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте архив с исходниками: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11657&amp;d=1772392000">SDL3_mixer-3.1.2.zip</a></li>
<li>Примечание. Свежий архив с исходниками можно скачать по этой ссылке: <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL_mixer/releases" target="_blank" title="https://github.com/libsdl-org/SDL_mixer/releases">https://github.com/libsdl-org/SDL_mixer/releases</a></li>
<li>Откройте консоль (CMD) от имени администратора. Например, на Windows 10 в поиске программ наберите &quot;cmd&quot; (без ковычек) и кликните &quot;Run as administrator&quot;. Из консоли перейдите в папку &quot;SDL3_mixer-3.1.2&quot; с помощью команды &quot;cd&quot;, например:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="499400265"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="499400265" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> C:\libs\SDL3_mixer-3.1.2</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Скопируйте в консоль следующую команду и по желанию измените адрес папку, куда будет установлена SDL3:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="354966935"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="354966935" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_INSTALL_PREFIX=<span class="st0">&quot;C:/libs/SDL3_mixer-devel-3.1.2-wasm&quot;</span> -DSDL3<span class="re2">_DIR</span>=<span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span> -DCMAKE_BUILD_TYPE=MinSizeRel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После того, как скопировали команду выше в консоль, нажмите Enter. Произойдёт конфигурирование библиотеки перед сборкой</li>
<li>Примечание. Кратко, что означают элементы команды выше:<ul><li>Ключ &quot;-S&quot; означает &quot;Source folder&quot;, то есть &quot;папка-источник&quot;. После &quot;-S&quot; идёт точка, которая означает, что источник - это текущая папка, где должен находиться файл CMakeLists.txt.</li>
<li>Ключ &quot;-B&quot; - это &quot;Build folder&quot;, то есть папка куда будут сохранены нужные файлы для сборки, а в нашем случае после ключа &quot;-В&quot; идёт название папки &quot;dist&quot;, то есть будет создана новая папка с именем &quot;dist&quot;, где будут автоматически созданы файлы для сборки после этапа конфигурирования</li>
<li>Опция -DCMAKE_INSTALL_PREFIX=&quot;C:/libs/SDL3_mixer-devel-3.1.2-wasm&quot; задаёт путь, куда будет установлена библиотека. Эту папку самом создавать не нужно - она будет создана автоматически на этапе установки библиотеки</li>
<li>Опция -DSDL3_DIR=&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3 - путь к SDL3, которую вы собрали по инструкции ранее</li>
<li>Опция DCMAKE_BUILD_TYPE=MinSizeRel задаёт тип сборки и этот тип называется MinSizeRel (Minimum Size Release), то есть минимальный размер библиотеки собранной в релиз</li>
</ul></li>
<li>Вводим команду для сборки, где в включе -j8 указывает количество потоков процессора:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="623448024"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="623448024" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--build</span> dist <span class="re5">-j8</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команду установки библиотеки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="621455308"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="621455308" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--install</span> dist</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После установки все необходимые файлы для разработки веб-приложений на C, C++, SDL3_mixer и сборки в Wasm будут скопированы в папку &quot;C:/libs/SDL3_mixer-devel-3.1.2-wasm&quot;. У меня получилась следующая сборка: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11658&amp;d=1772392473">SDL3_mixer-devel-3.1.2-wasm.zip</a></li>
<li>Запустите приложение &quot;Hello World&quot; по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10750.html">Работа со звуком через SDL3_mixer</a></li>
</ul><br />
<h2>Сборка библиотеки SDL3_image из исходников с помощью Emscripten 4.0.15 и CMake</h2><br />
<br />
Библиотека SDL3_image содержит расширенные инструменты для работы с изображениями. Если вам достаточно базовых инструментов, то можно использовать встроенные средства библиотеки SDL3: <a href="https://www.cyberforum.ru/blogs/416874/10754.html">Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)</a><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте архив с исходниками: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11660&amp;d=1772393584">SDL3_image-3.4.0.zip</a></li>
<li>Примечание. Свежий архив с исходниками можно скачать по этой ссылке: <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL_image/releases" target="_blank" title="https://github.com/libsdl-org/SDL_image/releases">https://github.com/libsdl-org/SDL_image/releases</a></li>
<li>Откройте консоль (CMD) от имени администратора. Например, на Windows 10 в поиске программ наберите &quot;cmd&quot; (без ковычек) и кликните &quot;Run as administrator&quot;. Из консоли перейдите в папку &quot;SDL3_image-3.4.0&quot; с помощью команды &quot;cd&quot;, например:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="599761261"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="599761261" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> C:\libs\SDL3_image-3.4.0</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Скопируйте в консоль следующую команду и по желанию измените адрес папку, куда будет установлена SDL3:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="143616312"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="143616312" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_INSTALL_PREFIX=<span class="st0">&quot;C:/libs/SDL3_image-devel-3.4.0-wasm&quot;</span> -DSDL3<span class="re2">_DIR</span>=<span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span> -DCMAKE_BUILD_TYPE=MinSizeRel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После того, как скопировали команду выше в консоль, нажмите Enter. Произойдёт конфигурирование библиотеки перед сборкой</li>
<li>Примечание. Кратко, что означают элементы команды выше:<ul><li>Ключ &quot;-S&quot; означает &quot;Source folder&quot;, то есть &quot;папка-источник&quot;. После &quot;-S&quot; идёт точка, которая означает, что источник - это текущая папка, где должен находиться файл CMakeLists.txt.</li>
<li>Ключ &quot;-B&quot; - это &quot;Build folder&quot;, то есть папка куда будут сохранены нужные файлы для сборки, а в нашем случае после ключа &quot;-В&quot; идёт название папки &quot;dist&quot;, то есть будет создана новая папка с именем &quot;dist&quot;, где будут автоматически созданы файлы для сборки после этапа конфигурирования</li>
<li>Опция -DCMAKE_INSTALL_PREFIX=&quot;C:/libs/SDL3_image-devel-3.4.0-wasm&quot; задаёт путь, куда будет установлена библиотека. Эту папку самом создавать не нужно - она будет создана автоматически на этапе установки библиотеки</li>
<li>Опция -DSDL3_DIR=&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3 - путь к SDL3, которую вы собрали по инструкции ранее</li>
<li>Опция DCMAKE_BUILD_TYPE=MinSizeRel задаёт тип сборки и этот тип называется MinSizeRel (Minimum Size Release), то есть минимальный размер библиотеки собранной в релиз</li>
</ul></li>
<li>Вводим команду для сборки, где в включе -j8 указывает количество потоков процессора:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="300185718"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="300185718" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--build</span> dist <span class="re5">-j8</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команду установки библиотеки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="300330497"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="300330497" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--install</span> dist</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После установки все необходимые файлы для разработки веб-приложений на C, C++, SDL3_image и сборки в Wasm будут скопированы в папку &quot;C:/libs/SDL3_image-devel-3.4.0-wasm&quot;. У меня получилась следующая сборка: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11661&amp;d=1772393837">SDL3_image-devel-3.4.0-wasm.zip</a></li>
<li>Запустите приложение &quot;Hello World&quot; по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10752.html">Загрузка PNG с прозрачным фоном с помощью SDL3_image</a></li>
</ul><br />
Примечание. Логи конфигурирования, сборки и установки библиотек выше: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11662&amp;d=1772393850">logs.zip</a></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11633&amp;d=1772280542">SDL3-3.4.2.zip</a> (16.22 Мб, 99 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11643&amp;d=1772313769">SDL3-devel-3.4.2-wasm.zip</a> (1.22 Мб, 92 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11644&amp;d=1772313786">box2d-3.1.1.zip</a> (861.5 Кб, 66 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11646&amp;d=1772314236">box2d-3.1.1-wasm.zip</a> (149.2 Кб, 68 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11651&amp;d=1772385552">freetype-VER-2-14-1.zip</a> (2.84 Мб, 55 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11653&amp;d=1772385552">freetype-2.14.1-wasm.zip</a> (553.5 Кб, 63 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11654&amp;d=1772385791">SDL3_ttf-3.2.2.zip</a> (2.90 Мб, 52 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11656&amp;d=1772385791">SDL3_ttf-devel-3.2.2-wasm.zip</a> (62.0 Кб, 64 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11657&amp;d=1772392000">SDL3_mixer-3.1.2.zip</a> (4.89 Мб, 66 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11658&amp;d=1772392473">SDL3_mixer-devel-3.1.2-wasm.zip</a> (165.7 Кб, 60 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11660&amp;d=1772393584">SDL3_image-3.4.0.zip</a> (12.21 Мб, 53 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11661&amp;d=1772393837">SDL3_image-devel-3.4.0-wasm.zip</a> (121.5 Кб, 60 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11662&amp;d=1772393850">logs.zip</a> (15.3 Кб, 48 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10795.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами</title>
			<link>https://www.cyberforum.ru/blogs/416874/10757.html</link>
			<pubDate>Fri, 20 Feb 2026 13:51:38 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Box2D позволяет легко...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее препятствие на этом скриншоте:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11616&amp;a= mp;d=1771345247" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
<a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/wasm/finish-player-movement-sdl3-c/" target="_blank" title="https://8observer8.github.io/wasm/finish-player-movement-sdl3-c/">Финальная демка</a> этой инструкции. Итоговый код: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11626&amp;d=1771548734">finish-player-movement-sdl3-c.zip</a><br />
<br />
В физическом мире Box2D перемещать главного героя (ГГ) можно с помощью: установки линейной скорости, импульса или приложения силы. В данной инструкции используем установку линейной скорости с помощью функции b2Body_SetLinearVelocity(). Коллайдером для ГГ будет круг, которому запретим вращение. На Desktop управлять движением будем с помощью клавиш WASD (и клавиш-стрелок). Для браузеров на мобильных устройствах добавим четыре квадрата-кнопки для движения ГГ при касании этих квадратов-кнопок.<br />
<br />
<h2>Подключение библиотек Box2D и SDL3 к стартовому примеру</h2><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте стартовый пример: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11618&amp;d=1771505781">start-player-movement-sdl3-c.zip</a></li>
<li>Примечание. Этот стартовый пример был получен в результате выполнения пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10755.html">Подключение Box2D v3, физика и отрисовка коллайдеров</a></li>
<li>Так выглядит код стартового примера:<br />
<br />
src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="872278945"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="872278945" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="co2">#define TIME_STEP (1.0f / 60.0f)</span>
<span class="co2">#define MAX_FRAME_TIME 0.25f</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">float</span> accumulator <span class="sy0">=</span> <span class="nu17">0.0f</span><span class="sy0">;</span>
<span class="kw4">static</span> Uint64 last_ticks <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu17">9.8f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Floor</span>
&nbsp; &nbsp; b2BodyDef floorBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId floorBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon floorShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef floorShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId floorShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Square</span>
&nbsp; &nbsp; b2BodyDef squareBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">201</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">100</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId squareBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon squareShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef squareShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId squareShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- DESKTOP ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">which</span> <span class="sy0">!=</span> SDL_TOUCH_MOUSEID<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>btnName <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">button</span> <span class="sy0">==</span> SDL_BUTTON_LEFT<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="st0">&quot;Левая&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Правая&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s кнопка (Мышь): x=%.0f, y=%.0f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> btnName<span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">x</span><span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- MOBILE / WASM (Touch) ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelX <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelY <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Проверяем количество пальцев на устройстве (touchId берем из события)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> numFingers <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTouchFingers<span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>tfinger.<span class="me1">touchID</span><span class="sy0">,</span> <span class="sy0">&amp;</span>numFingers<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numFingers <span class="sy0">&lt;=</span> <span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Левая кнопка (Тап 1 пальцем): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Правая кнопка (Тап несколькими): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Uint64 current_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> frameTime <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>current_ticks <span class="sy0">-</span> last_ticks<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">1000.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> current_ticks<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>frameTime <span class="sy0">&gt;</span> MAX_FRAME_TIME<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frameTime <span class="sy0">=</span> MAX_FRAME_TIME<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; accumulator <span class="sy0">+=</span> frameTime<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>src/debug-drawer.h<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="263670197"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="263670197" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
</pre></td><td class="de1"><pre class="de1"><span class="co2">#ifndef DEBUG_DRAWER_H</span>
<span class="co2">#define DEBUG_DRAWER_H</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
&nbsp;
<span class="kw2">extern</span> SDL_Renderer <span class="sy0">*</span>renderer<span class="sy0">;</span>
<span class="kw2">extern</span> <span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format<span class="sy0">;</span>
<span class="kw2">extern</span> <span class="kw4">float</span> ppm<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">void</span> drawSolidPolygon<span class="br0">&#40;</span>b2Transform transform<span class="sy0">,</span>
&nbsp; &nbsp; <span class="kw4">const</span> b2Vec2 <span class="sy0">*</span>vertices<span class="sy0">,</span> <span class="kw4">int</span> vertexCount<span class="sy0">,</span>
&nbsp; &nbsp; <span class="kw4">float</span> radius<span class="sy0">,</span> b2HexColor color<span class="sy0">,</span> <span class="kw4">void</span> <span class="sy0">*</span>context<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>radius<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>context<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Extract RGB</span>
&nbsp; &nbsp; Uint8 r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetRGB<span class="br0">&#40;</span>color<span class="sy0">,</span> format<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>r<span class="sy0">,</span> <span class="sy0">&amp;</span>g<span class="sy0">,</span> <span class="sy0">&amp;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Draw a collider rectangle with lines</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> vertexCount<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> next_index <span class="sy0">=</span> <span class="br0">&#40;</span>i <span class="sy0">+</span> <span class="nu0">1</span> <span class="sy0">==</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="nu0">0</span> <span class="sy0">:</span> i <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p0 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>next_index<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x0 <span class="sy0">=</span> p0.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y0 <span class="sy0">=</span> p0.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x1 <span class="sy0">=</span> p1.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y1 <span class="sy0">=</span> p1.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> x0<span class="sy0">,</span> y0<span class="sy0">,</span> x1<span class="sy0">,</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Tip: Draw orientation line ---</span>
&nbsp; &nbsp; <span class="co1">// Compute polygon center</span>
&nbsp; &nbsp; <span class="kw4">float</span> cx <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> cy <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> vertexCount<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; cx <span class="sy0">+=</span> p.<span class="me1">x</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; cy <span class="sy0">+=</span> p.<span class="me1">y</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; cx <span class="sy0">=</span> <span class="br0">&#40;</span>cx <span class="sy0">/</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; cy <span class="sy0">=</span> <span class="br0">&#40;</span>cy <span class="sy0">/</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Midpoint of second edge (vertex[1] → vertex[2])</span>
&nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 p2 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> mx <span class="sy0">=</span> <span class="br0">&#40;</span>p1.<span class="me1">x</span> <span class="sy0">+</span> p2.<span class="me1">x</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu17">0.5f</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> my <span class="sy0">=</span> <span class="br0">&#40;</span>p1.<span class="me1">y</span> <span class="sy0">+</span> p2.<span class="me1">y</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu17">0.5f</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw center → edge midpoint line (acts like &quot;direction tip&quot;)</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> cx<span class="sy0">,</span> cy<span class="sy0">,</span> mx<span class="sy0">,</span> my<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">void</span> drawSolidCircle<span class="br0">&#40;</span>b2Transform transform<span class="sy0">,</span> <span class="kw4">float</span> radius<span class="sy0">,</span>
&nbsp; &nbsp; b2HexColor color<span class="sy0">,</span> <span class="kw4">void</span> <span class="sy0">*</span>context<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>radius<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>context<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> angle <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">int</span> numberOfSegments <span class="sy0">=</span> <span class="nu0">20</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> angleStep <span class="sy0">=</span> <span class="nu0">360</span>.<span class="me1">f</span> <span class="sy0">/</span> numberOfSegments<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Extract RGB</span>
&nbsp; &nbsp; Uint8 r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetRGB<span class="br0">&#40;</span>color<span class="sy0">,</span> format<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>r<span class="sy0">,</span> <span class="sy0">&amp;</span>g<span class="sy0">,</span> <span class="sy0">&amp;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Draw a collider rectangle with lines</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">cos</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">sin</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 p0 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> x<span class="sy0">,</span> y <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> x0 <span class="sy0">=</span> p0.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y0 <span class="sy0">=</span> p0.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; angle <span class="sy0">+=</span> angleStep<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> numberOfSegments<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">cos</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">sin</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> x<span class="sy0">,</span> y <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x1 <span class="sy0">=</span> p1.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y1 <span class="sy0">=</span> p1.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> x0<span class="sy0">,</span> y0<span class="sy0">,</span> x1<span class="sy0">,</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; x0 <span class="sy0">=</span> x1<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; y0 <span class="sy0">=</span> y1<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; angle <span class="sy0">+=</span> angleStep<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>angle <span class="sy0">&gt;=</span> <span class="nu0">360</span>.<span class="me1">f</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; angle <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Tip: Draw orientation line ---</span>
&nbsp; &nbsp; <span class="co1">// Circle center</span>
&nbsp; &nbsp; b2Vec2 c <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> cx <span class="sy0">=</span> c.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> cy <span class="sy0">=</span> c.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Direction = transform applied to (radius, 0)</span>
&nbsp; &nbsp; b2Vec2 orient <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> radius<span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> ox <span class="sy0">=</span> orient.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> oy <span class="sy0">=</span> orient.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw center → orientation marker</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> cx<span class="sy0">,</span> cy<span class="sy0">,</span> ox<span class="sy0">,</span> oy<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co2">#endif // DEBUG_DRAWER_H</span></pre></td></tr></table></div></td></tr></tbody></table></div>CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="439272094"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="439272094" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-player-movement-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>box2d_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>box2d REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE box2d::box2d SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Напомню, что результатом этого стартового примера являются падающие квадрат и круг на статичный коллайдер:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11619&amp;a= mp;d=1771507019" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br /></li>
<li>Откройте папку со стартовым примером в какой-нибудь редакторе кода, например, в Notepad++ или в Sublime Text 4 (ST4): <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a></li>
<li>Скачайте библиотеку SDL3 для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11535&amp;d=1770761188">SDL3-devel-3.4.0-wasm.zip</a></li>
<li>Скачайте библиотеку Box2D v3 для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11536&amp;d=1770761326">box2d-3.1.1-wasm.zip</a></li>
<li>Извлеките содержимое архив выше в какую-нибудь новую общую папку, например, с именем &quot;libs&quot; на какой-нибудь диск, например, на C. Таким образом, создайте на диске C папку &quot;lib&quot;, скопируйте в неё архивы и извлеките их в текущую папку:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11624&amp;d=1771508195" border="0" alt="Название: e8933ad5-0754-45b3-8d63-176ee6e3b7d5.png
Просмотров: 2713

Размер: 4.2 Кб" style="margin: 5px" /></li>
<li>Откройте папку &quot;SDL3-devel-3.4.0-wasm&quot;, перейдите в папку &quot;lib/cmake/SDL3&quot; и скопируйте абсолютный путь:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11622&amp;a= mp;d=1771508078" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>В файле CMakeLists.txt стартового примера замените в переменной SDL3_DIR путь на свой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="960412474"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="960412474" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку &quot;box2d-3.1.1-wasm&quot;, перейдите в папку &quot;lib/cmake/box2d&quot; и скопируйте абсолютный путь:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11623&amp;a= mp;d=1771508099" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Замените в переменной box2d_DIR путь на свой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="632128233"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="632128233" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Тестовая сборка и тестовый запуск стартового примера в браузере на локальном хостинге</h2><br />
<br />
<ul><li>Откройте консоль (CMD) в корне стартового примера. Для этого можете просто в адресной строке папки (там где путь) написать &quot;cmd&quot; (без кавычек) и нажать Enter</li>
<li>В CMD введите команду для конфигурирования:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="781833065"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="781833065" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;config-web&quot; - это имя bash-файла (батника), который находится в корне папки стартового примера</li>
<li>В CMD введите команду сборки проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="486022143"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="486022143" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Собранные файлы (app.js и app.wasm) будут скопированы в папку &quot;public/js&quot; (папка &quot;public&quot; лежит в корне проекта)</li>
<li>В корне проекта запустите локальный сервер командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="958114839"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="958114839" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Будут выведены адреса:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="894840350"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="894840350" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>192.168.1.65:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 2. Адрес 192.168.1.65:8080 можно использовать для запуска приложения на мобильном устройстве, если у вас есть Wi-Fi - просто вводите этот адрес в браузере мобильного устройства и приложение запустится. Если интересен запуск на мобильном устройстве, то пройдите пошаговую инструкцию: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a></li>
<li>Откройте новую вкладку в браузере. Если у вас Chrome или Edge, то нажмите Ctrl+Shift+J, чтобы открыть консоль браузера для контроля вывода информации. Если у вас FireFox, то нажмите Ctrl+Shift+K</li>
<li>Перейдите по адресу:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="873070602"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="873070602" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Обновлять страницу после повторной сборки проекта лучше с очисткой кэша браузера. Для этого (обязательно с открытой консолью браузера) в браузере Chrome нужно найти в левом верхнем углу браузера кнопку обновления страницы (круговая стрелка), нажать по ней правой кнопкой мыши и выбрать &quot;Empty Cache and Hard Reload&quot;</li>
<li>Мы убедились, что тестовый пример запускается нормально. Если вы что-то меняете в коде (в файлах main.c или CMakeLists.txt), то достаточно ввести команду для сборки build-web (в CMD нажать стрелку-вверх и Enter) и обновить вкладку в браузере. Удобнее всего, чтобы локальный хостинг был запущен в одном окне CMD, а сборку делать в другом окне CMD</li>
</ul><br />
<h2>Добавляем обработку нажатий клавиш</h2><br />
<br />
Управлять героем будет с помощью клавиш WASD и клавиш-стрелок. Цель, на данном этапе, выводить слова в консоль: &quot;вверх&quot;, &quot;вниз&quot;, &quot;влево&quot;, &quot;вправо&quot; при нажатии соответствующих клавиш.<br />
<br />
<ul><li>В начале файла src/main.c наберите вручную код, для создания глобальной переменной:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="444322717"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="444322717" style="height: 174px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
</pre></td><td class="de1"><pre class="de1"><span class="kw4">typedef</span> <span class="kw4">struct</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; bool up<span class="sy0">;</span>
&nbsp; &nbsp; bool down<span class="sy0">;</span>
&nbsp; &nbsp; bool left<span class="sy0">;</span>
&nbsp; &nbsp; bool right<span class="sy0">;</span>
<span class="br0">&#125;</span> Keys<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> Keys keys <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span> <span class="br0">&#125;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Наберите код следующий код для обработки нажатий клавиш WASD и клавиш-стрелок. Здесь мы меняет значения переменных (членов структуры keys) на true и false в зависимости от того, нажата ли клавиша или не нажата:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="455546699"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="455546699" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Код обработки клика мышки можно удалить, но обработку касания экрана не удаляйте, потому что он нужен для управления героем на мобильных браузерах, чтобы отобразить кнопки управления (виртуальный джойстик), которые мы создадим позже</li>
<li>Перед функций SDL_AppIterate() наберите код функции с именем keyboard() для обработки нажатий клавиш:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="571836816"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="571836816" style="height: 334px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> keyboard<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">up</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;вверх<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">down</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;вниз<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;влево<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">right</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;вправо<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В начале функции SDL_AppIterate() добавьте вызов функции keyboard():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="181566709"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="181566709" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; keyboard<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Соберите приложение с помощью команды &quot;build-web&quot; и обновите вкладку браузера. Нажимайте клавиши WASD и клавиши-стрелки и вы увидите вывод в консоль:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11625&amp;d=1771517717" border="0" alt="Название: 38d21c65-17d7-4cb6-a237-2956a2494ea7.png
Просмотров: 2686

Размер: 3.3 Кб" style="margin: 5px" /></li>
</ul><br />
<h2>Добавляем управление героем</h2><br />
<br />
Нам нужно будет удалить гравитацию, потому что у нас вид сверху на игровое поле. Цель: управлять героем путём установления скорости. Если кнопки управления не нажаты, то линейная скорость героя должна быть обнулена. Мы будем управлять круговым коллайдером - это коллайдер главного героя.<br />
<br />
<ul><li>Найдите строку кода задания гравитации и обнулите её:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="686857076"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="686857076" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Найдите строку, где мы создаём идентификатор кругового коллайдера:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="258120865"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="258120865" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">b2BodyId circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Идентификатор коллайдера ГГ должен быть глобальным, чтобы он был доступен в функции keyboard() для задания линейной скорости ГГ. Скопируйте &quot;b2BodyId circleBodyId&quot; и удалите объявление перед circleBodyId в указанной выше строке кода.</li>
<li>Скопированное объявление идентификатора (&quot;b2BodyId circleBodyId&quot;) скопируйте выше функции SDL_AppInit(), то есть сделайте объявление circleBodyId глобальным</li>
<li>Добавьте глобальную константу playerSpeed с значениме 5:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="544643578"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="544643578" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">float</span> playerSpeed <span class="sy0">=</span> <span class="nu0">5</span>.<span class="me1">f</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции keyboard() добавьте задание скорости ГГ:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="390919294"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="390919294" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> keyboard<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; b2Vec2 velocity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">up</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">down</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">right</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; b2Body_SetLinearVelocity<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> velocity<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В первой консоли соберите приложение командой &quot;build-web&quot; и обновите вкладку браузера. Вы можете теперь управлять ГГ клавишами WASD и клавишам-стрелками</li>
<li>Обратите внимание, что при управлении клавишами коллайдер ГГ поворачивается. Нужно убрать это ненужное вращение. Добавьте код в функции SDL_AppInit() запрещающий вращение:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="719175821"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="719175821" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">circleBodyDef.<span class="me1">fixedRotation</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После пересборки приложения вы видите, что коллайдер не поворачивает при движении и ГГ не проходит через препятствие</li>
</ul><br />
<h2>Определяем в коде запущено ли приложение в Desktop-браузере или в браузере мобильного устройства</h2><br />
<br />
Цель: при запуске приложения вывести в консоль информацию на каком устройстве было запущено веб-приложение - из браузера ПК или из браузера мобильного устройства.<br />
<br />
<ul><li>Создайте глобальную переменную is_mobile:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="961221801"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="961221801" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> bool is_mobile <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создайте функцию is_mobile_browser():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="942715840"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="942715840" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1"><span class="co2">#ifdef __EMSCRIPTEN__</span>
<span class="co2">#include &lt;emscripten.h&gt;</span>
<span class="co1">// This JavaScript function returns true if the user agent matches mobile devices</span>
EM_JS<span class="br0">&#40;</span>bool<span class="sy0">,</span> is_mobile_browser<span class="sy0">,</span> <span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// We use the RegExp constructor to avoid using / / slashes which confuse Clang</span>
&nbsp; &nbsp; var filter <span class="sy0">=</span> new RegExp<span class="br0">&#40;</span><span class="st0">'iPhone|iPad|iPod|Android'</span><span class="sy0">,</span> <span class="st0">'i'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> filter.<span class="me1">test</span><span class="br0">&#40;</span>navigator.<span class="me1">userAgent</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#endif</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppInit() после функции создания окна и рисовальщика SDL_CreateWindowAndRenderer() добавляем код проверки на какой платформе был запуск веб-приложения (на Desktop или Mobile):<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="987684602"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="987684602" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Platform detection</span>
<span class="co2">#ifdef __EMSCRIPTEN__</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> is_mobile_browser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#elif defined(__ANDROID__) || defined(__IPHONEOS__)</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
<span class="co2">#endif</span>
&nbsp;
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Is Mobile: %s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> is_mobile <span class="sy0">?</span> <span class="st0">&quot;Yes&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;No&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Для того, чтобы увидеть вывод в консоль с мобильного браузера через USB-кабель или Wi-Fi выполните инструкцию: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств</a></li>
<li>При запуске в браузере на Desktop вы увидите в консоле браузера:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="739098153"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="739098153" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">Is Mobile: No</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>При запуске в браузере мобильного устройства вы увидите в консоле браузера:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="499709675"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="499709675" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">Is Mobile: Yes</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Запрет реакции смартфона на долгое удержание пальца на холсте</h2><br />
<br />
Если удерживать палец на холсте в мобильном браузере, то смартфон реагирует выделением текста, вызовом контекстного меню и т.д. Запрещаем это. Добавьте в public/index.html в тег &lt;head&gt; следующий код:<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="667812169"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="667812169" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">style</span><span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; canvas <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; touch<span class="sy0">-</span><span class="kw3">action</span><span class="sy0">:</span> <span class="kw-6">none</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">-</span>webkit<span class="sy0">-</span>touch<span class="sy0">-</span>callout<span class="sy0">:</span> <span class="kw-6">none</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">-</span>webkit<span class="sy0">-</span>user<span class="sy0">-</span>select<span class="sy0">:</span> <span class="kw-6">none</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; user<span class="sy0">-</span>select<span class="sy0">:</span> <span class="kw-6">none</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="sy0">&lt;/</span><span class="kw2">style</span><span class="sy0">&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div><br />
<h2>Добавляем джойстик для управления главным героем на мобильном браузере</h2><br />
<br />
Добавим четыре квадрата, чтобы управлять ГГ на мобильном браузере.<br />
<br />
<ul><li>Создайте глобальные константы для размера кнопок (BTN_SIZE), расстояния между кнопками (BTN_GAP) и структуры SDL_FRect для хранения координат и размеров кнопок:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="407945889"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="407945889" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> bool is_mobile <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_SIZE <span class="sy0">=</span> <span class="nu0">60</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_GAP <span class="sy0">=</span> <span class="nu0">5</span><span class="sy0">;</span>
<span class="kw4">static</span> SDL_FRect btnUp<span class="sy0">,</span> btnDown<span class="sy0">,</span> btnLeft<span class="sy0">,</span> btnRight<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте функцию updateButtonLayout() для расчёта позиций и размеров кнопок перед функций SDL_AppInit():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="167530275"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="167530275" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> updateButtonLayout<span class="br0">&#40;</span><span class="kw4">int</span> w<span class="sy0">,</span> <span class="kw4">int</span> h<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Positioning squares in a cross pattern at the bottom-left</span>
&nbsp; &nbsp; <span class="kw4">float</span> startX <span class="sy0">=</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> startY <span class="sy0">=</span> h <span class="sy0">-</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">*</span> <span class="nu0">3</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; btnUp <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnLeft <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX<span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnRight <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnDown <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте вызов функции updateButtonLayout() в функции SDL_AppInit() после строки включения вертикальной синхронизации:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="560532251"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="560532251" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Initial Layout</span>
&nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; updateButtonLayout<span class="br0">&#40;</span>w<span class="sy0">,</span> h<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В конце функции SDL_AppEvent() добавьте код обработки касаний клавиш джойстика:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="409777974"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="409777974" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// ...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Touch handling</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_UP <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_MOTION<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> tx <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> ty <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; bool pressed <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">!=</span> SDL_EVENT_FINGER_UP<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Point pt <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>tx<span class="sy0">,</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>ty <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Check rectangles (Manual check since FRect is float)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">+</span> btnUp.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">+</span> btnUp.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">+</span> btnDown.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">+</span> btnDown.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">+</span> btnLeft.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">+</span> btnLeft.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">+</span> btnRight.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">+</span> btnRight.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функцию SDL_AppIterate() добавьте код рисования кнопок джойстика после вызова функции b2World_Draw():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="49901938"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="49901938" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Render Touch UI only if mobile/web</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>is_mobile<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawBlendMode<span class="br0">&#40;</span>renderer<span class="sy0">,</span> SDL_BLENDMODE_BLEND<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Semi-transparent white</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnUp<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnDown<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnLeft<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnRight<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После сборки &quot;build-web&quot; и обновления вкладки в Desktop-браузере вы не увидите джойстика, так как он появляется только в браузере мобильных устройств и вы можете управлять героем с клавиатуры клавишами WASD и клавишами-стрелками</li>
<li>На мобильном браузере вы появляется джойстик из четырёх кнопок с помощью которых вы можете управлять ГГ</li>
<li>Текущий код:<br />
<br />
src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="222368393"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="222368393" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="co2">#define TIME_STEP (1.0f / 60.0f)</span>
<span class="co2">#define MAX_FRAME_TIME 0.25f</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">float</span> accumulator <span class="sy0">=</span> <span class="nu17">0.0f</span><span class="sy0">;</span>
<span class="kw4">static</span> Uint64 last_ticks <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">typedef</span> <span class="kw4">struct</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; bool up<span class="sy0">;</span>
&nbsp; &nbsp; bool down<span class="sy0">;</span>
&nbsp; &nbsp; bool left<span class="sy0">;</span>
&nbsp; &nbsp; bool right<span class="sy0">;</span>
<span class="br0">&#125;</span> Keys<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> Keys keys <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
b2BodyId circleBodyId<span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">float</span> playerSpeed <span class="sy0">=</span> <span class="nu0">5</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> bool is_mobile <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_SIZE <span class="sy0">=</span> <span class="nu0">60</span><span class="sy0">;</span>
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">int</span> BTN_GAP <span class="sy0">=</span> <span class="nu0">5</span><span class="sy0">;</span>
<span class="kw4">static</span> SDL_FRect btnUp<span class="sy0">,</span> btnDown<span class="sy0">,</span> btnLeft<span class="sy0">,</span> btnRight<span class="sy0">;</span>
&nbsp;
<span class="co2">#ifdef __EMSCRIPTEN__</span>
<span class="co2">#include &lt;emscripten.h&gt;</span>
<span class="co1">// This JavaScript function returns true if the user agent matches mobile devices</span>
EM_JS<span class="br0">&#40;</span>bool<span class="sy0">,</span> is_mobile_browser<span class="sy0">,</span> <span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// We use the RegExp constructor to avoid using / / slashes which confuse Clang</span>
&nbsp; &nbsp; &nbsp; &nbsp; var filter <span class="sy0">=</span> new RegExp<span class="br0">&#40;</span><span class="st0">'iPhone|iPad|iPod|Android'</span><span class="sy0">,</span> <span class="st0">'i'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> filter.<span class="me1">test</span><span class="br0">&#40;</span>navigator.<span class="me1">userAgent</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#endif</span>
&nbsp;
<span class="kw4">void</span> updateButtonLayout<span class="br0">&#40;</span><span class="kw4">int</span> w<span class="sy0">,</span> <span class="kw4">int</span> h<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Positioning squares in a cross pattern at the bottom-left</span>
&nbsp; &nbsp; <span class="kw4">float</span> startX <span class="sy0">=</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> startY <span class="sy0">=</span> h <span class="sy0">-</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">*</span> <span class="nu0">3</span><span class="br0">&#41;</span> <span class="sy0">-</span> <span class="nu17">20.0f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; btnUp <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnLeft <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX<span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnRight <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> startY <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; btnDown <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_FRect<span class="br0">&#41;</span> <span class="br0">&#123;</span> startX <span class="sy0">+</span> BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="sy0">,</span> startY <span class="sy0">+</span> <span class="br0">&#40;</span>BTN_SIZE <span class="sy0">+</span> BTN_GAP<span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu0">2</span><span class="sy0">,</span> BTN_SIZE<span class="sy0">,</span> BTN_SIZE <span class="br0">&#125;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Platform detection</span>
<span class="co2">#ifdef __EMSCRIPTEN__</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> is_mobile_browser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="co2">#elif defined(__ANDROID__) || defined(__IPHONEOS__)</span>
&nbsp; &nbsp; is_mobile <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
<span class="co2">#endif</span>
&nbsp;
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Is Mobile: %s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> is_mobile <span class="sy0">?</span> <span class="st0">&quot;Yes&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;No&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Initial Layout</span>
&nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; updateButtonLayout<span class="br0">&#40;</span>w<span class="sy0">,</span> h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Floor</span>
&nbsp; &nbsp; b2BodyDef floorBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId floorBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon floorShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef floorShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId floorShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Square</span>
&nbsp; &nbsp; b2BodyDef squareBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">201</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">100</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId squareBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon squareShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef squareShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId squareShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">fixedRotation</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_KEY_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Scancode sc <span class="sy0">=</span> event<span class="sy0">-&gt;</span>key.<span class="me1">scancode</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_W <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_UP<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_S <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_A <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_LEFT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>sc <span class="sy0">==</span> SDL_SCANCODE_D <span class="sy0">||</span> sc <span class="sy0">==</span> SDL_SCANCODE_RIGHT<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Touch handling</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_UP <span class="sy0">||</span> event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_MOTION<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> tx <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> ty <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; bool pressed <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">!=</span> SDL_EVENT_FINGER_UP<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Point pt <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>tx<span class="sy0">,</span> <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>ty <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Check rectangles (Manual check since FRect is float)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnUp.<span class="me1">x</span> <span class="sy0">+</span> btnUp.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnUp.<span class="me1">y</span> <span class="sy0">+</span> btnUp.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">up</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnDown.<span class="me1">x</span> <span class="sy0">+</span> btnDown.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnDown.<span class="me1">y</span> <span class="sy0">+</span> btnDown.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">down</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnLeft.<span class="me1">x</span> <span class="sy0">+</span> btnLeft.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnLeft.<span class="me1">y</span> <span class="sy0">+</span> btnLeft.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">left</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>tx <span class="sy0">&gt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">&amp;&amp;</span> tx <span class="sy0">&lt;=</span> btnRight.<span class="me1">x</span> <span class="sy0">+</span> btnRight.<span class="me1">w</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&gt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">&amp;&amp;</span> ty <span class="sy0">&lt;=</span> btnRight.<span class="me1">y</span> <span class="sy0">+</span> btnRight.<span class="me1">h</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keys.<span class="me1">right</span> <span class="sy0">=</span> pressed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> keyboard<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; b2Vec2 velocity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">up</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">down</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">y</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">left</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> <span class="sy0">-</span>playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>keys.<span class="me1">right</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; velocity.<span class="me1">x</span> <span class="sy0">=</span> playerSpeed<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; b2Body_SetLinearVelocity<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> velocity<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; keyboard<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; Uint64 current_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> frameTime <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>current_ticks <span class="sy0">-</span> last_ticks<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">1000.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> current_ticks<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>frameTime <span class="sy0">&gt;</span> MAX_FRAME_TIME<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frameTime <span class="sy0">=</span> MAX_FRAME_TIME<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; accumulator <span class="sy0">+=</span> frameTime<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Render Touch UI only if mobile/web</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>is_mobile<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawBlendMode<span class="br0">&#40;</span>renderer<span class="sy0">,</span> SDL_BLENDMODE_BLEND<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Semi-transparent white</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnUp<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnDown<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnLeft<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderFillRect<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="sy0">&amp;</span>btnRight<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>public/index.html<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="345491010"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="345491010" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1.0&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">style</span><span class="sy0">&gt;</span>
&nbsp; &nbsp; &nbsp; &nbsp; canvas <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; touch<span class="sy0">-</span><span class="kw3">action</span><span class="sy0">:</span> <span class="kw-6">none</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">-</span>webkit<span class="sy0">-</span>touch<span class="sy0">-</span>callout<span class="sy0">:</span> <span class="kw-6">none</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">-</span>webkit<span class="sy0">-</span>user<span class="sy0">-</span>select<span class="sy0">:</span> <span class="kw-6">none</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; user<span class="sy0">-</span>select<span class="sy0">:</span> <span class="kw-6">none</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="sy0">&lt;/</span><span class="kw2">style</span><span class="sy0">&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">canvas</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;canvas&quot;</span><span class="sy0">&gt;&lt;/</span><span class="kw2">canvas</span><span class="sy0">&gt;</span></span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> async <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./js/app.js&quot;</span><span class="sy0">&gt;</span><span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Добавляет стены, трение для стен и поворачиваем верхнюю стену</h2><br />
<br />
<ul><li>Удалите код создания пола и квадрата:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="185654122"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="185654122" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Floor</span>
&nbsp; &nbsp; b2BodyDef floorBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId floorBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon floorShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef floorShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId floorShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Square</span>
&nbsp; &nbsp; b2BodyDef squareBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">201</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">100</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId squareBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon squareShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef squareShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId squareShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShape<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Вместо этого удалённого кода выше добавьте код создания трёх стен. Здесь фигурные скобки используются для группировки для удобства чтения кода:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="809960173"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="809960173" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> friction <span class="sy0">=</span> <span class="nu17">0.1f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Top wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef topWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">20.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId topWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon topWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef topWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; topWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId topWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>topWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>topWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Left wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef leftWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">120</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">230</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId leftWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon leftWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef leftWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; leftWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId leftWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>leftWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>leftWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Right wall</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyDef rightWallBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">280</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">285</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallBodyDef.<span class="me1">rotation</span> <span class="sy0">=</span> b2MakeRot<span class="br0">&#40;</span><span class="nu17">90.0f</span> <span class="sy0">*</span> <span class="br0">&#40;</span><span class="nu17">3.14f</span> <span class="sy0">/</span> <span class="nu17">180.0f</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2BodyId rightWallBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2Polygon rightWallShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeDef rightWallShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; rightWallShapeDef.<span class="me1">enableContactEvents</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; b2ShapeId rightWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>rightWallBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>rightWallShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Зададим новые координаты главному герою:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="283033461"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="283033461" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">250</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Установим трение для ГГ:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="166458878"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="166458878" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">circleShapeDef.<span class="me1">material</span>.<span class="me1">friction</span> <span class="sy0">=</span> friction<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Проведите сборку &quot;build-web&quot; и обновите страницы на Desktop и мобильном браузере, чтобы увидеть результат. Главный герой теперь движется вдоль стен с заданным трением</li>
</ul><br />
<h2>Сборка в релиз</h2><br />
<br />
<ul><li>Для сборки в релиз нужно открыть файл &quot;config-web.bat&quot; в редакторе кода и исправить Debug на Release:<br />
<br />
config-web.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="458087306"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="458087306" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команды конфигурирования и сборки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="464133855"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="464133855" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">config-web
build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Вес файлов после сборки в Debug:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="373300140"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="373300140" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">376</span> KB
app.wasm - <span class="nu0">2.05</span> MB</pre></td></tr></table></div></td></tr></tbody></table></div>Вес файлов после сборки в Release:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="782106637"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="782106637" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">183</span> KB
app.wasm - <span class="nu0">1.03</span> MB</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Развёртывание на бесплатном хостинге Vercel</h2><br />
<br />
<ul><li>Скачайте установщик Node.js и установите: <a rel="nofollow noopener noreferrer" href="https://nodejs.org/en/download" target="_blank" title="https://nodejs.org/en/download">https://nodejs.org/en/download</a></li>
<li>Установите Vercel следующей командой из консоли глобально:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="392051491"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="392051491" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i vercel <span class="re5">-g</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Зарегистрируйтесь на Vercel: <a rel="nofollow noopener noreferrer" href="https://vercel.com/" target="_blank" title="https://vercel.com/">https://vercel.com/</a></li>
<li>Примечание. В стартовом прмер, который скачали в начале, уже есть файл vercel.json для решения проблемы с загрузкой wasm-файла</li>
<li>В консоле в корне проекта выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="427769989"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="427769989" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="kw2">login</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="598975897"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="598975897" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Будут заданы вопросы в консоли - просто нажимайте всегда Enter</li>
<li>В консоль будет выведен адрес вашего приложения: <a rel="nofollow noopener noreferrer" href="https://start-player-movement-sdl3-c.vercel.app" target="_blank" title="https://start-player-movement-sdl3-c.vercel.app">https://start-player-movement-sdl3-c.vercel.app</a></li>
<li>Примечание. Иногда при первом запуске Vercel может долго загружать приложение - бывает около минуты, поэтому лучше использовать для хостинга бесплатный GitHub Pages: <a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/wasm/finish-player-movement-sdl3-c/" target="_blank" title="https://8observer8.github.io/wasm/finish-player-movement-sdl3-c/">ссылка</a></li>
<li>Примечание. Когда вы что-то измените в проекте и захотите загрузить изменённое приложение на сервер, то введите команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="983345266"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="983345266" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="re5">--prod</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11616&amp;d=1771345247" rel="Lightbox" id="attachment11616" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11616&amp;thumb=1&amp;d=1771345247" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: b07733d3-add5-4ae0-b7bd-937222fe6af9.png
Просмотров: 19522
Размер:	2.0 Кб
ID:	11616" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11619&amp;d=1771507019" rel="Lightbox" id="attachment11619" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11619&amp;thumb=1&amp;d=1771507019" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 61f99572-0a7d-4270-a599-74c45b884feb.png
Просмотров: 2765
Размер:	971 байт
ID:	11619" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11622&amp;d=1771508078" rel="Lightbox" id="attachment11622" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11622&amp;thumb=1&amp;d=1771508078" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 47e98e58-f94e-4904-b77d-1452c9490b3b.png
Просмотров: 2792
Размер:	14.2 Кб
ID:	11622" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11623&amp;d=1771508099" rel="Lightbox" id="attachment11623" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11623&amp;thumb=1&amp;d=1771508099" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: ea00cd6e-b9d4-4ea3-a4d8-48e16284c9c5.png
Просмотров: 2773
Размер:	9.1 Кб
ID:	11623" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11618&amp;d=1771505781">start-player-movement-sdl3-c.zip</a> (6.6 Кб, 99 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11620&amp;d=1771507712">SDL3-devel-3.4.0-wasm.zip</a> (1.22 Мб, 64 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11621&amp;d=1771507712">box2d-3.1.1-wasm.zip</a> (555.4 Кб, 78 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11626&amp;d=1771548734">finish-player-movement-sdl3-c.zip</a> (7.7 Кб, 221 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10757.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров</title>
			<link>https://www.cyberforum.ru/blogs/416874/10755.html</link>
			<pubDate>Wed, 11 Feb 2026 21:48:44 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Финальная демка...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
<a rel="nofollow noopener noreferrer" href="https://start-box2d-v3-wasm-sdl3-c.vercel.app" target="_blank" title="https://start-box2d-v3-wasm-sdl3-c.vercel.app">Финальная демка</a> запускается в браузерах на Desktop (Windows, Linux, macOS) и в браузерах на мобильных устройствах (Android и iOS). Исходники результата: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11546&amp;d=1770846177">finish-box2d-v3-wasm-sdl3-c.zip</a><br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11682&amp;d= =1772487167" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. Например, когда главный герой собирает монетки, жизни, касается шипов, врагов и т.д. Пошагово напишем код, в котором по клику левой кнопки мыши (либо одно касание на мобильном) будут создаваться падающие квадраты, а по клику правой кнопки мыши (либо касание двумя пальцами на мобильном) будут создаваться круги. Квадраты и круги падают на пол.<br />
<br />
<h2>Подключение библиотек Box2D и SDL3 к стартовому примеру</h2><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте стартовый пример: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11533&amp;d=1770759384">start-box2d-v3-wasm-sdl3-c.zip</a><br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11534&amp;d=1770759399" border="0" alt="Название: 2774834c-f54d-4d5a-83ff-6a0078869654.png
Просмотров: 2172

Размер: 4.3 Кб" style="margin: 5px" /><br /></li>
<li>Далее представлен код стартового примера. В этом коде в функции SDL_AppEvent() добавлены два обработчика. Первый обработчик для клика левой и правой кнопки мыши. Они выводят в консоль текст &quot;Левая&quot; или &quot;Правая&quot; кнопка нажата и координаты клика. Второй обработчик для Android. Имитация левой кнопки - касание одним пальцем, а имитация правой кнопки - это касание двумя и более пальцами:<br />
<br />
src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="794602649"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="794602649" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- DESKTOP ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">which</span> <span class="sy0">!=</span> SDL_TOUCH_MOUSEID<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>btnName <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">button</span> <span class="sy0">==</span> SDL_BUTTON_LEFT<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="st0">&quot;Левая&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Правая&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s кнопка (Мышь): x=%.0f, y=%.0f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> btnName<span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">x</span><span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- MOBILE / WASM (Touch) ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelX <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelY <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Проверяем количество пальцев на устройстве (touchId берем из события)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> numFingers <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTouchFingers<span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>tfinger.<span class="me1">touchID</span><span class="sy0">,</span> <span class="sy0">&amp;</span>numFingers<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numFingers <span class="sy0">&lt;=</span> <span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Левая кнопка (Тап 1 пальцем): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Правая кнопка (Тап несколькими): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw here...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку со стартовым примером в какой-нибудь редакторе кода, например, в Notepad++ или в Sublime Text 4 (ST4): <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a></li>
<li>Скачайте библиотеку SDL3 для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11535&amp;d=1770761188">SDL3-devel-3.4.0-wasm.zip</a></li>
<li>Скачайте библиотеку Box2D v3 для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11536&amp;d=1770761326">box2d-3.1.1-wasm.zip</a></li>
<li>Извлеките содержимое архив выше в какую-нибудь новую общую папку, например, с именем &quot;libs&quot; на какой-нибудь диск, например, на C. Таким образом, создайте на диске C папку &quot;lib&quot;, скопируйте в неё архивы и извлеките их в текущую папку:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11540&amp;d=1770818669" border="0" alt="Название: e9edf644-df34-490d-9f00-43e569332704.png
Просмотров: 2202

Размер: 4.2 Кб" style="margin: 5px" /></li>
<li>Откройте папку &quot;SDL3-devel-3.4.0-wasm&quot;, перейдите в папку &quot;lib/cmake/SDL3&quot; и скопируйте абсолютный путь:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11541&amp;a= mp;d=1770818703" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>В файле CMakeLists.txt стартового примера создайте переменную SDL3_DIR и установите ей значение скопированного пути, заменив обратные слеши на прямые:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="424840555"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="424840555" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку &quot;box2d-3.1.1-wasm&quot;, перейдите в папку &quot;lib/cmake/box2d&quot; и скопируйте абсолютный путь:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11542&amp;d=1770818744" border="0" alt="Название: cb4f28a3-9838-42bd-aeb7-f1725945a6bf.png
Просмотров: 2191

Размер: 8.8 Кб" style="margin: 5px" /></li>
<li>В файле CMakeLists.txt стартового примера создайте переменную box2d_DIR и установите ей значение скопированного пути, заменив обратные слеши на прямые:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="836371722"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="836371722" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>box2d_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Здесь же в файле CMakeLists.txt добавьте команду для проверки наличия библиотеки box2d в системе, а если пути к этим библиотекам мы задали неверно, то будет выведена ошибка при конфигурировании проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="104092922"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="104092922" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>box2d REQUIRED<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Привязываем библиотеку Box2D к нашему приложению путём добавления box2d::box2d:<br />
<br />
Было:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="526998697"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="526998697" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="140896264"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="140896264" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE box2d::box2d SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>К этому моменту CMakeLists.txt выглядит так:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="543071896"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="543071896" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-box2d-v3-wasm-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотек</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>box2d_DIR <span class="st0">&quot;C:/libs/box2d-3.1.1-wasm/lib/cmake/box2d&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>box2d REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE box2d::box2d SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Далее создадим тестовую сборку, в которой создадим пустой физический мир с гравитацией и выведем значение гравитации в консоль</li>
</ul><br />
<h2>Тестовая сборка и тестовый запуск стартового примера в браузере на локальном хостинге</h2><br />
<br />
<ul><li>Прежде чем запустить скомпилировать код и запустить приложение, создадим пустой физический мир с гравитацией и выведем значение гравитации в консоль</li>
<li>Откройте файл src/main.c в редакторе кода</li>
<li>Подключите заголовочный файл библиотеки Box2D:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="872192625"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="872192625" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте объявление идентификатора для физического мира Box2D после объявлений переменных-указателей окна и рисовальщика:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="697407381"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="697407381" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте в конец функции SDL_AppInit() создание физического мира и вывод значения гравитации в консоль:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="830267323"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="830267323" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu17">9.8f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте в начало функции SDL_AppQuit() удаление физического мира:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="806473171"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="806473171" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span> 
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте консоль (CMD) в корне стартового примера. Для этого можете просто в адресной строке папки (там где путь) написать &quot;cmd&quot; (без кавычек) и нажать Enter</li>
<li>В CMD введите команду для конфигурирования:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="610712418"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="610712418" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;config-web&quot; - это имя bash-файла (батника), который находится в корне папки стартового примера</li>
<li>В CMD введите команду сборки проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="99924400"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="99924400" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Собранные файлы (app.js и app.wasm) будут скопированы в папку &quot;public/js&quot; (папка &quot;public&quot; лежит в корне проекта)</li>
<li>В корне проекта запустите локальный сервер командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="648532313"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="648532313" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Будут выведены адреса:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="192427463"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="192427463" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>192.168.1.65:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 2. Адрес 192.168.1.65:8080 можно использовать для запуска приложения на мобильном устройстве, если у вас есть Wi-Fi - просто вводите этот адрес в браузере мобильного устройства и приложение запустится. Если интересен запуск на мобильном устройстве, то пройдите пошаговую инструкцию: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a></li>
<li>Откройте новую вкладку в браузере. Если у вас Chrome или Edge, то нажмите Ctrl+Shift+J, чтобы открыть консоль браузера для контроля вывода информации. Если у вас FireFox, то нажмите Ctrl+Shift+K</li>
<li>Перейдите по адресу:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="751552055"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="751552055" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Обновлять страницу после повторной сборки проекта лучше с очисткой кэша браузера. Для этого (обязательно с открытой консолью браузера) в браузере Chrome нужно найти в левом верхнем углу браузера кнопку обновления страницы (круговая стрелка), нажать по ней правой кнопкой мыши и выбрать &quot;Empty Cache and Hard Reload&quot;</li>
<li>В браузере должен выводиться квадрат тёмного-серого цвета - это холст для рисования. В консоль браузера будет выведено сообщение:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="777892990"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="777892990" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">Текущее значение гравитации: x = <span class="nu0">0.00</span>, y = <span class="nu0">9.80</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Код main.c к этому моменту:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="499658326"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="499658326" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu17">9.8f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- DESKTOP ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">which</span> <span class="sy0">!=</span> SDL_TOUCH_MOUSEID<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>btnName <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">button</span> <span class="sy0">==</span> SDL_BUTTON_LEFT<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="st0">&quot;Левая&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Правая&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s кнопка (Мышь): x=%.0f, y=%.0f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> btnName<span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">x</span><span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- MOBILE / WASM (Touch) ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelX <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelY <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Проверяем количество пальцев на устройстве (touchId берем из события)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> numFingers <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTouchFingers<span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>tfinger.<span class="me1">touchID</span><span class="sy0">,</span> <span class="sy0">&amp;</span>numFingers<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numFingers <span class="sy0">&lt;=</span> <span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Левая кнопка (Тап 1 пальцем): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Правая кнопка (Тап несколькими): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw here...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span> 
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Добавляем пол, падающие квадрат и круг и рисуем коллайдеры</h2><br />
<br />
Определение Gemini 3, что такое коллайдер простыми словами:<br />
<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">Коллайдер в Box2D - &quot;физическая оболочка&quot; объекта, которая определяет его форму для столкновений. В цифровом мире картинка (спрайт) — это просто набор пикселей. Без коллайдера два танка на экране просто проедут друг сквозь друга, как привидения. Чтобы они столкнулись, движку нужно знать их границы.</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table>Коллайдеры можно рисовать линиями. В Box2D есть вспомогательные функции, которые помогают рисовать коллайдеры. Далее рассмотрим рисование коллайдера прямоугольной формы и в форме круга. В Box2D есть структура, которую мы создадим позже, под названием b2DefaultDebugDraw. У этой структуры есть два указателя на функции: DrawSolidPolygonFcn (для прямоугольников) и DrawSolidCircleFcn (для круговых коллайдеров). К этим указателям привязываем свои функции, которые будут вызываться, когда нужно будет нарисовать коллайдеры.<br />
<ul><li>Добавьте в main.c после объявления идентификатора физического мира объявление структуры b2DebugDraw:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="86637567"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="86637567" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В конце функции SDL_AppInit() добавьте код создания структуры типа b2DebugDraw. Две функции: drawSolidPolygon() и drawSolidCircle() мы создадим чуть позже:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="761871004"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="761871004" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После создания структуры debugDrawer напишите код создания пола:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="544238586"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="544238586" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Floor</span>
&nbsp; &nbsp; b2BodyDef floorBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId floorBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon floorShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef floorShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId topWallShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShape<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создайте файл &quot;debug-drawer.h&quot; в папке &quot;src&quot;. Скопируйте код определения двух функций: drawSolidPolygon() и drawSolidCircle():<br />
<br />
debug-drawer.h<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="49936504"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="49936504" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
</pre></td><td class="de1"><pre class="de1"><span class="co2">#ifndef DEBUG_DRAWER_H</span>
<span class="co2">#define DEBUG_DRAWER_H</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
&nbsp;
<span class="kw2">extern</span> SDL_Renderer <span class="sy0">*</span>renderer<span class="sy0">;</span>
<span class="kw2">extern</span> <span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format<span class="sy0">;</span>
<span class="kw2">extern</span> <span class="kw4">float</span> ppm<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">void</span> drawSolidPolygon<span class="br0">&#40;</span>b2Transform transform<span class="sy0">,</span>
&nbsp; &nbsp; <span class="kw4">const</span> b2Vec2 <span class="sy0">*</span>vertices<span class="sy0">,</span> <span class="kw4">int</span> vertexCount<span class="sy0">,</span>
&nbsp; &nbsp; <span class="kw4">float</span> radius<span class="sy0">,</span> b2HexColor color<span class="sy0">,</span> <span class="kw4">void</span> <span class="sy0">*</span>context<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>radius<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>context<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Extract RGB</span>
&nbsp; &nbsp; Uint8 r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetRGB<span class="br0">&#40;</span>color<span class="sy0">,</span> format<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>r<span class="sy0">,</span> <span class="sy0">&amp;</span>g<span class="sy0">,</span> <span class="sy0">&amp;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Draw a collider rectangle with lines</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> vertexCount<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> next_index <span class="sy0">=</span> <span class="br0">&#40;</span>i <span class="sy0">+</span> <span class="nu0">1</span> <span class="sy0">==</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="nu0">0</span> <span class="sy0">:</span> i <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p0 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>next_index<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x0 <span class="sy0">=</span> p0.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y0 <span class="sy0">=</span> p0.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x1 <span class="sy0">=</span> p1.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y1 <span class="sy0">=</span> p1.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> x0<span class="sy0">,</span> y0<span class="sy0">,</span> x1<span class="sy0">,</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Tip: Draw orientation line ---</span>
&nbsp; &nbsp; <span class="co1">// Compute polygon center</span>
&nbsp; &nbsp; <span class="kw4">float</span> cx <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> cy <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> vertexCount<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; cx <span class="sy0">+=</span> p.<span class="me1">x</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; cy <span class="sy0">+=</span> p.<span class="me1">y</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; cx <span class="sy0">=</span> <span class="br0">&#40;</span>cx <span class="sy0">/</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; cy <span class="sy0">=</span> <span class="br0">&#40;</span>cy <span class="sy0">/</span> vertexCount<span class="br0">&#41;</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Midpoint of second edge (vertex[1] → vertex[2])</span>
&nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 p2 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> vertices<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> mx <span class="sy0">=</span> <span class="br0">&#40;</span>p1.<span class="me1">x</span> <span class="sy0">+</span> p2.<span class="me1">x</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu17">0.5f</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> my <span class="sy0">=</span> <span class="br0">&#40;</span>p1.<span class="me1">y</span> <span class="sy0">+</span> p2.<span class="me1">y</span><span class="br0">&#41;</span> <span class="sy0">*</span> <span class="nu17">0.5f</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw center → edge midpoint line (acts like &quot;direction tip&quot;)</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> cx<span class="sy0">,</span> cy<span class="sy0">,</span> mx<span class="sy0">,</span> my<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">void</span> drawSolidCircle<span class="br0">&#40;</span>b2Transform transform<span class="sy0">,</span> <span class="kw4">float</span> radius<span class="sy0">,</span>
&nbsp; &nbsp; b2HexColor color<span class="sy0">,</span> <span class="kw4">void</span> <span class="sy0">*</span>context<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>radius<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span>context<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> angle <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">int</span> numberOfSegments <span class="sy0">=</span> <span class="nu0">20</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> angleStep <span class="sy0">=</span> <span class="nu0">360</span>.<span class="me1">f</span> <span class="sy0">/</span> numberOfSegments<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Extract RGB</span>
&nbsp; &nbsp; Uint8 r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetRGB<span class="br0">&#40;</span>color<span class="sy0">,</span> format<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>r<span class="sy0">,</span> <span class="sy0">&amp;</span>g<span class="sy0">,</span> <span class="sy0">&amp;</span>b<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Draw a collider rectangle with lines</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> r<span class="sy0">,</span> g<span class="sy0">,</span> b<span class="sy0">,</span> SDL_ALPHA_OPAQUE<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">cos</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">sin</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Vec2 p0 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> x<span class="sy0">,</span> y <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> x0 <span class="sy0">=</span> p0.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y0 <span class="sy0">=</span> p0.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; angle <span class="sy0">+=</span> angleStep<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0">&lt;</span> numberOfSegments<span class="sy0">;</span> <span class="sy0">++</span>i<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">cos</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> radius <span class="sy0">*</span> <span class="kw3">sin</span><span class="br0">&#40;</span>angle <span class="sy0">*</span> SDL_PI_F <span class="sy0">/</span> <span class="nu0">180</span>.<span class="me1">f</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2Vec2 p1 <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> x<span class="sy0">,</span> y <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> x1 <span class="sy0">=</span> p1.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> y1 <span class="sy0">=</span> p1.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> x0<span class="sy0">,</span> y0<span class="sy0">,</span> x1<span class="sy0">,</span> y1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; x0 <span class="sy0">=</span> x1<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; y0 <span class="sy0">=</span> y1<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; angle <span class="sy0">+=</span> angleStep<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>angle <span class="sy0">&gt;=</span> <span class="nu0">360</span>.<span class="me1">f</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; angle <span class="sy0">=</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Tip: Draw orientation line ---</span>
&nbsp; &nbsp; <span class="co1">// Circle center</span>
&nbsp; &nbsp; b2Vec2 c <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> cx <span class="sy0">=</span> c.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> cy <span class="sy0">=</span> c.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Direction = transform applied to (radius, 0)</span>
&nbsp; &nbsp; b2Vec2 orient <span class="sy0">=</span> b2TransformPoint<span class="br0">&#40;</span>transform<span class="sy0">,</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> radius<span class="sy0">,</span> <span class="nu0">0</span>.<span class="me1">f</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> ox <span class="sy0">=</span> orient.<span class="me1">x</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> oy <span class="sy0">=</span> orient.<span class="me1">y</span> <span class="sy0">*</span> ppm<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw center → orientation marker</span>
&nbsp; &nbsp; SDL_RenderLine<span class="br0">&#40;</span>renderer<span class="sy0">,</span> cx<span class="sy0">,</span> cy<span class="sy0">,</span> ox<span class="sy0">,</span> oy<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co2">#endif // DEBUG_DRAWER_H</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Этому файлу требуются глобальные переменные renderer и ppm (pixels per meter). Поэтому нужно в main.c убрать &quot;static&quot; в объявлении &quot;renderer&quot;. Добавьте константу &quot;format&quot; и &quot;ppm&quot;:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="33202079"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="33202079" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;ppm&quot; (pixel per meter) преобразует координатную сетку из мира пикселей в мир метрики Box2D. В Box2D измерения в метрах<br /></li>
<li>Глобальная константа &quot;format&quot; нужна для работы SDL3. Мы объявили её в файле main.c. Необходимо добавить её создание в конце функции SDL_AppInit():<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="57930521"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="57930521" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Рисование коллайдеров происходит при вызове функции b2World_Draw(), которой передаётся идентификатор мира и debugDrawer:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="426421930"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="426421930" style="height: 222px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Соберите проект командой:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="804467829"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="804467829" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Перейдите по адресу в браузере:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="102275690"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="102275690" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Программа рисует пол:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11543&amp;a= mp;d=1770842690" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br /></li>
<li>Полный код функции main.c на текущий момент, чтобы свериться, на случай если возникли ошибки:<br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="405153589"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="405153589" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu17">9.8f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Floor</span>
&nbsp; &nbsp; b2BodyDef floorBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId floorBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon floorShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef floorShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId floorShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- DESKTOP ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">which</span> <span class="sy0">!=</span> SDL_TOUCH_MOUSEID<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>btnName <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">button</span> <span class="sy0">==</span> SDL_BUTTON_LEFT<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="st0">&quot;Левая&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Правая&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s кнопка (Мышь): x=%.0f, y=%.0f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> btnName<span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">x</span><span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- MOBILE / WASM (Touch) ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelX <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelY <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Проверяем количество пальцев на устройстве (touchId берем из события)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> numFingers <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTouchFingers<span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>tfinger.<span class="me1">touchID</span><span class="sy0">,</span> <span class="sy0">&amp;</span>numFingers<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numFingers <span class="sy0">&lt;=</span> <span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Левая кнопка (Тап 1 пальцем): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Правая кнопка (Тап несколькими): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span> 
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавим два объекта, которые пока не падают на пол: куб и круг, а зависают в воздухе над полом. В функции SDL_AppInit() добавьте, после создания пола, код для квадрата и круга:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="968611759"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="968611759" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Square</span>
&nbsp; &nbsp; b2BodyDef squareBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">100</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId squareBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon squareShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef squareShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId squareShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Скомпилируйте код:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="268130447"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="268130447" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Запустите программу:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="386721838"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="386721838" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Мы видим пол, над которым зависли квадрат и круг:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11544&amp;a= mp;d=1770844660" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Полный код main.c:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="986045974"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="986045974" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu17">9.8f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Floor</span>
&nbsp; &nbsp; b2BodyDef floorBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId floorBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon floorShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef floorShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId floorShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Square</span>
&nbsp; &nbsp; b2BodyDef squareBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">100</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId squareBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon squareShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef squareShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId squareShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- DESKTOP ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">which</span> <span class="sy0">!=</span> SDL_TOUCH_MOUSEID<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>btnName <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">button</span> <span class="sy0">==</span> SDL_BUTTON_LEFT<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="st0">&quot;Левая&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Правая&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s кнопка (Мышь): x=%.0f, y=%.0f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> btnName<span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">x</span><span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- MOBILE / WASM (Touch) ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelX <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelY <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Проверяем количество пальцев на устройстве (touchId берем из события)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> numFingers <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTouchFingers<span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>tfinger.<span class="me1">touchID</span><span class="sy0">,</span> <span class="sy0">&amp;</span>numFingers<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numFingers <span class="sy0">&lt;=</span> <span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Левая кнопка (Тап 1 пальцем): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Правая кнопка (Тап несколькими): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Анимация падения. Независимость скорости анимации от частоты обновления экрана</h2><br />
<br />
<ul><li>Добавьте в начале файла main.c после &quot;include&quot; две константы:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="261721134"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="261721134" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define TIME_STEP (1.0f / 60.0f)</span>
<span class="co2">#define MAX_FRAME_TIME 0.25f</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Анимация физики будет происходить с фиксированным периодом равным TIME_STEP. Константа MAX_FRAME_TIME нужна будет для защиты от слишком длинных задержек</li>
<li>Добавьте две глобальные переменные смысл которых будет понятен далее:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="753001231"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="753001231" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> <span class="kw4">float</span> accumulator <span class="sy0">=</span> <span class="nu17">0.0f</span><span class="sy0">;</span>
<span class="kw4">static</span> Uint64 last_ticks <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В конце функции SDL_AppInit() инициализируйте переменную last_ticks:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="247327343"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="247327343" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">last_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В начале функции SDL_AppIterate() добавьте код для расчёта длительности кадра (frameTime) и удержания кадра пределах TIME_STEP:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="971393486"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="971393486" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Uint64 current_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> frameTime <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>current_ticks <span class="sy0">-</span> last_ticks<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">1000.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> current_ticks<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>frameTime <span class="sy0">&gt;</span> MAX_FRAME_TIME<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frameTime <span class="sy0">=</span> MAX_FRAME_TIME<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; accumulator <span class="sy0">+=</span> frameTime<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Функция b2World_Step() - это шаг во времени в физическом мире на величину TIME_STEP</li>
<li>Скомпилируте код:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="256046359"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="256046359" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Запустите приложение в браузере:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="606131887"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="606131887" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Вы увидите, что квадрат падает на круг и удерживает равновесие. Сместите на один пиксель квадрат вправо:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="219747166"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="219747166" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">squareBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">201</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">100</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Скомпилируйте и запустите приложение снова и вы увидите нормальную анимацию падения</li>
<li>Полный код main.c:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="974085362"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="974085362" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &quot;debug-drawer.h&quot;</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;box2d/box2d.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="co2">#define TIME_STEP (1.0f / 60.0f)</span>
<span class="co2">#define MAX_FRAME_TIME 0.25f</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> b2WorldId worldId<span class="sy0">;</span>
<span class="kw4">static</span> b2DebugDraw debugDrawer<span class="sy0">;</span>
&nbsp;
<span class="kw4">const</span> SDL_PixelFormatDetails <span class="sy0">*</span>format <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">float</span> ppm <span class="sy0">=</span> <span class="nu0">30</span>.<span class="me1">f</span><span class="sy0">;</span> <span class="co1">// Pixels per meter</span>
&nbsp;
<span class="kw4">static</span> <span class="kw4">float</span> accumulator <span class="sy0">=</span> <span class="nu17">0.0f</span><span class="sy0">;</span>
<span class="kw4">static</span> Uint64 last_ticks <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Создаём физический мир Box2D с гравитацией</span>
&nbsp; &nbsp; b2Vec2 gravity <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span>.<span class="me1">f</span><span class="sy0">,</span> <span class="nu17">9.8f</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2WorldDef worldDef <span class="sy0">=</span> b2DefaultWorldDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; worldDef.<span class="me1">gravity</span> <span class="sy0">=</span> gravity<span class="sy0">;</span>
&nbsp; &nbsp; worldId <span class="sy0">=</span> b2CreateWorld<span class="br0">&#40;</span><span class="sy0">&amp;</span>worldDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Выводим значение гравитации в консоль</span>
&nbsp; &nbsp; <span class="co1">// Получаем текущее значение гравитации</span>
&nbsp; &nbsp; b2Vec2 currentGravity <span class="sy0">=</span> b2World_GetGravity<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Выводим компоненты x и y</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Текущее значение гравитации: x = %.2f, y = %.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> currentGravity.<span class="me1">x</span><span class="sy0">,</span> currentGravity.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; debugDrawer <span class="sy0">=</span> b2DefaultDebugDraw<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">drawShapes</span> <span class="sy0">=</span> <span class="kw2">true</span><span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidPolygonFcn</span> <span class="sy0">=</span> drawSolidPolygon<span class="sy0">;</span>
&nbsp; &nbsp; debugDrawer.<span class="me1">DrawSolidCircleFcn</span> <span class="sy0">=</span> drawSolidCircle<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Floor</span>
&nbsp; &nbsp; b2BodyDef floorBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_staticBody<span class="sy0">;</span>
&nbsp; &nbsp; floorBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId floorBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon floorShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">300</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef floorShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId floorShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>floorBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>floorShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Square</span>
&nbsp; &nbsp; b2BodyDef squareBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">201</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">100</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; squareBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId squareBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Polygon squareShape <span class="sy0">=</span> b2MakeBox<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="br0">&#40;</span><span class="nu0">30</span>.<span class="me1">f</span> <span class="sy0">/</span> <span class="nu0">2</span>.<span class="me1">f</span><span class="br0">&#41;</span> <span class="sy0">/</span> ppm<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef squareShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId squareShapeId <span class="sy0">=</span> b2CreatePolygonShape<span class="br0">&#40;</span>squareBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>squareShape<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Circle</span>
&nbsp; &nbsp; b2BodyDef circleBodyDef <span class="sy0">=</span> b2DefaultBodyDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">type</span> <span class="sy0">=</span> b2_dynamicBody<span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">position</span> <span class="sy0">=</span> <span class="br0">&#40;</span>b2Vec2<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">200</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm<span class="sy0">,</span> <span class="nu0">150</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleBodyDef.<span class="me1">enableSleep</span> <span class="sy0">=</span> <span class="kw2">false</span><span class="sy0">;</span>
&nbsp; &nbsp; b2BodyId circleBodyId <span class="sy0">=</span> b2CreateBody<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleBodyDef<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2Circle circleCircle <span class="sy0">=</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">center</span> <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu17">0.0f</span><span class="sy0">,</span> <span class="nu17">0.0f</span> <span class="br0">&#125;</span><span class="sy0">,</span> <span class="co1">// &lt;--- ВАЖНО: 0,0 означает, что центр круга совпадает с центром тела</span>
&nbsp; &nbsp; &nbsp; &nbsp; .<span class="me1">radius</span> <span class="sy0">=</span> <span class="nu0">20</span>.<span class="me1">f</span> <span class="sy0">/</span> ppm &nbsp; &nbsp; &nbsp;<span class="co1">// Радиус в метрах</span>
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeDef circleShapeDef <span class="sy0">=</span> b2DefaultShapeDef<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; circleShapeDef.<span class="me1">density</span> <span class="sy0">=</span> <span class="nu17">1.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; b2ShapeId circleShapeId <span class="sy0">=</span> b2CreateCircleShape<span class="br0">&#40;</span>circleBodyId<span class="sy0">,</span> <span class="sy0">&amp;</span>circleShapeDef<span class="sy0">,</span> <span class="sy0">&amp;</span>circleCircle<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Get the pixel format</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_GetWindowSurface<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; format <span class="sy0">=</span> SDL_GetPixelFormatDetails<span class="br0">&#40;</span>surface<span class="sy0">-&gt;</span>format<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- DESKTOP ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">which</span> <span class="sy0">!=</span> SDL_TOUCH_MOUSEID<span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>btnName <span class="sy0">=</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>button.<span class="me1">button</span> <span class="sy0">==</span> SDL_BUTTON_LEFT<span class="br0">&#41;</span> <span class="sy0">?</span> <span class="st0">&quot;Левая&quot;</span> <span class="sy0">:</span> <span class="st0">&quot;Правая&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;%s кнопка (Мышь): x=%.0f, y=%.0f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> btnName<span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">x</span><span class="sy0">,</span> event<span class="sy0">-&gt;</span>button.<span class="me1">y</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- MOBILE / WASM (Touch) ---</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> w<span class="sy0">,</span> h<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetWindowSize<span class="br0">&#40;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>w<span class="sy0">,</span> <span class="sy0">&amp;</span>h<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelX <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">x</span> <span class="sy0">*</span> w<span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> pixelY <span class="sy0">=</span> event<span class="sy0">-&gt;</span>tfinger.<span class="me1">y</span> <span class="sy0">*</span> h<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Проверяем количество пальцев на устройстве (touchId берем из события)</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> numFingers <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_GetTouchFingers<span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>tfinger.<span class="me1">touchID</span><span class="sy0">,</span> <span class="sy0">&amp;</span>numFingers<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numFingers <span class="sy0">&lt;=</span> <span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Левая кнопка (Тап 1 пальцем): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Правая кнопка (Тап несколькими): x=%.2f, y=%.2f<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> pixelX<span class="sy0">,</span> pixelY<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; Uint64 current_ticks <span class="sy0">=</span> SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">float</span> frameTime <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>current_ticks <span class="sy0">-</span> last_ticks<span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu17">1000.0f</span><span class="sy0">;</span>
&nbsp; &nbsp; last_ticks <span class="sy0">=</span> current_ticks<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>frameTime <span class="sy0">&gt;</span> MAX_FRAME_TIME<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; frameTime <span class="sy0">=</span> MAX_FRAME_TIME<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; accumulator <span class="sy0">+=</span> frameTime<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>accumulator <span class="sy0">&gt;=</span> TIME_STEP<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Step physics</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2World_Step<span class="br0">&#40;</span>worldId<span class="sy0">,</span> TIME_STEP<span class="sy0">,</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; accumulator <span class="sy0">-=</span> TIME_STEP<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; b2World_Draw<span class="br0">&#40;</span>worldId<span class="sy0">,</span> <span class="sy0">&amp;</span>debugDrawer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Удаляем физический мир Box2D</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>b2World_IsValid<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; b2DestroyWorld<span class="br0">&#40;</span>worldId<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Сборка в релиз</h2><br />
<br />
<ul><li>Для сборки в релиз нужно открыть файл &quot;config-web.bat&quot; в редакторе кода и исправить Debug на Release:<br />
<br />
config-web.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="303299902"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="303299902" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команды конфигурирования и сборки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="798388714"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="798388714" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">config-web
build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Вес файлов после сборки в Debug:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="554106025"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="554106025" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">375</span> KB
app.wasm - <span class="nu0">2.05</span> MB</pre></td></tr></table></div></td></tr></tbody></table></div>Вес файлов после сборки в Release:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="506861181"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="506861181" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">183</span> KB
app.wasm - <span class="nu0">1.03</span> MB</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Развёртывание на бесплатном хостинге Vercel</h2><br />
<br />
<ul><li>Скачайте установщик Node.js и установите: <a rel="nofollow noopener noreferrer" href="https://nodejs.org/en/download" target="_blank" title="https://nodejs.org/en/download">https://nodejs.org/en/download</a></li>
<li>Установите Vercel следующей командой из консоли глобально:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="514431940"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="514431940" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i vercel <span class="re5">-g</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Зарегистрируйтесь на Vercel: <a rel="nofollow noopener noreferrer" href="https://vercel.com/" target="_blank" title="https://vercel.com/">https://vercel.com/</a></li>
<li>Примечание. В стартовом прмер, который скачали в начале, уже есть файл vercel.json для решения проблемы с загрузкой wasm-файла</li>
<li>В консоле в корне проекта выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="369051400"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="369051400" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="kw2">login</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="839712740"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="839712740" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Будут заданы вопросы в консоли - просто нажимайте всегда Enter</li>
<li>В консоль будет выведен адрес вашего приложения: <a rel="nofollow noopener noreferrer" href="https://start-box2d-v3-wasm-sdl3-c.vercel.app" target="_blank" title="https://start-box2d-v3-wasm-sdl3-c.vercel.app">https://start-box2d-v3-wasm-sdl3-c.vercel.app</a></li>
<li>Примечание. Когда вы что-то измените в проекте и захотите загрузить изменённое приложение на сервер, то введите команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="232033172"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="232033172" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="re5">--prod</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Результат работы приложения:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11682&amp;d=1772487167" border="0" alt="Название: finish-box2d-v3-wasm-sdl3-c.gif
Просмотров: 14136

Размер: 387.2 Кб" style="margin: 5px" /></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11541&amp;d=1770818703" rel="Lightbox" id="attachment11541" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11541&amp;thumb=1&amp;d=1770818703" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 8fd6087b-0ff8-4941-ae56-ab555bd1bf5b.png
Просмотров: 2240
Размер:	14.2 Кб
ID:	11541" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11543&amp;d=1770842690" rel="Lightbox" id="attachment11543" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11543&amp;thumb=1&amp;d=1770842690" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 93204352-f460-4144-bf2a-dbe5904fc2c5.png
Просмотров: 2245
Размер:	854 байт
ID:	11543" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11544&amp;d=1770844660" rel="Lightbox" id="attachment11544" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11544&amp;thumb=1&amp;d=1770844660" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 047ca334-6727-45ce-b9a5-7eb9fd1dbd1b.png
Просмотров: 2246
Размер:	1.3 Кб
ID:	11544" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11533&amp;d=1770759384">start-box2d-v3-wasm-sdl3-c.zip</a> (4.2 Кб, 91 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11535&amp;d=1770761188">SDL3-devel-3.4.0-wasm.zip</a> (1.22 Мб, 115 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11536&amp;d=1770761326">box2d-3.1.1-wasm.zip</a> (555.4 Кб, 133 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11546&amp;d=1770846177">finish-box2d-v3-wasm-sdl3-c.zip</a> (6.5 Кб, 222 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10755.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)</title>
			<link>https://www.cyberforum.ru/blogs/416874/10754.html</link>
			<pubDate>Wed, 11 Feb 2026 11:19:37 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Библиотека SDL3 содержит...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным фоном) встроенными средствами библиотеки SDL3. <a rel="nofollow noopener noreferrer" href="https://start-native-png-loader-wasm-sdl3-c.vercel.app" target="_blank" title="https://start-native-png-loader-wasm-sdl3-c.vercel.app">Финальная демка</a> запускается в браузерах на Desktop (Windows, Linux, macOS) и в браузерах на мобильных устройствах (Android и iOS). Исходники результата: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11530&amp;d=1770747513">finish-native-png-loader-wasm-sdl3-c.zip</a><br />
<br />
<h2>Подключение библиотек SDL3 к стартовому примеру</h2><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте стартовый пример: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11521&amp;d=1770745830">start-native-png-loader-wasm-sdl3-c.zip</a><br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11522&amp;d=1770745893" border="0" alt="Название: 1f4b01ca-4d6d-4c22-8b66-ce91259de101.png
Просмотров: 2050

Размер: 4.9 Кб" style="margin: 5px" /><br /></li>
<li>Код стартового примера:<br />
<br />
src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="530501610"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="530501610" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw here...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку со стартовым примером в какой-нибудь редакторе кода, например, в Notepad++ или в Sublime Text 4 (ST4): <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a></li>
<li>Скачайте библиотеку SDL3: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11526&amp;d=1770746676">SDL3-devel-3.4.0-wasm.zip</a></li>
<li>Извлеките содержимое архива в какую-нибудь новую общую папку, например, с именем &quot;libs&quot; на какой-нибудь диск, например, на C. Таким образом, создайте на диске C папку &quot;lib&quot;, скопируйте в неё архивы и извлеките их в текущую папку:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11523&amp;a= mp;d=1770746015" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Откройте папку &quot;SDL3-devel-3.4.0-wasm&quot;, перейдите в папку &quot;lib/cmake/SDL3&quot; и скопируйте абсолютный путь:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11524&amp;a= mp;d=1770746073" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>В файле CMakeLists.txt стартового примера создайте переменную SDL3_DIR и установите ей значение скопированного пути, заменив обратные слеши на прямые:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="266987526"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="266987526" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>К этому моменту CMakeLists.txt выглядит так:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="906634393"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="906634393" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-load-png-wasm-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотеки SDL3</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Тестовая сборка и тестовый запуск стартового примера в браузере на локальном хостинге</h2><br />
<br />
<ul><li>Откройте консоль (CMD) в корне стартового примера. Для этого можете просто в адресной строке папки (там где путь) написать &quot;cmd&quot; (без кавычек) и нажать Enter</li>
<li>В CMD введите команду для конфигурирования:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="603743610"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="603743610" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;config-web&quot; - это имя bash-файла (батника), который находится в корне папки стартового примера</li>
<li>В CMD введите команду сборки проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="710862050"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="710862050" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Собранные файлы (app.js и app.wasm) будут скопированы в папку &quot;public/js&quot; (папка &quot;public&quot; лежит в корне проекта)</li>
<li>В корне проекта запустите локальный сервер командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="322409340"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="322409340" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Будут выведены адреса:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="832576317"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="832576317" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>192.168.1.65:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 2. Адрес 192.168.1.65:8080 можно использовать для запуска приложения на мобильном устройстве, если у вас есть Wi-Fi - просто вводите этот адрес в браузере мобильного устройства и приложение запустится. Если интересен запуск на мобильном устройстве, то пройдите пошаговую инструкцию: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a></li>
<li>Откройте новую вкладку в браузере. Если у вас Chrome или Edge, то нажмите Ctrl+Shift+J, чтобы открыть консоль браузера для контроля вывода информации. Если у вас FireFox, то нажмите Ctrl+Shift+K</li>
<li>Перейдите по адресу:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="922805022"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="922805022" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Обновлять страницу после пересборки проекта лучше с очисткой кэша браузера. Для этого (обязательно с открытой консолью браузера) в браузере Chrome нужно найти в левом верхнем углу браузера кнопку обновления страницы (круговая стрелка), нажать по ней правой кнопкой мыши и выбрать &quot;Empty Cache and Hard Reload&quot;</li>
<li>В браузере должен выводиться квадрат тёмного-серого цвета - это холст для рисования. Приложение должно собраться и запуститься без ошибок</li>
</ul><br />
<h2>Добавление файла изображения в проект</h2><br />
<br />
<ul><li>Скачайте PNG-файл с прозрачным фоном: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11527&amp;d=1770746676">right-arrow.zip</a></li>
<li>Примечание. Это бесплатный файл, который был взят <a rel="nofollow noopener noreferrer" href="https://www.flaticon.com/free-icons/arrow" target="_blank" title="https://www.flaticon.com/free-icons/arrow">по ссылке</a></li>
<li>Внутри папки стартового примера создайте вложенную папку &quot;assets/images&quot; и скопируйте в неё скаченный файл:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11528&amp;a= mp;d=1770746867" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Откройте файл CMakeLists.txt в редакторе кода и скопируйте в него (в конец файла) код для встраивания изображения в файл &quot;app.wasm&quot;:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="358518695"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="358518695" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Встраиваем изображение в файл app.wasm</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>EMSCRIPTEN<span class="br0">&#41;</span>
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span><span class="st0">&quot;app&quot;</span> PRIVATE <span class="st0">&quot;SHELL:--embed-file <span class="es1">\&quot;</span><span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/images/right-arrow.png@/assets/images/right-arrow.png<span class="es1">\&quot;</span>&quot;</span><span class="br0">&#41;</span>
&nbsp;
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET <span class="st0">&quot;app&quot;</span> APPEND PROPERTY LINK_DEPENDS <span class="st0">&quot;<span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/images/right-arrow.png&quot;</span><span class="br0">&#41;</span>
endif<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Изображение добавлено в проект. Таким же образом вы можете добавлять и другие файлы: звуковые файлы, файлы шрифтов и т.д.</li>
</ul><br />
<h2>Написание кода для вывода изображения</h2><br />
<br />
Лучше всего код набирать вручную, а не копировать, чтобы он лучше запоминался и в дальнейшем было проще и проще с ним работать. Мы напишем код пошагово - строка за строкой.<br />
<br />
<ul><li>Откройте файл src/main.c в редакторе кода</li>
<li>Напишите код создания переменной указателя: texture после создания окна (window) и рисовальщика (renderer):<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="352820087"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="352820087" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>texture <span class="sy0">=</span> NULL<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Ключевое слово static означает, что имя переменной-указателя будет видимо только в пределах файла.</li>
<li>Примечание 2. Для того, чтобы избежать глобальных переменных нужно использовать аргумент appstate (первый аргумент всех 4-x callback-функции SDL3), как в прикреплённом примере этой инструкции по нативной сборки для Android: <a href="https://www.cyberforum.ru/blogs/416874/10727.html">SDL3 для Android: Работа со звуком через SDL3_mixer</a></li>
<li>Лучше сразу, чтобы не забыть, написать код уничтожения текстуры перед закрытием приложения в функции SDL_AppQuit():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="348106242"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="348106242" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
&nbsp;
&nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>texture<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В начале файла main.c найдите функцию SDL_AppInit(), которая вызывается один раз самой первой:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="99557881"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="99557881" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>На данный момент здесь в начале происходит инициализация библиотеки SDL3 с помощью вызова функции SDL_Init():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="403973189"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="403973189" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Далее создаются окно и рисовальщик с помощью вызова функции SDL_CreateWindowAndRenderer()</li>
<li>Вызов функции SDL_SetRenderVSync() включает синхронизацию, то есть вызов функции SDL_AppIterate() будет происходить с той же частотой, с которой работает монитор компьютера</li>
<li>После функции SDL_SetRenderVSync() добавьте код загрузки файла-изображения и создания текстуры:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="687954937"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="687954937" style="height: 190px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>texturePath <span class="sy0">=</span> <span class="st0">&quot;./assets/images/right-arrow.png&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> SDL_LoadPNG<span class="br0">&#40;</span>texturePath<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>surface<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;PNG load failed: %s: %s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> texturePath<span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; texture <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppIterate() добавьте код вывода изображения:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="616309845"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="616309845" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_FRect srcRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">512</span><span class="sy0">,</span> <span class="nu0">512</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_FRect destRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> texture<span class="sy0">,</span> <span class="sy0">&amp;</span>srcRect<span class="sy0">,</span> <span class="sy0">&amp;</span>destRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Сделаем сборку кода и запуск приложения. Сейчас у вас должен быть запущен локальный сервер от тестовой сборки вначале инструкции. Если нет, то запустите локальный сервер в корне проекта из CMD:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="428054584"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="428054584" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте ещё одну консоль внутри папки проекта и выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="724791939"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="724791939" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Не нужно выполнять команду &quot;config-web&quot;, потому что её требуется вводить только один раз, а далее CMake будет сам проверять перед сборкой были ли изменения в CMakeLists.txt и если изменения были, то CMake сам переконфигурирует проект</li>
<li>Если вы закрыли вкладку браузера, то откройте новую, нажмите Ctrl+Shift+J в Chrome/Edge (Ctrl+Shift+K) в FireFox и обновите страницу</li>
<li>Примечание. Можете подключить смартфон по USB-кабелю и протестировать код: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a> Если вы уже пробовали, то перейдите на компьютере по адресу chrome://inspect/#devices Найдите приложение в списке и нажмите &quot;inspect&quot;. Вы увидите экран смартфона на компьютере</li>
<li>В браузере да Desktop и в браузере на мобильном вы увидите результат работы приложения:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11529&amp;d=1770747330" border="0" alt="Название: c1383c69-8591-4a3d-b81e-a068130d5870.png
Просмотров: 2066

Размер: 1.0 Кб" style="margin: 5px" /></li>
</ul><br />
<h2>Сборка в релиз</h2><br />
<br />
<ul><li>Для сборки в релиз нужно открыть файл &quot;config-web.bat&quot; в редакторе кода и исправить Debug на Release:<br />
<br />
config-web.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="395912353"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="395912353" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команды конфигурирования и сборки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="918158525"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="918158525" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">config-web
build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Вес файлов после сборки в Debug:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="801412647"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="801412647" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">376</span> KB
app.wasm - <span class="nu0">1.37</span> MB</pre></td></tr></table></div></td></tr></tbody></table></div>Вес файлов после сборки в Release:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="576553492"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="576553492" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">183</span> KB
app.wasm - <span class="nu0">803</span> KB</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Развёртывание на бесплатном хостинге Vercel</h2><br />
<br />
<ul><li>Скачайте установщик Node.js и установите: <a rel="nofollow noopener noreferrer" href="https://nodejs.org/en/download" target="_blank" title="https://nodejs.org/en/download">https://nodejs.org/en/download</a></li>
<li>Установите Vercel следующей командой из консоли глобально:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="962494868"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="962494868" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i vercel <span class="re5">-g</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Зарегистрируйтесь на Vercel: <a rel="nofollow noopener noreferrer" href="https://vercel.com/" target="_blank" title="https://vercel.com/">https://vercel.com/</a></li>
<li>Примечание. В стартовом прмер, который скачали в начале, уже есть файл vercel.json для решения проблемы с загрузкой wasm-файла</li>
<li>В консоле в корне проекта выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="791343859"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="791343859" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="kw2">login</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="296519410"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="296519410" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Будут заданы вопросы в консоли - просто нажимайте всегда Enter</li>
<li>В консоль будет выведен адрес вашего приложения: <a rel="nofollow noopener noreferrer" href="https://start-native-png-loader-wasm-sdl3-c.vercel.app" target="_blank" title="https://start-native-png-loader-wasm-sdl3-c.vercel.app">https://start-native-png-loade... vercel.app</a></li>
<li>Примечание. Когда вы что-то измените в проекте и захотите загрузить изменённое приложение на сервер, то введите команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="922983373"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="922983373" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="re5">--prod</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11523&amp;d=1770746015" rel="Lightbox" id="attachment11523" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11523&amp;thumb=1&amp;d=1770746015" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: ef3d275d-68a8-48e3-8534-78a8fed6dce8.png
Просмотров: 2127
Размер:	3.3 Кб
ID:	11523" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11524&amp;d=1770746073" rel="Lightbox" id="attachment11524" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11524&amp;thumb=1&amp;d=1770746073" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 67b8b40c-6da7-4da4-86c1-06387b3c699e.png
Просмотров: 2151
Размер:	14.2 Кб
ID:	11524" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11528&amp;d=1770746867" rel="Lightbox" id="attachment11528" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11528&amp;thumb=1&amp;d=1770746867" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 400251bc-e2e5-4f86-b58e-f554ac33f829.png
Просмотров: 2145
Размер:	4.8 Кб
ID:	11528" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11521&amp;d=1770745830">start-native-png-loader-wasm-sdl3-c.zip</a> (6.3 Кб, 67 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11526&amp;d=1770746676">SDL3-devel-3.4.0-wasm.zip</a> (1.22 Мб, 108 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11527&amp;d=1770746676">right-arrow.zip</a> (1.5 Кб, 71 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11530&amp;d=1770747513">finish-native-png-loader-wasm-sdl3-c.zip</a> (6.4 Кб, 219 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10754.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image</title>
			<link>https://www.cyberforum.ru/blogs/416874/10752.html</link>
			<pubDate>Tue, 10 Feb 2026 18:25:10 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Библиотека SDL3_image...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным фоном) помощью библиотеки SDL3_image. <a rel="nofollow noopener noreferrer" href="https://start-load-png-wasm-sdl3-c.vercel.app" target="_blank" title="https://start-load-png-wasm-sdl3-c.vercel.app">Финальная демка</a> запускается в браузерах на Desktop (Windows, Linux, macOS) и в браузерах на мобильных устройствах (Android и iOS). Исходники результата: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11519&amp;d=1770742574">finish-load-png-wasm-sdl3-c.zip</a><br />
<br />
<h2>Подключение библиотек SDL3 и SDL3_image к стартовому примеру</h2><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте стартовый пример: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11509&amp;d=1770590395">start-load-png-wasm-sdl3-c.zip</a><br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11516&amp;d=1770671296" border="0" alt="Название: 63feb986-3bf6-4e01-ba6d-fccf8999b1c2.png
Просмотров: 942

Размер: 4.2 Кб" style="margin: 5px" /><br /></li>
<li>Код стартового примера:<br />
<br />
src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="599902532"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="599902532" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw here...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку со стартовым примером в какой-нибудь редакторе кода, например, в Notepad++ или в Sublime Text 4 (ST4): <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a></li>
<li>Скачайте библиотеку SDL3: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11510&amp;d=1770590411">SDL3-devel-3.4.0-wasm.zip</a></li>
<li>Скачайте библиотеку SDL3_image: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11511&amp;d=1770590411">SDL3_image-devel-3.4.0-wasm.zip</a></li>
<li>Извлеките содержимое архивов библиотек в какую-нибудь новую общую папку, например, с именем &quot;libs&quot; на какой-нибудь диск, например, на C. Таким образом, создайте на диске C папку &quot;lib&quot;, скопируйте в неё архивы и извлеките их в текущую папку:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11506&amp;a= mp;d=1770590182" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Откройте папку &quot;SDL3-devel-3.4.0-wasm&quot;, перейдите в папку &quot;lib/cmake/SDL3&quot; и скопируйте абсолютный путь:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11512&amp;a= mp;d=1770635713" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>В файле CMakeLists.txt стартового примера создайте переменную SDL3_DIR и установите ей значение скопированного пути, заменив обратные слеши на прямые:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="837879627"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="837879627" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку &quot;SDL3_image-devel-3.4.0-wasm&quot;, перейдите в папку &quot;lib/cmake/SDL3_image&quot; и скопируйте абсолютный путь:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11513&amp;a= mp;d=1770636133" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>В файле CMakeLists.txt стартового примера создайте переменную SDL3_image_DIR и установите ей значение скопированного пути, заменив обратные слеши на прямые:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="541369544"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="541369544" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_image_DIR <span class="st0">&quot;C:/libs/SDL3_image-devel-3.4.0-wasm/lib/cmake/SDL3_image&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Здесь же в файле CMakeLists.txt добавьте команду для проверки наличия библиотеки SDL3_image в системе, а если пути к этим библиотекам мы задали неверно, то будет выведена ошибка при конфигурировании проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="232733659"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="232733659" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_image REQUIRED<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Привязываем библиотеку SDL3_image к нашему приложению путём добавления SDL3_image::SDL3_image:<br />
<br />
Было:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="308318037"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="308318037" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="536947175"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="536947175" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3_image::SDL3_image SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>К этому моменту CMakeLists.txt выглядит так:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="228048844"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="228048844" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-load-png-wasm-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотеки SDL3</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_image_DIR <span class="st0">&quot;C:/libs/SDL3_image-devel-3.4.0-wasm/lib/cmake/SDL3_image&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_image REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3_image::SDL3_image SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Тестовая сборка и тестовый запуск стартового примера в браузере на локальном хостинге</h2><br />
<br />
<ul><li>Откройте консоль (CMD) в корне стартового примера. Для этого можете просто в адресной строке папки (там где путь) написать &quot;cmd&quot; (без кавычек) и нажать Enter</li>
<li>В CMD введите команду для конфигурирования:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="658378753"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="658378753" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;config-web&quot; - это имя bash-файла (батника), который находится в корне папки стартового примера</li>
<li>В CMD введите команду сборки проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="562099494"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="562099494" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Собранные файлы (app.js и app.wasm) будут скопированы в папку &quot;public/js&quot; (папка &quot;public&quot; лежит в корне проекта)</li>
<li>В корне проекта запустите локальный сервер командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="328504884"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="328504884" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Будут выведены адреса:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="487700084"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="487700084" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>192.168.1.65:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 2. Адрес 192.168.1.65:8080 можно использовать для запуска приложения на мобильном устройстве, если у вас есть Wi-Fi - просто вводите этот адрес в браузере мобильного устройства и приложение запустится. Если интересен запуск на мобильном устройстве, то пройдите пошаговую инструкцию: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a></li>
<li>Откройте новую вкладку в браузере. Если у вас Chrome или Edge, то нажмите Ctrl+Shift+J, чтобы открыть консоль браузера для контроля вывода информации. Если у вас FireFox, то нажмите Ctrl+Shift+K</li>
<li>Перейдите по адресу:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="558855526"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="558855526" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Обновлять страницу после пересборки проекта лучше с очисткой кэша браузера. Для этого (обязательно с открытой консолью браузера) в браузере Chrome нужно найти в левом верхнем углу браузера кнопку обновления страницы (круговая стрелка), нажать по ней правой кнопкой мыши и выбрать &quot;Empty Cache and Hard Reload&quot;</li>
<li>В браузере должен выводиться квадрат тёмного-серого цвета - это холст для рисования. Приложение должно собраться и запуститься без ошибок</li>
</ul><br />
<h2>Добавление файла изображения в проект</h2><br />
<br />
<ul><li>Скачайте PNG-файл с прозрачным фоном: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11514&amp;d=1770641845">right-arrow.zip</a></li>
<li>Примечание. Это бесплатный файл, который был взят <a rel="nofollow noopener noreferrer" href="https://www.flaticon.com/free-icons/arrow" target="_blank" title="https://www.flaticon.com/free-icons/arrow">по ссылке</a></li>
<li>Внутри папки стартового примера создайте вложенную папку &quot;assets/images&quot; и скопируйте в неё скаченный файл:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11517&amp;d=1770739956" border="0" alt="Название: ff5442cd-1c0d-4347-8750-052d4e4fbeb9.png
Просмотров: 952

Размер: 2.1 Кб" style="margin: 5px" /></li>
<li>Откройте файл CMakeLists.txt в редакторе кода и скопируйте в него (в конец файла) код для встраивания изображения в файл &quot;app.wasm&quot;:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="846356734"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="846356734" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Встраиваем изображение в файл app.wasm</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>EMSCRIPTEN<span class="br0">&#41;</span>
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span><span class="st0">&quot;app&quot;</span> PRIVATE <span class="st0">&quot;SHELL:--embed-file <span class="es1">\&quot;</span><span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/images/right-arrow.png@/assets/images/right-arrow.png<span class="es1">\&quot;</span>&quot;</span><span class="br0">&#41;</span>
&nbsp;
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET <span class="st0">&quot;app&quot;</span> APPEND PROPERTY LINK_DEPENDS <span class="st0">&quot;<span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/images/right-arrow.png&quot;</span><span class="br0">&#41;</span>
endif<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Изображение добавлено в проект. Таким же образом вы можете добавлять и другие файлы: звуковые файлы, файлы шрифтов и т.д.</li>
</ul><br />
<h2>Написание кода для вывода изображения</h2><br />
<br />
Лучше всего код набирать вручную, а не копировать, чтобы он лучше запоминался и в дальнейшем было проще и проще с ним работать. Мы напишем код пошагово - строка за строкой.<br />
<ul><li>Откройте файл src/main.c в редакторе кода</li>
<li>Напишите код включения заголовочного файла SDL_image.h в этом месте кода:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="978353538"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="978353538" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_image/SDL_image.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Напишите код создания переменной указателя: texture после создания окна (window) и рисовальщика (renderer):<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="608864172"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="608864172" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>texture <span class="sy0">=</span> NULL<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Ключевое слово static означает, что имя переменной-указателя будет видимо только в пределах файла.</li>
<li>Примечание 2. Для того, чтобы избежать глобальных переменных нужно использовать аргумент appstate (первый аргумент всех 4-x callback-функции SDL3), как в прикреплённом примере этой инструкции по нативной сборки для Android: <a href="https://www.cyberforum.ru/blogs/416874/10727.html">SDL3 для Android: Работа со звуком через SDL3_mixer</a></li>
<li>Лучше сразу, чтобы не забыть, написать код уничтожения текстуры перед закрытием приложения в функции SDL_AppQuit():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="170479910"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="170479910" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
&nbsp;
&nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>texture<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В начале файла main.c найдите функцию SDL_AppInit(), которая вызывается один раз самой первой:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="921167715"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="921167715" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>На данный момент здесь в начале происходит инициализация библиотеки SDL3 с помощью вызова функции SDL_Init():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="800191386"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="800191386" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Далее создаются окно и рисовальщик с помощью вызова функции SDL_CreateWindowAndRenderer()</li>
<li>Вызов функции SDL_SetRenderVSync() включает синхронизацию, то есть вызов функции SDL_AppIterate() будет происходить с той же частотой, с которой работает монитор компьютера</li>
<li>После функции SDL_SetRenderVSync() добавьте код загрузки файла-изображения и создания текстуры:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="835132042"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="835132042" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>texturePath <span class="sy0">=</span> <span class="st0">&quot;./assets/images/right-arrow.png&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; texture <span class="sy0">=</span> IMG_LoadTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> texturePath<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>texture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't load %s: %s<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> texturePath<span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppIterate() добавьте код вывода изображения:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="46714468"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="46714468" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_FRect srcRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">512</span><span class="sy0">,</span> <span class="nu0">512</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_FRect destRect <span class="sy0">=</span> <span class="br0">&#123;</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> texture<span class="sy0">,</span> <span class="sy0">&amp;</span>srcRect<span class="sy0">,</span> <span class="sy0">&amp;</span>destRect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Сделаем сборку кода и запуск приложения. Сейчас у вас должен быть запущен локальный сервер от тестовой сборки вначале инструкции. Если нет, то запустите локальный сервер в корне проекта из CMD:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="365294699"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="365294699" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте ещё одну консоль внутри папки проекта и выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="358489067"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="358489067" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Не нужно выполнять команду &quot;config-web&quot;, потому что её требуется вводить только один раз, а далее CMake будет сам проверять перед сборкой были ли изменения в CMakeLists.txt и если изменения были, то CMake сам переконфигурирует проект</li>
<li>Если вы закрыли вкладку браузера, то откройте новую, нажмите Ctrl+Shift+J в Chrome/Edge (Ctrl+Shift+K) в FireFox и обновите страницу</li>
<li>Примечание. Можете подключить смартфон по USB-кабелю и протестировать код: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a> Если вы уже пробовали, то перейдите на компьютере по адресу chrome://inspect/#devices Найдите приложение в списке и нажмите &quot;inspect&quot;. Вы увидите экран смартфона на компьютере</li>
<li>В браузере да Desktop и в браузере на мобильном вы увидите результат работы приложения:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11518&amp;d=1770742486" border="0" alt="Название: 35300b97-4c78-4982-9904-78c48b8b1700.png
Просмотров: 964

Размер: 1.0 Кб" style="margin: 5px" /></li>
</ul><br />
<h2>Сборка в релиз</h2><br />
<br />
<ul><li>Для сборки в релиз нужно открыть файл &quot;config-web.bat&quot; в редакторе кода и исправить Debug на Release:<br />
<br />
config-web.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="2822901"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="2822901" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команды конфигурирования и сборки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="126992523"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="126992523" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">config-web
build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Вес файлов после сборки в Debug:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="347687062"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="347687062" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">377</span> KB
app.wasm - <span class="nu0">1.5</span> MB</pre></td></tr></table></div></td></tr></tbody></table></div>Вес файлов после сборки в Release:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="215662333"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="215662333" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">184</span> KB
app.wasm - <span class="nu0">916</span> KB</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Развёртывание на бесплатном хостинге Vercel</h2><br />
<br />
<ul><li>Скачайте установщик Node.js и установите: <a rel="nofollow noopener noreferrer" href="https://nodejs.org/en/download" target="_blank" title="https://nodejs.org/en/download">https://nodejs.org/en/download</a></li>
<li>Установите Vercel следующей командой из консоли глобально:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="63341353"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="63341353" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i vercel <span class="re5">-g</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Зарегистрируйтесь на Vercel: <a rel="nofollow noopener noreferrer" href="https://vercel.com/" target="_blank" title="https://vercel.com/">https://vercel.com/</a></li>
<li>Примечание. В стартовом прмер, который скачали в начале, уже есть файл vercel.json для решения проблемы с загрузкой wasm-файла</li>
<li>В консоле в корне проекта выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="36658274"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="36658274" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="kw2">login</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="475290274"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="475290274" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Будут заданы вопросы в консоли - просто нажимайте всегда Enter</li>
<li>В консоль будет выведен адрес вашего приложения: <a rel="nofollow noopener noreferrer" href="https://start-load-png-wasm-sdl3-c.vercel.app" target="_blank" title="https://start-load-png-wasm-sdl3-c.vercel.app">https://start-load-png-wasm-sdl3-c.vercel.app</a></li>
<li>Примечание. Когда вы что-то измените в проекте и захотите загрузить изменённое приложение на сервер, то введите команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="846442674"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="846442674" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="re5">--prod</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11506&amp;d=1770590182" rel="Lightbox" id="attachment11506" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11506&amp;thumb=1&amp;d=1770590182" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 30e9ee21-d349-4c1b-9a49-941f1eabedd7.png
Просмотров: 1024
Размер:	4.2 Кб
ID:	11506" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11512&amp;d=1770635713" rel="Lightbox" id="attachment11512" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11512&amp;thumb=1&amp;d=1770635713" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: cae80b14-6ee1-45e7-bdb6-404691c34fb6.png
Просмотров: 1016
Размер:	14.2 Кб
ID:	11512" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11513&amp;d=1770636133" rel="Lightbox" id="attachment11513" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11513&amp;thumb=1&amp;d=1770636133" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: bea2d5f8-2f0e-4924-90d0-270682653243.png
Просмотров: 995
Размер:	12.4 Кб
ID:	11513" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11509&amp;d=1770590395">start-load-png-wasm-sdl3-c.zip</a> (3.7 Кб, 70 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11510&amp;d=1770590411">SDL3-devel-3.4.0-wasm.zip</a> (1.22 Мб, 89 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11511&amp;d=1770590411">SDL3_image-devel-3.4.0-wasm.zip</a> (121.5 Кб, 64 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11514&amp;d=1770641845">right-arrow.zip</a> (1.5 Кб, 69 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11520&amp;d=1770745679">finish-load-png-wasm-sdl3-c.zip</a> (6.1 Кб, 85 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10752.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer</title>
			<link>https://www.cyberforum.ru/blogs/416874/10750.html</link>
			<pubDate>Sun, 08 Feb 2026 20:05:48 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Пошагово создадим проект...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по касанию холста на мобильных устройствах. Запустить финальную демку в браузере можно по <a rel="nofollow noopener noreferrer" href="https://start-play-sound-wasm-sdl3-c.vercel.app" target="_blank" title="https://start-play-sound-wasm-sdl3-c.vercel.app">ссылке</a>. Скачать результат: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11504&amp;d=1770581097">finish-play-sound-wasm-sdl3-c.zip</a><br />
<br />
<h2>Подключение библиотек SDL3 и SDL3_mixer к стартовому примеру</h2><br />
<br />
<ul><li>Установите Emscripten 4.0.15 и CMake по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a></li>
<li>Скачайте стартовый пример: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11497&amp;d=1770497144">start-play-sound-wasm-sdl3-c.zip</a></li>
<li>Код стартового примера:<br />
<br />
src/main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="167261223"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="167261223" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Отключаем генерацию событий мыши из касаний пальцем</span>
&nbsp; &nbsp; SDL_SetHint<span class="br0">&#40;</span>SDL_HINT_TOUCH_MOUSE_EVENTS<span class="sy0">,</span> <span class="st0">&quot;0&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Клик мышью<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Касание экрана<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw here...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте папку со стартовым примером в какой-нибудь редакторе кода, например, в Notepad++ или в Sublime Text 4 (ST4): <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a></li>
<li>Скачайте библиотеку SDL3: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11499&amp;d=1770551495">SDL3-devel-3.4.0-wasm.zip</a></li>
<li>Скачайте библиотеку SDL3_mixer: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11500&amp;d=1770551495">SDL3_mixer-devel-3.1.2-wasm.zip</a></li>
<li>Извлеките содержимое архивов библиотек в какую-нибудь новую общую папку, например, с именем &quot;libs&quot; на какой-нибудь диск, например, на C. Таким образом, создайте на диске C папку &quot;lib&quot;, скопируйте в неё архивы и извлеките их в текущую папку:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11498&amp;a= mp;d=1770551420" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Примечание. В папках этих библиотек есть конфигурационные файлы для CMake. Мы будем использовать пути следующего вида для подключения этих библиотек в нашем проекте:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11501&amp;a= mp;d=1770551983" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Скопируйте путь показанный на скриншоте выше, откройте в редакторе кода файл CMakeLists.txt и замените старый путь на новый в строке:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="83616717"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="83616717" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Важно! После копирования пути замените обратные слеши (косую черту) на прямые</li>
<li>То же самое проделайте для подключения библиотеки SDL3_mixer. То есть, зайдите в папку с конфигурационными файлами SDL3_mixer, создайте в CMakeLists.txt переменную SDL3_mixer_DIR и установите ей значение пути. У вас получится две строчки кода в CMakeLists.txt:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="273926678"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="273926678" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Указываем точное местоположение конфигурационных файлов библиотеки SDL3</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_mixer_DIR <span class="st0">&quot;C:/libs/SDL3_mixer-devel-3.1.2-wasm/lib/cmake/SDL3_mixer&quot;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Здесь же в файле CMakeLists.txt добавьте команду для проверки наличия библиотеки SDL3_mixer в системе, а если пути к этим библиотекам мы задали неверно, то будет выведена ошибка при конфигурировании проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="358952971"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="358952971" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_mixer REQUIRED<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Привязываем библиотеку SDL3_mixer к нашему приложению путём добавления SDL3_mixer::SDL3_mixer:<br />
<br />
Было:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="996470363"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="996470363" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="993354145"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="993354145" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3_mixer::SDL3_mixer SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>К этому моменту CMakeLists.txt выглядит так:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="398255774"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="398255774" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-play-sound-wasm-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а</span>
<span class="co0"># в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотеки SDL3</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_mixer_DIR <span class="st0">&quot;C:/libs/SDL3_mixer-devel-3.1.2-wasm/lib/cmake/SDL3_mixer&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_mixer REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3_mixer::SDL3_mixer SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Тестовая сборка и тестовый запуск стартового примера в браузере на локальном хостинге</h2><br />
<br />
<ul><li>Откройте консоль (CMD) в корне стартового примера. Для этого можете просто в адресной строке папки (там где путь) написать &quot;cmd&quot; (без кавычек) и нажать Enter</li>
<li>В CMD введите команду для конфигурирования:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="532025791"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="532025791" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. &quot;config-web&quot; - это имя bash-файла (батника), который находится в корне папки стартового примера</li>
<li>В CMD введите команду сборки проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="722797161"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="722797161" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Собранные файлы (app.js и app.wasm) будут скопированы в папку &quot;public/js&quot; (папка &quot;public&quot; лежит в корне проекта)</li>
<li>В корне проекта запустите локальный сервер командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="27725859"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="27725859" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Будут выведены адреса:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="406313895"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="406313895" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>192.168.1.65:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 2. Адрес 192.168.1.65:8080 можно использовать для запуска приложения на мобильном устройстве, если у вас есть Wi-Fi - просто вводите этот адрес в браузере мобильного устройства и приложение запустится. Если интересен запуск на мобильном устройстве, то пройдите пошаговую инструкцию: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a></li>
<li>Откройте новую вкладку в браузере. Если у вас Chrome или Edge, то нажмите Ctrl+Shift+J, чтобы открыть консоль браузера для контроля вывода информации. Если у вас FireFox, то нажмите Ctrl+Shift+K</li>
<li>Перейдите по адресу:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="344352101"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="344352101" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Обновлять страницу после пересборки проекта лучше с очисткой кэша браузера. Для этого (обязательно с открытой консолью браузера) в браузере Chrome нужно найти в левом верхнем углу браузера кнопку обновления страницы (круговая стрелка), нажать по ней правой кнопкой мыши и выбрать &quot;Empty Cache and Hard Reload&quot;</li>
<li>Кликайте по серому холсту и наблюдайте вывод текста в консоль. Должно выводиться:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="419135481"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="419135481" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">Клик мышью</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Добавление аудио-файла в проект</h2><br />
<br />
<ul><li>Скачайте аудио-файл: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11502&amp;d=1770562036">Picked Coin Echo 2.zip</a></li>
<li>Примечание. Это бесплатный файл, который был взят <a rel="nofollow noopener noreferrer" href="https://opengameart.org/content/picked-coin-echo-2" target="_blank" title="https://opengameart.org/content/picked-coin-echo-2">по ссылке</a></li>
<li>Внутри папки стартового примера создайте вложенную папку &quot;assets/audio&quot; и скопируйте в неё скаченный аудио-файл:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11503&amp;d=1770562247" border="0" alt="Название: 6fe16441-fcc6-480f-b8fa-f86c60b4a7c2.png
Просмотров: 856

Размер: 3.1 Кб" style="margin: 5px" /></li>
<li>Откройте файл CMakeLists.txt в редакторе кода и скопируйте в него (в конец файла) код для встраивания аудио-файла в файл &quot;app.wasm&quot;:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="349182742"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="349182742" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="co0"># Встраиваем аудио-файл в файл app.wasm</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>EMSCRIPTEN<span class="br0">&#41;</span>
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span><span class="st0">&quot;app&quot;</span> PRIVATE <span class="st0">&quot;SHELL:--embed-file <span class="es1">\&quot;</span><span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/audio/Picked Coin Echo 2.wav@/assets/audio/Picked Coin Echo 2.wav<span class="es1">\&quot;</span>&quot;</span><span class="br0">&#41;</span>
&nbsp;
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET <span class="st0">&quot;app&quot;</span> APPEND PROPERTY LINK_DEPENDS <span class="st0">&quot;<span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/audio/Picked Coin Echo 2.wav&quot;</span><span class="br0">&#41;</span>
endif<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Текущий файл CMakeLists.txt на данный момент:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="818114085"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="818114085" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-play-sound-wasm-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Указываем точное местоположение конфигурационных файлов библиотеки SDL3</span>
<span class="co0"># Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_mixer_DIR <span class="st0">&quot;C:/libs/SDL3_mixer-devel-3.1.2-wasm/lib/cmake/SDL3_mixer&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Проверяем наличие библиотек в системе</span>
<span class="co0"># Если она не будет найдены, CMake прервет настройку с ошибкой</span>
<span class="co0"># REQUIRED - переводится, как «обязательно» или «требуется»</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_mixer REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем библиотеки к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3_mixer::SDL3_mixer SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исходный код к проекту</span>
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Встраиваем аудио-файл в файл app.wasm</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>EMSCRIPTEN<span class="br0">&#41;</span>
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span><span class="st0">&quot;app&quot;</span> PRIVATE <span class="st0">&quot;SHELL:--embed-file <span class="es1">\&quot;</span><span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/audio/Picked Coin Echo 2.wav@/assets/audio/Picked Coin Echo 2.wav<span class="es1">\&quot;</span>&quot;</span><span class="br0">&#41;</span>
&nbsp;
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET <span class="st0">&quot;app&quot;</span> APPEND PROPERTY LINK_DEPENDS <span class="st0">&quot;<span class="es3">${CMAKE_CURRENT_SOURCE_DIR}</span>/assets/audio/Picked Coin Echo 2.wav&quot;</span><span class="br0">&#41;</span>
endif<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Аудио-файл добавлен в проект. Таким же образом вы можете добавлять и другие файлы: изображения, шрифты и т.д.</li>
</ul><br />
<h2>Написание кода для проигрывания звука</h2><br />
<br />
Код лучше всего набирать вручную, а не копировать, чтобы быстрее его запоминать. Мы напишем код пошагово - строка за строкой. Эта инструкция базируется на официальном примере <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL_mixer/blob/37b2f3325a0fb1e98ba265aa38826aa9e16624fb/docs/hello.c" target="_blank" title="https://github.com/libsdl-org/SDL_mixer/blob/37b2f3325a0fb1e98ba265aa38826aa9e16624fb/docs/hello.c">hello.c</a>, но мы не будет использовать track. Содержимое файла hello.c:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="199145618"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="199145618" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 &nbsp;/* use the callbacks instead of main() */</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_mixer/SDL_mixer.h&gt;</span>
&nbsp;
<span class="kw4">static</span> MIX_Mixer <span class="sy0">*</span>mixer<span class="sy0">;</span>
<span class="kw4">static</span> MIX_Track <span class="sy0">*</span>track<span class="sy0">;</span>
<span class="kw4">static</span> MIX_Audio <span class="sy0">*</span>audio<span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>file<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* this doesn't have to run very much, so give up tons of CPU time between iterations. */</span>
&nbsp; &nbsp; SDL_SetHint<span class="br0">&#40;</span>SDL_HINT_MAIN_CALLBACK_RATE<span class="sy0">,</span> <span class="st0">&quot;5&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>argc <span class="sy0">!=</span> <span class="nu0">2</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Usage: %s &lt;file_to_play&gt;&quot;</span><span class="sy0">,</span> argv<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; file <span class="sy0">=</span> argv<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>MIX_Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL_mixer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; mixer <span class="sy0">=</span> MIX_CreateMixerDevice<span class="br0">&#40;</span>SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK<span class="sy0">,</span> NULL<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>mixer<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create mixer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; audio <span class="sy0">=</span> MIX_LoadAudio<span class="br0">&#40;</span>mixer<span class="sy0">,</span> file<span class="sy0">,</span> <span class="kw2">true</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>audio<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't load audio from %s: %s&quot;</span><span class="sy0">,</span> file<span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; track <span class="sy0">=</span> MIX_CreateTrack<span class="br0">&#40;</span>mixer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>track<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create track: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; MIX_SetTrackAudio<span class="br0">&#40;</span>track<span class="sy0">,</span> audio<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; MIX_PlayTrack<span class="br0">&#40;</span>track<span class="sy0">,</span> <span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>MIX_TrackPlaying<span class="br0">&#40;</span>track<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="coMULTI">/* This will close the audio device and free all mixers and audio data */</span>
&nbsp; &nbsp; MIX_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div><ul><li>Откройте файл src/main.c в редакторе кода</li>
<li>Напишите код включения заголовочного файла SDL_mixer.h в этом месте кода:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="265992073"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="265992073" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_mixer/SDL_mixer.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Напишите код создания двух переменных указателя: mixer и audio после создания окна (window) и рисовальщика (renderer):<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="5235585"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="5235585" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> MIX_Mixer <span class="sy0">*</span>mixer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> MIX_Audio <span class="sy0">*</span>audio <span class="sy0">=</span> NULL<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Ключевое слово static означает, что имя переменной-указателя будет видимо только в пределах файла.</li>
<li>Примечание 2. Для того, чтобы избежать глобальных переменных нужно использовать аргумент appstate (первый аргумент всех 4-x callback-функции SDL3), как в прикреплённом примере этой инструкции по нативной сборки для Android: <a href="https://www.cyberforum.ru/blogs/416874/10727.html">SDL3 для Android: Работа со звуком через SDL3_mixer</a></li>
<li>В стартовом примере в начале файла main.c есть функция SDL_AppInit(), которая вызывается один раз самой первой:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="30483809"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="30483809" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Отключаем генерацию событий мыши из касаний пальцем</span>
&nbsp; &nbsp; SDL_SetHint<span class="br0">&#40;</span>SDL_HINT_TOUCH_MOUSE_EVENTS<span class="sy0">,</span> <span class="st0">&quot;0&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>На данный момент здесь в начале происходит инициализация библиотеки SDL3 с помощью вызова функции SDL_Init():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="166747860"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="166747860" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Удалите эту строку кода:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="681041657"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="681041657" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Отключаем генерацию событий мыши из касаний пальцем</span>
&nbsp; &nbsp; SDL_SetHint<span class="br0">&#40;</span>SDL_HINT_TOUCH_MOUSE_EVENTS<span class="sy0">,</span> <span class="st0">&quot;0&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Строку выше удалили, чтобы было поведение по умолчанию - пусть клик мыши на Desktop и касание холста на мобильном устройстве приводит к срабатыванию события SDL_EVENT_MOUSE_BUTTON_DOWN в функции SDL_AppEvent():<br />
<br />
Было:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="29671895"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="29671895" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Клик мышью<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Касание экрана<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="286026327"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="286026327" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;События клика/касания холста<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Протестируем изменения. Сейчас у вас должен быть запущен локальный сервер. Откройте ещё одну консоль внутри папки проекта и выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="899161329"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="899161329" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Не нужно выполнять команду &quot;config-web&quot;, потому что её требуется вводить только один раз, а далее CMake будет сам проверять перед сборкой были ли изменения в CMakeLists.txt и если изменения были, то CMake сам переконфигурирует проект</li>
<li>Если вы закрыли вкладку браузера, то откройте новую, нажмите Ctrl+Shift+J в Chrome/Edge (Ctrl+Shift+K) в FireFox и обновите страницу. Кликайте по серому холсту и вы увидите вывод в консоли при клике.</li>
<li>Примечание. Можете подключить смартфон по USB-кабелю и протестировать код: <a href="https://www.cyberforum.ru/blogs/416874/10741.html">Основы отладки веб-приложений на SDL3 по USB и Wi-Fi</a> Если вы уже пробовали, то перейдите на компьютере по адресу chrome://inspect/#devices Найдите приложение в списке и нажмите &quot;inspect&quot;. Вы увидите экран смартфона на компьютере. Касайтесь экрана смартфона и наблюдайте на вывод в консоль браузера Chrome на компьютере</li>
<li>Текущий код main.c на данным момент:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="651197565"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="651197565" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_mixer/SDL_mixer.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="kw4">static</span> MIX_Mixer <span class="sy0">*</span>mixer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> MIX_Audio <span class="sy0">*</span>audio <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;События клика/касания холста<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw here...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Текущий код протестирован. Продолжаем добавлять код для воспроизведения звука в браузере</li>
<li>Напишите код инициализации SDL3_mixer после вызова функции SDL_Init():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="597943153"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="597943153" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>MIX_Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL_mixer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После функции SDL_SetRenderVSync() добавьте код создания микшера:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="94889781"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="94889781" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; mixer <span class="sy0">=</span> MIX_CreateMixerDevice<span class="br0">&#40;</span>SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK<span class="sy0">,</span> NULL<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>mixer<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create mixer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После создания микшера добавьте код загрузки аудио файла:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="256211216"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="256211216" style="height: 126px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>audiofile <span class="sy0">=</span> <span class="st0">&quot;./assets/audio/Picked Coin Echo 2.wav&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; audio <span class="sy0">=</span> MIX_LoadAudio<span class="br0">&#40;</span>mixer<span class="sy0">,</span> audiofile<span class="sy0">,</span> <span class="kw2">false</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>audio<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Failed to load '%s': %s&quot;</span><span class="sy0">,</span> audiofile<span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppEvent() добавьте код проигрывания аудио по клику:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="286993902"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="286993902" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// printf(&quot;События клика/касания холста\n&quot;);</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>MIX_PlayAudio<span class="br0">&#40;</span>mixer<span class="sy0">,</span> audio<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Failed to play audio: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В функции SDL_AppQuit() добавьте функцию освобождения ресурсов:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="205151261"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="205151261" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL автоматически закроет окно и очистит рендерер</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Эта функция приведет к закрытию аудиоустройства и</span>
&nbsp; &nbsp; <span class="co1">// освобождению всех микшеров и аудиоданных</span>
&nbsp; &nbsp; MIX_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Запустите сборку проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="696674013"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="696674013" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Обновите страницу на браузере Desktop и на мобильном браузере - и там и там услышите звук при клике мыши по холсту на Desktop и при касании экрана на смартфоне</li>
</ul><br />
<h2>Сборка в релиз</h2><br />
<br />
<ul><li>Для сборки в релиз нужно открыть файл &quot;config-web.bat&quot; в редакторе кода и исправить Debug на Release:<br />
<br />
config-web.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="284856909"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="284856909" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команды конфигурирования и сборки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="517780982"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="517780982" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">config-web
build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Вес файлов после сборки в Debug:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="447584150"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="447584150" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">377</span> KB
app.wasm - <span class="nu0">2.16</span> MB</pre></td></tr></table></div></td></tr></tbody></table></div>Вес файлов после сборки в Release:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="668266772"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="668266772" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">app.js - <span class="nu0">184</span> KB
app.wasm - <span class="nu0">1.53</span> MB</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Развёртывание на бесплатном хостинге Vercel</h2><br />
<br />
<ul><li>Скачайте установщик Node.js и установите: <a rel="nofollow noopener noreferrer" href="https://nodejs.org/en/download" target="_blank" title="https://nodejs.org/en/download">https://nodejs.org/en/download</a></li>
<li>Установите Vercel следующей командой из консоли глобально:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="731235527"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="731235527" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i vercel <span class="re5">-g</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Зарегистрируйтесь на Vercel: <a rel="nofollow noopener noreferrer" href="https://vercel.com/" target="_blank" title="https://vercel.com/">https://vercel.com/</a></li>
<li>Примечание. В стартовом прмер, который скачали в начале, уже есть файл vercel.json для решения проблемы с загрузкой wasm-файла</li>
<li>В консоле в корне проекта выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="424356784"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="424356784" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="kw2">login</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Выполните команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="44538105"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="44538105" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Будут заданы вопросы в консоли. На все вопросы ответьте &quot;y&quot; (yes) (или нажимайте Enter), кроме этих вопросов, на которые нужно ответить &quot;n&quot; (no):<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="362699193"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="362699193" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">Link to existing project? no
Want to modify these settings? no
Do you want to change additional project settings? no</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В консоль будет выведен адрес вашего приложения: <a rel="nofollow noopener noreferrer" href="https://start-play-sound-wasm-sdl3-c.vercel.app" target="_blank" title="https://start-play-sound-wasm-sdl3-c.vercel.app">https://start-play-sound-wasm-sdl3-c.vercel.app</a></li>
<li>Примечание. Когда вы что-то измените в проекте и захотите загрузить изменённое приложение на сервер, то введите команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="913229392"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="913229392" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="re5">--prod</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11498&amp;d=1770551420" rel="Lightbox" id="attachment11498" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11498&amp;thumb=1&amp;d=1770551420" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 69d48c79-af26-4ac3-948b-6cd45d56b939.png
Просмотров: 935
Размер:	4.3 Кб
ID:	11498" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11501&amp;d=1770551983" rel="Lightbox" id="attachment11501" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11501&amp;thumb=1&amp;d=1770551983" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 81114b44-2e99-4781-9ca2-aa6eeaf51845.png
Просмотров: 957
Размер:	14.2 Кб
ID:	11501" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11497&amp;d=1770497144">start-play-sound-wasm-sdl3-c.zip</a> (4.0 Кб, 71 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11499&amp;d=1770551495">SDL3-devel-3.4.0-wasm.zip</a> (1.22 Мб, 72 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11500&amp;d=1770551495">SDL3_mixer-devel-3.1.2-wasm.zip</a> (165.7 Кб, 77 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11502&amp;d=1770562036">Picked Coin Echo 2.zip</a> (350.1 Кб, 69 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11504&amp;d=1770581097">finish-play-sound-wasm-sdl3-c.zip</a> (355.0 Кб, 189 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10750.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств</title>
			<link>https://www.cyberforum.ru/blogs/416874/10741.html</link>
			<pubDate>Sat, 07 Feb 2026 14:31:19 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Браузер Chrome имеет...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса отладки. В этой инструкции подключим мобильное устройство по USB-кабелю к компьютеру. Выведем отладочную информацию и мобильного веб-приложения в консоль браузера Chrome на компьютер.<br />
<br />
<ul><li>Выполните пошаговую инструкцию для создания стартового примера: <a href="https://www.cyberforum.ru/blogs/416874/10738.html">Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве</a> (в начале той инструкции можно скачать результат в виде архива: mouse-and-touch-handlers-sdl3.zip)</li>
<li>По инструкции выше мы создали проект с именем &quot;mouse-and-touch-handlers-sdl3&quot;. Переименуйте папку проекта, добавив в начале имени &quot;debug-&quot;, то есть у вас получится &quot;debug-mouse-and-touch-handlers-sdl3&quot;</li>
<li>Откройте папку с проектом в каком-нибудь редакторе кода, например, в Notepad++ и в Sublime Text 4 (ST4). Скачать ST4 можно здесь: <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a> После установки ST4 нужно добавить в Path папку куда установилась ST4, тогда вы сможете зайти в папку проекта из консоли (например, из Far Manager) и набрать subl + точка вот так:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="485398832"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="485398832" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">subl .</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Так выглядит стартовый пример, открытый в ST4:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11490&amp;a= mp;d=1770461154" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Откройте в редакторе года файл CMakeLists.txt и исправьте название проекта в команде &quot;project()&quot;:<br />
<br />
Было:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="152768531"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="152768531" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">project<span class="br0">&#40;</span>mouse<span class="sy0">-</span>and<span class="sy0">-</span>touch<span class="sy0">-</span>handlers<span class="sy0">-</span>sdl3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Стало:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="674989885"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="674989885" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">project<span class="br0">&#40;</span>debug<span class="sy0">-</span>mouse<span class="sy0">-</span>and<span class="sy0">-</span>touch<span class="sy0">-</span>handlers<span class="sy0">-</span>sdl3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Не забывайте сохранять файлы проекта после редактирования, нажимая Ctrl+S<br />
</li>
</ul><br />
<h2>Активация режима разработчика и отладки на Android по USB-кабелю</h2><br />
<br />
Если у вас не активирован режим разработчика и отладки на Android, то посмотрите, как это делается на вашем смартфоне и вашей версии Android - спросите у Gemini, ChatGPT, DeepSeek и т.д. На моём телефоне Redmi 10 и Android 13 это делается так:<br />
<br />
<ul><li>Находите иконку с настройками &quot;Settings&quot; и нажимаете на неё. Открываются настройки</li>
<li>Нажимаете &quot;About phone&quot;</li>
<li>Далее, нажимаете на &quot;MIUI version&quot; подряд семь раз. Режим разработчика активирован</li>
<li>Вернитесь назад в главные настройки</li>
<li>Пролистайте почти в самый вниз</li>
<li>Выберите &quot;Additional settings&quot;</li>
<li>Пролистайте до самой последней строки под названием &quot;Developer options&quot;</li>
<li>Пролистайте немного вниз и увидите опцию &quot;USB debugging&quot;. Включите эту опцию</li>
<li>Отладка по USB-кабелю активирована</li>
</ul><br />
<h2>Сборка проекта в Wasm</h2><br />
<br />
У вас должны быть к этом моменту установлены Emscripten и Cmake, а если нет, то установите по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm</a><br />
<br />
<ul><li>Откройте консоль CMD внутри папки с проектом - можете просто в адресной строке папки Windows набрать &quot;cmd&quot; (без ковычек) и нажать Enter</li>
<li>Введите команду конфигурирования, запустив bash-файл, который находится в папке проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="182437824"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="182437824" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команду сборки (это батник):<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="131023107"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="131023107" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После сборки в папке &quot;public/js&quot; появятся два файла: &quot;app.js&quot; и &quot;app.wasm&quot;. Файл &quot;app.js&quot; служит промежуточным звеном для подключения файла &quot;app.wasm&quot;. Файл &quot;app.js&quot; подключается в файле &quot;public/index.html&quot;</li>
</ul><br />
<h2>Запуск Wasm-проекта локально на Android и Desktop с помощью локального сервера http-server</h2><br />
<br />
Примечание. Если у вас не установлены Node.js и пакет http-server, то установите их по инструкции:<br />
<ul><li>Скачайте Node.js по ссылке <a rel="nofollow noopener noreferrer" href="https://nodejs.org/en/download" target="_blank" title="https://nodejs.org/en/download">https://nodejs.org/en/download</a> и установите с опциями по умолчанию</li>
<li>В CMD введите команду для глобально установки (ключ -g) пакета http-server:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="285664351"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="285664351" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i http-server <span class="re5">-g</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h3>Запуск локального сервера и клиента на Desktop</h3><br />
<ul><li>Если http-server у вас установлен глобально, то скопируйте команду запуска локального сервера:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="326148230"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="326148230" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В консоль будут выведены адреса, у меня такие:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="561056029"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="561056029" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http://192.168.1.65:<span class="nu0">8080</span>
&nbsp; http://127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Вместо &quot;127.0.0.1&quot; можно использовать &quot;localhost&quot; и набрать в браузере на Desktop:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="379739614"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="379739614" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Вы увидите, что приложение запущено в браузере. Вы можете открыть консоль разработчика в браузера (Ctrl+Shift+J в Chrome) и кликнуть по холсту. В браузер будут выведено сообщение &quot;Клик мышью&quot;, благоданя обработчику клика мыши:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="475805152"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="475805152" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Клик мышью<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Касание экрана<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h3>Запуск клиента на Android с помощью локального сервера на Desktop</h3><br />
<br />
<ul><li>Подключите смартфон по USB-кабелю к компьютеру</li>
<li>На смартфоне откройте Chrome и введите &quot;localhost:8080&quot; (без ковычек). Вы увидите надпись:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="98450325"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="98450325" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">This site can't be reached</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В браузере на компьютере перейдите по адресу: chrome://inspect</li>
<li>Нажмите на кнопку &quot;Port forwarding...&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11491&amp;a= mp;d=1770468171" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>В открывшемся диалоговом окне наберите &quot;8080&quot;, &quot;localhost:8080&quot;, поставьте галочку &quot;Enable port forwarding&quot; и нажмите кнопку &quot;Done&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11493 tc=1&amp;d=1770474377" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Возьмите смартфон и обновите страницу мобильного браузера</li>
<li>Примечание. Обновить окно браузера на смартфоне можно несколькими способами: нажать кнопку &quot;Reload&quot;, провести пальцем сверху вниз (но не на холсте, а рядом или ниже), либо три точки в правом верхнем углу смартфона и выбрать кнопку с круговой стрелкой</li>
<li>Вы увидите веб-приложение запущенное в браузере мобильного устройства</li>
</ul><br />
<h3>Вывод консоли браузера мобильного устройства в консоль браузера компьютера</h3><br />
<br />
<ul><li>Убедитесь, что телефон подключен по USB и страница открыта на нем</li>
<li>На компьютере в Chrome перейдите по знакомому адресу: chrome://inspect/#devices</li>
<li>Найдите в списке ваше устройство и открытую вкладку с адресом localhost:8080</li>
<li>Нажмите на синюю ссылку inspect под названием вкладки:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11494&amp;a= mp;d=1770470504" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>Откроется новое окно. Это и есть полноценные инструменты разработчика для вашего мобильного браузера. Здесь вы будете видеть тоже самое, что и на телефоне, а так же будет выведена консоль браузера, куда будут выводиться сообщения из мобильного браузера. Здесь же в этом окне вы можете обновлять мобильное приложение после перекомпиляции. Вы можете попробовать прикоснуться к холсту на мобильном устройстве и в консоль браузера на компьютере будет выводиться:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="747520140"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="747520140" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">Клик мышью
Касание экрана</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h3>Вывод в консоль браузера на компьютере из мобильного браузера по Wi-Fi (без USB-кабеля)</h3><br />
<br />
<ul><li>Отключите USB-кабель</li>
<li>Обратите внимание, что http-server вывел в консоль адрес 192.168.1.65:8080 при запуске (у вас будет другой адрес, но примерно такого же вида)<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="458731402"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="458731402" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http://192.168.1.65:<span class="nu0">8080</span>
&nbsp; http://127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите этот адрес в Chrome на мобильном устройстве. Вы увидите запущенное приложение</li>
<li>Зайдите в настройки телефона</li>
<li>Пролистайте вниз и нажмите &quot;Additional settings&quot;</li>
<li>Пролистайте в самый низ и нажмите &quot;Developer options&quot;</li>
<li>Пролистайте немного до &quot;Wireless debugging&quot; и включите эту опцию. Здесь вы увидите IP и порт</li>
<li>Установите Android SDK если он у вас не установлен: <a href="https://www.cyberforum.ru/blogs/416874/10726.html">Установка Android SDK</a></li>
<li>Выполните команду в консоли:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="33995441"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="33995441" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">adb connect <span class="sy0">&lt;</span>IP_телефона<span class="sy0">&gt;</span>:<span class="sy0">&lt;</span>порт<span class="sy0">&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>На компьютере в Chrome перейдите по знакомому адресу: chrome://inspect/#devices и подождите 10-15 секунд</li>
<li>Нажмите на ссылку &quot;inspect&quot;:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11495&amp;a= mp;d=1770472730" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
<li>На компьютере откроется окно, где вы будете видеть тоже самое, что и на телефоне, а так же будет выведена консоль браузера, куда будут выводиться сообщения из мобильного браузера. Здесь же в этом окне вы можете обновлять мобильное приложение после перекомпиляции. Вы можете попробовать прикоснуться к холсту на мобильном устройстве и в консоль браузера на компьютере будет выводиться:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="67785355"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="67785355" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">Клик мышью
Касание экрана</pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h2>Примечание Gemini по поводу выбора отладки веб-приложений на мобильном устройстве по USB-кабелю и по Wi-Fi</h2><br />
<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message"><h3>Почему через USB (localhost) лучше</h3><br />
<br />
Раз вы уже настроили Port Forwarding, я настоятельно рекомендую остаться на кабеле. Вот 3 причины, почему «Inspect по Wi-Fi» — это боль:<br />
<ul><li>Потеря пакетов: Wi-Fi вносит задержки в передачу логов. Вы кликаете на экран, а сообщение в консоли на ПК появляется через секунду</li>
<li>Загрузка CPU: Телефон тратит много энергии на поддержание беспроводного отладочного моста</li>
<li>Сложность: При каждом переподключении к Wi-Fi IP-адрес или порт отладки могут меняться.</li>
</ul><br />
<h3>Как пользоваться Inspect прямо сейчас (по USB)</h3><br />
<ul><li>Убедитесь, что в chrome://inspect/#devices стоит галочка &quot;Discover USB devices&quot;</li>
<li>Если телефон подключен, но списка вкладок нет — проверьте экран телефона. Там может висеть запрос: «Разрешить отладку с этого компьютера?». Нажмите «ОК»</li>
<li>Как только вы увидите свою вкладку localhost:8080, нажмите inspect</li>
</ul><br />
<h3>Что делать, если &quot;inspect&quot; открывается, но там белый экран?</h3><br />
<br />
Иногда окно инспектора само не может загрузиться. В этом случае:<br />
<ul><li>Закройте окно инспектора</li>
<li>Нажмите &quot;focus tab&quot; в списке устройств (рядом с кнопкой inspect)</li>
<li>Затем снова нажмите inspect</li>
</ul><br />
Если сайт на Android открывается по Wi-Fi (192.168...), а инспектор — нет, это нормально. Для работы инспектора по сети нужна предварительная команда через adb</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table><h2>Исправление логической ошибки в программе</h2><br />
<br />
В стартовом примере есть логическая ошибка. Когда вы касаетесь экрана по холсту в отладочном инспекторе Chrome на компьютере, то в консоль инспектора выводятся две строки:<br />
<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="358224826"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="358224826" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">Клик мышью
Касание экрана</pre></td></tr></table></div></td></tr></tbody></table></div>Но по логике, мы хотим, чтобы в браузере Desktop приложение выводило &quot;Клик мышью&quot;, а в мобильном браузере выводило &quot;Касание экрана&quot;. Для исправления нужно добавить эту настройку в main.c перед созданием окна:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="190302787"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="190302787" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Отключаем генерацию событий мыши из касаний пальцем</span>
&nbsp; &nbsp; SDL_SetHint<span class="br0">&#40;</span>SDL_HINT_TOUCH_MOUSE_EVENTS<span class="sy0">,</span> <span class="st0">&quot;0&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div><ul><li>Сохраняем изменения в main.c (Ctrl+S)</li>
<li>Открываем новую CMD в папке проекта, чтобы не останавливать локальные сервер и набираем команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="763362845"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="763362845" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В инспекторе на компьютере обновляем страницу, нажимая в левом верхнем углу закруглённую стрелку</li>
<li>Касаемся холста на смартфоне и видим в инспекторе, что выводится сообщение &quot;Касание экрана&quot;</li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11490&amp;d=1770461154" rel="Lightbox" id="attachment11490" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11490&amp;thumb=1&amp;d=1770461154" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 8c0a7c00-4afb-4e58-9451-59b5b9f6b925.png
Просмотров: 1184
Размер:	7.8 Кб
ID:	11490" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11491&amp;d=1770468171" rel="Lightbox" id="attachment11491" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11491&amp;thumb=1&amp;d=1770468171" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: bf803653-513e-4abc-9a42-380e73c7e8c3.png
Просмотров: 1168
Размер:	8.0 Кб
ID:	11491" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11493&amp;d=1770470043" rel="Lightbox" id="attachment11493" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11493&amp;thumb=1&amp;d=1770470043" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 0d655c42-1a78-4feb-9fca-d840b0af37af.png
Просмотров: 272
Размер:	7.0 Кб
ID:	11493" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11494&amp;d=1770470504" rel="Lightbox" id="attachment11494" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11494&amp;thumb=1&amp;d=1770470504" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 26dc13ec-11bd-464a-a569-c291179a2e0c.png
Просмотров: 1178
Размер:	16.6 Кб
ID:	11494" style="margin: 5px" /></a><br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11495&amp;d=1770472730" rel="Lightbox" id="attachment11495" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11495&amp;thumb=1&amp;d=1770472730" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 70cf9b97-f33b-48bd-a05e-f6dad3e1307c.png
Просмотров: 1160
Размер:	16.9 Кб
ID:	11495" style="margin: 5px" /></a><br />

				   </div>
			   </div></div>

]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10741.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве</title>
			<link>https://www.cyberforum.ru/blogs/416874/10738.html</link>
			<pubDate>Sun, 01 Feb 2026 21:05:30 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Для начала пошагово...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик касания экрана мобильного устройства, чтобы один и тот же проект работал в браузере ПК и в браузере мобильного устройства. Исходники того, что получилось: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11483&amp;d=1769980901">mouse-and-touch-handlers-sdl3.zip</a><br />
<br />
Если у вас не установлены Emscripten SDK и CMake, то установите их по следующей инструкции и выполните &quot;hello world&quot; инструкцию там же: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a><br />
<br />
<h3>Установка библиотеки SDL3 для Wasm</h3><br />
<br />
<ul><li>Скачайте SDL3 для Wasm: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11479&amp;d=1769979538">SDL3-devel-3.4.0-wasm.zip</a> Библиотека была собрана из исходников с помощью emsdk3 4.0.15</li>
<li>Создайте пустую папку с именем &quot;libs&quot;, например, на диске C</li>
<li>Извлеките архив с библиотекой в папку &quot;libs&quot;</li>
<li>Установка библиотеки SDL3 для Wasm закончена. Теперь можно использовать этот путь в своих проектах в файле CMakeListst.txt, чтобы указывать точное местоположение конфигурационных файлов библиотеки SDL3:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="124405796"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="124405796" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">set<span class="br0">&#40;</span>SDL3_DIR &quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Команда &quot;set&quot; создаёт переменную SDL3_DIR и устанавливает ей значение &quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;</li>
<li>Примечание 2. Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR</li>
</ul><br />
<h3>Настройка проекта</h3><br />
<br />
<ul><li>Создайте пустую папку с именем &quot;mouse-and-touch-handlers-sdl3&quot;. Это будет папка для проекта</li>
<li>Откройте созданную папку в каком-нибудь редакторе кода, например, в Notepad++ и Sublime Text4 (ST4): <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a> Если у вас путь к ST4 находится в Path, то отройте консоль (CMD) в созданной папке &quot;mouse-and-touch-handlers-sdl3&quot; и введите команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="814939322"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="814939322" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">subl .</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Точка после subl означает - открыть <b>текущую папку</b> в Sublime Text 4</li>
</ul><br />
<h4>Пошаговое создание файла CMakeLists.txt</h4><br />
<br />
<ul><li>В корне проекта создайте файл CMakeLists.txt</li>
<li>Наберите строку указания минимальной версии CMake:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="177794378"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="177794378" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте строку, которая задаёт название проекта в системе CMake:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="110449393"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="110449393" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">project<span class="br0">&#40;</span>mouse-and-touch-handlers-sdl3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте строку, которая задаёт название для генерируемых исполняемых файлов:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="140068367"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="140068367" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. В Windows был бы сгенерирован файл app.exe, а в вебе будет app.js / app.wasm</li>
<li>Добавьте строку, которая задаёт используемый стандарт языка Си:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="465312781"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="465312781" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">set<span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Для C++ эквивалентом будет строка &quot;set(CMAKE_CXX_STANDARD 20)&quot;</li>
<li>Добавьте строку, которая указывает точное местоположение конфигурационных файлов библиотеки SDL3:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="934055988"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="934055988" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">set<span class="br0">&#40;</span>SDL3_DIR &quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте строку, которая проверяет наличие библиотеки SDL3 в системе<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="209592649"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="209592649" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Команда find_package() проверяет наличие библиотеки SDL3 в системе по установленному ранее пути (SDL3_DIR)</li>
<li>Добавьте строку, которая привязывает библиотеку SDL3 к нашему приложению<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="698708966"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="698708966" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3::SDL3<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте код для подключения файла исходного кода main.c:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="410289370"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="410289370" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src/main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
В итоге должен получиться файл:<br />
<br />
CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="466595535"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="466595535" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>mouse-and-touch-handlers-sdl3<span class="br0">&#41;</span>
&nbsp;
# Задаем название будущего приложения <span class="br0">&#40;</span>в Windows это был бы app.exe, а в вебе будет app.js / app.wasm<span class="br0">&#41;</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
# Устанавливаем стандарт C
set<span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
# Указываем точное местоположение конфигурационных файлов библиотеки SDL3
# Имя переменной должно строго соответствовать: НазваниеБиблиотеки_DIR
set<span class="br0">&#40;</span>SDL3_DIR &quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;<span class="br0">&#41;</span>
&nbsp;
# Проверяем наличие библиотеки SDL3 в системе
# Если она не будет найдены, CMake прервет настройку с ошибкой
# REQUIRED - переводится, как «обязательно» или «требуется»
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
&nbsp;
# Добавляем исходный код к проекту
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src/main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div><h3>Пошаговое создание файла main.c</h3><br />
<br />
<ul><li>Создайте папку &quot;src&quot;, а в ней файл &quot;main.c&quot;</li>
<li>Откройте в файл src/main.c в редакторе кода</li>
<li>Примечание. Код лучше не копировать и вставлять, а набирать вручную - так лучше запоминается</li>
<li>Добавьте строку для переключения на режим &quot;Использовать SDL3-callback вместо main()&quot;<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="960603328"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="960603328" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте строки подключения необходимых заголовочных файлов SDL3:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="557784470"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="557784470" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создайте две глобальные переменные: window - окно и renderer - рисовальщик:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="801004137"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="801004137" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Ключевое слово static делает переменную видимой только в файле main.c</li>
</ul><br />
<h4>Функция SDL_AppInit() - инициализация</h4><br />
<br />
<ul><li>Напишите функцию SDL_AppInit(), которая будет вызываться библиотекой SDL3 автоматически один раз перед запуском основного цикла приложения:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="919143514"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="919143514" style="height: 318px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. В этой функции вызывается функция SDL_Init() с аргументом SDL_INIT_VIDEO, для инициализации библиотеки SDL3. В случае, если по каким-то причинам инициализация не прошла, то выводится текст ошибки и приложение закрывается</li>
<li>Примечание 2. Функция SDL_CreateWindowAndRenderer() создаёт холст размера 400 на 400 пикселей и возвращает созданные: window и renderer</li>
<li>Примечание 3. Функция SDL_SetRenderVSync() включает вертикальную синхронизацию. Главный цикл приложения будет запущен с той же частотой с которой работает монитор компьютера. Это значительно снижает нагрузку на процессор. На старом ноутбуке эта разница будет примерно такая: 30% CPU с отключенной VSync и 1-3% с включенной VSync<br />
<br />
<h4>Функция SDL_AppEvent() - обработка событий</h4><br />
<br /></li>
<li>Напишите код функции SDL_AppEvent(), которая отвечает за события, а в данном случае за обработку события закрытия окна:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="515874146"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="515874146" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Эта функция отвечает за события в приложении. Например, нажатия кнопок клавиатуры, движение мыши, клик мышью, касание экрана на мобильном устройстве и т.д. В данном случае, пользователь кликает по крестику. Срабатывает функция SDL_AppEvent(). Условие if проверяет какой тип события. Если это тим SDL_EVENT_QUIT, то срабатывает тело условия if и происходит выход из программы с кодом SDL_APP_SUCCESS, то есть сообщаем операционной системе, что выход успешный. Если было какое-то другое событие, то выполнение главного цикла продолжается (return SDL_APP_CONTINUE)<br />
<br />
<h4>Функция SDL_AppIterate() - главный цикл приложения</h4><br />
<br /></li>
<li>Напишите код главного цикла приложения, то есть функцию SDL_AppIterate():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="279936768"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="279936768" style="height: 222px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw here...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. Функция SDL_AppIterate() вызывается библиотекой SDL3 автоматически с частотой равной частоте монитора при включённом VSync. Таким образом, если у вас монитор с частотой 60 Гц, то функция SDL_AppIterate будет вызываться 60 раз в секунд с интервалом примерно 0.016 секунды между вызовами</li>
<li>Примечание 2. Функция SDL_SetRenderDrawColor задаём цвет в формате R, G, B, A (Red - красный, Green - зелёный, Blue - синий, Alpha альфа канал), где каждое значение находится в диапазоне [0, 255]. Последний параметр - это альфа канал - прозрачность: 0 - прозрачный фон, 255 - непрозрачный фон. Цвет (100, 100, 100, 255) - серый, непрозрачный</li>
<li>Примечание 3. Функция SDL_RenderClear() стирает всё с холста и заливает холст заданным цветом, то есть в данном случае серый</li>
<li>Примечание 4. Функция SDL_RenderPresent() - выводит кадр на экран<br />
<br />
<h4>Функция SDL_AppQuit() - освобождение ресурсов</h4><br />
<br /></li>
<li>Напишите код функции под названием SDL_AppQuit(), которая автоматически вызывается библиотекой SDL3 перед завершением приложения, когда пользователь закроет окно:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="927156505"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="927156505" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1"><span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Эта функция нужная для освобождения ресурсов</li>
</ul><br />
<h3>Конфигурирование проекта, компиляция кода и запуск на локальном сервере</h3><br />
<br />
<ul><li>В корне проекта создайте два батника со следующими названиями и содержимым:<br />
<br />
config-web.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="750870713"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="750870713" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div>build-web.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="637085717"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="637085717" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> dist
cmake <span class="re5">--build</span> .
&nbsp;
<span class="kw3">cd</span> ..
<span class="kw2">mkdir</span> public\js
<span class="kw1">set</span> <span class="re2">current_dir</span>=<span class="sy0">%</span>~dp0
copy <span class="st0">&quot;%current_dir%dist\app.wasm&quot;</span> <span class="st0">&quot;%current_dir%public\js&quot;</span>
copy <span class="st0">&quot;%current_dir%dist\app.js&quot;</span> <span class="st0">&quot;%current_dir%public\js&quot;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Батник &quot;config-web.bat&quot; нужно запустить один раз, а дальше во время разработки и отладки запускать батник &quot;build-web.bat&quot; для сборки проекта. После сборки в папке &quot;dist&quot; появятся два файла: &quot;app.js&quot; и &quot;app.wasm&quot;, появится папка &quot;public/js&quot; и оба файла (&quot;app.js&quot; и &quot;app.wasm&quot;) буду автоматически скопированы в папку &quot;public/js&quot;</li>
<li>В корне проекта выполните две команды в консоли, которые запустят батники:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="243155704"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="243155704" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">config-web
build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Можете проверить, что появилась папка &quot;public/js&quot;, в которой находятся два файла: &quot;app.js&quot; и &quot;app.wasm&quot;</li>
<li>Создайте файл &quot;index.html&quot; в папке &quot;public&quot; со следующим содержимым:<br />
<br />
index.html<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="958287232"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="958287232" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1.0&quot;</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">canvas</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;canvas&quot;</span><span class="sy0">&gt;&lt;/</span><span class="kw2">canvas</span><span class="sy0">&gt;</span></span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> async <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./js/app.js&quot;</span><span class="sy0">&gt;</span><span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Здесь создаётся элемент &lt;canvas&gt; c id=&quot;canvas&quot;, который будет использовать SDL3 для рисования. Подключается файл &quot;./js/app.js&quot;. Элемент &lt;meta name=&quot;viewport&quot;... нужен, чтобы в нормальном масштабе отображалось на разных устройствах, например, в браузерах на смартфонах</li>
<li>Запустите локальный сервер командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="892010394"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="892010394" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Перейдите в браузере ПК по адресу:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="485295417"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="485295417" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">localhost:<span class="nu0">8080</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. По Wi-Fi на Android тоже работает</li>
</ul><br />
<h3>Обработчик клика мыши</h3><br />
<br />
<ul><li>Добавьте заголовочный файл для использования функции printf():<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="652386662"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="652386662" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1"><span class="co2">#include &lt;stdio.h&gt;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте обработчик клика мышью и выведите текст в консоль:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="846245745"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="846245745" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Клик мышью<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В результате получился пример:<br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="247504449"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="247504449" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
&nbsp;
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;Example&quot;</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">100</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw here...</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// SDL will clean up the window/renderer for us</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команду для сборки проекта &quot;build-web&quot;</li>
<li>Откройте новую страницу в браузере</li>
<li>Откройте отладочную консоль браузера (Ctrl+Shift+J на Chrome/Edge или Ctrl+Shfit+K)</li>
<li>Перейдите по адресу &quot;localhost:8080&quot;</li>
</ul><br />
[H3]Обработчик касания экрана на смартфоне[/H4]<br />
<br />
<ul><li>Добавьте обработчик касания экрана (тип события SDL_EVENT_FINGER_DOWN) в функцию SDL_AppEvent:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="848264610"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="848264610" style="height: 302px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="de1"><pre class="de1">SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_MOUSE_BUTTON_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Клик мышью<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">else</span> <span class="kw1">if</span><span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_FINGER_DOWN<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Касание экрана<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Если вы перейдёте в отладочную консоль браузера ПК, то вторая кнопка сверху &quot;Toggle device toolbar&quot; переключает на эмуляцию мобильного устройства. Там вы увидите, что срабатывают оба события: SDL_EVENT_MOUSE_BUTTON_DOWN и SDL_EVENT_FINGER_DOWN. Если вам нужно событие клика на Desktop и отдельно одиночного касания экрана на Android, то можно использовать тип события SDL_EVENT_MOUSE_BUTTON_DOWN. Если нужно отдельно касания обрабатывать и отключать события мыши на Android, то можно использовать следующую опцию, которую нужно разместить до строки создания окна:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="432050213"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="432050213" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">&nbsp; &nbsp; <span class="co1">// Отключаем генерацию событий мыши из касаний пальцем</span>
&nbsp; &nbsp; SDL_SetHint<span class="br0">&#40;</span>SDL_HINT_TOUCH_MOUSE_EVENTS<span class="sy0">,</span> <span class="st0">&quot;0&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
<h3>Загрузка приложения на бесплатный хостинг Vercel</h3><br />
<br />
<ul><li>Установите Node.js: <a rel="nofollow noopener noreferrer" href="https://nodejs.org/en/download" target="_blank" title="https://nodejs.org/en/download">https://nodejs.org/en/download</a></li>
<li>Установите Vercel:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="643928783"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="643928783" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i <span class="re5">-g</span> vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Добавьте в корень проекта файл &quot;vercel.json&quot;:<br />
<br />
vercel.json<br />
<br />
<div class="codeblock"><table class="json"><thead><tr><td colspan="2" id="84575425"  class="head">JSON</td></tr></thead><tbody><tr class="li1"><td><div id="84575425" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1"><span class="br0">&#123;</span>
&nbsp; <span class="st0">&quot;headers&quot;</span><span class="sy0">:</span> <span class="br0">&#91;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;source&quot;</span><span class="sy0">:</span> <span class="st0">&quot;/(.*)&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;headers&quot;</span><span class="sy0">:</span> <span class="br0">&#91;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> <span class="st0">&quot;key&quot;</span><span class="sy0">:</span> <span class="st0">&quot;Cross-Origin-Embedder-Policy&quot;</span><span class="sy0">,</span> <span class="st0">&quot;value&quot;</span><span class="sy0">:</span> <span class="st0">&quot;require-corp&quot;</span> <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> <span class="st0">&quot;key&quot;</span><span class="sy0">:</span> <span class="st0">&quot;Cross-Origin-Opener-Policy&quot;</span><span class="sy0">,</span> <span class="st0">&quot;value&quot;</span><span class="sy0">:</span> <span class="st0">&quot;same-origin&quot;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; <span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#93;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Соберите проект в Release, а для этого замените Debug на Release в файле config-web.bat</li>
<li>Сконфигурируйте проект командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="154018588"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="154018588" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">config-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Собирите проект командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="129070381"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="129070381" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команды:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="923519516"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="923519516" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">vercel <span class="kw2">login</span>
vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Будет выведено меню из двух пунктов и нужно будет выбрать второй пункт, нажав кнопку &quot;стрелка вниз&quot; на клавиатуре:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="29167709"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="29167709" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">? Which project?
&nbsp; Search all projects
&gt; Create a new project</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Далее будут выводиться вопросы и вы на каждый вопрос нажимайте Enter</li>
<li>В консоль будет выведена ссылка на ваше приложение в браузере: <a rel="nofollow noopener noreferrer" href="https://mouse-and-touch-handlers-sdl3.vercel.app" target="_blank" title="https://mouse-and-touch-handlers-sdl3.vercel.app">https://mouse-and-touch-handlers-sdl3.vercel.app</a></li>
<li>Примечание. Если вы что-то изменили в приложении и пересобрали его, то достаточно ввести одну команду для перезаливки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="784727364"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="784727364" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="re5">--prod</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ul><br />
Вес приложения в релизе на SDL3:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11480&amp;d=1769979698" border="0" alt="Название: 61799a872638385d41742d3efeeaa986e8afabb0.png
Просмотров: 2238

Размер: 2.7 Кб" style="margin: 5px" /><br />
<br />
Структура проекта:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11481&amp;d=1769979834" border="0" alt="Название: 9b4dc960d2a3e1563f06260a5f7ae942c13e0834.png
Просмотров: 2238

Размер: 3.8 Кб" style="margin: 5px" /></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11479&amp;d=1769979538">SDL3-devel-3.4.0-wasm.zip</a> (1.22 Мб, 138 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11483&amp;d=1769980901">mouse-and-touch-handlers-sdl3.zip</a> (280.6 Кб, 169 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10738.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf</title>
			<link>https://www.cyberforum.ru/blogs/416874/10737.html</link>
			<pubDate>Sat, 31 Jan 2026 21:47:12 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
В этой пошаговой...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на  локальном сервере. Загрузим Release на бесплатный хостинг Vercel из консоли парой консольных команд: &quot;vercel login&quot; и &quot;vercel&quot;. Финальный результат инструкции в браузере: <a rel="nofollow noopener noreferrer" href="https://finish-hello-ttf-wasm-sdl3-c.vercel.app" target="_blank" title="https://finish-hello-ttf-wasm-sdl3-c.vercel.app">запустить демку в один клик</a>. Исходники финальной демки: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11476&amp;d=1769908815">finish-hello-ttf-wasm-sdl3-c.zip</a><br />
<br />
Если у вас не установлены Emscripten SDK и CMake, то установите их по следующей инструкции и выполните &quot;hello world&quot; инструкцию там же: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a><br />
<br />
<ul><li>Скачайте стартовый пример: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11469&amp;d=1769894252">start-hello-ttf-wasm-sdl3-c.zip</a>. Этот пример мы создали в инструкции по установке: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK</a> - обязательно пойдите &quot;hello world&quot; инструкцию там же</li>
<li>Откройте этот пример в каком-нибудь редакторе кода. Например, в Notepad++. Мне больше всего нравится редактор кода Sublime Text 4: <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a>. ST4 почти такой же лёгкий, как Notepad++ и гораздо удобнее. Добавьте путь с ST4 в Path и вы сможете запускать ST4 из консоли, открывая проект в текущей папке, командой: subl . (точка означает, что нужно открыть текущую папку в ST4)<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11468&amp;d=1769891319" border="0" alt="Название: cecfe6687db475bc69135f0f0e7532f3268c6d28.png
Просмотров: 1967

Размер: 5.6 Кб" style="margin: 5px" /></li>
<li>Скачайте архив <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11472&amp;stc=1&amp;d=1769895800">SDL3-devel-3.4.0-wasm.zip</a> - это SDL3-библиотека, которая собрана из исходников для Wasm-проектов с помощью emsdk 4.0.15. У вас должна быть установлена и активирована именно эта версия emsdk</li>
<li>Скачайте архив <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11473&amp;stc=1&amp;d=1769895806">SDL3_ttf-devel-3.2.2-wasm.zip</a> - эта библиотека для SDL3-проектов для работы с TTF-шрифтами, которая собрана для Wasm-проектов с помощью emsdk 4.0.15</li>
<li>Скачайте архив <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11474&amp;stc=1&amp;d=1769895811">freetype-2.13.3-wasm.zip</a> - библиотека FreeType необходима для работы SDL3_ttf</li>
<li>Извлеките архивы в текущую папку и перенесите три извлечённые папки на какой-нибудь локальный диск, наприме, можете создать папку &quot;libs&quot; на системном диске C и скопировать эти папки в папку &quot;libs&quot;</li>
<li>Откройте файл CMakeLists.txt и добавьте код для подключения библиотек SDL3, SDL3_ttf и FreeType (проверьте пути в этом файле - правильные ли они на вашем компьютере):<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="878034277"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="878034277" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-hello-ttf-wasm-sdl3-c<span class="br0">&#41;</span>
&nbsp;
# Задаем название будущего приложения <span class="br0">&#40;</span>в Windows это был бы app.exe, а в вебе будет app.js / app.wasm<span class="br0">&#41;</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
# Устанавливаем стандарт C
set<span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
# Подсказываем CMake, где искать конфигурационные файлы библиотек
set<span class="br0">&#40;</span>SDL3_DIR &quot;C:/libs/SDL3-devel-3.4.0-wasm/lib/cmake/SDL3&quot;<span class="br0">&#41;</span>
set<span class="br0">&#40;</span>SDL3_ttf_DIR &quot;C:/libs/SDL3_ttf-devel-3.2.2-wasm/lib/cmake/SDL3_ttf&quot;<span class="br0">&#41;</span>
set<span class="br0">&#40;</span>FREETYPE_INCLUDE_DIRS &quot;C:/libs/freetype-2.13.3-wasm/include&quot;<span class="br0">&#41;</span>
set<span class="br0">&#40;</span>FREETYPE_LIBRARY &quot;C:/libs/freetype-2.13.3-wasm/lib/libfreetype.a&quot;<span class="br0">&#41;</span>
&nbsp;
# Загружаем настройки пакетов <span class="br0">&#40;</span>параметры компиляции и пути к заголовкам<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
find_package<span class="br0">&#40;</span>SDL3_ttf REQUIRED<span class="br0">&#41;</span>
&nbsp;
# Привязываем библиотеки к нашему приложению <span class="br0">&#40;</span>настройка линковки и путей include<span class="br0">&#41;</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3_ttf::SDL3_ttf SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
# Добавляем исходный код к проекту
target_sources<span class="br0">&#40;</span>app
&nbsp; &nbsp; PRIVATE
&nbsp; &nbsp; src/main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Пример пока пустой (в main.c только базовый код вывода &quot;hello world&quot; в консоль), но проверьте работоспособность. В инструкции по установке Emscripten SDK мы запускали этот пример командами:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="194434062"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="194434062" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">config-web
build-web
http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Локальный сервер выведет адреса, которые скопировать в адресную строку браузера, например, 127.0.0.1:8080 (либо можно ввести localhost:8080)</li>
<li>Перейдите в браузер и введите адрес: localhost:8080 и нажмите Enter</li>
<li>Вы увидите результат работы программы в консоли браузера, если нажмёте: Ctrl+Shift+J в Chrome и Edge, либо Ctrl+Shift+K в FireFox</li>
<li>Запустите в корне папки проекта вторую консоль, чтобы дальше можно было переконфигурировать и собирать проект в этой консоли, а в первой консоли пусть запущен локальные сервер</li>
<li>Откройте файл src/main.c и добавим код с базовыми четырьмя функциями SDL3. Этот код создаёт холст для рисования размеров 400 на 400 пикселя, заливает его тёмно-серым цветом и выводит в консоль версию SDL3: <br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="238803427"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="238803427" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_ttf/SDL_ttf.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="co1">// This function runs once at startup</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>title <span class="sy0">=</span> <span class="st0">&quot;Example&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span>title<span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">400</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Print SDL versions ---</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Compiled SDL3 version: %d.%d.%d<span class="es1">\n</span>&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_MAJOR_VERSION<span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_MINOR_VERSION<span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_MICRO_VERSION<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Get the version of the SDL library linked at runtime</span>
&nbsp; &nbsp; <span class="kw4">int</span> v <span class="sy0">=</span> SDL_GetVersion<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Linked SDL3 version: &nbsp; %d.%d.%d<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> SDL_VERSIONNUM_MAJOR<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_VERSIONNUM_MINOR<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="sy0">,</span> SDL_VERSIONNUM_MICRO<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// This function runs when a new event (mouse input, keypresses, etc) occurs</span>
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// This function runs once per frame, and is the heart of the program</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">50</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// This function runs once at shutdown</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>renderer<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyRenderer<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>window<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyWindow<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; window <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте в редакторе кода файл &quot;public/index.html&quot; и добавьте элемент &lt;canvas&gt; и удалите элемент &lt;title&gt; (потому что Title задаются в функции SDL_CreateWindowAndRenderer - в первом аргументе этой функции):<br />
<br />
index.html<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="286975486"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="286975486" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1.0&quot;</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">canvas</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;canvas&quot;</span><span class="sy0">&gt;&lt;/</span><span class="kw2">canvas</span><span class="sy0">&gt;</span></span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> async <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./js/app.js&quot;</span><span class="sy0">&gt;</span><span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команды конфигурирования и сборки:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="972670656"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="972670656" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">config-web
build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Перейдите в браузер и введите адрес: localhost:8080 и нажмите Enter</li>
<li>Вы увидите холст размером 400 на 400 пикселей тёрмно-серого цвета. Если откроете консоль браузера, то увидите вывод версии SDL3:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="60581237"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="60581237" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">Compiled SDL3 version: 3.4.0
Linked SDL3 version: &nbsp; 3.4.0</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Скачайте бесплатный шрифт TTF: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11470&amp;d=1769894261">LiberationSans-Regular.zip</a> (файл был взят по <a rel="nofollow noopener noreferrer" href="https://github.com/liberationfonts/liberation-fonts/releases/tag/2.1.5" target="_blank" title="https://github.com/liberationfonts/liberation-fonts/releases/tag/2.1.5">ссылке</a>)</li>
<li>В корне проекта создайте папку &quot;assets&quot;, а в внутри этой папки создайте папку &quot;fonts&quot;</li>
<li>Перенесите извлечённый файл LiberationSans-Regular.ttf в папку &quot;assets/fonts&quot;</li>
<li>Откройте файл CMakeLists.txt и скопируйте код для загрузки TTF файла в конец файла CMakeLists.txt:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="56212302"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="56212302" style="height: 94px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
</pre></td><td class="de1"><pre class="de1">if <span class="br0">&#40;</span>EMSCRIPTEN<span class="br0">&#41;</span>
&nbsp; &nbsp; target_link_options<span class="br0">&#40;</span>&quot;app&quot; PRIVATE &quot;SHELL:--embed-file $<span class="br0">&#123;</span>CMAKE_CURRENT_SOURCE_DIR<span class="br0">&#125;</span>/assets/fonts/LiberationSans-Regular.ttf@/assets/fonts/LiberationSans-Regular.ttf&quot;<span class="br0">&#41;</span>
&nbsp; &nbsp; set_property<span class="br0">&#40;</span>TARGET &quot;app&quot; APPEND PROPERTY LINK_DEPENDS &quot;$<span class="br0">&#123;</span>CMAKE_CURRENT_SOURCE_DIR<span class="br0">&#125;</span>/assets/fonts/LiberationSans-Regular.ttf&quot;<span class="br0">&#41;</span>
endif<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Таким образом можно загружать любые ассеты: картинки, звуки, JSON-файлы и т.д. - просто копируйте код выше и меняйте пути</li>
<li>Замените весь код main.c на следующий код, который выводит текст &quot;Привет из WebAssembly!&quot; зелёного цвета размера 28 на холст:<br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="949262436"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="949262436" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
</pre></td><td class="de1"><pre class="de1"><span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 // Use the callbacks instead of main()</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
<span class="co2">#include &lt;SDL3_ttf/SDL_ttf.h&gt;</span>
<span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="co1">// We will use this renderer to draw into this window every frame</span>
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Texture <span class="sy0">*</span>texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="co1">// This function runs once at startup</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Initialize the TTF library</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>TTF_Init<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize TTF: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy0">*</span>title <span class="sy0">=</span> <span class="st0">&quot;English Text (SDL3 / C)&quot;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span>title<span class="sy0">,</span> <span class="nu0">350</span><span class="sy0">,</span> <span class="nu0">350</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- Print SDL versions ---</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Compiled SDL3 version: %d.%d.%d<span class="es1">\n</span>&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_MAJOR_VERSION<span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_MINOR_VERSION<span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_MICRO_VERSION<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="co1">// Get the version of the SDL library linked at runtime</span>
&nbsp; &nbsp; <span class="kw4">int</span> v <span class="sy0">=</span> SDL_GetVersion<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Linked SDL3 version: &nbsp; %d.%d.%d<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> SDL_VERSIONNUM_MAJOR<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_VERSIONNUM_MINOR<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="sy0">,</span> SDL_VERSIONNUM_MICRO<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// --- SDL3_ttf version ---</span>
&nbsp; &nbsp; v <span class="sy0">=</span> TTF_Version<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">int</span> major <span class="sy0">=</span> SDL_VERSIONNUM_MAJOR<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">int</span> minor <span class="sy0">=</span> SDL_VERSIONNUM_MINOR<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">int</span> micro <span class="sy0">=</span> SDL_VERSIONNUM_MICRO<span class="br0">&#40;</span>v<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;SDL3_ttf version: &nbsp; &nbsp; &nbsp;%d.%d.%d<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> major<span class="sy0">,</span> minor<span class="sy0">,</span> micro<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; TTF_Font <span class="sy0">*</span>font <span class="sy0">=</span> TTF_OpenFont<span class="br0">&#40;</span><span class="st0">&quot;assets/fonts/LiberationSans-Regular.ttf&quot;</span><span class="sy0">,</span> <span class="nu0">28</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>font<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;TTF_OpenFont failed: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_Color textColor <span class="sy0">=</span> <span class="br0">&#40;</span>SDL_Color<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">255</span><span class="sy0">,</span> <span class="nu0">0</span> <span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_Surface <span class="sy0">*</span>surface <span class="sy0">=</span> TTF_RenderText_Blended<span class="br0">&#40;</span>font<span class="sy0">,</span> <span class="st0">&quot;Привет из WebAssembly!&quot;</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> textColor<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; texture <span class="sy0">=</span> SDL_CreateTextureFromSurface<span class="br0">&#40;</span>renderer<span class="sy0">,</span> surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_DestroySurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// This function runs when a new event (mouse input, keypresses, etc) occurs</span>
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="co1">// End the program, reporting success to the OS</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// This function runs once per frame, and is the heart of the program</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Set the position where you want to draw the text</span>
&nbsp; &nbsp; <span class="kw4">float</span> x <span class="sy0">=</span> <span class="nu0">10</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">float</span> y <span class="sy0">=</span> <span class="nu0">10</span>.<span class="me1">f</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Create a rectangle to hold the texture dimensions</span>
&nbsp; &nbsp; SDL_FRect rect<span class="sy0">;</span>
&nbsp; &nbsp; SDL_GetTextureSize<span class="br0">&#40;</span>texture<span class="sy0">,</span> <span class="sy0">&amp;</span>rect.<span class="me1">w</span><span class="sy0">,</span> <span class="sy0">&amp;</span>rect.<span class="me1">h</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; rect.<span class="me1">x</span> <span class="sy0">=</span> x<span class="sy0">;</span>
&nbsp; &nbsp; rect.<span class="me1">y</span> <span class="sy0">=</span> y<span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// SDL_RenderTexture(renderer, texture, NULL, NULL);</span>
&nbsp; &nbsp; <span class="co1">// Clear the screen</span>
&nbsp; &nbsp; SDL_SetRenderDrawColor<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">255</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Draw the text</span>
&nbsp; &nbsp; SDL_RenderTexture<span class="br0">&#40;</span>renderer<span class="sy0">,</span> texture<span class="sy0">,</span> NULL<span class="sy0">,</span> <span class="sy0">&amp;</span>rect<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Update the screen</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// This function runs once at shutdown</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>texture<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyTexture<span class="br0">&#40;</span>texture<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; texture <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>renderer<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyRenderer<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>window<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_DestroyWindow<span class="br0">&#40;</span>window<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; window <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; TTF_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Ещё код выше выводит в консоль версии SDL3 и SDL3_ttf:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="622527749"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="622527749" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">Compiled SDL3 version: 3.4.0
Linked SDL3 version: &nbsp; 3.4.0
SDL3_ttf version: &nbsp; &nbsp; &nbsp;3.2.2</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Не смотря на то, что были изменения в файле CMakeLists.txt конфигурировать проект командой config-web не нужно. Просто введите команду для сборки:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="223482918"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="223482918" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Обновите страницу браузера и вы увидите результат вывода текста в окне браузера:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11471&amp;a= mp;d=1769895599" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /></li>
</ul><br />
<h3>Запуск веб-приложения на Android на локальном сервере</h3><br />
<br />
<ul><li>Обратите внимание, что локальный сервер http-server выводит адреса, например, у меня:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="966716197"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="966716197" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http://100.116.245.193:<span class="nu0">8080</span>
&nbsp; http://192.168.56.1:<span class="nu0">8080</span>
&nbsp; http://127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Вы можете взять телефон, который подключён к Wi-Fi и ввести в его браузере адрес 192.168.56.1:8080 и приложение запустится на Android</li>
</ul><br />
<h3>Загрузка веб-приложения на бесплатный хостинг Vercel из консоли</h3><br />
<br />
<ul><li>Загрузите это веб-приложение на бесплатный хостинг Vercel по следующей инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake</a> (пролистайте до &quot;Загрузка веб-приложения на бесплатный хостинг Vercel&quot;)</li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюра</div>
				   <div class="spoiler-body">
					   <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11471&amp;d=1769895599" rel="Lightbox" id="attachment11471" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11471&amp;thumb=1&amp;d=1769895599" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 310386be29a8adbce84b534aac12b0c1bf1aedbe.png
Просмотров: 2025
Размер:	2.7 Кб
ID:	11471" style="margin: 5px" /></a>
				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11469&amp;d=1769894252">start-hello-ttf-wasm-sdl3-c.zip</a> (3.0 Кб, 66 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11470&amp;d=1769894261">LiberationSans-Regular.zip</a> (206.0 Кб, 64 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11472&amp;d=1769895800">SDL3-devel-3.4.0-wasm.zip</a> (1.22 Мб, 146 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11473&amp;d=1769895806">SDL3_ttf-devel-3.2.2-wasm.zip</a> (62.0 Кб, 165 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11474&amp;d=1769895811">freetype-2.13.3-wasm.zip</a> (1.20 Мб, 168 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11476&amp;d=1769908815">finish-hello-ttf-wasm-sdl3-c.zip</a> (211.0 Кб, 191 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10737.html</guid>
		</item>
		<item>
			<title>SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли в WebAssembly (Wasm)</title>
			<link>https://www.cyberforum.ru/blogs/416874/10736.html</link>
			<pubDate>Fri, 30 Jan 2026 20:45:27 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Финальный код:...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Финальный код: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11822&amp;d=1774908053">finish-hello-wasm-sdl3-c.zip</a><br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11823&amp;d=1774908228" border="0" alt="Название: 693b6f07-c865-4613-88b4-b0e812a904bf.png
Просмотров: 7077

Размер: 2.0 Кб" style="margin: 5px" /><br />
<br />
QR-код для запуска на смартфонах:<br />
<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11821&amp;d=1774907966" border="0" alt="Название: 010516df-4372-49e1-8b0a-ffcb04494b76.png
Просмотров: 7081

Размер: 4.6 Кб" style="margin: 5px" /><br />
<br />
<a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/wasm/sdl3/finish-hello-wasm-sdl3-c/" target="_blank" title="https://8observer8.github.io/wasm/sdl3/finish-hello-wasm-sdl3-c/">Демка в браузере</a><br />
<br />
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/tree/main/examples" target="_blank" title="https://github.com/libsdl-org/SDL/tree/main/examples">examples</a> (кстати, они все на Си), то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main() отсутствует:<br />
<ul><li>SDL_AppInit (Initialization) - эта функция срабатывает один раз самой первой.</li>
<li>SDL_AppEvent (Event Handler) - эта функция срабатывает каждый раз, когда происходит какое-то событие, например, нажатие клавиши, движение мышью, клик мышью, изменение размеров окна и т.д.</li>
<li>SDL_AppIterate (Main Loop) - эта функция срабатывает множество раз в секунду. Здесь можно рассчитать dt (delta time) и сделать анимацию, скорость которой не будет зависеть от числа кадров в секунду, который поддерживает монитор.</li>
<li>SDL_AppQuit (Clean up) - эта функция сработает один раз перед закрытием приложения. Здесь нужно располагать код для освобождения ресурсов.</li>
</ul><br />
Эти функции позволяют собирать один и тот же код для Android, Desktop и WebAssembly без лишних #ifdef и дублирования логики - например, без специфичного для браузера цикла <code class="inlinecode">emscripten_set_main_loop</code> при сборке через Emscripten. То есть кодовая база на SDL3-callbacks будет одинаковая для сборки в .exe, .apk, .wasm и т.д.<br />
<br />
Рассмотрим пример <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/blob/main/examples/renderer/01-clear/clear.c" target="_blank" title="https://github.com/libsdl-org/SDL/blob/main/examples/renderer/01-clear/clear.c">01-clear</a> в файле clear.c. Я попросил Gemini 3 перевести комментарии на русский, не меняя ничего в коде, даже отступы:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="413893949"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="413893949" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
</pre></td><td class="de1"><pre class="de1"><span class="coMULTI">/*</span>
<span class="coMULTI">&nbsp;* Этот пример кода создает окно и рендерер SDL, а затем очищает</span>
<span class="coMULTI">&nbsp;* окно разным цветом в каждом кадре, так что вы фактически получите окно,</span>
<span class="coMULTI">&nbsp;* цвет которого плавно меняется.</span>
<span class="coMULTI">&nbsp;*</span>
<span class="coMULTI">&nbsp;* Этот код является общественным достоянием. Не стесняйтесь использовать его в любых целях!</span>
<span class="coMULTI">&nbsp;*/</span>
&nbsp;
<span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 &nbsp;/* использовать функции обратного вызова вместо main() */</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
&nbsp;
<span class="coMULTI">/* Мы будем использовать этот рендерер для отрисовки в этом окне в каждом кадре. */</span>
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз при запуске. */</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_SetAppMetadata<span class="br0">&#40;</span><span class="st0">&quot;Example Renderer Clear&quot;</span><span class="sy0">,</span> <span class="st0">&quot;1.0&quot;</span><span class="sy0">,</span> <span class="st0">&quot;com.example.renderer-clear&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;examples/renderer/clear&quot;</span><span class="sy0">,</span> <span class="nu0">640</span><span class="sy0">,</span> <span class="nu0">480</span><span class="sy0">,</span> SDL_WINDOW_RESIZABLE<span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_SetRenderLogicalPresentation<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">640</span><span class="sy0">,</span> <span class="nu0">480</span><span class="sy0">,</span> SDL_LOGICAL_PRESENTATION_LETTERBOX<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем выполнение программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается, когда происходит новое событие (ввод мыши, нажатия клавиш и т. д.). */</span>
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* завершаем программу, сообщая ОС об успешном завершении. */</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем выполнение программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз за кадр и является сердцем программы. */</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">double</span> now <span class="sy0">=</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu16">1000.0</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* преобразуем миллисекунды в секунды. */</span>
&nbsp; &nbsp; <span class="coMULTI">/* выбираем цвет для кадра, который будем рисовать. Трюк с синусоидой заставляет цвета плавно сменять друг друга. */</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> red <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> green <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now <span class="sy0">+</span> SDL_PI_D <span class="sy0">*</span> <span class="nu0">2</span> <span class="sy0">/</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> blue <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now <span class="sy0">+</span> SDL_PI_D <span class="sy0">*</span> <span class="nu0">4</span> <span class="sy0">/</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColorFloat<span class="br0">&#40;</span>renderer<span class="sy0">,</span> red<span class="sy0">,</span> green<span class="sy0">,</span> blue<span class="sy0">,</span> SDL_ALPHA_OPAQUE_FLOAT<span class="br0">&#41;</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* новый цвет, полная непрозрачность. */</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* очищаем окно цветом отрисовки. */</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* выводим свежеочищенный рендер на экран. */</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> &nbsp;<span class="coMULTI">/* продолжаем выполнение программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз при завершении работы. */</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="coMULTI">/* SDL сама очистит окно/рендерер за нас. */</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>Далее мы по шагам рассмотрим, как собрать этот пример в WASM, запустить в браузере локально и загрузить на бесплатный хостинг Vercel из командной строки.<br />
<br />
<h2>Код стартового примера</h2><br />
<br />
<ul><li>Скачайте стартовый пример: <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11819&amp;d=1774898333">start-hello-wasm-sdl3-c.zip</a></li>
<li>Код стартового примера:<br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="918901132"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="918901132" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="de1"><pre class="de1"><span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &lt;emscripten.h&gt;</span>
&nbsp;
<span class="co1">// Функция, которая будет вызываться браузером каждую итерацию (фрейм)</span>
<span class="kw4">void</span> loop<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Здесь обычно обрабатывается ввод пользователя или обновление кадра</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">int</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Привет из WebAssembly!<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="co1">// Устанавливает главный цикл приложения. </span>
&nbsp; &nbsp; <span class="co1">// 0 — использовать стандартную частоту кадров браузера.</span>
&nbsp; &nbsp; <span class="co1">// 1 — имитировать бесконечный цикл (предотвращает выход из main).</span>
&nbsp; &nbsp; emscripten_set_main_loop<span class="br0">&#40;</span>loop<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span> 
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div>CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="677091809"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="677091809" style="height: 286px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-hello-wasm-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C (обязательно перед add_executable)</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">17</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD_REQUIRED ON<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а</span>
<span class="co0"># в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исполняемый файл в сборку</span>
target_sources<span class="br0">&#40;</span>app
PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div>index.html<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="319743179"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="319743179" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1.0&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>Hello Wasm<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> async <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./js/app.js&quot;</span><span class="sy0">&gt;</span><span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Эта программа выводит строку &quot;Привет из WebAssembly!&quot; в консоль браузера. Функция main() не должна завершаться в браузере, поэтому используется бесконечный цикл <code class="inlinecode">emscripten_set_main_loop</code>. Но мы не будет использовать эту функцию дальше. Мы будет использовать SDL3-callbacks, то есть 4 функции вместо main(), которые и на Desktop и в браузере<br /></li>
<li>Примечание. При сборке в Release стартового примера выше у меня получилось приложение весом всего лишь 15.8 KB:<br />
<ul><li>index.html - 245 bytes</li>
<li>app.js - 13.9 KB</li>
<li>app.wasm - 1.68 KB</li>
<li>Итог - 15.8 KB</li>
</ul><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11818&amp;d=1774895196" border="0" alt="Название: 6f45f4bc-ddf5-43eb-88fe-9a9ef02fa610.png
Просмотров: 65

Размер: 2.9 Кб" style="margin: 5px" /></li>
<li>На SDL3 будет около в районе 1 МБ, что тоже мало по современным меркам</li>
<li>Сделает сборку стартового примера по пошаговой инструкции ниже</li>
</ul><br />
<h2>Сборка стартового примера</h2><br />
<br />
<ul><li>Проверим работоспособность стартового примера, который мы скачали выше</li>
<li>Установите <code class="inlinecode">emsdk 4.0.15</code> по пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10735.html">Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm</a></li>
<li>После выполнения инструкции выше у вас будут установлены: CMake, emsdk, Node.js и http-server</li>
<li>Откройте CMD (консоль) в папке стартового примера</li>
<li>Введите следующие команды по очереди (это команды: конфигурирования, сборки и запуска локального сервера)<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="870325633"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="870325633" style="height: 78px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
</pre></td><td class="de1"><pre class="de1">config-web
build-web
http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Перейдите в браузер и введите адрес: localhost:8080 и нажмите Enter</li>
<li>Вы увидите результат работы программы в консоли браузера, если нажмёте: Ctrl+Shift+J в Chrome и Edge, либо Ctrl+Shift+K в FireFox</li>
<li>Запустите в корне папки проекта вторую консоль, чтобы дальше можно было переконфигурировать и собирать проект в этой консоли, а в первой консоли пусть запущен локальные сервер</li>
</ul><br />
<br />
<h2>Настройка инструментов</h2><br />
<br />
<ul><li>Скачайте архив <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11820&amp;d=1774898358">SDL3-devel-3.4.2-wasm.zip</a></li>
<li>Примечание. Эту библиотеку я собрал из исходников с помощью Emscripten SDK 4.0.15 по инструкции: <a href="https://www.cyberforum.ru/blogs/416874/10795.html">SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten</a></li>
<li>Создайте на каком-нибудь локальном диске папку &quot;libs&quot;, например, на диске C и разархивируйте скаченный архив в папку &quot;libs&quot;:<br />
<a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11817&amp;d=1774893317" rel="Lightbox" id="attachment11817" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11817&amp;thumb=1&amp;d=1774893317" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: 931653e4-26ae-43ee-9938-f38e599e9330.png
Просмотров: 37
Размер:	3.0 Кб
ID:	11817" style="margin: 5px" /></a></li>
<li>Откройте скаченный пример в каком-нибудь редакторе кода, например, Notepad++, а лучше в Sublime Text 4: <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a>. Если вы добавите путь к Sublime Text 4 (ST4) в PATH, то сможете запускать ST4 из консоли командой <code class="inlinecode">subl .</code> и тогда ST4 откроет текущую папку</li>
<li>Откройте файл <code class="inlinecode">CMakeLists.txt</code> и скопируйте в него следующие настройки и не забудьте заменить путь к SDL3 на свой, если у вас путь отличается:<br />
<br />
CMakeLists.txt<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="996895619"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="996895619" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>start-hello-wasm-sdl3-c<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Устанавливаем стандарт C (обязательно перед add_executable)</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">17</span><span class="br0">&#41;</span>
<span class="kw1">set</span><span class="br0">&#40;</span>CMAKE_C_STANDARD_REQUIRED ON<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Задаем название будущего приложения (в Windows это был бы app.exe, а</span>
<span class="co0"># в вебе будет app.js / app.wasm)</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Подсказываем CMake, где искать конфигурационные файлы библиотеки SDL3</span>
<span class="kw1">set</span><span class="br0">&#40;</span>SDL3_DIR <span class="st0">&quot;C:/libs/SDL3-devel-3.4.2-wasm/lib/cmake/SDL3&quot;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Загружаем настройки пакета SDL3 (параметры компиляции и пути к заголовкам)</span>
find_package<span class="br0">&#40;</span>SDL3 REQUIRED<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Привязываем SDL3 к нашему приложению (настройка линковки и путей include)</span>
target_link_libraries<span class="br0">&#40;</span>app PRIVATE SDL3::SDL3<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># Добавляем исполняемый файл в сборку</span>
target_sources<span class="br0">&#40;</span>app
PRIVATE
&nbsp; &nbsp; src<span class="sy0">/</span>main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Заменим этот код на код из официального примера, который был показан в начале этого сообщения (пример <a rel="nofollow noopener noreferrer" href="https://github.com/libsdl-org/SDL/blob/main/examples/renderer/01-clear/clear.c" target="_blank" title="https://github.com/libsdl-org/SDL/blob/main/examples/renderer/01-clear/clear.c">01-clear</a>), а в самом начале этого сообщение мы перевели комментарии на русский с помощью Gemini</li>
<li>Добавьте в код строку <code class="inlinecode">SDL_SetRenderVSync(renderer, 1);</code> после создания окна:<br />
<br />
main.c<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="680798204"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="680798204" style="height: 350px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
</pre></td><td class="de1"><pre class="de1"><span class="coMULTI">/*</span>
<span class="coMULTI">&nbsp;* Этот пример кода создает окно и рендерер SDL, а затем очищает</span>
<span class="coMULTI">&nbsp;* окно разным цветом в каждом кадре, так что вы фактически получите окно,</span>
<span class="coMULTI">&nbsp;* цвет которого плавно меняется.</span>
<span class="coMULTI">&nbsp;*</span>
<span class="coMULTI">&nbsp;* Этот код является общественным достоянием. Не стесняйтесь использовать его в любых целях!</span>
<span class="coMULTI">&nbsp;*/</span>
&nbsp;
<span class="co2">#define SDL_MAIN_USE_CALLBACKS 1 /* использовать функции обратного вызова вместо main() */</span>
<span class="co2">#include &lt;SDL3/SDL.h&gt;</span>
<span class="co2">#include &lt;SDL3/SDL_main.h&gt;</span>
&nbsp;
<span class="coMULTI">/* Мы будем использовать этот рендерер для отрисовки в этом окне в каждом кадре. */</span>
<span class="kw4">static</span> SDL_Window <span class="sy0">*</span>window <span class="sy0">=</span> NULL<span class="sy0">;</span>
<span class="kw4">static</span> SDL_Renderer <span class="sy0">*</span>renderer <span class="sy0">=</span> NULL<span class="sy0">;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз при запуске. */</span>
SDL_AppResult SDL_AppInit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">**</span>appstate<span class="sy0">,</span> <span class="kw4">int</span> argc<span class="sy0">,</span> <span class="kw4">char</span> <span class="sy0">*</span>argv<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; SDL_SetAppMetadata<span class="br0">&#40;</span><span class="st0">&quot;Example Renderer Clear&quot;</span><span class="sy0">,</span> <span class="st0">&quot;1.0&quot;</span><span class="sy0">,</span> <span class="st0">&quot;com.example.renderer-clear&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_VIDEO<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't initialize SDL: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>SDL_CreateWindowAndRenderer<span class="br0">&#40;</span><span class="st0">&quot;examples/renderer/clear&quot;</span><span class="sy0">,</span> <span class="nu0">640</span><span class="sy0">,</span> <span class="nu0">480</span><span class="sy0">,</span> SDL_WINDOW_RESIZABLE<span class="sy0">,</span> <span class="sy0">&amp;</span>window<span class="sy0">,</span> <span class="sy0">&amp;</span>renderer<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Log<span class="br0">&#40;</span><span class="st0">&quot;Couldn't create window/renderer: %s&quot;</span><span class="sy0">,</span> SDL_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_FAILURE<span class="sy0">;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; SDL_SetRenderLogicalPresentation<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">640</span><span class="sy0">,</span> <span class="nu0">480</span><span class="sy0">,</span> SDL_LOGICAL_PRESENTATION_LETTERBOX<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; SDL_SetRenderVSync<span class="br0">&#40;</span>renderer<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="coMULTI">/* продолжаем выполнение программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается, когда происходит новое событие (ввод мыши, нажатия клавиш и т. д.). */</span>
SDL_AppResult SDL_AppEvent<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_Event <span class="sy0">*</span>event<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>event<span class="sy0">-&gt;</span>type <span class="sy0">==</span> SDL_EVENT_QUIT<span class="br0">&#41;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_SUCCESS<span class="sy0">;</span> <span class="coMULTI">/* завершаем программу, сообщая ОС об успешном завершении. */</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="coMULTI">/* продолжаем выполнение программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз за кадр и является сердцем программы. */</span>
SDL_AppResult SDL_AppIterate<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">double</span> now <span class="sy0">=</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">double</span><span class="br0">&#41;</span>SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu16">1000.0</span><span class="sy0">;</span> <span class="coMULTI">/* преобразуем миллисекунды в секунды. */</span>
&nbsp; &nbsp; <span class="coMULTI">/* выбираем цвет для кадра, который будем рисовать. Трюк с синусоидой заставляет цвета плавно сменять друг друга. */</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> red <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> green <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now <span class="sy0">+</span> SDL_PI_D <span class="sy0">*</span> <span class="nu0">2</span> <span class="sy0">/</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">float</span> blue <span class="sy0">=</span> <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span><span class="nu16">0.5</span> <span class="sy0">+</span> <span class="nu16">0.5</span> <span class="sy0">*</span> SDL_sin<span class="br0">&#40;</span>now <span class="sy0">+</span> SDL_PI_D <span class="sy0">*</span> <span class="nu0">4</span> <span class="sy0">/</span> <span class="nu0">3</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; SDL_SetRenderDrawColorFloat<span class="br0">&#40;</span>renderer<span class="sy0">,</span> red<span class="sy0">,</span> green<span class="sy0">,</span> blue<span class="sy0">,</span> SDL_ALPHA_OPAQUE_FLOAT<span class="br0">&#41;</span><span class="sy0">;</span> <span class="coMULTI">/* новый цвет, полная непрозрачность. */</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* очищаем окно цветом отрисовки. */</span>
&nbsp; &nbsp; SDL_RenderClear<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="coMULTI">/* выводим свежеочищенный рендер на экран. */</span>
&nbsp; &nbsp; SDL_RenderPresent<span class="br0">&#40;</span>renderer<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
&nbsp; &nbsp; <span class="kw1">return</span> SDL_APP_CONTINUE<span class="sy0">;</span> <span class="coMULTI">/* продолжаем выполнение программы! */</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="coMULTI">/* Эта функция запускается один раз при завершении работы. */</span>
<span class="kw4">void</span> SDL_AppQuit<span class="br0">&#40;</span><span class="kw4">void</span> <span class="sy0">*</span>appstate<span class="sy0">,</span> SDL_AppResult result<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="coMULTI">/* SDL сама очистит окно/рендерер за нас. */</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Вы можете отформатировать одой командой из консоли, то есть автоматически расставить отступы с помощью пошаговой инструкции: <a href="https://www.cyberforum.ru/blogs/416874/8437.html">Консольные команды для форматирования исходного кода на C, C++, C#, Java, JavaScript, HTML и CSS. Сортировка пакетов на Python</a><br /></li>
<li>Откройте в редакторе кода файл &quot;public/index.html&quot; и замените его содержимое на следующее:<br />
<br />
index.html<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="418319022"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="418319022" style="height: 286px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1.0&quot;</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">canvas</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;canvas&quot;</span><span class="sy0">&gt;&lt;/</span><span class="kw2">canvas</span><span class="sy0">&gt;</span></span>
&nbsp;
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> async <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./js/app.js&quot;</span><span class="sy0">&gt;</span><span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">html</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Введите команды конфигурирования и сборки (на самом деле можно команду build-web, а конфигурирование произойдёт по автомату, потому что CMake автоматически проверяет не был ли изменён файл CMakeLists.txt)<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="826090189"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="826090189" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">config-web
build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Перейдите в браузер и введите адрес: localhost:8080 и нажмите Enter</li>
<li>Обратите внимание, что локальный сервер http-server выводит адреса, например, у меня:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="666714015"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="666714015" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http:<span class="sy0">//</span>100.116.245.193:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>192.168.56.1:<span class="nu0">8080</span>
&nbsp; http:<span class="sy0">//</span>127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Вы можете взять телефон, который подключён к Wi-Fi и ввести в его браузере адрес 192.168.56.1:8080 и приложение запустится на Android</li>
<li>Загрузите созданное веб-приложение (папку <code class="inlinecode">public</code> на бесплатный хостинг Vercel по следующей инструкции</li>
</ul><br />
<h2>Сборка в Release и вес SDL3 веб-приложения</h2><br />
<br />
При сборке в релиз нужно в файле <code class="inlinecode">config-web.bat</code> заменить <code class="inlinecode">Debug</code> на <code class="inlinecode">Release&#93;</code>:<br />
<br />
config-web.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="689411177"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="689411177" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div>После этого нужно ввести команду <code class="inlinecode">config-web</code>. Собирается медленнее секунд на 10 секунд, чем в <code class="inlinecode">Debug</code>, в зависимости от мощности компьютера. В результате у меня получилось приложение весом 982 KB (папка <code class="inlinecode">public</code>). Папку <code class="inlinecode">public</code> мы будет отгружать на бесплатный хостинг в следующей инструкции<br />
<br />
<h2>Загрузка веб-приложения на бесплатный хостинг Vercel</h2><br />
<br />
<ul><li>Зарегистрируйтесь в Vercel: <a rel="nofollow noopener noreferrer" href="https://vercel.com/" target="_blank" title="https://vercel.com/">https://vercel.com/</a><br />
Установите Vercel глобально командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="274888845"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="274888845" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i <span class="re5">-g</span> vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В корне проекта создайте файл с именем &quot;vercel.json&quot; со следующим содержимым:<br />
<br />
vercel.json<br />
<br />
<div class="codeblock"><table class="json"><thead><tr><td colspan="2" id="884644299"  class="head">JSON</td></tr></thead><tbody><tr class="li1"><td><div id="884644299" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1"><span class="br0">&#123;</span>
&nbsp; <span class="st0">&quot;headers&quot;</span><span class="sy0">:</span> <span class="br0">&#91;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;source&quot;</span><span class="sy0">:</span> <span class="st0">&quot;/(.*)&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;headers&quot;</span><span class="sy0">:</span> <span class="br0">&#91;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> <span class="st0">&quot;key&quot;</span><span class="sy0">:</span> <span class="st0">&quot;Cross-Origin-Embedder-Policy&quot;</span><span class="sy0">,</span> <span class="st0">&quot;value&quot;</span><span class="sy0">:</span> <span class="st0">&quot;require-corp&quot;</span> <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> <span class="st0">&quot;key&quot;</span><span class="sy0">:</span> <span class="st0">&quot;Cross-Origin-Opener-Policy&quot;</span><span class="sy0">,</span> <span class="st0">&quot;value&quot;</span><span class="sy0">:</span> <span class="st0">&quot;same-origin&quot;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; <span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#93;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Этот файл нужен для загрузки файла app.wasm</li>
<li>В консоли из корня проекта выполните команду для входа в Vercel:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="219541492"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="219541492" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="kw2">login</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В консоли вы увидите сообщение: &quot;Press [ENTER] to open the browser&quot; (&quot;Нажмите [ENTER], чтобы перейти в браузер&quot;)</li>
<li>Нажмите Enter и вы будете перенаправлены в браузер, где нужно будет нажать кнопку &quot;Allow&quot; (&quot;Позволяю&quot;)</li>
<li>Наберите команду для первой отгрузки приложения на хостинг:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="923847545"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="923847545" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В консоли будут задаваться вопросы и на все эти вопросы Enter</li>
<li>Вы будет выдан адрес вашего приложения:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="291317293"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="291317293" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">Aliased: https://finish-hello-wasm-sdl3-c.vercel.app</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. К сожалению, иногда Vercel часто становится недоступным в РФ. Как альтернатива, можете загрузить папку <code class="inlinecode">public</code> на бесплатный хостинг GitHub Pages. Я загрузил финальный результат на GitHub Pages -&gt; <a rel="nofollow noopener noreferrer" href="https://8observer8.github.io/wasm/sdl3/finish-hello-wasm-sdl3-c/" target="_blank" title="https://8observer8.github.io/wasm/sdl3/finish-hello-wasm-sdl3-c/">демка в браузере</a></li>
</ul><br />
<h2>Создание QR-кода для быстрого запуска на смартфонах</h2><br />
<br />
Мы собрали приложение и загрузили его на бесплатный хостинг. У нас есть ссылка на приложение. Используем эту ссылку, чтобы создать QR-код<br />
<br />
<ul><li>Наберите в поисковике интернета: qr code generator</li>
<li>Одна из первых ссылок будет указывать на ресурс, на который нужно перейти: <a rel="nofollow noopener noreferrer" href="https://www.qr-code-generator.com/" target="_blank" title="https://www.qr-code-generator.com/">https://www.qr-code-generator.com/</a></li>
<li>В поле ввода скопируйте ссылку на приложение. QR-код появится справа</li>
<li>Внизу выберите какой-нибудь способ отображение QR-кода. Нарпимер:<br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11821&amp;d=1774907966" border="0" alt="Название: 010516df-4372-49e1-8b0a-ffcb04494b76.png
Просмотров: 7081

Размер: 4.6 Кб" style="margin: 5px" /></li>
</ul></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11819&amp;d=1774898333">start-hello-wasm-sdl3-c.zip</a> (3.2 Кб, 24 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11820&amp;d=1774898358">SDL3-devel-3.4.2-wasm.zip</a> (1.22 Мб, 43 просмотров)</td>
</tr><tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11822&amp;d=1774908053">finish-hello-wasm-sdl3-c.zip</a> (4.5 Кб, 124 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10736.html</guid>
		</item>
		<item>
			<title>Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm</title>
			<link>https://www.cyberforum.ru/blogs/416874/10735.html</link>
			<pubDate>Fri, 30 Jan 2026 17:21:00 GMT</pubDate>
			<description>Содержание блога (https://www.cyberforum.ru/blogs/416874/blog8091.html) 
 
Для того чтобы скачать...</description>
			<content:encoded><![CDATA[<div><a href="https://www.cyberforum.ru/blogs/416874/blog8091.html">Содержание блога</a><br />
<br />
Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: <a rel="nofollow noopener noreferrer" href="https://git-scm.com/install/windows" target="_blank" title="https://git-scm.com/install/windows">Install for Windows</a>. Следуйте стандартной процедуре установки Git через установщик. Система контроля версиями Git необходимо в данном случае только для клонирования репозитория emsdk.<br />
<br />
<h3>Установка Emscripten SDK (emsdk)</h3><br />
<br />
Есть <a rel="nofollow noopener noreferrer" href="https://emscripten.org/docs/getting_started/downloads.html" target="_blank" title="https://emscripten.org/docs/getting_started/downloads.html">официальная пошаговая инструкция</a>, которой мы будет следовать:<br />
<br />
<ol style="list-style-type: decimal"><li>Откройте терминал в корне диска С (или другого локального диска) - например, в поиске программ наберите CMD</li>
<li>Скачайте инструменты:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="573249182"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="573249182" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1"><span class="kw2">git clone</span> https:<span class="sy0">//</span>github.com<span class="sy0">/</span>emscripten-core<span class="sy0">/</span>emsdk.git
<span class="kw3">cd</span> emsdk</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Установите и активируйте требуемую версию - 4.0.15:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="178389132"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="178389132" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">emsdk <span class="kw2">install</span> 4.0.15
emsdk activate 4.0.15</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Все библиотеки, которые вы используете в своих проектах нужно собирать с одной и той же версией emsdk. Нельзя перемешивать сборки библиотек с разными версиями emsdk</li>
<li>Добавьте следующий путь в Path: C:\emsdk\upstream\emscripten</li>
<li>Примечание. Если не знаете, что такое переменная окружения среды Path и как добавить в неё путь, то спросите у ИИ. Скопируйте для ИИ вопрос:<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">Что такое переменная окружения Path и как добавить в неё путь на Windows 10 (и 11)</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table></li>
</ol><br />
<h3>Установка CMake</h3><br />
<br />
<ol style="list-style-type: decimal"><li>Скачайте и установите <a rel="nofollow noopener noreferrer" href="https://github.com/Kitware/CMake/releases" target="_blank" title="https://github.com/Kitware/CMake/releases">CMake</a>. Ищите cmake-x.x.x-windows-x86_64.msi в списке для установки</li>
<li>Нажимайте кнопки Next -&gt; Next -&gt; Finish</li>
<li>Откройте консоль (CMD) и проверьте запускается ли CMake:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="466039226"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="466039226" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--version</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
</ol><br />
<h3>Пишем &quot;Hello World&quot; на C для запуска в браузере</h3><br />
<br />
<ol style="list-style-type: decimal"><li>Создайте пустую папку для проекта, например, с именем: hello-wasm-c</li>
<li>Откройте эту папку каком-нибудь редакторе кода, например, в Nodepad++. Мне больше всего нравится Sublime Text 4: <a rel="nofollow noopener noreferrer" href="https://www.sublimetext.com/download" target="_blank" title="https://www.sublimetext.com/download">https://www.sublimetext.com/download</a></li>
<li>В папке &quot;hello-wasm-c&quot; создайте папку &quot;src&quot;, а в этой папке &quot;src&quot; создайте файл &quot;main.c&quot;</li>
<li>Откройте файл &quot;main.c&quot; в редакторе кода и напишите код на С или скопируйте:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="680418997"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="680418997" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1"><span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">int</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Привет из WebAssembly!<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Создайте файл CMakeLists.txt в папке &quot;hello-wasm-c&quot;:<br />
<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="766386751"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="766386751" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1">cmake_minimum_required<span class="br0">&#40;</span>VERSION <span class="nu0">3.21</span><span class="br0">&#41;</span>
project<span class="br0">&#40;</span>hello-wasm-c<span class="br0">&#41;</span>
&nbsp;
# Задаем название будущего приложения <span class="br0">&#40;</span>в Windows это был бы app.exe, а в вебе будет app.js / app.wasm<span class="br0">&#41;</span>
add_executable<span class="br0">&#40;</span>app<span class="br0">&#41;</span>
&nbsp;
# Устанавливаем стандарт C
set<span class="br0">&#40;</span>CMAKE_C_STANDARD <span class="nu0">11</span><span class="br0">&#41;</span>
&nbsp;
# Добавляем исполняемый файл
target_sources<span class="br0">&#40;</span>app
PRIVATE
&nbsp; &nbsp; src/main.c
<span class="br0">&#41;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Откройте терминал в корне проекта и скопируйте в терминал команду для конфигурирования проекта:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="622634832"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="622634832" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake <span class="re5">-S</span> . <span class="re5">-B</span> dist -DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Наберите и выполните команду для компиляции:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="783934138"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="783934138" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">cmake <span class="re5">--build</span> dist</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>После команды выше в папке dist будут созданы два файла: app.js и app.wasm</li>
<li>В папке &quot;hello-wasm-c&quot; создайте папку &quot;public&quot;, а в этой папке &quot;public&quot; создайте файл &quot;index.html&quot;</li>
<li>Откройте файл &quot;index.html&quot; в редакторе кода и скопируйте в него следующий код, который подключает файл &quot;app.js&quot;:<br />
<br />
<div class="codeblock"><table class="phphtml"><thead><tr><td colspan="2" id="937539793"  class="head">PHP/HTML</td></tr></thead><tbody><tr class="li1"><td><div id="937539793" style="height: 238px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="de1"><pre class="de1"><span class="sc0">&lt;!DOCTYPE html&gt;</span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">html</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw3">charset</span><span class="sy0">=</span><span class="st0">&quot;utf-8&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">meta</span> <span class="kw-3">name</span><span class="sy0">=</span><span class="st0">&quot;viewport&quot;</span> <span class="kw-7">content</span><span class="sy0">=</span><span class="st0">&quot;width=device-width, initial-scale=1.0&quot;</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sc2"><span class="sy0">&lt;</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>Hello Wasm<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">title</span><span class="sy0">&gt;</span></span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">head</span><span class="sy0">&gt;</span></span>
&nbsp;
<span class="sc2"><span class="sy0">&lt;</span><span class="kw2">body</span><span class="sy0">&gt;</span></span>
&nbsp; &nbsp; <span class="sy0">&lt;</span><span class="kw2">script</span> async <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./js/app.js&quot;</span><span class="sy0">&gt;</span><span class="kw-1">&lt;/<span class="kw2">script</span>&gt;</span>
<span class="sc2"><span class="sy0">&lt;/</span><span class="kw2">body</span><span class="sy0">&gt;</span></span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В папке &quot;public&quot; создайте папку &quot;js&quot;</li>
<li>Скопируйте в папку &quot;js&quot; два файла: &quot;app.js&quot; и &quot;app.wasm&quot; (из папки &quot;dist&quot;)</li>
<li>Веб-приложение готово - оно находится в папке &quot;public&quot;. Вы можете запустить это веб-приложение локально, с помощью локального сервера. Либо вы можете загрузить папку &quot;public&quot; на бесплатный хостинг: Vercel, Firebase, GitHub Pages и т.д.</li>
</ol><br />
<h3>Запуск веб-приложения на локальном хостинге с помощью Node.js и http-server</h3><br />
<br />
<ul><li>Скачайте и установите Node.js: <a rel="nofollow noopener noreferrer" href="https://nodejs.org/en/download" target="_blank" title="https://nodejs.org/en/download">https://nodejs.org/en/download</a> - это стандартный установщик: Next -&gt; Next -&gt; ... -&gt; Finish</li>
<li>Node.js содержит установщик пакетов под названием NPM</li>
<li>Откройте терминал (CMD) и установите пакет http-server с помощью команду:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="654175160"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="654175160" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i http-server <span class="re5">-g</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Ключ -g означает &quot;глобально&quot;, то есть команда для запуска локального сервера будет доступна из терминала</li>
<li>Откройте терминал в корне проекта и запустите локальный сервер командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="349655388"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="349655388" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">http-server <span class="re5">-c-1</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Ключ -c-1 означает дать команду браузеру не кэшировать файлы, чтобы загружались только актуальные файлы в браузер</li>
<li>Локальный сервер запущен. В консоль выводятся адреса, по которым можно посмотреть результат:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="387826267"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="387826267" style="height: 110px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
</pre></td><td class="de1"><pre class="de1">Available on:
&nbsp; http://100.116.245.193:<span class="nu0">8080</span>
&nbsp; http://192.168.56.1:<span class="nu0">8080</span>
&nbsp; http://127.0.0.1:<span class="nu0">8080</span>
Hit CTRL-C to stop the server</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Вы можете скопировать одни из адресов в браузер, либо можете набрать в адресной строке браузера: localhost:8080 и нажать Enter</li>
<li>Примечание. Если у вас есть Wi-Fi на телефоне, то можете в нём адрес в браузере, например: 192.168.56.1:8080 Правда, в данном приложении вы не увидите вывод в мобильном браузере. Можете спросить у ИИ как выводить содержимое консоли мобильного в браузер на компьютере для отладки мобильных приложений в браузере</li>
<li>Откройте отладочную консоль браузера, чтобы увидеть результат работы программы. В Chrome и Edge для открытия отладочной консоли нужно нажать Ctrl+Shift+J (в FireFox: Ctrl + Shift + K)</li>
<li>В консоли вы увидите вывод:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="872174881"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="872174881" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">Привет из WebAssembly!</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Попробуйте, что изменить в программе и перекомпилировать её. Например, добавьте в коде в выводе текста: &quot;Урааааа!&quot;:<br />
<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="702360560"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="702360560" style="height: 142px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
</pre></td><td class="de1"><pre class="de1"><span class="co2">#include &lt;stdio.h&gt;</span>
&nbsp;
<span class="kw4">int</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Привет из WebAssembly! Урааааа!<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Лучше держать две консоли открытыми. В одной вы запустили локальный сервер и не трогаете эту консоль. А во второй консоли вы ввели один раз команду для сборки &quot;cmake --build dist&quot; и потом просто нажимаете стрелку вверх в консоли, чтобы выбрать предыдущую команду и нажимаете Enter</li>
<li>Чтобы каждый раз не копировать вручную файлы app.js и app.wasm из папки &quot;dist&quot; в папку &quot;public/js&quot; скопируйте этот bash-скрипт (то есть батник) в корень проекта &quot;hello-wasm-c&quot; и назовите батник &quot;build-web.bat&quot;:<br />
<br />
build-web.bat<br />
<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="709460527"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="709460527" style="height: 158px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
</pre></td><td class="de1"><pre class="de1"><span class="kw3">cd</span> dist
cmake <span class="re5">--build</span> .
&nbsp;
<span class="kw3">cd</span> ..
<span class="kw2">mkdir</span> public\js
<span class="kw1">set</span> <span class="re2">current_dir</span>=<span class="sy0">%</span>~dp0
copy <span class="st0">&quot;%current_dir%dist\app.wasm&quot;</span> <span class="st0">&quot;%current_dir%public\js&quot;</span>
copy <span class="st0">&quot;%current_dir%dist\app.js&quot;</span> <span class="st0">&quot;%current_dir%public\js&quot;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Как видно из кода выше. Сначала происходит вход в папку &quot;dist&quot; (cd dist). Потом сборка в текущей папке (cmake --build .). Далее выход из папки &quot;dist&quot; в корень проекта (cd ..). Создаётся папка &quot;public/js&quot;, если она не была ещё создана (mkdir public\js). Потом создаётся переменная &quot;current_dir&quot;, в которую сохраняется путь до текущей директории. А в конце два файла (app.js и app.wasm) копируются в папку &quot;public/js&quot; с помощью команд &quot;copy&quot;</li>
<li>Теперь можно компилировать код одной командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="713207257"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="713207257" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">build-web</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Переходите в браузер и обновляете страницу. Лучше всего обновлять (при открытой консоли браузера) правой кнопкой по кнопке &quot;Reload&quot; и выбрать &quot;Empty Cache and Hard Reload&quot;, чтобы точно быть уверенным, что загрузятся актуальные файлы проекта в браузер</li>
<li>Лучше всего ещё команду конфигурирования сохранить в батник с именем &quot;config-web.bat&quot; в корень проекта:<br />
<br />
config-web.bat<br />
<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="741083588"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="741083588" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake -S . -B dist -DCMAKE_BUILD_TYPE=Debug</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Команда выше конфигурирует проект Debug (для отладки) и в этом случае собирается быстро, но файл app.wasm весит больше (95.6 KB), а если вместо Debug написать Release, то будет весить меньше, но собираться будет дольше:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="790812791"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="790812791" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">emcmake cmake -S . -B dist -DCMAKE_BUILD_TYPE=Release</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Это приложение настолько простое, что по весу разницы нет между Debug и Release ни в весе ни в скорости сборки</li>
</ul><br />
<h3>Загрузка веб-приложения на бесплатный хостинг Vercel</h3><br />
<br />
<ul><li>Зарегистрируйтесь в Vercel: <a rel="nofollow noopener noreferrer" href="https://vercel.com/" target="_blank" title="https://vercel.com/">https://vercel.com/</a></li>
<li>Установите Vercel глобально командой:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="225238406"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="225238406" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">npm i <span class="re5">-g</span> vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В корне проекта создайте файл с именем &quot;vercel.json&quot; со следующим содержимым:<br />
<br />
vercel.json<br />
<br />
<div class="codeblock"><table class="json"><thead><tr><td colspan="2" id="9064771"  class="head">JSON</td></tr></thead><tbody><tr class="li1"><td><div id="9064771" style="height: 206px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="de1"><pre class="de1"><span class="br0">&#123;</span>
&nbsp; <span class="st0">&quot;headers&quot;</span><span class="sy0">:</span> <span class="br0">&#91;</span>
&nbsp; &nbsp; <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;source&quot;</span><span class="sy0">:</span> <span class="st0">&quot;/(.*)&quot;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; <span class="st0">&quot;headers&quot;</span><span class="sy0">:</span> <span class="br0">&#91;</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> <span class="st0">&quot;key&quot;</span><span class="sy0">:</span> <span class="st0">&quot;Cross-Origin-Embedder-Policy&quot;</span><span class="sy0">,</span> <span class="st0">&quot;value&quot;</span><span class="sy0">:</span> <span class="st0">&quot;require-corp&quot;</span> <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span> <span class="st0">&quot;key&quot;</span><span class="sy0">:</span> <span class="st0">&quot;Cross-Origin-Opener-Policy&quot;</span><span class="sy0">,</span> <span class="st0">&quot;value&quot;</span><span class="sy0">:</span> <span class="st0">&quot;same-origin&quot;</span> <span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; <span class="br0">&#93;</span>
&nbsp; &nbsp; <span class="br0">&#125;</span>
&nbsp; <span class="br0">&#93;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание. Этот файл нужен для загрузки файла app.wasm</li>
<li>В консоли из корня проекта выполните команду для входа в Vercel:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="607704647"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="607704647" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel <span class="kw2">login</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>В консоли вы увидите сообщение: &quot;Press [ENTER] to open the browser&quot; (&quot;Нажмите [ENTER], чтобы перейти в браузер&quot;)</li>
<li>Нажмите Enter и вы будете перенаправлены в браузер, где нужно будет нажать кнопку &quot;Allow&quot; (&quot;Позволяю&quot;)</li>
<li>Наберите команду для первой отгрузки приложения на хостинг:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="880090853"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="880090853" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">vercel</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Вас спросят: &quot;Set up and deploy&quot;. Нажмите клавишу &quot;y&quot; и Enter, то есть &quot;yes&quot;</li>
<li>Следующий вопрос: &quot;Which scope should contain your project?&quot; - нажмите Enter</li>
<li>Вопрос: &quot;Link to existing project?&quot; - нажмите &quot;n&quot; и Enter</li>
<li>Вопрос: &quot;What’s your project’s name? (hello-wasm-c)&quot; - нажмите Enter</li>
<li>Вопрос: &quot;In which directory is your code located?&quot; - наберите public и нажмите Enter</li>
<li>Вопрос: &quot;Want to modify these settings?&quot; - нажмите &quot;n&quot; и Enter</li>
<li>Вопрос: &quot;Do you want to change additional project settings?&quot; - нажмите &quot;n&quot; и Enter</li>
<li>Подождите несколько секунд пока содержимое папку &quot;public&quot; загружается на бесплатный хостинг Vercel</li>
<li>Будет выведет адрес в консоль, по которому будет доступно приложение в браузере:<br />
<div class="codeblock"><table class="unknown"><thead><tr><td colspan="2" id="897808334"  class="head">Code</td></tr></thead><tbody><tr class="li1"><td><div id="897808334" style="height: 46px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
</pre></td><td class="de1"><pre class="de1">Aliased: https://hello-wasm-c.vercel.app</pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Теперь приложение можно попробовать открыть в браузере, но оно зависнет: <a rel="nofollow noopener noreferrer" href="https://hello-wasm-c.vercel.app" target="_blank" title="https://hello-wasm-c.vercel.app">https://hello-wasm-c.vercel.app</a></li>
<li>Ответ Gemini:<br />

<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message">Зависнет, потому что на Vercel как только произошел return 0, Emscripten по умолчанию считает, что работа окончена. Он &quot;схлопывает&quot; виртуальную файловую систему и закрывает потоки stdout. А при запуске на на локальном сервере весь JS-клей и WASM-бинарник прилетают в браузер мгновенно. printf успевает &quot;выплюнуть&quot; данные в консоль до того, как движок JavaScript решит, что модуль можно полностью выгрузить или остановить.</div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table></li>
<li>Чтобы эту проблему решить нужно подключить заголовочный файл emscripten.h и функцию emscripten_set_main_loop(), которая просто запустит бесконечный цикл:<br />
<div class="codeblock"><table class="c"><thead><tr><td colspan="2" id="995627175"  class="head">C</td></tr></thead><tbody><tr class="li1"><td><div id="995627175" style="height: 254px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="de1"><pre class="de1"><span class="co2">#include &lt;stdio.h&gt;</span>
<span class="co2">#include &lt;emscripten.h&gt;</span>
&nbsp;
<span class="kw4">void</span> loop<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="co1">// Пусто</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw4">int</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="kw3">printf</span><span class="br0">&#40;</span><span class="st0">&quot;Привет из WebAssembly на Vercel!<span class="es1">\n</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; &nbsp; emscripten_set_main_loop<span class="br0">&#40;</span>loop<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// Это не даст программе закрыться</span>
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Запускайте команды сборки и отгрузки на Vercel:<br />
<div class="codeblock"><table class="bash"><thead><tr><td colspan="2" id="661611226"  class="head">Bash</td></tr></thead><tbody><tr class="li1"><td><div id="661611226" style="height: 62px" class="codeframe"><table><tr class="li1"><td class="ln" style="padding: 0px 10px 0px 5px;"><pre class="de1">1
2
</pre></td><td class="de1"><pre class="de1">build-web
vercel <span class="re5">--prod</span></pre></td></tr></table></div></td></tr></tbody></table></div></li>
<li>Примечание 1. На самом деле emscripten_set_main_loop - это обёртка над window.requestAnimationFrame в браузере</li>
<li>Примечание 2. При использовании SDL3-callback функций не нужно будет явно писать функцию emscripten_set_main_loop. На SDL3 код один и и тот же код можно собирать для WASM, Desktop и Android</li>
<li>Примечание 3. Если вы скомпилируете код выше в Debug, то вес составит примерно: app.js - 66 KB, app.wasm - 96 KB. А если скомпилируете в Release, то вес будет значительно меньше: app.js - 14 KB и app.wasm - 2 KB. Не забывайте набрать команду config-web.bat, когда вы поменяли Debug на Release или Release на Debug, а потом вводите команду build-web.bat Как только вы ввели по одному разу config-web и build-web, то вы можете переключаться между ними стрелками вверх и вниз в консоли</li>
</ul><br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Ответ Gemini 3 на вопрос, что такое Emscripten и WebAssembly</div>
				   <div class="spoiler-body">
					   
<table width="95%"  class="bbcode_maincontainer"><tr><td>
	<div class="bbcode_container">
	  <div class="bbcode_quote">
	    <div class="btbtbt">
		<div class="quote_container">
	      	<div class="bbcode_quote_container"></div>
	       	<div class="bbcode_postedby">
	         	
	        </div>
	        <div class="message"><br />
<b>WebAssembly (Wasm)</b> — это технология (формат кода), которая позволяет запускать тяжелые приложения в браузере почти со скоростью обычных компьютерных программ. <b>Emscripten</b> — это главный инструмент (компилятор), который превращает ваш код на C++ или C в этот самый формат.<br />
<br />
Вот подробный разбор того, как они работают и в чем разница.<br />
<br />
<b>1. WebAssembly (Wasm) — это &quot;Мишень&quot;</b><br />
<br />
WebAssembly — это не язык программирования в привычном смысле, а низкоуровневый формат инструкций.<br />
<br />
<ul><li><b>Для чего нужен:</b> Раньше браузеры понимали только JavaScript. JS гибкий, но медленный для тяжелых вычислений (игры, видеомонтаж). Wasm дает браузеру возможность выполнять бинарный код.</li>
<li><b>Особенности:</b> * Работает в песочнице (безопасно).<ul><li>Кроссплатформенный (работает везде, где есть браузер).</li>
<li><b>Не заменяет JavaScript</b>, а работает с ним в паре.</li>
</ul></li>
</ul><br />
<b>2. Emscripten — это &quot;Инструмент&quot;</b><br />
<br />
Emscripten — это мощный набор инструментов (Toolchain) на базе LLVM. Представьте его как переводчика-профессионала.<br />
<br />
<ul><li><b>Что делает:</b> Он берет исходный код, написанный на C, C++ или других языках, и переводит (компилирует) его в файл .wasm.</li>
<li><b>Дополнительная магия:</b> Emscripten не просто переводит код, он имитирует целую операционную систему для вашей программы внутри браузера. Он создает &quot;мостики&quot; для работы с файловой системой, графикой (через WebGL) и звуком.</li>
</ul><br />
<img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11463&amp;d= =1769775385" border="0" alt="" style="max-width: 800px; margin: 5px 0px 5px 0px;" /><br />
<br />
<b>Как они работают вместе</b><br />
<br />
Процесс обычно выглядит так:<br />
<br />
<ul><li>Вы берете библиотеку на <b>C++</b> (например, движок для обработки фото).</li>
<li>Запускаете <b>Emscripten</b>.</li>
<li>На выходе получаете файл <b>.wasm</b> (сама логика) и файл <b>.js</b> (клей, который помогает браузеру запустить этот Wasm).</li>
<li>Ваш сайт теперь может обрабатывать фото в 10 раз быстрее, чем на чистом JS.</li>
</ul><br />
<b>Интересный факт:</b> Благодаря этой связке в браузере теперь работают такие гиганты, как <b>Google Earth</b>, <b>Adobe Photoshop</b> и т.д.<br />
<br />

			   <div class="spoiler-wrap">
				   <div class="spoiler-head folded clickable">Миниатюры</div>
				   <div class="spoiler-body">
					   <a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11463&amp;d=1769775385" rel="Lightbox" id="attachment11463" ><img src="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11463&amp;thumb=1&amp;d=1769775385" class="thumbnail" border="0" alt="Нажмите на изображение для увеличения
Название: ce56b0241ef687f666658001c62328a7667b86ad.png
Просмотров: 2540
Размер:	22.1 Кб
ID:	11463" style="margin: 5px" /></a>
				   </div>
			   </div></div>
	      </div>
			</div> 
		</div>
	</div>
</td></tr></table>
				   </div>
			   </div></div>


<!-- attachments -->
	<div style="margin-top:10px">

		
		
		
		
			<fieldset class="fieldset">
				<legend>Вложения</legend>
				<table cellpadding="0" cellspacing="3" border="0">
				<tr>
	<td><img loading="lazy" decoding="async" class="inlineimg" src="http://www.cyberforum.ru//cyberstatic.net/images/attach/zip.gif" alt="Тип файла: zip" width="16" height="16" border="0" style="vertical-align:baseline" /></td>
	<td><a href="https://www.cyberforum.ru/blog_attachment.php?attachmentid=11464&amp;d=1769794137">hello-wasm-c.zip</a> (2.7 Кб, 67 просмотров)</td>
</tr>
				</table>
			</fieldset>
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>8Observer8</dc:creator>
			<guid isPermaLink="true">https://www.cyberforum.ru/blogs/416874/10735.html</guid>
		</item>
	</channel>
</rss>
