SGDK. Двигаем много спрайтов.

Данная статья является продолжением урока SGDK. Двигаем спрайт по экрану.

Откройте проект из предыдущего урока, будем его дорабатывать.

Сперва, определим константу, которая будет задавать размер массива для спрайтов. Добавьте её после #include.

#define CUP_COUNT 10

Т.к. мы будем работать с несколькими спрайтами, нам потребуется создать объект, который будет хранить:

  • позицию спрайта
  • его скорость
  • сам спрайт
  • размер спрайта

В-общем, все то что хранили в отдельных переменных, теперь, будет помещено в структуру, из которой, будем обращаться к этим переменным. Это нужно, что-бы в будущем, можно было прогнать эти объекты по циклу.

Замените старые переменные, новой структурой.

typedef struct
{
	Sprite *sprite;
	s16 posX;
	s16 posY;
	s16 x_spd;
	s16 y_spd;
	u16 cup_width;
	u16 cup_height;
} Cup;

Следующей строкой, создайте массив этих объектов (структур).

Cup cups[CUP_COUNT];

Замените строку SPR_addSprite, перед while, на новый вариант.

s16 i;
for(i = 0; i<CUP_COUNT; i++) {
	s16 randSpdX = (random() % 5)+1;
	s16 randSpdY = (random() % 5)+1;
	Cup oneCup = {NULL, 0, 0, randSpdX, randSpdY, 64, 64};
	Sprite* spr = SPR_addSprite(&spr_cup, oneCup.posX,  oneCup.posY, TILE_ATTR(PAL3, 0, FALSE, FALSE));
	oneCup.sprite = spr;
	cups[i] = oneCup;
}

Разберем данный код.

for(i = 0; i<CUP_COUNT; i++) {

Создали цикл, который проходится по всем элементам массива cups.

s16 randSpdX = (random() % 5)+1;
s16 randSpdY = (random() % 5)+1;

Функция random() — возвращает случайное целое число. от этого числа, взяли остаток от деления на 5

random() % 5

Тем самым, получили число в диапазоне от 0 до 4. Ноль нам не нужен, поэтому прибавляем 1.

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

Cup oneCup = {NULL, 0, 0, randSpdX, randSpdY, 64, 64};

Мы создали объект oneCup по шаблону, взятому из структуры Cup, теперь у oneCup есть собственные набор переменных. Далее, заполняем объект значениями, в том порядке, в котором расположили переменные в структуре. Спрайт, пока не указан, ставим NULL.

Sprite* spr = SPR_addSprite(&spr_cup, oneCup.posX,  oneCup.posY, TILE_ATTR(PAL3, 0, FALSE, FALSE));

Добавляем спрайт на экран, в отличии от прошлого урока, здесь используются координаты объекта oneCup.

oneCup.sprite = spr;

Присваиваем этот спрайт к объекту (обращение к переменным объекта осуществляется через точку)

cups[i] = oneCup;

И добавили объект в массив.

Теперь, начнем двигать эти спрайты. Измените цикл while, на следующее.

while(1)
{
	SPR_update();
        SYS_doVBlankProcess();
	for(i = 0; i<CUP_COUNT; i++) {
		Cup oneCup = cups[i];
		oneCup.posX += oneCup.x_spd;
		oneCup.posY += oneCup.y_spd;
	
		if(oneCup.posX > 320-oneCup.cup_width || oneCup.posX < 0)
			oneCup.x_spd *= -1;
		if(oneCup.posY > 240-oneCup.cup_height || oneCup.posY < 0)
			oneCup.y_spd *= -1;
		SPR_setPosition(oneCup.sprite, oneCup.posX, oneCup.posY);
		cups[i] = oneCup;
      }
}

У каждого элемента массива.

for(i = 0; i<CUP_COUNT; i++) {

Достали объект из массива, и записали в отдельную переменную (для удобства).

Cup oneCup = cups[i];

После чего, сделали все те же действия, что и раньше, но с использованием координат внутри объекта.

oneCup.posX += oneCup.x_spd;
oneCup.posY += oneCup.y_spd;
if(oneCup.posX > 320-oneCup.cup_width || oneCup.posX < 0)
	oneCup.x_spd *= -1;
if(oneCup.posY > 240-oneCup.cup_height || oneCup.posY < 0)
	oneCup.y_spd *= -1;
SPR_setPosition(oneCup.sprite, oneCup.posX, oneCup.posY);

И записали объект oneCup, обратно в массив.

Готово. В итоге, получили следующее.

Итоговый результат.