summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCara Salter <cara@devcara.com>2023-01-07 23:24:04 -0500
committerCara Salter <cara@devcara.com>2023-01-07 23:24:04 -0500
commit36d4f4741cd2559362de7e64820ca4b29b022121 (patch)
tree172537aa08f946e2a6dc65bc4bec40985f6e1f95
downloadcpp-rl-master.tar.gz
cpp-rl-master.zip
Initial commitHEADmaster
-rw-r--r--.gitignore68
-rw-r--r--SConstruct9
-rw-r--r--src/frame.cpp216
-rw-r--r--src/frame.hpp76
-rw-r--r--src/main.cpp71
-rw-r--r--src/mob.cpp43
-rw-r--r--src/mob.hpp34
-rw-r--r--src/noise.cpp100
-rw-r--r--src/noise.hpp32
-rw-r--r--src/screen.cpp49
-rw-r--r--src/screen.hpp33
11 files changed, 731 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e596c2b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,68 @@
+# Created by https://www.toptal.com/developers/gitignore/api/scons,vim,c++
+# Edit at https://www.toptal.com/developers/gitignore?templates=scons,vim,c++
+
+### C++ ###
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+### SCons ###
+# for projects that use SCons for building: http://http://www.scons.org/
+.sconsign.dblite
+
+# When configure fails, SCons outputs these
+config.log
+.sconf_temp
+
+### Vim ###
+# Swap
+[._]*.s[a-v][a-z]
+!*.svg # comment out if you don't need vector files
+[._]*.sw[a-p]
+[._]s[a-rt-v][a-z]
+[._]ss[a-gi-z]
+[._]sw[a-p]
+
+# Session
+Session.vim
+Sessionx.vim
+
+# Temporary
+.netrwhist
+*~
+# Auto-generated tag files
+tags
+# Persistent undo
+[._]*.un~
+
+# End of https://www.toptal.com/developers/gitignore/api/scons,vim,c++
+cpp-rl*
diff --git a/SConstruct b/SConstruct
new file mode 100644
index 0000000..38474cf
--- /dev/null
+++ b/SConstruct
@@ -0,0 +1,9 @@
+
+envDebug = Environment(CXXFLAGS='-g')
+
+
+
+targetDebug = envDebug.Program(target = 'cpp-rl-dbg', source=Glob('src/*.cpp'), LIBS=['ncurses', 'tinfo'])
+
+envDebug.Default(targetDebug)
+
diff --git a/src/frame.cpp b/src/frame.cpp
new file mode 100644
index 0000000..48b5687
--- /dev/null
+++ b/src/frame.cpp
@@ -0,0 +1,216 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: frame.cpp
+ *
+ * Description: Implementation of frames
+ *
+ * Version: 1.0
+ * Created: 01/07/2023 10:11:54 PM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter (muirrum), cara@devcara.com
+ * Organization:
+ *
+ * =====================================================================================
+ */
+
+#include <stdlib.h>
+#include "frame.hpp"
+#include "noise.hpp"
+#include <ncurses.h>
+
+Frame::Frame(int nr_rows, int nr_cols, int row_0, int col_0) {
+ _has_super = FALSE;
+ _super = NULL;
+ _w = newwin(nr_rows, nr_cols, row_0, col_0);
+ _height = nr_rows;
+ _width = nr_cols;
+ _row = row_0;
+ _col = col_0;
+}
+
+Frame::Frame(Frame &sw, int nr_rows, int nr_cols, int row_0, int col_0) {
+ _has_super = TRUE;
+ _super = sw.win();
+
+ _w = derwin(sw.win(), nr_rows, nr_cols, row_0, col_0);
+ _height = nr_rows;
+ _width = nr_cols;
+ _row = row_0;
+ _col = col_0;
+}
+
+Frame::~Frame() {
+ delwin(_w);
+}
+
+// Place a mob in the window
+void Frame::place_mob(Mob &x) {
+ mvwaddch(_w, x.row(), x.col(), x.symbol());
+}
+
+void Frame::place_mob(Mob &x, int row_0, int col_0) {
+ if ((row_0 >= 0 && row_0 < _height) && (col_0 >= 0 && col_0 < _width)) {
+ // Get element at target position
+ char target = mvwinch(_w, row_0, col_0);
+ if (target == '~' || target == '#' || target == 'S') {
+ return;
+ }
+ erase(x);
+ mvwaddch(_w, row_0, col_0, x.symbol());
+ x.move(row_0, col_0);
+ }
+}
+
+void Frame::erase(Mob &x) {
+ mvwaddch(_w, x.row(), x.col(), ' ');
+}
+
+void Frame::center(Mob &x) {
+ if(_has_super) {
+ int rr = _row, cc = _col, hh, ww;
+ int _r = x.row() - _height/2;
+ int _c = x.col() - _width/2;
+
+ getmaxyx(_super, hh, ww);
+
+ if(_c + _width >= ww) {
+ int delta = ww - (_c + _width);
+ cc = _c + delta;
+ }
+ else {
+ cc = _c;
+ }
+
+ if(_r +_height >= hh) {
+ int delta = hh - (_r +_height);
+ rr = _r + delta;
+ }
+ else {
+ rr = _r;
+ }
+
+ if (_r < 0) {
+ rr = 0;
+ }
+
+ if (_c < 0) {
+ cc = 0;
+ }
+
+
+ move(rr, cc);
+ }
+}
+
+// Refresh window
+void Frame::refresh() {
+ if (_has_super) {
+ touchwin(_super);
+ }
+ wrefresh(_w);
+}
+
+// Move a window to a new position
+void Frame::move(int r, int c) {
+ if (_has_super) {
+ mvderwin(_w, r, c);
+ _row = r;
+ _col = c;
+ ::refresh();
+ }
+}
+
+void Frame::fill_window() {
+ int mid_x = _width/2;
+ int mid_y = _height/2;
+
+ // first region w 0s
+ for (int y = 0; y < mid_y; ++y) {
+ for(int x = 0; x < mid_x; ++x) {
+ mvwaddch(_w, y, x, '0');
+ }
+ }
+ for (int y = 0; y < mid_y; ++y) {
+ for(int x = mid_x; x < _width; ++x) {
+ mvwaddch(_w, y, x, '1');
+ }
+ }
+ for (int y = mid_y; y < _height; ++y) {
+ for(int x = 0; x < mid_x; ++x) {
+ mvwaddch(_w, y, x, '2');
+ }
+ }
+ for (int y = mid_y; y < _height; ++y) {
+ for(int x = mid_x; x < _width; ++x) {
+ mvwaddch(_w, y, x, '3');
+ }
+ }
+
+ for (int y = 0; y < _height; ++y) {
+ mvwaddch(_w, y, 0, '|');
+ mvwaddch(_w, y, _width - 1, '|');
+ }
+
+ for (int x = 0; x < _width; ++ x) {
+ mvwaddch(_w, 0, x, '-');
+ mvwaddch(_w, _height - 1, x, '-');
+ }
+}
+
+void Frame::gen_Perlin(const unsigned int &seed) {
+ PerlinNoise pn(seed);
+
+ for (int i = 0; i < _height; ++i) {
+ for (int j = 0; j < _width; ++j) {
+ double x = (double)j/((double)_width);
+ double y = (double)i/((double) _height);
+
+ double n = pn.noise(10 * x, 10 * y, 0.8);
+
+ // Water
+ if (n < 0.35) {
+ mvwaddch(_w, i, j, '~');
+ } else if (n >= 0.35 && n < 0.6) {
+ // Floors
+ mvwaddch(_w, i, j, '.');
+ } else if (n >= 0.6 && n < 0.8) {
+ // Walls
+ mvwaddch(_w, i, j, '#');
+ } else {
+ // Ice
+ mvwaddch(_w, i, j, 'S');
+ }
+ }
+ }
+}
+
+WINDOW* Frame::win() {
+ return _w;
+}
+
+WINDOW* Frame::super() {
+ return _super;
+}
+
+bool Frame::has_super() {
+ return _has_super;
+}
+
+int Frame::height() {
+ return _height;
+}
+
+int Frame::width() {
+ return _width;
+}
+
+int Frame::row() {
+ return _row;
+}
+
+int Frame::col() {
+ return _col;
+}
diff --git a/src/frame.hpp b/src/frame.hpp
new file mode 100644
index 0000000..378619e
--- /dev/null
+++ b/src/frame.hpp
@@ -0,0 +1,76 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: frame.hpp
+ *
+ * Description: Abstractions around NCurses windows
+ *
+ * Version: 1.0
+ * Created: 01/07/2023 09:55:52 PM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter (muirrum), cara@devcara.com
+ * Organization:
+ *
+ * =====================================================================================
+ */
+
+#pragma once
+
+#include <ncurses.h>
+
+#include "mob.hpp"
+
+class Frame {
+ // dimensions
+ int _height, _width;
+ // Position
+ int _row, _col;
+ // FALSE when root window and TRUE for a subwindow
+ bool _has_super;
+ // Pointer to an ncurses window
+ WINDOW* _w;
+ // The super-window, if exists
+ WINDOW* _super;
+
+ public:
+ // Init with no parent
+ Frame(int nr_rows, int nr_cols, int row_0, int col_0);
+ // Init with parent window
+ Frame(Frame &super, int nr_rows, int nr_cols, int row_0, int col_0);
+ ~Frame();
+
+ // Get window type
+ bool has_super();
+
+ WINDOW* win();
+ WINDOW *super();
+
+ // Get height of window
+ int height();
+ int width();
+ int row();
+ int col();
+
+ void refresh();
+ void move(int r, int c);
+
+ // Fill a window with numbers, for debugging
+ // Will look like this:
+ // 0 | 1
+ // -----
+ // 2 | 3
+ void fill_window();
+
+ void move_window(int r, int c);
+
+ void erase(Mob &x);
+ // Add a mob to the window
+ void place_mob(Mob &x);
+ void place_mob(Mob &x, int row_0, int col_0);
+ // Center viewport around mob
+ void center(Mob &x);
+
+ void gen_Perlin(const unsigned int &seed);
+};
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..7a27f82
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,71 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: main.cpp
+ *
+ * Description: Entrypoint
+ *
+ * Version: 1.0
+ * Created: 01/07/2023 09:36:42 PM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter (muirrum), cara@devcara.com
+ * Organization:
+ *
+ * =====================================================================================
+ */
+#include <stdlib.h>
+#include <ncurses.h>
+
+#include "screen.hpp"
+#include "mob.hpp"
+#include "frame.hpp"
+
+void game_loop(Frame &map, Frame &viewport, Mob &character, int ch);
+
+int main() {
+ Screen scr;
+
+ scr.add("Welcome to the game!\nPress any key to start.");
+
+ int ch = getch();
+
+ Frame game_map(2*scr.height(), 2*scr.width(), 0, 0);
+
+ Frame viewport(game_map, scr.height(), scr.width(), 0, 0);
+
+ Mob character('@', game_map.height()/2, game_map.width()/2);
+
+ game_map.gen_Perlin(237);
+
+ game_loop(game_map, viewport, character, ch);
+
+ return 0;
+}
+
+void game_loop(Frame &map, Frame &viewport, Mob &character, int ch) {
+ if (ch == 'q' || ch == 'Q') return;
+
+ map.place_mob(character);
+ viewport.center(character);
+ viewport.refresh();
+
+ for(;;) {
+ ch = getch();
+
+ if (ch == 'h') {
+ map.place_mob(character, character.row(), character.col() -1);
+ } else if (ch == 'j') {
+ map.place_mob(character, character.row() + 1, character.col());
+ } else if (ch == 'k') {
+ map.place_mob(character, character.row() - 1, character.col());
+ } else if (ch == 'l') {
+ map.place_mob(character, character.row(), character.col() + 1);
+ } else if (ch == 'q') {
+ break;
+ }
+ viewport.center(character);
+ viewport.refresh();
+ }
+}
diff --git a/src/mob.cpp b/src/mob.cpp
new file mode 100644
index 0000000..0da7b34
--- /dev/null
+++ b/src/mob.cpp
@@ -0,0 +1,43 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: mob.cpp
+ *
+ * Description: Implements a mobile entity
+ *
+ * Version: 1.0
+ * Created: 01/07/2023 10:02:44 PM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter (muirrum), cara@devcara.com
+ * Organization:
+ *
+ * =====================================================================================
+ */
+#include <stdlib.h>
+#include <ncurses.h>
+#include "mob.hpp"
+
+Mob::Mob(char symbol, int row_0, int col_0) {
+ _symbol = symbol;
+ _row = row_0;
+ _col = col_0;
+}
+
+void Mob::move(int row_0, int col_0) {
+ _row = row_0;
+ _col = col_0;
+}
+
+int Mob::row() {
+ return _row;
+}
+
+int Mob::col() {
+ return _col;
+}
+
+char Mob::symbol() {
+ return _symbol;
+}
diff --git a/src/mob.hpp b/src/mob.hpp
new file mode 100644
index 0000000..496a7bd
--- /dev/null
+++ b/src/mob.hpp
@@ -0,0 +1,34 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: mob.hpp
+ *
+ * Description: Defines a mobile entity
+ *
+ * Version: 1.0
+ * Created: 01/07/2023 09:54:14 PM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter (muirrum), cara@devcara.com
+ * Organization:
+ *
+ * =====================================================================================
+ */
+
+#pragma once
+class Mob {
+ int _row, _col;
+ char _symbol;
+ public:
+ // Create a mob
+ Mob(char symbol, int row_0, int col_0);
+ // Change mob position
+ void move(int row_0, int col_0);
+ // Get character's row (y) position
+ int row();
+ // Get mob's col (x) position
+ int col();
+ // Get the symbol that represents this mob
+ char symbol();
+};
diff --git a/src/noise.cpp b/src/noise.cpp
new file mode 100644
index 0000000..d91345b
--- /dev/null
+++ b/src/noise.cpp
@@ -0,0 +1,100 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: noise.cpp
+ *
+ * Description: Implementation of Perlin Noise
+ *
+ * Version: 1.0
+ * Created: 01/07/2023 10:55:49 PM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter (muirrum), cara@devcara.com
+ * Organization:
+ *
+ * =====================================================================================
+ */
+#include <stdlib.h>
+#include <iostream>
+#include <cmath>
+#include <random>
+#include <algorithm>
+#include "noise.hpp"
+
+PerlinNoise::PerlinNoise() {
+ // Magic numbers... magic numbers everywhere
+ p = {
+ 151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,
+ 8,99,37,240,21,10,23,190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,
+ 35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,
+ 134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,
+ 55,46,245,40,244,102,143,54, 65,25,63,161,1,216,80,73,209,76,132,187,208, 89,
+ 18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,
+ 250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,
+ 189,28,42,223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167,
+ 43,172,9,129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,
+ 97,228,251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,
+ 107,49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+ 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 };
+
+ // Duplicate
+ p.insert(p.end(), p.begin(), p.end());
+}
+
+PerlinNoise::PerlinNoise(unsigned int seed) {
+ p.resize(256);
+
+ // fill p with values from 0 to 255
+ std::iota(p.begin(), p.end(), 0);
+
+ std::default_random_engine engine(seed);
+
+ std::shuffle(p.begin(), p.end(), engine);
+
+ p.insert(p.end(), p.begin(), p.end());
+}
+
+double PerlinNoise::noise(double x, double y, double z) {
+ // Find the unit cube that contains the input
+ int X = (int) floor(x) & 255;
+ int Y = (int) floor(y) & 255;
+ int Z = (int) floor(z) & 255;
+
+ // find relative x, y, z in cube
+ x -= floor(x);
+ y -= floor(y);
+ z -= floor(z);
+
+ // Fade curves!
+ double u = fade(x);
+ double v = fade(y);
+ double w = fade(z);
+
+ // hash coordinates
+ int A = p[X] + Y;
+ int AA = p[A] + Z;
+ int AB = p[A + 1] + Z;
+ int B = p[X + 1] + Y;
+ int BA = p[B] + Z;
+ int BB = p[B + 1] + Z;
+
+ // Blend!
+ double res = lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), grad(p[BA], x-1, y, z)), lerp(u, grad(p[AB], x, y-1, z), grad(p[BB], x-1, y-1, z))), lerp(v, lerp(u, grad(p[AA+1], x, y, z-1), grad(p[BA+1], x-1, y, z-1)), lerp(u, grad(p[AB+1], x, y-1, z-1), grad(p[BB+1], x-1, y-1, z-1))));
+ return (res + 1.0)/2.0;
+}
+
+double PerlinNoise::fade(double t) {
+ return t * t * t * (t * (t * 6 - 15) + 10);
+}
+
+double PerlinNoise::lerp(double t, double a, double b) {
+ return a + t * (b - a);
+}
+
+double PerlinNoise::grad(int hash, double x, double y, double z) {
+ int h = hash & 15;
+ double u = h < 8 ? x : y,
+ v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+ return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
+}
diff --git a/src/noise.hpp b/src/noise.hpp
new file mode 100644
index 0000000..c127e7f
--- /dev/null
+++ b/src/noise.hpp
@@ -0,0 +1,32 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: noise.hpp
+ *
+ * Description: Defining Perlin Noise
+ *
+ * Version: 1.0
+ * Created: 01/07/2023 10:52:51 PM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter (muirrum), cara@devcara.com
+ * Organization:
+ *
+ * =====================================================================================
+ */
+#include <vector>
+#include <stdlib.h>
+
+class PerlinNoise {
+ // permutation vector
+ std::vector<int> p;
+ public:
+ PerlinNoise();
+ PerlinNoise(unsigned int seed);
+ double noise(double x, double y, double z);
+ private:
+ double fade(double t);
+ double lerp(double t, double a, double b);
+ double grad(int hash, double x, double y, double z);
+};
diff --git a/src/screen.cpp b/src/screen.cpp
new file mode 100644
index 0000000..9bff98f
--- /dev/null
+++ b/src/screen.cpp
@@ -0,0 +1,49 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: screen.cpp
+ *
+ * Description: Defines an NCurses screen
+ *
+ * Version: 1.0
+ * Created: 01/07/2023 09:52:27 PM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter (muirrum), cara@devcara.com
+ * Organization:
+ *
+ * =====================================================================================
+ */
+
+#include <ncurses.h>
+#include <stdlib.h>
+#include "screen.hpp"
+
+Screen::Screen() {
+ initscr();
+ clear();
+ noecho();
+ cbreak();
+ keypad(stdscr, TRUE);
+ curs_set(0);
+
+ getmaxyx(stdscr, _height, _width);
+}
+
+Screen::~Screen() {
+ endwin();
+}
+
+// Print a message
+void Screen::add(const char* message) {
+ printw(message);
+}
+
+int Screen::height() {
+ return _height;
+}
+
+int Screen::width() {
+ return _width;
+}
diff --git a/src/screen.hpp b/src/screen.hpp
new file mode 100644
index 0000000..d9324a2
--- /dev/null
+++ b/src/screen.hpp
@@ -0,0 +1,33 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: screen.hpp
+ *
+ * Description: NCurses screen
+ *
+ * Version: 1.0
+ * Created: 01/07/2023 09:52:54 PM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: Cara Salter (muirrum), cara@devcara.com
+ * Organization:
+ *
+ * =====================================================================================
+ */
+
+
+class Screen {
+ int _height, _width;
+ public:
+ // Initialize NCurses
+ Screen();
+ // Clear NCurses
+ ~Screen();
+ // Print a message on the screen
+ void add(const char* message);
+ // Get the screen height
+ int height();
+ // Get the screen width
+ int width();
+};