На хабре достаточно много пользователей коммуникаторов. И вы рассказывали достаточно много историй о том, как вы их использовали в своё время: раскладывали пасьянс, играли в шарики, сидели в интернете, читали книги и в конце-концов, использовали как телефон. А что, если я вам скажу, что на коммуникаторах было аж два API для рисования 3D графики? Причем оба могли уметь хардварное ускорение. Так почему бы не написать 3D игрушку под них, причем с фоллбеком до девайсов без 3D ускорения?
Что будет за игра?
Давайте определимся с вектором развития нашей игры: жанр, проекция, GAPI, поддерживаемые платформы и методы ввода.
Игра будет в классическом жанре скроллшутера. Только шутер у нас 3D, поэтому вид у нас будет сзади нашего космического корабля. Как многие догадываются, в таких играх кораблик обычно никуда не летит, он стоит на месте, а впереди него просто спавнятся и летят в его сторону враги. За это у нас будет отвечать SpawnDirector. Как GAPI мы возьмём D3D Mobile - спец GAPI для Windows Mobile, появившееся с WM5.0(но его можно установить и на Pocket PC 2003). Из платформ мы будем поддерживать от PPC2003, до WM6.5, т.е почти все устройства. Из методов ввода у нас будут как хардварные кнопки с альтернативными биндами(например влево - это dpad и кнопка a, для девайсов с полноценной клавиатурой аля qtek 9100) и тачскрин. В качестве "графа" сцены будет использоваться классическая концепция сущностей - есть World, есть Entity, а игровые объекты наследуются от этого Entity и обновляют своё состояние/рисуют себя сами. Язык будет C#, основной принцип программирования - KISS. Я решил излагать в начале каждого "модуля" концепцию каждого отдельного класса, за что он отвечает и как влияет на общую картину. Возможно тот, кто читает эту статью не имел опыта в разработке игр, или имел самый базовый на готовом движке типа unity, и пытается теперь этот опыт тащить во все остальные сферы - это совершенно необязательно.
Стоит отметить что каких-то разительных отличий разработки именно под WM нет - здесь нет концепции бандлов из iOS или ассетов из Android, тачскрин == мышка, нет удобного DirectSound, но есть классический waveOut. Однако достаточно переносимое кроссплатформенное ядро будет реализовано. Настолько переносимое, что игру можно будет портировать за пару часов на совершенно другое GAPI или платформу(там, где есть .NET).
Хочется отметить, что разработку и отладку мы в первую очередь будем проводить на ПК(не под эмулятором). Постоянно деплоить на КПК неудобно и долго, поэтому у нас будет две версии игры - под ПК для отладки игровой логики, и для коммуникатора для оптимизации и адаптации управления. Именно такая практика позволит сделать ядро игры легко портируемым куда угодно. Изначально бОльшую часть игры я написал деплоя на реальный девайс(дабы понимать потянет ли софтрендер вообще такое качество графики), но когда пришел черед доводки геймплейных механик - портировал игру на ПК. Порт занял где-то 15-20 минут(это не шутка).
Во время портирования игры я свожу к минимуму использование препроцессора и всякие #if WIN32 #if WINMOBILE #if ANDROID и.т.п.
Теперь по модулям:
Рендерер
Для такой игры сложный рендерер с крутыми тенями и оптимизациями не нужен. Наоборот - чем меньше тем лучше. Как я уже говорил - Entity сам может себя рисовать, и для этого ему предоставлен фактически один единственный метод - DrawMesh, принимающий в себя сам меш, матрицу трансформации и материал. Установкой рендерстейтов(а большинство рендерстейтов задаются при создании контекста) занимается тоже он, в зависимости от материала. По большей части это текстура(у которой фиксированный сэмплерстейт - repeat режим адрессации текстуры, отключенный мипмаппинг и point фильтрация), и цвет. Ещё например, можно отключить запись в глубину(что используется для фона).
За рендеринг отвечает класс Graphics. Он создаёт контекст, задает рендерстейты, отображает картинку на экран, задаёт трансформацию и проекцию для камеры и.т.п. Текстуры только 2D(никаких кубмап), и загружаются они с помощью встроенного загрузчика текстур(я не увидел смысла писать свой, поскольку у d3d нативный загрузчик очень шустрый) GAPI. Меши содержат в себе VertexBuffer(меши не индексированные), и грузятся из md2(простой и лёгкий формат, грузится только первый кадр анимации). Кроме того, он умеет рисовать текст(TextRenderer) используя нативное API системы.
Фактически порт с WM на ПК у меня занял 10-20 минут, поскольку D3DM очень похож на D3D8, а следовательно, и на D3D9. Всё те же концепции - "вершинные потоки", FVF, texture stages. Нет только шейдеров(только FFP), и есть более тонкая настройка некоторых аспектов(например перспективная коррекция текстур).
Под WM(и вообще старые платформы, в том числе Symbian) нужно соблюдать некоторые правила, например стоит вообще отказаться от альфа-блендинга, и заменить его на альфа-тест. Альфа-тест не нужно сортировать в отличии от блендинга(поэтому он используется например в cutout шейдерах листвы). Здесь нет сглаживания(оно хардварно может не поддерживаться драйвером), а формат бэкбуфера обычно RGB565(вместо ARGB/XRGB). Глубина обычно либо D16, либо D15S1(15 бит под глубину, 1 под трафарет).
Вот например, код заполнения структуры инициализации контекста:
PresentParameters pp = new PresentParameters();
pp.AutoDepthStencilFormat = DepthFormat.D16;
pp.BackBufferCount = 1;
pp.BackBufferFormat = Format.R5G6B5;
pp.BackBufferWidth = Engine.Current.Window.ViewportWidth;
pp.BackBufferHeight = Engine.Current.Window.ViewportHeight;
pp.EnableAutoDepthStencil = true;
pp.PresentFlag = PresentFlag.None;
pp.SwapEffect = SwapEffect.Discard;
pp.MultiSample = MultiSampleType.None;
pp.FullScreenPresentationInterval = PresentInterval.Default;
pp.Windowed = true;
Нужно быть готовым к тому, что драйвер может даже не поддерживать VSync(PresentationInterval), кроме Default(интеловский не поддерживает). Напоминает ситуацию с встроенной графикой Intel в нулевых, когда она кое-как поддерживала d3d и очень слабо держала ogl.
Формат вершины имеет позицию и текстурную координату. Нормалей нет, т.к ни освещения, ни отражений нет. На данный момент, они тут не нужны. Все расчёты в float(на девайсах без FPU, ага).
Движок
Громко сказано. Это просто центральный объект, который управляет игровым циклом, считает delta time, создаёт окно и остальные подмодули. А ещё он занимается логированием(один-единственный метод Log) и резолвом ассетов. Выполнен как синглтон с конструктором, который создаёт окошко и задаёт базовые параметры, и методом Init, который инициализирует собственно сами подмодули(адепты RAII покидают этот пост и ставят минус)
Звук
Классика. waveOut. Никакого 3D звука и даже панирования, сырой PCM поток направляется прямо в системный микшер через waveOut. Есть ещё DirectShow, но с ним отваливается PPC2003 - а у меня целых два деваса на этой платформе и терять её я не хочу ;P
WAV 8-битный, моно. Этого качества вполне хватает и оно универсально между платформами.
Ввод
Ввод представлен как стандартный Sony-like контроллер, плюс тачскрин. Никакой абстракции типа GetAxis нет, игра получает инпут ровно от того, что ей нужно. Игра поддерживает как тачскрин(игровое поле поделено на две части - каждое отвечает за свое направление движение кораблика), так и дпад. Тоже самое и в менюшках - в будущем это даст возможность портировать игру, например, на Android TV.
Ввод посылает Window, он же разбирается с назначениями клавиш. Таким образом легко протянуть в игру ввод с XInput, Android геймпадов, XNA геймпадов(если будет порт на wp7). Это лучше чем городить отдельные абстракции типа клавиатуры, мыши, тача и геймпада. Фактически весь инпут это структура Touch(одно касание только) и IsKeyPressed. Всё.
Матлиба
Опять же, громко сказано. Универсальная абстракция, дабы не зависеть от типов векторов/матриц GAPI. Реализован Mathf с широко-используемой математикой(интерполяция, градусы в радианы, clamp) и Vector3/Vector4. Для физики используется BoundingBox.
Сами матрицы не представлены как обёртки над матрицами матлибы того GAPI, что мы используем. Вместо этого есть класс Transform который оперирует с позицией/поворотом(углы Эйлера, в будущем можно легко добавить кватернионы)/масштабом.
public Matrix Matrix;
public Vector3 Position;
public Vector3 Rotation;
public Vector3 Scale;
public Transform(Vector3 pos, Vector3 rot, Vector3 scale)
{
Position = pos;
Rotation = rot;
Scale = scale;
Matrix = Matrix.Scaling(scale.X, scale.Y, scale.Z) *
Matrix.RotationY(rot.Y * Mathf.DegToRad) *
Matrix.RotationZ(rot.Z * Mathf.DegToRad) *
Matrix.RotationX(rot.X * Mathf.DegToRad) *
Matrix.Translation(pos.X, pos.Y, pos.Z);
}
Всё! Это весь "движок"! Без шуток ;) Теперь переходим к геймплею.
Геймплей
Как я уже говорил - геймплей строится на том, что кораблик летает из точки в точку по одной оси, и уворачивается(и отстреливает) астероиды(однако противников можно добавить в будущем). "Граф" сцены строится на списке игровых объектов, а игровые объекты наследуются от Entity. Так давайте по порядку!
World
Основной класс в игре, в каком-то смысле даже годобжект. Именно он управляет списком сущностей, спавном и деспавном игровых объектов, рисует фон, анимирует его, считает время и счёт и создаёт SpawnDirector. Кроме того, он рисует HUD(Head's Up Display - "геймплейный" UI).
SpawnDirector же управляет спавном врагов(т.е астероидов) и бонусов в фиксированные промежутки времени в зависимости от сложности. Сложность - нарастающая переменна раз в минуту, которая означает стадию игры. Чем выше стадия, тем быстрее спавнятся и летят астероиды на игрока.
Entity базовый класс для всех игровых объектов. Сам по себе очень примитивный, управляет апдейтами и отрисовкой. Имеет общие для всех объектов свойства - позицию, поворот, масштаб и хитбокс. Адепты противников виртуальных методов могут высказать своё мнение в комментариях(в манагед языке то).
public Vector3 Position;
public Vector3 Rotation;
public Vector3 Scale;
public BoundingBox Bounds;
public Entity()
{
Scale = new Vector3(1, 1, 1);
}
public BoundingBox GetBounds()
{
return new BoundingBox(Position.X + Bounds.X, Position.Y + Bounds.Y, Position.Z + Bounds.Z, Bounds.X2, Bounds.Y2, Bounds.Z2);
}
protected Transform GetTransform()
{
return new Transform(Position, Rotation, Scale);
}
public virtual void Update()
{
}
public virtual void Draw()
{
}
Player
Собственно, класс игрока. Рисует кораблик, обрабатывает ввод от игрока, обрабатывает эффекты от бонусов и анимацию.
Код апдейта:
public override void Update()
{
base.Update();
UpdateFOVEffect();
UpdateInput();
if (nextAttack < 0)
{
if (Bonus == PlayerBonus.DoubleTheFun)
{
Projectile p1 = new Projectile(50, 1, false);
p1.Position = Position;
p1.Position.X -= p1.Bounds.X2;
Projectile p2 = new Projectile(50, 1, false);
p2.Position = Position;
p2.Position.X += p1.Bounds.X2;
Game.Current.World.Spawn(p1);
Game.Current.World.Spawn(p2);
nextAttack = 0.5f;
}
else
{
Projectile proj = new Projectile(50, 1, false);
proj.Position = Position;
Game.Current.World.Spawn(proj);
if (Bonus == PlayerBonus.QuickDick)
nextAttack = 0.3f;
else
nextAttack = 0.5f;
}
}
if (BonusTime < 0)
Bonus = PlayerBonus.None;
Position.X = Mathf.Clamp(Position.X, -World.Bounds, World.Bounds);
nextAttack -= Engine.Current.DeltaTime;
BonusTime -= Engine.Current.DeltaTime;
}
Где UpdateFOVEffect - анимирует плавающий угол обзора, создающий эффект полёта и качения, а UpdateInput - собственно обрабатывает ввод и двигает кораблик:
float strafe = 0;
if (Engine.Current.Input.IsPressed(Key.Left))
strafe = -1;
if (Engine.Current.Input.IsPressed(Key.Right))
strafe = 1;
if (Engine.Current.Input.Touch.IsTouching)
{
if (Engine.Current.Input.Touch.X < Engine.Current.Window.ViewportWidth / 2)
strafe = -1;
else
strafe = 1;
}
Position.X += strafe * (Speed * Engine.Current.DeltaTime);
Rotation.Z = strafe * -RotationEffect;
}
Кораблик сам стреляет в определенные промежутки времени, а эффекты бонусов обрабатываются "на месте", без всяких модных IBonusModifier.
Projectile
Собственно, сам снаряд. Спавнит его игрок, но попозже его смогут спавнить и враги в сторону игрока. Каждый кадр "проходятся" по списку сущностей и, если пересекаются с кем-то, то наносят урон и сами себя уничтожают. Урон снаряда, и его направление регулирует тот, кто стреляет.
public override void Update()
{
base.Update();
foreach (Entity ent in Game.Current.World.EntityList)
{
if (ent.GetBounds().Intersects(GetBounds()))
{
if (ent is Enemy)
{
((Enemy)ent).Health -= damage;
Game.Current.World.Destroy(this);
}
}
}
if (lifeTime < 0)
Game.Current.World.Destroy(this);
lifeTime -= Engine.Current.DeltaTime;
Position.Z += direction * Speed;
}
Pickup
Очевидно - различные бонусы, которые игра может подкидывать, чтобы игрок не скучал(и не умирал слишком рано). Есть два типа - аптечка и случайный бонус:
public abstract class Pickup : Entity
{
public const float Speed = 15.0f;
public Mesh Mesh;
public Material Material;
public Pickup()
{
Mesh = Mesh.FromFile("pickup.md2");
Bounds = new BoundingBox(-15, -15, -15, 15, 15, 15);
}
public override void Draw()
{
base.Draw();
Engine.Current.Graphics.DrawMesh(Mesh, GetTransform(), Material);
}
public override void Update()
{
base.Update();
if(GetBounds().Intersects(Game.Current.World.Player.GetBounds()))
{
Pick();
Game.Current.World.Destroy(this);
}
Rotation.Y += (Speed * 3) * Engine.Current.DeltaTime;
Position.Z -= Speed * Engine.Current.DeltaTime;
}
public abstract void Pick();
}
public class HealthPickup : Pickup
{
public HealthPickup()
: base()
{
Material.Texture = Texture2D.FromFile("health.jpg");
}
public override void Pick()
{
Game.Current.World.Player.Health = Mathf.Clamp(Game.Current.World.Player.Health + 40, 0, 120);
}
}
public class BonusPickup : Pickup
{
public BonusPickup()
: base()
{
Material.Texture = Texture2D.FromFile("upgrade.jpg");
}
public override void Pick()
{
Game.Current.World.Player.TakeBonus((PlayerBonus)new Random().Next(1, (int)PlayerBonus.MaxBonus - 1));
}
}
Enemy
Базовый класс для врагов. Отрисовывает врага, отрабатывает столкновение с игроком. Остальное поведение(в т.ч анимацию и "пуляния"/траекторию отрабатывает дочерний класс).
Asteroid - один из видов врагов. Вот фактически весь код его реализации:
public sealed class Asteroid : Enemy
{
public const float Speed = 15;
public const float Rotate = 56;
public const int HPAmount = 20;
public Asteroid()
{
Mesh = Mesh.FromFile("asteroid.md2");
Material.Texture = Texture2D.FromFile("as0.jpg");
Bounds = new BoundingBox(-10, -10, -10, 10, 10, 10);
}
public override void Update()
{
base.Update();
if (Game.Current.World.Player.GetBounds().Intersects(GetBounds()))
{
Game.Current.World.Player.Health -= HPAmount;
Game.Current.World.Destroy(this);
}
Rotation.X += Rotate * Engine.Current.DeltaTime;
Position.Z -= Speed * Engine.Current.DeltaTime;
}
}
Просто и понятно? Я тоже так считаю, и можно легко добавить новых!
HUD
HUD рисует UI во время игры - т.е здоровье, очки и всё такое. Кроме того, он рисует статус игрока(подобран бонус например).
Заключение
Это скорее технодемка, нежели действительно полноценная игра. Её ещё предстоит доводить в следующей статье - вектор развития выбираете вы в голосовании. Хоть на данный момент это технодемка, в целом, получившийся фреймворк можно использовать не только для таких примитивных игр - например можно сделать простенькие гоночки. Или три в ряд. Возможно будет порт на Android. Если вам зашел такой стиль подачи игровой архитектуры - то я могу написать девлоги и по другим демкам, коих у меня несколько. Например "ралли кубок на тазах"(рабочее название, я питаю тёплые чувства к машинам этого автозавода):
Или арена-шутер для мобилок "мощный семён" и его 2D версия
Репозиторий на гитхабе
Архив с билдом под Windows
Всем спасибо. Жду вас во второй части, а снизу опрос, на что делать упор.
Комментарии (31)
bodyawm Автор
25.10.2022 19:13Возможно будет мультирендер(правда, статически слинкованный), интересно пощупать VincentGL, и оптимизировать игру даже под слабенький HTC Gene.
jaguard
25.10.2022 22:27+4Делал такое в нулевых:
www.youtube.com/watch?v=3GiuQwRY_ng
Платформа винмобайл была крутая, но конечно типично никакой тебе там 3д графики не предусматривалось — и даже обычные афинные преобразования картинок пикселей эдак 60х60 — с большим трудом. 3д ускорители появились на закате платформы и были в 2.5 устройствах (я помню только одно, но кажется были еще).
И конечно, писать риалтайм приложения на богомерзком C# в платформу с древним одноядерным ARM — ну такое.bodyawm Автор
25.10.2022 22:33Сами GPU появилось рано - вроде бы в 2005-2006 уже был 2700G(который PowerVR MBX Lite с видеодекодером от интела), NV GoForce, и ATI Imageon. Из устройств... ну не то чтобы 2.5. Что мне удалось нагуглить, так это то, что были шустрые проприетарные софтрендеры от больших контор, но на что они способны - я не знаю. Вот список:
Intel 2700G: GigaByte GSmart MW998, GigaByte GSmart t600, Dell Axim X51v, Dell Axim X50v.ATI Imageon/Adreno 130: ASUS P835, HTC Touch Diamond2, HTC MAX 4G, HTC Touch HD, HTC Touch Diamond P3700, HTC Touch Pro2, HTC Touch Pro, Sony Ericsson XPERIA X1, Gigabyte GSmart S1200 Sony Ericsson XPERIA X2, Garmin-Asus nüvifone M20.ATI Imageon Z430/Adreno 200: Toshiba TG01, Acer F1 (S200) ,HTC HD2 (Leo) , Garmin-Asus nüvifone M10, LG GW825 IQ, LG GW820 eXpo, LG VS750.GoForce 5500: O2 XDA Flame, i-Mate Ultimate 8150 Sharp EM-ONESamsung 6410: Acer Tempo F900, Acer Tempo M900, Samsung Omnia II (I8000), Samsung OmniaPRO (B7610) Samsung Armani 2 (GT-B7620) в аппаратах на новой платформе от самсунг имеется безымянный ускоритель, чтобы в некоторых играх/программах он был задействован необходимо установить самодельные драйвера
А насчёт шарпа, вот как бы это странно не звучало, но он именно что используется как скриптовый - никаких сложных вычислений нет, матрицы считаются нативно, прямой работы с памятью фактически нет. т.е на нем висит только логика, и команды аля "нарисовать меш". Поэтому работает это шустренько.
Не вижу тебя на гдру. Куда подвелся?)
jaguard
25.10.2022 22:59+1Большая часть списка — трупики на WM5.5-6+, вышедшие после iPhone, никого к тому времени это уже не интересовало. Axim'ов помню, да.
Не вижу тебя на гдру. Куда подвелся?)
После определенных событий пропало желание даже виртуально находиться рядом с людьми определенных идеологических настроений.bodyawm Автор
26.10.2022 07:57Так не забывай что на айфон нельзя было сторонние приложения ставить до выхода второй иоси) плюс не продавался он в рф официально и несмотря на то, что кпк сами по себе недешевые штуки были, за айфон ломили гораздо большие деньги.
jaguard
26.10.2022 14:59Это совсем небольшой срок. WM девайзы вышли в 8-9 году, магазин приложений Appstore появился в 2008, в ноябре-декабре мы уже выпустили первую игру там.
Что касается цен, то коммуникаторы на WM с 3д ускорителем стоили тоже «премиумных» денег.
bodyawm Автор
26.10.2022 08:04и на большинство девайсов были т.н кухни, где люди пока плясали с бубном вокруг старых ядер, портировали свежие wm
bodyawm Автор
25.10.2022 22:39+1концепция .net cf была офигенна - практически полностью переносимые приложения между кпк и пк. Зачем m$ закопала ее в угоду сильверлайту и плиточкам - не понятно. Хотел как эпол?*
jaguard
25.10.2022 22:48+1Концепция — может быть, но работало это все примерно никак — на КПК Compact Framework был жалким подобием настоящего. И вот что удивительно — этот древний франкинштейн в результате пророс внутрь вполне современной Visual Studio 2017/2019, намертво сломав мне возможность ее установки в Windows 8.1 (ошибка при установке возникала именно на этом компоненте — и не чинилось никак).
bodyawm Автор
26.10.2022 07:59.net cf развивался параллельно с wince - когда wm помер в 2009-2010 году, ce еще использовался в wp7, а затем обновлялся где-то до 2013 года. Вот туда новые версии компакта и подвозили :) сейчас он легаси конечно же, а на ce забили.
orcy
27.10.2022 09:21+1Еще поддерживаю на работе некоторые продукты на CE, в enterprise мире остались различного рода устройства которые еще используются по назначению. Однако даже в Enterprise мире теперь на смену CE пришел Android, WEC2013 была вроде последняя ОС этого семейства.
bodyawm Автор
27.10.2022 09:27да, читал об этом. CE в ЧПУ станках частенько используется и прочих промышленных машинах, просто CE в свое время требовала гораздо меньше ресурсов - 16-32мб ОЗУ минимум вместе с GUI, был дотнет и можно было на относительно низком уроне общаться с железом. .NET Compact Framework кстати развивался аж до 3.9 версии, которые уже на вм не выходили, а были чисто для энтерпрайза.
Вкупе с достаточной стабильностью CE, она могла бы найти применение в IoT - например на allwinner v3s с 64мб ОЗУ в чипе, но увы, m$ её прибила.
orcy
28.10.2022 13:19+1но увы, m$ её прибила
У Андроид в этом смысле образовалось преимущество, бесплатность и opensource-ность. Разработчики железа типа allwinner поставляют платы с готовой Android платформой своим клиентам, а те могут делать там хоть телефоны, хоть enterprise устройства и никто не платит за это Microsoft.
RabraBabr
27.10.2022 11:01Ха ха. В пятерочках сканеры штрихкодов на CE. Как то мимо проходил гляжу на сканере приложуха упала и рабочий стол подозрительно знакомый обнажился. Я прям ногтем в пуск сеттингс залез и точно WinCE пятерка кажется.
daggert
25.10.2022 22:50+1Сервелат вообще непонятный продукт был. Мы с знакомыми писали под платформы различные и уже явно было видно что платформа флеш идет к закату - внезапно появляется сервелат... помню смотрел на него тогда с опаской. А майки сделали на него ставку большую. Только довели продукт до релиза - все, EOL. Ну а плитки лично мне зашли сильней чем скевоморфизм эппла и ведра.
bodyawm Автор
26.10.2022 08:03+1ux у системы хороший. Я про вот эту дичь типа зарегайся на 100 девпорталах, скачай 100 сдк и заплати взнос, при этом нельзя просто закинуть бинарник и запустить его. На WM можно любой произвольный бинарник запускать, даже не устанавливая его - и это клево.
fire64
26.10.2022 08:43+4Помню когда-то давно, портировал небольшие игры на OpenGL.
Windows Mobile был хорош тем, что его API очень близок к стандартному Windows API и соответственно очень легко было создавать кроссплатформенный софт.
jaguard
26.10.2022 15:31+2Это было главное преимущество платформы (и еще настоящая многозадачность и многооконность), весьма жалко что пролюбили все полимеры. Я с 2002 с удивлением смотрел — такая классная платформа, а никакой движухи. Делаю игры — продаются 2.5 копии, т.к. 99% людей даже не в курсе, что на КПК можно поставить сторонний софт, или даже если знают — не хотят иметь дело с какими-то непонятными сторонними магазинами. Эпичный фейл.
bodyawm Автор
26.10.2022 15:43расскажи подробнее что за магазины и по чем тогда были БУ кпк/коммуники?
Насчет многооконности я создавал на лоре тред, где пытался разобраться, почему современные мобильные системы не многозадачные, и точно такую же мысль изъявил: в винсе есть окна. Даже в WP8 нет такой многозадачности, хотя она построена уже на NT
jaguard
26.10.2022 15:57Было три основных сторонних магазина: Pocketgear, Handango, Clickgamer, доля рынка у них была плюс-минус одинаково никакая. Первые два благополучно умерли, последний взял нас и еще несколько разработчиков и позвал издаваться на iOS, где мы довольно успешно выступали, пока не пришел ф2п. После его прихода clickgamer продался EA за копейки, а издательство игр благополучно умерло.
Что касается многозадачности, то технически проблем никаких нет, проблема исключительно идеологическая — нельзя давать слишком много бекграунд процессам, ибо жрут батарейку и CPU и влияют на общий юзер экспириенс.
Многооконность в том или ином виде в последних iOS и Android пытается внедряться, тоже вопрос идеологический — как сделать, чтобы было удобно.
ЗЫ: По ценам не могу сказать, не помню, но обычный Pocket PC я купил за довольно небольшие деньги, что-то вроде $200..300.bodyawm Автор
26.10.2022 17:05зп в регионах была 200...
jaguard
26.10.2022 17:34+2ЗП в регионах была не 200, а разная, как и сейчас. Середина нулевых была благополучным периодом: люди накапливали первоначальный капитал после кризиса 98го, цены на квартиры росли кратно, но все еще оставались относительно невысокими, свободки всякие.
… Но при чем тут это все вообще?bodyawm Автор
26.10.2022 18:45Интересно узнать от первоисточника. У меня и батя и маман в 2005 5к получали == 200$
jaguard
26.10.2022 19:10+1Ну я получал от разработки игр под эти самые КПК что-то около $800 в среднем, и не чувствовал себя успешным (зато свободным чувствовал), денег хватало впритык. $200 это очень мало даже по меркам 2005го.
Wolf4D
26.10.2022 18:29+1Я покупал во времена оно игры и софт для КПК на дисках. До сих пор лежит несколько боксов.
bodyawm Автор
26.10.2022 23:32+1Я не знаю, пришли ли вы в эту статью как мой подписчик, или просто нашли статью в гугле/в ленте/в хабе. На всякий перечитал правила, такое вроде бы можно. Если вам статья зашла, и вы хотите проголосовать - не поленитесь прожать плюсик самой статье. Продолжение будет в любом случае(пишем UI не зависящий от разрешения, добавляем профили, магазин, апгрейды и дорабатываем геймплей), но если эта статья наберет 30 плюсиков - то хабр вознаградит меня по правилам ППА(3.000руб).
Деньги пойдут не на еду/квартплату/пиво/карбюратор озон для ваз 21074, а на заказ запчастей для будущих статей, у меня есть еще много девайсов, на которые было бы интересно взглянуть вам: например флагманский смартфон на x86, планшет-трансформер, подделка под самсунг из 2014 за 4.000руб(он именно новым стоял столько), дешевые телефоны по 100 рублей, сони эриксон с натурально сожженным дисплеем зажигалкой(не мной).
Если вам статья понравилась - плюсик очень поможет. На ништяки у меня не так много личных денег.
bodyawm Автор
Я не знаю, пришли ли вы в эту статью как мой подписчик, или просто нашли статью в гугле/в ленте/в хабе. На всякий перечитал правила, такое вроде бы можно. Если вам статья зашла, и вы хотите проголосовать - не поленитесь прожать плюсик самой статье. Продолжение будет в любом случае(пишем UI не зависящий от разрешения, добавляем профили, магазин, апгрейды и дорабатываем геймплей), но если эта статья наберет 30 плюсиков - то хабр вознаградит меня по правилам ППА(3.000руб).
Деньги пойдут не на еду/квартплату/пиво/карбюратор озон для ваз 21074, а на заказ запчастей для будущих статей, у меня есть еще много девайсов, на которые было бы интересно взглянуть вам: например флагманский смартфон на x86, планшет-трансформер, подделка под самсунг из 2014 за 4.000руб(он именно новым стоял столько), дешевые телефоны по 100 рублей, сони эриксон с натурально сожженным дисплеем зажигалкой(не мной).
Если вам статья понравилась - плюсик очень поможет. На ништяки у меня не так много личных денег.