Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/GameCanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ GameCanvas::GameCanvas(Micro* micro)
dx = 0;
dy = height2;

commandMenu = new Command("Menu", 1, 1);
commandMenu = std::make_unique<Command>("Menu", 1, 1);
defaultFontWidth00 = defaultFont->stringWidth("00") + 3;
}

Expand Down Expand Up @@ -589,7 +589,7 @@ void GameCanvas::setMenuManager(MenuManager* menuManager)
void GameCanvas::handleMenuCommand(Command* command, Displayable* displayable)
{
(void)displayable;
if (command == commandMenu) {
if (command == commandMenu.get()) {
menuManager->isMenuRenderingBlocked = true; // Signal menu manager to show menu
micro->gameToMenu(); // Transition from game to menu state
}
Expand Down Expand Up @@ -620,10 +620,15 @@ void GameCanvas::commandAction(Command* command, Displayable* displayable)

void GameCanvas::removeMenuCommand()
{
removeCommand(commandMenu);
removeCommand(commandMenu.get());
}

void GameCanvas::addMenuCommand()
{
addCommand(commandMenu);
addCommand(commandMenu.get());
}

void GameCanvas::requestExit()
{
Micro::isGameLoopRunning = false;
}
11 changes: 6 additions & 5 deletions src/GameCanvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ class GameCanvas : public Canvas, public CommandListener {
void handleUpdatedInput();
void processTimers();

Graphics* graphics = nullptr;
Graphics* graphics = nullptr; // Non-owning reference (owned by Canvas base class)
int dx;
int dy;
int engineSpriteWidth;
int engineSpriteHeight;
int fenderSpriteWidth;
int fenderSpriteHeight;
GamePhysics* gamePhysics = nullptr;
MenuManager* menuManager = nullptr;
GamePhysics* gamePhysics = nullptr; // Non-owning reference (owned by Micro)
MenuManager* menuManager = nullptr; // Non-owning reference (owned by Micro)
// Additional offsets for camera view adjustment
int cameraOffsetX = 0;
int cameraOffsetY = 0;
Micro* micro = nullptr;
Micro* micro = nullptr; // Non-owning reference (root owner)
std::shared_ptr<Font> font;
bool timerTriggered = false;
// 0=gameplay, 1=logo screen, 2=splash screen
Expand All @@ -54,7 +54,7 @@ class GameCanvas : public Canvas, public CommandListener {
std::string timerMessage = "";
int timerId = 0;
std::vector<Timer> timers;
Command* commandMenu;
std::unique_ptr<Command> commandMenu; // Owned by GameCanvas
inline static std::string stringWithTime = "";
std::vector<std::string> time10MsToStringCache = std::vector<std::string>(100);
int timeInSeconds = -1;
Expand Down Expand Up @@ -120,6 +120,7 @@ class GameCanvas : public Canvas, public CommandListener {
void commandAction(Command* command, Displayable* displayable);
void removeMenuCommand();
void addMenuCommand();
void requestExit() override;

int width;
int height2;
Expand Down
1 change: 0 additions & 1 deletion src/GameLevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class GameLevel {
std::vector<std::vector<int>> pointPositions;

GameLevel();
~GameLevel();
void init();
void setStartFinishPositions(int startX, int startY, int finishX, int finishY);
int getStartPosX();
Expand Down
5 changes: 5 additions & 0 deletions src/GameMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,11 @@ void GameMenu::navigateToItem(int targetIndex)
{
resetToFirstItem();

// Bounds check: don't navigate beyond the last element
if (targetIndex >= static_cast<int>(vector.size())) {
targetIndex = vector.size() - 1;
}

while (selectedItemIndex < targetIndex) {
++selectedItemIndex;
if (selectedItemIndex > scrollOffsetLast) {
Expand Down
6 changes: 4 additions & 2 deletions src/GameMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ class Graphics;

class GameMenu {
private:
GameMenu* gameMenu;
GameMenu* gameMenu; // Non-owning reference (parent menu, owned by MenuManager)
std::string menuTitle;
int selectedItemIndex;
// Non-owning references to menu elements. Elements are owned by MenuManager.
std::vector<IGameMenuElement*> vector;
Micro* micro;
Micro* micro; // Non-owning reference (owned by root)
std::shared_ptr<Font> font;
std::shared_ptr<Font> font2;
std::shared_ptr<Font> font3;
Expand Down Expand Up @@ -49,6 +50,7 @@ class GameMenu {
void setMenuTitle(std::string title);
void resetToFirstItem();
void resetToLastItem();
// Adds element (non-owning reference). Element must be owned elsewhere (e.g., MenuManager).
void addMenuElement(IGameMenuElement* element);
void processGameActionDown();
void processGameActionUp();
Expand Down
4 changes: 2 additions & 2 deletions src/GamePhysics.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#include <vector>
#include <memory>
#include "PhysicsElemOrMenuItem.h"
#include "MotoComponent.h"

class LevelLoader;
class MotoComponent;
class GameCanvas;

/**
Expand Down Expand Up @@ -50,7 +50,7 @@ class GamePhysics {

// Engine momentum / throttle value (drives wheel torque)
int engineMomentumF16 = 0;
LevelLoader* levelLoader;
LevelLoader* levelLoader; // Non-owning reference (owned by Micro)
// Collision normal X - from LevelLoader
int collisionNormalXF16 = 0;
// Collision normal Y - from LevelLoader
Expand Down
20 changes: 9 additions & 11 deletions src/LevelLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@ LevelLoader::LevelLoader(const std::filesystem::path& mrgFilePath)
}

if (!mrgFilePath.string().empty()) {
FileStream* fileStream = new FileStream(mrgFilePath, std::ios::in | std::ios::binary);
if (!fileStream->isOpen()) {
levelFileStream = std::make_unique<FileStream>(mrgFilePath, std::ios::in | std::ios::binary);
if (!levelFileStream->isOpen()) {
throw std::system_error(errno, std::system_category(), "Failed to open " + mrgFilePath.string());
}
levelFileStream = fileStream;
} else {
EmbedFileStream* embedFileStream = new EmbedFileStream("levels.mrg");
levelFileStream = static_cast<FileStream*>(embedFileStream);
levelFileStream = std::make_unique<EmbedFileStream>("levels.mrg");
}

loadLevels();
Expand All @@ -37,7 +35,7 @@ LevelLoader::LevelLoader(const std::filesystem::path& mrgFilePath)

LevelLoader::~LevelLoader()
{
delete levelFileStream;
// unique_ptr members (levelFileStream and gameLevel) are automatically cleaned up
}

void LevelLoader::loadLevels()
Expand Down Expand Up @@ -101,11 +99,11 @@ void LevelLoader::seekAndLoadTrackData(int league, int track)
{
// Seek to track byte offset in MRG file (1-based indices)
levelFileStream->setPos(trackOffsetInFile[league - 1][track - 1]);
if (gameLevel == nullptr) {
gameLevel = new GameLevel();
if (!gameLevel) {
gameLevel = std::make_unique<GameLevel>();
}
gameLevel->load(levelFileStream);
precomputeTrackGeometry(gameLevel);
gameLevel->load(levelFileStream.get());
precomputeTrackGeometry(gameLevel.get());
}

void LevelLoader::cacheStartPosition()
Expand Down Expand Up @@ -144,7 +142,7 @@ int LevelLoader::getTrackProgressRatio(int xF16)
void LevelLoader::precomputeTrackGeometry(GameLevel* level)
{
trackMinX = INT_MIN;
this->gameLevel = level;
// Note: level is the same as gameLevel.get(), passed for convenience
int pointsCount = level->pointsCount;

// Resize trackSegmentNormals array if needed (min capacity: 100)
Expand Down
5 changes: 3 additions & 2 deletions src/LevelLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <string>
#include <fstream>
#include <stdexcept>
#include <memory>

#include "GamePhysics.h"
#include "GameCanvas.h"
Expand Down Expand Up @@ -33,13 +34,13 @@ class LevelLoader {
// Cached X position of visibleSegmentEndIdx
static int visibleSegmentEndX;

FileStream* levelFileStream;
std::unique_ptr<FileStream> levelFileStream;
void loadLevels();

public:
static bool isEnabledPerspective;
static bool isEnabledShadows;
GameLevel* gameLevel = nullptr;
std::unique_ptr<GameLevel> gameLevel;
int currentLevel = 0;
int currentTrack = -1;
std::vector<std::vector<std::string>> trackNames = std::vector<std::vector<std::string>>(3);
Expand Down
Loading