Найти тему
Making games is easy!

Математические алгоритмы для 2D игр. (на Java)

Оглавление

Все функции ниже будут представлены на языке 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);

}

}

}

Дальше рассмотрим каноническое уравнение прямой

-2

И уравнение прямой по двум точкам:

-3

Из нее можно вывести y = y1 + [(y2 - y1) / (x2 - x1)]·(x - x1)

Как вы поняли тут даже функцию на Java не надо приводить.

Теперь посмотрим на параметрические уравнения прямой на плоскости

-4

Эта формула строится из знакомого нам уже уравнения

-5

Поэтому

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) ; // Выводим

}

Если вам понравилась статья, не забудьте подписаться на канал.