Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр Игра рыбалка представляет собой полноценный симулятор рыбалки и дает возможность порыбачить в реально существующих местах из жизни и поймать рыбу, которая там обитает.

Рыбный дождь

Спорт, Симуляторы, Рыбалка

Играть

Топ прошлой недели

  • AlexKud AlexKud 38 постов
  • Animalrescueed Animalrescueed 36 постов
  • Oskanov Oskanov 7 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
0 просмотренных постов скрыто
509
monobogdan
monobogdan
Посты о ремонте и моддинге ретрогаджетов.
TECHNO BROTHER
1 месяц назад

Пишем 3D-игру для ретро-устройств весом в 600Кб…⁠⁠

...которая работает на первых Android-смартфонах в мире, компьютерах из 90-х и даже Mac'ах! Часть 2.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Иногда у меня лежит душа просто взять и написать какую-нибудь небольшую игрушку с нуля, без использования готовых движков. В процессе разработки я ставлю перед собой интересные задачки: игра должна весить как можно меньше, работать на как можно большем числе платформ и использовать нетипичный для меня архитектурный паттерн. Недавно я начал писать ремейк классических «танчиков» и в рамках серии статей готов рассказать о всех деталях разработки трёхмерной игры с нуля в 2025 году. Если вам интересно узнать, как работают небольшие 3D-демки «под капотом» от написания фреймворка до разработки геймплея — жду вас под катом!

❯ Предисловие

Ещё в начале этого года, мне взбрело в голову проверить насколько концепция «Write once, run anywhere» правдива. Все мы знаем, что Java достаточно обширно используется в Enterprise-секторе по типу банков, Android-гаджетах в качестве языка, на котором написано около 80% системы и даже в смарт-карточках, куда входят привычные нам SIM и банковские карты.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Изначально я хотел написать игру, которая работала бы не только на самых первых Android-смартфонах в мире, но ещё и на ретро-кнопочных телефонах, и при всём этом была 3D. В течении недели, я успел написать некоторые наработки для трёхмерной гоночки с примитивной физикой на основе «линий»:

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

В игре был мультиреднер для M3G и MascotCapsule... не хуже игр Fishlabs :))

Но затем я понял, что лишаюсь очень многих фич языка. Дело в том, что игры для Java-телефонов писались не столько на самой «джаве», сколько на её своеобразном диалекте. В мире C/C++ такой подход принято называть «C с классами», но в случае Java - подход заключался в написании большей части логики в одном-двух классах для улучшения производительности игры. Наследование, полиморфизм и абстракции на кнопочных телефонах использовать не рекомендуется. Кроме того, версия JDK в кнопочных телефонах была на уровне 1.3 — а значит, никаких дженериков и иных полезных фишек Java.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Про разработку игр для кнопочных телефонов я писал отдельную статью. Дабы не отвлекать вас от прочтения этой, ссылку оставлю в закрепленном комментарии :)

По итогу я решил сфокусироваться на относительно свежем HTC Dream — первом серийном Android-смартфоне в мире, который вышел в далёком 2008 году с Android 1.0 на борту. В нём используется уже не JVM, а своя виртуальная машина Dalvik с собственным байткодом и версией JDK — 1.5, да и процессор здесь значительно помощнее, а следовательно и куда больше возможностей для разработки!

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Поскольку игру я разрабатываю и отлаживаю на ПК, у меня также есть отдельный билд и для ретро-компьютеров с GPU из 90-х и нулевых. И в рамках статьи, мы, конечно же, сделаем с вами практические тесты!

❯ Рендер

В первой части мы с вами закончили на том, что написали основу для игры — фреймворк, который включает в себя рендерер, менеджер ресурсов на слабых ссылках, некое подобие графа сцены с компонентной системой и загрузчик уровней. Но этого всё ещё мало для 3D-игры и, что самое важное, все эти модули ещё не оптимизированы.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Например, если грузить уровень «в лоб» и на каждый кубик выделять по отдельному игровому объекту, который «рисует сам себя отдельно» — мы быстро столкнемся с тем, что количество вызовов отрисовки (DIP'ов) превысит все разумные нормы. Для уровня в 16x16 блоков это уже целых 256 DIP'ов - а вкупе с другими танчиками и UI - не менее 260-270.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Самая базовая оптимизация в таком случае — это отсечение по пирамиде видимости (Frustum culling). Концепция простая: для отрисовки всего, что мы видим с вами на экране используется три матрицы размерности 4x4: мировая (позиция и поворот объекта в мире), вида (камера, позиция из «глаз») и проекции. При перемножении, они образуют так называемую WorldViewProjection-матрицу и если каждую вершину модели умножить на эту матрицу — то мы получаем её позицию в Clip-Space (или NDC) пространстве. Далее растеризатор берёт каждые три трансформированные вершины в качестве углов треугольника и отрисовывает их в рендертаргет - в нашем случае, это экран. Именно за счёт перспективной матрицы проекции и Z-буфера, мы с вами и получаем тот самый эффект трёхмерного пространства.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Если взять произведение матрицы вида с матрицей проекции и разбить её на плоскости, соответствующие каждой стороне мира (вверх, вниз, влево, вправо, вперёд, назад) — то путём выполнения простейшей проверки можно понять — находится ли точка мирового пространства в текущей позиции камеры:

public void calculate(Matrix viewProj) {
float[] items = viewProj.Matrix;
planes[0].set(items[3] - items[0], items[7] - items[4], items[11] - items[8], items[15] - items[12]).normalize();
planes[1].set(items[3] + items[0], items[7] + items[4], items[11] + items[8], items[15] + items[12]).normalize();
planes[2].set(items[3] + items[1], items[7] + items[5], items[11] + items[9], items[15] + items[13]).normalize();
planes[3].set(items[3] - items[1], items[7] - items[5], items[11] - items[9], items[15] - items[13]).normalize();
planes[4].set(items[3] - items[2], items[7] - items[6], items[11] - items[10], items[15] - items[14]).normalize();
planes[5].set(items[3] + items[2], items[7] + items[6], items[11] + items[10], items[15] + items[14]).normalize();
}

// Allocation-less
public boolean isPointInFrustum(float x, float y, float z)
{
for(int i = 0; i < planes.length; i++)
{
Plane plane = planes[i];

if ((plane.A * x) + (plane.B * y) + (plane.C * z) + plane.D <= 0)
return false;
}

return true;
}

Далее проверить попадает ли наш кубик или танчик в кадр — дело техники. Есть два подхода: подсчитать Bounding-sphere для модели (радиус относительно самой нижней и самой верхней вершины), или Bounding-box. В самом простом случае, можно обойтись проверкой самой нижней и самой верхней точки Bounding-box'а, однако в некоторых случаях такой алгоритм может давать сбой — например если уткнутся в «стенку» носом в игре:

public boolean isMeshRendererInFrustum(MeshRenderer renderer) {
float x = renderer.Parent.Position.X;
float y = renderer.Parent.Position.Y;
float z = renderer.Parent.Position.Z;
Vector min = renderer.Mesh.BoundingMin;
Vector max = renderer.Mesh.BoundingMax;

return isPointInFrustum(x + min.X, -(y + min.Y), z + min.Z) || isPointInFrustum(x + max.X, -(y + max.Y), z + max.Z);
}

Конкретно в нашем случае, такая оптимизация помогает сэкономить около 100 DIP'ов и даёт неплохой прирост FPS. На Galaxy S3 с Mali 400MP4 мы получаем стабильные 60FPS, в то время как на Xperia Play — около 30... Что-ж, этого всё равно мало, тем более для смартфона, в котором GPU — кровный брат Xenos в Xbox 360...

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Нарисовать 256 кубиков для GPU, даже мобильного — не проблема, особенно если они не бьют по филлрейту. Однако на классических мобильных GPU был строгий бюджет на число DIP'ов — в идеале не более 100, иначе FPS заметно просаживается даже на примитивной геометрии. Поэтому для оптимизации можно использовать технику батчинга: объединяем все кубики с одним материалом в сцене в одну большую модель и рисуем за один вызов DIPUP:

public void bake() {
int uniqueMaterials = 0;

batchList.clear();
batchRenderers.clear();
world.findComponentsOfType(BatchedMeshRenderer.class, batchRenderers);

for(int i = 0; i < batchRenderers.size(); i++) {
BatchedMeshRenderer renderer = batchRenderers.get(i);
renderer.IsTakenByBatcher = false;

if(renderer.Mesh != null && renderer.Material != null) {
if(renderer.Mesh.Buffers.length != 1)
continue; // Only simple meshes is supported now

Batch batch = meshes.get(renderer.Material);

if(batch == null)
meshes.put(renderer.Material, batch = new Batch(renderer.Material));

batch.addMesh(renderer);
}
}

for(Map.Entry<Material, Batch> materialBatch : meshes.entrySet()) {
batchList.add(new BatchHolder(materialBatch.getKey(), materialBatch.getValue()));
materialBatch.getValue().finish(); // Upload mesh to GPU
}
}

После этого, FPS поднимается до очень приятных значений - целых 45! Однако есть и обратная сторона: эта техника очень сильно бьёт не только по памяти, но и в случае динамического батчинга (танки ведь уничтожают кубики) - по процессору. Однако можно и далее оптимизировать этот алгоритм путём разбиения батчей на сетку, чтобы отсекать невидимые группы "кубиков" :)

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Следующая тема — это материалы для поверхностей, описывающие внешний вид модели на экране. В первой статье я написал базовую систему материалов, которая оборачивала в себе набор рендерстейтов и парочку текстур: Diffuse и Detail. Но мало кто помнит, что ещё до шейдеров, в FFP был довольно мощный инструмент, именуемый комбайнерами. По сути, комбайнеры — это возможность задействования сразу нескольких текстурных юнитов для смешивания двух и более текстур за один вызов отрисовки.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Пример использования комбайнеров — плавное смешивание двух текстур на ландшафте с использованием маски. Эдакая вариация техники Splat mapping

Поэтому я решил написать загрузчик для материалов, описанных в простом текстовом формате по типу ini-файлов. В секции Texture описываются используемые текстуры, которые затем подгружаются из пула ресурсов, в RenderStates — напрямую указаны поля в классе Material, а в Combiners — очень-очень примитивная вариация на тему шейдеров!

[Texture]
Primary = textures/t72_diffuse.tex
Secondary = textures/brick.tex

[RenderStates]
AlphaTest = 0
AlphaTestValue = 1

DepthWrite = 1
DepthTest = 1
AlphaBlend = 0
Fog = 1
Unlit = 1

[Combiners]
Sample Primary
Interpolate Secondary 0.3
MultiplyColor Primary

Изначально я хотел сделать чтобы материалы описывали эдакий набор инструкций как «шейдеры» в Quake 3. Однако учитывая отсутствие лямбд в Java 1.5, реализация на интерфейсах (и тем более на рефлексии) не впечатлила своей производительностью и я решил сделать «программируемыми» только сами комбайнеры. Суть простая: отдельные псевдо-шейдеры реализуют интерфейс FixedFunctionShader и в теле метода onApply применяют необходимые операции над комбайнерами. При этом строго запрещается менять стейт самого графического API кроме биндинга текстур:

static class Sample implements BaseGraphics.FixedFunctionShader {

@override
public void onApply(Material material, int combiner, float[] params) {
if(params.length != 1)
throw new ShaderException(this, material, params, "Expected 1 argument");

int texId = (int)params[0];
Texture2D tex = material.Textures[texId];

if(tex == null)
throw new ShaderException(this, material, params, "Texture " + texId + " was null");

tex.bind();

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0 + combiner);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0 + combiner);

glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
}
}

Затем при вызове отрисовки модели, рендерер выполняет «инструкции» для таких комбайнеров по одному и если нужно — откатывается до простой «однотекстурной» версии (драйвер GLES на Mali-400 и VideoCore IV не поддерживает комбайнеры, несмотря на то, что спецификация требует их поддержки). Получается довольно шустро:

if(GPUClass.QualityLevel >= com.monobogdan.engine.GPUClass.QUALITY_LEVEL_NORMAL) {
for (int i = 0; i < Material.COMBINER_STAGE_COUNT; i++) {
// Reset combiner state
glActiveTexture(GL_TEXTURE0 + i);
glDisable(GL_TEXTURE_2D);
}

for (int i = 0; i < material.Shaders.length; i++) {
Material.ShaderInstance instance = material.Shaders[i];

glActiveTexture(GL_TEXTURE0 + i);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glEnable(GL_TEXTURE_2D);
instance.Shader.onApply(material, i, instance.Params);
}
} else {
// Single texture fallback for very slow GPU's
glActiveTexture(GL_TEXTURE0);
setState(GL_TEXTURE_2D, material.Textures[0] != null);
material.Textures[0].bind();
}

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Наполовину кирпичный танк — видели ли вы когда-нибудь такой камуфляж? :)

Следующая тема — рендеринг текста. В более ранних статьях я обычно не парился над демками и просто рисовал текст нативными средствами системы в текстуру, а затем рисовал полноэкранный квад. Такая методика работает шустро на смартфонах, но очень тормозная на ПК и более того, такая текстура занимает слишком много VRAM! Однако чаще всего я использую так называемые битмапные шрифты, которые состоят из атласа — текстуры с «запеченными» буквами и информации о том, где какой символ в ней находится. Для генерации таких шрифтов я использую утилиту BMFont, а сам код рендеринга получается очень простым:

public void drawString(BitmapFont font, Vector color, float x, float y, String str) {
if(font == null)
throw new NullPointerException("font was null");

if(str == null)
return;

int sz = font.Size / 2;

for(int i = 0; i < str.length(); i++) {
char chr = str.charAt(i);

if(chr == ' ')
x += sz;
else {
BitmapFont.CharacterInfo chrInfo = font.getCharacter(chr);
drawImage(font.Pages[chrInfo.Page], x, y + chrInfo.YOffset, chrInfo.X, chrInfo.Y, chrInfo.Width, chrInfo.Height, chrInfo.Width, chrInfo.Height, color);
x += chrInfo.Width;
}
}
}

И результат - весьма симпатичным:

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

В целом, далее особо оптимизировать и нечего для рендерера. Инстансинга в FFP нет, шейдеров — тоже, а рендер идентичный и на Android, и на ПК. Поэтому имеем что имеем!

❯ Аллокации

Однако когда я начал отлаживать игру на смартфонах, я заметил резкие просадки кадров и абсолютно нестабильный FPS. При этом характер лагов был константный: раз в 2-3 секунды просадка в 20 кадров. Заглянув в logcat, я обнаружил что Dalvik постоянно вызывает GC (сборщик мусора) и блокирует все потоки на невероятные 16мс — даже для простейших объектов в «куче»! В зависимости от устройства, Dalvik выделяет от 8 до 32Мб памяти для каждого приложения - что очень немного!

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

В первой статье я рассказывал о том, что большинство объектов у меня мутабельные и предполагают аллокацию не в update/draw, а в конструкторе компонента. Это касается векторов, матриц и иных примитивных классов для различных расчетов — ведь в отличии от .NET, в Java нет Value-типов, которые можно выделить на стеке, кроме примитивов. Например, если в C# написать такой код для сложения двух векторов:

struct Vector3 {
public float X, Y, Z;

public Vector3(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}

public static Vector3 operator +(Vector3 a, Vector3 b)
{
return new Vector3(a.X + b.X, a.Y + b.y, a.Z + b.z);
}
}

...

Transform.Position += Velocity;

То из-за того, что Vector3 — простая структура без ссылок на управляемые объекты, которая не требует контроля от GC, рантайм .NET выделит её на стеке, а не в куче и автоматически удалит при выходе из скоупа метода, где она использовалась. Если попытаться сделать такое в Java:

public static Vector3 add(Vector3 a, Vector3 b)
{
return new Vector3(a.X + b.X, a.Y + b.y, a.Z + b.z);
}

...

transform.position = Vector3.add(transform.position, velocity);

То мы получим аллокацию для каждого объекта, вызывающий этот участок кода на каждый кадр. И когда придёт время вызывать GC — он обязательно тормознет игру и вызовет огромные фризы, прямо как в Minecraft на ПК. Главный нюанс здесь в том, что Dalvik оптимизирован под минимальное потребление памяти и поэтому начинает слишком часто вызывать GC, тормозя работу игры. В смартфонах с большим объёмом ОЗУ (хотя-бы 1Гб) таких проблем уже нет.

Но как я уже и сказал выше — мои игровые объекты и компоненты написаны так, чтобы не нагружать ни GC, ни кучу, но сборщик мусора всё равно продолжает тормозить игру, а значит нужно максимально экономить аллокации. Начав профайлить код, я обнаружил что огромное число аллокаций приходится на... итераторы! Да-да, та же самая проблема, что и в примере с векторами: даже несмотря на крошечный вес в памяти, итерации в каждом кадре засоряют хип и по итогу вызывают GC. Решение: перевести все индексированные списки на классический for:

for(int i = 0; i < GameObjects.size(); i++) {
GameObjects.get(i).onUpdate();
}

// Second pass for late updates
for(int i = 0; i < GameObjects.size(); i++)
GameObjects.get(i).onLateUpdate();

И после этого, частота вызова GC наконец-то стабилизировалась!

❯ Ввод

Отдельный вопрос — это грамотная обработка ввода. Хочется чтобы наша игра поддерживала не только клавиатуру, но и геймпады, а на смартфонах — ещё и виртуальные джойстики. Чтобы не размазывать подсистему ввода в игре на 150 источников как в Unity, есть смысл её абстрагировать на некий виртуальный геймпад с необходимыми для игры кнопками: в нашем случае это стрелки и кнопка стрельбы.

Затем необходимо замаппить физические кнопки на наш виртуальный геймпад. Для этого, на смартфонах я сделал таблицу с маппингом, которая подходит для большинства игровых гаджетов: Xperia Play, игровых консолей на Android'е из 2012-го и даже смартфонов с аппаратными QWERTY-клавиатурами. И если захочется добавить возможность переназначения кнопок — это тоже не станет проблемой!

private static int[] xperiaPlayMapping = {
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_CENTER,
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_BUTTON_X, KeyEvent.KEYCODE_BUTTON_Y, KeyEvent.KEYCODE_BUTTON_R1, KeyEvent.KEYCODE_BUTTON_L1
};

private static int[] genericQWERTYMapping = {
KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_D, KeyEvent.KEYCODE_W, KeyEvent.KEYCODE_S, KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_J, KeyEvent.KEYCODE_K,
KeyEvent.KEYCODE_Q, KeyEvent.KEYCODE_E
};

public static int[][] ConversionTable = {
xperiaPlayMapping,
genericQWERTYMapping
};

...

private int resolveGamePadTranslationTable(int keyCode) {
for(int i = 0; i < GamePadKeyTable.ConversionTable.length; i++) {
int[] keys = GamePadKeyTable.ConversionTable[i];

for(int j = 0; j < keys.length; j++) {
if(keyCode == keys[j])
return j;
}
}

return -1; // Not resolved
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
int gamePadKey = resolveGamePadTranslationTable(keyCode);
handleKeyEvent(event.getScanCode(), Input.STATE_RELEASED);

if(gamePadKey != -1)
handleGamePadEvent(gamePadKey, Input.STATE_RELEASED);

return true;
}

По итогу, у нас есть унифицированное управление на ПК и смартфонах, покататься в нашей демке можно даже на легендарной Xperia Play!

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Для смартфонов без аппаратной клавиатуры, виртуальный геймпад пишется буквально за 5 минут. Главное — использовать относительные нормализованные координаты для адаптивности и учитывать Aspect Ratio устройства, который может быть разным:

public void drawUI() {
VerticalInput = 0;
HorizontalInput = 0;

float scaled = UI_BASE_SIZE * Scale;
float baseY = 1.0f - (scaled * 3); // 0.7f is base coefficient for 1.0f scaling

if(game.Runtime.UI.imageButton(arrowUp, scaled, baseY, scaled, scaled, true))
VerticalInput = 1;

if(game.Runtime.UI.imageButton(arrowDown, scaled, baseY + (scaled * 2), scaled, scaled, true))
VerticalInput = -1;

if(game.Runtime.UI.imageButton(arrowLeft, 0.0f, baseY + scaled, scaled, scaled, true))
HorizontalInput = -1;

if(game.Runtime.UI.imageButton(arrowRight, scaled * 2, baseY + scaled, scaled, scaled, true))
HorizontalInput = 1;
}

❯ Тестируем игру

Пришло время протестировать то, что мы успели с вами сделать за неделю. И сегодня в тестах участвует сразу несколько машинок: Asus eeePC 4G в роли «компьютера из 90-х», Sony Ericsson Xperia Play, iPhone 4S с нюансом и Samsung Galaxy Y Pro. Все гаджеты по своему хороши, имеют разные GPU и всех их объединяет статус легендарных.

Начинаем с SE Xperia Play 2011 года выпуска, который изначально позиционировался как игровой смартфон. По сути, Xperia Play - чуточку переделанный Xperia Pro, где QWERTY-клавиатуру заменили на геймпад, при этом аппаратная платформа почти всех "сонериков" 2011 года идентичная: чипсет Qualcomm MSM8250 с ARMv7-совместимым ядром Scorpio на частоте 1ГГц и GPU Adreno 205 (ребрендинг ATI Imageon Z430, на архитектуре Xenos), 512Мб ОЗУ типа DDR1 и 512Мб флэш-памяти. С смартфонами в те годы была такая же ситуация, как и с компьютерами в начале нулевых: прогресс был слишком быстрым и уже в 2012 году, Xperia Play не тянул многие свежие игры из-за слабенького процессора и GPU!
Но в нашем случае, он показывает себя неплохо и стабильно тянет рендеринг уровня и танчика в 40-45 FPS... В играх на Unity3D, Adreno 205 таким результатом похвастаться не мог.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Переходим к iPhone 4S, который, как я уже сказал, с некоторым нюансом: это китайская реплика на Android. При этом довольно интересен тот факт, что у копии очень крутая IPS-матрица почти такого же разрешения (800x480 против 960x640), как и на оригинальном айфоне. Работает "клон" на базе чипсета MediaTek MT6515 2012 года выпуска с одним ядром Cortex-A9, работающим на частоте 1ГГц и GPU PowerVR SGX531 Ultra. Также в смартфоне установлено 256Мб оперативной памяти и 256Мб постоянной - в общем, типичный бюджетник тех лет. GPU от PowerVR - главное достоинство этого смартфона в плане гейминга, наша демка спокойно выдаёт 50-60 стабильных FPS. Я считаю что это прекрасный результат.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

ERTY-клавиатурой, но и очень диковинным (и родственным Raspberry Pi) процессором Broadcom BCM21553 с одним ARMv6-совместимым ядром на частоте 832МГц и крайне необычным GPU собственной разработки VideoCore IV. Дело в том, что GPU в чипсетах Broadcom выполняет роль системного монитора и по архитектуре заметно отличается от классических видеоускорителей. По сути, это DSP с очень крутым векторным сопроцессором из-за чего его отчасти можно назвать софтрендером. Однако ранние драйвера для этого GPU были очень сырыми из-за чего большинство игр выдавали артефакты или работали очень медленно. Наша игрушка - не исключение, всего лишь 20 FPS при 240x320...

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Переходим к довольно необычной машинке: Asus eeePC 4G. Первые модели легендарной линейки нетбуков отличались очень низкой ценой, довольно слабым и прожорливым процессором Celeron M 353 на архитектуре Dothan (прямой поток Pentium III Tualatin) и частоте 900МГц, встроенной графикой Intel GMA900 с поддержкой пиксельных шейдеров 2.0 и довольно небольшим объёмом ОЗУ в 512Мб типа DDR2. Здесь я проводил тесты на JRE 1.7 - и получил почти 60 FPS... за вычетом того, что раз в 3-4 секунды я получаю микрофризы и нагрузку на процессор в 80%. Однако сама JRE здесь не причём: такая высокая нагрузка связана с тем, что у GPU нет аппаратного вершинного конвейера и поэтому вся трансформация геометрии происходит на процессоре. Такой вот нюанс:

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

❯ Заключение

Вот такая статья о разработке 3D-игры с нуля у нас с вами получилась. Прошлые статьи в этой рубрике я писал в стиле туториала, но в этой я решил рассмотреть конкретные кейсы и архитектурные решения. И может она не настолько простая и понятная, как статья про разработку «самолетиков» или Top-Down стрелялки по зомби, думаю своего читателя она точно нашла! Если вам интересно, с кодом можно ознакомиться на моём Github.

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

А если вам интересна тематика ремонта, моддинга и программирования для гаджетов прошлых лет — подписывайтесь на мой Telegram-канал «Клуб фанатов балдежа», куда я выкладываю бэкстейджи статей, ссылки на новые статьи и видео, а также иногда выкладываю полезные посты и щитпостю. А ролики (не всегда дублирующие статьи) можно найти на моём YouTube канале.

Что думаете о таком формате статей?
Всего голосов:

Очень важно! Разыскиваются девайсы для будущих статей!

Друзья! Для подготовки статей с разработкой самопальных игрушек под необычные устройства, объявляется розыск телефонов и консолей! В 2000-х годах, китайцы часто делали дешевые телефоны с игровым уклоном — обычно у них было подобие геймпада (джойстика) или хотя бы две кнопки с верхней части устройства, выполняющие функцию A/B, а также предустановлены эмуляторы NES/Sega. Фишка в том, что на таких телефонах можно выполнять нативный код и портировать на них новые эмуляторы, чем я и хочу заняться и написать об этом подробную статью и записать видео! Если у вас есть телефон подобного формата и вы готовы его задонатить или продать, пожалуйста напишите мне в Telegram (@monobogdan) или в комментарии. Также интересуют смартфоны-консоли на Android (на рынке РФ точно была Func Much-01), там будет контент чуточку другого формата :)

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

А также я ищу старые (2010-2014) подделки на брендовые смартфоны Samsung, Apple и т. п. Они зачастую работают на весьма интересных чипсетах и поддаются хорошему моддингу, парочку статей уже вышло, но у меня ещё есть идеи по их моддингу! Также может у кого-то остались самые первые смартфоны Xiaomi (серии Mi), Meizu (ещё на Exynos) или телефоны Motorola на Linux (например, EM30, RAZR V8, ROKR Z6, ROKR E2, ROKR E5, ZINE ZN5 и т. п., о них я хотел бы подготовить специальную статью и видео т. к. на самом деле они работали на очень мощных для своих лет процессорах, поддавались серьезному моддингу и были способны запустить даже Quake!). Всем большое спасибо за донаты!

Пишем 3D-игру для ретро-устройств весом в 600Кб… Опрос, Гаджеты, Смартфон, Программирование, Java, 3D, Gamedev, Opengl, Android, Android разработка, Гифка, Длиннопост

Статья написана при поддержке Таймвеб КЛАУД.

Показать полностью 22 1
[моё] Опрос Гаджеты Смартфон Программирование Java 3D Gamedev Opengl Android Android разработка Гифка Длиннопост
43
66
monobogdan
monobogdan
Посты о ремонте и моддинге ретрогаджетов.
TECHNO BROTHER
1 год назад

Первый легендарный мобильный GPU: каким был PowerVR MBX Lite? Пишем игру-демку про «жигули» с нуля, ч. 2⁠⁠

Это продолжение поста Первый легендарный мобильный GPU: каким был PowerVR MBX Lite? Пишем игру-демку про «жигули» с нуля, ч.1

❯ Практическая часть: Геймплей

Дисклеймер: игра была написана как простенькая, но познавательная демка именно для PowerVR MBX и именно для Axim X51v. Именно поэтому здесь нет нормального Update-таймера, расчёта дельты времени, а игра прибита к константным временным отрезкам и величинам скорости!


Итак, как же игры подобного планы работают «под капотом»? По факту, обычно мы с вами никуда не едем: фоновые модели ландшафта и дороги просто скроллятся и телепортируются друг за другом, когда одна из частей уходят за экран, что создаёт эффект бесконечной дороги. И эта техника используется во многих играх! Что же касается машинок, от которых мы должны лавировать, то это не мы едем на них, это они едут на нас! По итогу создаётся эффект будто мы с вами куда-то едем и уворачиваемся от машинок, хотя на деле это не так!

Начинаем с реализации базовой вещи в архитектуре любой современной игры, а именно системы игровых объектов. В нашей игре нет необходимости в реализации сложного графа сцены с комплексной компонентной системой, или, например, ECS. Хватит классического линейного списка игровых объектов (который использовался, например, в Half-Life), по которому объект World проходится каждый кадр, вызывая необходимые функции для обновления состояния объекта и его отрисовки:

public abstract class Entity
{
public Transform Transform;

public abstract void Update();
public abstract void Draw();
}

public void Spawn(Entity ent)
{
if(ent != null)
Entities.Add(ent);
}

public void Remove(Entity ent)
{
entityRemovalList.Add(ent);
}

public void Update()
{
sky.Update();
renderer.Update();
spawner.Update();

foreach (Entity ent in Entities)
ent.Update();

foreach (Entity ent in entityRemovalList)
Entities.Remove(ent);

entityRemovalList.Clear();
}

public void Draw()
{
sky.Draw();

renderer.Draw();

foreach (Entity ent in Entities)
ent.Draw();
}

Самым первым нашим объектом будет машинка игрока, которой можно будет управлять!
Модельки я взял лоуполи со скетчфаба, вот ссылка на ВАЗ 21099 и VW Golf Mk2. Спасибо авторам моделей за их работу!

Первый легендарный мобильный GPU: каким был PowerVR MBX Lite? Пишем игру-демку про «жигули» с нуля, ч. 2 Опрос, Программирование, Гаджеты, Смартфон, 3D графика, Gamedev, 3D, Видеокарта, Opengl, Gles, Directx, Видео, Без звука, Вертикальное видео, Длиннопост

Наследуемся от Entity и реализуем абстрактные методы с логикой объекта. Здесь мы получаем состояние аппаратных кнопок влево и вправо, в зависимости от них вычисляем направление поворота машинки и, собственно, поворачиваем машинку путём сложения с координатой X вычисленного направления, помноженного на «скорость» поворота машинки. Для лучшего визуального эффекта, мы также плавно поворачиваем машинку эффектом а-ля EaseIn/EaseOut:

float hVel = Engine.Current.Input.GetKeyState(GamepadKey.Left) ? -1 : (Engine.Current.Input.GetKeyState(GamepadKey.Right) ? 1 : 0);

Transform.Position.X += hVel * SteerSpeed;
Transform.Rotation.Y = MathUtils.lerp(Transform.Rotation.Y, 180 + (hVel * 35), 0.1f);

Теперь нам нужно, чтобы машинка где-то «ездила». Для этого мы моделируем в блендере примитивный кусок дороги с элементами ландшафта:

Первый легендарный мобильный GPU: каким был PowerVR MBX Lite? Пишем игру-демку про «жигули» с нуля, ч. 2 Опрос, Программирование, Гаджеты, Смартфон, 3D графика, Gamedev, 3D, Видеокарта, Opengl, Gles, Directx, Видео, Без звука, Вертикальное видео, Длиннопост

А затем реализуем примитивный рендерер фона, который будет скроллить два одинаковых seamless-куска уровня и как я уже говорил ранее, просто телепортировать их друг за другом, создавая эффект бесконечности.

public SectorRenderer()
{
road = Model.FromFile("road.mdl");
roadMaterial.Diffuse = Texture2D.FromFile("road.tex");

terrain = Model.FromFile("terrain.mdl");
terrainMaterial.Diffuse = Texture2D.FromFile("grass.tex");

sector1.Position.Y = -4;
sector2.Position.Y = -4;
sector2.Position.Z = SectorSize;
}

public void Update()
{
sector1.Position.Z -= ScrollingSpeed;
sector2.Position.Z -= ScrollingSpeed;

if (sector1.Position.Z + SectorSize < 0)
sector1.Position.Z = SectorSize;

if (sector2.Position.Z + SectorSize < 0)
sector2.Position.Z = SectorSize;
}

public void Draw()
{
Engine.Current.Graphics.DrawModel(road, sector1, roadMaterial);
Engine.Current.Graphics.DrawModel(terrain, sector1, terrainMaterial);
Engine.Current.Graphics.DrawModel(road, sector2, roadMaterial);
Engine.Current.Graphics.DrawModel(terrain, sector2, terrainMaterial);
}

Где terrain.mdl — окружающий ландшафт, а road.mdl — собственно, сам меш дороги. Получаем вот такой эффект:

Артефакты на видео — следствие проблем с точностью float у MBX Lite в процессе клиппинга геометрии при ближней плоскости отсечения в 0.1f. Меняем на 1.0f и всё снова работает нормально :)
Чуть изменяем проекцию, переместив камеру выше и наклонив на 45 градусов и игра уже похожа на Traffic Racer!

Переходим к реализации машин трафика. Модельки их машин будут загружаться при старте игры:

private static void LoadTrafficModel(int idx, string name)
{
PreloadedCars[idx] = Model.FromFile(name + ".mdl");
PreloadedMaterials[idx].Diffuse = Texture2D.FromFile(name + ".tex");
}

public static void Preload()
{
PreloadedCars = new Model[1];
PreloadedMaterials = new Material[1];

LoadTrafficModel(0, "traffic1");
}

А сама их логика предельно проста. При спавне, машинка выбирает себе полосу, по которой будет ехать и рандомный множитель скорости, который вносит разнообразие в игру:

Rand rand = new Random();
Transform.Position.X = Game.Current.world.PickLane(rand .Next(0, 4));
Transform.Position.Y = Game.Current.world.Player.Transform.Position.Y;
Transform.Position.Z = rand .Next(ZOffset, ZOffsetMax);

selectedBias = rand.Next(0, SpeedBias.Length - 1);

int carModel = rand .Next(0, PreloadedCars.Length - 1);
model = PreloadedCars[carModel];
material = PreloadedMaterials[carModel];

А при обновлении, машинка просто продолжает ехать вниз! Логика простая до жути, даже без перестроений.

Transform.Position.Z -= BaseSpeed * SpeedBias[selectedBias];

Переходим к обработке столкновений. Помним, что мы на этапе конвертации моделей посчитали Axis Aligned Bounding Box для каждой модели? В качестве алгоритма мы будем использовать классический AABB — или Rect vs rect:

public bool Intersects(BoundingBox box)
{
return (X < box.X + box.X2 && Y < box.Y + box.Y2 && Z < box.Z + box.Z2 && box.X < X + X2 && box.Y < Y + Y2 && box.Z < Z + Z2);
}

Теперь для проверки столкновения между ними, нам надо посчитать абсолютный Bounding Box для каждого игрового объекта:

Bounds = model.Bounds;
Bounds.X += Transform.Position.X;
Bounds.Y += Transform.Position.Y;
Bounds.Z += Transform.Position.Z;

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

foreach (Entity ent in Game.Current.World.Entities)
{
if (ent is TrafficCar)
{
if (Player.Bounds.Intersects(((TrafficCar)ent).Bounds))
{
// TODO: Damage logic
Player.IsDestroyed = true;
}
}
}

Уже что-то немного похожее на игру. Добавим конечное препятствие — необходимость рестарта при столкновении с другой машинкой и для демки пока-что хватит.

public void Draw()
{
string scoreFmt = string.Format("Score: {0} x{1}", Game.Current.world.Statistics.Score, 1);
Engine.Current.Graphics.DrawString(scoreFmt, 15, 15, StatsColor);

if (Game.Current.world.Player.IsDestroyed)
{
int measure = Engine.Current.Graphics.MeasureString(RestartString);
Engine.Current.Graphics.DrawString("Press Return to restart", Engine.Current.Graphics.ViewWidth / 2 - (measure / 2), Engine.Current.Graphics.ViewHeight / 2, StatsColor);
}
}

Вот что у нас получилось:

Правда, что на МКАДе каждый вечер такое? Я просто не с МСК :)

❯ Заключение


Вот такой у нас получился материал про PowerVR MBX! С выходом iPhone, этот GPU дал толчок для появления красивых мобильных игр с уровнем графики, близким к полноценным домашним консолям… жаль, что золотая эра интересных, самодостаточных и бездонатных мобильных игр и закончилась во времена iPhone 5 :(

В остальном же, надеюсь материал был достаточно интересен и познавателен для всех моих читателей, даже тех, кто никогда не программировал игры! Был у вас Dell Axim X51v? Пишите в комментариях!

Исходный код демки и бинарники можно найти на моём гитхабе.

Материал написан при поддержке TimeWeb Cloud. Подписывайтесь на меня и @Timeweb.Cloud , чтобы не пропускать новые статьи каждую неделю! А ещё у меня есть своя телега, куда я публикую бэкстейдж статей и вовремя публикую ссылки на новый материал!

Понравился материал?
Всего голосов:

А ещё я собираю деньги на проект с уже настоящим, физическим ТАЗом и его электронным дооснащением бортовым компьютером "по самому дешману" своими руками! Уже собрано 50.000 рублей из планируемых 70.000 на машину, из них 45.000 моих личных сбережений и 5.000 рублей - помощь читателей, за что вам большое спасибо :)

Первый легендарный мобильный GPU: каким был PowerVR MBX Lite? Пишем игру-демку про «жигули» с нуля, ч. 2 Опрос, Программирование, Гаджеты, Смартфон, 3D графика, Gamedev, 3D, Видеокарта, Opengl, Gles, Directx, Видео, Без звука, Вертикальное видео, Длиннопост
Показать полностью 3 5 1
[моё] Опрос Программирование Гаджеты Смартфон 3D графика Gamedev 3D Видеокарта Opengl Gles Directx Видео Без звука Вертикальное видео Длиннопост
4
Kuchka70
Kuchka70
2 года назад

Такой шоппинг мне б понравился⁠⁠

3D Кроссовки Смартфон Виртуальная реальность Дополненная реальность Видео Вертикальное видео
3
1611
Jawhitt
Jawhitt
2 года назад

Смартфон СССР⁠⁠

Моя интерпретация советского смартфона. Сделана была давненько, но, подумал, почему бы не поделиться.
https://www.artstation.com/artwork/oAPY6m

Смартфон СССР СССР, Смартфон, Советское, iPhone, 3D, 3D моделирование, Дизайн, Длиннопост
Смартфон СССР СССР, Смартфон, Советское, iPhone, 3D, 3D моделирование, Дизайн, Длиннопост
Смартфон СССР СССР, Смартфон, Советское, iPhone, 3D, 3D моделирование, Дизайн, Длиннопост
Смартфон СССР СССР, Смартфон, Советское, iPhone, 3D, 3D моделирование, Дизайн, Длиннопост
Смартфон СССР СССР, Смартфон, Советское, iPhone, 3D, 3D моделирование, Дизайн, Длиннопост
Смартфон СССР СССР, Смартфон, Советское, iPhone, 3D, 3D моделирование, Дизайн, Длиннопост
Показать полностью 5
[моё] СССР Смартфон Советское iPhone 3D 3D моделирование Дизайн Длиннопост
90
236
quadzilla2000
quadzilla2000
3 года назад
IT минувших дней

3D в каждый карман! HTC Evo 3D⁠⁠

Сегодня расскажу о действительно необычном смартфоне прямиком из 2011 года, когда рынок активно развивался,  а покупатель был голоден до нововведений и всего необычного.

Простите за непрезентабельные фото, но из личного архива остались только они.

3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост

Не спрашивайте, почему тут Miui.

3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост

Не буду тянуть - HTC сделала модель которая снимает 3D и показывает 3D. И показывает его без очков и других приспособлений - просто смотришь в экран, просто видишь объёмную картинку.

3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост

Что бы наслаждаться 3D без очков, была применена параллаксная решётка.

Принцип её работы довольно прост: перед матрицей расположена специальная решетка, состоящая из очень узких полос, закрывающих пиксели. Если взять смартфон горизонтально, то полосы будут расположены вертикально. Расположение полос таково, что один глаз видит один ряд пикселей, а другой — соседний. Картинка на дисплее получается поделенной на две, для левого и правого глаза. После привыкания и подстройки глаз в определенный момент обе картинки сливаются в одну — эффект 3D достигнут.

С параллаксной решеткой технически это выглядело так:

3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост

Что бы примерно было понятно, как это ощущалось вживую - вот вам гифка:

3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост

Да, как на магнитике у вас на кухне.

Фото с таким эффектом можно было сделать на камеры Evo 3D - они здесь абсолютно одинаковые, по 5 Мп. Качество фото на уровне для 2011 года.

Что приятно - так это металлическая вставка с рычажком переключения режима съёмки фото и видео в 3D, и отдельная кнопка спуска. Хоть это был и не фотофлагман, но делать фотки было комфортнее чем у конкурентов.

3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост
3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост

Довольно занятно, что первые двухкамерные смартфоны были с двумя одинаковыми модулями, хотя производительности для такого решения хватало впритык, и только в 2014 HTC выпустила One M8 с дополнительным модулем, который помогал размывать фон на фото.

3D для сильных духом

Почему всё не так радужно с 3D? Проблема  в том, что в этом режиме из-за конструктива видимое разрешение дисплея падала с весьма недурных 540*960 пикселей, до 270*480 пикселей, что смотрелось не так впечатляюще.

И вообще видеть это 3D во всей красе было непросто - картинка хорошо смотрелась только на определенном расстоянии и под определённым углом, вдвоём 3D кино не посмотреть и фоточки не полистать. К тому же, лично у меня и у многих людей с непривычки быстро уставали глаза и начинала болеть голова. Я всё же смог  привыкнуть, однако 3D-фильмы я на нём даже не пытался смотреть, да и играть дольше 30-40 минут за сессию не пытался, ибо чревато.

Помню как смотрел эти дурацкие ролики с смартфона, ВЕДЬ 3D ЭТО КРУТООООО!!1

В общем, вау-эффект был достигнут:)

Кстати, о играх

Внезапно, но если вы ищете необычный игровой опыт на смартфоне, то наш HTC можно ставить в один ряд с Xperia Play, ведь поиграть с 3D эффектом очень немногие пробовали даже на ПК, не то что на смартфоне. Из альтернатив можно вспомнить разве что LG Optimus 3D и консоль Nintendo 3DS.

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

- Spider-Man: Total Mayhem

- Asphalt 6: Adrenaline

- The Sims 3

- N.O.V.A. Near Orbit Vanguard Alliance

- GT Racing: Motor Academy 3D

- Need For Speed Shift HD

И много других. Благодаря достаточно простой адаптации под 3D -режим и мощной на момент выхода начинке, конечный список игр выглядел весьма внушительно. Когда-то была отдельная тема на 4пда с играми поддерживающими стереоскопический эффект, однако она удалена:(

Я любил играть в Спайдермена и дико популярную SpeedX 3D. Последняя особенно впечатляла - это был очень простой по своей сути раннер, но эффект глубины взрывал мозг, оторваться было сложно:)

3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост
3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост

Впечатления от смартфона

Что бы вы понимали, насколько я поразился существованию этого смартфона и как он в последствии мне понравился - купив его в 2017-м году ради поиграться, я почти год использовал его как основной смартфон. Благодаря приличной начинке в виде 2х1.2 Ггц и 1 гб оперативной памяти я довольно комфортно пользовался интернетом и мессенджерами, разве что автономность немного расстраивала.

Я без ума от дизайна HTC тех лет, они для меня на втором месте после Apple. Металл и прорезиненный пластик, в руках он ощущался добротно и немного брутально, ничего не скрипело и не казалось хрупким и собирающим царапины, как Sony Ericsson.

3D в каждый карман! HTC Evo 3D Htc, Смартфон, Ретро, 3D, Ретро-обзор, Гифка, Видео, Длиннопост

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

Жаль, что компания не выдержала конкуренции и практически ушла с рынка смартфонов.

P.S. Если у вас есть соответствующие очки - посмотрите промо-ролик HTC, презентующий Evo 3D. Отличный маркетинговый ход:)

P.P.S. У меня есть небольшой канал в телеграме, где я пишу о старых железках и и около-ретро тематике (там нет рекламы) - https://t.me/gadgetsandtime

Показать полностью 10 2
[моё] Htc Смартфон Ретро 3D Ретро-обзор Гифка Видео Длиннопост
72
11
DELETED
4 года назад

Ускоренная версия как работает SSD(переведено на русский)⁠⁠

если вам понравилось видео - полная версия и другие ролики подобного плана вы можете найти в моих постах

[моё] Техника Смартфон SSD Флешки Видео Как это сделано Анимация 3D
6
16
DELETED
4 года назад

Как устроена карта SSD? (переведено на русский)⁠⁠

[моё] Техника Смартфон SSD 3D Флешки Видео
7
10
rasfasolenka
rasfasolenka
5 лет назад

Как запустить NFS Most Wanted 2005 в 3D на телефоне⁠⁠

Всем привет! Решил запилить пост об этом, потому что для меня это стало открытием, что вообще возможно поиграть в старый добрый НидФоСпид с тем самым черным списком, открытым миром и копами - на смартфоне, да еще и в натуральном 3Д, в VR очках. Я вообще люблю рулить, чинить тачки и всё что с ними связано, а вот в тему технологий и мобильных игр я почти не углублялся никогда. Итак, приступим.

Как запустить NFS Most Wanted 2005 в 3D на телефоне 3D, Игры, Смартфон, Гонки, Олдскул, 2000-е, Тег в виде гномика, Need for Speed, Видео, Длиннопост

Мы будем запускать ISO образ игры от приставки Nintendo GameCube через эмулятор на андроид. Также нам понадобится переходник от порта телефона на большой USB и VR очки. Переходник я покупал за 150р., очки я взял за 450р. Вот такие:

Как запустить NFS Most Wanted 2005 в 3D на телефоне 3D, Игры, Смартфон, Гонки, Олдскул, 2000-е, Тег в виде гномика, Need for Speed, Видео, Длиннопост

В идеале нам понадобится довольно мощное устройство на андроиде, (я использую Galaxy Note 10+) но можно попытаться запустить и на менее мощных телефонах. Скачиваем из Google Play приложение Dolphin Emulator.

Как запустить NFS Most Wanted 2005 в 3D на телефоне 3D, Игры, Смартфон, Гонки, Олдскул, 2000-е, Тег в виде гномика, Need for Speed, Видео, Длиннопост

Далее скачиваем образ игры. Я это делал на сайте "freeroms" (гуглится первым), там выбираем приставку Nintendo GameCube, находим NFS и загружаем на устройство. Потом распаковываем ISO из архива в любую папку. Далее в эмуляторе выбираем папку, где лежит образ и игра появляется в главном меню эмулятора. Вот первые настойки эмулятора:

После настроек графики подключаем через переходник клавиатуру к телефону, открываем настройки GameCube джойстиков и прописываем кнопки. Всё, можно вставлять телефон в очки и запускать)) Сразу скажу, чтобы добиться наилучшего FPS нужно будет настраивать проценты в меню Override CPU Clock Speed, у меня на 40% порядка 20-25 FPS выдаёт, что позволяет комфортно играть. И еще можно уменьшить разрешение на минимальное, но тогда в очках будут видны пиксели. (Видео записывал с экрана, может подтормаживать, в реале немного быстрее работает)

В меню эмулятора во время запущенной игры можно убрать все кнопки, которые видны на экране, они всё равно не будут использоваться при игре с клавиатуры.
Вообще есть еще NFS на Nintendo, которые можно запустить на телефоне, начиная с Hot Pursuit и заканчивая Carbon, но мне MostWanted
зашел в свое время больше всего) да и вообще сейчас меня поразило, до чего техника дошла, помню как в 2000х запускали мы с отцом на компьютере этот MW, как он в окошке 640х480 лагал жутко)) ещё понравился 3Д эффект в очках, мир реально трёхмерный, видна глубина и погружение почти полное происходит в гонку, только головой нельзя крутить. Интересно будет попробовать вместо клавы подрубить руль с педалями, валялись где-то))

Показать полностью 2 2
[моё] 3D Игры Смартфон Гонки Олдскул 2000-е Тег в виде гномика Need for Speed Видео Длиннопост
15
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии