line between two vector algorithm impl + tests
This commit is contained in:
parent
598c62976b
commit
6fe6187d2c
|
@ -4,44 +4,23 @@
|
|||
|
||||
#include <libgba-sprite-engine/background/text_stream.h>
|
||||
#include <libgba-sprite-engine/gba/tonc_bios.h>
|
||||
#include <cmath>
|
||||
#include <libgba-sprite-engine/math.h>
|
||||
#include "bullet.h"
|
||||
|
||||
#define FIXED_POINT_BASE 1000
|
||||
#define SPEED_DELTA 1
|
||||
|
||||
void Bullet::setDestination(VECTOR destination) {
|
||||
auto currentPos = sprite->getPos();
|
||||
this->dest = destination;
|
||||
|
||||
diff.x = (destination.x - currentPos.x);
|
||||
diff.y = (destination.y - currentPos.y);
|
||||
directionToCover.x = diff.x * FIXED_POINT_BASE;
|
||||
directionToCover.y = diff.y * FIXED_POINT_BASE;
|
||||
|
||||
TextStream::instance().setText(std::string("covering: ") + std::to_string(directionToCover.x) + std::string(",") + std::to_string(directionToCover.y), 15, 1);
|
||||
this->coords = Math::bresenhamLineBetween(currentPos, destination);
|
||||
}
|
||||
|
||||
void Bullet::tick() {
|
||||
auto x = sprite->getX(), y = sprite->getY();
|
||||
|
||||
if(directionToCover.x != 0) {
|
||||
if(directionToCover.x > 0) {
|
||||
directionToCover.x -= FIXED_POINT_BASE;
|
||||
x += SPEED_DELTA;
|
||||
} else {
|
||||
directionToCover.x += FIXED_POINT_BASE;
|
||||
x -= SPEED_DELTA;
|
||||
}
|
||||
}
|
||||
if(directionToCover.y != 0) {
|
||||
if(directionToCover.y > 0) {
|
||||
directionToCover.y -= FIXED_POINT_BASE;
|
||||
y += SPEED_DELTA;
|
||||
} else {
|
||||
directionToCover.y += FIXED_POINT_BASE;
|
||||
y -= SPEED_DELTA;
|
||||
}
|
||||
if(coords.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
sprite->moveTo(x, y);
|
||||
sprite->moveTo(coords.front());
|
||||
coords.pop_front();
|
||||
}
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
|
||||
#include <libgba-sprite-engine/sprites/sprite.h>
|
||||
#include <libgba-sprite-engine/gba/tonc_math.h>
|
||||
#include <deque>
|
||||
|
||||
class Bullet {
|
||||
private:
|
||||
std::unique_ptr<Sprite> sprite;
|
||||
std::deque<VECTOR> coords;
|
||||
VECTOR dest;
|
||||
VECTOR diff;
|
||||
VECTOR directionToCover;
|
||||
|
||||
public:
|
||||
Bullet(std::unique_ptr<Sprite> sprite) : sprite(std::move(sprite)), dest(VECTOR()) {}
|
||||
|
|
|
@ -128,5 +128,5 @@ void FoodScene::load() {
|
|||
bulletCooldown = BULLET_COOLDOWN_START;
|
||||
|
||||
// rotation of a point on a circle within the resolution means our radius should be big enough
|
||||
defaultBulletTarget = { GBA_SCREEN_WIDTH / 2, GBA_SCREEN_HEIGHT + (GBA_SCREEN_WIDTH / 2) - avatar->getCenter().y};
|
||||
defaultBulletTarget = { GBA_SCREEN_WIDTH / 2, GBA_SCREEN_HEIGHT + (GBA_SCREEN_WIDTH / 2) - avatar->getCenter().y + 40};
|
||||
}
|
|
@ -18,7 +18,7 @@ add_library(${PROJECT_NAME}
|
|||
src/background/text_stream.cpp
|
||||
src/background/background.cpp
|
||||
src/effects/fade_out_scene.cpp
|
||||
src/sound_control.cpp src/scene.cpp src/timer.cpp)
|
||||
src/sound_control.cpp src/scene.cpp src/timer.cpp include/libgba-sprite-engine/math.h src/math.cpp)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// Created by Wouter Groeneveld on 14/12/18.
|
||||
//
|
||||
|
||||
#ifndef GBA_SPRITE_ENGINE_PROJECT_MATH_H
|
||||
#define GBA_SPRITE_ENGINE_PROJECT_MATH_H
|
||||
|
||||
#include <deque>
|
||||
#include <libgba-sprite-engine/gba/tonc_math.h>
|
||||
|
||||
class Math {
|
||||
public:
|
||||
static std::deque<VECTOR> bresenhamLineBetween(VECTOR src, VECTOR dest);
|
||||
};
|
||||
|
||||
#endif //GBA_SPRITE_ENGINE_PROJECT_MATH_H
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// Created by Wouter Groeneveld on 14/12/18.
|
||||
//
|
||||
|
||||
#include <libgba-sprite-engine/math.h>
|
||||
|
||||
std::deque<VECTOR> Math::bresenhamLineBetween(VECTOR src, VECTOR dest) {
|
||||
// https://www.coranac.com/tonc/text/bitmaps.htm - Bresenham's line algorithm with fixed points
|
||||
VECTOR step, delta;
|
||||
|
||||
std::deque<VECTOR> coords;
|
||||
|
||||
if(src.x > dest.x) {
|
||||
step.x = -1;
|
||||
delta.x = (src.x - dest.x);
|
||||
} else {
|
||||
step.x = +1;
|
||||
delta.x = (dest.x - src.x);
|
||||
}
|
||||
if(src.y > dest.y) {
|
||||
step.y = -1;
|
||||
delta.y = (src.y - dest.y);
|
||||
} else {
|
||||
step.y = +1;
|
||||
delta.y = (dest.y - src.y);
|
||||
}
|
||||
|
||||
int dd, x = src.x, y = src.y, ii;
|
||||
|
||||
if(delta.y == 0) {
|
||||
// horizontal
|
||||
for(ii = 0; ii <= delta.x; ii++) {
|
||||
coords.push_back({x, y});
|
||||
x += step.x;
|
||||
}
|
||||
} else if(delta.x == 0) {
|
||||
// vertical
|
||||
for(ii = 0; ii <= delta.y; ii++) {
|
||||
coords.push_back({x, y});
|
||||
y += step.y;
|
||||
}
|
||||
} else if(delta.x >= delta.y) {
|
||||
// Diagonal, slope <= 1
|
||||
dd = 2 * delta.y - delta.x;
|
||||
|
||||
for(ii = 0; ii <= delta.x; ii++) {
|
||||
coords.push_back({x, y});
|
||||
if(dd >= 0) {
|
||||
dd -= 2 * delta.x;
|
||||
y += step.y;
|
||||
}
|
||||
dd += 2 * delta.y;
|
||||
x += step.x;
|
||||
}
|
||||
} else {
|
||||
// Diagonal, slope > 1
|
||||
dd = 2 * delta.x - delta.y;
|
||||
|
||||
for(ii = 0; ii <= delta.y; ii++) {
|
||||
coords.push_back({x, y});
|
||||
if(dd >= 0) {
|
||||
dd -= 2 * delta.y;
|
||||
x += step.x;
|
||||
}
|
||||
dd += 2 * delta.x;
|
||||
y += step.y;
|
||||
}
|
||||
}
|
||||
|
||||
return coords;
|
||||
}
|
|
@ -35,6 +35,7 @@ add_executable(unittest
|
|||
../engine/src/allocator.cpp
|
||||
../engine/src/palette/combined_palette.cpp
|
||||
../engine/src/timer.cpp
|
||||
timertest.cpp)
|
||||
../engine/src/math.cpp
|
||||
timertest.cpp mathtest.cpp)
|
||||
|
||||
target_link_libraries(unittest ${GTEST_LIBRARY}/build/libgtest.a ${GTEST_LIBRARY}/build/libgtest_main.a)
|
||||
|
|
|
@ -69,7 +69,7 @@ TEST_F(AllocatorSuite, Allocate_Sprite_Pointers_Reservers_Some_Tile_Space) {
|
|||
auto curr2 = Allocator::getCurrentSpriteIndex();
|
||||
auto diff2 = curr2 - curr;
|
||||
|
||||
cout << "prev: " << prev << " - curr: " << curr << " (diff: " << diff << ")" << " and " << curr2 << endl;
|
||||
cout << "prev: " << prev << " - curr: " << curr << " (delta: " << diff << ")" << " and " << curr2 << endl;
|
||||
|
||||
ASSERT_EQ(prev, allocated.currentAddress);
|
||||
ASSERT_EQ(curr, allocated2.currentAddress);
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
//
|
||||
// Created by Wouter Groeneveld on 14/12/18.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <libgba-sprite-engine/math.h>
|
||||
|
||||
class MathSuite : public ::testing::Test {
|
||||
protected:
|
||||
|
||||
virtual void TearDown() {
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MathSuite, LineBetween_Diagonal_ToTopRightCorner) {
|
||||
auto points = Math::bresenhamLineBetween({120, 80}, {240, 0});
|
||||
ASSERT_EQ(121, points.size());
|
||||
VECTOR pt;
|
||||
|
||||
// some sampling
|
||||
pt = points.at(1);
|
||||
ASSERT_EQ(121, pt.x);
|
||||
ASSERT_EQ(79, pt.y);
|
||||
pt = points.at(2);
|
||||
ASSERT_EQ(122, pt.x);
|
||||
ASSERT_EQ(79, pt.y);
|
||||
pt = points.at(10);
|
||||
ASSERT_EQ(130, pt.x);
|
||||
ASSERT_EQ(73, pt.y);
|
||||
pt = points.at(100);
|
||||
ASSERT_EQ(220, pt.x);
|
||||
ASSERT_EQ(13, pt.y);
|
||||
}
|
||||
|
||||
TEST_F(MathSuite, LineBetween_Diagonal_ToTopLeftCorner) {
|
||||
auto points = Math::bresenhamLineBetween({120, 80}, {0, 0});
|
||||
ASSERT_EQ(121, points.size());
|
||||
VECTOR pt;
|
||||
|
||||
// some sampling
|
||||
pt = points.at(1);
|
||||
ASSERT_EQ(119, pt.x);
|
||||
ASSERT_EQ(79, pt.y);
|
||||
pt = points.at(2);
|
||||
ASSERT_EQ(118, pt.x);
|
||||
ASSERT_EQ(79, pt.y);
|
||||
pt = points.at(10);
|
||||
ASSERT_EQ(110, pt.x);
|
||||
ASSERT_EQ(73, pt.y);
|
||||
pt = points.at(100);
|
||||
ASSERT_EQ(20, pt.x);
|
||||
ASSERT_EQ(13, pt.y);
|
||||
}
|
||||
|
||||
TEST_F(MathSuite, LineBetween_Diagonal_ToBottomLeftCorner) {
|
||||
auto points = Math::bresenhamLineBetween({120, 80}, {0, 160});
|
||||
ASSERT_EQ(121, points.size());
|
||||
VECTOR pt;
|
||||
|
||||
// some sampling
|
||||
pt = points.at(1);
|
||||
ASSERT_EQ(119, pt.x);
|
||||
ASSERT_EQ(81, pt.y);
|
||||
pt = points.at(2);
|
||||
ASSERT_EQ(118, pt.x);
|
||||
ASSERT_EQ(81, pt.y);
|
||||
pt = points.at(10);
|
||||
ASSERT_EQ(110, pt.x);
|
||||
ASSERT_EQ(87, pt.y);
|
||||
pt = points.at(100);
|
||||
ASSERT_EQ(20, pt.x);
|
||||
ASSERT_EQ(147, pt.y);
|
||||
}
|
||||
|
||||
TEST_F(MathSuite, LineBetween_Diagonal_ToBottomRightCorner) {
|
||||
auto points = Math::bresenhamLineBetween({120, 80}, {240, 160});
|
||||
ASSERT_EQ(121, points.size());
|
||||
VECTOR pt;
|
||||
|
||||
// some sampling
|
||||
pt = points.at(1);
|
||||
ASSERT_EQ(121, pt.x);
|
||||
ASSERT_EQ(81, pt.y);
|
||||
pt = points.at(2);
|
||||
ASSERT_EQ(122, pt.x);
|
||||
ASSERT_EQ(81, pt.y);
|
||||
pt = points.at(10);
|
||||
ASSERT_EQ(130, pt.x);
|
||||
ASSERT_EQ(87, pt.y);
|
||||
pt = points.at(100);
|
||||
ASSERT_EQ(220, pt.x);
|
||||
ASSERT_EQ(147, pt.y);
|
||||
}
|
||||
|
||||
TEST_F(MathSuite, LineBetween_Horizontal_FromCenterToHalfYZeroX) {
|
||||
auto points = Math::bresenhamLineBetween({120, 80}, {0, 80});
|
||||
ASSERT_EQ(121, points.size());
|
||||
for(int i = 0; i <= 120; i++) {
|
||||
auto &vec = points.front();
|
||||
ASSERT_EQ(80, vec.y);
|
||||
ASSERT_EQ(120 - i, vec.x);
|
||||
points.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MathSuite, LineBetween_Vertical_FromCenterToHalfXFullY) {
|
||||
auto points = Math::bresenhamLineBetween({120, 80}, {120, 160});
|
||||
ASSERT_EQ(81, points.size());
|
||||
for(int i = 0; i <= (160 - 80); i++) {
|
||||
auto &vec = points.front();
|
||||
ASSERT_EQ(120, vec.x);
|
||||
ASSERT_EQ(80 + i, vec.y);
|
||||
points.pop_front();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue