diff options
author | Star Rauchenberger <fefferburbia@gmail.com> | 2024-05-12 17:48:02 -0400 |
---|---|---|
committer | Star Rauchenberger <fefferburbia@gmail.com> | 2024-05-12 17:48:02 -0400 |
commit | ea16cff14ff4faf5782da8ff684a6ec412b7b6ac (patch) | |
tree | a5f09508f2f6c5e969a993de67181d5e94878924 /src | |
parent | 8edd1bfd4ed2a42c28830f6c6575684aa3461b77 (diff) | |
download | lingo-ap-tracker-ea16cff14ff4faf5782da8ff684a6ec412b7b6ac.tar.gz lingo-ap-tracker-ea16cff14ff4faf5782da8ff684a6ec412b7b6ac.tar.bz2 lingo-ap-tracker-ea16cff14ff4faf5782da8ff684a6ec412b7b6ac.zip |
Started making subway map
Diffstat (limited to 'src')
-rw-r--r-- | src/game_data.cpp | 62 | ||||
-rw-r--r-- | src/game_data.h | 25 | ||||
-rw-r--r-- | src/subway_map.cpp | 89 | ||||
-rw-r--r-- | src/subway_map.h | 35 | ||||
-rw-r--r-- | src/tracker_frame.cpp | 13 | ||||
-rw-r--r-- | src/tracker_frame.h | 2 | ||||
-rw-r--r-- | src/tracker_state.cpp | 20 | ||||
-rw-r--r-- | src/tracker_state.h | 2 |
8 files changed, 244 insertions, 4 deletions
diff --git a/src/game_data.cpp b/src/game_data.cpp index c98f532..4348967 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp | |||
@@ -44,6 +44,7 @@ struct GameData { | |||
44 | std::vector<Door> doors_; | 44 | std::vector<Door> doors_; |
45 | std::vector<Panel> panels_; | 45 | std::vector<Panel> panels_; |
46 | std::vector<MapArea> map_areas_; | 46 | std::vector<MapArea> map_areas_; |
47 | std::vector<SubwayItem> subway_items_; | ||
47 | 48 | ||
48 | std::map<std::string, int> room_by_id_; | 49 | std::map<std::string, int> room_by_id_; |
49 | std::map<std::string, int> door_by_id_; | 50 | std::map<std::string, int> door_by_id_; |
@@ -606,6 +607,56 @@ struct GameData { | |||
606 | errstr << "Area data not found for: " << area; | 607 | errstr << "Area data not found for: " << area; |
607 | TrackerLog(errstr.str()); | 608 | TrackerLog(errstr.str()); |
608 | } | 609 | } |
610 | |||
611 | // Read in subway items. | ||
612 | YAML::Node subway_config = | ||
613 | YAML::LoadFile(GetAbsolutePath("assets/subway.yaml")); | ||
614 | for (const auto &subway_it : subway_config) { | ||
615 | SubwayItem subway_item; | ||
616 | subway_item.id = subway_items_.size(); | ||
617 | subway_item.x = subway_it["pos"][0].as<int>(); | ||
618 | subway_item.y = subway_it["pos"][1].as<int>(); | ||
619 | |||
620 | if (subway_it["door"]) { | ||
621 | subway_item.door = AddOrGetDoor(subway_it["room"].as<std::string>(), | ||
622 | subway_it["door"].as<std::string>()); | ||
623 | } | ||
624 | |||
625 | if (subway_it["paintings"]) { | ||
626 | for (const auto &painting_it : subway_it["paintings"]) { | ||
627 | subway_item.paintings.push_back(painting_it.as<std::string>()); | ||
628 | } | ||
629 | } | ||
630 | |||
631 | if (subway_it["tags"]) { | ||
632 | for (const auto &tag_it : subway_it["tags"]) { | ||
633 | subway_item.tags.push_back(tag_it.as<std::string>()); | ||
634 | } | ||
635 | } | ||
636 | |||
637 | if (subway_it["sunwarp"]) { | ||
638 | SubwaySunwarp sunwarp; | ||
639 | sunwarp.dots = subway_it["sunwarp"]["dots"].as<int>(); | ||
640 | |||
641 | std::string sunwarp_type = | ||
642 | subway_it["sunwarp"]["type"].as<std::string>(); | ||
643 | if (sunwarp_type == "final") { | ||
644 | sunwarp.type = SubwaySunwarpType::kFinal; | ||
645 | } else if (sunwarp_type == "exit") { | ||
646 | sunwarp.type = SubwaySunwarpType::kExit; | ||
647 | } else { | ||
648 | sunwarp.type = SubwaySunwarpType::kEnter; | ||
649 | } | ||
650 | |||
651 | subway_item.sunwarp = sunwarp; | ||
652 | } | ||
653 | |||
654 | if (subway_it["special"]) { | ||
655 | subway_item.special = subway_it["special"].as<std::string>(); | ||
656 | } | ||
657 | |||
658 | subway_items_.push_back(subway_item); | ||
659 | } | ||
609 | } | 660 | } |
610 | 661 | ||
611 | int AddOrGetRoom(std::string room) { | 662 | int AddOrGetRoom(std::string room) { |
@@ -621,8 +672,9 @@ struct GameData { | |||
621 | std::string full_name = room + " - " + door; | 672 | std::string full_name = room + " - " + door; |
622 | 673 | ||
623 | if (!door_by_id_.count(full_name)) { | 674 | if (!door_by_id_.count(full_name)) { |
675 | int door_id = doors_.size(); | ||
624 | door_by_id_[full_name] = doors_.size(); | 676 | door_by_id_[full_name] = doors_.size(); |
625 | doors_.push_back({.room = AddOrGetRoom(room), .name = door}); | 677 | doors_.push_back({.id = door_id, .room = AddOrGetRoom(room), .name = door}); |
626 | } | 678 | } |
627 | 679 | ||
628 | return door_by_id_[full_name]; | 680 | return door_by_id_[full_name]; |
@@ -704,3 +756,11 @@ const std::vector<int> &GD_GetSunwarpDoors() { | |||
704 | int GD_GetRoomForSunwarp(int index) { | 756 | int GD_GetRoomForSunwarp(int index) { |
705 | return GetState().room_by_sunwarp_.at(index); | 757 | return GetState().room_by_sunwarp_.at(index); |
706 | } | 758 | } |
759 | |||
760 | const std::vector<SubwayItem> &GD_GetSubwayItems() { | ||
761 | return GetState().subway_items_; | ||
762 | } | ||
763 | |||
764 | const SubwayItem &GD_GetSubwayItem(int id) { | ||
765 | return GetState().subway_items_.at(id); | ||
766 | } | ||
diff --git a/src/game_data.h b/src/game_data.h index cd09627..37d1eb3 100644 --- a/src/game_data.h +++ b/src/game_data.h | |||
@@ -62,6 +62,7 @@ struct ProgressiveRequirement { | |||
62 | }; | 62 | }; |
63 | 63 | ||
64 | struct Door { | 64 | struct Door { |
65 | int id; | ||
65 | int room; | 66 | int room; |
66 | std::string name; | 67 | std::string name; |
67 | std::string location_name; | 68 | std::string location_name; |
@@ -118,6 +119,28 @@ struct MapArea { | |||
118 | bool hunt = false; | 119 | bool hunt = false; |
119 | }; | 120 | }; |
120 | 121 | ||
122 | enum class SubwaySunwarpType { | ||
123 | kEnter, | ||
124 | kExit, | ||
125 | kFinal | ||
126 | }; | ||
127 | |||
128 | struct SubwaySunwarp { | ||
129 | int dots; | ||
130 | SubwaySunwarpType type; | ||
131 | }; | ||
132 | |||
133 | struct SubwayItem { | ||
134 | int id; | ||
135 | int x; | ||
136 | int y; | ||
137 | std::optional<int> door; | ||
138 | std::vector<std::string> paintings; | ||
139 | std::vector<std::string> tags; | ||
140 | std::optional<SubwaySunwarp> sunwarp; | ||
141 | std::optional<std::string> special; | ||
142 | }; | ||
143 | |||
121 | const std::vector<MapArea>& GD_GetMapAreas(); | 144 | const std::vector<MapArea>& GD_GetMapAreas(); |
122 | const MapArea& GD_GetMapArea(int id); | 145 | const MapArea& GD_GetMapArea(int id); |
123 | int GD_GetRoomByName(const std::string& name); | 146 | int GD_GetRoomByName(const std::string& name); |
@@ -131,5 +154,7 @@ const std::vector<int>& GD_GetAchievementPanels(); | |||
131 | int GD_GetItemIdForColor(LingoColor color); | 154 | int GD_GetItemIdForColor(LingoColor color); |
132 | const std::vector<int>& GD_GetSunwarpDoors(); | 155 | const std::vector<int>& GD_GetSunwarpDoors(); |
133 | int GD_GetRoomForSunwarp(int index); | 156 | int GD_GetRoomForSunwarp(int index); |
157 | const std::vector<SubwayItem>& GD_GetSubwayItems(); | ||
158 | const SubwayItem& GD_GetSubwayItem(int id); | ||
134 | 159 | ||
135 | #endif /* end of include guard: GAME_DATA_H_9C42AC51 */ | 160 | #endif /* end of include guard: GAME_DATA_H_9C42AC51 */ |
diff --git a/src/subway_map.cpp b/src/subway_map.cpp new file mode 100644 index 0000000..c58b2d1 --- /dev/null +++ b/src/subway_map.cpp | |||
@@ -0,0 +1,89 @@ | |||
1 | #include "subway_map.h" | ||
2 | |||
3 | #include "game_data.h" | ||
4 | #include "global.h" | ||
5 | #include "tracker_state.h" | ||
6 | |||
7 | constexpr int AREA_ACTUAL_SIZE = 21; | ||
8 | |||
9 | SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | ||
10 | map_image_ = | ||
11 | wxImage(GetAbsolutePath("assets/subway.png").c_str(), wxBITMAP_TYPE_PNG); | ||
12 | if (!map_image_.IsOk()) { | ||
13 | return; | ||
14 | } | ||
15 | |||
16 | Redraw(); | ||
17 | Resize(); | ||
18 | |||
19 | Bind(wxEVT_PAINT, &SubwayMap::OnPaint, this); | ||
20 | Bind(wxEVT_MOTION, &SubwayMap::OnMouseMove, this); | ||
21 | } | ||
22 | |||
23 | void SubwayMap::UpdateIndicators() { | ||
24 | Redraw(); | ||
25 | Resize(); | ||
26 | } | ||
27 | |||
28 | void SubwayMap::OnPaint(wxPaintEvent &event) { | ||
29 | if (GetSize() != resized_.GetSize()) { | ||
30 | Resize(); | ||
31 | } | ||
32 | |||
33 | wxPaintDC dc(this); | ||
34 | dc.DrawBitmap(resized_, 0, 0); | ||
35 | |||
36 | event.Skip(); | ||
37 | } | ||
38 | |||
39 | void SubwayMap::OnMouseMove(wxMouseEvent &event) { | ||
40 | event.Skip(); | ||
41 | } | ||
42 | |||
43 | void SubwayMap::Redraw() { | ||
44 | rendered_ = wxBitmap(map_image_); | ||
45 | |||
46 | wxMemoryDC dc; | ||
47 | dc.SelectObject(rendered_); | ||
48 | |||
49 | for (const SubwayItem &subway_item : GD_GetSubwayItems()) { | ||
50 | const wxBrush *brush_color = wxGREY_BRUSH; | ||
51 | if (subway_item.door) { | ||
52 | if (IsDoorOpen(*subway_item.door)) { | ||
53 | brush_color = wxGREEN_BRUSH; | ||
54 | } else { | ||
55 | brush_color = wxRED_BRUSH; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1)); | ||
60 | dc.SetBrush(*brush_color); | ||
61 | dc.DrawRectangle({subway_item.x, subway_item.y}, | ||
62 | {AREA_ACTUAL_SIZE, AREA_ACTUAL_SIZE}); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | void SubwayMap::Resize() { | ||
67 | wxSize panel_size = GetSize(); | ||
68 | wxSize image_size = rendered_.GetSize(); | ||
69 | |||
70 | render_x_ = 0; | ||
71 | render_y_ = 0; | ||
72 | render_width_ = panel_size.GetWidth(); | ||
73 | render_height_ = panel_size.GetHeight(); | ||
74 | |||
75 | if (image_size.GetWidth() * panel_size.GetHeight() > | ||
76 | panel_size.GetWidth() * image_size.GetHeight()) { | ||
77 | render_height_ = (panel_size.GetWidth() * image_size.GetHeight()) / | ||
78 | image_size.GetWidth(); | ||
79 | render_y_ = (panel_size.GetHeight() - render_height_) / 2; | ||
80 | } else { | ||
81 | render_width_ = (image_size.GetWidth() * panel_size.GetHeight()) / | ||
82 | image_size.GetHeight(); | ||
83 | render_x_ = (panel_size.GetWidth() - render_width_) / 2; | ||
84 | } | ||
85 | |||
86 | resized_ = wxBitmap(rendered_.ConvertToImage() | ||
87 | .Scale(render_width_, render_height_, wxIMAGE_QUALITY_BILINEAR) | ||
88 | .Size(panel_size, {render_x_, render_y_}, 0, 0, 0)); | ||
89 | } | ||
diff --git a/src/subway_map.h b/src/subway_map.h new file mode 100644 index 0000000..dc67867 --- /dev/null +++ b/src/subway_map.h | |||
@@ -0,0 +1,35 @@ | |||
1 | #ifndef SUBWAY_MAP_H_BD2D843E | ||
2 | #define SUBWAY_MAP_H_BD2D843E | ||
3 | |||
4 | #include <wx/wxprec.h> | ||
5 | |||
6 | #ifndef WX_PRECOMP | ||
7 | #include <wx/wx.h> | ||
8 | #endif | ||
9 | |||
10 | #include <vector> | ||
11 | |||
12 | class SubwayMap : public wxPanel { | ||
13 | public: | ||
14 | SubwayMap(wxWindow *parent); | ||
15 | |||
16 | void UpdateIndicators(); | ||
17 | |||
18 | private: | ||
19 | void OnPaint(wxPaintEvent &event); | ||
20 | void OnMouseMove(wxMouseEvent &event); | ||
21 | |||
22 | void Redraw(); | ||
23 | void Resize(); | ||
24 | |||
25 | wxImage map_image_; | ||
26 | wxBitmap rendered_; | ||
27 | wxBitmap resized_; | ||
28 | int render_x_ = 0; | ||
29 | int render_y_ = 0; | ||
30 | int render_width_ = 0; | ||
31 | int render_height_ = 0; | ||
32 | |||
33 | }; | ||
34 | |||
35 | #endif /* end of include guard: SUBWAY_MAP_H_BD2D843E */ | ||
diff --git a/src/tracker_frame.cpp b/src/tracker_frame.cpp index 8a0c764..70fee2d 100644 --- a/src/tracker_frame.cpp +++ b/src/tracker_frame.cpp | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "ap_state.h" | 11 | #include "ap_state.h" |
12 | #include "connection_dialog.h" | 12 | #include "connection_dialog.h" |
13 | #include "settings_dialog.h" | 13 | #include "settings_dialog.h" |
14 | #include "subway_map.h" | ||
14 | #include "tracker_config.h" | 15 | #include "tracker_config.h" |
15 | #include "tracker_panel.h" | 16 | #include "tracker_panel.h" |
16 | #include "version.h" | 17 | #include "version.h" |
@@ -58,15 +59,20 @@ TrackerFrame::TrackerFrame() | |||
58 | Bind(STATE_CHANGED, &TrackerFrame::OnStateChanged, this); | 59 | Bind(STATE_CHANGED, &TrackerFrame::OnStateChanged, this); |
59 | Bind(STATUS_CHANGED, &TrackerFrame::OnStatusChanged, this); | 60 | Bind(STATUS_CHANGED, &TrackerFrame::OnStatusChanged, this); |
60 | 61 | ||
61 | wxChoicebook *choicebook = new wxChoicebook(this, wxID_ANY); | ||
62 | achievements_pane_ = new AchievementsPane(this); | 62 | achievements_pane_ = new AchievementsPane(this); |
63 | |||
64 | wxChoicebook *choicebook = new wxChoicebook(this, wxID_ANY); | ||
63 | choicebook->AddPage(achievements_pane_, "Achievements"); | 65 | choicebook->AddPage(achievements_pane_, "Achievements"); |
64 | 66 | ||
65 | tracker_panel_ = new TrackerPanel(this); | 67 | wxNotebook *rightpane = new wxNotebook(this, wxID_ANY); |
68 | tracker_panel_ = new TrackerPanel(rightpane); | ||
69 | subway_map_ = new SubwayMap(rightpane); | ||
70 | rightpane->AddPage(tracker_panel_, "Map"); | ||
71 | rightpane->AddPage(subway_map_, "Subway"); | ||
66 | 72 | ||
67 | wxBoxSizer *top_sizer = new wxBoxSizer(wxHORIZONTAL); | 73 | wxBoxSizer *top_sizer = new wxBoxSizer(wxHORIZONTAL); |
68 | top_sizer->Add(choicebook, wxSizerFlags().Expand().Proportion(1)); | 74 | top_sizer->Add(choicebook, wxSizerFlags().Expand().Proportion(1)); |
69 | top_sizer->Add(tracker_panel_, wxSizerFlags().Expand().Proportion(3)); | 75 | top_sizer->Add(rightpane, wxSizerFlags().Expand().Proportion(3)); |
70 | 76 | ||
71 | SetSizerAndFit(top_sizer); | 77 | SetSizerAndFit(top_sizer); |
72 | SetSize(1280, 728); | 78 | SetSize(1280, 728); |
@@ -165,6 +171,7 @@ void TrackerFrame::OnCheckForUpdates(wxCommandEvent &event) { | |||
165 | void TrackerFrame::OnStateChanged(wxCommandEvent &event) { | 171 | void TrackerFrame::OnStateChanged(wxCommandEvent &event) { |
166 | tracker_panel_->UpdateIndicators(); | 172 | tracker_panel_->UpdateIndicators(); |
167 | achievements_pane_->UpdateIndicators(); | 173 | achievements_pane_->UpdateIndicators(); |
174 | subway_map_->UpdateIndicators(); | ||
168 | Refresh(); | 175 | Refresh(); |
169 | } | 176 | } |
170 | 177 | ||
diff --git a/src/tracker_frame.h b/src/tracker_frame.h index e5bf97e..c7c6772 100644 --- a/src/tracker_frame.h +++ b/src/tracker_frame.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #endif | 8 | #endif |
9 | 9 | ||
10 | class AchievementsPane; | 10 | class AchievementsPane; |
11 | class SubwayMap; | ||
11 | class TrackerPanel; | 12 | class TrackerPanel; |
12 | 13 | ||
13 | wxDECLARE_EVENT(STATE_CHANGED, wxCommandEvent); | 14 | wxDECLARE_EVENT(STATE_CHANGED, wxCommandEvent); |
@@ -35,6 +36,7 @@ class TrackerFrame : public wxFrame { | |||
35 | 36 | ||
36 | TrackerPanel *tracker_panel_; | 37 | TrackerPanel *tracker_panel_; |
37 | AchievementsPane *achievements_pane_; | 38 | AchievementsPane *achievements_pane_; |
39 | SubwayMap *subway_map_; | ||
38 | }; | 40 | }; |
39 | 41 | ||
40 | #endif /* end of include guard: TRACKER_FRAME_H_86BD8DFB */ | 42 | #endif /* end of include guard: TRACKER_FRAME_H_86BD8DFB */ |
diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index 640a159..5588c7f 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp | |||
@@ -14,6 +14,7 @@ namespace { | |||
14 | 14 | ||
15 | struct TrackerState { | 15 | struct TrackerState { |
16 | std::map<int, bool> reachability; | 16 | std::map<int, bool> reachability; |
17 | std::set<int> reachable_doors; | ||
17 | std::mutex reachability_mutex; | 18 | std::mutex reachability_mutex; |
18 | }; | 19 | }; |
19 | 20 | ||
@@ -156,6 +157,11 @@ class StateCalculator { | |||
156 | flood_boundary = new_boundary; | 157 | flood_boundary = new_boundary; |
157 | panel_boundary = new_panel_boundary; | 158 | panel_boundary = new_panel_boundary; |
158 | } | 159 | } |
160 | |||
161 | // Now that we know the full reachable area, let's make sure all doors are evaluated. | ||
162 | for (const Door& door : GD_GetDoors()) { | ||
163 | int discard = IsDoorReachable(door.id); | ||
164 | } | ||
159 | } | 165 | } |
160 | 166 | ||
161 | const std::set<int>& GetReachableRooms() const { return reachable_rooms_; } | 167 | const std::set<int>& GetReachableRooms() const { return reachable_rooms_; } |
@@ -422,9 +428,17 @@ void RecalculateReachability() { | |||
422 | } | 428 | } |
423 | } | 429 | } |
424 | 430 | ||
431 | std::set<int> new_reachable_doors; | ||
432 | for (const auto& [door_id, decision] : state_calculator.GetDoorDecisions()) { | ||
433 | if (decision == kYes) { | ||
434 | new_reachable_doors.insert(door_id); | ||
435 | } | ||
436 | } | ||
437 | |||
425 | { | 438 | { |
426 | std::lock_guard reachability_guard(GetState().reachability_mutex); | 439 | std::lock_guard reachability_guard(GetState().reachability_mutex); |
427 | std::swap(GetState().reachability, new_reachability); | 440 | std::swap(GetState().reachability, new_reachability); |
441 | std::swap(GetState().reachable_doors, new_reachable_doors); | ||
428 | } | 442 | } |
429 | } | 443 | } |
430 | 444 | ||
@@ -437,3 +451,9 @@ bool IsLocationReachable(int location_id) { | |||
437 | return false; | 451 | return false; |
438 | } | 452 | } |
439 | } | 453 | } |
454 | |||
455 | bool IsDoorOpen(int door_id) { | ||
456 | std::lock_guard reachability_guard(GetState().reachability_mutex); | ||
457 | |||
458 | return GetState().reachable_doors.count(door_id); | ||
459 | } | ||
diff --git a/src/tracker_state.h b/src/tracker_state.h index e73607f..119b3b5 100644 --- a/src/tracker_state.h +++ b/src/tracker_state.h | |||
@@ -5,4 +5,6 @@ void RecalculateReachability(); | |||
5 | 5 | ||
6 | bool IsLocationReachable(int location_id); | 6 | bool IsLocationReachable(int location_id); |
7 | 7 | ||
8 | bool IsDoorOpen(int door_id); | ||
9 | |||
8 | #endif /* end of include guard: TRACKER_STATE_H_8639BC90 */ | 10 | #endif /* end of include guard: TRACKER_STATE_H_8639BC90 */ |