diff --git a/coresdk/src/coresdk/collisions.h b/coresdk/src/coresdk/collisions.h index 8a6a0d3b..03ba64d4 100644 --- a/coresdk/src/coresdk/collisions.h +++ b/coresdk/src/coresdk/collisions.h @@ -558,12 +558,18 @@ namespace splashkit_lib bool bitmap_quad_collision(bitmap bmp, const point_2d &pt, const quad &q); /** - * Tests if a sprite will collide with a bitmap drawn at the indicated - * location. + * Tests if a sprite will collide with a specific cell of a bitmap drawn at + * the indicated location. This is useful when the bitmap contains multiple + * animation frames or states organised as cells. * * @param s The sprite to test * @param bmp The bitmap to test - * @param cell The cell of the bitmap to check + * @param cell The index of the specific cell/frame within the bitmap to check for collision. + * Bitmaps can be divided into a grid of cells using `bitmap_set_cell_details`, + * which is useful for sprite sheets containing animation frames or tile sets. + * Use this parameter to test collision against a specific frame rather than + * the entire bitmap. For example, checking if a player collides with frame 2 + * of a spike trap animation (spikes extended) vs frame 0 (spikes retracted). * @param x The x location where the bitmap is drawn * @param y The y location where the bitmap is drawn * @return True if the sprite collides with the bitmap cell when drawn @@ -577,12 +583,18 @@ namespace splashkit_lib bool sprite_bitmap_collision(sprite s, bitmap bmp, int cell, double x, double y); /** - * Tests if a sprite will collide with a bitmap drawn at the indicated - * location. + * Tests if a sprite will collide with a specific cell of a bitmap drawn at + * the indicated point. This is useful when the bitmap contains multiple + * animation frames or states organised as cells. * * @param s The sprite to test * @param bmp The bitmap to test - * @param cell The cell of the bitmap to check + * @param cell The index of the specific cell/frame within the bitmap to check for collision. + * Bitmaps can be divided into a grid of cells using `bitmap_set_cell_details`, + * which is useful for sprite sheets containing animation frames or tile sets. + * Use this parameter to test collision against a specific frame rather than + * the entire bitmap. For example, checking if a player collides with frame 2 + * of a spike trap animation (spikes extended) vs frame 0 (spikes retracted). * @param pt The point where the bitmap is drawn * @return True if the sprite collides with the bitmap cell when drawn * at the indicated location. diff --git a/coresdk/src/test/test_main.cpp b/coresdk/src/test/test_main.cpp index 0b6e8ab9..0a1c9fd7 100644 --- a/coresdk/src/test/test_main.cpp +++ b/coresdk/src/test/test_main.cpp @@ -59,6 +59,7 @@ void setup_tests() add_test("UDP Networking Test", run_udp_networking_test); add_test("TCP Networking Test", run_tcp_networking_test); add_test("UI Tests", run_ui_test); + add_test("Sprite Bitmap Cell Collision", run_sprite_bitmap_cell_collision_test); add_test("GPIO - Basic Tests", run_gpio_tests); add_test("GPIO - Remote GPIO Tests", run_remote_gpio_tests); add_test("GPIO - ADC Tests", run_gpio_adc_tests); diff --git a/coresdk/src/test/test_main.h b/coresdk/src/test/test_main.h index 1beddfc8..4f46a485 100644 --- a/coresdk/src/test/test_main.h +++ b/coresdk/src/test/test_main.h @@ -44,5 +44,6 @@ void run_gpio_i2c_quad_14_seg_test(); void run_terminal_test(); void run_logging_test(); void run_ui_test(); +void run_sprite_bitmap_cell_collision_test(); #endif /* test_main_h */ diff --git a/coresdk/src/test/test_sprite_bitmap_cell_collision.cpp b/coresdk/src/test/test_sprite_bitmap_cell_collision.cpp new file mode 100644 index 00000000..6b83d342 --- /dev/null +++ b/coresdk/src/test/test_sprite_bitmap_cell_collision.cpp @@ -0,0 +1,179 @@ +// +// test_sprite_bitmap_cell_collision.cpp +// splashkit +// +// Example demonstrating sprite-bitmap collision detection using cells. +// This shows how to check collision against specific animation frames +// within a sprite sheet rather than the entire bitmap. +// + +#include "sprites.h" +#include "images.h" +#include "graphics.h" +#include "window_manager.h" +#include "input.h" +#include "collisions.h" +#include "text.h" +#include + +using namespace std; +using namespace splashkit_lib; + +void run_sprite_bitmap_cell_collision_test() +{ + open_window("Sprite Bitmap Cell Collision Test", 800, 600); + + // Load a sprite sheet with multiple frames representing an environmental hazard + // In this example, we'll create a bitmap representing a spike trap with different states + // Frame 0: Retracted (no spikes - safe) + // Frame 1: Extending (medium spikes - some danger) + // Frame 2: Fully Extended (large spikes - dangerous) + bitmap hazard_spritesheet = create_bitmap("spike_trap_sheet", 300, 100); + + // Set up cell details: 3 frames (100x100 each) in a horizontal strip + bitmap_set_cell_details(hazard_spritesheet, 100, 100, 3, 1, 3); + + // Frame 0 (Retracted): Small grey square (20x20) at bottom - minimal collision area + fill_rectangle_on_bitmap(hazard_spritesheet, rgba_color(128, 128, 128, 255), 40, 75, 20, 20); + + // Frame 1 (Extending): Medium red trapezoid shape (40x40) - moderate collision area + // Draw a simple trapezoid to represent extending spikes + fill_rectangle_on_bitmap(hazard_spritesheet, rgba_color(200, 0, 0, 255), 130, 55, 40, 40); + fill_triangle_on_bitmap(hazard_spritesheet, rgba_color(200, 0, 0, 255), + 130, 55, 170, 55, 150, 40); + + // Frame 2 (Extended): Large bright red spike pattern (60x70) - maximum collision area + // Draw multiple triangular shapes to represent fully extended spikes + // Base platform + fill_rectangle_on_bitmap(hazard_spritesheet, rgba_color(150, 0, 0, 255), 220, 75, 60, 20); + // Spikes pointing up + fill_triangle_on_bitmap(hazard_spritesheet, rgba_color(255, 0, 0, 255), + 220, 75, 230, 75, 225, 25); + fill_triangle_on_bitmap(hazard_spritesheet, rgba_color(255, 0, 0, 255), + 235, 75, 245, 75, 240, 25); + fill_triangle_on_bitmap(hazard_spritesheet, rgba_color(255, 0, 0, 255), + 250, 75, 260, 75, 255, 25); + fill_triangle_on_bitmap(hazard_spritesheet, rgba_color(255, 0, 0, 255), + 265, 75, 275, 75, 270, 25); + + // IMPORTANT: Setup collision mask for the hazard bitmap + // This ensures transparent areas are NOT counted in collision detection + setup_collision_mask(hazard_spritesheet); + + // Create a player sprite with a solid circle + bitmap player_bmp = create_bitmap("player", 40, 40); + clear_bitmap(player_bmp, COLOR_TRANSPARENT); + fill_circle_on_bitmap(player_bmp, COLOR_YELLOW, 20, 20, 18); + + // Setup collision mask for player too + setup_collision_mask(player_bmp); + + sprite player = create_sprite("player", player_bmp); + sprite_set_x(player, 400); + sprite_set_y(player, 300); + + // Hazard bitmap position (fixed on screen) + double hazard_x = 350; + double hazard_y = 250; + + int current_cell = 0; // Start with retracted spikes + + cout << "Sprite Bitmap Cell Collision Test" << endl; + cout << "Use LEFT/RIGHT arrows to change spike trap animation frame (cell)" << endl; + cout << "Use WASD to move the player sprite" << endl; + cout << "Observe how collision changes with different cells!" << endl; + cout << "The trap cycles through: Retracted -> Extending -> Extended" << endl; + + while (!quit_requested()) + { + process_events(); + + // Handle input for changing cells + if (key_typed(RIGHT_KEY)) + { + current_cell = (current_cell + 1) % 3; + } + if (key_typed(LEFT_KEY)) + { + current_cell = (current_cell - 1 + 3) % 3; + } + + // Move player with WASD + if (key_down(W_KEY)) sprite_set_y(player, sprite_y(player) - 3); + if (key_down(S_KEY)) sprite_set_y(player, sprite_y(player) + 3); + if (key_down(A_KEY)) sprite_set_x(player, sprite_x(player) - 3); + if (key_down(D_KEY)) sprite_set_x(player, sprite_x(player) + 3); + + // Check collision with the SPECIFIC CELL (frame) of the hazard sprite sheet + // This is the key function we're demonstrating! + bool colliding = sprite_bitmap_collision(player, hazard_spritesheet, current_cell, hazard_x, hazard_y); + + // Draw + clear_screen(COLOR_WHITE); + + // Draw the current cell of the hazard sprite sheet + drawing_options opts = option_part_bmp( + current_cell * 100, // x offset in source + 0, // y offset in source + 100, // width + 100 // height + ); + draw_bitmap(hazard_spritesheet, hazard_x, hazard_y, opts); + + // Draw a dashed rectangle around the hazard to show cell boundary + draw_rectangle(rgba_color(0, 0, 0, 100), hazard_x, hazard_y, 100, 100); + + // Draw the player sprite (colour changes based on collision) + if (colliding) + { + // Player is colliding - draw in red with pulsing effect + fill_circle(rgba_color(255, 0, 0, 200), sprite_x(player) + 20, sprite_y(player) + 20, 20); + // Draw warning outline + draw_circle(COLOR_RED, sprite_x(player) + 20, sprite_y(player) + 20, 25); + } + else + { + // No collision - draw normally + draw_sprite(player); + } + + // Display information with better formatting + string cell_names[] = {"Retracted (safe)", "Extending (danger!)", "Extended (deadly!)"}; + color cell_colors[] = {COLOR_GREEN, rgba_color(255, 140, 0, 255), COLOR_RED}; + + // Title + draw_text("Spike Trap Cell Collision Demo", COLOR_BLACK, "Arial", 20, 10, 10); + + // Current state info + draw_text("Current Trap State: " + cell_names[current_cell], cell_colors[current_cell], "Arial", 16, 10, 40); + draw_text("Cell Index: " + to_string(current_cell), COLOR_BLACK, 10, 60); + + // Collision status with prominent display + string collision_text = colliding ? "COLLISION DETECTED!" : "No Collision"; + color collision_color = colliding ? COLOR_RED : COLOR_GREEN; + draw_text(collision_text, collision_color, "Arial", 18, 10, 90); + + // Instructions box + fill_rectangle(rgba_color(240, 240, 240, 255), 10, 480, 380, 110); + draw_rectangle(COLOR_BLACK, 10, 480, 380, 110); + draw_text("Instructions:", COLOR_BLACK, "Arial", 14, 20, 490); + draw_text("LEFT/RIGHT: Change spike trap animation state", COLOR_BLACK, 20, 510); + draw_text("WASD: Move player", COLOR_BLACK, 20, 530); + draw_text("Move close to see collision detection in action!", COLOR_BLACK, 20, 550); + + // Explanation box + fill_rectangle(rgba_color(230, 240, 255, 255), 400, 480, 390, 110); + draw_rectangle(COLOR_BLUE, 400, 480, 390, 110); + draw_text("What This Demonstrates:", COLOR_BLUE, "Arial", 14, 410, 490); + draw_text("Testing collision with SPECIFIC CELLS (frames)", COLOR_BLACK, 410, 510); + draw_text("Different animation states = different collision areas", COLOR_BLACK, 410, 530); + draw_text("Notice: Retracted trap has tiny hitbox, extended has large hitbox!", COLOR_BLACK, 410, 550); + + refresh_screen(60); + } + + free_sprite(player); + free_bitmap(player_bmp); + free_bitmap(hazard_spritesheet); + close_all_windows(); +}