Big refactor, FSM for game state, input event callbacks
This commit is contained in:
parent
328fd40a55
commit
2e299dbcfa
12 changed files with 624 additions and 432 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -32,3 +32,4 @@ build
|
||||||
*.log
|
*.log
|
||||||
imgui.ini
|
imgui.ini
|
||||||
*.sublime*
|
*.sublime*
|
||||||
|
*.dll
|
||||||
|
|
160
src/App.cpp
Normal file
160
src/App.cpp
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
//
|
||||||
|
// Created by Adrian on 2017-09-19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "App.h"
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <ctime>
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "Input.h"
|
||||||
|
#include "Gamestate.h"
|
||||||
|
#include "PlayState.h"
|
||||||
|
|
||||||
|
Uint64 perfFreq;
|
||||||
|
double currTime() {
|
||||||
|
return SDL_GetPerformanceCounter() / (double)perfFreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool App::init() {
|
||||||
|
//setenv("MESA_DEBUG", "", 0);
|
||||||
|
|
||||||
|
Config cfg = Config("dungeon.cfg");
|
||||||
|
cfg.load();
|
||||||
|
|
||||||
|
int windowWidth = cfg.getInt("ResolutionX", 1280);
|
||||||
|
int windowHeight = cfg.getInt("ResolutionY", 720);
|
||||||
|
bool vsync = cfg.getBool("VSync", false);
|
||||||
|
bool wireframe = cfg.getBool("Wireframes", false);
|
||||||
|
|
||||||
|
cfg.save();
|
||||||
|
|
||||||
|
int err = 0;
|
||||||
|
err = SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
|
||||||
|
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
|
||||||
|
if (err != 0) {
|
||||||
|
const char* error = SDL_GetError();
|
||||||
|
fprintf(stderr, error);
|
||||||
|
SDL_Quit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM,"SDL initialized.\n");
|
||||||
|
|
||||||
|
renderer = new Renderer();
|
||||||
|
if (!renderer->Init("Dungeon", windowWidth, windowHeight)) {
|
||||||
|
const char* error = SDL_GetError();
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "%s", error);
|
||||||
|
SDL_ShowSimpleMessageBox(0, "Error", error, nullptr);
|
||||||
|
SDL_Quit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->SetVSyncEnabled(vsync);
|
||||||
|
renderer->SetWireframesEnabled(wireframe);
|
||||||
|
|
||||||
|
input = new Input();
|
||||||
|
srand(static_cast<unsigned int>(time(nullptr)));
|
||||||
|
perfFreq = SDL_GetPerformanceFrequency();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int App::start() {
|
||||||
|
current = new PlayState();
|
||||||
|
current->init(this);
|
||||||
|
current->load();
|
||||||
|
|
||||||
|
double dt = 1.0/30;
|
||||||
|
double currentTime = currTime();
|
||||||
|
double accumulator = dt;
|
||||||
|
|
||||||
|
bool running = true;
|
||||||
|
Gamestate* nextstate = nullptr;
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
double newTime = currTime();
|
||||||
|
double frametime = newTime - currentTime;
|
||||||
|
if (frametime > 1.0/30) {
|
||||||
|
frametime = 1.0/30;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextstate != nullptr) {
|
||||||
|
current->quit();
|
||||||
|
delete current;
|
||||||
|
current = nextstate;
|
||||||
|
current->init(this);
|
||||||
|
current->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTime = newTime;
|
||||||
|
accumulator += frametime;
|
||||||
|
|
||||||
|
SDL_Event ev{};
|
||||||
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
|
renderer->ImguiNewFrame();
|
||||||
|
while (SDL_PollEvent(&ev)) {
|
||||||
|
renderer->ImguiProcessEvents(&ev);
|
||||||
|
switch (ev.type) {
|
||||||
|
case SDL_WINDOWEVENT:
|
||||||
|
switch (ev.window.event) {
|
||||||
|
case SDL_WINDOWEVENT_CLOSE:
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
if (!io.WantCaptureMouse) {
|
||||||
|
InputEvent inputEvent = input->set_mouse_pos(ev.motion.x, ev.motion.y, ev.motion.xrel, ev.motion.yrel);
|
||||||
|
current->inputevent(&inputEvent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
if (!io.WantCaptureMouse) {
|
||||||
|
InputEvent inputEvent = input->set_mouse_button(ev.button.button, ev.button.x, ev.button.y, true);
|
||||||
|
current->inputevent(&inputEvent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEBUTTONUP:
|
||||||
|
if (!io.WantCaptureMouse) {
|
||||||
|
InputEvent inputEvent = input->set_mouse_button(ev.button.button, ev.button.x, ev.button.y, false);
|
||||||
|
current->inputevent(&inputEvent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
if (!io.WantCaptureKeyboard) {
|
||||||
|
InputEvent inputEvent = input->setkey(ev.key.keysym.sym, (SDL_Keymod)ev.key.keysym.mod, true);
|
||||||
|
current->inputevent(&inputEvent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_KEYUP:
|
||||||
|
if (!io.WantCaptureKeyboard){
|
||||||
|
InputEvent inputEvent = input->setkey(ev.key.keysym.sym, (SDL_Keymod)ev.key.keysym.mod, false);
|
||||||
|
current->inputevent(&inputEvent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_QUIT:
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (running && accumulator >= dt) {
|
||||||
|
nextstate = current->update(dt);
|
||||||
|
input->newframe();
|
||||||
|
|
||||||
|
accumulator -= dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->Clear();
|
||||||
|
current->draw(accumulator / dt);
|
||||||
|
renderer->Present();
|
||||||
|
SDL_Delay(1);
|
||||||
|
}
|
||||||
|
delete renderer;
|
||||||
|
SDL_Quit();
|
||||||
|
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Quit.");
|
||||||
|
return 0;
|
||||||
|
}
|
24
src/App.h
Normal file
24
src/App.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
//
|
||||||
|
// Created by Adrian on 2017-09-19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef DUNGEON_APP_H
|
||||||
|
#define DUNGEON_APP_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Gamestate;
|
||||||
|
class Renderer;
|
||||||
|
class Input;
|
||||||
|
|
||||||
|
class App {
|
||||||
|
public:
|
||||||
|
Gamestate* current;
|
||||||
|
Renderer* renderer;
|
||||||
|
Input* input;
|
||||||
|
bool init();
|
||||||
|
int start();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //DUNGEON_APP_H
|
265
src/Game.cpp
265
src/Game.cpp
|
@ -1,265 +0,0 @@
|
||||||
#include "Game.h"
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "Input.h"
|
|
||||||
#include "Renderer.h"
|
|
||||||
|
|
||||||
#include "Tilemap.h"
|
|
||||||
#include "Tileset.h"
|
|
||||||
#include "Hero.h"
|
|
||||||
#include "Goblin.h"
|
|
||||||
#include "Shaman.h"
|
|
||||||
|
|
||||||
const int mapwidth = 32;
|
|
||||||
const std::string map =
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# @ . . . # # # # # # # # . . . . . . . . . . . . . . . . . # #"
|
|
||||||
"# . . . . . . . . # # # # . # # . # # # # # # . # # # # # . # #"
|
|
||||||
"# . . . . # # # . . . . . . # . g . # # # # # . # # # . . g . #"
|
|
||||||
"# . . . . # # # # # # # # . # . . . # # . . . . . . . . . . . #"
|
|
||||||
"# # # . # # # # # # # # # . . . . g # # . # # # . # # . . g . #"
|
|
||||||
"# . . . . . . . . . . . . . # # # # # . . . # # . # # # # # # #"
|
|
||||||
"# . # # # # # # # # . # # . # # # # # . g . # # . # . . g . . #"
|
|
||||||
"# . . . . g # # . . . # . . . # # # # . . . # # . # . . . . . #"
|
|
||||||
"# . . g . . # # . # # # . s . . . # # # # # # # . . . . s . . #"
|
|
||||||
"# . . . . . # # . . . # . . . # . . . . . . . . . # . g . . . #"
|
|
||||||
"# # . # # # # # . # . # # # # # # # # # . # # # # # # # # . # #"
|
|
||||||
"# . . . . . . . . # . . . . . . . . . . . . . . . . . . . . . #"
|
|
||||||
"# . # # # # # # # # # # . # . # # # # # # # # # # . # # # # . #"
|
|
||||||
"# . . . . . . . . . . . . # . # . . . . # . . . . . # # # . . #"
|
|
||||||
"# # # # # # . # # # . # # # . # . . . . # . . . # . # # # . # #"
|
|
||||||
"# . . . . # . # . . . . . # . . . . . . . . . . # . # # . . . #"
|
|
||||||
"# . . . . # . # . . . . . # . # . . . . # # # # # . . . . . . #"
|
|
||||||
"# . . . . . . # . . . . . # . # # # # # # . . . . . # # . . . #"
|
|
||||||
"# . . . . # . # # # # # # # . . . . . . . . # # # # # # # # # #"
|
|
||||||
"# . . . . # . . . . . . . . . # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
|
||||||
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #";
|
|
||||||
|
|
||||||
Renderer* renderer;
|
|
||||||
Input* input;
|
|
||||||
|
|
||||||
Tileset* ascii;
|
|
||||||
Tilemap* tilemap;
|
|
||||||
Hero* hero;
|
|
||||||
|
|
||||||
bool paused;
|
|
||||||
bool debug = false;
|
|
||||||
|
|
||||||
void init() {
|
|
||||||
paused = true;
|
|
||||||
|
|
||||||
if (tilemap != nullptr) {
|
|
||||||
delete tilemap;
|
|
||||||
tilemap = nullptr;
|
|
||||||
hero = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hero != nullptr) {
|
|
||||||
delete hero;
|
|
||||||
hero = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Creating tilemap...\n");
|
|
||||||
tilemap = new Tilemap(32, 32);
|
|
||||||
int y = 0;
|
|
||||||
int x = 0;
|
|
||||||
for (int i = 0; i < map.length(); i++) {
|
|
||||||
|
|
||||||
if (y >= 32) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (x >= mapwidth) {
|
|
||||||
y++;
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
if (map[i] == ' ' || map[i] == '\t' || map[i] == '\n') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map[i] == '@') {
|
|
||||||
hero = new Hero(tilemap, vec2i(x, y));
|
|
||||||
tilemap->AddActor(hero);
|
|
||||||
tilemap->SetTile(x, y, '.');
|
|
||||||
}
|
|
||||||
else if (map[i] == 'g') {
|
|
||||||
tilemap->AddActor(new Goblin(tilemap, vec2i(x, y)));
|
|
||||||
tilemap->SetTile(x, y, '.');
|
|
||||||
}
|
|
||||||
else if (map[i] == 's') {
|
|
||||||
tilemap->AddActor(new Shaman(tilemap, vec2i(x, y)));
|
|
||||||
tilemap->SetTile(x, y, '.');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tilemap->SetTile(x, y, map[i]);
|
|
||||||
}
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Done.\n");
|
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Calculating initial FOV...\n");
|
|
||||||
hero->CalcFOV();
|
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Done.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void load(Renderer* rend, Input* inp) {
|
|
||||||
renderer = rend;
|
|
||||||
input = inp;
|
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Creating ascii tileset...\n");
|
|
||||||
ascii = new Tileset(renderer, "./assets/12x12.bmp", 192, 192, 12, 12);
|
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Created ascii tileset.\n");
|
|
||||||
input->bindkey(SDLK_r, ACTION_RESET);
|
|
||||||
input->bindkey(SDLK_SPACE, ACTION_PAUSE);
|
|
||||||
input->bindkey(SDLK_RETURN, ACTION_STEP);
|
|
||||||
input->bindkey(SDLK_F1, ACTION_TOGGLE_DEBUG);
|
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Keybinds bound.\n");
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
float delay = .5;
|
|
||||||
double timer;
|
|
||||||
|
|
||||||
void update(double dt) {
|
|
||||||
if (input->wasJustPressed(ACTION_TOGGLE_DEBUG)) {
|
|
||||||
debug = !debug;
|
|
||||||
}
|
|
||||||
if (input->wasJustPressed(ACTION_PAUSE)) {
|
|
||||||
paused = !paused;
|
|
||||||
}
|
|
||||||
if (input->wasJustPressed(ACTION_RESET)) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
timer += dt;
|
|
||||||
if (!paused || input->wasJustPressed(ACTION_STEP)) {
|
|
||||||
if (timer >= delay) {
|
|
||||||
timer = 0;
|
|
||||||
|
|
||||||
auto actors = tilemap->GetActorList();
|
|
||||||
for (Actor* var : *actors) {
|
|
||||||
var->Update();
|
|
||||||
}
|
|
||||||
for (int i = (int)actors->size() - 1; i >= 0; i--) {
|
|
||||||
if (!actors->at(i)->alive) {
|
|
||||||
if (actors->at(i) == hero) {
|
|
||||||
hero = nullptr;
|
|
||||||
}
|
|
||||||
delete actors->at(i);
|
|
||||||
actors->erase(actors->begin() + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(double alpha) {
|
|
||||||
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
bool wireframe = renderer->IsWireframesEnabled();
|
|
||||||
ImGui::Checkbox("Wireframes", &wireframe);
|
|
||||||
renderer->SetWireframesEnabled(wireframe);
|
|
||||||
bool vsync = renderer->IsVSyncEnabled();
|
|
||||||
ImGui::Checkbox("VSync", &vsync);
|
|
||||||
renderer->SetVSyncEnabled(vsync);
|
|
||||||
|
|
||||||
ImGui::BeginMainMenuBar();
|
|
||||||
|
|
||||||
if (ImGui::BeginMenu("File")) {
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Edit")) {
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginMenu("View")) {
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndMainMenuBar();
|
|
||||||
|
|
||||||
ImGui::SliderFloat("turndelay", &delay, .01f, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (int x = 0; x < 32; x++) {
|
|
||||||
for (int y = 0; y < 32; y++) {
|
|
||||||
if (hero == nullptr || hero->HasSeen(x, y)) {
|
|
||||||
renderer->SetColor(1, 1, 1, 1);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(tilemap->GetTile(x, y)), x * 12, y * 12);
|
|
||||||
if (hero != nullptr && !hero->CanSee(x, y)) {
|
|
||||||
renderer->SetColor(0, 0, 0, .5f);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), x * 12, y * 12);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto actors = tilemap->GetActorList();
|
|
||||||
for (Actor* var : *actors) {
|
|
||||||
vec2i pos = var->getPosition();
|
|
||||||
if (hero == nullptr || hero->CanSee(pos.x, pos.y)) {
|
|
||||||
renderer->SetColor(0, 0, 0, 255);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), pos.x * 12, pos.y * 12);
|
|
||||||
|
|
||||||
int sprite;
|
|
||||||
switch (var->Type()) {
|
|
||||||
case ACT_HERO:
|
|
||||||
renderer->SetColor(.2f, .6f, 1, 1);
|
|
||||||
sprite = '@';
|
|
||||||
break;
|
|
||||||
case ACT_GOBLIN:
|
|
||||||
renderer->SetColor(.6f, 1, .2f, 1);
|
|
||||||
sprite = 'g';
|
|
||||||
break;
|
|
||||||
case ACT_SHAMAN:
|
|
||||||
renderer->SetColor(.2f, 1, .6f, 1);
|
|
||||||
sprite = 's';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
renderer->SetColor(1, 1, 1, 1);
|
|
||||||
sprite = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(sprite), pos.x * 12, pos.y * 12);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hero != nullptr) {
|
|
||||||
renderer->SetColor(155, 5, 5, 255);
|
|
||||||
for (int i = 0; i < hero->health; i++) {
|
|
||||||
renderer->SetColor(0, 0, 0, 255);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), i * 12, 0);
|
|
||||||
renderer->SetColor(255, 0, 0, 255);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(3), i * 12, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (paused) {
|
|
||||||
renderer->SetColor(255, 0, 0, 255);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), 12 * 0, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), 12 * 1, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), 12 * 2, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), 12 * 3, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), 12 * 4, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), 12 * 5, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), 12 * 6, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite(219), 12 * 7, 0);
|
|
||||||
renderer->SetColor(0, 0, 0, 255);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite('-'), 12 * 0, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite('P'), 12 * 1, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite('A'), 12 * 2, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite('U'), 12 * 3, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite('S'), 12 * 4, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite('E'), 12 * 5, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite('D'), 12 * 6, 0);
|
|
||||||
renderer->DrawSprite(ascii->GetSprite('-'), 12 * 7, 0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
class Renderer;
|
|
||||||
class Input;
|
|
||||||
|
|
||||||
void load(Renderer* rend, Input* inp);
|
|
||||||
void update(double dt);
|
|
||||||
void draw(double alpha);
|
|
10
src/Gamestate.cpp
Normal file
10
src/Gamestate.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//
|
||||||
|
// Created by Adrian on 2017-09-19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Gamestate.h"
|
||||||
|
#include "App.h"
|
||||||
|
|
||||||
|
void Gamestate::init(App *app) {
|
||||||
|
this->app = app;
|
||||||
|
}
|
24
src/Gamestate.h
Normal file
24
src/Gamestate.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
//
|
||||||
|
// Created by Adrian on 2017-09-19.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef DUNGEON_GAMESTATE_H
|
||||||
|
#define DUNGEON_GAMESTATE_H
|
||||||
|
|
||||||
|
class App;
|
||||||
|
struct InputEvent;
|
||||||
|
|
||||||
|
class Gamestate {
|
||||||
|
protected:
|
||||||
|
App* app;
|
||||||
|
public:
|
||||||
|
void init(App* app);
|
||||||
|
virtual void load() = 0;
|
||||||
|
virtual Gamestate* update(double delta) = 0;
|
||||||
|
virtual void draw(double delta) = 0;
|
||||||
|
virtual void quit() = 0;
|
||||||
|
virtual void inputevent(InputEvent* event) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //DUNGEON_GAMESTATE_H
|
|
@ -16,17 +16,21 @@ Input::~Input()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::newframe()
|
void Input::newframe() {
|
||||||
{
|
for(int i = 0; i < INPUTACTION_END; i++) {
|
||||||
for(int i = 0; i < INPUTACTION_END; i++)
|
|
||||||
{
|
|
||||||
justpressed[i] = false;
|
justpressed[i] = false;
|
||||||
justreleased[i] = false;
|
justreleased[i] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::setkey(SDL_Keycode key, SDL_Keymod mod, bool pressed)
|
InputEvent Input::setkey(SDL_Keycode key, SDL_Keymod mod, bool pressed)
|
||||||
{
|
{
|
||||||
|
InputEvent event;
|
||||||
|
event.type = INPUT_KEY_EVENT;
|
||||||
|
event.key_press_event.key = key;
|
||||||
|
event.key_press_event.mod = mod;
|
||||||
|
event.pressed = pressed;
|
||||||
|
|
||||||
if (mod & KMOD_NUM) { // let's ignore numlock
|
if (mod & KMOD_NUM) { // let's ignore numlock
|
||||||
mod = (SDL_Keymod)(mod ^ KMOD_NUM);
|
mod = (SDL_Keymod)(mod ^ KMOD_NUM);
|
||||||
}
|
}
|
||||||
|
@ -37,45 +41,66 @@ void Input::setkey(SDL_Keycode key, SDL_Keymod mod, bool pressed)
|
||||||
if (binds.find(bind) != binds.end())
|
if (binds.find(bind) != binds.end())
|
||||||
{
|
{
|
||||||
InputAction action = binds[bind];
|
InputAction action = binds[bind];
|
||||||
|
event.action = action;
|
||||||
if (ispressed[action] != pressed) // Ignore keypress/release if it's already pressed/released, this disables repeats.
|
event.key_press_event.echo = ispressed[action] != pressed;
|
||||||
{
|
if (event.key_press_event.echo) { // Ignore keypress/release if it's already pressed/released, this disables repeats.
|
||||||
ispressed[action] = pressed;
|
ispressed[action] = pressed;
|
||||||
if (pressed)
|
if (pressed) {
|
||||||
{
|
|
||||||
justpressed[action] = true;
|
justpressed[action] = true;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
justreleased[action] = true;
|
justreleased[action] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::bindkey(SDL_Keycode key, InputAction action, SDL_Keymod mod)
|
void Input::bindkey(SDL_Keycode key, InputAction action, SDL_Keymod mod) {
|
||||||
{
|
|
||||||
Bind bind = { key, mod };
|
Bind bind = { key, mod };
|
||||||
binds[bind] = action;
|
binds[bind] = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::unbindkey(SDL_Keycode key, SDL_Keymod mod)
|
void Input::unbindkey(SDL_Keycode key, SDL_Keymod mod) {
|
||||||
{
|
|
||||||
Bind bind = { key, mod };
|
Bind bind = { key, mod };
|
||||||
binds.erase(bind);
|
binds.erase(bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Input::isPressed(InputAction action)
|
bool Input::isPressed(InputAction action) {
|
||||||
{
|
|
||||||
return ispressed[action];
|
return ispressed[action];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Input::wasJustPressed(InputAction action)
|
bool Input::wasJustPressed(InputAction action) {
|
||||||
{
|
|
||||||
return justpressed[action];
|
return justpressed[action];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Input::wasJustReleased(InputAction action)
|
bool Input::wasJustReleased(InputAction action) {
|
||||||
{
|
|
||||||
return justreleased[action];
|
return justreleased[action];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputEvent Input::set_mouse_pos(int x, int y, int dx, int dy) {
|
||||||
|
mouse_x = x;
|
||||||
|
mouse_y = y;
|
||||||
|
|
||||||
|
InputEvent event;
|
||||||
|
event.type = INPUT_MOUSE_MOVE_EVENT;
|
||||||
|
event.mouse_move_event.x = x;
|
||||||
|
event.mouse_move_event.y = y;
|
||||||
|
event.mouse_move_event.dx = dx;
|
||||||
|
event.mouse_move_event.dy = dy;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputEvent Input::set_mouse_button(int button, int x, int y, bool pressed) {
|
||||||
|
mouse_x = x;
|
||||||
|
mouse_y = y;
|
||||||
|
|
||||||
|
InputEvent event;
|
||||||
|
event.type = INPUT_MOUSE_CLICK_EVENT;
|
||||||
|
event.action = ACTION_NONE;
|
||||||
|
event.pressed = pressed;
|
||||||
|
event.mouse_click_event.button = button;
|
||||||
|
event.mouse_click_event.x = x;
|
||||||
|
event.mouse_click_event.y = y;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
51
src/Input.h
51
src/Input.h
|
@ -5,10 +5,17 @@
|
||||||
|
|
||||||
enum InputAction {
|
enum InputAction {
|
||||||
ACTION_NONE,
|
ACTION_NONE,
|
||||||
ACTION_PAUSE,
|
ACTION_ESCAPE_MENU,
|
||||||
ACTION_RESET,
|
ACTION_RESET,
|
||||||
ACTION_STEP,
|
|
||||||
ACTION_TOGGLE_DEBUG,
|
ACTION_TOGGLE_DEBUG,
|
||||||
|
ACTION_MOVE_NORTH,
|
||||||
|
ACTION_MOVE_NORTHWEST,
|
||||||
|
ACTION_MOVE_NORTHEAST,
|
||||||
|
ACTION_MOVE_WEST,
|
||||||
|
ACTION_MOVE_EAST,
|
||||||
|
ACTION_MOVE_SOUTH,
|
||||||
|
ACTION_MOVE_SOUTHWEST,
|
||||||
|
ACTION_MOVE_SOUTHEAST,
|
||||||
INPUTACTION_END // Used to get the length of the enum. Must be the final entry.
|
INPUTACTION_END // Used to get the length of the enum. Must be the final entry.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,17 +31,55 @@ struct Bind {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum InputEventType {
|
||||||
|
INPUT_MOUSE_MOVE_EVENT,
|
||||||
|
INPUT_MOUSE_CLICK_EVENT,
|
||||||
|
INPUT_KEY_EVENT,
|
||||||
|
};
|
||||||
|
struct InputEvent {
|
||||||
|
InputEventType type;
|
||||||
|
InputAction action;
|
||||||
|
bool pressed;
|
||||||
|
|
||||||
|
struct MouseMoveEvent { // mouse click;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int dx;
|
||||||
|
int dy;
|
||||||
|
};
|
||||||
|
struct MouseClickEvent { // mouse click;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int button;
|
||||||
|
};
|
||||||
|
struct KeyPressEvent { // key
|
||||||
|
SDL_Keycode key;
|
||||||
|
SDL_Keymod mod;
|
||||||
|
bool echo;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
MouseMoveEvent mouse_move_event;
|
||||||
|
MouseClickEvent mouse_click_event;
|
||||||
|
KeyPressEvent key_press_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class Input
|
class Input
|
||||||
{
|
{
|
||||||
std::map<Bind, InputAction> binds;
|
std::map<Bind, InputAction> binds;
|
||||||
bool ispressed[INPUTACTION_END];
|
bool ispressed[INPUTACTION_END];
|
||||||
bool justpressed[INPUTACTION_END];
|
bool justpressed[INPUTACTION_END];
|
||||||
bool justreleased[INPUTACTION_END];
|
bool justreleased[INPUTACTION_END];
|
||||||
|
int mouse_x, mouse_y;
|
||||||
public:
|
public:
|
||||||
Input();
|
Input();
|
||||||
~Input();
|
~Input();
|
||||||
void newframe();
|
void newframe();
|
||||||
void setkey(SDL_Keycode key, SDL_Keymod mod, bool pressed);
|
InputEvent setkey(SDL_Keycode key, SDL_Keymod mod, bool pressed);
|
||||||
|
InputEvent set_mouse_pos(int x, int y, int dx, int dy);
|
||||||
|
InputEvent set_mouse_button(int button, int x, int y, bool pressed);
|
||||||
void bindkey(SDL_Keycode key, InputAction action, SDL_Keymod mod = KMOD_NONE);
|
void bindkey(SDL_Keycode key, InputAction action, SDL_Keymod mod = KMOD_NONE);
|
||||||
void unbindkey(SDL_Keycode key, SDL_Keymod mod);
|
void unbindkey(SDL_Keycode key, SDL_Keymod mod);
|
||||||
bool isPressed(InputAction action);
|
bool isPressed(InputAction action);
|
||||||
|
|
141
src/Main.cpp
141
src/Main.cpp
|
@ -1,139 +1,12 @@
|
||||||
//#define _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH
|
|
||||||
//#define _ITERATOR_DEBUG_LEVEL 0
|
|
||||||
|
|
||||||
|
#include "App.h"
|
||||||
|
|
||||||
#include <SDL.h>
|
//#undef main
|
||||||
#include <stdio.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <string>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include "Input.h"
|
|
||||||
#include "Config.h"
|
|
||||||
#include "Game.h"
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
|
|
||||||
Uint64 perfFreq;
|
|
||||||
|
|
||||||
double currTime();
|
|
||||||
|
|
||||||
#undef main
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
Renderer* renderer;
|
App app{};
|
||||||
Input* input;
|
int err = 1;
|
||||||
|
if (app.init()) {
|
||||||
//setenv("MESA_DEBUG", "", 0);
|
err = app.start();
|
||||||
|
|
||||||
Config cfg = Config("dungeon.cfg");
|
|
||||||
cfg.load();
|
|
||||||
|
|
||||||
int windowWidth = cfg.getInt("ResolutionX", 1280);
|
|
||||||
int windowHeight = cfg.getInt("ResolutionY", 720);
|
|
||||||
bool vsync = cfg.getBool("VSync", false);
|
|
||||||
bool wireframe = cfg.getBool("Wireframes", false);
|
|
||||||
|
|
||||||
cfg.save();
|
|
||||||
|
|
||||||
int err = 0;
|
|
||||||
err = SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
|
|
||||||
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
|
|
||||||
if (err != 0) {
|
|
||||||
const char* error = SDL_GetError();
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "%s", error);
|
|
||||||
SDL_Quit();
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM,"SDL initialized.\n");
|
return err;
|
||||||
|
|
||||||
renderer = new Renderer();
|
|
||||||
if (!renderer->Init("Dungeon", windowWidth, windowHeight)) {
|
|
||||||
const char* error = SDL_GetError();
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "%s", error);
|
|
||||||
SDL_ShowSimpleMessageBox(0, "Error", error, nullptr);
|
|
||||||
SDL_Quit();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer->SetVSyncEnabled(vsync);
|
|
||||||
renderer->SetWireframesEnabled(wireframe);
|
|
||||||
|
|
||||||
input = new Input();
|
|
||||||
srand(time(nullptr));
|
|
||||||
load(renderer, input);
|
|
||||||
|
|
||||||
perfFreq = SDL_GetPerformanceFrequency();
|
|
||||||
|
|
||||||
double dt = 1.0/30;
|
|
||||||
double currentTime = currTime();
|
|
||||||
double accumulator = dt;
|
|
||||||
|
|
||||||
int currentframe = 0;
|
|
||||||
bool running = true;
|
|
||||||
|
|
||||||
while (running) {
|
|
||||||
double newTime = currTime();
|
|
||||||
double frametime = newTime - currentTime;
|
|
||||||
if (frametime > 1.0/30) {
|
|
||||||
frametime = 1.0/30;
|
|
||||||
}
|
|
||||||
currentTime = newTime;
|
|
||||||
|
|
||||||
accumulator += frametime;
|
|
||||||
|
|
||||||
//dt = (SDL_GetTicks() - currentframe) * 0.001f;
|
|
||||||
currentframe = SDL_GetTicks();
|
|
||||||
|
|
||||||
SDL_Event ev;
|
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
|
||||||
renderer->ImguiNewFrame();
|
|
||||||
while (SDL_PollEvent(&ev)) {
|
|
||||||
renderer->ImguiProcessEvents(&ev);
|
|
||||||
switch (ev.type) {
|
|
||||||
case SDL_WINDOWEVENT:
|
|
||||||
switch (ev.window.event) {
|
|
||||||
case SDL_WINDOWEVENT_CLOSE:
|
|
||||||
running = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SDL_KEYDOWN:
|
|
||||||
if (!io.WantCaptureKeyboard)
|
|
||||||
input->setkey(ev.key.keysym.sym, (SDL_Keymod)ev.key.keysym.mod, true);
|
|
||||||
break;
|
|
||||||
case SDL_KEYUP:
|
|
||||||
if (!io.WantCaptureKeyboard)
|
|
||||||
input->setkey(ev.key.keysym.sym, (SDL_Keymod)ev.key.keysym.mod, false);
|
|
||||||
break;
|
|
||||||
case SDL_QUIT:
|
|
||||||
running = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (running && accumulator >= dt) {
|
|
||||||
update(dt);
|
|
||||||
input->newframe();
|
|
||||||
|
|
||||||
accumulator -= dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer->Clear();
|
|
||||||
draw(accumulator / dt);
|
|
||||||
renderer->Present();
|
|
||||||
SDL_Delay(1);
|
|
||||||
}
|
|
||||||
delete renderer;
|
|
||||||
SDL_Quit();
|
|
||||||
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Quit.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double currTime() {
|
|
||||||
return SDL_GetPerformanceCounter() / (double)perfFreq;
|
|
||||||
}
|
}
|
||||||
|
|
268
src/PlayState.cpp
Normal file
268
src/PlayState.cpp
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
//
|
||||||
|
// Created by Adrian on 2017-09-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "PlayState.h"
|
||||||
|
#include "Input.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
#include "Actor.h"
|
||||||
|
#include "App.h"
|
||||||
|
#include "Tilemap.h"
|
||||||
|
#include "Tileset.h"
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "Hero.h"
|
||||||
|
#include "Goblin.h"
|
||||||
|
#include "Shaman.h"
|
||||||
|
|
||||||
|
const int mapwidth = 32;
|
||||||
|
const std::string map =
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# @ . . . # # # # # # # # . . . . . . . . . . . . . . . . . # #"
|
||||||
|
"# . . . . . . . . # # # # . # # . # # # # # # . # # # # # . # #"
|
||||||
|
"# . . . . # # # . . . . . . # . g . # # # # # . # # # . . g . #"
|
||||||
|
"# . . . . # # # # # # # # . # . . . # # . . . . . . . . . . . #"
|
||||||
|
"# # # . # # # # # # # # # . . . . g # # . # # # . # # . . g . #"
|
||||||
|
"# . . . . . . . . . . . . . # # # # # . . . # # . # # # # # # #"
|
||||||
|
"# . # # # # # # # # . # # . # # # # # . g . # # . # . . g . . #"
|
||||||
|
"# . . . . g # # . . . # . . . # # # # . . . # # . # . . . . . #"
|
||||||
|
"# . . g . . # # . # # # . s . . . # # # # # # # . . . . s . . #"
|
||||||
|
"# . . . . . # # . . . # . . . # . . . . . . . . . # . g . . . #"
|
||||||
|
"# # . # # # # # . # . # # # # # # # # # . # # # # # # # # . # #"
|
||||||
|
"# . . . . . . . . # . . . . . . . . . . . . . . . . . . . . . #"
|
||||||
|
"# . # # # # # # # # # # . # . # # # # # # # # # # . # # # # . #"
|
||||||
|
"# . . . . . . . . . . . . # . # . . . . # . . . . . # # # . . #"
|
||||||
|
"# # # # # # . # # # . # # # . # . . . . # . . . # . # # # . # #"
|
||||||
|
"# . . . . # . # . . . . . # . . . . . . . . . . # . # # . . . #"
|
||||||
|
"# . . . . # . # . . . . . # . # . . . . # # # # # . . . . . . #"
|
||||||
|
"# . . . . . . # . . . . . # . # # # # # # . . . . . # # . . . #"
|
||||||
|
"# . . . . # . # # # # # # # . . . . . . . . # # # # # # # # # #"
|
||||||
|
"# . . . . # . . . . . . . . . # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #"
|
||||||
|
"# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #";
|
||||||
|
|
||||||
|
void PlayState::load() {
|
||||||
|
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Creating ascii tileset...\n");
|
||||||
|
ascii = new Tileset(app->renderer, "./assets/12x12.bmp", 192, 192, 12, 12);
|
||||||
|
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Created ascii tileset.\n");
|
||||||
|
|
||||||
|
app->input->bindkey(SDLK_ESCAPE, ACTION_ESCAPE_MENU);
|
||||||
|
app->input->bindkey(SDLK_KP_8, ACTION_MOVE_NORTH);
|
||||||
|
app->input->bindkey(SDLK_KP_7, ACTION_MOVE_NORTHWEST);
|
||||||
|
app->input->bindkey(SDLK_KP_9, ACTION_MOVE_NORTHEAST);
|
||||||
|
app->input->bindkey(SDLK_KP_4, ACTION_MOVE_WEST);
|
||||||
|
app->input->bindkey(SDLK_KP_6, ACTION_MOVE_EAST);
|
||||||
|
app->input->bindkey(SDLK_KP_2, ACTION_MOVE_SOUTH);
|
||||||
|
app->input->bindkey(SDLK_KP_1, ACTION_MOVE_SOUTHWEST);
|
||||||
|
app->input->bindkey(SDLK_KP_3, ACTION_MOVE_SOUTHEAST);
|
||||||
|
app->input->bindkey(SDLK_F1, ACTION_TOGGLE_DEBUG);
|
||||||
|
|
||||||
|
app->input->bindkey(SDLK_r, ACTION_RESET);
|
||||||
|
|
||||||
|
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Keybinds bound.\n");
|
||||||
|
new_game();
|
||||||
|
}
|
||||||
|
|
||||||
|
Gamestate *PlayState::update(double delta) {
|
||||||
|
timer += delta;
|
||||||
|
if (!paused) {
|
||||||
|
if (timer >= delay) {
|
||||||
|
timer = 0;
|
||||||
|
|
||||||
|
auto actors = tilemap->GetActorList();
|
||||||
|
for (Actor* var : *actors) {
|
||||||
|
var->Update();
|
||||||
|
}
|
||||||
|
for (int i = (int)actors->size() - 1; i >= 0; i--) {
|
||||||
|
if (!actors->at(i)->alive) {
|
||||||
|
if (actors->at(i) == hero) {
|
||||||
|
hero = nullptr;
|
||||||
|
}
|
||||||
|
delete actors->at(i);
|
||||||
|
actors->erase(actors->begin() + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayState::draw(double delta) {
|
||||||
|
if (debug) {
|
||||||
|
bool wireframe = app->renderer->IsWireframesEnabled();
|
||||||
|
ImGui::Checkbox("Wireframes", &wireframe);
|
||||||
|
app->renderer->SetWireframesEnabled(wireframe);
|
||||||
|
bool vsync = app->renderer->IsVSyncEnabled();
|
||||||
|
ImGui::Checkbox("VSync", &vsync);
|
||||||
|
app->renderer->SetVSyncEnabled(vsync);
|
||||||
|
|
||||||
|
ImGui::BeginMainMenuBar();
|
||||||
|
|
||||||
|
if (ImGui::BeginMenu("File")) {
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginMenu("Edit")) {
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginMenu("View")) {
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndMainMenuBar();
|
||||||
|
|
||||||
|
ImGui::SliderFloat("turndelay", &delay, .01f, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int x = 0; x < 32; x++) {
|
||||||
|
for (int y = 0; y < 32; y++) {
|
||||||
|
if (hero == nullptr || hero->HasSeen(x, y)) {
|
||||||
|
app->renderer->SetColor(1, 1, 1, 1);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(tilemap->GetTile(x, y)), x * 12, y * 12);
|
||||||
|
if (hero != nullptr && !hero->CanSee(x, y)) {
|
||||||
|
app->renderer->SetColor(0, 0, 0, .5f);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), x * 12, y * 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto actors = tilemap->GetActorList();
|
||||||
|
for (Actor* var : *actors) {
|
||||||
|
vec2i pos = var->getPosition();
|
||||||
|
if (hero == nullptr || hero->CanSee(pos.x, pos.y)) {
|
||||||
|
app->renderer->SetColor(0, 0, 0, 255);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), pos.x * 12, pos.y * 12);
|
||||||
|
|
||||||
|
int sprite;
|
||||||
|
switch (var->Type()) {
|
||||||
|
case ACT_HERO:
|
||||||
|
app->renderer->SetColor(.2f, .6f, 1, 1);
|
||||||
|
sprite = '@';
|
||||||
|
break;
|
||||||
|
case ACT_GOBLIN:
|
||||||
|
app->renderer->SetColor(.6f, 1, .2f, 1);
|
||||||
|
sprite = 'g';
|
||||||
|
break;
|
||||||
|
case ACT_SHAMAN:
|
||||||
|
app->renderer->SetColor(.2f, 1, .6f, 1);
|
||||||
|
sprite = 's';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
app->renderer->SetColor(1, 1, 1, 1);
|
||||||
|
sprite = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(sprite), pos.x * 12, pos.y * 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hero != nullptr) {
|
||||||
|
app->renderer->SetColor(155, 5, 5, 255);
|
||||||
|
for (int i = 0; i < hero->health; i++) {
|
||||||
|
app->renderer->SetColor(0, 0, 0, 255);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), i * 12, 0);
|
||||||
|
app->renderer->SetColor(255, 0, 0, 255);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(3), i * 12, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (paused) {
|
||||||
|
app->renderer->SetColor(255, 0, 0, 255);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), 12 * 0, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), 12 * 1, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), 12 * 2, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), 12 * 3, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), 12 * 4, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), 12 * 5, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), 12 * 6, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite(219), 12 * 7, 0);
|
||||||
|
app->renderer->SetColor(0, 0, 0, 255);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite('-'), 12 * 0, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite('P'), 12 * 1, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite('A'), 12 * 2, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite('U'), 12 * 3, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite('S'), 12 * 4, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite('E'), 12 * 5, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite('D'), 12 * 6, 0);
|
||||||
|
app->renderer->DrawSprite(ascii->GetSprite('-'), 12 * 7, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayState::quit() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayState::inputevent(InputEvent *event) {
|
||||||
|
if (event->pressed) {
|
||||||
|
switch (event->action) {
|
||||||
|
case ACTION_TOGGLE_DEBUG: debug = !debug; break;
|
||||||
|
case ACTION_ESCAPE_MENU: paused = !paused; break;
|
||||||
|
case ACTION_RESET: new_game(); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayState::new_game() {
|
||||||
|
paused = true;
|
||||||
|
|
||||||
|
if (tilemap != nullptr) {
|
||||||
|
delete tilemap;
|
||||||
|
tilemap = nullptr;
|
||||||
|
hero = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hero != nullptr) {
|
||||||
|
delete hero;
|
||||||
|
hero = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Creating tilemap...\n");
|
||||||
|
tilemap = new Tilemap(32, 32);
|
||||||
|
int y = 0;
|
||||||
|
int x = 0;
|
||||||
|
for (int i = 0; i < map.length(); i++) {
|
||||||
|
|
||||||
|
if (y >= 32) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (x >= mapwidth) {
|
||||||
|
y++;
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
if (map[i] == ' ' || map[i] == '\t' || map[i] == '\n') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map[i] == '@') {
|
||||||
|
hero = new Hero(tilemap, vec2i(x, y));
|
||||||
|
tilemap->AddActor(hero);
|
||||||
|
tilemap->SetTile(x, y, '.');
|
||||||
|
}
|
||||||
|
else if (map[i] == 'g') {
|
||||||
|
tilemap->AddActor(new Goblin(tilemap, vec2i(x, y)));
|
||||||
|
tilemap->SetTile(x, y, '.');
|
||||||
|
}
|
||||||
|
else if (map[i] == 's') {
|
||||||
|
tilemap->AddActor(new Shaman(tilemap, vec2i(x, y)));
|
||||||
|
tilemap->SetTile(x, y, '.');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tilemap->SetTile(x, y, map[i]);
|
||||||
|
}
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Done.\n");
|
||||||
|
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Calculating initial FOV...\n");
|
||||||
|
hero->CalcFOV();
|
||||||
|
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Done.\n");
|
||||||
|
}
|
35
src/PlayState.h
Normal file
35
src/PlayState.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// Created by Adrian on 2017-09-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef DUNGEON_PLAYSTATE_H
|
||||||
|
#define DUNGEON_PLAYSTATE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "Gamestate.h"
|
||||||
|
|
||||||
|
class Tileset;
|
||||||
|
class Tilemap;
|
||||||
|
class Actor;
|
||||||
|
|
||||||
|
class PlayState : public Gamestate {
|
||||||
|
Tileset* ascii;
|
||||||
|
Tilemap* tilemap;
|
||||||
|
Actor * hero;
|
||||||
|
|
||||||
|
float delay = .5;
|
||||||
|
double timer;
|
||||||
|
|
||||||
|
bool paused;
|
||||||
|
bool debug;
|
||||||
|
public:
|
||||||
|
void new_game();
|
||||||
|
void load() override;
|
||||||
|
Gamestate* update(double delta) override;
|
||||||
|
void draw(double delta) override;
|
||||||
|
void quit() override;
|
||||||
|
void inputevent(InputEvent* event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //DUNGEON_PLAYSTATE_H
|
Loading…
Add table
Reference in a new issue