Есть объект. Кнопками "вправо" и "влево" он поворачивается на определённый угол. При нажатии кнопок "вперёд" и "назад" он должен двигаться соответственно, под определённым углом. Не понимаю, как это реализовать на С++. Т.к. мне известны только координаты объекта(т.е. x и y), гипотенуза(т.е. скорость) и угол по отношению к осям, я пробовал через прямоугольный треугольник и его катеты, т.е. через синусы и косинусы, но объект в итоге двигался не под тем углом, который ему задавался. Как это можно реализовать ?
Кто как делает/делал ?
Функция, которая производит движение:
void MoveAhead(int& x, int& y, int imageRad, int speed)
{
int xangle = 0;
int yangle = 0;
if (imageRad >= 0 && imageRad <= 90)
{
xangle = 90 - imageRad;
yangle = 0 - imageRad;
xangle = (xangle < 0) ? xangle * -1 : xangle;
yangle = (yangle < 0) ? yangle * -1 : yangle;
}
else if (imageRad >= 90 && imageRad <= 180)
{
xangle = 90 - imageRad;
yangle = 180 - imageRad;
xangle = (xangle < 0) ? xangle * -1 : xangle;
yangle = (yangle < 0) ? yangle * -1 : yangle;
}
else if (imageRad >= 180 && imageRad <= 270)
{
xangle = 180 - imageRad;
yangle = 270 - imageRad;
xangle = (xangle < 0) ? xangle * -1 : xangle;
yangle = (yangle < 0) ? yangle * -1 : yangle;
}
else if (imageRad >= 270 && imageRad <= 360)
{
xangle = 270 - imageRad;
yangle = 360 - imageRad;
xangle = (xangle < 0) ? xangle * -1 : xangle;
yangle = (yangle < 0) ? yangle * -1 : yangle;
}
float ycoord = speed * sin(yangle * 3.14159 / 180);
float xcoord = speed * sin(xangle * 3.14159 / 180);
x += xcoord;
y += ycoord;
}
imageRad - градусы поворота изображения/градусы угла относительно осей.
speed - скорость движения/длина вектора/для гипотенузы.
Единицы измерения - градусы, но для поворота изображения приходится переводить в радианы(в функции вывода). Использую либу Allegro.
al_draw_rotated_bitmap(image, x,y , imX, imY, imageRad+(3.14159/180), 0);
Вот код main:
#include <allegro5\allegro.h>
#include <allegro5\allegro_image.h>
#include <math.h>
#include <allegro5\allegro_font.h>
#include <allegro5\allegro_ttf.h>
enum KEYS { UP, DOWN, LEFT, RIGHT };
void MoveAhead(int& imX, int& imY, int imageRad, int speed, int x, int y);
int main(void)
{
//variables
int width = 640;
int height = 480;
bool done = false;
int FPS = 60;
bool keys[4] = { false, false, false, false };
int imageWidth = 0;
int imageHeight = 0;
int imageRad = 0;
int speed = 10;
int x, y;
int imX;
int imY;
//allegro variable
ALLEGRO_DISPLAY* display = NULL;
ALLEGRO_EVENT_QUEUE* event_queue = NULL;
ALLEGRO_BITMAP* image = NULL;
ALLEGRO_TIMER* timer = NULL;
ALLEGRO_FONT* font18 = NULL;
//program init
if (!al_init()) //initialize Allegro
return -1;
display = al_create_display(width, height); //create our display object
timer = al_create_timer(1.0 / FPS);
if (!display) //test display object
return -1;
//addon init
al_install_keyboard();
al_init_image_addon();
al_init_font_addon();
al_init_ttf_addon();
font18 = al_load_font("arial.ttf", 18, 0);
image = al_load_bitmap("spider.png");
imageWidth = al_get_bitmap_width(image);
imageHeight = al_get_bitmap_height(image);
x = imageWidth / 2;
y = imageHeight / 2;
imX = width / 2 - imageWidth / 2;
imY = height / 2 - imageHeight / 2;
event_queue = al_create_event_queue();
al_register_event_source(event_queue, al_get_keyboard_event_source());
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_start_timer(timer);
while (!done)
{
ALLEGRO_EVENT ev;
al_wait_for_event(event_queue, &ev);
if (ev.type == ALLEGRO_EVENT_KEY_DOWN)
{
switch (ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
case ALLEGRO_KEY_RIGHT:
case ALLEGRO_KEY_D:
keys[RIGHT] = true;
break;
case ALLEGRO_KEY_LEFT:
case ALLEGRO_KEY_A:
keys[LEFT] = true;
break;
case ALLEGRO_KEY_UP:
case ALLEGRO_KEY_W:
keys[UP] = true;
break;
case ALLEGRO_KEY_DOWN:
case ALLEGRO_KEY_S:
keys[DOWN] = true;
break;
}
}
else if (ev.type == ALLEGRO_EVENT_KEY_UP)
{
switch (ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = false;
break;
case ALLEGRO_KEY_RIGHT:
case ALLEGRO_KEY_D:
keys[RIGHT] = false;
break;
case ALLEGRO_KEY_LEFT:
case ALLEGRO_KEY_A:
keys[LEFT] = false;
break;
case ALLEGRO_KEY_UP:
case ALLEGRO_KEY_W:
keys[UP] = false;
break;
case ALLEGRO_KEY_DOWN:
case ALLEGRO_KEY_S:
keys[DOWN] = false;
break;
}
}
else if (ev.type == ALLEGRO_EVENT_TIMER)
{
if (keys[UP])
MoveAhead(imX, imY, imageRad, speed, x, y);
if (keys[DOWN])
MoveAhead(imX, imY, imageRad, -speed, x, y);
if (keys[LEFT])
{
imageRad -= 5;
if (imageRad <= 0)
imageRad = 360;
}
if (keys[RIGHT])
{
imageRad += 5;
if (imageRad >= 360)
imageRad = 0;
}
}
al_draw_textf(font18, al_map_rgb(255, 255, 255), 20, 10, ALLEGRO_ALIGN_CENTRE, "%i", imageRad);
al_draw_textf(font18, al_map_rgb(255, 255, 255), width-50, 10, ALLEGRO_ALIGN_CENTRE, "%f", (imageRad*3.14159)/180.0);
al_draw_rotated_bitmap(image, x,y , imX, imY, imageRad*(3.14159/180), 0);
al_flip_display();
al_clear_to_color(al_map_rgb(0, 0, 0));
}
al_destroy_font(font18);
al_destroy_bitmap(image);
al_destroy_event_queue(event_queue);
al_destroy_timer(timer);
al_destroy_display(display); //destroy our display object
return 0;
}
Начальное положение. Начало координат в верхнем левом углу. Угол 0 градусов.
Нажал вперёд...
Вернулся в центр, повернул изображение и снова нажал вперёд...