Skip to content

Commit aeea53c

Browse files
Add memory fragment collection & UI
Implements collectible memory fragments: adds fragment_id map property and reads it when spawning MemoryFragment entities. MemoryFragment notifies Player on collect; Player gains arrays to track collected/new fragments. SaveSystem persists hasMemoryFragment[0..2] to XML and restores them (new flags cleared on load). Scene: stores fragment persistence across map loads, loads/unloads collected variant textures, draws collected/new animations in the inventory, shows fragment markers on the minimap, and preserves fragment state during submap loads/unloads. Minor UI tweak (inventory portrait vertical offset) and initialization of timers/texture pointers included. MapTemplate.tmx updated with a default fragment_id property.
1 parent 04eaa7d commit aeea53c

9 files changed

Lines changed: 176 additions & 59 deletions

File tree

assets/maps/MapTemplate.tmx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@
423423
<object id="1809" name="MemoryFragment" type="MemoryFragment" x="3784" y="2637" width="80" height="60">
424424
<properties>
425425
<property name="video_path" value="assets/video/Anchor_1.mp4"/>
426+
<property name="fragment_id" type="int" value="0"/>
426427
</properties>
427428
</object>
428429
<object id="1811" name="HidingRock" type="HidingRock" x="6286.79" y="8529.7" width="64" height="64">

include/MemoryFragment.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class MemoryFragment : public Entity
1717
void SetVideoPath(const std::string& path) { videoPath_ = path; }
1818
void SetCollectRange(float r) { collectRange_ = r; }
1919
void SetScale(float s) { scale_ = s; }
20+
void SetFragmentId(int id) { fragmentId_ = id; }
2021

2122
private:
2223
void Draw();
@@ -30,6 +31,7 @@ class MemoryFragment : public Entity
3031
std::string videoPath_ = "";
3132
float collectRange_ = 100.0f;
3233
float scale_ = 0.5f; // 256 * 0.5 = 128px on screen
34+
int fragmentId_ = -1;
3335

3436
// SS_Fragment_Collectible.png: 1536x1024 → 6 cols × 4 rows of 256×256 frames
3537
static constexpr int COLS = 6;

include/Player.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ class Player : public Entity
6868
bool IsBearMode() const { return isBearMode_; }
6969
bool IsBearModeActive() const { return isBearMode_ || isBearTransforming_ || isThrowingBear_ || isKidSleeping_; }
7070

71+
// Memory Fragments
72+
bool HasMemoryFragment(int index) const { return index >= 0 && index < 3 ? hasMemoryFragment_[index] : false; }
73+
void SetMemoryFragment(int index, bool v) { if (index >= 0 && index < 3) hasMemoryFragment_[index] = v; }
74+
bool IsMemoryFragmentNew(int index) const { return index >= 0 && index < 3 ? isMemoryFragmentNew_[index] : false; }
75+
void SetMemoryFragmentNew(int index, bool v) { if (index >= 0 && index < 3) isMemoryFragmentNew_[index] = v; }
76+
7177
private:
7278

7379
void GetPhysicsValues();
@@ -194,6 +200,10 @@ class Player : public Entity
194200
bool hasStuffedAnimal_ = false;
195201
EquippedItem equippedItem_ = EquippedItem::NONE;
196202

203+
// Memory fragments
204+
bool hasMemoryFragment_[3] = { false, false, false };
205+
bool isMemoryFragmentNew_[3] = { false, false, false };
206+
197207
// Push rock state
198208
bool isPushing_ = false;
199209
int pushContactCount_ = 0; // track overlapping push_rock contacts

include/SaveSystem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct GameState
2525
bool playerHasBlanket = false;
2626
bool playerHasSlingshot = false;
2727
bool playerHasStuffedAnimal = false;
28+
bool hasMemoryFragment[3] = { false, false, false };
2829

2930
// Checkpoint state
3031
std::string activeCheckpointId;

include/Scene.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ class Scene : public Module
248248
// ── Loading Screen ────────────────────────────────────────────────────────
249249
void LoadLoading();
250250
void UnloadLoading();
251+
252+
// Persistent state across map loads
253+
bool savedHasBlanket_ = false;
254+
bool savedHasSlingshot_ = false;
255+
bool savedHasStuffedAnimal_ = false;
256+
bool savedFragments_[3] = {false, false, false};
251257
void UpdateLoading(float dt);
252258
void DrawLoading();
253259
float loadingTimer_ = 0.0f;
@@ -508,14 +514,17 @@ class Scene : public Module
508514

509515
// ── Memories UI ───────────────────────────────────────────────────────────
510516
SDL_Texture* texMemoria1Base_ = nullptr;
517+
SDL_Texture* texMemoria1Collected_ = nullptr;
511518
SDL_Texture* texMemoria1N1_ = nullptr;
512519
SDL_Texture* texMemoria1N2_ = nullptr;
513520

514521
SDL_Texture* texMemoria2Base_ = nullptr;
522+
SDL_Texture* texMemoria2Collected_ = nullptr;
515523
SDL_Texture* texMemoria2N1_ = nullptr;
516524
SDL_Texture* texMemoria2N2_ = nullptr;
517525

518526
SDL_Texture* texMemoria3Base_ = nullptr;
527+
SDL_Texture* texMemoria3Collected_ = nullptr;
519528
SDL_Texture* texMemoria3N1_ = nullptr;
520529
SDL_Texture* texMemoria3N2_ = nullptr;
521530
SDL_Texture* texMemoria3N3_ = nullptr;
@@ -532,6 +541,7 @@ class Scene : public Module
532541

533542
// Hover fade states
534543
float memoryHoverTimers_[3] = { 0.0f, 0.0f, 0.0f };
544+
float memoryNewAnimTimer_[3] = { 0.0f, 0.0f, 0.0f };
535545

536546
// Fullscreen state
537547
bool showMemoryViewer_ = false;

src/Map.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,8 @@ void Map::LoadEntities(std::shared_ptr<Player> &player, bool portalTransition,
10671067
frag->SetCollectRange(prop.attribute("value").as_float(100.0f));
10681068
else if (pname == "scale")
10691069
frag->SetScale(prop.attribute("value").as_float(0.5f));
1070+
else if (pname == "fragment_id")
1071+
frag->SetFragmentId(prop.attribute("value").as_int(-1));
10701072
}
10711073
frag->Start();
10721074
LOG("MemoryFragment spawned at (%.0f, %.0f)", frag->position.getX(),

src/MemoryFragment.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "Cinematics.h"
88
#include "Log.h"
99
#include <cmath>
10+
#include "Player.h"
1011

1112
MemoryFragment::MemoryFragment() : Entity(EntityType::MEMORY_FRAGMENT)
1213
{
@@ -53,6 +54,16 @@ bool MemoryFragment::Update(float dt)
5354
{
5455
fading_ = false;
5556
collected_ = true;
57+
58+
// Set fragment in Player
59+
if (fragmentId_ >= 0 && fragmentId_ < 3) {
60+
auto& scn = *Engine::GetInstance().scene;
61+
if (scn.player) {
62+
scn.player->SetMemoryFragment(fragmentId_, true);
63+
scn.player->SetMemoryFragmentNew(fragmentId_, true);
64+
}
65+
}
66+
5667
if (!videoPath_.empty())
5768
{
5869
Engine::GetInstance().cinematics->PlayVideo(videoPath_.c_str());

src/SaveSystem.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ void SaveSystem::CollectPlayerState()
268268
gameState_.playerHasBlanket = scene->player ? scene->player->HasBlanket() : false;
269269
gameState_.playerHasSlingshot = scene->player ? scene->player->HasSlingshot() : false;
270270
gameState_.playerHasStuffedAnimal = scene->player ? scene->player->HasStuffedAnimal() : false;
271+
for (int i = 0; i < 3; ++i) {
272+
gameState_.hasMemoryFragment[i] = scene->player ? scene->player->HasMemoryFragment(i) : false;
273+
}
271274

272275
if (pendingCheckpointPositionOverride_)
273276
{
@@ -349,6 +352,10 @@ void SaveSystem::ApplyPlayerState()
349352
scene->player->SetHasBlanket(gameState_.playerHasBlanket);
350353
scene->player->SetHasSlingshot(gameState_.playerHasSlingshot);
351354
scene->player->SetHasStuffedAnimal(gameState_.playerHasStuffedAnimal);
355+
for (int i = 0; i < 3; ++i) {
356+
scene->player->SetMemoryFragment(i, gameState_.hasMemoryFragment[i]);
357+
scene->player->SetMemoryFragmentNew(i, false);
358+
}
352359
scene->player->Revive();
353360
scene->ResetHealthUI(scene->player->health);
354361
}
@@ -503,6 +510,10 @@ bool SaveSystem::WriteXML(const std::string& filename)
503510
stateNode.append_attribute("hasBlanket") = gameState_.playerHasBlanket;
504511
stateNode.append_attribute("hasSlingshot") = gameState_.playerHasSlingshot;
505512
stateNode.append_attribute("hasStuffedAnimal") = gameState_.playerHasStuffedAnimal;
513+
for (int i = 0; i < 3; ++i) {
514+
std::string attrName = "hasMemoryFragment" + std::to_string(i);
515+
stateNode.append_attribute(attrName.c_str()) = gameState_.hasMemoryFragment[i];
516+
}
506517

507518
// Entities node (placeholder for future)
508519
pugi::xml_node entitiesNode = root.append_child("entities");
@@ -577,6 +588,10 @@ bool SaveSystem::ReadXML(const std::string& filename)
577588
gameState_.playerHasBlanket = stateNode.attribute("hasBlanket").as_bool(false);
578589
gameState_.playerHasSlingshot = stateNode.attribute("hasSlingshot").as_bool(false);
579590
gameState_.playerHasStuffedAnimal = stateNode.attribute("hasStuffedAnimal").as_bool(false);
591+
for (int i = 0; i < 3; ++i) {
592+
std::string attrName = "hasMemoryFragment" + std::to_string(i);
593+
gameState_.hasMemoryFragment[i] = stateNode.attribute(attrName.c_str()).as_bool(false);
594+
}
580595
}
581596
}
582597

0 commit comments

Comments
 (0)