Reply to Re: overlapping hitboxes + touch()
If you don't have an account, just leave the password field blank.
For whatever reason, I decided to take a stab at making a generic exact solution for hitbox intersection.
First, for getting hitbox data to dink-readable format, I made this AWK-script
which can then be run with command "awk -f boundmaker.awk dink.ini > story/mkbounds.c" to create a DinkC script that stores the hardbox data in sprite info.
Then you should add a
Then, to check the hitbox intersection, you use this script:
To use it call it with external, with two parametres corresponding for the sprites to check
Note that you must leave maps 748 to 768 unsused (or adjust above scripts if you want to use some other range).
Some caveats:
* It does not work on sprites with automatic hitbox sizes.
* It does not care about set_sprite_info or set_frame_frame INI lines
* Weapon scripts (and any other scripts where you call init()) can change the hitbox data.
* If you modify dink.ini, you must remember to regenerate mkchanges.c
* If you modify dink.ini, the old savegames will still have the old hitbox data. You could fix this by getting mkchanges to run on the game load.
Fixing these issues is left as an exercise for the reader.
Edit: argh, why can't DTN escape stuff inside the code-blocks, I definitely don't want "↦" to be parsed as "↦" within. Though at least now I know that html escape sequences work on DTN 🤷
Edit 2: Here's an example D-mod
First, for getting hitbox data to dink-readable format, I made this AWK-script
BEGIN { FS = " " last_map = 0; base_map = 748; print "void main(void)\n{" } tolower($1) ~ "^load_sequence" { print "//", $0; map = base_map + int($3 / 100); spr = $3 % 100; print "&player_map = " map ";"; print "editor_seq(" spr ", " ($7 * -1) ");"; print "editor_frame(" spr ", " ($8 * -1) ");"; map += 10; print "&player_map = " map ";"; print "editor_seq(" spr ", " $9 ");"; print "editor_frame(" spr ", " $10 ");"; } END { print "kill_this_task();\n}" }
which can then be run with command "awk -f boundmaker.awk dink.ini > story/mkbounds.c" to create a DinkC script that stores the hardbox data in sprite info.
Then you should add a
spawn("mkbounds")line to start-1.c, to actually run the script.
Then, to check the hitbox intersection, you use this script:
// Bounds.c void get_left(void) { int &real_map = &player_map; int &tmp_map = sp_pseq(&arg1, -1); &tmp_map /= 100; &tmp_map += 748; &player_map = &tmp_map; int &spr = sp_pseq(&arg1, -1); &spr = math_mod(&spr, 100); int &ret = editor_seq(&spr, -1); &player_map = &real_map; return(&ret); } void get_top(void) { int &real_map = &player_map; int &tmp_map = sp_pseq(&arg1, -1); &tmp_map /= 100; &tmp_map += 748; &player_map = &tmp_map; int &spr = sp_pseq(&arg1, -1); &spr = math_mod(&spr, 100); int &ret = editor_frame(&spr, -1); &player_map = &real_map; return(&ret); } void get_right(void) { int &real_map = &player_map; int &tmp_map = sp_pseq(&arg1, -1); &tmp_map /= 100; &tmp_map += 758; &player_map = &tmp_map; int &spr = sp_pseq(&arg1, -1); &spr = math_mod(&spr, 100); int &ret = editor_seq(&spr, -1); &player_map = &real_map; return(&ret); } void get_bottom(void) { int &real_map = &player_map; int &tmp_map = sp_pseq(&arg1, -1); &tmp_map /= 100; &tmp_map += 758; &player_map = &tmp_map; int &spr = sp_pseq(&arg1, -1); &spr = math_mod(&spr, 100); int &ret = editor_frame(&spr, -1); &player_map = &real_map; return(&ret); } // Returns 1 if arg1 and arg2's hitboxes intersect, 0 otherwise void intersects(void) { int &dist; int &diff; &diff = sp_x(&arg1, -1); &diff -= sp_x(&arg2, -1); if(&diff > 0) { get_left(&arg1); &dist = &return; get_right(&arg2); &dist += &return; } else { &diff *= -1; get_right(&arg1); &dist = &return; get_left(&arg2); &dist += &return; } if(&diff > &dist) { //No overlap, too much horizontal distance return(0); } &diff = sp_y(&arg1, -1); &diff -= sp_y(&arg2, -1); if(&diff > 0) { get_top(&arg1); &dist = &return; get_bottom(&arg2); &dist += &return; } else { &diff *= -1; get_bottom(&arg1); &dist = &return; get_top(&arg2); &dist += &return; } if(&diff > &dist) { //No overlap, too much vertical distance return(0); } //Sprites intersect! return(1); }
To use it call it with external, with two parametres corresponding for the sprites to check
void main (void) { loop: wait(0); external("bounds", "intersects", ¤t_sprite, 1); if(&return == 0) { say("Hey, come closer!", ¤t_sprite); } else { say("Hey, stop touching me!", ¤t_sprite); } goto loop; }
Note that you must leave maps 748 to 768 unsused (or adjust above scripts if you want to use some other range).
Some caveats:
* It does not work on sprites with automatic hitbox sizes.
* It does not care about set_sprite_info or set_frame_frame INI lines
* Weapon scripts (and any other scripts where you call init()) can change the hitbox data.
* If you modify dink.ini, you must remember to regenerate mkchanges.c
* If you modify dink.ini, the old savegames will still have the old hitbox data. You could fix this by getting mkchanges to run on the game load.
Fixing these issues is left as an exercise for the reader.
Edit: argh, why can't DTN escape stuff inside the code-blocks, I definitely don't want "↦" to be parsed as "↦" within. Though at least now I know that html escape sequences work on DTN 🤷
Edit 2: Here's an example D-mod