P
P
Pavel Matveev2019-07-11 14:44:27
C++ / C#
Pavel Matveev, 2019-07-11 14:44:27

How to organize movement in 2D at a certain angle?

There is an object. With the "right" and "left" buttons, it rotates to a certain angle. When you press the "forward" and "backward" buttons, it should move accordingly, at a certain angle. I don't understand how to implement this in C++. Because I only know the coordinates of the object (i.e. x and y), the hypotenuse (i.e. speed) and the angle with respect to the axes, I tried through a right triangle and its legs, i.e. through sines and cosines, but in the end the object did not move at the angle that was given to it. How can this be implemented?
Who does/did how?
The function that produces the movement:

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 - скорость движения/длина вектора/для гипотенузы.

Units of measurement are degrees, but to rotate the image, you have to convert to radians (in the output function). I use the Allegro lib.
al_draw_rotated_bitmap(image, x,y , imX, imY, imageRad+(3.14159/180), 0);

Here is the main code:
#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;
}

Starting position. The origin is in the upper left corner. Angle 0 degrees.
5d27585e0bea2599225872.png
Pressed forward... Came
5d27586808497089521312.png
back to the center, rotated the image and pressed forward again...
5d2758700368a459700608.png

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
dollar, 2019-07-11
@axe_lankaster13

That's just the sines and cosines and are the answer to the question.
And if you can't, then there's an error somewhere. What units are you using for the angle? Give a small example of the piece of code that calculates the new coordinates. And also the results are an example of what is obtained and what is expected for different input parameters.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question