diff options
Diffstat (limited to 'game')
-rw-r--r-- | game/entity.cpp | 3 | ||||
-rw-r--r-- | game/entity.h | 43 | ||||
-rw-r--r-- | game/ground.cpp | 82 | ||||
-rw-r--r-- | game/ground.h | 22 | ||||
-rw-r--r-- | game/gst.cpp | 1 | ||||
-rw-r--r-- | game/gst.h | 34 | ||||
-rw-r--r-- | game/menu.cpp | 29 | ||||
-rw-r--r-- | game/menu.h | 47 | ||||
-rw-r--r-- | game/player.h | 12 | ||||
-rw-r--r-- | game/playercontrol.cpp | 116 | ||||
-rw-r--r-- | game/playercontrol.h | 87 | ||||
-rw-r--r-- | game/tile.cpp | 1 | ||||
-rw-r--r-- | game/tile.h | 23 | ||||
-rw-r--r-- | game/view.cpp | 77 | ||||
-rw-r--r-- | game/view.h | 32 |
15 files changed, 609 insertions, 0 deletions
diff --git a/game/entity.cpp b/game/entity.cpp new file mode 100644 index 0000000..8362c40 --- /dev/null +++ b/game/entity.cpp @@ -0,0 +1,3 @@ +#include "entity.h" +#include <iostream> +;
\ No newline at end of file diff --git a/game/entity.h b/game/entity.h new file mode 100644 index 0000000..1fcf026 --- /dev/null +++ b/game/entity.h @@ -0,0 +1,43 @@ +#ifndef ENTITIES_H +#define ENTITIES_H + +#include <vector> +#include <string> + +#include "../umath/vec2.h" + +class Ability { + public: + Ability(); +}; + +class EntityInfo { + public: + EntityInfo() { spritebounds = vec2 { 16*6, 16 }; } + + std::string name; + + float hp; + float attack; + float defence; + int range; + float sight; + int move; + std::vector<Ability> abilities; + + vec2 spritebounds; +}; + +class Entity { + public: + Entity(int x, int y, EntityInfo &info, int owner) + : x(x), y(y), info(info), owner(owner) {} + + int x, y; + bool done = false; + EntityInfo &info; + + int owner; +}; + +#endif
\ No newline at end of file diff --git a/game/ground.cpp b/game/ground.cpp new file mode 100644 index 0000000..c0ba2ca --- /dev/null +++ b/game/ground.cpp @@ -0,0 +1,82 @@ +#include "ground.h" +#include "gst.h" + +#include <iostream> +#include <algorithm> + +Ground::Ground (int sx, int sy) { + sizex = sx; sizey = sy; + tiles = new int[sx*sy]; + for (int i=0; i<sx*sy; i++) tiles[i] = 0; +} + +Ground::~Ground () { + +} + +int Ground::at(int x, int y) { + return x+y*sizex; +} + + +// move area +std::vector<int> Ground::star (int pos) { + std::vector<int> fs; + int x = pos % sizex, y = pos / sizex; + if (x-1 >= 0) { fs.push_back(at(x-1, y)); } + if (x+1 < sizex) { fs.push_back(at(x+1, y)); } + if (y-1 >= 0) { fs.push_back(at(x, y-1)); } + if (y+1 < sizey) { fs.push_back(at(x, y+1)); } + return fs; +} + +class step { public: + step(int pos, int m) : pos(pos), m(m) {}; + bool operator==(step oth) { return pos==oth.pos && m==oth.m; } + bool operator==(int p) { return pos==p; } + int pos, m; +}; + +std::vector<int> Ground::move_area (Gst &gst, Entity ent) { + std::vector<int> moves; + std::vector<int> visited { at(ent.x, ent.y) }; + std::vector<step> frontier { step { at(ent.x, ent.y), ent.info.move } }; + + int iter=0; + for (; iter<10000; iter++) { + + if (frontier.size() == 0) break; + step maxf {-1, -1}; + for (step t : frontier) { + if (t.m > maxf.m) { + maxf.pos = t.pos; + maxf.m = t.m; + } + } + frontier.erase(std::remove(frontier.begin(), frontier.end(), maxf), + frontier.end()); + auto forward_star = star(maxf.pos); + for (int t : forward_star) { + if (!(std::find(visited.begin(), visited.end(), t) != visited.end()) + && !(std::find(frontier.begin(), frontier.end(), t) != frontier.end())) { + int walkedm = maxf.m - gst.tiles[gst.ground.tiles[t]].move_cost; + bool obstructed = false; + for (Entity &e : gst.entities) { + if (e.owner != ent.owner && at(e.x, e.y) == t) { + obstructed = true; + break; + } + } + if (walkedm >= 0 && !obstructed) { + frontier.emplace_back(t, walkedm); + moves.push_back(t); + } + } + } + visited.push_back(maxf.pos); + } + + std::cout << "iters: " << iter; + + return moves; +}
\ No newline at end of file diff --git a/game/ground.h b/game/ground.h new file mode 100644 index 0000000..545deb9 --- /dev/null +++ b/game/ground.h @@ -0,0 +1,22 @@ +#ifndef GROUND_H +#define GROUND_H + +#include "entity.h" + +class Gst; + +class Ground { + public: + Ground (int sx, int sy); + ~Ground (); + + int *tiles; + + int sizex; + int sizey; + int at (int x, int y); + std::vector<int> star (int pos); + std::vector<int> move_area (Gst &gst, Entity ent); +}; + +#endif
\ No newline at end of file diff --git a/game/gst.cpp b/game/gst.cpp new file mode 100644 index 0000000..5c195c8 --- /dev/null +++ b/game/gst.cpp @@ -0,0 +1 @@ +#include "gst.h"
\ No newline at end of file diff --git a/game/gst.h b/game/gst.h new file mode 100644 index 0000000..340d596 --- /dev/null +++ b/game/gst.h @@ -0,0 +1,34 @@ +#ifndef GST_H +#define GST_H + +#include <vector> + +#include "ground.h" +#include "entity.h" +#include "tile.h" +#include "player.h" + +class Gst { + public: + Gst(int sx, int sy) : ground(sx, sy) {} + + std::vector<EntityInfo> infos; + std::vector<Tile> tiles; + std::vector<Entity> entities; + Ground ground; + + std::vector<Player> players; + + int turn { 0 }; + int day { 0 }; + + void end_day () { + day++; + if (day >= players.size()) { + day = 0; + turn++; + } + } +}; + +#endif
\ No newline at end of file diff --git a/game/menu.cpp b/game/menu.cpp new file mode 100644 index 0000000..76913b5 --- /dev/null +++ b/game/menu.cpp @@ -0,0 +1,29 @@ +#include "menu.h" + +void Menu::close () { + active = false; +} + +void Menu::open (vec2 res) { + active = true; + pos = vec2 { (float)res.x, (float)res.y }; + float height = options.size() * 20; + size = vec2 { 120, height+10 }; + pos *= 0.5f; + pos -= size/2; +} + +int Menu::mouse_option (vec2 mouse) { + int i=0; + for (Option opt : options) { + vec2 off { 10, 10.0f + i*20 }; + vec2 sizeopt { 100, 20 }; + off += pos; + if (off.x < mouse.x && mouse.x < off.x+sizeopt.x + && off.y < mouse.y && mouse.y < off.y+sizeopt.y ) { + return opt.id; + } + i++; + } + return -1; +}
\ No newline at end of file diff --git a/game/menu.h b/game/menu.h new file mode 100644 index 0000000..95be683 --- /dev/null +++ b/game/menu.h @@ -0,0 +1,47 @@ +#ifndef MENU_H +#define MENU_H + +#include <vector> +#include <string> + +#include "../umath/vec2.h" + +class Option { + public: + Option(std::string name, int id) : name(name), id(id) {} + + std::string name; + int id; +}; + + +class Menu { + public: + bool active { false }; + std::vector<Option> options; + vec2 pos, size; + + void open (vec2 res); + void close (); + int mouse_option (vec2 mouse); +}; + +class Menu_unit : public Menu { + public: + Menu_unit () {} + + enum Opts { + move, attack, done + }; +}; + +class Menu_day : public Menu { + public: + Menu_day () {} + + enum Opts { + end_day, tech, empire_review, scoring + }; +}; + +#endif
\ No newline at end of file diff --git a/game/player.h b/game/player.h new file mode 100644 index 0000000..2cee05f --- /dev/null +++ b/game/player.h @@ -0,0 +1,12 @@ +#ifndef PLAYER_H +#define PLAYER_H + + +class Player { + public: + Player (int r, int g, int b) : r(r), g(g), b(b) {} + + int r, g, b; +}; + +#endif
\ No newline at end of file diff --git a/game/playercontrol.cpp b/game/playercontrol.cpp new file mode 100644 index 0000000..15b1b86 --- /dev/null +++ b/game/playercontrol.cpp @@ -0,0 +1,116 @@ +#include <iostream> +#include <string> + +#include "playercontrol.h" +#include "entity.h" + +Player_control::Player_control () { + fsm.arcs.emplace_back( + select, sel_ground, -1, + [](Gst &gst, View &view, Fsm &fsm, int p) { + view.selected_ground = p; + std::cout << "selected ground " << p << "\n"; + view.menu_day.options.clear(); + view.menu_day.options.emplace_back("End Day", Menu_day::Opts::end_day); + view.menu_day.options.emplace_back("Research", Menu_day::Opts::tech); + view.menu_day.options.emplace_back("Empire Review", Menu_day::Opts::empire_review); + view.menu_day.options.emplace_back("Scoring", Menu_day::Opts::scoring); + view.menu_day.open(view.res); + return menu_day; + } + ); + fsm.arcs.emplace_back( + menu_day, opt, Menu_day::Opts::end_day, + [](Gst &gst, View &view, Fsm &fsm, int p) { + view.menu_day.close(); + view.selected_ground = -1; + // end turn calcs + for (Entity &e : gst.entities) { + e.done = false; + } + gst.end_day(); + std::cout << "end day " << p << "\n"; + return select; + } + ); + fsm.arcs.emplace_back( + menu_day, back, -1, + [](Gst &gst, View &view, Fsm &fsm, int p) { + view.menu_day.close(); + view.selected_ground = -1; + return select; + } + ); + fsm.arcs.emplace_back( + select, sel_unit, -1, + [](Gst &gst, View &view, Fsm &fsm, int p) { + view.selected_entity = p; + view.menu_unit.options.clear(); + view.menu_unit.options.emplace_back("Move", Menu_unit::Opts::move); + view.menu_unit.options.emplace_back("Attack", Menu_unit::Opts::attack); + view.menu_unit.options.emplace_back("Done", Menu_unit::Opts::done); + view.menu_unit.open(view.res); + std::cout << "selected unit " << p << "\n"; + return menu_unit; + } + ); + fsm.arcs.emplace_back( + menu_unit, back, -1, + [](Gst &gst, View &view, Fsm &fsm, int p) { + view.selected_entity = -1; + view.menu_unit.close(); + return select; + } + ); + fsm.arcs.emplace_back( + menu_unit, opt, Menu_unit::Opts::move, + [](Gst &gst, View &view, Fsm &fsm, int p) { + view.menu_unit.close(); + std::cout << "move " << p << "\n"; + Entity &ent = gst.entities[view.selected_entity]; + view.moves = gst.ground.move_area(gst, ent); + return move; + } + ); + fsm.arcs.emplace_back( + move, sel_ground, -1, + [](Gst &gst, View &view, Fsm &fsm, int p) { + std::cout << "moved to " << p << "\n"; + Entity &ent = gst.entities[view.selected_entity]; + view.moves.clear(); + ent.x = p % gst.ground.sizex; + ent.y = p / gst.ground.sizex; + // remove move points + view.menu_unit.options.clear(); + view.menu_unit.options.emplace_back("Attack", Menu_unit::Opts::attack); + view.menu_unit.options.emplace_back("Done", Menu_unit::Opts::done); + view.menu_unit.open(view.res); + return menu_unit; + } + ); + fsm.arcs.emplace_back( + menu_unit, opt, Menu_unit::Opts::done, + [](Gst &gst, View &view, Fsm &fsm, int p) { + view.menu_unit.close(); + gst.entities[view.selected_entity].done = true; + view.selected_entity = -1; + std::cout << "done " << p << "\n"; + return select; + } + ); +} + +void Player_control::process (Gst &gst, View &view) { + if (view.cursor_entity != -1) { + fsm.transition(gst, view, fsm, sel_unit, view.cursor_entity); + } + if (view.cursor_ground != -1) { + fsm.transition(gst, view, fsm, sel_ground, view.cursor_ground); + } + if (view.back != -1) { + fsm.transition(gst, view, fsm, back, 0); + } + if (view.opt != -1) { + fsm.transition(gst, view, fsm, opt, view.opt); + } +}
\ No newline at end of file diff --git a/game/playercontrol.h b/game/playercontrol.h new file mode 100644 index 0000000..4e66e07 --- /dev/null +++ b/game/playercontrol.h @@ -0,0 +1,87 @@ +#ifndef PLAYERCONTROL_H +#define PLAYERCONTROL_H + +#include <iostream> + +#include "gst.h" +#include "view.h" +#include <vector> +#include <functional> + +enum pc_state { + select, + move, + attack, + train, + build, + merge, + trade, + age_up, + heal, + power, + move_target, + attack_target, + menu_train, + menu_build, + target_build, + merge_target, + target_heal, + menu_power, + target_power, + menu_unit, + menu_day, + end +}; + +enum pc_action { + sel_unit, + sel_ground, + opt, + back +}; + + +class Fsm; +using lambda = std::function<pc_state(Gst&, View&, Fsm&, int p)>; + + +class Arc { + public: + Arc (pc_state from, pc_action act, int p, lambda f) + : from(from), act(act), p(p), f(f) {}; + pc_state from; + pc_action act; + int p; + + lambda f; +}; + +class Fsm { + public: + Fsm() { state = select; } + + void transition (Gst &gst, View &view, Fsm &fsm, pc_action act, int p) { + std::cout << "> transitioning from " << state << " with " << act << std::endl; + for (Arc a : arcs) { + if (a.from == state && a.act == act && (a.p == p || a.p == -1)) { + state = a.f(gst, view, fsm, p); + break; + } + } + } + std::vector<Arc> arcs; + + private: + pc_state state; +}; + + +class Player_control { + public: + Player_control (); + void process (Gst &gst, View &view); + + Fsm fsm; +}; + +#endif
\ No newline at end of file diff --git a/game/tile.cpp b/game/tile.cpp new file mode 100644 index 0000000..a765b2e --- /dev/null +++ b/game/tile.cpp @@ -0,0 +1 @@ +#include "tile.h"
\ No newline at end of file diff --git a/game/tile.h b/game/tile.h new file mode 100644 index 0000000..3b83531 --- /dev/null +++ b/game/tile.h @@ -0,0 +1,23 @@ +#ifndef TILE_H +#define TILE_H + +#include <vector> +#include <string> + +#include "../umath/vec2.h" + +class Tile { + public: + Tile() {} + + std::string name; + int move_cost; + int sight_cost; + int range_bonus; + float attack_bonus; + float defence_bonus; + + vec2 spritebounds; +}; + +#endif
\ No newline at end of file diff --git a/game/view.cpp b/game/view.cpp new file mode 100644 index 0000000..6599a0e --- /dev/null +++ b/game/view.cpp @@ -0,0 +1,77 @@ +#include "view.h" + +void View::process (Gst &gst, vec2 cam, vec2 mouse, int *mheld) { + Ground &gr = gst.ground; + std::vector<Entity> &entities = gst.entities; + + vec2 absmouse { mouse }; + absmouse -= cam; + + cursor_ground = -1; + cursor_entity = -1; + back = -1; + opt = -1; + + if (mheld[0] == 1) { + bool found = false; + + if (moves.size() > 0 && !found) { + for (int i=0; i<moves.size() && !found; i++) { + int x = moves[i] % gr.sizex; + int y = moves[i] / gr.sizex; + vec2 pos { (float)x*32, (float)y*32 }; + if (pos.x < absmouse.x && absmouse.x < pos.x+32 + && pos.y < absmouse.y && absmouse.y < pos.y+32) + { + cursor_ground = moves[i]; + found = true; + } + } + } + + if (menu_unit.active && !found) { + int selected = menu_unit.mouse_option(mouse); + if (selected != -1) { + opt = selected; + found = true; + } else { + back = 1; + found = 1; + } + } + + if (menu_day.active && !found) { + int selected = menu_day.mouse_option(mouse); + if (selected != -1) { + opt = selected; + found = true; + } else { + back = 1; + found = 1; + } + } + + for (int i=0; i<entities.size() && !found; i++) { + if (entities[i].done) continue; + if (entities[i].owner != gst.day) continue; + vec2 pos { (float)entities[i].x*32, (float)entities[i].y*32 }; + if (pos.x < absmouse.x && absmouse.x < pos.x+32 + && pos.y < absmouse.y && absmouse.y < pos.y+32) + { + cursor_entity = i; + found = true; + } + } + for (int y=0; y<gr.sizey && !found; y++) { + for (int x=0; x<gr.sizex && !found; x++) { + vec2 pos { (float)x*32, (float)y*32 }; + if (pos.x < absmouse.x && absmouse.x < pos.x+32 + && pos.y < absmouse.y && absmouse.y < pos.y+32) + { + cursor_ground = x+y*gr.sizex; + found = true; + } + } + } + } +}
\ No newline at end of file diff --git a/game/view.h b/game/view.h new file mode 100644 index 0000000..6aa3486 --- /dev/null +++ b/game/view.h @@ -0,0 +1,32 @@ +#ifndef VIEW_H +#define VIEW_H + +#include <vector> +#include <functional> + +#include "gst.h" +#include "menu.h" + +class View { + public: + View (vec2 res) : res(res) {} + + vec2 res; + + int selected_ground {-1}; + int selected_entity {-1}; + int cursor_ground {-1}; + int cursor_entity {-1}; + int back {-1}; + int opt {-1}; + std::vector<int> moves; + std::vector<int> attacks; + std::vector<int> builds; + + Menu_unit menu_unit; + Menu_day menu_day; + + void process (Gst &gst, vec2 cam, vec2 mouse, int *mheld); +}; + +#endif
\ No newline at end of file |