У меня есть проект, в котором я хочу создать игру, в которой используются корабли в стиле астероидов, чтобы продемонстрировать поведение нахождения пути и управления ИИ.
Объект сохраняет значения для положения центра тяжести треугольника (в противном случае положение игрока) и ориентации кораблей в градусах, а затем вычисляет положение трех вершин следующим образом:
А это нос треугольника. Когда ориентация равна 0 градусам, нос корабля сидит на оси Х, смещенной по РАЗМЕРУ, который определяет размер корабля, равный радиусу его ограничивающей окружности.
Вершины B и C поворачиваются от положения A на 120 и 240 градусов соответственно, затем программа рисует отрезки линии между каждой вершиной.
Когда я запускаю программу, это прекрасно работает, и мой ограничительный круг, вектор ориентации и корабль выглядят так, как я ожидаю.
Тем не менее, я реализовал элемент управления таким образом, что угол увеличивается и уменьшается с помощью клавиш со стрелками влево и вправо. Этот контроль был проверен и доказал свою работоспособность. Когда это происходит, вектор ориентации корректируется соответствующим образом, и корабль вращается … но только в некотором роде. Точки немедленно перемещаются в центр массы, пока они не разрушатся в центре и не исчезнут навсегда, независимо от того, в каком направлении я поверну.
//Convert degrees into radians
float Ship::convert(float degrees){
return degrees*(PI/180);
}
//Rotation X-Coord
int Ship::rotateX(int x, int y, float degrees){
return (x*cos(convert(degrees)))-(y*sin(convert(degrees)));
}
//Rotate Y-Coord
int Ship::rotateY(int x, int y, float degrees){
return x*sin(convert(degrees))+y*cos(convert(degrees));
}
//Rotate the Ship
void Ship::rotateShip(float degrees){
vertA [0]=rotateX(vertA [0], vertA [1], degrees);
vertA [1]=rotateY(vertA [0], vertA [1], degrees);
vertB [0]=rotateX(vertB [0], vertB [1], degrees);
vertB [1]=rotateY(vertB [0], vertB [1], degrees);
vertC [0]=rotateX(vertC [0], vertC [1], degrees);
vertC [1]=rotateY(vertC [0], vertC [1], degrees);
}
Функции поворота работают нормально, но я не уверен, что вращение корабля работает. Кажется, это должно быть — переменные vert — это массивы, в которых хранятся координаты X и Y этой вершины. Если я поверну каждую вершину на угол ориентации корабля, то теоретически он должен вращать треугольник в его центре, верно?
Все верты откалиброваны относительно начала координат, и функция drawShip () в объекте Game берет эти координаты и добавляет playerX и playerY, чтобы перевести полностью нарисованный корабль в позицию игрока. По сути, переводя его в начало координат, поворачивая его и переводя обратно в положение игрока.
Если это поможет, я включу соответствующие функции из игрового объекта. В этом коде psp является объектом Ship. Розыгрыш корабля принимает все параметры корабля и должен работать, но я получаю нежелательные результаты.
//Draw Ship
void Game::drawShip1(int shipX, int shipY, int vel, int alpha, int size, int* vertA, int* vertB, int* vertC, int r, int g, int b){
//Draw a bounding circle
drawCircle(shipX, shipY, size, 0, 255, 255);
//Draw the ship by connecting vertices A, B, and C
//Segment AB
drawLine(shipX+vertA[0], shipY+vertA[1], shipX+vertB [0], shipY+vertB [1], r, g, b);
//Segment AC
drawLine(shipX+vertA[0], shipY+vertA[1], shipX+vertC [0], shipY+vertC [1], r, g, b);
//Segment BC
drawLine(shipX+vertB[0], shipY+vertB[1], shipX+vertC [0], shipY+vertC [1], r, g, b);
}void Game::ComposeFrame()
{
float pAlpha=psp.getAlpha();
if(kbd.LeftIsPressed()){
pAlpha-=1;
psp.setAlpha(pAlpha);
psp.rotateShip(psp.getAlpha());
}
if(kbd.RightIsPressed()){
pAlpha+=1;
psp.setAlpha(pAlpha);
psp.rotateShip(psp.getAlpha());
}
//Draw Playership
drawShip1(psp.getX(), psp.getY(), psp.getV(), psp.getAlpha(), psp.getSize(), psp.getVertA(), psp.getVertB(), psp.getVertC(), psp.getR(), psp.getG(), psp.getB());
drawLine(psp.getX(), psp.getY(), psp.getX()+psp.rotateX(0+psp.getSize(), 0, psp.getAlpha()), psp.getY()+psp.rotateY(0+psp.getSize(), 0, psp.getAlpha()), psp.getR(), psp.getG(), psp.getB());
}
Я вижу несколько проблем в вашем коде, которые могут добавить к результату, который вы видите.
Первое, что вы обрабатываете координаты как целые числа. Из-за этого десятичные знаки обрезаются, а значение становится все меньше и меньше. Используйте float или даже double.
Второе — вращение происходит в два этапа. Первый шаг (вычисление координаты X) является правильным. Однако второй шаг (вычисление координаты y) является ошибочным. Вы используете новую X-координату, но должны предоставить старую. Вы должны реализовать метод, который вращает полный вектор, а не его часть. Почему вы не используете математические функции DirectX?
Других решений пока нет …