about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2024-05-12 17:48:02 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2024-05-12 17:48:02 -0400
commitea16cff14ff4faf5782da8ff684a6ec412b7b6ac (patch)
treea5f09508f2f6c5e969a993de67181d5e94878924 /src
parent8edd1bfd4ed2a42c28830f6c6575684aa3461b77 (diff)
downloadlingo-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.cpp62
-rw-r--r--src/game_data.h25
-rw-r--r--src/subway_map.cpp89
-rw-r--r--src/subway_map.h35
-rw-r--r--src/tracker_frame.cpp13
-rw-r--r--src/tracker_frame.h2
-rw-r--r--src/tracker_state.cpp20
-rw-r--r--src/tracker_state.h2
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() {
704int GD_GetRoomForSunwarp(int index) { 756int GD_GetRoomForSunwarp(int index) {
705 return GetState().room_by_sunwarp_.at(index); 757 return GetState().room_by_sunwarp_.at(index);
706} 758}
759
760const std::vector<SubwayItem> &GD_GetSubwayItems() {
761 return GetState().subway_items_;
762}
763
764const 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
64struct Door { 64struct 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
122enum class SubwaySunwarpType {
123 kEnter,
124 kExit,
125 kFinal
126};
127
128struct SubwaySunwarp {
129 int dots;
130 SubwaySunwarpType type;
131};
132
133struct 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
121const std::vector<MapArea>& GD_GetMapAreas(); 144const std::vector<MapArea>& GD_GetMapAreas();
122const MapArea& GD_GetMapArea(int id); 145const MapArea& GD_GetMapArea(int id);
123int GD_GetRoomByName(const std::string& name); 146int GD_GetRoomByName(const std::string& name);
@@ -131,5 +154,7 @@ const std::vector<int>& GD_GetAchievementPanels();
131int GD_GetItemIdForColor(LingoColor color); 154int GD_GetItemIdForColor(LingoColor color);
132const std::vector<int>& GD_GetSunwarpDoors(); 155const std::vector<int>& GD_GetSunwarpDoors();
133int GD_GetRoomForSunwarp(int index); 156int GD_GetRoomForSunwarp(int index);
157const std::vector<SubwayItem>& GD_GetSubwayItems();
158const 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
7constexpr int AREA_ACTUAL_SIZE = 21;
8
9SubwayMap::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
23void SubwayMap::UpdateIndicators() {
24 Redraw();
25 Resize();
26}
27
28void 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
39void SubwayMap::OnMouseMove(wxMouseEvent &event) {
40 event.Skip();
41}
42
43void 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
66void 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
12class 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) {
165void TrackerFrame::OnStateChanged(wxCommandEvent &event) { 171void 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
10class AchievementsPane; 10class AchievementsPane;
11class SubwayMap;
11class TrackerPanel; 12class TrackerPanel;
12 13
13wxDECLARE_EVENT(STATE_CHANGED, wxCommandEvent); 14wxDECLARE_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
15struct TrackerState { 15struct 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
455bool 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
6bool IsLocationReachable(int location_id); 6bool IsLocationReachable(int location_id);
7 7
8bool 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 */