diff --git a/Crawler/Crawler.vcxproj b/Crawler/Crawler.vcxproj
index 9c6368ef..a47757da 100644
--- a/Crawler/Crawler.vcxproj
+++ b/Crawler/Crawler.vcxproj
@@ -133,6 +133,7 @@
+
diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters
index ea59ed75..69ac8a8b 100644
--- a/Crawler/Crawler.vcxproj.filters
+++ b/Crawler/Crawler.vcxproj.filters
@@ -27,6 +27,9 @@
Header Files
+
+ Header Files
+
diff --git a/Crawler/assets/nico-warrior.png b/Crawler/assets/nico-warrior.png
index 03428b2e..9b84f38a 100644
Binary files a/Crawler/assets/nico-warrior.png and b/Crawler/assets/nico-warrior.png differ
diff --git a/Crawler/assets/nico-warrior.xcf b/Crawler/assets/nico-warrior.xcf
index 361693c7..1ce35b5b 100644
Binary files a/Crawler/assets/nico-warrior.xcf and b/Crawler/assets/nico-warrior.xcf differ
diff --git a/Crawler/main.cpp b/Crawler/main.cpp
index 29d6e38d..84793f09 100644
--- a/Crawler/main.cpp
+++ b/Crawler/main.cpp
@@ -3,18 +3,51 @@
#include "olcUTIL_Camera2D.h"
#define OLC_PGEX_TRANSFORMEDVIEW
#include "olcPGEX_TransformedView.h"
+#include "olcUTIL_Animate2D.h"
using namespace olc;
using namespace olc::utils;
const vi2d WINDOW_SIZE={24*8,24*8};
+enum AnimationState{
+ WALK_S,WALK_E,WALK_N,WALK_W,
+ IDLE_S,IDLE_E,IDLE_N,IDLE_W
+};
+
struct Player{
vf2d pos;
float moveSpd;
+ AnimationState animState=AnimationState::IDLE_S;
+ private:
+ Animate2D::Animationanimation;
+ Animate2D::AnimationState internal_animState;
+ Key lastReleasedMovementKey;
+ public:
Player(){};
Player(vf2d pos,float moveSpd):
- pos(pos),moveSpd(moveSpd){};
+ pos(pos),moveSpd(moveSpd){
+ };
+ void Update(float fElapsedTime){
+ animation.UpdateState(internal_animState,fElapsedTime);
+ }
+ void AddAnimation(AnimationState state,Animate2D::FrameSequence frame){
+ animation.AddState(state,frame);
+ };
+ void UpdateAnimation(AnimationState animState){
+ animation.ChangeState(internal_animState,animState);
+ }
+
+ Animate2D::Frame GetFrame(){
+ return animation.GetFrame(internal_animState);
+ }
+
+ void SetLastReleasedMovementKey(Key k){
+ lastReleasedMovementKey=k;
+ }
+ Key GetLastReleasedMovementKey(){
+ return lastReleasedMovementKey;
+ }
};
class Crawler : public olc::PixelGameEngine
@@ -23,6 +56,7 @@ class Crawler : public olc::PixelGameEngine
Camera2D camera;
TileTransformedView view;
Player player=Player{{},100};
+ Renderable GFX_Pl_sheet;
public:
Crawler()
@@ -33,35 +67,167 @@ public:
public:
bool OnUserCreate() override
{
+ //Initialize Camera.
camera=Camera2D{WINDOW_SIZE};
camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow);
camera.SetTarget(player.pos);
camera.SetWorldBoundary({0,0},WORLD_SIZE*24);
camera.EnableWorldBoundary(false);
+
+ //Graphics
+ GFX_Pl_sheet.Load("assets/nico-warrior.png");
+
+ //Animations
+ Animate2D::FrameSequence pl_walk_s{0.2};
+ pl_walk_s.AddFrame({&GFX_Pl_sheet,{vi2d{0,0}*24,{24,24}}});
+ pl_walk_s.AddFrame({&GFX_Pl_sheet,{vi2d{1,0}*24,{24,24}}});
+ pl_walk_s.AddFrame({&GFX_Pl_sheet,{vi2d{0,0}*24,{24,24}}});
+ pl_walk_s.AddFrame({&GFX_Pl_sheet,{vi2d{2,0}*24,{24,24}}});
+ Animate2D::FrameSequence pl_walk_e{0.2};
+ pl_walk_e.AddFrame({&GFX_Pl_sheet,{vi2d{0,3}*24,{24,24}}});
+ pl_walk_e.AddFrame({&GFX_Pl_sheet,{vi2d{1,3}*24,{24,24}}});
+ pl_walk_e.AddFrame({&GFX_Pl_sheet,{vi2d{0,3}*24,{24,24}}});
+ pl_walk_e.AddFrame({&GFX_Pl_sheet,{vi2d{2,3}*24,{24,24}}});
+ Animate2D::FrameSequence pl_walk_w{0.2};
+ pl_walk_w.AddFrame({&GFX_Pl_sheet,{vi2d{0,2}*24,{24,24}}});
+ pl_walk_w.AddFrame({&GFX_Pl_sheet,{vi2d{1,2}*24,{24,24}}});
+ pl_walk_w.AddFrame({&GFX_Pl_sheet,{vi2d{0,2}*24,{24,24}}});
+ pl_walk_w.AddFrame({&GFX_Pl_sheet,{vi2d{2,2}*24,{24,24}}});
+ Animate2D::FrameSequence pl_walk_n{0.2};
+ pl_walk_n.AddFrame({&GFX_Pl_sheet,{vi2d{0,1}*24,{24,24}}});
+ pl_walk_n.AddFrame({&GFX_Pl_sheet,{vi2d{1,1}*24,{24,24}}});
+ pl_walk_n.AddFrame({&GFX_Pl_sheet,{vi2d{0,1}*24,{24,24}}});
+ pl_walk_n.AddFrame({&GFX_Pl_sheet,{vi2d{2,1}*24,{24,24}}});
+ Animate2D::FrameSequence pl_idle_s;
+ pl_idle_s.AddFrame({&GFX_Pl_sheet,{vi2d{0,0}*24,{24,24}}});
+ Animate2D::FrameSequence pl_idle_e;
+ pl_idle_e.AddFrame({&GFX_Pl_sheet,{vi2d{0,3}*24,{24,24}}});
+ Animate2D::FrameSequence pl_idle_w;
+ pl_idle_w.AddFrame({&GFX_Pl_sheet,{vi2d{0,2}*24,{24,24}}});
+ Animate2D::FrameSequence pl_idle_n;
+ pl_idle_n.AddFrame({&GFX_Pl_sheet,{vi2d{0,1}*24,{24,24}}});
+
+
+ player.AddAnimation(WALK_N,pl_walk_n);
+ player.AddAnimation(WALK_E,pl_walk_e);
+ player.AddAnimation(WALK_S,pl_walk_s);
+ player.AddAnimation(WALK_W,pl_walk_w);
+ player.AddAnimation(IDLE_N,pl_idle_n);
+ player.AddAnimation(IDLE_E,pl_idle_e);
+ player.AddAnimation(IDLE_S,pl_idle_s);
+ player.AddAnimation(IDLE_W,pl_idle_w);
view=TileTransformedView{GetScreenSize(),{1,1}};
+
+ player.UpdateAnimation(IDLE_S);
+
return true;
}
bool OnUserUpdate(float fElapsedTime) override
{
HandleUserInput(fElapsedTime);
+ player.Update(fElapsedTime);
UpdateCamera(fElapsedTime);
RenderWorld();
return true;
}
void HandleUserInput(float fElapsedTime){
+ bool setIdleAnimation=true;
if(GetKey(RIGHT).bHeld){
player.pos.x+=fElapsedTime*player.moveSpd;
+ player.UpdateAnimation(WALK_E);
+ setIdleAnimation=false;
}
if(GetKey(LEFT).bHeld){
player.pos.x-=fElapsedTime*player.moveSpd;
+ if(setIdleAnimation){
+ player.UpdateAnimation(WALK_W);
+ }
+ setIdleAnimation=false;
}
if(GetKey(UP).bHeld){
player.pos.y-=fElapsedTime*player.moveSpd;
+ if(setIdleAnimation){
+ player.UpdateAnimation(WALK_N);
+ }
+ setIdleAnimation=false;
}
if(GetKey(DOWN).bHeld){
player.pos.y+=fElapsedTime*player.moveSpd;
+ if(setIdleAnimation){
+ player.UpdateAnimation(WALK_S);
+ }
+ setIdleAnimation=false;
+ }
+
+ if(GetKey(UP).bReleased){
+ player.SetLastReleasedMovementKey(UP);
+ if(GetKey(RIGHT).bHeld){
+ player.UpdateAnimation(WALK_E);
+ } else
+ if(GetKey(DOWN).bHeld){
+ player.UpdateAnimation(WALK_S);
+ } else
+ if(GetKey(LEFT).bHeld){
+ player.UpdateAnimation(WALK_W);
+ }
+ }
+ if(GetKey(RIGHT).bReleased){
+ player.SetLastReleasedMovementKey(RIGHT);
+ if(GetKey(UP).bHeld){
+ player.UpdateAnimation(WALK_N);
+ } else
+ if(GetKey(DOWN).bHeld){
+ player.UpdateAnimation(WALK_S);
+ } else
+ if(GetKey(LEFT).bHeld){
+ player.UpdateAnimation(WALK_W);
+ }
+ }
+ if(GetKey(LEFT).bReleased){
+ player.SetLastReleasedMovementKey(LEFT);
+ if(GetKey(RIGHT).bHeld){
+ player.UpdateAnimation(WALK_E);
+ } else
+ if(GetKey(DOWN).bHeld){
+ player.UpdateAnimation(WALK_S);
+ } else
+ if(GetKey(UP).bHeld){
+ player.UpdateAnimation(WALK_N);
+ }
+ }
+ if(GetKey(DOWN).bReleased){
+ player.SetLastReleasedMovementKey(DOWN);
+ if(GetKey(RIGHT).bHeld){
+ player.UpdateAnimation(WALK_E);
+ } else
+ if(GetKey(UP).bHeld){
+ player.UpdateAnimation(WALK_N);
+ } else
+ if(GetKey(LEFT).bHeld){
+ player.UpdateAnimation(WALK_W);
+ }
+ }
+
+ if(setIdleAnimation){
+ switch(player.GetLastReleasedMovementKey()){
+ case UP:{
+ player.UpdateAnimation(IDLE_N);
+ }break;
+ case DOWN:{
+ player.UpdateAnimation(IDLE_S);
+ }break;
+ case LEFT:{
+ player.UpdateAnimation(IDLE_W);
+ }break;
+ case RIGHT:{
+ player.UpdateAnimation(IDLE_E);
+ }break;
+ default:{
+ player.UpdateAnimation(IDLE_S);
+ }
+ }
}
}
@@ -71,13 +237,13 @@ public:
}
void RenderWorld(){
- Clear(BLACK);
+ Clear({100,180,100});
for (int x = view.GetTopLeftTile().x/24-1; x <= view.GetBottomRightTile().x/24; x++){
for (int y = view.GetTopLeftTile().y/24-1; y <= view.GetBottomRightTile().y/24; y++){
view.DrawRect(vi2d{x,y}*24,{24,24},VERY_DARK_GREY);
}
}
- view.DrawCircle(player.pos,8);
+ view.DrawPartialDecal(player.pos-vi2d{12,12},player.GetFrame().GetSourceImage()->Decal(),player.GetFrame().GetSourceRect().pos,player.GetFrame().GetSourceRect().size);
}
};
diff --git a/Crawler/olcUTIL_Animate2D.h b/Crawler/olcUTIL_Animate2D.h
index 0fe2fc29..5fd8c01f 100644
--- a/Crawler/olcUTIL_Animate2D.h
+++ b/Crawler/olcUTIL_Animate2D.h
@@ -55,7 +55,7 @@ David Barr, aka javidx9, �OneLoneCoder 2019, 2020, 2021, 2022
#pragma once
#include "olcPixelGameEngine.h"
-#include "utilities/olcUTIL_Geometry2D.h"
+#include "olcUTIL_Geometry2D.h"
namespace olc::utils::Animate2D
{
diff --git a/Crawler/olcUTIL_Geometry2D.h b/Crawler/olcUTIL_Geometry2D.h
new file mode 100644
index 00000000..1b7d1be9
--- /dev/null
+++ b/Crawler/olcUTIL_Geometry2D.h
@@ -0,0 +1,1046 @@
+/*
+OneLoneCoder - Geometry 2D v1.01
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A collection of 2D Geometric primitives and functions to work with
+and between them.
+
+
+License (OLC-3)
+~~~~~~~~~~~~~~~
+
+Copyright 2018 - 2022 OneLoneCoder.com
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions or derivations of source code must retain the above
+copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions or derivative works in binary form must reproduce
+the above copyright notice. This list of conditions and the following
+disclaimer must be reproduced in the documentation and/or other
+materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Links
+~~~~~
+YouTube: https://www.youtube.com/javidx9
+Discord: https://discord.gg/WhwHUMV
+Twitter: https://www.twitter.com/javidx9
+Twitch: https://www.twitch.tv/javidx9
+GitHub: https://www.github.com/onelonecoder
+Homepage: https://www.onelonecoder.com
+
+Author
+~~~~~~
+David Barr, aka javidx9, �OneLoneCoder 2019, 2020, 2021, 2022
+
+Changes:
+v1.01: +Made constants inline
++Header guards (lol... sigh...)
+
+*/
+
+#pragma once
+#include "olcPixelGameEngine.h"
+
+namespace olc::utils::geom2d
+{
+ // Lemon Meringue
+ inline const double pi = 3.141592653589793238462643383279502884;
+
+ // Floating point error margin
+ inline const double epsilon = 0.001;
+
+ //https://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
+ template
+ constexpr int sgn(T val) { return (T(0) < val) - (val < T(0)); }
+
+ // Defines a line segment
+ template
+ struct line
+ {
+ olc::v2d_generic start;
+ olc::v2d_generic end;
+
+ inline line(const olc::v2d_generic& s = { T(0), T(0) },
+ const olc::v2d_generic& e = { T(0), T(0) })
+ : start(s), end(e)
+ { }
+
+
+ // Get length of line
+ inline constexpr T length()
+ {
+ return (end - start).mag();
+ }
+
+ // Get length of line^2
+ inline constexpr T length2()
+ {
+ return (end - start).mag2();
+ }
+
+ inline constexpr olc::v2d_generic vector() const
+ {
+ return (end - start);
+ }
+
+ // Given a real distance, get point along line
+ inline constexpr olc::v2d_generic rpoint(const T& distance) const
+ {
+ return start + (end - start).norm() * distance;
+ }
+
+ // Given a unit distance, get point along line
+ inline constexpr olc::v2d_generic upoint(const T& distance) const
+ {
+ return start + (end - start) * distance;
+ }
+
+ // Return which side of the line does a point lie
+ inline constexpr int32_t side(const olc::v2d_generic& point) const
+ {
+ double d = (end - start).cross(point - start);
+ if (d < 0)
+ return -1;
+ else
+ if (d > 0)
+ return 1;
+ else
+ return 0;
+ }
+ };
+
+ template
+ struct ray
+ {
+ olc::v2d_generic origin;
+ olc::v2d_generic direction;
+ };
+
+ template
+ struct rect
+ {
+ olc::v2d_generic pos;
+ olc::v2d_generic size;
+
+ inline rect(const olc::v2d_generic& p = { T(0), T(0) },
+ const olc::v2d_generic& s = { T(1), T(1) })
+ : pos(p), size(s)
+ { }
+
+ inline olc::v2d_generic middle() const
+ {
+ return pos + (size * double(0.5));
+ }
+
+ // Get line segment from top side of rectangle
+ inline line top() const
+ {
+ return { pos, {pos.x + size.x, pos.y } };
+ }
+
+ // Get line segment from bottom side of rectangle
+ inline line bottom() const
+ {
+ return { {pos.x, pos.y + size.y}, pos + size };
+ }
+
+ // Get line segment from left side of rectangle
+ inline line left() const
+ {
+ return { pos, {pos.x, pos.y + size.y} };
+ }
+
+ // Get line segment from right side of rectangle
+ inline line right() const
+ {
+ return { {pos.x + size.x, pos.y }, pos + size };
+ }
+
+ // Get a line from an indexed side, starting top, going clockwise
+ inline line side(const size_t i) const
+ {
+ if (i & 0b11 == 0) return top();
+ if (i & 0b11 == 1) return right();
+ if (i & 0b11 == 2) return bottom();
+ if (i & 0b11 == 3) return left();
+ }
+
+ // Get area of rectangle
+ inline constexpr T area() const
+ {
+ return size.x * size.y;
+ }
+
+ // Get perimeter of rectangle
+ inline constexpr T perimeter() const
+ {
+ return T(2) * (size.x + size.y);
+ }
+ };
+
+
+ template
+ struct circle
+ {
+ olc::v2d_generic pos;
+ T radius = T(0);
+
+ inline circle(const olc::v2d_generic& p = { T(0), T(0) }, const T r = T(0))
+ : pos(p), radius(r)
+ { }
+
+ // Get area of circle
+ inline constexpr T area() const
+ {
+ return T(pi) * radius * radius;
+ }
+
+ // Get circumference of circle
+ inline constexpr T perimeter() const
+ {
+ return T(2.0 * pi) * radius;
+ }
+
+ // Get circumference of circle
+ inline constexpr T circumference() const
+ {
+ return perimeter();
+ }
+ };
+
+
+ template
+ struct triangle
+ {
+ std::array, 3> pos;
+
+ inline triangle(
+ const olc::v2d_generic& p0 = { T(0), T(0) },
+ const olc::v2d_generic& p1 = { T(0), T(0) },
+ const olc::v2d_generic& p2 = { T(0), T(0) })
+ : pos{ p0,p1,p2 }
+ { }
+
+ // Get a line from an indexed side, starting top, going clockwise
+ inline line side(const size_t i) const
+ {
+ return line(pos[i % 3], pos[(i + 1) % 3]);
+ }
+
+ // Get area of triangle
+ inline constexpr T area() const
+ {
+ return double(0.5) * std::abs(
+ (pos[0].x * (pos[1].y - pos[2].y)) +
+ (pos[1].x * (pos[2].y - pos[0].y)) +
+ (pos[2].x * (pos[0].y - pos[1].y)));
+ }
+
+ // Get perimeter of triangle
+ inline constexpr T perimeter() const
+ {
+ return line(pos[0], pos[1]).length()
+ + line(pos[1], pos[2]).length()
+ + line(pos[2], pos[0]).length();
+ }
+ };
+
+
+ template
+ struct polygon
+ {
+ std::vector> vPoints;
+ };
+
+
+ // =========================================================================================================================
+ // Closest(shape, point) ===================================================================================================
+
+ // Returns closest point to point
+ template
+ inline olc::v2d_generic closest(const olc::v2d_generic& p1, const olc::v2d_generic& p2)
+ {
+ return p1;
+ }
+
+ // Returns closest point on line to point
+ template
+ inline olc::v2d_generic closest(const line& l, const olc::v2d_generic& p)
+ {
+ auto d = l.vector();
+ double u = std::clamp(double(d.dot(p - l.start)) / d.mag2(), 0.0, 1.0);
+ return l.start + u * d;
+ }
+
+ // Returns closest point on circle to point
+ template
+ inline olc::v2d_generic closest(const circle& c, const olc::v2d_generic& p)
+ {
+ return c.pos + olc::vd2d(p - c.pos).norm() * c.radius;
+ }
+
+ // Returns closest point on rectangle to point
+ template
+ inline olc::v2d_generic closest(const rect& r, const olc::v2d_generic& p)
+ {
+ // This could be a "constrain" function hmmmm
+ // TODO: Not quite what i wanted, should restrain to boundary
+ return olc::v2d_generic{ std::clamp(p.x, r.pos.x, r.pos.x + r.size.x), std::clamp(p.y, r.pos.y, r.pos.y + r.size.y) };
+
+ }
+
+ // Returns closest point on triangle to point
+ template
+ inline olc::v2d_generic closest(const triangle& t, const olc::v2d_generic& p)
+ {
+ olc::utils::geom2d::line l{t.pos[0], t.pos[1]};
+ auto p0 = closest(l, p);
+ auto d0 = (p0 - p).mag2();
+
+ l.end = t.pos[2];
+ auto p1 = closest(l, p);
+ auto d1 = (p1 - p).mag2();
+
+ l.start = t.pos[1];
+ auto p2 = closest(l, p);
+ auto d2 = (p2 - p).mag2();
+
+ if((d0 <= d1) && (d0 <= d2)) {
+ return p0;
+ } else if((d1 <= d0) && (d1 <= d2)) {
+ return p1;
+ } else {
+ return p2;
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+ // ================================================================================================================
+ // POINT ==========================================================================================================
+
+ // Checks if point contains point
+ template
+ inline constexpr bool contains(const olc::v2d_generic& p1, const olc::v2d_generic& p2)
+ {
+ return (p1 - p2).mag2() < epsilon;
+ }
+
+ // Checks if line contains point
+ template
+ inline constexpr bool contains(const line& l, const olc::v2d_generic& p)
+ {
+ double d = ((p.x - l.start.x) * (l.end.y - l.start.y) - (p.y - l.start.y) * (l.end.x - l.start.x));
+ if (std::abs(d) < epsilon)
+ {
+ // point is on line
+ double u = l.vector().dot(p - l.start) / l.vector().mag2();
+ return (u >= double(0.0) && u <= double(1.0));
+ }
+
+ return false;
+ }
+
+ // Checks if rectangle contains point
+ template
+ inline constexpr bool contains(const rect& r, const olc::v2d_generic& p)
+ {
+ return !(p.x < r.pos.x || p.y < r.pos.y ||
+ p.x > (r.pos.x + r.size.x) || p.y > (r.pos.y + r.size.y));
+ }
+
+ // Checks if circle contains a point
+ template
+ inline constexpr bool contains(const circle& c, const olc::v2d_generic& p)
+ {
+ return (c.pos - p).mag2() < (c.radius * c.radius);
+ }
+
+ // Checks if triangle contains a point
+ template
+ inline constexpr bool contains(const triangle& t, const olc::v2d_generic& p)
+ {
+ // http://jsfiddle.net/PerroAZUL/zdaY8/1/
+ T2 A = T2(0.5) * (-t.pos[1].y * t.pos[2].x + t.pos[0].y * (-t.pos[1].x + t.pos[2].x) + t.pos[0].x * (t.pos[1].y - t.pos[2].y) + t.pos[1].x * t.pos[2].y);
+ T2 sign = A < T2(0) ? T2(-1) : T2(1);
+ T2 s = (t.pos[0].y * t.pos[2].x - t.pos[0].x * t.pos[2].y + (t.pos[2].y - t.pos[0].y) * p.x + (t.pos[0].x - t.pos[2].x) * p.y) * sign;
+ T2 v = (t.pos[0].x * t.pos[1].y - t.pos[0].y * t.pos[1].x + (t.pos[0].y - t.pos[1].y) * p.x + (t.pos[1].x - t.pos[0].x) * p.y) * sign;
+ return s > T2(0) && v > T2(0) && (s + v) < T2(2) * A * sign;
+ }
+
+
+
+
+ // Check if point overlaps with point (analagous to contains())
+ template
+ inline constexpr bool overlaps(const olc::v2d_generic& p1, const olc::v2d_generic& p2)
+ {
+ return contains(p1, p2);
+ }
+
+ // Checks if line segment overlaps with point
+ template
+ inline constexpr bool overlaps(const line& l, const olc::v2d_generic& p)
+ {
+ return contains(l, p);
+ }
+
+ // Checks if rectangle overlaps with point
+ template
+ inline constexpr bool overlaps(const rect& r, const olc::v2d_generic& p)
+ {
+ return contains(r, p);
+ }
+
+ // Checks if circle overlaps with point
+ template
+ inline constexpr bool overlaps(const circle& c, const olc::v2d_generic& p)
+ {
+ return contains(c, p);
+ }
+
+ // Checks if triangle overlaps with point
+ template
+ inline constexpr bool overlaps(const triangle& t, const olc::v2d_generic& p)
+ {
+ return contains(t, p);
+ }
+
+
+
+
+ // Get intersection points where point intersects with point
+ template
+ inline std::vector> intersects(const olc::v2d_generic& p1, const olc::v2d_generic& p2)
+ {
+ if (contains(p1, p2))
+ return { p1 };
+ else
+ return {};
+ }
+
+ // Get intersection points where line segment intersects with point
+ template
+ inline std::vector> intersects(const line& l, const olc::v2d_generic& p)
+ {
+ if (contains(l, p))
+ return { p };
+ else
+ return {};
+ }
+
+ // Get intersection points where rectangle intersects with point
+ template
+ inline std::vector> intersects(const rect& r, const olc::v2d_generic& p)
+ {
+ std::vector> vPoints;
+ if (contains(r.top(), p)) vPoints.push_back(p);
+ if (contains(r.bottom(), p)) vPoints.push_back(p);
+ if (contains(r.left(), p)) vPoints.push_back(p);
+ if (contains(r.right(), p)) vPoints.push_back(p);
+ return vPoints;
+ }
+
+ // Get intersection points where circle intersects with point
+ template
+ inline std::vector> intersects(const circle& c, const olc::v2d_generic& p)
+ {
+ if (std::abs((p - c.pos).mag2() - (c.radius * c.radius)) <= epsilon)
+ return { p };
+ else
+ return {};
+ }
+
+ // Get intersection points where triangle intersects with point
+ template
+ inline std::vector> intersects(const triangle& r, const olc::v2d_generic& p)
+ {
+ // TODO:
+ return {};
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+ // ================================================================================================================
+ // LINE ===========================================================================================================
+
+ // Check if point contains line segment
+ template
+ inline constexpr bool contains(const olc::v2d_generic& p, const line& l)
+ {
+ return false; // It can't!
+ }
+
+ // Check if line segment contains line segment
+ template
+ inline constexpr bool contains(const line& l1, const line& l2)
+ {
+ // TODO: Check if segments are colinear, and l1 exists within bounds of l2
+ return false;
+ }
+
+ // Check if rectangle contains line segment
+ template
+ inline constexpr bool contains(const rect& r, const line& l)
+ {
+ return contains(r, l.start) && contains(r, l.end);
+ }
+
+ // Check if circle contains line segment
+ template
+ inline constexpr bool contains(const circle& c1, const line& l)
+ {
+ return contains(c1, l.start) && contains(c1, l.end);
+ }
+
+ // Check if triangle contains line segment
+ template
+ inline constexpr bool contains(const triangle& t, const line& l)
+ {
+ return contains(t, l.start) && contains(t, l.end);
+ }
+
+
+
+
+ // Check if point overlaps line segment
+ template
+ inline constexpr bool overlaps(const olc::v2d_generic& p, const line& l)
+ {
+ return contains(l, p);
+ }
+
+ // Check if line segment overlaps line segment
+ template
+ inline constexpr bool overlaps(const line& l1, const line& l2)
+ {
+ // TODO:
+ return false;
+ }
+
+ // Check if rectangle overlaps line segment
+ template
+ inline constexpr bool overlaps(const rect& r, const line& l)
+ {
+ return contains(r, l.start)
+ || contains(r, l.end);
+
+ // TODO: This method is no good, it cant detect lines whose start and end
+ // points are outside the rectangle
+ }
+
+ // Check if circle overlaps line segment
+ template
+ inline constexpr bool overlaps(const circle& c, const line& l)
+ {
+ // TODO:
+ return false;
+ }
+
+ // Check if triangle overlaps line segment
+ template
+ inline constexpr bool overlaps(const triangle& t, const line& l)
+ {
+ return overlaps(t, l.start) || overlaps(t, l.end);
+
+ // TODO: This method is no good, it cant detect lines whose start and end
+ // points are outside the triangle
+ }
+
+
+
+
+ // Get intersection points where point intersects with line segment
+ template
+ inline std::vector> intersects(const olc::v2d_generic& p, const line& l)
+ {
+ // TODO:
+ return {};
+ }
+
+ // Get intersection points where line segment intersects with line segment
+ template
+ inline std::vector> intersects(const line& l1, const line& l2)
+ {
+ // TODO:
+ return {};
+ }
+
+ // Get intersection points where rectangle intersects with line segment
+ template
+ inline std::vector> intersects(const rect& r, const line& l)
+ {
+ // TODO:
+ return {};
+ }
+
+ // Get intersection points where circle intersects with line segment
+ template
+ inline std::vector> intersects(const circle& c, const line& l)
+ {
+ // TODO:
+ return {};
+ }
+
+ // Get intersection points where triangle intersects with line segment
+ template
+ inline std::vector> intersects(const triangle& t, const line& l)
+ {
+ // TODO:
+ return {};
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+ // ================================================================================================================
+ // RECTANGLE ======================================================================================================
+
+ // Check if point contains rectangle
+ template
+ inline constexpr bool contains(const olc::v2d_generic& p, const rect& r)
+ {
+ return false; // It can't!
+ }
+
+ // Check if line segment contains rectangle
+ template
+ inline constexpr bool contains(const line& l, const rect& r)
+ {
+ return false; // It can't
+ }
+
+ // Check if rectangle contains rectangle
+ template
+ inline constexpr bool contains(const rect& r1, const rect& r2)
+ {
+ return (r2.pos.x >= r1.pos.x) && (r2.pos.x + r2.size.x < r1.pos.x + r1.size.x) &&
+ (r2.pos.y >= r1.pos.y) && (r2.pos.y + r2.size.y < r1.pos.y + r1.size.y);
+ }
+
+ // Check if circle contains rectangle
+ template
+ inline constexpr bool contains(const circle& c, const rect& r)
+ {
+ return contains(c, r.pos)
+ && contains(c, olc::v2d_generic{ r.pos.x + r.size.x, r.pos.y })
+ && contains(c, olc::v2d_generic{ r.pos.x, r.pos.y + r.size.y })
+ && contains(c, r.pos + r.size);
+ }
+
+ // Check if triangle contains rectangle
+ template
+ inline constexpr bool contains(const triangle& t, const rect& r)
+ {
+ return contains(t, r.pos)
+ && contains(t, r.pos + r.size)
+ && contains(t, olc::v2d_generic{ r.pos.x + r.size.x,r.pos.y })
+ && contains(t, olc::v2d_generic{ r.pos.x, r.pos.y + r.size.y });
+ }
+
+
+
+
+ // Check if point overlaps rectangle
+ template
+ inline constexpr bool overlaps(const olc::v2d_generic& p, const rect& r)
+ {
+ return overlaps(r, p);
+ }
+
+ // Check if line segment overlaps rectangle
+ template
+ inline constexpr bool overlaps(const line& l, const rect& r)
+ {
+ return overlaps(r, l);
+ }
+
+ // Check if rectangle overlaps rectangle
+ template
+ inline constexpr bool overlaps(const rect& r1, const rect& r2)
+ {
+ return (r1.pos.x < r2.pos.x + r2.size.x && r1.pos.x + r1.size.x >= r2.pos.x &&
+ r1.pos.y < r2.pos.y + r2.size.y && r1.pos.y + r1.size.y >= r2.pos.y);
+ }
+
+ // Check if circle overlaps rectangle
+ template
+ inline constexpr bool overlaps(const circle& c, const rect& r)
+ {
+ // Inspired by this (very clever btw)
+ // https://stackoverflow.com/questions/45370692/circle-rectangle-collision-response
+ // But modified to work :P
+ T2 overlap = (olc::v2d_generic{ std::clamp(c.pos.x, r.pos.x, r.pos.x + r.size.x), std::clamp(c.pos.y, r.pos.y, r.pos.y + r.size.y) } - c.pos).mag2();
+ if (std::isnan(overlap)) overlap = T2(0);
+ return (overlap - (c.radius * c.radius)) < T2(0);
+ }
+
+ // Check if triangle overlaps rectangle
+ template
+ inline constexpr bool overlaps(const triangle& t, const rect& r)
+ {
+ return contains(t, r.pos)
+ || contains(t, r.pos + r.size)
+ || contains(t, olc::v2d_generic{ r.pos.x + r.size.x, r.pos.y })
+ || contains(t, olc::v2d_generic{ r.pos.x, r.pos.y + r.size.y });
+
+ // TODO: This method is no good, consider rectangle with all vertices
+ // outside of triangle, but edges still crossing
+ }
+
+
+
+
+ // Get intersection points where point intersects with rectangle
+ template
+ inline std::vector> intersects(const olc::v2d_generic& p, const rect& r)
+ {
+ return intersects(r, p);
+ }
+
+ // Get intersection points where line segment intersects with rectangle
+ template
+ inline std::vector> intersects(const line& l, const rect& r)
+ {
+ // TODO:
+ return {};
+ }
+
+ // Get intersection points where rectangle intersects with rectangle
+ template
+ inline std::vector> intersects(const rect& r1, const rect& r2)
+ {
+ // TODO:
+ return {};
+ }
+
+ // Get intersection points where circle intersects with rectangle
+ template
+ inline std::vector> intersects(const circle& c, const rect& r)
+ {
+ // TODO:
+ return {};
+ }
+
+ // Get intersection points where triangle intersects with rectangle
+ template
+ inline std::vector> intersects(const triangle& t, const rect& r)
+ {
+ // TODO:
+ return {};
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ // ================================================================================================================
+ // CIRCLE =========================================================================================================
+
+ // Check if point contains circle
+ template
+ inline constexpr bool contains(const olc::v2d_generic& p, const circle& c)
+ {
+ return false; // It can't!
+ }
+
+ // Check if line segment contains circle
+ template
+ inline constexpr bool contains(const line& l, const circle& c)
+ {
+ return false; // It can't!
+ }
+
+ // Check if rectangle contains circle
+ template
+ inline constexpr bool contains(const rect& r, const circle& c)
+ {
+ // TODO:
+ return false;
+ }
+
+ // Check if circle contains circle
+ template
+ inline constexpr bool contains(const circle& c1, const circle& c2)
+ {
+ return (c1.pos - c2.pos).mag2() <= (c1.radius - c2.radius) * (c1.radius - c2.radius);
+ }
+
+ // Check if triangle contains circle
+ template
+ inline constexpr bool contains(const triangle& t, const circle& c)
+ {
+ // TODO:
+ return false;
+ }
+
+
+
+
+ // Check if point overlaps circle
+ template
+ inline constexpr bool overlaps(const olc::v2d_generic& p, const circle& c)
+ {
+ return overlaps(c, p);
+ }
+
+ // Check if line segment overlaps circle
+ template
+ inline constexpr bool overlaps(const line& l, const circle& c)
+ {
+ return overlaps(c, l);
+ }
+
+ // Check if rectangle overlaps circle
+ template
+ inline constexpr bool overlaps(const rect& r, const circle& c)
+ {
+ return overlaps(c, r);
+ }
+
+ // Check if circle overlaps circle
+ template
+ inline constexpr bool overlaps(const circle& c1, const circle& c2)
+ {
+ return (c1.pos - c2.pos).mag2() <= (c1.radius + c2.radius) * (c1.radius + c2.radius);
+ }
+
+ // Check if triangle overlaps circle
+ template
+ inline constexpr bool overlaps(const triangle& t, const circle& c)
+ {
+ // TODO:
+ return false;
+ }
+
+
+
+
+ // Get intersection points where point intersects with circle
+ template
+ inline std::vector> intersects(const olc::v2d_generic& p, const circle& c)
+ {
+ // TODO:
+ return {};
+ }
+
+ // Get intersection points where line segment intersects with circle
+ template
+ inline std::vector> intersects(const line