Browse Source

Added VSCode setup, look mode, entity draw, stats

master
Macoy Madson 5 years ago
parent
commit
aa69a4d954
  1. 81
      .vscode/c_cpp_properties.json
  2. 35
      .vscode/launch.json
  3. 15
      src/Entity.cpp
  4. 35
      src/Entity.hpp
  5. 20
      src/Globals.hpp
  6. 29
      src/Levels.cpp
  7. 3
      src/Levels.hpp
  8. 1
      src/Logging.hpp
  9. 25
      src/RLMap.cpp
  10. 3
      src/RLMap.hpp
  11. 275
      src/main.cpp

81
.vscode/c_cpp_properties.json

@ -0,0 +1,81 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
]
},
{
"name": "Linux",
"includePath": [
"/usr/include/c++/5",
"/usr/include/x86_64-linux-gnu/c++/5",
"/usr/include/c++/5/backward",
"/usr/lib/gcc/x86_64-linux-gnu/5/include",
"/usr/local/include",
"/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"/usr/include/x86_64-linux-gnu",
"/usr/include",
"${workspaceRoot}",
"${workspaceRoot}/libs/base2.0"
],
"defines": [],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include/c++/5",
"/usr/include/x86_64-linux-gnu/c++/5",
"/usr/include/c++/5/backward",
"/usr/lib/gcc/x86_64-linux-gnu/5/include",
"/usr/local/include",
"/usr/lib/gcc/x86_64-linux-gnu/5/include-fixed",
"/usr/include/x86_64-linux-gnu",
"/usr/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Win32",
"includePath": [
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include",
"${workspaceRoot}"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": 3
}

35
.vscode/launch.json

@ -0,0 +1,35 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "(lldb) Launch",
"program": "${workspaceFolder}/bin/7drl2018",
"args": [],
"cwd": "${workspaceFolder}"
},
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/7drl2018",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

15
src/Entity.cpp

@ -1,6 +1,21 @@
#include "Entity.hpp"
bool RLEntity::SamePos(RLEntity& otherEnt)
{
return otherEnt.X == X && otherEnt.Y == Y;
}
Player::Player()
{
Type = PLAYER_TYPE;
Color = {PLAYER_COLOR_NORMAL};
Speed = 1;
Description = "yourself";
Stats["HP"] = {"Health", PLAYER_STARTING_MAX_HEALTH, PLAYER_STARTING_MAX_HEALTH};
}
bool canMoveTo(RLEntity& entity, int deltaX, int deltaY, RLMap& map)
{
return map.At(entity.X + deltaX, entity.Y + deltaY).Type == FLOOR_TYPE;
}

35
src/Entity.hpp

@ -1,16 +1,41 @@
#pragma once
typedef char RLDrawableType;
#include <map>
struct RLDrawable
#include "RLColor.hpp"
#include "RLMap.hpp"
typedef char RLEntityType;
struct RLCombatStat
{
std::string Name;
int Max;
int Value;
};
typedef std::map<std::string, RLCombatStat> RLCombatStatistics;
struct RLEntity
{
int X;
int Y;
RLDrawableType Type;
int Speed;
RLEntityType Type;
RLColor Color;
std::string Description;
RLCombatStatistics Stats;
bool SamePos(RLEntity& otherEnt);
};
struct Player : RLDrawable
struct Player : RLEntity
{
Player();
};
};
bool canMoveTo(RLEntity& entity, int deltaX, int deltaY, RLMap& map);

20
src/Globals.hpp

@ -1,8 +1,5 @@
#pragma once
#include <vector>
#include <string>
// Global.hpp is included by all files automatically
#define CLAMP(value, min, max) if (value > max) value = max; else if (value < min) value = min;
@ -12,19 +9,34 @@
//
// Colors
//
// Interface
#define WIN_BACKGROUND_COLOR 34, 34, 34, 255
#define LOG_COLOR_NORMAL 255, 255, 255, 255
#define LOG_COLOR_IMPORTANT 249, 212, 35, 255
#define LOG_COLOR_DEAD 232, 30, 34, 255
#define LOOK_CURSOR_COLOR 252, 145, 57, 255
// Tiles
#define WALL_TILE_COLOR_NORMAL 255, 255, 255, 255
#define FLOOR_TILE_COLOR_NORMAL 46, 64, 75, 255
// Entities
#define PLAYER_COLOR_NORMAL 252, 145, 57, 255
#define ENEMY_COLOR_NORMAL 232, 30, 34, 255
//
// Tile/Entity Types
//
#define PLAYER_TYPE '@'
#define SKELETON_TYPE 's'
#define WALL_TYPE '#'
#define FLOOR_TYPE '.'
#define FLOOR_TYPE '.'
#define LOOK_MODE_CURSOR "_"
//
// Combat constants
//
#define PLAYER_STARTING_MAX_HEALTH 100

29
src/Levels.cpp

@ -1,16 +1,37 @@
#include "noise/noise.hpp"
#include "Levels.hpp"
#include "RLMap.hpp"
void createTestMap(RLMap& map)
{
for (int camY = 0; camY < map.Height; ++camY)
for (int tileY = 0; tileY < map.Height; ++tileY)
{
for (int tileX = 0; tileX < map.Width; ++tileX)
{
if ((tileY == 0 || tileY == map.Height - 1) || (tileX == 0 || tileX == map.Width - 1))
{
RLTile& currentTile = map.At(tileX, tileY);
currentTile.Type = WALL_TYPE;
currentTile.Color = {WALL_TILE_COLOR_NORMAL};
}
}
}
}
void createTestMap2(RLMap& map)
{
static Noise2d noise(3158008);
const float scale = 0.1;
for (int tileY = 0; tileY < map.Height; ++tileY)
{
for (int camX = 0; camX < map.Width; ++camX)
for (int tileX = 0; tileX < map.Width; ++tileX)
{
if ((camY == 0 || camY == map.Height - 1) || (camX == 0 || camX == map.Width - 1))
float noiseValue = noise.scaledOctaveNoise2d(tileX, tileY, 0, 255, 10, scale, 0.55, 2);
if (noiseValue < 100.f)
{
RLTile& currentTile = map.At(camX, camY);
RLTile& currentTile = map.At(tileX, tileY);
currentTile.Type = WALL_TYPE;
currentTile.Color = {WALL_TILE_COLOR_NORMAL};
}

3
src/Levels.hpp

@ -2,4 +2,5 @@
typedef struct RLMap RLMap;
void createTestMap(RLMap& map);
void createTestMap(RLMap& map);
void createTestMap2(RLMap& map);

1
src/Logging.hpp

@ -2,6 +2,7 @@
// size_t
#include <stddef.h>
#include <string>
// This file is based on PLog's interface but uses C strings only. See Plog:
// Plog - portable and simple log for C++

25
src/RLMap.cpp

@ -1,5 +1,24 @@
#include "RLMap.hpp"
std::string GetTileDescription(RLTile& tile)
{
std::string description = "";
switch (tile.Type)
{
case '#':
description += "a wall";
break;
case '.':
description += "a stone tile";
break;
default:
description += "something you don't understand";
break;
}
return description;
}
RLMap::RLMap(int width, int height) : Width(width), Height(height)
{
Tiles.resize(width * height);
@ -13,5 +32,9 @@ RLMap::RLMap(int width, int height) : Width(width), Height(height)
RLTile& RLMap::At(int x, int y)
{
return Tiles[y * Width + x];
CLAMP(x, 0, Width - 1);
CLAMP(y, 0, Height - 1);
unsigned int index = y * Width + x;
index = MIN(index, Tiles.size() - 1);
return Tiles[index];
}

3
src/RLMap.hpp

@ -1,6 +1,7 @@
#pragma once
#include <vector>
#include <string>
#include "RLColor.hpp"
@ -14,6 +15,8 @@ struct RLTile
RLColor Color;
};
std::string GetTileDescription(RLTile& tile);
struct RLMap
{
int Width;

275
src/main.cpp

@ -1,5 +1,7 @@
#include <iostream>
#include <map>
#include "graphics/graphics.hpp"
#include "input/input.hpp"
@ -8,6 +10,8 @@
#include "Entity.hpp"
#include "Levels.hpp"
static int TurnCounter = 0;
static std::vector<std::string> GameLog;
// @Callback: CustomLogOutputFunc
@ -42,8 +46,22 @@ void ConsoleAndGameLogOutput(const gv::Logging::Record& record)
if (IsInfo)
{
static int lastTurnLog = 0;
std::string gameLogAction(buffer);
GameLog.push_back(gameLogAction);
// Append logs to the same line if they occur on the same turn
if (lastTurnLog == TurnCounter && !GameLog.empty() && gameLogAction != GameLog.back())
{
std::string& currentTurnLog = GameLog.back();
currentTurnLog += ". ";
currentTurnLog += gameLogAction;
}
else
{
GameLog.push_back(gameLogAction);
lastTurnLog = TurnCounter;
}
}
}
@ -68,16 +86,71 @@ void initializeDisplayText(text& text)
std::cout << "err: cannot load default text font\n";
}
struct GameInput
{
inputManager& inp;
std::map<inputCode::keyCode, bool> keyTapStates;
GameInput(inputManager& newInput) : inp(newInput)
{
}
bool Tapped(inputCode::keyCode key)
{
bool isPressed = inp.isPressed(key);
std::map<inputCode::keyCode, bool>::iterator findIt = keyTapStates.find(key);
if (findIt != keyTapStates.end())
{
if (isPressed)
{
if (findIt->second)
{
// Wasn't tapped this frame
return false;
}
else
{
findIt->second = true;
return true;
}
}
else
findIt->second = false;
}
else
{
keyTapStates[key] = true;
return isPressed;
}
return false;
}
};
void SetTextColor(text& text, RLColor& color)
{
text.setColor(color.r, color.g, color.b, color.a);
}
int main(int argc, char const* argv[])
{
const int WindowWidth = 2500;
const int WindowHeight = 1600;
const int TileTextHeight = 32;
const int TileTextWidth = TileTextHeight / 2;
const int ViewTileRightMargin = 2;
const int SidebarTileWidth = 30;
const int ViewTileRightMargin = SidebarTileWidth + 1;
const int ViewTileBottomMargin = 2;
const int ViewTileWidth = (WindowWidth / TileTextWidth) - ViewTileRightMargin;
const int ViewTileHeight = (WindowHeight / TileTextHeight) - ViewTileBottomMargin;
const int SidebarStartX = (ViewTileWidth + 1) * TileTextWidth;
const int SidebarStartY = 0 * TileTextHeight;
const int LogX = 10;
const int LogY = ViewTileHeight * TileTextHeight;
@ -90,6 +163,7 @@ int main(int argc, char const* argv[])
initializeWindow(win);
inputManager inp(&win);
GameInput gameInp(inp);
text displayText;
initializeDisplayText(displayText);
@ -104,35 +178,104 @@ int main(int argc, char const* argv[])
player.X = ViewTileWidth / 2;
player.Y = ViewTileHeight / 2;
RLEntity lookModeCursor;
RLMap testMap(ViewTileWidth, ViewTileHeight);
createTestMap(testMap);
// createTestMap(testMap);
createTestMap2(testMap);
RLEntity skeleton;
skeleton.X = (ViewTileWidth / 2) + 3;
skeleton.Y = ViewTileHeight / 2;
skeleton.Speed = 1;
skeleton.Type = SKELETON_TYPE;
skeleton.Color = {ENEMY_COLOR_NORMAL};
skeleton.Description = "a skeleton";
skeleton.Stats["HP"] = {"Health", PLAYER_STARTING_MAX_HEALTH, PLAYER_STARTING_MAX_HEALTH};
std::vector<RLEntity> npcs{skeleton};
int camXOffset = 0;
int camYOffset = 0;
while (!win.shouldClose() && !inp.isPressed(inputCode::Return) &&
!inp.isPressed(inputCode::Escape))
bool lookMode = false;
while (!win.shouldClose() && !inp.isPressed(inputCode::Return))
{
bool playerTurnPerformed = false;
//
// Input
//
// Player movement
if (inp.isPressed(inputCode::Up))
// Escape exits modes or closes the game
if (gameInp.Tapped(inputCode::Escape))
{
player.Y -= 1;
if (lookMode)
lookMode = false;
else
// Close the game
break;
}
if (inp.isPressed(inputCode::Down))
// Look mode
if (gameInp.Tapped(inputCode::L))
{
player.Y += 1;
// Entering look mode; set the cursor to the player's position
if (!lookMode)
{
lookModeCursor.X = player.X;
lookModeCursor.Y = player.Y;
}
lookMode = !lookMode;
}
if (inp.isPressed(inputCode::Left))
// Directional navigation
int deltaX = 0;
int deltaY = 0;
if (gameInp.Tapped(inputCode::Up))
deltaY -= 1;
if (gameInp.Tapped(inputCode::Down))
deltaY += 1;
if (gameInp.Tapped(inputCode::Left))
deltaX -= 1;
if (gameInp.Tapped(inputCode::Right))
deltaX += 1;
if (lookMode)
{
player.X -= 1;
if (deltaX || deltaY)
{
lookModeCursor.X += deltaX;
lookModeCursor.Y += deltaY;
}
}
if (inp.isPressed(inputCode::Right))
else
{
player.X += 1;
// Player movement
if (canMoveTo(player, deltaX, deltaY, testMap))
{
player.X += deltaX;
player.Y += deltaY;
// Decide whether we need to make this a turn
if (abs(deltaX) >= player.Speed || abs(deltaY) >= player.Speed)
{
playerTurnPerformed = true;
}
}
else
{
LOGI << "You bump into a wall";
}
}
//
// Turn update
//
if (playerTurnPerformed)
{
TurnCounter++;
}
//
@ -149,16 +292,28 @@ int main(int argc, char const* argv[])
static std::string buffer = "";
buffer.clear();
if (player.X == tileX && player.Y == tileY)
bool shouldDrawTile = true;
for (RLEntity& npc : npcs)
{
if (npc.X == tileX && npc.Y == tileY)
{
buffer += npc.Type;
SetTextColor(displayText, npc.Color);
shouldDrawTile = false;
break;
}
}
if (buffer.empty() && player.X == tileX && player.Y == tileY)
{
buffer += player.Type;
displayText.setColor(PLAYER_COLOR_NORMAL);
SetTextColor(displayText, player.Color);
}
else
else if (buffer.empty())
{
buffer += currentTile.Type;
displayText.setColor(currentTile.Color.r, currentTile.Color.g,
currentTile.Color.b, currentTile.Color.a);
SetTextColor(displayText, currentTile.Color);
}
displayText.setText(buffer);
@ -167,10 +322,88 @@ int main(int argc, char const* argv[])
}
}
// Draw look mode cursor
if (lookMode)
{
static std::string lookModeCursorText(LOOK_MODE_CURSOR);
displayText.setText(lookModeCursorText);
displayText.setColor(LOOK_CURSOR_COLOR);
displayText.setPosition(TileTextWidth * lookModeCursor.X,
TileTextHeight * lookModeCursor.Y);
win.draw(&displayText);
}
//
// Draw sidebar
//
{
int currentRowY = SidebarStartY;
displayText.setColor(LOG_COLOR_NORMAL);
displayText.setText("Stats");
displayText.setPosition(SidebarStartX, SidebarStartY);
win.draw(&displayText);
currentRowY += TileTextHeight * 2;
for (std::pair<const std::string, RLCombatStat>& stat : player.Stats)
{
std::string statName(stat.second.Name);
std::string statValue(std::to_string(stat.second.Value));
std::string statText(statName);
// Add justify spaces
for (unsigned int i = 0;
i < SidebarTileWidth - (statName.size() + statValue.size()) - 1; i++)
statText += ' ';
statText += statValue;
displayText.setPosition(SidebarStartX, currentRowY);
displayText.setText(statText);
win.draw(&displayText);
currentRowY += TileTextHeight;
}
}
//
// Draw log
// Draw log/status
//
if (GameLog.size())
if (lookMode)
{
std::string description;
RLTile& lookTile = testMap.At(lookModeCursor.X, lookModeCursor.Y);
std::string tileDescription = GetTileDescription(lookTile);
std::string npcDescription;
for (RLEntity& npc : npcs)
{
if (npc.X == lookModeCursor.X && npc.Y == lookModeCursor.Y)
{
npcDescription += npc.Description;
break;
}
}
if (!tileDescription.empty() || !npcDescription.empty())
{
if (player.SamePos(lookModeCursor))
description += "You are standing on ";
else if (description.empty())
description += "You see ";
if (!npcDescription.empty())
{
description += npcDescription;
description += " standing on ";
description += tileDescription;
}
else
description += tileDescription;
}
displayText.setText(description);
displayText.setColor(LOG_COLOR_NORMAL);
displayText.setPosition(LogX, LogY);
win.draw(&displayText);
}
else if (GameLog.size())
{
displayText.setText(GameLog.back());
displayText.setColor(LOG_COLOR_NORMAL);

Loading…
Cancel
Save