diff --git a/docs/changelog.txt b/docs/changelog.txt index 4d1beaa0d..ed71a61db 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -5,8 +5,9 @@ are a lot of changes, including a large number of crash fixes. Brief summaries of each section: General: worlds are decrypted in memory now, MegaZeux 1.x worlds -are now supported, you can have more custom sound effects, and -the 1/8th random movement chance of dragons has been readded. +are now supported, you can have more custom sound effects, the +1/8th random movement chance of dragons has been readded, and +static sprites now collide at their apparent position. Robotic: new label PLAYERDIED, new counter KEY_PRESSEDn, new counter DATE_WEEKDAY, new counter SPRn_OFFONEXIT, new viewport @@ -74,6 +75,10 @@ GENERAL could cause it to rarely return a number outside of the expected range. This unfortunately breaks compatibility for the RANDOM_SEED# counter. ++ Static sprites now collide as if they are at the position on + the board where they are currently being drawn i.e. relative + to the viewport instead of at their actual X/Y position. This + behavior has also been added to the IF SPRITE AT # # command. + Optimized ccheck 3 sprite collision performance by generating visibility masks for characters directly instead of using an intermediate render and skipping pixel checks for blank chars. diff --git a/src/run_robot.c b/src/run_robot.c index 4e5be09f9..5821ca37a 100644 --- a/src/run_robot.c +++ b/src/run_robot.c @@ -2313,7 +2313,8 @@ void run_robot(context *ctx, int id, int x, int y) for(i = check_color; i < MAX_SPRITES; i++) { - if(sprite_at_xy(mzx_world->sprite_list[i], check_x, check_y)) + if(sprite_at_xy(mzx_world, mzx_world->sprite_list[i], + check_x, check_y)) break; } if(i == MAX_SPRITES) @@ -2331,7 +2332,7 @@ void run_robot(context *ctx, int id, int x, int y) { if((unsigned int)check_param < 256) { - ret = sprite_at_xy(mzx_world->sprite_list[check_param], + ret = sprite_at_xy(mzx_world, mzx_world->sprite_list[check_param], check_x, check_y); } } diff --git a/src/sprite.c b/src/sprite.c index 2c2714275..2ccba2cff 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -872,7 +872,7 @@ static inline struct rect board_rectangle(struct rect r) ); } -boolean sprite_at_xy(struct sprite *spr, int x, int y) +boolean sprite_at_xy(struct world *mzx_world, struct sprite *spr, int x, int y) { struct rect sprite_rect; struct rect pos_rect; @@ -884,6 +884,15 @@ boolean sprite_at_xy(struct sprite *spr, int x, int y) sprite_rect = sprite_rectangle(spr); pos_rect = rectangle(x * CHAR_W, y * CHAR_H, CHAR_W, CHAR_H); + // Static sprite collision occurs at its apparent position from 2.93 onward. + if((spr->flags & SPRITE_STATIC) && mzx_world->version >= V293) + { + int screen_x, screen_y; + calculate_xytop(mzx_world, &screen_x, &screen_y); + sprite_rect.x += screen_x * CHAR_W; + sprite_rect.y += screen_y * CHAR_H; + } + if(rectangle_overlap(sprite_rect, pos_rect)) return true; return false; @@ -1126,6 +1135,8 @@ int sprite_colliding_xy(struct world *mzx_world, struct sprite *spr, struct board *cur_board = mzx_world->current_board; char *level_id = cur_board->level_id; int board_width = cur_board->board_width; + int screen_x = 0; + int screen_y = 0; int bx, by; int sprite_idx; int cx, cy; @@ -1139,6 +1150,14 @@ int sprite_colliding_xy(struct world *mzx_world, struct sprite *spr, if(mzx_world->version < V290) return sprite_colliding_xy_old(mzx_world, spr, x, y); + // Adjust static sprites to match their apparent positions onscreen. + if(mzx_world->version >= V293) + { + calculate_xytop(mzx_world, &screen_x, &screen_y); + screen_x *= CHAR_W; + screen_y *= CHAR_H; + } + board_rect = rectangle( 0, 0, @@ -1168,6 +1187,11 @@ int sprite_colliding_xy(struct world *mzx_world, struct sprite *spr, sprite_rect = sprite_rectangle(&collision_sprite); col_rect = collision_rectangle(&collision_sprite); + if(spr->flags & SPRITE_STATIC) + { + sprite_rect.x += screen_x; + sprite_rect.y += screen_y; + } col_rect.x += sprite_rect.x; col_rect.y += sprite_rect.y; @@ -1231,6 +1255,11 @@ int sprite_colliding_xy(struct world *mzx_world, struct sprite *spr, target_spr_rect = sprite_rectangle(target_spr); target_col_rect = collision_rectangle(target_spr); + if(target_spr->flags & SPRITE_STATIC) + { + target_spr_rect.x += screen_x; + target_spr_rect.y += screen_y; + } //debug("sprite #%d a: %d %d %d %d\n", // target_rect.x, target_rect.y, target_rect.w, target_rect.h); target_col_rect.x += target_spr_rect.x; diff --git a/src/sprite.h b/src/sprite.h index 4f2616f64..31d07df5f 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -65,7 +65,7 @@ enum void plot_sprite(struct world *mzx_world, struct sprite *cur_sprite, int color, int x, int y); void draw_sprites(struct world *mzx_world); -boolean sprite_at_xy(struct sprite *cur_sprite, int x, int y); +boolean sprite_at_xy(struct world *mzx_world, struct sprite *cur_sprite, int x, int y); int sprite_colliding_xy(struct world *mzx_world, struct sprite *check_sprite, int x, int y); diff --git a/testworlds/2.65/004 Static Sprite Collision.mzx b/testworlds/2.65/004 Static Sprite Collision.mzx new file mode 100644 index 000000000..3d3863bd0 Binary files /dev/null and b/testworlds/2.65/004 Static Sprite Collision.mzx differ diff --git a/testworlds/2.65/004 Static Sprite Collision.txt b/testworlds/2.65/004 Static Sprite Collision.txt new file mode 100644 index 000000000..877bb257a --- /dev/null +++ b/testworlds/2.65/004 Static Sprite Collision.txt @@ -0,0 +1,3 @@ +Title: Static Sprite Collision (2.65) +Author: Alice Rowan +Desc: Pre-2.90 static sprites display relative to the screen but do not collide relative to the screen. This world tests the original collision function from before unbound sprites. diff --git a/testworlds/2.90/016 Static Sprite Collision.mzx b/testworlds/2.90/016 Static Sprite Collision.mzx new file mode 100644 index 000000000..25dc97be5 Binary files /dev/null and b/testworlds/2.90/016 Static Sprite Collision.mzx differ diff --git a/testworlds/2.93/012 Static Sprite Collision.mzx b/testworlds/2.93/012 Static Sprite Collision.mzx new file mode 100644 index 000000000..d2fc17b6f Binary files /dev/null and b/testworlds/2.93/012 Static Sprite Collision.mzx differ