четверг, 26 ноября 2015 г.

Движение объекта по кругу (2D)

Рассмотрим простой алгоритм движения спрайта по кругу с заданной скоростью и заданным радиусом движения.
Мы будем использовать две тригонометрические функции: синус и косинус. Синус будет задавать изменение координаты X, а косинус - Y.
Для примера я взял картинки с игры The Binding of Isaac. В игре мухи "защитные" спутники летают вокруг Айзека по кругу. Сделаем тоже самое и мы!
В примере будут 3 основных объекта: главный персонаж и две мухи, которые будут летать вокруг него.

 Для начала нужно создать свой тип данных (подобие класса):

Type object            \\тип данных называем object    
sprite as integer       \\номер спрайта
radius as integer       \\радиус круга
angle as float             \\угол поворота
base_x as float            \\х-координата точки вокруг которой будет летать муха
base_y as float              \\у-координата точки вокруг которой будет летать муха
rotate_speed as float      \\скорость движения
endtype                            \\конец типа данных

Этот тип данных нам нужен для удобства написания игры. Можно, конечно, каждый параметр занести в отдельную переменную, но тогда можно легко запутаться.

Dim object[2] as object   \\создаем массив данных под названием object, в котором будет два                                                 элемента (можно больше), тип данных указываем наш (object)

Дальше создадим функцию которая будет создавать объект в игре (муху). ID - это номер объекта (у нас будет 1 или 2):

Function CreateObject(ID,x,y,radius,image)
object[ID].sprite=CreateSprite(image)
object[ID].base_x=x
object[ID].base_y=y
SetSpritePositionByOffset(object[ID].sprite,object[ID].base_x,object[ID].base_y)
object[ID].radius=radius
endfunction

И главная функция которая будет делать основную работу:

Function RotateObject(ID)
object[ID].angle=object[ID].angle+object[ID].rotate_speed
x#=object[ID].base_x+object[ID].radius*sin(object[ID].angle)
y#=object[ID].base_y+object[ID].radius*cos(object[ID].angle)
SetSpritePositionByOffset(object[ID].sprite,x#,y#)
endfunction

Координату x# определяем основываясь на базовой координате объекта object[ID].base_x и значении object[ID].radius*sin(object[ID].angle). Тоже самое будет и с координатой y#.

Теперь посмотрим весь код целиком:

global screen_x=1280     \\переменная в которой хранится ширина окна
global screen_y=720        \\переменная в которой хранится высота окна

SetVirtualResolution(screen_x,screen_y)  \\выставляем разрешение окна

LoadImage(1,"1.png")    \\изображение мухи_1
LoadImage(2,"2.png")    \\муха_2
LoadImage(3,"3.png")    \\герой (попрошайка)
LoadImage(4,"4.png")    \\ фон

Type object
sprite as integer
radius as integer
angle as float
base_x as float
base_y as float
rotate_speed as float
endtype

Dim object[2] as object

CreateObject(1,screen_x/2,screen_y/2,100,1) \\создаем муху_1 в центре экрана
CreateObject(2,screen_x/2,screen_y/2,300,2)  \\создаем муху_2 в центре экрана

object[1].rotate_speed=0.5   \\устанавливаем скорость полета для 1
object[2].rotate_speed=1      \\устанавливаем скорость полета для 2

CreateSprite(1,3)             \\создаем спрайт героя в центре
SetSpritePositionByOffset(1,screen_x/2,screen_y/2)
CreateSprite(2,4)              \\создаем фон
SetSpritePositionByOffset(2,screen_x/2,screen_y/2)
SetSpriteDepth(2,16)    \\устанавливаем фон на задний план  (16 это глубина, по стандарту 10)

DO   \\начало цикла
RotateObject(1)  \\двигаем первый объект
RotateObject(2)  \\двигаем второй объект
 Sync()  \\обновление экрана
LOOP \\конец цикла

///////////////////////////////
Function RotateObject(ID)
object[ID].angle=object[ID].angle+object[ID].rotate_speed
x#=object[ID].base_x+object[ID].radius*sin(object[ID].angle)
y#=object[ID].base_y+object[ID].radius*cos(object[ID].angle)
SetSpritePositionByOffset(object[ID].sprite,x#,y#)
endfunction
///////////////////////////////
Function CreateObject(ID,x,y,radius,image)
object[ID].sprite=CreateSprite(image)
object[ID].base_x=x
object[ID].base_y=y
SetSpritePositionByOffset(object[ID].sprite,object[ID].base_x,object[ID].base_y)
object[ID].radius=radius
endfunction


Скачать демонстрацию
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Если нужно изменить движение в противоположную сторону, меняем в строке
 x#=object[ID].base_x+object[ID].radius*sin(object[ID].angle)
знак + на -
 x#=object[ID].base_x-object[ID].radius*sin(object[ID].angle)
Вот и все.
Код написан в App Game Kit, но реализовать его можно в любой другой программе, главное понять сам принцип.


Комментариев нет:

Отправить комментарий