Skip to content

Commit

Permalink
refator: death and ui messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Cadecraft committed Apr 7, 2024
1 parent 94a3316 commit a7aa18e
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 26 deletions.
29 changes: 23 additions & 6 deletions src/gamestate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,24 @@ void GameState::spawnObject(WorldObject* object) {
}

UpdateResult GameState::update() {
// Update world objects
for (WorldObject* object : objects) {
UpdateResult updateResult = object->update(worldState, objects);
if (updateResult == UpdateResult::NextLevel) {
// TODO: improve this
return UpdateResult::NextLevel;
} else if (updateResult == UpdateResult::DieReset) {
// Died
return UpdateResult::DieReset;
}
}
// Update UI messages
for (std::vector<UIMessage>::iterator it = uiMessages.begin(); it != uiMessages.end();) {
if (it->update()) {
// Delete the message
it = uiMessages.erase(it);
} else {
it++;
}
}
return UpdateResult::None;
Expand All @@ -26,14 +39,18 @@ std::string GameState::getNextLevelName() {
void GameState::updateLevelNames(std::string newLevelName, std::string newNextLevelName) {
levelName = newLevelName;
nextLevelName = newNextLevelName;
// Add the message
// TODO: use level display names
addUIMessage("Teleported to " + newLevelName, { 255, 255, 255 });
}

std::vector<WorldObject*>::iterator GameState::objectsBegin() {
return objects.begin();
}

std::vector<WorldObject*>::iterator GameState::objectsEnd() {
return objects.end();
void GameState::addUIMessage(std::string message, Color color, int fontSize, long durationFrames) {
uiMessages.push_back({
message,
color,
fontSize,
durationFrames
});
}

void GameState::clear() {
Expand Down
12 changes: 8 additions & 4 deletions src/gamestate.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@
#include <vector>
#include "worldobject.h"
#include "worldstate.h"
#include "uimessage.h"

// Store the full state of the world and all objects
class GameState {
private:
WorldState worldState;
std::string levelName;
std::string nextLevelName;
std::vector<WorldObject*> objects;

public:
// All world objects (public)
std::vector<WorldObject*> objects;
// All UI messages (public)
std::vector<UIMessage> uiMessages;

// Spawn an object
void spawnObject(WorldObject* object);
// Update
Expand All @@ -23,9 +28,8 @@ class GameState {
std::string getNextLevelName();
// Update the current level name
void updateLevelNames(std::string newLevelName, std::string newNextLevelName);
// Get all objects
std::vector<WorldObject*>::iterator objectsBegin();
std::vector<WorldObject*>::iterator objectsEnd();
// Add a UI message
void addUIMessage(std::string message, Color color, int fontSize = 14, long durationFrames = 150);
// Clear all objects from the world, aside from Persisting objects
void clear();
// Destructor to free memory
Expand Down
9 changes: 7 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ int main() {
// Debug: spawn blue cubes
gameState.spawnObject(new BlueCube(player->getLocx(), player->getLocy()));
keysPressed.erase(sf::Keyboard::P);
gameState.addUIMessage("Player spawned a debug blue cube", { 0, 0, 255 });
}

// Update the game and world
// Update the game and world
if (LEVEL_DESIGN_MODE) {
// Level Design Mode: keep reloading the world without updating it
worldSpawner.spawnWorld(gameState, gameState.getLevelName());
Expand All @@ -96,14 +97,18 @@ int main() {
// Load the next level, if possible
// TODO: impl better
worldSpawner.spawnWorld(gameState, gameState.getNextLevelName());
} else if (updateResult == UpdateResult::DieReset) {
// Died: re-load the same level
worldSpawner.spawnWorld(gameState, gameState.getLevelName());
gameState.addUIMessage("Death #" + std::to_string(player->getDeathCounter()), { 255, 0, 0 });
}

// Render
window.clear(sf::Color(0, 0, 0));
// Game and world
renderer.setCamera(player->getLocx(), player->getLocy(), 0.8);
renderer.renderWorld(gameState);
// Update
// Update
window.display();
}
}
32 changes: 22 additions & 10 deletions src/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ void Renderer::renderFromData(RenderData data) {
}
}

void Renderer::renderMessage(UIMessage& uiMessage, int locx, int locy) {
sf::Text text;
text.setFont(assetHandler.getMainFont());
text.setString(uiMessage.message);
text.setCharacterSize(uiMessage.fontSize);
text.setFillColor(sf::Color(uiMessage.color.r, uiMessage.color.g, uiMessage.color.b));
text.setPosition(locx, locy);
window.draw(text);
}

void Renderer::setCamera(double newWorldCameraCenterX, double newWorldCameraCenterY, double percentEasing) {
worldCameraCenterX = worldCameraCenterX * percentEasing + newWorldCameraCenterX * (1 - percentEasing);
worldCameraCenterY = worldCameraCenterY * percentEasing + newWorldCameraCenterY * (1 - percentEasing);
Expand All @@ -77,16 +87,18 @@ void Renderer::renderWorld(GameState& gameState) {
// Clear/render sky
window.clear(sf::Color(111, 201, 252));
// Render world objects
for (std::vector<WorldObject*>::iterator it = gameState.objectsBegin(); it != gameState.objectsEnd(); it++) {
renderFromData((*it)->getRenderData());
for (WorldObject* object : gameState.objects) {
renderFromData(object->getRenderData());
}

// TODO: render on-screen debug messages (ex. "enemy_fipa spawned")
// TODO: refactor/abstract this
sf::Text levelName;
levelName.setFont(assetHandler.getMainFont());
levelName.setString(gameState.getLevelName()); // TODO: use display name instead
levelName.setCharacterSize(10);
levelName.setFillColor(sf::Color::White);
levelName.setPosition(24, 24);
window.draw(levelName);
// Render UI messages
int level = 0;
for (int i = gameState.uiMessages.size() - 1; i >= 0; i--) {
renderMessage(gameState.uiMessages[i], 24, 24 + level * 20);
level++;
}
// Render other UI
UIMessage levelName = { gameState.getLevelName(), { 255, 255, 255 }, 24 };
renderMessage(levelName, window.getSize().x - 140, 18);
}
3 changes: 3 additions & 0 deletions src/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class Renderer {
// Render from a RenderData object
void renderFromData(RenderData data);

// Render a message
void renderMessage(UIMessage& message, int locx, int locy);

// Set the camera
void setCamera(double newWorldCameraCenterX, double newWorldCameraCenterY, double percentEasing = 0.0);

Expand Down
17 changes: 17 additions & 0 deletions src/uimessage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <string>
#include "renderdata.h"

// A message with a designated text color
struct UIMessage {
std::string message;
Color color;
int fontSize = 14;
long durationFramesRemaining = 150;
// Update the UI message, returning whether it should be deleted
bool update() {
durationFramesRemaining--;
return durationFramesRemaining <= 0;
}
};
1 change: 1 addition & 0 deletions src/worldobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
enum class UpdateResult {
None,
Destroy,
DieReset,
NextLevel // TODO: better naming
};

Expand Down
23 changes: 19 additions & 4 deletions src/worldobjects/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Player : public WorldObject {
double velx = 0;
double vely = 0;
bool onGround = false;
int deathCounter = 0;

public:
// Constructor
Expand Down Expand Up @@ -39,6 +40,19 @@ class Player : public WorldObject {
return locy;
}

int getDeathCounter() {
return deathCounter;
}

void die() {
deathCounter++;
// Reset position and physics
teleport(5, 10);
velx = 0;
vely = 0;
onGround = false;
}

void teleport(double locx, double locy) {
this->locx = locx;
this->locy = locy;
Expand All @@ -54,6 +68,7 @@ class Player : public WorldObject {
locx += velx;
locy += vely;
// Check collision and update
UpdateResult updateResultToReturn = UpdateResult::None;
onGround = false;
// TODO: refactor
// TODO: only check with types enabling collision
Expand Down Expand Up @@ -115,8 +130,8 @@ class Player : public WorldObject {
// Collision stuff
if (collided && object->hasAttribute(ObjectAttribute::Deadly)) {
// Die
// todo: impl
teleport(5, 10);
die();
updateResultToReturn = UpdateResult::DieReset;
}
if (overlapped && object->hasAttribute(ObjectAttribute::LevelTeleport)) {
// Teleport to the next level
Expand All @@ -125,8 +140,8 @@ class Player : public WorldObject {
return UpdateResult::NextLevel;
}
}
// TODO: out of bounds respawn/death
return UpdateResult::None;
// TODO: out of bounds respawn/death (and restart level/message on die)
return updateResultToReturn;
}

// Override rendering
Expand Down

0 comments on commit a7aa18e

Please sign in to comment.