Reworked gamestates to reset NF objects when exiting states; Intro state + fading is now based on delta time

This commit is contained in:
Grayson Riffe (Desktop) 2021-09-08 02:09:20 -05:00
parent 6e3a576fef
commit 2d3b3653ff
29 changed files with 260 additions and 108 deletions

View File

@ -230,6 +230,7 @@
<ClInclude Include="src\include\Input.h" /> <ClInclude Include="src\include\Input.h" />
<ClInclude Include="src\include\Light.h" /> <ClInclude Include="src\include\Light.h" />
<ClInclude Include="src\include\Model.h" /> <ClInclude Include="src\include\Model.h" />
<ClInclude Include="src\include\NFObject.h" />
<ClInclude Include="src\include\NothinFancy.h" /> <ClInclude Include="src\include\NothinFancy.h" />
<ClInclude Include="src\include\Renderer.h" /> <ClInclude Include="src\include\Renderer.h" />
<ClInclude Include="src\include\Shader.h" /> <ClInclude Include="src\include\Shader.h" />

View File

@ -146,6 +146,9 @@
<ClInclude Include="src\include\Cubemap.h"> <ClInclude Include="src\include\Cubemap.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\include\NFObject.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Natvis Include="NatvisFile.natvis" /> <Natvis Include="NatvisFile.natvis" />

View File

@ -18,6 +18,9 @@ namespace nf {
Log("Creating NF application"); Log("Creating NF application");
Log("Width: " + std::to_string(m_currentConfig.width) + ", Height: " + std::to_string(m_currentConfig.height) + ", Fullscreen: " + std::to_string(m_currentConfig.fullscreen) + ", Title: " + m_currentConfig.title); Log("Width: " + std::to_string(m_currentConfig.width) + ", Height: " + std::to_string(m_currentConfig.height) + ", Fullscreen: " + std::to_string(m_currentConfig.fullscreen) + ", Title: " + m_currentConfig.title);
if (getApp() != nullptr)
Error("Cannot create two NF Application objects!");
setApp(this);
m_hInst = GetModuleHandle(NULL); m_hInst = GetModuleHandle(NULL);
registerWindowClass(); registerWindowClass();
RECT windowSize = getWindowRect(); RECT windowSize = getWindowRect();
@ -97,6 +100,10 @@ namespace nf {
m_nextState = stateName; m_nextState = stateName;
} }
Gamestate* Application::getCurrentState() {
return m_currentState;
}
void Application::showWindow(bool show) { void Application::showWindow(bool show) {
if (show) if (show)
ShowWindow(m_window, SW_SHOW); ShowWindow(m_window, SW_SHOW);
@ -152,6 +159,10 @@ namespace nf {
m_mouseDiffY = 0; m_mouseDiffY = 0;
} }
Application* Application::getApp() {
return currentApp;
}
void Application::registerWindowClass() { void Application::registerWindowClass() {
if (!FindWindow(L"NFClass", NULL)) { if (!FindWindow(L"NFClass", NULL)) {
m_wclassName = L"NFClass"; m_wclassName = L"NFClass";
@ -249,43 +260,41 @@ namespace nf {
} }
void Application::runMainGameThread() { void Application::runMainGameThread() {
m_sIntro = new IntroGamestate;
m_currentState = m_sIntro;
m_renderer = new Renderer(this); m_renderer = new Renderer(this);
startIntroState(); m_currentState->setup(this);
m_currentState->onEnter();
m_renderer->setFade(true, false, true); m_renderer->setFade(true, false, true);
std::chrono::steady_clock::time_point currentTime = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point currentFrame = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point lastFrame = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point lastFrame = std::chrono::steady_clock::now();
while (m_running) { while (m_running) {
currentTime = std::chrono::steady_clock::now(); currentFrame = std::chrono::steady_clock::now();
m_deltaTime = std::chrono::duration<double>(currentTime - lastFrame).count(); m_deltaTime = std::chrono::duration<double>(currentFrame - lastFrame).count();
if (m_deltaTime >= m_minFrametime) { if (m_deltaTime >= m_minFrametime) {
lastFrame = std::chrono::steady_clock::now(); lastFrame = std::chrono::steady_clock::now();
m_currentState->update(m_deltaTime); m_currentState->update(m_deltaTime);
m_currentState->render(*m_renderer); m_currentState->render(*m_renderer);
m_renderer->doFrame(m_currentState->getCamera()); m_renderer->doFrame(m_currentState->getCamera(), m_deltaTime);
m_frames++;
if (m_stateChange) if (m_stateChange)
doStateChange(); doStateChange();
} }
m_fpsClock2 = std::chrono::steady_clock::now(); m_fpsClock2 = std::chrono::steady_clock::now();
m_fpsDuration = m_fpsClock2 - m_fpsClock1; m_fpsDuration = m_fpsClock2 - m_fpsClock1;
if (m_fpsDuration.count() >= 1.0) { if (m_fpsDuration.count() >= 0.2) {
m_FPS = m_frames; m_FPS = (int)(1.0 / m_deltaTime);
m_frames = 0; static int i = 0;
Log("FPS: " + std::to_string(m_FPS)); i++;
if (i % 5 == 0)
Log("FPS: " + std::to_string(m_FPS));
m_fpsClock1 = std::chrono::steady_clock::now(); m_fpsClock1 = std::chrono::steady_clock::now();
} }
} }
m_currentState->onExit(); m_currentState->onExit();
m_currentState->cleanup();
delete m_renderer; delete m_renderer;
} }
void Application::startIntroState() {
m_sIntro = new IntroGamestate;
m_sIntro->setup(this);
m_currentState = m_sIntro;
m_currentState->onEnter();
}
void Application::doStateChange() { void Application::doStateChange() {
static bool once = true; static bool once = true;
if (once) { if (once) {
@ -295,6 +304,7 @@ namespace nf {
if (m_renderer->isFadeOutComplete()) { if (m_renderer->isFadeOutComplete()) {
m_currentState->onExit(); m_currentState->onExit();
m_currentState->cleanup();
m_currentState = m_states[m_nextState]; m_currentState = m_states[m_nextState];
m_currentState->setup(this); m_currentState->setup(this);
m_currentState->onEnter(); m_currentState->onEnter();
@ -304,6 +314,10 @@ namespace nf {
} }
} }
void Application::setApp(Application* app) {
currentApp = app;
}
LRESULT CALLBACK Application::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT CALLBACK Application::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
Application* app = (Application*)GetProp(hWnd, L"App"); Application* app = (Application*)GetProp(hWnd, L"App");
switch (uMsg) { switch (uMsg) {
@ -358,4 +372,6 @@ namespace nf {
delete curr; delete curr;
} }
} }
Application* Application::currentApp = nullptr;
} }

View File

@ -1,5 +1,6 @@
#include "Assets.h" #include "Assets.h"
#include "Application.h"
#include "Model.h" #include "Model.h"
#include "Utility.h" #include "Utility.h"
@ -40,6 +41,7 @@ namespace nf {
void AssetPack::load(const char* packName) { void AssetPack::load(const char* packName) {
std::string path = "assets/" + (std::string)packName; std::string path = "assets/" + (std::string)packName;
std::string packContents = readFile(path); std::string packContents = readFile(path);
std::unordered_map<std::string, ACubemap*> cubemaps;
unsigned int cubemapCount = 0; unsigned int cubemapCount = 0;
while (packContents.size()) { while (packContents.size()) {
unsigned int startingPos = packContents.find_first_of("#NFASSET ") + 9; unsigned int startingPos = packContents.find_first_of("#NFASSET ") + 9;
@ -68,12 +70,13 @@ namespace nf {
geometry->data[assetSize] = '\0'; geometry->data[assetSize] = '\0';
geometry->alreadyLoaded = false; geometry->alreadyLoaded = false;
geometry->loadedModel = nullptr; geometry->loadedModel = nullptr;
if (packName == "base.nfpack")
geometry->isBaseAsset = true;
m_assets[assetName] = geometry; m_assets[assetName] = geometry;
continue; continue;
} }
if (extension == "png") { if (extension == "png") {
if (assetName.find("_cmfront") != std::string::npos || assetName.find("_cmback") != std::string::npos || assetName.find("_cmtop") != std::string::npos || assetName.find("_cmbottom") != std::string::npos || assetName.find("_cmleft") != std::string::npos || assetName.find("_cmright") != std::string::npos) { if (assetName.find("_cmfront") != std::string::npos || assetName.find("_cmback") != std::string::npos || assetName.find("_cmtop") != std::string::npos || assetName.find("_cmbottom") != std::string::npos || assetName.find("_cmleft") != std::string::npos || assetName.find("_cmright") != std::string::npos) {
static std::unordered_map<std::string, ACubemap*> cubemaps;
std::string cmName = assetName.substr(0, assetName.find('_')); std::string cmName = assetName.substr(0, assetName.find('_'));
ACubemap* curr; ACubemap* curr;
if (cubemaps.find(cmName) == cubemaps.end()) { if (cubemaps.find(cmName) == cubemaps.end()) {
@ -126,6 +129,8 @@ namespace nf {
texture->data = new char[assetSize]; texture->data = new char[assetSize];
std::memcpy(texture->data, &assetContents[0], assetSize); std::memcpy(texture->data, &assetContents[0], assetSize);
texture->size = assetSize; texture->size = assetSize;
if (packName == "base.nfpack")
texture->isBaseAsset = true;
m_assets[assetName] = texture; m_assets[assetName] = texture;
continue; continue;
} }
@ -142,13 +147,17 @@ namespace nf {
font->data = new char[assetSize]; font->data = new char[assetSize];
std::memcpy(font->data, &assetContents[0], assetSize); std::memcpy(font->data, &assetContents[0], assetSize);
font->size = assetSize; font->size = assetSize;
if (packName == "base.nfpack")
font->isBaseAsset = true;
m_assets[assetName] = font; m_assets[assetName] = font;
continue; continue;
} }
Error("Invalid asset extention in pack \"" + (std::string)packName + (std::string)"\"!"); Error("Invalid asset extention in pack \"" + (std::string)packName + (std::string)"\"!");
} }
if (cubemapCount % 6 != 0) if (cubemapCount % 6 != 0)
Error("Could not find full cubemap in pack \"" + (std::string)packName + (std::string)"\"!") Error("Could not find full cubemap in pack \"" + (std::string)packName + (std::string)"\"!");
if (packName != "base.nfpack")
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
} }
Asset* AssetPack::operator[](const char* in) { Asset* AssetPack::operator[](const char* in) {
@ -162,9 +171,14 @@ namespace nf {
return m_assets[in]; return m_assets[in];
} }
void AssetPack::destroy() {
unload();
}
void AssetPack::unload() { void AssetPack::unload() {
for (auto curr : m_assets) for (auto curr : m_assets)
delete curr.second; delete curr.second;
m_assets.clear();
} }
AssetPack::~AssetPack() { AssetPack::~AssetPack() {

View File

@ -35,4 +35,13 @@ namespace nf {
void Gamestate::onExit() { void Gamestate::onExit() {
} }
void Gamestate::cleanup() {
for (NFObject* curr : m_nfObjects)
curr->destroy();
m_nfObjects.clear();
delete camera;
app = nullptr;
}
} }

View File

@ -7,34 +7,33 @@
namespace nf { namespace nf {
void IntroGamestate::onEnter() { void IntroGamestate::onEnter() {
Log("Intro onEnter!"); Log("Intro onEnter!");
logoTex.create(BaseAssets::logo, Vec2(0.0, 0.0)); m_logoTex.create(BaseAssets::logo, Vec2(0.0, 0.0));
logoTex.centered(true, true); m_logoTex.centered(true, true);
text.create("(C) Grayson Riffe 2021", Vec2(0.01, 0.025), Vec3(0.8)); m_text.create("(C) Grayson Riffe 2021", Vec2(0.01, 0.025), Vec3(0.8));
text.setScale(0.6); m_text.setScale(0.6);
m_counter = 0; m_start = std::chrono::steady_clock::now();
} }
void IntroGamestate::update(double deltaTime) { void IntroGamestate::update(double deltaTime) {
if (m_counter >= 240) { std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
app->changeState(app->getDefaultState()); std::chrono::duration<double, std::ratio<1i64>> dur = now - m_start;
}
static double scale = 2.0; static double scale = 2.0;
logoTex.setScale(scale); m_logoTex.setScale(scale);
if (m_counter >= 20) { if (dur.count() > 0.2) {
scale += 0.002; scale += 0.12 * deltaTime;
} }
m_counter++;
if (app->isInput(NFI_SPACE)) if (dur.count() > 3.5 || app->isInput(NFI_SPACE)) {
m_counter = 240; app->changeState(app->getDefaultState());
}
if (app->isInput(NFI_ESCAPE)) if (app->isInput(NFI_ESCAPE))
app->quit(); app->quit();
} }
void IntroGamestate::render(Renderer& renderer) { void IntroGamestate::render(Renderer& renderer) {
renderer.render(logoTex); renderer.render(m_logoTex);
renderer.render(text); renderer.render(m_text);
} }
void IntroGamestate::onExit() { void IntroGamestate::onExit() {

View File

@ -120,6 +120,6 @@ namespace nf {
} }
Camera::~Camera() { Camera::~Camera() {
m_app->trackMouse(false);
} }
} }

View File

@ -4,6 +4,7 @@
#include "GL/glew.h" #include "GL/glew.h"
#include "stb_image.h" #include "stb_image.h"
#include "Application.h"
#include "Assets.h" #include "Assets.h"
namespace nf { namespace nf {
@ -108,6 +109,8 @@ namespace nf {
m_vao->addBuffer(vb, sizeof(vb)); m_vao->addBuffer(vb, sizeof(vb));
m_vao->push<float>(3); m_vao->push<float>(3);
m_vao->finishBufferLayout(); m_vao->finishBufferLayout();
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
} }
bool Cubemap::isConstructed() { bool Cubemap::isConstructed() {
@ -122,8 +125,15 @@ namespace nf {
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
} }
Cubemap::~Cubemap() { void Cubemap::destroy() {
if(m_constructed) if (m_constructed)
glDeleteTextures(1, &m_id); glDeleteTextures(1, &m_id);
m_constructed = false;
m_id = 0;
delete m_vao;
}
Cubemap::~Cubemap() {
} }
} }

View File

@ -2,6 +2,8 @@
#include<vector> #include<vector>
#include "Application.h"
#include "Model.h"
#include "Shader.h" #include "Shader.h"
namespace nf { namespace nf {
@ -18,24 +20,28 @@ namespace nf {
void Entity::create(Asset* modelAsset, Asset* textureAsset) { void Entity::create(Asset* modelAsset, Asset* textureAsset) {
m_constructed = true; m_constructed = true;
AModel& model = *(AModel*)modelAsset; AModel& model = *(AModel*)modelAsset;
//TODO: Change this when doing materials
if (model.alreadyLoaded && textureAsset == nullptr) { if (model.alreadyLoaded && textureAsset == nullptr) {
m_model = model.loadedModel; m_model = model.loadedModel;
return;
} }
if (!textureAsset) else {
Error("No texture given to Entity create function on new model load!"); if (!textureAsset)
ATexture& texture = *(ATexture*)textureAsset; Error("No texture given to Entity create function on new model load!");
std::string obj = model.data; ATexture& texture = *(ATexture*)textureAsset;
m_model = new Model; std::string obj = model.data;
std::vector<float> vb; m_model = new Model;
std::vector<unsigned int> ib; std::vector<float> vb;
size_t ibCount = 0; std::vector<unsigned int> ib;
std::vector<float> tc; size_t ibCount = 0;
std::vector<float> vn; std::vector<float> tc;
parseOBJ(obj, vb, ib, ibCount, tc, vn); std::vector<float> vn;
m_model->create(&vb[0], vb.size() * sizeof(float), &ib[0], ibCount, &vn[0], vn.size() * sizeof(float), &tc[0], tc.size() * sizeof(float), &texture); parseOBJ(obj, vb, ib, ibCount, tc, vn);
model.alreadyLoaded = true; m_model->create(&vb[0], vb.size() * sizeof(float), &ib[0], ibCount, &vn[0], vn.size() * sizeof(float), &tc[0], tc.size() * sizeof(float), &texture);
model.loadedModel = m_model; model.alreadyLoaded = true;
model.loadedModel = m_model;
}
m_model->setBaseAsset(model.isBaseAsset);
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
} }
bool Entity::isConstructed() { bool Entity::isConstructed() {
@ -90,6 +96,22 @@ namespace nf {
shader->setUniform("model", model); shader->setUniform("model", model);
} }
void Entity::destroy() {
m_constructed = false;
if(m_model && !m_model->isBaseAsset())
delete m_model;
m_model = nullptr;
m_position.x = 0.0;
m_position.y = 0.0;
m_position.z = 0.0;
m_rotation.x = 0.0;
m_rotation.y = 0.0;
m_rotation.z = 0.0;
m_scale.x = 1.0;
m_scale.y = 1.0;
m_scale.z = 1.0;
}
Entity::~Entity() { Entity::~Entity() {
} }

View File

@ -1,11 +1,12 @@
#include "Light.h" #include "Light.h"
#include "Application.h"
#include "Shader.h" #include "Shader.h"
namespace nf { namespace nf {
Light::Light() : Light::Light() :
m_type(Type::POINT),
m_constructed(false), m_constructed(false),
m_type(Type::POINT),
m_strength(1.0f) m_strength(1.0f)
{ {
@ -18,6 +19,7 @@ namespace nf {
m_type = type; m_type = type;
m_strength = strength; m_strength = strength;
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
} }
bool Light::isConstructed() { bool Light::isConstructed() {
@ -77,6 +79,14 @@ namespace nf {
return m_strength; return m_strength;
} }
void Light::destroy() {
m_constructed = false;
m_type = Type::POINT;
m_position = Vec3(0.0);
m_color = Vec3(0.0);
m_strength = 1.0f;
}
Light::~Light() { Light::~Light() {
} }

View File

@ -8,6 +8,7 @@
namespace nf { namespace nf {
Model::Model() : Model::Model() :
m_base(false),
m_texture(nullptr) m_texture(nullptr)
{ {
@ -29,7 +30,7 @@ namespace nf {
} }
else { else {
m_texture = new Texture; m_texture = new Texture;
m_texture->create(texture->data, texture->size); m_texture->create(texture);
texture->alreadyLoaded = true; texture->alreadyLoaded = true;
texture->loadedTexture = m_texture; texture->loadedTexture = m_texture;
} }
@ -45,6 +46,14 @@ namespace nf {
m_ib->bind(); m_ib->bind();
} }
void Model::setBaseAsset(bool isBase) {
m_base = isBase;
}
bool Model::isBaseAsset() {
return m_base;
}
Model::~Model() { Model::~Model() {
delete m_texture; delete m_texture;
} }

View File

@ -4,6 +4,7 @@
#include "ft2build.h" #include "ft2build.h"
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include "Application.h"
#include "UIElement.h" #include "UIElement.h"
#include "Shader.h" #include "Shader.h"
@ -53,6 +54,7 @@ namespace nf {
FT_Done_FreeType(ft); FT_Done_FreeType(ft);
newFont.alreadyLoaded = true; newFont.alreadyLoaded = true;
newFont.loadedFont = m_font; newFont.loadedFont = m_font;
m_font->isBase = newFont.isBaseAsset;
} }
m_vao = new VertexArray; m_vao = new VertexArray;
m_vao->addBuffer(nullptr, 0); m_vao->addBuffer(nullptr, 0);
@ -61,6 +63,13 @@ namespace nf {
m_vao->addBuffer(nullptr, 0); m_vao->addBuffer(nullptr, 0);
m_vao->push<float>(2); m_vao->push<float>(2);
m_vao->finishBufferLayout(); m_vao->finishBufferLayout();
if (m_string == "NFLoadingText") {
m_string = "Loading...";
}
else {
Application::getApp()->getCurrentState()->m_nfObjects.push_back(this);
}
} }
void Text::setText(const std::string& string) { void Text::setText(const std::string& string) {
@ -135,6 +144,18 @@ namespace nf {
} }
} }
void Text::destroy() {
m_constructed = false;
m_position = Vec2(0.0);
m_centeredX = m_centeredY = false;
m_string = std::string();
if (!m_font->isBase)
delete m_font;
m_color = Vec3(0.0);
m_scale = 1.0f;
m_opacity = 1.0f;
}
Text::~Text() { Text::~Text() {
} }

View File

@ -26,7 +26,7 @@ namespace nf {
} }
else { else {
m_texture = new Texture; m_texture = new Texture;
m_texture->create(tex->data, tex->size); m_texture->create(tex);
} }
m_vao = new VertexArray; m_vao = new VertexArray;
@ -84,6 +84,17 @@ namespace nf {
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
} }
void UITexture::destroy() {
m_constructed = false;
m_position = Vec2(0.0);
m_centeredX = m_centeredY = false;
if (!m_texture->isBaseAsset())
delete m_texture;
m_scale = 1.0f;
m_opacity = 1.0f;
delete m_vao;
}
UITexture::~UITexture() { UITexture::~UITexture() {
} }

View File

@ -8,6 +8,7 @@
#include "Shader.h" #include "Shader.h"
#include "Light.h" #include "Light.h"
#include "Entity.h" #include "Entity.h"
#include "Model.h"
#include "Cubemap.h" #include "Cubemap.h"
#include "UIElement.h" #include "UIElement.h"
#include "Camera.h" #include "Camera.h"
@ -107,7 +108,7 @@ namespace nf {
m_fadeVAO->push<float>(2); m_fadeVAO->push<float>(2);
m_fadeVAO->finishBufferLayout(); m_fadeVAO->finishBufferLayout();
m_fadeIB = new IndexBuffer(fadeIB, 6); m_fadeIB = new IndexBuffer(fadeIB, 6);
m_loadingText.create("Loading...", Vec2(0.025, 0.044), Vec3(0.7, 0.7, 0.7)); m_loadingText.create("NFLoadingText", Vec2(0.025, 0.044), Vec3(0.7, 0.7, 0.7));
} }
void Renderer::setFade(bool in, bool out, bool noText) { void Renderer::setFade(bool in, bool out, bool noText) {
@ -142,7 +143,7 @@ namespace nf {
m_cubemap = &in; m_cubemap = &in;
} }
void Renderer::doFrame(Camera* camera) { void Renderer::doFrame(Camera* camera, double dT) {
//Begin frame //Begin frame
glViewport(0, 0, m_app->getConfig().width, m_app->getConfig().height); glViewport(0, 0, m_app->getConfig().width, m_app->getConfig().height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -202,7 +203,7 @@ namespace nf {
m_loadingText.setOpacity(opacity); m_loadingText.setOpacity(opacity);
m_loadingText.render(m_textShader, m_app->getConfig().width, m_app->getConfig().height); m_loadingText.render(m_textShader, m_app->getConfig().width, m_app->getConfig().height);
} }
opacity -= 0.03; opacity -= 0.8 * dT;
if (opacity <= 0.0) { if (opacity <= 0.0) {
m_fadeIn = false; m_fadeIn = false;
m_fadeOutComplete = false; m_fadeOutComplete = false;
@ -220,7 +221,7 @@ namespace nf {
m_loadingText.setOpacity(opacity); m_loadingText.setOpacity(opacity);
m_loadingText.render(m_textShader, m_app->getConfig().width, m_app->getConfig().height); m_loadingText.render(m_textShader, m_app->getConfig().width, m_app->getConfig().height);
} }
opacity += 0.03; opacity += 1.2 * dT;
if (opacity >= 1.0) { if (opacity >= 1.0) {
m_fadeIn = false; m_fadeIn = false;
m_fadeOutComplete = true; m_fadeOutComplete = true;

View File

@ -4,28 +4,33 @@
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h" #include "stb_image.h"
#include "Assets.h"
#include "Utility.h" #include "Utility.h"
namespace nf { namespace nf {
Texture::Texture() : Texture::Texture() :
m_isBase(false),
m_id(0),
m_x(0), m_x(0),
m_y(0) m_y(0)
{ {
glGenTextures(1, &m_id);
} }
void Texture::create(const char* textureData, size_t textureSize) { void Texture::create(ATexture* tex) {
int nChannels; int nChannels;
stbi_set_flip_vertically_on_load(true); stbi_set_flip_vertically_on_load(true);
unsigned char* texture = stbi_load_from_memory((unsigned char*)textureData, textureSize, &m_x, &m_y, &nChannels, 0); unsigned char* texture = stbi_load_from_memory((unsigned char*)tex->data, tex->size, &m_x, &m_y, &nChannels, 0);
if (!texture) if (!texture)
Error("Texture failed to load from memory!"); Error("Texture failed to load from memory!");
glGenTextures(1, &m_id);
glBindTexture(GL_TEXTURE_2D, m_id); glBindTexture(GL_TEXTURE_2D, m_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_x, m_y, 0, nChannels == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_x, m_y, 0, nChannels == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, texture);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(texture); stbi_image_free(texture);
m_isBase = tex->isBaseAsset;
} }
void Texture::bind() { void Texture::bind() {
@ -36,6 +41,10 @@ namespace nf {
return { (float)m_x, (float)m_y }; return { (float)m_x, (float)m_y };
} }
bool Texture::isBaseAsset() {
return m_isBase;
}
Texture::~Texture() { Texture::~Texture() {
glDeleteTextures(1, &m_id); glDeleteTextures(1, &m_id);
} }

View File

@ -23,6 +23,7 @@ namespace nf {
const std::string& getDefaultState(); const std::string& getDefaultState();
void run(); void run();
void changeState(const std::string& stateName); void changeState(const std::string& stateName);
Gamestate* getCurrentState();
void showWindow(bool show); void showWindow(bool show);
const HWND& getWindow(); const HWND& getWindow();
void changeConfig(const Config& in); void changeConfig(const Config& in);
@ -31,6 +32,7 @@ namespace nf {
bool isInput(unsigned int code); bool isInput(unsigned int code);
void trackMouse(bool track); void trackMouse(bool track);
void getMouseDiff(int& x, int& y); void getMouseDiff(int& x, int& y);
static Application* getApp();
void quit(); void quit();
~Application(); ~Application();
@ -41,11 +43,12 @@ namespace nf {
void toggleFullscreen(); void toggleFullscreen();
void updateInput(); void updateInput();
void runMainGameThread(); void runMainGameThread();
void startIntroState();
void doStateChange(); void doStateChange();
static void setApp(Application* app);
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static Application* currentApp;
Config m_currentConfig; Config m_currentConfig;
bool m_running; bool m_running;
bool m_quit; bool m_quit;
@ -59,7 +62,6 @@ namespace nf {
double m_deltaTime; double m_deltaTime;
std::chrono::steady_clock::time_point m_fpsClock1 = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point m_fpsClock1 = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point m_fpsClock2 = m_fpsClock1; std::chrono::steady_clock::time_point m_fpsClock2 = m_fpsClock1;
int m_frames;
const int m_targetFPS = 60; const int m_targetFPS = 60;
const double m_minFrametime = 1.0 / m_targetFPS; const double m_minFrametime = 1.0 / m_targetFPS;
int m_FPS; int m_FPS;

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <unordered_map> #include <unordered_map>
#include "NFObject.h"
namespace nf { namespace nf {
class Model; class Model;
@ -9,6 +10,7 @@ namespace nf {
struct Asset { struct Asset {
char* data = nullptr; char* data = nullptr;
bool alreadyLoaded = false; bool alreadyLoaded = false;
bool isBaseAsset = false;
virtual ~Asset(); virtual ~Asset();
}; };
@ -55,7 +57,7 @@ namespace nf {
~AFont() override; ~AFont() override;
}; };
class AssetPack { class AssetPack : public NFObject {
public: public:
AssetPack(); AssetPack();
@ -63,6 +65,7 @@ namespace nf {
Asset* operator[](const char* in); Asset* operator[](const char* in);
Asset* operator[](std::string& in); Asset* operator[](std::string& in);
void destroy() override;
void unload(); void unload();
~AssetPack(); ~AssetPack();
private: private:

View File

@ -1,10 +1,11 @@
#pragma once #pragma once
#include "NFObject.h"
#include "Drawable.h" #include "Drawable.h"
namespace nf { namespace nf {
struct Asset; struct Asset;
class Cubemap : public Drawable { class Cubemap : public Drawable, public NFObject {
public: public:
Cubemap(); Cubemap();
@ -12,6 +13,7 @@ namespace nf {
bool isConstructed(); bool isConstructed();
void render(); void render();
void destroy() override;
~Cubemap(); ~Cubemap();
private: private:
bool m_constructed; bool m_constructed;

View File

@ -1,12 +1,13 @@
#pragma once #pragma once
#include "Model.h"
#include "Assets.h" #include "Assets.h"
#include "NFObject.h"
#include "Utility.h" #include "Utility.h"
namespace nf { namespace nf {
class Shader; class Shader;
class Model;
class Entity { class Entity : public NFObject {
public: public:
Entity(); Entity();
@ -24,6 +25,7 @@ namespace nf {
void bind(Shader* shader); void bind(Shader* shader);
Model* getModel() const; Model* getModel() const;
void destroy() override;
~Entity(); ~Entity();
private: private:
void setModelMatrix(Shader* shader); void setModelMatrix(Shader* shader);

View File

@ -1,5 +1,8 @@
#pragma once #pragma once
#include <vector>
#include "Camera.h" #include "Camera.h"
#include "NFObject.h"
namespace nf { namespace nf {
class Application; class Application;
@ -20,6 +23,9 @@ namespace nf {
virtual void render(Renderer& renderer); virtual void render(Renderer& renderer);
virtual void onExit(); virtual void onExit();
void cleanup();
std::vector<NFObject*> m_nfObjects;
protected: protected:
Application* app; Application* app;
Camera* camera; Camera* camera;

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "Gamestate.h" #include "Gamestate.h"
#include "UITexture.h" #include "UITexture.h"
#include "Text.h" #include "Text.h"
@ -13,8 +14,8 @@ namespace nf {
void onExit() override; void onExit() override;
private: private:
int m_counter; std::chrono::steady_clock::time_point m_start;
UITexture logoTex; UITexture m_logoTex;
Text text; Text m_text;
}; };
} }

View File

@ -1,10 +1,11 @@
#pragma once #pragma once
#include "NFObject.h"
#include "Utility.h" #include "Utility.h"
namespace nf { namespace nf {
class Shader; class Shader;
class Light { class Light : public NFObject {
public: public:
enum class Type { enum class Type {
DIRECTIONAL, DIRECTIONAL,
@ -25,6 +26,7 @@ namespace nf {
const Vec3& getColor(); const Vec3& getColor();
const float getStrength(); const float getStrength();
void destroy() override;
~Light(); ~Light();
private: private:
bool m_constructed; bool m_constructed;

View File

@ -13,8 +13,12 @@ namespace nf {
void create(const void* vertexBufferData, const size_t vertexBufferSize, const void* indexBufferData, size_t indexBufferCount, const void* textureCoordinatesBufferData, size_t textureCoordinatesBufferSize, const void* normalsBufferData, size_t normalsBufferSize, ATexture* texture); void create(const void* vertexBufferData, const size_t vertexBufferSize, const void* indexBufferData, size_t indexBufferCount, const void* textureCoordinatesBufferData, size_t textureCoordinatesBufferSize, const void* normalsBufferData, size_t normalsBufferSize, ATexture* texture);
void bind() override; void bind() override;
void setBaseAsset(bool isBase);
bool isBaseAsset();
~Model(); ~Model();
private: private:
bool m_base;
Texture* m_texture; Texture* m_texture;
}; };
} }

View File

@ -0,0 +1,11 @@
#pragma once
namespace nf {
class NFObject {
public:
virtual void destroy() = 0;
private:
};
}

View File

@ -9,6 +9,7 @@
#include "Utility.h" #include "Utility.h"
#include "IntroGamestate.h" #include "IntroGamestate.h"
#include "Assets.h" #include "Assets.h"
#include "Entity.h"
#include "Light.h" #include "Light.h"
#include "Cubemap.h" #include "Cubemap.h"
#include "Text.h" #include "Text.h"
@ -20,34 +21,6 @@ namespace nf {
class Shader; class Shader;
class Model; class Model;
class Entity {
public:
Entity();
void create(Asset* modelAsset, Asset* textureAsset = nullptr);
void setPosition(double x, double y, double z);
void setPosition(const Vec3& position);
void setRotation(double x, double y, double z);
void setRotation(const Vec3& rotation);
void setScale(double x);
void setScale(double x, double y, double z);
void setScale(const Vec3& scale);
void bind(Shader* shader);
Model* getModel() const;
~Entity();
private:
void setModelMatrix(Shader* shader);
Model* m_model;
Vec3 m_position;
Vec3 m_rotation;
Vec3 m_scale;
};
class Renderer { class Renderer {
public: public:
Renderer(Application* app); Renderer(Application* app);
@ -60,7 +33,7 @@ namespace nf {
void render(Light& in); void render(Light& in);
void render(Cubemap& in); void render(Cubemap& in);
void doFrame(Camera* camera); void doFrame(Camera* camera, double dT);
~Renderer(); ~Renderer();
private: private:
@ -103,6 +76,7 @@ namespace nf {
const std::string& getDefaultState(); const std::string& getDefaultState();
void run(); void run();
void changeState(const std::string& stateName); void changeState(const std::string& stateName);
Gamestate* getCurrentState();
void showWindow(bool show); void showWindow(bool show);
const HWND& getWindow(); const HWND& getWindow();
void changeConfig(const Config& in); void changeConfig(const Config& in);
@ -111,6 +85,7 @@ namespace nf {
bool isInput(unsigned int code); bool isInput(unsigned int code);
void trackMouse(bool track); void trackMouse(bool track);
void getMouseDiff(int& x, int& y); void getMouseDiff(int& x, int& y);
static Application* getApp();
void quit(); void quit();
~Application(); ~Application();
@ -121,11 +96,12 @@ namespace nf {
void toggleFullscreen(); void toggleFullscreen();
void updateInput(); void updateInput();
void runMainGameThread(); void runMainGameThread();
void startIntroState();
void doStateChange(); void doStateChange();
static void setApp(Application* app);
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static Application* currentApp;
Config m_currentConfig; Config m_currentConfig;
bool m_running; bool m_running;
bool m_quit; bool m_quit;
@ -139,7 +115,6 @@ namespace nf {
double m_deltaTime; double m_deltaTime;
std::chrono::steady_clock::time_point m_fpsClock1 = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point m_fpsClock1 = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point m_fpsClock2 = m_fpsClock1; std::chrono::steady_clock::time_point m_fpsClock2 = m_fpsClock1;
int m_frames;
const int m_targetFPS = 60; const int m_targetFPS = 60;
const double m_minFrametime = 1.0 / m_targetFPS; const double m_minFrametime = 1.0 / m_targetFPS;
int m_FPS; int m_FPS;

View File

@ -28,7 +28,7 @@ namespace nf {
void render(Light& in); void render(Light& in);
void render(Cubemap& in); void render(Cubemap& in);
void doFrame(Camera* camera); void doFrame(Camera* camera, double dT);
~Renderer(); ~Renderer();
private: private:

View File

@ -2,6 +2,7 @@
#include <map> #include <map>
#include "UIElement.h" #include "UIElement.h"
#include "NFObject.h"
#include "Assets.h" #include "Assets.h"
#include "Utility.h" #include "Utility.h"
@ -15,9 +16,10 @@ namespace nf {
struct Font { struct Font {
std::map<char, Character> m_characters; std::map<char, Character> m_characters;
bool isBase = false;
}; };
class Text : public UIElement { class Text : public UIElement, public NFObject {
public: public:
Text(); Text();
@ -29,6 +31,7 @@ namespace nf {
void setOpacity(double opacity); void setOpacity(double opacity);
void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) override; void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) override;
void destroy() override;
~Text(); ~Text();
private: private:
std::string m_string; std::string m_string;

View File

@ -2,16 +2,20 @@
#include "Utility.h" #include "Utility.h"
namespace nf { namespace nf {
struct ATexture;
class Texture { class Texture {
public: public:
Texture(); Texture();
void create(const char* textureData, size_t textureSize); void create(ATexture* tex);
void bind(); void bind();
Vec2 getDimensions(); Vec2 getDimensions();
bool isBaseAsset();
~Texture(); ~Texture();
private: private:
bool m_isBase;
unsigned int m_id; unsigned int m_id;
int m_x; int m_x;
int m_y; int m_y;

View File

@ -1,12 +1,13 @@
#pragma once #pragma once
#include "UIElement.h" #include "UIElement.h"
#include "NFObject.h"
#include "Utility.h" #include "Utility.h"
namespace nf { namespace nf {
class Texture; class Texture;
struct Asset; struct Asset;
class UITexture : public UIElement { class UITexture : public UIElement, public NFObject {
public: public:
UITexture(); UITexture();
@ -16,6 +17,7 @@ namespace nf {
void setOpacity(double opacity); void setOpacity(double opacity);
void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) override; void render(Shader* shader, unsigned int windowWidth, unsigned int windowHeight) override;
void destroy() override;
~UITexture(); ~UITexture();
private: private:
Texture* m_texture; Texture* m_texture;