Добавлены локации и перемещение по ним

This commit is contained in:
DeLiss
2026-06-11 11:37:19 +05:00
parent 1e7bac87d3
commit cba2274630
15 changed files with 506 additions and 57 deletions

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
@@ -123,6 +123,7 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\location.cpp" />
<ClCompile Include="src\game.cpp" /> <ClCompile Include="src\game.cpp" />
<ClCompile Include="src\main.cpp" /> <ClCompile Include="src\main.cpp" />
<ClCompile Include="src\player.cpp" /> <ClCompile Include="src\player.cpp" />
@@ -130,6 +131,7 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="include\game.h" /> <ClInclude Include="include\game.h" />
<ClInclude Include="include\player.h" /> <ClInclude Include="include\player.h" />
<ClInclude Include="include\location.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@@ -24,13 +24,19 @@
<ClCompile Include="src\player.cpp"> <ClCompile Include="src\player.cpp">
<Filter>Исходные файлы</Filter> <Filter>Исходные файлы</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\location.cpp">
<Filter>Исходные файлы</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="include\location.h">
<Filter>Файлы заголовков</Filter>
</ClInclude>
<ClInclude Include="include\game.h"> <ClInclude Include="include\game.h">
<Filter>Исходные файлы</Filter> <Filter>Файлы заголовков</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="include\player.h"> <ClInclude Include="include\player.h">
<Filter>Исходные файлы</Filter> <Filter>Файлы заголовков</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -0,0 +1,21 @@
ID=1
TITLE=Entrance Hall
WIDTH=10
HEIGHT=6
START_X=1
START_Y=1
NORTH=0
SOUTH=2
WEST=0
EAST=0
RIDDLE_TYPE=1
RIDDLE_TEXT=What gets bigger when you take something away?
RIDDLE_ANSWER=hole
MAP_BEGIN
##########
#@.......#
#....C...#
#........#
#......D.#
##########
MAP_END

View File

@@ -0,0 +1,21 @@
ID=2
TITLE=Old Corridor
WIDTH=10
HEIGHT=6
START_X=1
START_Y=1
NORTH=1
SOUTH=3
WEST=0
EAST=0
RIDDLE_TYPE=2
RIDDLE_TEXT=Decode this word: MBHJD. Each letter is shifted by one.
RIDDLE_ANSWER=magic
MAP_BEGIN
##########
#@.......#
#..E.....#
#........#
#......D.#
##########
MAP_END

View File

@@ -0,0 +1,21 @@
ID=3
TITLE=Guard Room
WIDTH=10
HEIGHT=6
START_X=1
START_Y=1
NORTH=2
SOUTH=4
WEST=0
EAST=0
RIDDLE_TYPE=3
RIDDLE_TEXT=Continue the sequence: 2 4 8 16
RIDDLE_ANSWER=32
MAP_BEGIN
##########
#@.......#
#....N...#
#........#
#......D.#
##########
MAP_END

View File

@@ -0,0 +1,21 @@
ID=4
TITLE=Library
WIDTH=10
HEIGHT=6
START_X=1
START_Y=1
NORTH=3
SOUTH=5
WEST=0
EAST=0
RIDDLE_TYPE=4
RIDDLE_TEXT=Where is knowledge usually stored?
RIDDLE_ANSWER=book
MAP_BEGIN
##########
#@.......#
#....C...#
#..E.....#
#......D.#
##########
MAP_END

View File

@@ -0,0 +1,21 @@
ID=5
TITLE=Final Gate
WIDTH=10
HEIGHT=6
START_X=1
START_Y=1
NORTH=4
SOUTH=0
WEST=0
EAST=0
RIDDLE_TYPE=5
RIDDLE_TEXT=What key opens no door?
RIDDLE_ANSWER=keyboard
MAP_BEGIN
##########
#@.......#
#....E...#
#....C...#
#......D.#
##########
MAP_END

View File

@@ -1,5 +1,7 @@
#include "player.h"
#pragma once #pragma once
#include "player.h"
#include "location.h"
#include <vector>
class Game { class Game {
public: public:
@@ -7,11 +9,20 @@ public:
private: private:
bool isRunning = true; bool isRunning = true;
Player player; Player player;
std::vector<Location> locations;
void showMainMenu(); void showMainMenu();
void processCommand();
void render();
};
#pragma once void loadLocations();
Location* getCurrentLocation();
void render();
void processCommand();
void movePlayer(int dx, int dy);
void handleTile(char tile);
bool solveRiddle(Location& location);
};

61
include/location.h Normal file
View File

@@ -0,0 +1,61 @@
#pragma once
#include <string>
#include <vector>
struct Point {
int x = 0;
int y = 0;
};
struct Chest {
Point pos;
int gold = 0;
bool opened = false;
};
struct Enemy {
Point pos;
std::string type;
int hp = 50;
};
struct NPC {
Point pos;
std::string name;
};
struct Riddle {
int type = 0;
std::string text;
std::string answer;
bool isSolved = false;
};
class Location {
public:
int id = 0;
std::string title;
int width = 0;
int height = 0;
int north = 0;
int south = 0;
int west = 0;
int east = 0;
Point startPosition;
Riddle riddle;
std::vector<std::string> map;
std::vector<Chest> chests;
std::vector<Enemy> enemies;
std::vector<NPC> npcs;
bool loadFromFile(const std::string& path);
void draw(const Point& playerPosition) const;
bool isWalkable(int x, int y) const;
char getTile(int x, int y) const;
};

View File

@@ -1,20 +1,24 @@
#pragma once #pragma once
#include <string> #include <string>
#include <vector> #include <vector>
#include "location.h"
class Player { class Player {
public: public:
std::string name = "Character Name"; std::string name = "Character Name";
int hp = 100; int hp = 100;
int atk = 1; int atk = 10;
int gold = 0; int gold = 0;
int currentLocation = 1; int currentLocation = 1;
Point position;
int weaponId = 101; int weaponId = 101;
std::vector<int> items; std::vector<int> items;
Player() {}; Player() = default;
Player(std::string _name); Player(std::string name);
void showStats();
};
#pragma once void showStats() const;
};

View File

View File

@@ -1,17 +0,0 @@
#pragma once
#include <string>
class Location {
public:
std::string title;
int id;
int sizeX;
int sizeY;
int gold = 0;
Location() {};
Location(std::string _name);
void showStats();
};
#pragma once

View File

@@ -1,16 +1,40 @@
#include "../include/game.h" #include "../include/game.h"
#include "../include/player.h"
#include <iostream> #include <iostream>
#include <string> #include <string>
void Game::run() { void Game::run() {
loadLocations();
showMainMenu(); showMainMenu();
while (isRunning) { while (isRunning) {
render(); render();
processCommand(); processCommand();
} }
} }
void Game::loadLocations() {
locations.clear();
for (int i = 1; i <= 5; i++) {
Location location;
std::string path = "data/locations/location_" + std::to_string(i) + ".txt";
if (location.loadFromFile(path)) {
locations.push_back(location);
}
}
}
Location* Game::getCurrentLocation() {
for (auto& location : locations) {
if (location.id == player.currentLocation) {
return &location;
}
}
return nullptr;
}
void Game::showMainMenu() { void Game::showMainMenu() {
while (true) { while (true) {
std::cout << "=== ASCII-G - The Cookies Edition ===\n"; std::cout << "=== ASCII-G - The Cookies Edition ===\n";
@@ -22,47 +46,61 @@ void Game::showMainMenu() {
std::string str; std::string str;
std::getline(std::cin, str); std::getline(std::cin, str);
if (str.length() != 1) { if (str == "1") {
std::cout << "It seems you've tried to input more than 1 digit... Don't do this please.\n";
continue;
}
char select = str[0];
if (select == '1') {
std::string name; std::string name;
std::cout << ">>> Enter your character name: "; std::cout << ">>> Enter your character name: ";
std::getline(std::cin, name); std::getline(std::cin, name);
if (name == "") {
std::cout << ">>> Empty name? Damn... let's call you Zero!\n"; if (name.empty()) {
player = Player("Zero"); player = Player("Zero");
} }
else { else {
player = Player(name); player = Player(name);
} }
std::cout << ">>> Created new character " << player.name << "!";
Location* location = getCurrentLocation();
if (location != nullptr) {
player.position = location->startPosition;
}
std::cout << ">>> Created new character " << player.name << "!\n";
break; break;
} }
else if (select == '2') { else if (str == "2") {
std::cout << ">>> I can't do this... yet."; std::cout << ">>> Load system is not ready yet.\n";
} }
else if (select == '3') { else if (str == "3") {
isRunning = false; isRunning = false;
break; break;
} }
else { else {
std::cout << ">>> I can't do this... yet? Let's try again!"; std::cout << ">>> Unknown menu option.\n";
} }
} }
} }
void Game::render() { void Game::render() {
std::cout << "\n\n=== ASCII-G - The Cookies Edition ===\n"; Location* location = getCurrentLocation();
std::cout << "Commands: stats, exit\n";
if (location == nullptr) {
std::cout << "Current location not found.\n";
isRunning = false;
return;
}
location->draw(player.position);
std::cout << "\nCommands:\n";
std::cout << "WASD - move\n";
std::cout << "stats - show stats\n";
std::cout << "exit - exit game\n";
} }
void Game::processCommand() { void Game::processCommand() {
std::string command; std::string command;
std::cout << "> "; std::cout << "> ";
std::cin >> command; std::cin >> command;
@@ -72,7 +110,117 @@ void Game::processCommand() {
else if (command == "stats") { else if (command == "stats") {
player.showStats(); player.showStats();
} }
else if (command == "w" || command == "W") {
movePlayer(0, -1);
}
else if (command == "s" || command == "S") {
movePlayer(0, 1);
}
else if (command == "a" || command == "A") {
movePlayer(-1, 0);
}
else if (command == "d" || command == "D") {
movePlayer(1, 0);
}
else { else {
std::cout << "Unknown command.\n"; std::cout << "Unknown command.\n";
} }
} }
void Game::movePlayer(int dx, int dy) {
Location* location = getCurrentLocation();
if (location == nullptr) {
return;
}
int newX = player.position.x + dx;
int newY = player.position.y + dy;
if (!location->isWalkable(newX, newY)) {
std::cout << "You hit the wall.\n";
return;
}
char tile = location->getTile(newX, newY);
player.position.x = newX;
player.position.y = newY;
handleTile(tile);
}
void Game::handleTile(char tile) {
Location* location = getCurrentLocation();
if (location == nullptr) {
return;
}
if (tile == 'C') {
std::cout << "You found a chest. For now it gives you 25 gold.\n";
player.gold += 25;
}
else if (tile == 'E') {
std::cout << "Enemy encountered. Combat will be added later.\n";
}
else if (tile == 'N') {
std::cout << "NPC: Hello, traveler.\n";
}
else if (tile == 'D') {
if (!location->riddle.isSolved) {
bool solved = solveRiddle(*location);
if (!solved) {
player.hp -= 10;
std::cout << "Wrong answer. You lost 10 HP.\n";
return;
}
}
if (location->south != 0) {
player.currentLocation = location->south;
}
else if (location->east != 0) {
player.currentLocation = location->east;
}
else if (location->north != 0) {
player.currentLocation = location->north;
}
else if (location->west != 0) {
player.currentLocation = location->west;
}
else {
std::cout << "There is no exit from this door.\n";
return;
}
Location* newLocation = getCurrentLocation();
if (newLocation != nullptr) {
player.position = newLocation->startPosition;
std::cout << "You entered: " << newLocation->title << "\n";
}
}
}
bool Game::solveRiddle(Location& location) {
if (location.riddle.text.empty()) {
return true;
}
std::cout << "\nRiddle:\n";
std::cout << location.riddle.text << "\n";
std::cout << "Answer: ";
std::string answer;
std::cin >> answer;
if (answer == location.riddle.answer) {
std::cout << "Correct.\n";
location.riddle.isSolved = true;
return true;
}
return false;
}

127
src/location.cpp Normal file
View File

@@ -0,0 +1,127 @@
#include "../include/location.h"
#include <fstream>
#include <iostream>
#include <sstream>
bool Location::loadFromFile(const std::string& path) {
std::ifstream file(path);
if (!file.is_open()) {
std::cout << "Cannot open location file: " << path << "\n";
return false;
}
std::string line;
bool readingMap = false;
while (std::getline(file, line)) {
if (line.empty()) {
continue;
}
if (line == "MAP_BEGIN") {
readingMap = true;
continue;
}
if (line == "MAP_END") {
readingMap = false;
continue;
}
if (readingMap) {
map.push_back(line);
continue;
}
size_t pos = line.find('=');
if (pos == std::string::npos) {
continue;
}
std::string key = line.substr(0, pos);
std::string value = line.substr(pos + 1);
if (key == "ID") id = std::stoi(value);
else if (key == "TITLE") title = value;
else if (key == "WIDTH") width = std::stoi(value);
else if (key == "HEIGHT") height = std::stoi(value);
else if (key == "START_X") startPosition.x = std::stoi(value);
else if (key == "START_Y") startPosition.y = std::stoi(value);
else if (key == "NORTH") north = std::stoi(value);
else if (key == "SOUTH") south = std::stoi(value);
else if (key == "WEST") west = std::stoi(value);
else if (key == "EAST") east = std::stoi(value);
else if (key == "RIDDLE_TYPE") riddle.type = std::stoi(value);
else if (key == "RIDDLE_TEXT") riddle.text = value;
else if (key == "RIDDLE_ANSWER") riddle.answer = value;
}
for (int y = 0; y < map.size(); y++) {
for (int x = 0; x < map[y].size(); x++) {
char tile = map[y][x];
if (tile == 'C') {
Chest chest;
chest.pos = { x, y };
chest.gold = 25;
chests.push_back(chest);
}
else if (tile == 'E') {
Enemy enemy;
enemy.pos = { x, y };
enemy.type = "Goblin";
enemy.hp = 50;
enemies.push_back(enemy);
}
else if (tile == 'N') {
NPC npc;
npc.pos = { x, y };
npc.name = "Stranger";
npcs.push_back(npc);
}
}
}
return true;
}
void Location::draw(const Point& playerPosition) const {
std::cout << "\n=== " << title << " ===\n";
for (int y = 0; y < map.size(); y++) {
for (int x = 0; x < map[y].size(); x++) {
if (playerPosition.x == x && playerPosition.y == y) {
std::cout << '@';
}
else {
char tile = map[y][x];
if (tile == '@') {
std::cout << '.';
}
else {
std::cout << tile;
}
}
}
std::cout << "\n";
}
}
bool Location::isWalkable(int x, int y) const {
if (y < 0 || y >= map.size()) return false;
if (x < 0 || x >= map[y].size()) return false;
char tile = map[y][x];
return tile != '#';
}
char Location::getTile(int x, int y) const {
if (y < 0 || y >= map.size()) return '#';
if (x < 0 || x >= map[y].size()) return '#';
return map[y][x];
}

View File

@@ -1,17 +1,19 @@
#include "../include/player.h" #include "../include/player.h"
#include <iostream> #include <iostream>
Player::Player(std::string _name) Player::Player(std::string name) {
{ this->name = name;
this->name = _name;
hp = 100; hp = 100;
atk = 10; atk = 10;
gold = 0; gold = 0;
currentLocation = 1;
} }
void Player::showStats() { void Player::showStats() const {
std::cout << "\n === " << this->name << "'s STATS ==="; std::cout << "\n=== " << name << "'s STATS ===";
std::cout << "\nHP : " << this->hp; std::cout << "\nHP: " << hp;
std::cout << "\nATK : " << this->atk; std::cout << "\nATK: " << atk;
std::cout << "\nGOLD : " << this->gold; std::cout << "\nGOLD: " << gold;
std::cout << "\nLOCATION: " << currentLocation;
std::cout << "\nPOSITION: " << position.x << ", " << position.y << "\n";
} }