Support multiple and custom levels

This commit is contained in:
Martin Prokoph
2025-01-15 17:42:28 +01:00
parent 2959d06db4
commit f5297dfb66
10 changed files with 127 additions and 14 deletions

View File

@@ -1,16 +1,21 @@
#pragma once
#include "identifier.hpp"
#include "color.hpp"
#include "blockSettings.hpp"
class Block {
private:
Identifier id = Identifier("adventure", "missing");
char encoding;
Color color;
BlockSettings settings;
public:
Block(Identifier id, char encoding, BlockSettings settings) {
Block(Identifier id, char encoding, BlockSettings settings) : Block(id, encoding, Color::RESET, settings) {};
Block(Identifier id, char encoding, Color color, BlockSettings settings) {
this->id = id;
this->encoding = encoding;
this->color = color;
this->settings = settings;
};
@@ -21,6 +26,9 @@ public:
Identifier getId() {
return id;
}
Color getColor() {
return color;
}
char getEncoding() {
return encoding;
}

View File

@@ -9,17 +9,23 @@ using std::string;
class BlockRegistry {
public:
Block AIR = Block(Identifier("adventura", "air"), ' ', BlockSettingsBuilder().nonSolid().build());
Block WATER = Block(Identifier("adventura", "water"), '~', Color::BRIGHT_BLUE, BlockSettingsBuilder().nonSolid().build());
Block PLATFORM = Block(Identifier("adventura", "platform"), '-', BlockSettingsBuilder().build());
Block LADDER = Block(Identifier("adventura", "ladder"), 'H', BlockSettingsBuilder().climbableFromBottom().climbableFromTop().build());
Block START = Block(Identifier("adventura", "start"), 'S', BlockSettingsBuilder().build());
Block GOAL = Block(Identifier("adventura", "goal"), 'O', BlockSettingsBuilder().build());
Block LADDER = Block(Identifier("adventura", "ladder"), 'H', Color::BRIGHT_MAGENTA, BlockSettingsBuilder().climbableFromBottom().climbableFromTop().build());
Block START = Block(Identifier("adventura", "start"), 'S', BlockSettingsBuilder().nonSolid().build());
Block GOAL = Block(Identifier("adventura", "goal"), 'O', Color::BRIGHT_GREEN, BlockSettingsBuilder().nonSolid().build());
Block WALL = Block(Identifier("adventura", "wall"), '0', Color::BRIGHT_BLACK, BlockSettingsBuilder().collidable().build());
Block SPIKE = Block(Identifier("adventura", "spike"), '^', Color::BRIGHT_RED, BlockSettingsBuilder().lethal().build());
BlockRegistry() {
registerBlock(AIR);
registerBlock(WATER);
registerBlock(PLATFORM);
registerBlock(LADDER);
registerBlock(START);
registerBlock(GOAL);
registerBlock(GOAL);
registerBlock(WALL);
registerBlock(SPIKE);
}
const Block getByEncoding(char encoding) {

View File

@@ -4,9 +4,15 @@ class BlockSettings {
bool isSolid() {
return isSolid_;
}
bool hasCollision() {
return hasCollision_;
}
bool isMovable() {
return isMovable_;
}
bool isLethal() {
return isLethal_;
}
bool isClimbableFromTop() {
return isClimbableFromTop_;
}
@@ -20,6 +26,12 @@ class BlockSettings {
void setMovable(bool isMovable) {
this->isMovable_ = isMovable;
}
void setCollision(bool hasCollision) {
this->hasCollision_ = hasCollision;
}
void setLethal(bool isLethal) {
this->isLethal_ = isLethal;
}
void setClimbableFromTop(bool isClimbableFromTop) {
this->isClimbableFromTop_ = isClimbableFromTop;
}
@@ -32,6 +44,8 @@ class BlockSettings {
bool isMovable_ = false;
bool isClimbableFromTop_ = false;
bool isClimbableFromBottom_ = false;
bool isLethal_ = false;
bool hasCollision_ = false;
};
class BlockSettingsBuilder {
public:
@@ -43,6 +57,14 @@ class BlockSettingsBuilder {
blockSettings.setMovable(true);
return *this;
}
BlockSettingsBuilder collidable() {
blockSettings.setCollision(true);
return *this;
}
BlockSettingsBuilder lethal() {
blockSettings.setLethal(true);
return *this;
}
BlockSettingsBuilder climbableFromTop() {
blockSettings.setClimbableFromTop(true);
return *this;

16
src/color.hpp Normal file
View File

@@ -0,0 +1,16 @@
#include <iostream>
enum class Color {
RESET = 0,
BRIGHT_BLACK= 90,
BRIGHT_RED= 91,
BRIGHT_GREEN= 92,
BRIGHT_YELLOW= 93,
BRIGHT_BLUE= 94,
BRIGHT_MAGENTA= 95,
BRIGHT_CYAN= 96,
BRIGHT_WHITE= 97
};
std::ostream& operator<<(std::ostream& os, Color color) {
return os << "\033[" << static_cast<int>(color) << "m";
}

View File

@@ -1,5 +1,6 @@
#include <string>
#include <iostream>
#include <filesystem>
#include "world.hpp"
#include "player.hpp"
#include "blockRegistry.hpp"
@@ -8,26 +9,33 @@
using std::string;
using std::cout;
using std::endl;
namespace fs = std::filesystem;
void render(World &world, Player &player);
void redraw(World &world, Player &player);
void jumpBackOneLine();
bool startWorld(string worldFile);
int main() {
for (const auto & entry : fs::directory_iterator("./worlds"))
if (!startWorld(entry.path())) return 0;
return 0;
}
bool startWorld(string worldFile) {
BlockRegistry blockRegistry = BlockRegistry();
World world = World(blockRegistry);
string worldFile = "worlds/world.txt";
world.loadFromFile(worldFile);
Player player = Player(world.getStartPos(), world);
render(world, player);
while (player.isAlive()) {
while (player.isAlive() && !player.hasReachedGoal()) {
char lastChar;
cin >> lastChar;
if (onInput(lastChar, world, player)) redraw(world, player);
else jumpBackOneLine();
}
return 0;
return player.hasReachedGoal();
}
void jumpBackOneLine() {
std::cout << "\033[1A";
@@ -48,10 +56,10 @@ void render(World &world, Player &player) {
for (unsigned int y = 0; y <= world.getMaxY(); y++) {
for (unsigned int x = 0; x <= world.getMaxX(); x++) {
if (playerTexture.size() > y && playerTexture.at(y).size() > x && playerTexture.at(y).at(x) != ' ') {
cout << playerTexture.at(y).at(x);
cout << Color::BRIGHT_YELLOW << playerTexture.at(y).at(x);
}
else if (canvas.size() > y && canvas.at(y).size() > x) {
cout << canvas.at(y).at(x).getEncoding();
cout << canvas.at(y).at(x).getColor() << canvas.at(y).at(x).getEncoding();
}
else cout << ' ';
}

View File

@@ -2,19 +2,20 @@
#include "world.hpp"
#include "blockRegistry.hpp"
bool tryWalk(World& world, Player& player, bool left);
bool tryGoDown(World& world, Player& player);
bool tryGoUp(World& world, Player& player);
bool onInput(char lastChar, World& world, Player& player) {
switch (lastChar) {
case ' ':
case 'w':
case 'W':
return tryGoUp(world, player);
case 'a':
case 'A':
player.move(-1, 0);
return true;
return tryWalk(world, player, true);
case 's':
case 'S':
@@ -22,12 +23,18 @@ bool onInput(char lastChar, World& world, Player& player) {
case 'd':
case 'D':
player.move(1, 0);
return true;
return tryWalk(world, player, false);
default: return false;
}
}
bool tryWalk(World& world, Player& player, bool left) {
if (!world.getBlockAt(player.getPos()+(left ? BlockPos(-1, 1) : BlockPos(1, 1))).getSettings().hasCollision()) {
player.move(left ? BlockPos(-1, 0) : BlockPos(1,0));
return true;
}
return false;
}
bool tryGoDown(World& world, Player& player) {
if (world.getBlockAt(player.getPos()+BlockPos(0, 2)).getSettings().isClimbableFromTop() || world.getBlockAt(player.getPos()+BlockPos(0, 3)).getSettings().isClimbableFromTop()) {
player.move(0, 1);
@@ -40,5 +47,13 @@ bool tryGoUp(World& world, Player& player) {
player.move(0, -1);
return true;
}
else if (world.getBlockAt(player.getPos()+BlockPos(1, 1)).getSettings().hasCollision() && !world.getBlockAt(player.getPos()+BlockPos(1, 0)).getSettings().isSolid()) {
player.move(1, -1);
return true;
}
else if (world.getBlockAt(player.getPos()+BlockPos(-1, 1)).getSettings().hasCollision() && !world.getBlockAt(player.getPos()+BlockPos(-1, 0)).getSettings().isSolid()) {
player.move(-1, -1);
return true;
}
return false;
}

View File

@@ -30,6 +30,8 @@ public:
}
this->pos = pos;
if (world.getBlockAt(pos) == world.getBlockRegistry().GOAL) reachedGoal = true;
isFreeFalling = !world.getBlockAt(pos+BlockPos(0, 2)).getSettings().isSolid();
if (isFreeFalling) {
move(BlockPos(0, 1));
@@ -37,10 +39,15 @@ public:
if (fallLength > 5) alive = false;
}
else fallLength = 0;
if (world.getBlockAt(pos+BlockPos(0, 2)).getSettings().isLethal()) alive = false;
}
bool isAlive() {
return alive;
}
bool hasReachedGoal() {
return reachedGoal;
}
vector<vector<char>> mapToWorldspace() {
vector<vector<char>> map;
for (unsigned int y = 0; y <= world.getMaxY(); y++) {
@@ -69,5 +76,6 @@ private:
BlockPos pos = BlockPos(0, 0);
bool alive = true;
bool isFreeFalling = false;
bool reachedGoal = false;
int fallLength = 0;
};

15
worlds/2.txt Normal file
View File

@@ -0,0 +1,15 @@
o
S /|\
/ \
------------- -----------
H H
H H
H H
H --------- -------
-------- H 0 0
H H 0 0
H H 0 0 O
H H 0^^^^^0
----------------------------------------

15
worlds/3.txt Normal file
View File

@@ -0,0 +1,15 @@
----------------------
00
00
00
---------
0 o 00----- O
0 S /|\ 00 0
0 / \ 00 0 ---------------
---------------- 0 H 0
0 H 0
0 H 0
0 H 0
0~~~~~~0---------
--------