commit 4d661e4a3ea534ed0244d124baa673ea7aa179cf Author: Andrew Pamment Date: Sun Apr 20 10:05:21 2025 +1000 Initial Commit diff --git a/ADG5.cpp b/ADG5.cpp new file mode 100644 index 0000000..555cb47 --- /dev/null +++ b/ADG5.cpp @@ -0,0 +1,38 @@ +// ADG5.cpp : Defines the entry point for the application. +// +#include +#include +#include "libtcod.hpp" +#include "Engine.h" +#include "ADG5.h" + +using namespace std; + +Engine *engine; + +int main(int argc, char **argv) +{ + auto console = tcod::Console(80, 50); + auto params = TCOD_ContextParams{}; + + int playerx = 40, playery = 25; + + params.console = console.get(); + params.window_title = "Andrew's Dungeon Game 5"; + params.sdl_window_flags = SDL_WINDOW_RESIZABLE; + params.vsync = true; + params.argc = argc; + params.argv = argv; + + auto context = tcod::Context(params); + engine = new Engine(&context, &console); + engine->init(); + + while (engine->update()) { + engine->render(); + } + + delete engine; + + return 0; +} diff --git a/ADG5.h b/ADG5.h new file mode 100644 index 0000000..a20e344 --- /dev/null +++ b/ADG5.h @@ -0,0 +1,8 @@ +// ADG5.h : Include file for standard system include files, +// or project specific include files. + +#pragma once + +#include + +// TODO: Reference additional headers your program requires here. diff --git a/Actor.cpp b/Actor.cpp new file mode 100644 index 0000000..4e503b1 --- /dev/null +++ b/Actor.cpp @@ -0,0 +1,10 @@ +#include "libtcod.hpp" +#include "Actor.h" + +Actor::Actor(int x, int y, std::string_view ch, const TCOD_ColorRGB& col) : + x(x), y(y), ch(ch), col(col) { +} + +void Actor::render(TCOD_Console& cons) const { + tcod::print(cons, { x, y }, ch, col, std::nullopt); +} \ No newline at end of file diff --git a/Actor.h b/Actor.h new file mode 100644 index 0000000..dbb61c1 --- /dev/null +++ b/Actor.h @@ -0,0 +1,13 @@ +#pragma once + +#include "libtcod.hpp" + +class Actor { +public: + int x, y; // position on map + std::string_view ch; // ascii code + TCOD_ColorRGB col; // color + + Actor(int x, int y, std::string_view ch, const TCOD_ColorRGB& col); + void render(TCOD_Console& cons) const; +}; \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d81d478 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,28 @@ +# CMakeList.txt : CMake project for ADG5, include source and define +# project specific logic here. +# +cmake_minimum_required (VERSION 3.8) + +# Enable Hot Reload for MSVC compilers if supported. +if (POLICY CMP0141) + cmake_policy(SET CMP0141 NEW) + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") +endif() + +project ("ADG5") + +find_package(libtcod CONFIG REQUIRED) + +# Add source to this project's executable. +add_executable (ADG5 "ADG5.cpp" "ADG5.h" "Actor.cpp" "Actor.h" "Map.h" "Map.cpp" "Engine.h" "Engine.cpp" ) + +target_link_libraries(ADG5 + PRIVATE + libtcod::libtcod +) + +if (CMAKE_VERSION VERSION_GREATER 3.12) + set_property(TARGET ADG5 PROPERTY CXX_STANDARD 20) +endif() + +# TODO: Add tests and install targets if needed. diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..955bb0b --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,69 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "windows-base", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "installDir": "${sourceDir}/out/install/${presetName}", + "cacheVariables": { + "CMAKE_C_COMPILER": "cl.exe", + "CMAKE_CXX_COMPILER": "cl.exe" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + } + }, + { + "name": "vcpkg", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + } + }, + { + "name": "x64-debug", + "displayName": "x64 Debug", + "inherits": "windows-base", + "architecture": { + "value": "x64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "x64-release", + "displayName": "x64 Release", + "inherits": "x64-debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "x86-debug", + "displayName": "x86 Debug", + "inherits": "windows-base", + "architecture": { + "value": "x86", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "x86-release", + "displayName": "x86 Release", + "inherits": "x86-debug", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + } + ] +} diff --git a/CMakeUserPresets.json b/CMakeUserPresets.json new file mode 100644 index 0000000..36896a1 --- /dev/null +++ b/CMakeUserPresets.json @@ -0,0 +1,12 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default", + "inherits": "vcpkg", + "environment": { + "VCPKG_ROOT": "C:/Users/apamm/Projects/vcpkg" + } + } + ] +} \ No newline at end of file diff --git a/Engine.cpp b/Engine.cpp new file mode 100644 index 0000000..a3cb582 --- /dev/null +++ b/Engine.cpp @@ -0,0 +1,74 @@ +#include +#include "libtcod.hpp" +#include "Actor.h" +#include "Map.h" +#include "Engine.h" + + + +Engine::Engine(tcod::Context *context, tcod::Console *console) { + this->context = context; + this->console = console; + map = nullptr; + player = nullptr; +} + +void Engine::init() { + player = new Actor(40, 25, "@", TCOD_ColorRGB(255, 255, 255)); + actors.push(player); + map = new Map(80, 45); +} + +Engine::~Engine() { + actors.clearAndDelete(); + delete map; +} + +bool Engine::update() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + context->convert_event_coordinates(event); + switch (event.type) { + case SDL_EVENT_KEY_DOWN: + switch (event.key.key) { + case SDLK_UP: + if (!map->isWall(player->x, player->y - 1)) + player->y--; + break; + case SDLK_DOWN: + if (!map->isWall(player->x, player->y + 1)) + player->y++; + break; + case SDLK_LEFT: + if (!map->isWall(player->x - 1, player->y)) + player->x--; + break; + case SDLK_RIGHT: + if (!map->isWall(player->x + 1, player->y)) + player->x++; + break; + default: + break; + } + break; + case SDL_EVENT_QUIT: + return false; + default: + break; + } + } + return true; +} + +void Engine::render() { + console->clear(); + // draw the map + map->render(*console); + + // draw the actors + for (Actor** iterator = actors.begin(); + iterator != actors.end(); iterator++) { + (*iterator)->render(*console); + } + context->present(*console); +} diff --git a/Engine.h b/Engine.h new file mode 100644 index 0000000..f7fe96a --- /dev/null +++ b/Engine.h @@ -0,0 +1,21 @@ +#pragma once +class Actor; +class Map; + +#include "libtcod.hpp" + +class Engine { +public: + TCODList actors; + Actor* player; + Map* map; + tcod::Context *context; + tcod::Console* console; + Engine(tcod::Context *context, tcod::Console *console); + void init(); + ~Engine(); + bool update(); + void render(); +}; + +extern Engine *engine; \ No newline at end of file diff --git a/Map.cpp b/Map.cpp new file mode 100644 index 0000000..7d350b3 --- /dev/null +++ b/Map.cpp @@ -0,0 +1,102 @@ +#include "libtcod.hpp" +#include "Map.h" +#include "Actor.h" +#include "Engine.h" + +static const int ROOM_MAX_SIZE = 12; +static const int ROOM_MIN_SIZE = 6; + +class BspListener : public ITCODBspCallback { +private: + Map& map; // a map to dig + int roomNum; // room number + int lastx = 0, lasty = 0; // center of the last room + +public: + BspListener(Map& map) : map(map), roomNum(0) {} + bool visitNode(TCODBsp* node, void* userData) { + if (node->isLeaf()) { + int x, y, w, h; + // dig a room + TCODRandom* rng = TCODRandom::getInstance(); + w = rng->getInt(ROOM_MIN_SIZE, node->w - 2); + h = rng->getInt(ROOM_MIN_SIZE, node->h - 2); + x = rng->getInt(node->x + 1, node->x + node->w - w - 1); + y = rng->getInt(node->y + 1, node->y + node->h - h - 1); + map.createRoom(roomNum == 0, x, y, x + w - 1, y + h - 1); + if (roomNum != 0) { + // dig a corridor from last room + map.dig(lastx, lasty, x + w / 2, lasty); + map.dig(x + w / 2, lasty, x + w / 2, y + h / 2); + } + lastx = x + w / 2; + lasty = y + h / 2; + roomNum++; + } + return true; + } +}; + +Map::Map(int width, int height) : width(width), height(height) { + tiles = new Tile[width * height]; + TCODBsp bsp(0, 0, width, height); + bsp.splitRecursive(NULL, 8, ROOM_MAX_SIZE, ROOM_MAX_SIZE, 1.5f, 1.5f); + BspListener listener(*this); + bsp.traverseInvertedLevelOrder(&listener, NULL); +} + +Map::~Map() { + delete[] tiles; +} + +bool Map::isWall(int x, int y) const { + return !tiles[x + y * width].canWalk; +} + +void Map::setWall(int x, int y) { + tiles[x + y * width].canWalk = false; +} + +void Map::render(TCOD_Console& cons) const { + static const TCOD_ColorRGB darkWall(0, 0, 100); + static const TCOD_ColorRGB darkGround(50, 50, 150); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + tcod::print(cons, { x, y }, " ", std::nullopt, isWall(x, y) ? darkWall : darkGround); + } + } +} + +void Map::dig(int x1, int y1, int x2, int y2) { + if (x2 < x1) { + int tmp = x2; + x2 = x1; + x1 = tmp; + } + if (y2 < y1) { + int tmp = y2; + y2 = y1; + y1 = tmp; + } + for (int tilex = x1; tilex <= x2; tilex++) { + for (int tiley = y1; tiley <= y2; tiley++) { + tiles[tilex + tiley * width].canWalk = true; + } + } +} + +void Map::createRoom(bool first, int x1, int y1, int x2, int y2) { + dig(x1, y1, x2, y2); + if (first) { + // put the player in the first room + engine->player->x = (x1 + x2) / 2; + engine->player->y = (y1 + y2) / 2; + } + else { + TCODRandom* rng = TCODRandom::getInstance(); + if (rng->getInt(0, 3) == 0) { + engine->actors.push(new Actor((x1 + x2) / 2, (y1 + y2) / 2, "@", + TCOD_ColorRGB(255, 255, 0))); + } + } +} \ No newline at end of file diff --git a/Map.h b/Map.h new file mode 100644 index 0000000..510b98a --- /dev/null +++ b/Map.h @@ -0,0 +1,26 @@ +#pragma once +struct Tile { + bool explored; // has the player already seen this tile ? + Tile() : explored(false) {} +}; + +class Map { +public: + int width, height; + + Map(int width, int height); + ~Map(); + bool isWall(int x, int y) const; + bool isInFov(int x, int y) const; + bool isExplored(int x, int y) const; + void computeFov(); + void render(TCOD_Console& cons) const; +protected: + Tile* tiles; + friend class BspListener; + TCODMap* map; + void dig(int x1, int y1, int x2, int y2); + void createRoom(bool first, int x1, int y1, int x2, int y2); + + void setWall(int x, int y); +}; \ No newline at end of file diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 0000000..c8a7759 --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,14 @@ +{ + "default-registry": { + "kind": "git", + "baseline": "0d5cae153065957df7f382de7c1549ccc88027e5", + "repository": "https://github.com/microsoft/vcpkg" + }, + "registries": [ + { + "kind": "artifact", + "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", + "name": "microsoft" + } + ] +} diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..768eab2 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,5 @@ +{ + "dependencies": [ + "libtcod" + ] +}