Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

math and other stuff #316

Merged
merged 4 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion docs/game_data/spel2.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions docs/src/includes/_globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,16 @@ Load another script by id "author/name" and import its `exports` table. Returns:
- `false` if the script was not found but optional is set to true
- an error if the script was not found and the optional argument was not set

### intersection


> Search script examples for [intersection](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=intersection)

#### [Vec2](#Vec2) intersection(const [Vec2](#Vec2) A, const [Vec2](#Vec2) B, const [Vec2](#Vec2) C, const [Vec2](#Vec2) D)

Find intersection point of two lines [A, B] and [C, D], returns INFINITY if the lines don't intersect each other [parallel]


### is_character_female


Expand Down Expand Up @@ -1646,6 +1656,20 @@ Returns true if a bitmask is set in the number.

Open or close the journal as if pressing the journal button. Will respect visible journal popups and [force_journal](#force_journal).

### two_lines_angle


> Search script examples for [two_lines_angle](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=two_lines_angle)

#### float two_lines_angle([Vec2](#Vec2) A, [Vec2](#Vec2) common, [Vec2](#Vec2) B)

Mesures angle between two lines with one common point

#### float two_lines_angle([Vec2](#Vec2) line1_A, [Vec2](#Vec2) line1_B, [Vec2](#Vec2) line2_A, [Vec2](#Vec2) line2_B)

Gets line1_A, intersection point and line2_B and calls the 3 parameter version of this function


### update_liquid_collision_at


Expand Down
11 changes: 10 additions & 1 deletion docs/src/includes/_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,8 @@ float | [top_left_y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=to
[Quad](#Quad)& | [rotate(float angle, float px, float py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=rotate) | Rotates a [Quad](#Quad) by an angle, px/py are not offsets, use `:get_AABB():center()` to get approximated center for simetrical quadrangle
[Quad](#Quad)& | [flip_horizontally()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flip_horizontally) |
[Quad](#Quad)& | [flip_vertically()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flip_vertically) |
bool | [is_point_inside(Vec2 p, optional<float> epsilon)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_point_inside) | Check if point lies inside of triangle<br/>Because of the imprecise nature of floating point values, the `epsilon` value is needed to compare the floats, the default value is `0.00001`
bool | [is_point_inside(float x, float y, optional<float> epsilon)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_point_inside) |
tuple&lt;[Vec2](#Vec2), [Vec2](#Vec2), [Vec2](#Vec2), [Vec2](#Vec2)&gt; | [split()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=split) | Returns the corners in order: bottom_left, bottom_right, top_right, top_left

### RenderInfo
Expand Down Expand Up @@ -803,7 +805,10 @@ Type | Name | Description
[Vec2](#Vec2) | [center()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=center) | Also known as centroid
tuple&lt;float, float, float&gt; | [get_angles()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_angles) | Returns ABC, BCA, CAB angles in radians
[Triangle](#Triangle)& | [scale(float scale)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=scale) |
tuple&lt;[Vec2](#Vec2), [Vec2](#Vec2), [Vec2](#Vec2)&gt; | [split()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=split) | Returns the corners
float | [area()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=area) |
bool | [is_point_inside(Vec2 p, optional<float> epsilon)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_point_inside) | Check if point lies inside of triangle<br/>Because of the imprecise nature of floating point values, the `epsilon` value is needed to compare the floats, the default value is `0.0001`
bool | [is_point_inside(float x, float y, optional<float> epsilon)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_point_inside) |
tuple&lt;[Vec2](#Vec2), [Vec2](#Vec2), [Vec2](#Vec2)&gt; | [split()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=split) | Returns the corner points

### Vec2

Expand Down Expand Up @@ -1902,6 +1907,7 @@ Derived from [Screen](#Screen)

Type | Name | Description
---- | ---- | -----------
[SoundMeta](#SoundMeta) | [bg_music_info](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bg_music_info) |

### ScreenDeath

Expand All @@ -1919,6 +1925,9 @@ Derived from [Screen](#Screen)
Type | Name | Description
---- | ---- | -----------
[TextureRenderingInfo](#TextureRenderingInfo) | [unknown4](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=unknown4) |
float | [darkness](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=darkness) |
bool | [active](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=active) | ends the intro immediately if set to false
bool | [skip_prologue](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=skip_prologue) | skips prologue and goes straight to the title screen after the intro

### ScreenLeaderboards

Expand Down
2 changes: 1 addition & 1 deletion src/game_api/drops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ std::vector<DropEntry> drop_entries{
{"KAPALA_HEALTH", "\xBA\x01\x00\x00\x00\xB8\x01"s, VTABLE_OFFSET::NONE, 0, 1},
/* can't do elixir as there are some calculations for cursed, poisoned etc.
can't do pet, it has some complex calculation for some reason
can't do ankh as it is a byte, and some complex stuff
can't do ankh made a separete function for that (see modify_ankh_health_gain)
can't do initial health (camp, level, duat, coffin) as it's a word/byte
can't do drops for: humphead, yetiking, yetiqueen, alien queen, pangxie (gems) those are stored in array, need special funciton for that
*/
Expand Down
71 changes: 71 additions & 0 deletions src/game_api/math.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
#include "math.hpp"

bool Triangle::is_point_inside(Vec2 p, float epsilon) const
{
// you can compare it eather by area or by angle
// not sure if one if faster thne the order, so i left code for both

// float area1 = Triangle(A, B, p).area();
// float area2 = Triangle(A, C, p).area();
// float area3 = Triangle(B, C, p).area();
// return std::abs(this->area() - (area1 + area2 + area3)) < epsilon;

float angle1 = two_lines_angle(A, p, B);
float angle2 = two_lines_angle(B, p, C);
float angle3 = two_lines_angle(C, p, A);
const float pi = 3.14159f;
return std::abs(pi - (angle1 + angle2 + angle3)) < epsilon;
}

Vec2 intersection(const Vec2 A, const Vec2 B, const Vec2 C, const Vec2 D)
{
float a = B.y - A.y;
Expand All @@ -17,3 +34,57 @@ Vec2 intersection(const Vec2 A, const Vec2 B, const Vec2 C, const Vec2 D)

return Vec2{(b1 * c - b * c1) / det, (a * c1 - a1 * c) / det};
}

float two_lines_angle(Vec2 A, Vec2 common, Vec2 B)
{
Vec2 ab = common - B;
Vec2 bc = A - common;
return std::atan2((bc.y * ab.x - bc.x * ab.y), (bc.x * ab.x + bc.y * ab.y));
};

float two_lines_angle(Vec2 line1_A, Vec2 line1_B, Vec2 line2_A, Vec2 line2_B)
{
return two_lines_angle(line1_A, intersection(line1_A, line1_B, line2_A, line2_B), line2_B);
};

bool Quad::is_point_inside(Vec2 p, float epsilon) const
{
std::tuple<Vec2, Vec2, Vec2, Vec2> points = *this;

const Vec2 extra_point{999.0f, p.y};
int count = 0;
AABB cd{p, Vec2{INFINITY, p.y}};
cd.abs().extrude(0, epsilon);

auto check_if_on_line = [&cd, &epsilon](Vec2& A, Vec2& B, Vec2& ints) // this only makes sense together with intersection function
{
AABB ab{A, B};
ab.abs().extrude(A.x == B.x ? epsilon : 0, A.y == B.y ? epsilon : 0);

if (ab.is_point_inside(ints) && cd.is_point_inside(ints))
return true;

return false;
};
auto first = intersection(std::get<0>(points), std::get<1>(points), p, extra_point);
if (!isinf(first.x) && check_if_on_line(std::get<0>(points), std::get<1>(points), first))
{
++count;
}
auto second = intersection(std::get<1>(points), std::get<2>(points), p, extra_point);
if (!isinf(second.x) && check_if_on_line(std::get<1>(points), std::get<2>(points), second))
{
++count;
}
auto third = intersection(std::get<2>(points), std::get<3>(points), p, extra_point);
if (!isinf(third.x) && check_if_on_line(std::get<2>(points), std::get<3>(points), third))
{
++count;
}
auto fourth = intersection(std::get<3>(points), std::get<0>(points), p, extra_point);
if (!isinf(fourth.x) && check_if_on_line(std::get<3>(points), std::get<0>(points), fourth))
{
++count;
}
return (count & 1); // check if not even
}
68 changes: 56 additions & 12 deletions src/game_api/math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,20 +238,20 @@ struct AABB
return (top - bottom);
}
/// Checks if point lies between left/right and top/bottom
bool is_point_inside(const Vec2 p)
bool is_point_inside(const Vec2 p) const
{
AABB copy{*this};
copy.abs();
if (copy.left < p.x && copy.right > p.x && copy.bottom < p.y && copy.top > p.y)
if (copy.left <= p.x && copy.right >= p.x && copy.bottom <= p.y && copy.top >= p.y)
return true;

return false;
}
bool is_point_inside(float x, float y)
bool is_point_inside(float x, float y) const
{
AABB copy{*this};
copy.abs();
if (copy.left < x && copy.right > x && copy.bottom < y && copy.top > y)
if (copy.left <= x && copy.right >= x && copy.bottom <= y && copy.top >= y)
return true;

return false;
Expand Down Expand Up @@ -349,11 +349,31 @@ struct Triangle
C = (C - centroid) * scale + centroid;
return *this;
}
float area() const
{
return std::abs((A.x * (B.y - C.y) + B.x * (C.y - A.y) + C.x * (A.y - B.y)) / 2.0f);
}
bool is_point_inside(Vec2 p) const
{
return is_point_inside(p, 0.0001f);
}
bool is_point_inside(Vec2 p, float epsilon) const;
bool is_point_inside(float x, float y) const
{
return is_point_inside(Vec2{x, y}, 0.0001f);
}
bool is_point_inside(float x, float y, float epsilon) const
{
return is_point_inside(Vec2{x, y}, epsilon);
}

/*
/// Returns the corners
std::tuple<Vec2, Vec2, Vec2> split()
{} // just for the autodoc
/* // just for the autodoc
/// Returns the corner points
std::tuple<Vec2, Vec2, Vec2> split();
/// Check if point lies inside of triangle
/// Because of the imprecise nature of floating point values, the `epsilon` value is needed to compare the floats, the default value is `0.0001`
bool is_point_inside_triangle(Vec2 p, std::optional<float> epsilon);
bool is_point_inside_triangle(float x, float y, std::optional<float> epsilon);
*/

/// Returns the corners
Expand Down Expand Up @@ -470,10 +490,28 @@ struct Quad

return *this;
}
/*

bool is_point_inside(Vec2 p) const
{
return is_point_inside(p, 0.00001f);
}
bool is_point_inside(Vec2 p, float epsilon) const;
bool is_point_inside(float x, float y) const
{
return is_point_inside(Vec2{x, y}, 0.00001f);
}
bool is_point_inside(float x, float y, float epsilon) const
{
return is_point_inside(Vec2{x, y}, epsilon);
}

/* // just for the autodoc
/// Returns the corners in order: bottom_left, bottom_right, top_right, top_left
std::tuple<Vec2, Vec2, Vec2, Vec2> split()
{} // just for the autodoc
std::tuple<Vec2, Vec2, Vec2, Vec2> split();
/// Check if point lies inside of triangle
/// Because of the imprecise nature of floating point values, the `epsilon` value is needed to compare the floats, the default value is `0.00001`
bool is_point_inside_quad(Vec2 p, std::optional<float> epsilon);
bool is_point_inside_quad(float x, float y, std::optional<float> epsilon);
*/

/// Returns the corners in order: bottom_left, bottom_right, top_right, top_left
Expand All @@ -492,5 +530,11 @@ struct Quad
float top_left_y{0};
};

// get intersection point of two lines
/// Find intersection point of two lines [A, B] and [C, D], returns INFINITY if the lines don't intersect each other [parallel]
Vec2 intersection(const Vec2 A, const Vec2 B, const Vec2 C, const Vec2 D);

/// Mesures angle between two lines with one common point
float two_lines_angle(Vec2 A, Vec2 common, Vec2 B);

/// Gets line1_A, intersection point and line2_B and calls the 3 parameter version of this function
float two_lines_angle(Vec2 line1_A, Vec2 line1_B, Vec2 line2_A, Vec2 line2_B);
7 changes: 6 additions & 1 deletion src/game_api/screen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ class ScreenIntro : public Screen // ID: 1
{
public:
TextureRenderingInfo unknown4;
float darkness;
/// ends the intro immediately if set to false
bool active;
/// skips prologue and goes straight to the title screen after the intro
bool skip_prologue;
};

class ScreenPrologue : public Screen // ID: 2
Expand Down Expand Up @@ -605,7 +610,7 @@ class ScreenCredits : public Screen // ID: 17
{
public:
float* credits_progression;
size_t bg_music_info; /* unsure */
SoundMeta* bg_music_info;
};

class ScreenScores : public Screen // ID: 18
Expand Down
Loading
Loading