FINALLY figured out how to rotate to face a square, thanks to all the help from Twitch chat. I need to study Trig.

This commit is contained in:
Zed A. Shaw 2025-09-02 02:26:08 -04:00
parent d822cb3438
commit 9faad5f263
5 changed files with 85 additions and 11 deletions

View file

@ -37,7 +37,7 @@ tracy_build:
meson compile -j 10 -C builddir
test:
./builddir/runtests -d yes
./builddir/runtests -d yes "[systems-rotate]"
run: build test
ifeq '$(OS)' 'Windows_NT'
@ -60,7 +60,7 @@ clean:
meson compile --clean -C builddir
debug_test: build
gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests -e
gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests -e "[systems-rotate]"
win_installer:
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'

View file

@ -135,6 +135,11 @@ bool Autowalker::path_player(Pathing& paths, Point& target_out) {
void Autowalker::rotate_player(Point target) {
auto player = GameDB::player_position();
if(target == player.location) {
dbc::log("!!!!!!!!!!!! maybe this is wrong");
return;
}
auto dir = System::shortest_rotate(player.location, player.aiming_at, target);
while(rayview->aiming_at != target) {
@ -180,7 +185,7 @@ void Autowalker::handle_player_walk(ai::State& start, ai::State& goal) {
start = update_state(start);
auto a_plan = ai::plan("Host::actions", start, goal);
auto action = a_plan.script.front();
ai::dump_script("AUTOWALK", start, a_plan.script);
// ai::dump_script("AUTOWALK", start, a_plan.script);
if(action.name == "find_enemy") {
status(L"FINDING ENEMY");

View file

@ -132,7 +132,6 @@ executable('runtests', sources + [
'tests/animation.cpp',
'tests/base.cpp',
'tests/battle.cpp',
'tests/palette.cpp',
'tests/components.cpp',
'tests/config.cpp',
'tests/dbc.cpp',
@ -146,12 +145,14 @@ executable('runtests', sources + [
'tests/map.cpp',
'tests/matrix.cpp',
'tests/mazes.cpp',
'tests/palette.cpp',
'tests/pathing.cpp',
'tests/rituals.cpp',
'tests/shaders.cpp',
'tests/sound.cpp',
'tests/spatialmap.cpp',
'tests/stats.cpp',
'tests/systems.cpp',
'tests/textures.cpp',
],
cpp_args: cpp_args,

View file

@ -650,13 +650,20 @@ bool System::use_item(const string& slot_name) {
}
}
gui::Event System::shortest_rotate(Point player_at, Point aiming_at, Point turn_to) {
dbc::check(aiming_at != turn_to, "you're already pointing there.");
dbc::check(player_at != turn_to, "you can't turn on yourself");
gui::Event System::shortest_rotate(Point player_at, Point aiming_at, Point target) {
dbc::check(aiming_at != target, "you're already pointing there.");
dbc::check(player_at != target, "you can't turn on yourself");
Point facing{player_at.x - aiming_at.x, player_at.y - aiming_at.y};
Point target{player_at.x - turn_to.x, player_at.y - turn_to.y};
Point mag{size_t(abs(int(facing.x - target.x))), size_t(abs(int(facing.y - target.y)))};
float target_dx = float(player_at.x) - float(target.x);
float target_dy = float(player_at.y) - float(target.y);
float aiming_dx = float(player_at.x) - float(aiming_at.x);
float aiming_dy = float(player_at.y) - float(aiming_at.y);
return mag.x <= mag.y ? gui::Event::ROTATE_LEFT : gui::Event::ROTATE_RIGHT;
float target_angle = atan2(-target_dy, target_dx) * (180.0 / std::numbers::pi);
float aiming_angle = atan2(-aiming_dy, aiming_dx) * (180.0 / std::numbers::pi);
float diff = target_angle - aiming_angle;
double normalized = fmod(diff + 360.0, 360.0);
return normalized < 180.0 ? gui::Event::ROTATE_LEFT : gui::Event::ROTATE_RIGHT;
}

61
tests/systems.cpp Normal file
View file

@ -0,0 +1,61 @@
#include <catch2/catch_test_macros.hpp>
#include <fmt/core.h>
#include "systems.hpp"
#include <cmath>
#include <numbers>
/*
face_x := rand.Float64() * 100
face_y := rand.Float64() * 100
target_x := rand.Float64() * 100
target_y := rand.Float64() * 100
rad_angle1 := atan2(target_y, target_x)
rad_angle2 := atan2(face_y, face_x)
diff := rad_angle1 - rad_angle2
if diff < 0 { fmt.Printf("\nTurn Right") }
else { fmt.Printf("\nTurn Left") }
*/
TEST_CASE("figure out best rotation direction", "[systems-rotate]") {
Matrix map = matrix::make(3, 3);
Point player_at{1, 1};
map[player_at.y][player_at.x] = 2;
for(matrix::box target{map, player_at.x, player_at.y, 1}; target.next();) {
for(matrix::box aiming_at{map, player_at.x, player_at.y, 1}; aiming_at.next();) {
map[aiming_at.y][aiming_at.x] = 10;
float target_dx = float(player_at.x) - float(target.x);
float target_dy = float(player_at.y) - float(target.y);
float aiming_dx = float(player_at.x) - float(aiming_at.x);
float aiming_dy = float(player_at.y) - float(aiming_at.y);
fmt::println("target_d={},{}; aiming_d={},{}",
target_dx, target_dy, aiming_dx, aiming_dy);
float target_angle = atan2(-target_dy, target_dx) * (180.0 / std::numbers::pi);
float aiming_angle = atan2(-aiming_dy, aiming_dx) * (180.0 / std::numbers::pi);
float diff = target_angle - aiming_angle;
double normalized = fmod(diff + 360.0, 360.0);
fmt::println("\n\n>>>>>>>>> BEGIN");
if(normalized != diff) fmt::println("YOU NEED NORMALIZED");
fmt::println("aming_angle={}, target_angle={}, delta={}, norm={}",
aiming_angle, target_angle, diff, normalized);
fmt::println("TURN {}", normalized < 180.0 ? "LEFT" : "RIGHT");
matrix::dump("< is target, a is aim", map, target.x, target.y);
fmt::println("-----------------END");
map[aiming_at.y][aiming_at.x] = 0;
}
}
}