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

Add bitmap-ray and sprite-ray collision functions #198

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f85507b
Add quad_from function to create a quad from segment endpoints and width
matt439 Dec 4, 2024
889d70b
Add bitmap_ray_collision function for ray and bitmap collision detection
matt439 Dec 4, 2024
0588345
Add bitmap_quad_collision function for bitmap and quad collision dete…
matt439 Dec 4, 2024
36c35bf
Update bitmap_ray_collision function signature to include cell and po…
matt439 Dec 4, 2024
1be422d
Refactor bitmap_ray_collision function to include cell and point para…
matt439 Dec 4, 2024
a680da2
Refactor circle calculations in bitmap functions to use diagonal dist…
matt439 Dec 4, 2024
40c6a10
Add test for bitmap ray collision functionality in geometry tests
matt439 Dec 4, 2024
4e53300
Refactor test_bitmap_ray_collision to reposition ray drawing logic fo…
matt439 Dec 4, 2024
36a662f
Refactor bitmap_ray_collision functions to include translation matrix…
matt439 Dec 4, 2024
29ee718
Add sprite ray collision test with interactive ray manipulation
matt439 Dec 4, 2024
6093863
Add sprite ray collision function to handle ray-based collision detec…
matt439 Dec 4, 2024
33e3d7e
Refactor sprite test functions for improved organization and clarity
matt439 Dec 4, 2024
df8fa92
Uncomment geometry test functions to enable full test suite execution
matt439 Dec 4, 2024
a68eb52
Add documentation to ray collision functions
matt439 Dec 4, 2024
a3ca9a9
Add documentation for quad_from overload
matt439 Dec 4, 2024
4544f06
Rename ray collision function parameters for clarity
matt439 Dec 5, 2024
cb0e335
Rename ray collision function parameters for clarity
matt439 Dec 13, 2024
d6e496c
Rename parameters in quad_from function
matt439 Dec 16, 2024
286ad0a
Add null pointer check for bitmap in bitmap_ray_collision function
matt439 Dec 16, 2024
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
66 changes: 66 additions & 0 deletions coresdk/src/coresdk/collisions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "graphics.h"
#include "utils.h"

constexpr double RAY_QUAD_LINE_THICKNESS = 1.0;

using std::function;

namespace splashkit_lib
Expand Down Expand Up @@ -274,6 +276,65 @@ namespace splashkit_lib
return bitmap_circle_collision(bmp, cell, translation_matrix(x, y), circ);
}

bool bitmap_quad_collision(bitmap bmp, int cell, const matrix_2d &translation, const quad& q)
{
if (INVALID_PTR(bmp, BITMAP_PTR))
{
return false;
}

quad q1 = quad_from(bitmap_cell_rectangle(bmp), translation);
rectangle rect = rectangle_around(q);

if ( not quads_intersect(q1, q) ) return false;

return _step_through_pixels(rect.width, rect.height, translation_matrix(rect.x, rect.y), bmp->cell_w, bmp->cell_h, translation, [&] (int ax, int ay, int bx, int by)
{
return pixel_drawn_at_point(bmp, cell, bx, by) && point_in_quad(point_at(rect.x + ax, rect.y + ay), q);
});
}

bool bitmap_ray_collision(bitmap bmp, int cell, const matrix_2d& translation, const point_2d& origin, const vector_2d& heading)
{
if (INVALID_PTR(bmp, BITMAP_PTR))
{
return false;
}

point_2d bmp_position = matrix_multiply(translation, point_at(0.0, 0.0));
point_2d bmp_center = point_offset_by(bmp_position, vector_to(bitmap_center(bmp)));
circle bmp_bounding_circle = bitmap_bounding_circle(bmp, bmp_center);

vector_2d unit_ray_heading = unit_vector(heading);

// get point which will allow segment to fully pass through the bitmap
double distance_to_center = vector_magnitude(vector_point_to_point(origin, bmp_center));
point_2d ray_end = point_offset_by(origin, vector_multiply(unit_ray_heading, distance_to_center + bmp_bounding_circle.radius));

quad ray_quad = quad_from(origin, ray_end, RAY_QUAD_LINE_THICKNESS);
return bitmap_quad_collision(bmp, cell, translation, ray_quad);
}

bool bitmap_ray_collision(bitmap bmp, int cell, const point_2d& pt, const point_2d& origin, const vector_2d& heading)
{
return bitmap_ray_collision(bmp, cell, translation_matrix(pt), origin, heading);
}

bool bitmap_ray_collision(bitmap bmp, int cell, double x, double y, const point_2d& origin, const vector_2d& heading)
{
return bitmap_ray_collision(bmp, cell, translation_matrix(x, y), origin, heading);
}

bool bitmap_ray_collision(bitmap bmp, double x, double y, const point_2d& origin, const vector_2d& heading)
{
return bitmap_ray_collision(bmp, 0, translation_matrix(x, y), origin, heading);
}

bool bitmap_ray_collision(bitmap bmp, const point_2d& pt, const point_2d& origin, const vector_2d& heading)
{
return bitmap_ray_collision(bmp, 0, translation_matrix(pt), origin, heading);
}

bool sprite_bitmap_collision(sprite s, bitmap bmp, int cell, double x, double y)
{
if (!rectangles_intersect(sprite_collision_rectangle(s), bitmap_cell_rectangle(bmp, point_at(x, y))))
Expand Down Expand Up @@ -329,6 +390,11 @@ namespace splashkit_lib

return bitmap_rectangle_collision(sprite_collision_bitmap(s), sprite_current_cell(s), sprite_location_matrix(s), rect);
}

bool sprite_ray_collision(sprite s, const point_2d& origin, const vector_2d& heading)
{
return bitmap_ray_collision(sprite_collision_bitmap(s), sprite_current_cell(s), sprite_location_matrix(s), origin, heading);
}

bool sprite_collision(sprite s1, sprite s2)
{
Expand Down
122 changes: 122 additions & 0 deletions coresdk/src/coresdk/collisions.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,116 @@ namespace splashkit_lib
* @attribute method circle_collision
*/
bool bitmap_circle_collision(bitmap bmp, const point_2d& pt, const circle& circ);

/**
* Tests if a bitmap cell drawn using a passed in translation, will
* intersect with a quad. You can use this to detect collisions between
* bitmaps and quads.
*
* @param bmp The bitmap to test
* @param cell The cell of the bitmap to check
* @param translation The matrix used to transfrom the bitmap when drawing
* @param q The quad to test
* @return True if a drawn pixel in the cell of the bitmap will
* intersect with `q` when drawn.
*
* @attribute suffix for_cell_with_translation
*
* @attribute class bitmap
* @attribute method quad_collision
*/
bool bitmap_quad_collision(bitmap bmp, int cell, const matrix_2d &translation, const quad &q);

/**
* Tests if a bitmap cell drawn using a passed in translation, will
* intersect with a ray. You can use this to detect collisions between
* bitmaps and rays.
*
* @param bmp The bitmap to test
* @param cell The cell of the bitmap to check
* @param translation The matrix used to transfrom the bitmap when drawing
* @param origin The origin of the ray
* @param heading The heading of the ray
* @return True if a drawn pixel in the cell of the bitmap will
* intersect with the ray when drawn.
*
* @attribute suffix for_cell_with_translation
*
* @attribute class bitmap
* @attribute method ray_collision
*/
bool bitmap_ray_collision(bitmap bmp, int cell, const matrix_2d& translation, const point_2d& origin, const vector_2d& heading);

/**
* Tests if a bitmap cell drawn at `pt` would intersect with a ray.
*
* @param bmp The bitmap to test
* @param cell The cell of the bitmap to check
* @param pt The location where the bitmap is drawn
* @param origin The origin of the ray
* @param heading The heading of the ray
* @return True if a drawn pixel in the cell of the bitmap will
* intersect with the ray when drawn.
*
* @attribute suffix for_cell_at_point
*
* @attribute class bitmap
* @attribute method ray_collision
*/
bool bitmap_ray_collision(bitmap bmp, int cell, const point_2d& pt, const point_2d& origin, const vector_2d& heading);

/**
* Tests if a bitmap cell drawn at `x`, `y` would intersect with a ray.
*
* @param bmp The bitmap to test
* @param cell The cell of the bitmap to check
* @param x The x location where the bitmap is drawn
* @param y The y location where the bitmap is drawn
* @param origin The origin of the ray
* @param heading The heading of the ray
* @return True if a drawn pixel in the cell of the bitmap will
* intersect with the ray when drawn.
*
* @attribute suffix for_cell
*
* @attribute class bitmap
* @attribute method ray_collision
*/
bool bitmap_ray_collision(bitmap bmp, int cell, double x, double y, const point_2d& origin, const vector_2d& heading);

/**
* Tests if a bitmap drawn at `x`, `y` would intersect with a ray.
*
* @param bmp The bitmap to test
* @param x The x location where the bitmap is drawn
* @param y The y location where the bitmap is drawn
* @param origin The origin of the ray
* @param heading The heading of the ray
* @return True if a drawn pixel in the bitmap will
* intersect with the ray when drawn.
*
* @attribute class bitmap
* @attribute method ray_collision
*/
bool bitmap_ray_collision(bitmap bmp, double x, double y, const point_2d& origin, const vector_2d& heading);

/**
* Tests if a bitmap drawn at `pt` would intersect with a ray.
*
* @param bmp The bitmap to test
* @param pt The location where the bitmap is drawn
* @param origin The origin of the ray
* @param heading The heading of the ray
* @return True if a drawn pixel in the cell of the bitmap will
* intersect with the ray when drawn.
*
* @attribute suffix at_point
*
* @attribute class bitmap
* @attribute method ray_collision
*/
bool bitmap_ray_collision(bitmap bmp, const point_2d& pt, const point_2d& origin, const vector_2d& heading);

/**
* Tests if a sprite will collide with a bitmap drawn at the indicated
* location.
Expand Down Expand Up @@ -374,6 +483,19 @@ namespace splashkit_lib
*/
bool sprite_rectangle_collision(sprite s, const rectangle& rect);

/**
* Tests if a sprite is drawn along a given ray.
*
* @param s The sprite to test
* @param origin The origin of the ray
* @param heading The heading of the ray
* @return True if the sprite is drawn along the ray
*
* @attribute class sprite
* @attribute method ray_collision
*/
bool sprite_ray_collision(sprite s, const point_2d& origin, const vector_2d& heading);

/**
* Tests if two given sprites `s1` and `s2` are collided
* @param s1 the first `sprite` to test
Expand Down
4 changes: 2 additions & 2 deletions coresdk/src/coresdk/images.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ namespace splashkit_lib
return circle_at(0, 0, 0);
}

return circle_at(pt, MAX(bmp->cell_w, bmp->cell_h) / 2.0f * scale);
return circle_at(pt, sqrt(pow(bmp->cell_w / 2.0, 2.0) + pow(bmp->cell_h / 2.0, 2.0)) * scale);
}

circle bitmap_cell_circle(bitmap bmp, const point_2d pt)
Expand All @@ -408,7 +408,7 @@ namespace splashkit_lib
return circle_at(0,0,0);
}

return circle_at(pt, MAX(bmp->image.surface.width, bmp->image.surface.height));
return circle_at(pt, sqrt(pow(bmp->image.surface.width / 2.0, 2.0) + pow(bmp->image.surface.height / 2.0, 2.0)));
}

int bitmap_cell_columns(bitmap bmp)
Expand Down
15 changes: 15 additions & 0 deletions coresdk/src/coresdk/quad_geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ namespace splashkit_lib
return result;
}

quad quad_from(const point_2d& line_origin, const point_2d& line_end, double width)
{
vector_2d heading = vector_point_to_point(line_origin, line_end);
vector_2d normal = vector_normal(heading);
vector_2d offset = vector_multiply(normal, width / 2.0);

quad result;
result.points[0] = point_offset_by(line_origin, offset);
result.points[1] = point_offset_by(line_end, offset);
result.points[2] = point_offset_by(line_origin, vector_invert(offset));
result.points[3] = point_offset_by(line_end, vector_invert(offset));

return result;
}

void set_quad_point(quad &q, int idx, const point_2d &value)
{
if (idx < 0 || idx > 3)
Expand Down
14 changes: 14 additions & 0 deletions coresdk/src/coresdk/quad_geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ namespace splashkit_lib
const point_2d &p3,
const point_2d &p4);

/**
* Returns a quad from the passed in line and width.
* The quad will be a rectangle with the line as the diagonal,
* and the width as the width of the rectangle.
*
* @param line_origin The origin of the line
* @param line_end The end of the line
* @param width The width of the quad
* @return A quad that represents the line with the given width
*
* @attribute suffix from_line
*/
quad quad_from(const point_2d& line_origin, const point_2d& line_end, double width);

/**
* Change a point in a quad.
*
Expand Down
67 changes: 67 additions & 0 deletions coresdk/src/test/test_geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,77 @@ void test_triangle()
close_window(w1);
}

void test_bitmap_ray_collision()
{
window w1 = open_window("Bitmap Ray Collision", 800, 600);
bitmap bmp_1 = load_bitmap("on_med", "on_med.png");
point_2d bmp_1_position = point_at(300.0, 300.0);
point_2d bmp_1_center = point_offset_by(bmp_1_position, vector_to(bitmap_center(bmp_1)));
bitmap bmp_2 = load_bitmap("rocket_sprt", "rocket_sprt.png");
point_2d bmp_2_position = point_at(500.0, 300.0);
point_2d bmp_2_center = point_offset_by(bmp_2_position, vector_to(bitmap_center(bmp_2)));
bitmap bmp_3 = load_bitmap("up_pole", "up_pole.png");
point_2d bmp_3_position = point_at(700.0, 300.0);
point_2d bmp_3_center = point_offset_by(bmp_3_position, vector_to(bitmap_center(bmp_3)));
point_2d ray_origin = point_at(100, 100);
vector_2d ray_heading = vector_to(200, 200);

while ( !window_close_requested(w1) ) {
process_events();

clear_screen(COLOR_WHITE);

if (key_down(UP_KEY))
ray_origin.y -= 1.0;
if (key_down(DOWN_KEY))
ray_origin.y += 1.0;
if (key_down(LEFT_KEY))
ray_origin.x -= 1.0;
if (key_down(RIGHT_KEY))
ray_origin.x += 1.0;

bool collision_1 = bitmap_ray_collision(bmp_1, 0, bmp_1_position, ray_origin, ray_heading);
bool collision_2 = bitmap_ray_collision(bmp_2, 0, bmp_2_position, ray_origin, ray_heading);
bool collision_3 = bitmap_ray_collision(bmp_3, 0, bmp_3_position, ray_origin, ray_heading);

draw_bitmap(bmp_1, bmp_1_position.x, bmp_1_position.y);
if (collision_1)
{
fill_circle(COLOR_RED, circle_at(bmp_1_center, 30.0));
}

draw_bitmap(bmp_2, bmp_2_position.x, bmp_2_position.y);
if (collision_2)
{
fill_circle(COLOR_RED, circle_at(bmp_2_center, 8.0));
}

draw_bitmap(bmp_3, bmp_3_position.x, bmp_3_position.y);
if (collision_3)
{
fill_circle(COLOR_RED, circle_at(bmp_3_center, 30.0));
}

ray_heading = vector_point_to_point(ray_origin, mouse_position());
vector_2d normal_heading = unit_vector(ray_heading);
draw_line(COLOR_BLACK, ray_origin, point_offset_by(ray_origin, vector_multiply(normal_heading, 800.0)));

circle mouse_circle = circle_at(mouse_position(), 3.0);
draw_circle(COLOR_GREEN, mouse_circle);

circle ray_origin_circle = circle_at(ray_origin, 3.0);
draw_circle(COLOR_BLUE, ray_origin_circle);

refresh_screen();
}
close_window(w1);
}

void run_geometry_test()
{
test_rectangle();
test_points();
test_lines();
test_triangle();
test_bitmap_ray_collision();
}
Loading
Loading