Статичні зображення у Cocos2d-x

6 хв. читання

У попередньому пості ми з'ясували, як створити базовий проєкт програми у Cocos2d-x. Точніше, він створювався автоматично скриптом cocos, потрібно було його лише скомпілювати та запустити.

Цього разу я розкажу про основні терміни, поняття та класи фреймворку, а також поясню, як вони використовувались у базовому проєкті. Наприкінці, щоб продемонструвати ці основні поняття, ми напишемо невелику програму, котра виводитиме на екран кілька зображень.

Розмір екрана програми

Але почати хотілося б з одного моменту, який ми не обговорили у попередній статті. Розглянута там дефолтна програма працює у вікні 480 на 320 пікселів. Цей розмір було вказано у файлі AppDelegate.cpp ось в такому рядку:

static cocos2d::Size designResolutionSize = cocos2d::Size(480, 320);

Розробники Cococ2d-x щось перемудрили, тому поряд з цією змінною оголошені ще кілька інших розмірів. Окрім того, далі ці інші розміри нібито використовуються в якихось розрахунках, але насправді це все неважливо.

Роботі з розміром екрана на мобільних пристроях (або при повноекранному запуску на десктопі) буде присвячено окремий пост пізніше. Поки що просто повірте, що розмір вікна тестової програми на Linux чи Windows вказується саме у designResolutionSize. Якщо вам не подобаються зайві змінні для розмірів екрана, ви можете їх просто видалити, як у цьому файлі.

В інших місцях для позиціювання елементів я поки що буду використовувати абсолютні (захардкоджені) числа. Це не дуже добра практика, але так код сприйматиметься простіше.

Повернемось до теорії.

Node і його нащадки

Node — базовий клас, що реалізує спільну для об'єктів сцени функціональність.

Усі об'єкти Node мають такі властивості:

  • позицію;
  • масштаб;
  • кут повороту (у градусах за годинниковою стрілкою);
  • положення опорної точки;
  • розмір вмісту (contentSize);
  • видимість.

Окрім того, Node реалізує відносини parent-child. Можна призначити один об'єкт дитиною іншого, тоді при видаленні батьківського об'єкта він видалить всіх своїх дітей. Пізніше буде окремий пост про роботу з пам'яттю та створення-видалення об'єктів, а поки що у тестових програмах це не так важливо.

У нашій програмі було три нащадки Node:

  • Sprite — призначений для виведення зображень;
  • Label — це панель для тексту;
  • MenuItemImage — це один клас для виведення зображень, але ще він має функціональність кнопки.

Ось всі вони у нашій дефолтній програмі:

Статичні зображення у Cocos2d-x
Розбір тестової програми

Напис «GL Verts / GL calls» не є частиною сцени. Це налагоджувальна інформація, яку фреймворк додає до вікна програми. Її можна приховати, але поки цього робити не варто, вона ще знадобиться.

В принципі, згаданий вище клас Scene також є нащадком Node. Але він використовується трохи інакше, ніж інші, тому його краще було розглядати окремо.

Координати та опорна точка

Cocos2d використовує «шкільну» систему координат:

  • x змінюється по горизонталі зліва направо
  • y змінюється по вертикалі знизу вверх.

Центр системи координат розташований в опорній точці (anchor point). Положення опорної точки можна задавати окремо для кожного об'єкта Node методом setAnchorPoint. Метод отримує два параметри у діапазоні від 0 до 1, найчастіше це значення 0, 0.5 або 1. Наприклад:

  • setActionPoint(Vec2(0.5, 0.5)) встановлює опорну точку в центр об'єкта.
  • setActionPoint(Vec2(0, 0)) встановлює опорну точку в лівий нижній кут об'єкта. Так автоматично робить клас Scene.
  • setActionPoint(Vec2(0, 1)) встановлює опорну точку в лівий верхній кут об'єкта. Це схоже на систему координат, прийняту в html canvas або Qt, але, на відміну від них, вісь Y все ще направлена знизу вверх.

Програма з фоном

Щоб побачити, як це все працює, ми візьмемо малюнок з клітинками по 160х120 пікселів і зробимо його фоновим зображенням програми.

Статичні зображення у Cocos2d-x
Порожня сітка, осі координат, розміри

Робиться це за допомогою такого коду, розміщеного у функції init сцени:

const char backFilename[] = "background.png";

Sprite* sprite = Sprite::create(backFilename);
if (sprite == nullptr) {
  printf("Error while loading: %s\
", backFilename);
  return false;
}

sprite->setAnchorPoint(Vec2(0,0));
sprite->setPosition(0,0);
addChild(sprite, 0);

Спрайт створюється за допомогою статичного методу create. Це стандартна для Cocos2d практика — майже у кожного класу є такий метод, за допомогою якого і треба створювати об'єкти.

Потім ми встановлюємо опорну точку спрайту в лівий нижній кут і ставимо спрайт на центр координат сцени (який теж розташований у лівому нижньому куті).

Метод addChild додає новостворений спрайт на сцену. Другим параметром цього методу є z-order: якщо без подробиць, це число, яке визначає порядок «перекривання» елементів. Елементи з більшим числом будуть намальовані пізніше, відповідно, менші стануть для них фоном.

Більше спрайтів

Тепер додамо до сцени ще пару спрайтів. Один за допомогою ось такого коду:

const char shipFilename[] = "ships/playerShip3_blue.png";

Sprite* sprite = Sprite::create(shipFilename);

sprite->setAnchorPoint(Vec2(0.5,0.5));
sprite->setPosition(Vec2(160, 240));

addChild(sprite, 10);

А інший ось так:

const char shipFilename[] = "ships/playerShip3_blue.png";
Sprite* sprite = Sprite::create(shipFilename);

sprite->setRotation(45);
sprite->setPosition(Vec2(160, 120));

addChild(sprite, 10);

Відмінність у тому, що в другому випадку спрайт додатково повертається на 45 градусів.

В обох спрайтів опорна точка розташована в центрі (0.5, 0.5). Відповідно, після встановлення позиції, центр спрайту опиниться на перетині квадратів, ось так:

Статичні зображення у Cocos2d-x
Опорна точка синіх кораблів розташована в центрі об'єкта

Створимо ще два спрайти, ось так:

const char shipFilename[] = "ships/playerShip3_green.png";
Sprite* sprite = Sprite::create(shipFilename);

sprite->setAnchorPoint(Vec2(0,0));
sprite->setPosition(Vec2(480, 240));

addChild(sprite, 10);

і так:

const char shipFilename[] = "ships/playerShip3_green.png";
Sprite* sprite = Sprite::create(shipFilename);

sprite->setAnchorPoint(Vec2(0,0));
sprite->setRotation(45);
sprite->setPosition(Vec2(480, 120));

addChild(sprite, 10);

Тут опорна точка спрайтів встановлюється у нижній лівий кут, також другий спрайт повертається на 45 градусів.

Результат:

Статичні зображення у Cocos2d-x

Опорна точка у зелених кораблів розташована на перетині квадратів, тому самі спрайти опинились правіше і вище. У другому випадку поворот здійснено навколо опорної точки.

Node

Об'єкти класу Node можна використовувати для групування об'єктів. Наприклад, можна зібрати власний корабель, скомбінувавши три зображення:

Статичні зображення у Cocos2d-x

Для цього потрібен такий код:

const char cockpitFilename[] = "parts/cockpitRed.png";
Sprite* cockpitSprite = Sprite::create(cockpitFilename);

const char wingFilename[] = "parts/wingRed.png";
Sprite* rightWingSprite = Sprite::create(wingFilename);
Sprite* leftWingSprite = Sprite::create(wingFilename);

Node* resultNode = Node::create();
resultNode->setAnchorPoint(Vec2(0.5,0.5));

//
rightWingSprite->setAnchorPoint(Vec2(0.5,0.5));
rightWingSprite->setScale(1, -1);
rightWingSprite->setPosition(Vec2(60, 15));
rightWingSprite->setRotation(90);
resultNode->addChild(rightWingSprite);

leftWingSprite->setAnchorPoint(Vec2(0.5,0.5));
leftWingSprite->setPosition(Vec2(-60, 15));
leftWingSprite->setRotation(90);
resultNode->addChild(leftWingSprite);

resultNode->addChild(cockpitSprite);
//
resultNode->setAnchorPoint(Vec2(0.5,0.5));

Спершу ми створюємо три спрайти (два крила та фюзеляж) і порожній об'єкт Node, який об'єднає ці елементи.

Спрайти крил повертаються та встановлюються у потрібне положення. Координати для їх встановлення (60, 15) добираються емпірично, щоб було більш-менш гарно. Крім того, спрайт правого крила треба віддзеркалити викликом setScale(1, -1).

Наприкінці окремі спрайти додаються у якості дітей до вузла-результату. Робота з фінальним об'єктом не відрізняється від роботи з одиноким спрайтом, тому я тут не буду наводити цей код. Як і все інше, його можна знайти у проєкті-прикладі на GitHub.

У результаті наша тестова програма стане такою:

Статичні зображення у Cocos2d-x

На цьому поки що все, дякую за увагу. У наступних постах зображення почнуть рухатись, тож стане цікавіше :)

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.8K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація