Все функции ниже будут представлены на языке Java.
В этой статье я представлю основные математические алгоритмы, без которых не обойдется написание 2D игр.
И так, что будет в статье:
1. Измерение расстояния между двумя точками.
2. Уравнение прямой и для чего оно нужно.
3. Определение перпендикуляра с точки на линию
4. Пересечение отрезков
5. Вращение по кругу
6. Определение углов между линиями
7. Нахождение средней точки на отрезке
1) Измерение расстояния между двумя точками:
Начнем с простого, но пожалуй самого применяемого алгоритма.
public double distance(int x1, int y1, int x2, int y2)
{
// Расчет расстояния между двумя точками
return Math.sqrt(Math.pow(x2 - x1, 2) +
Math.pow(y2 - y1, 2) * 1.0);
}
Или такая универсальная функция
public class Main {
public static double euclidianDistance(double[] doubles1,
double[] doubles2) {
double result = 0;
for (int i = 0; i < doubles1.length; i++) {
result += Math.pow(doubles1[i] - doubles2[i], 2);
}
return Math.sqrt(result);
}
}
2) Уравнение прямой.
Уравнение прямой может применяться для множества расчетов.
- Для определения лежит ли точка на прямой;
- Можно построить параллельную линию лежащую на определенной точке;
- Движение наискосок (движение от точки к точке).
И многое другое. Поэтому я приведу основные формулы.
Уравнение прямой по точке и угловому коэффициенту.
y = mx + b
y = как далеко вверх
x = как далеко вперед
m = уклон или градиент (насколько крута линия (соотношение сторон))
b = значение y, когда x=0
Ниже пример
m = 2/1 = 2
b = 1 (значение y при x=0 (можно попробовать x сдвинуть на 0))
Итак: y = 2x + 1
Теперь выберите любое значение для x и найдите соответствующее значение для y
Например, когда x равно 3:
y = 2×3 + 1 = 7
И конечно долгожданная функция на Java позволяющая построить уравнение прямой по двум точкам 2D:
class Point {
final float x;
final float y;
public Point(float x1, float y1) {
x = x1;
y = y1;
}
}
class MyClass {
public static void main(String[] args) {
Point xy1 = new Point(4, -1); // Точка 1 x=4; y=-1;
Point xy2 = new Point(3, -6); // Точка 2 x=3; y=-6
// y = mx+b
float m = (xy1.y-xy2.y)/(xy1.x-xy2.x);
float b = -(m*xy1.x)+xy1.y;
//assert -(m*xy2.x)+xy2.y == b;
if (b >= 0) {
System.out.println("y = "+m+"x+"+b); // Собственно вывод данных
} else {
System.out.println("y = "+m+"x"+b);
}
}
}
Дальше рассмотрим каноническое уравнение прямой
И уравнение прямой по двум точкам:
Из нее можно вывести y = y1 + [(y2 - y1) / (x2 - x1)]·(x - x1)
Как вы поняли тут даже функцию на Java не надо приводить.
Теперь посмотрим на параметрические уравнения прямой на плоскости
Эта формула строится из знакомого нам уже уравнения
Поэтому
P1 = X2-X1, a P2 = Y2-Y1
P1 и P2 – по сути это наш направляющий вектор
t – это наш коэффициент с помощью которого можно например двигать точку по прямой, т.е. умножая на t двигаем все координаты по прямой (по вектору)
X0 и Y0 – точка лежащая на прямой
Так и быть, представлю функцию на Java все же эта статья для начинающих:
public float[] n_funk(float koef, float n_x0, float n_y0,
float x1, float y1,
float x2, float y2){
float _x = (x2 - x1)*koef + n_x0;
float _y = (y2 - y1)*koef + n_y0;
float[] ghj ={_x,_y};
return ghj;
}
Перейдем к следующему пункту
3) Определение перпендикуляра с точки на линию
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
public class Main {
public static Point2D.Double getPerpendicularPointToLine(Point2D ptA,
Point2D ptB, Point2D ptC) {
if (ptA == null || ptB == null || ptA.equals(ptB) || ptC == null) {
return null;
}
double ax = ptA.getX(), ay = ptA.getY();
double bx = ptB.getX(), by = ptB.getY();
double cx = ptC.getX(), cy = ptC.getY();
double r = ((ay - cy) * (ay - by) + (ax - cx) * (ax - bx))
/ Point2D.distanceSq(ax, ay, bx, by);
return new Point2D.Double(ax + r * (bx - ax), ay + r * (by - ay));
}
public static Point2D.Double getPerpendicularPointToLine(Line2D line,
Point2D ptC) {
if (line == null || ptC == null) {
return null;
}
return getPerpendicularPointToLine(line.getP1(), line.getP2(), ptC);
}
}
4) Пересечение отрезков
Используется для определения столкновений 2D объектов
public boolean intersection(double ax,double ay, double bx, double by, double cx, double cy, double dx, double dy)
{ // Формула определения пересечения отрезков
double common = (bx - ax)*(dy - cy) - (by - ay)*(dx - cx);
if (common == 0) return false;
double rH = (ay - cy)*(dx - cx) - (ax - cx)*(dy - cy);
double sH = (ay - cy)*(bx - ax) - (ax - cx)*(by - ay);
double r = rH / common;
double s = sH / common;
if (r >= 0 && r <= 1 && s >= 0 && s <= 1)
return true;
else
return false;
}
5) Вращение по кругу
Приведу функцию нахождения уравнения окружности
import java.util.*;
class solution
{
// Функция нахождения уравнения окружности по центру и радиусу
static void circle_equation(double x1, double y1, double r)
{
double a = -2 * x1;
double b = -2 * y1;
double c = (r * r) - (x1 * x1) - (y1 * y1);
// Вывод данных
System.out.print("x^2 + (" +a+ " x) + ");
System.out.print("y^2 + ("+b + " y) = ");
System.out.println(c +"." );
}
// Driver code
public static void main(String arr[])
{
double x1 = 2, y1 = -3, r = 8;
circle_equation(x1, y1, r);
}
}
Повращаем наши точки по кругу с помощью следующей функции
public float[] func_cicle(float radius, float centr_x, float centr_y, float angle){
// Хоть здесь и написано angle по сути это градус от 0 до 360
float angleRad = (float) Math.toRadians(angle);
float x = centr_x + radius * Math.sin(angleRad);
float y = centr_y + radius * Math.cos(angleRad);
float[] x_y_point = { x, y };
return x_y_point;
}
6) Определение углов между линиями
(В функцию даются 3 точки. Одна точка общая для двух линий )
import java.awt.geom.*;
import java.util.*;
public class Main{
public static double angle(double x1, double y1, double x2, double y2,
double x3, double y3) {
final double dx1 = x1 - x2;
final double dy1 = y1 - y2;
final double dx2 = x3 - x2;
final double dy2 = y3 - y2;
final double ang1 = Math.atan2(dx1, dy1);
final double ang2 = Math.atan2(dx2, dy2);
final double angle = ang2 - ang1;
return GeometryUtils.trimAngle(angle);
}
public static double trimAngle(double angle) {
if (angle > Math.PI) {
return angle - 2. * Math.PI;
}
if (angle < -Math.PI) {
return angle + 2. * Math.PI;
}
return angle;
}
}
Ниже еще одна функция находящая все углы треугольника
import java.awt.Point;
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
import static java.lang.Math.acos;
class Test
{
static int lengthSquare(Point p1, Point p2)
{
int xDiff = p1.x- p2.x;
int yDiff = p1.y- p2.y;
return xDiff*xDiff + yDiff*yDiff;
}
static void printAngle(Point A, Point B,
Point C)
{
int a2 = lengthSquare(B,C);
int b2 = lengthSquare(A,C);
int c2 = lengthSquare(A,B);
// Длина сторон a, b, c
float a = (float)sqrt(a2);
float b = (float)sqrt(b2);
float c = (float)sqrt(c2);
float alpha = (float) acos((b2 + c2 - a2)/(2*b*c));
float betta = (float) acos((a2 + c2 - b2)/(2*a*c));
float gamma = (float) acos((a2 + b2 - c2)/(2*a*b));
// Преобразование к углам
alpha = (float) (alpha * 180 / PI);
betta = (float) (betta * 180 / PI);
gamma = (float) (gamma * 180 / PI);
// Отображение
System.out.println("alpha : " + alpha);
System.out.println("betta : " + betta);
System.out.println("gamma : " + gamma);
}
// Запуск
public static void main(String[] args)
{
Point A = new Point(0,0); // Точки треугольника x и y
Point B = new Point(0,1);
Point C = new Point(1,0);
printAngle(A,B,C); // Здесь запускаем функцию
}
}
7) Нахождение средней точки на отрезке
public void midpoint(int x1, int x2,
int y1, int y2)
{
System.out.print((x1 + x2) / 2 + " , " + (y1 + y2) / 2) ; // Выводим
}
Если вам понравилась статья, не забудьте подписаться на канал.