Improved logger, added a debug timer, other small stuff, and wrote more user guide
This commit is contained in:
parent
f66c3fb4e0
commit
21764d3f98
@ -61,6 +61,7 @@
|
|||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(SolutionDir)NothinFancy\src\include\</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(SolutionDir)NothinFancy\src\include\</AdditionalIncludeDirectories>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@ -90,6 +91,7 @@ if exist "base.nfpack" (copy "base.nfpack" "$(OutDir)assets\")</Command>
|
|||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(SolutionDir)NothinFancy\src\include\</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(SolutionDir)NothinFancy\src\include\</AdditionalIncludeDirectories>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
@ -16,6 +16,8 @@ int main(int argc, char* argv[]) {
|
|||||||
app.setDefaultState("Main State");
|
app.setDefaultState("Main State");
|
||||||
|
|
||||||
app.run();
|
app.run();
|
||||||
|
|
||||||
|
delete test;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -6,11 +6,9 @@ void MainState::onEnter() {
|
|||||||
camera->setType(currCamType);
|
camera->setType(currCamType);
|
||||||
ap.load("example.nfpack");
|
ap.load("example.nfpack");
|
||||||
|
|
||||||
test.create(ap.get("2mats.obj"), nf::Entity::Type::DYNAMIC);
|
test.create(ap.get("2mats.obj"), nf::Vec3(0.0, 1.5, -5.0), nf::Entity::Type::DYNAMIC);
|
||||||
test.setPosition(nf::Vec3(0.0, 1.5, -5.0));
|
plane.create(ap.get("env.obj"), nf::Vec3(0.0, -20.0, 0.0), nf::Entity::Type::MAP);
|
||||||
plane.create(ap.get("env.obj"), nf::Entity::Type::MAP);
|
|
||||||
plane.setScale(20.0);
|
plane.setScale(20.0);
|
||||||
plane.setPosition(0.0, -20.0, 0.0);
|
|
||||||
|
|
||||||
light.create(nf::Vec3(0.0, 20.0, 0.0), nf::Vec3(1.0, 1.0, 1.0));
|
light.create(nf::Vec3(0.0, 20.0, 0.0), nf::Vec3(1.0, 1.0, 1.0));
|
||||||
light2.create(nf::Vec3(-10.0, 20.0, -10.0), nf::Vec3(1.0, 1.0, 1.0));
|
light2.create(nf::Vec3(-10.0, 20.0, -10.0), nf::Vec3(1.0, 1.0, 1.0));
|
||||||
@ -42,8 +40,7 @@ void MainState::onEnter() {
|
|||||||
for (int y = 0; y < 3; y++) {
|
for (int y = 0; y < 3; y++) {
|
||||||
for (int z = 0; z < 3; z++) {
|
for (int z = 0; z < 3; z++) {
|
||||||
entities.push_back(new nf::Entity);
|
entities.push_back(new nf::Entity);
|
||||||
entities.back()->create(nf::BaseAssets::cube, nf::Entity::Type::DYNAMIC);
|
entities.back()->create(nf::BaseAssets::cube, nf::Vec3(5.0 + x * 2.05, 1.0 + y * 2.05, -5.0 + z * 2.05), nf::Entity::Type::DYNAMIC);
|
||||||
entities.back()->setPosition(nf::Vec3(5.0 + x * 2.05, 1.0 + y * 2.05, -5.0 + z * 2.05));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,7 +48,8 @@ void MainState::onEnter() {
|
|||||||
grav = 2.0f;
|
grav = 2.0f;
|
||||||
setGravity(grav);
|
setGravity(grav);
|
||||||
|
|
||||||
amb = 0.5f;
|
amb = 0.1f;
|
||||||
|
setAmbientLight(amb);
|
||||||
|
|
||||||
camera->setPosition(-20.0, 7.0, 0.0);
|
camera->setPosition(-20.0, 7.0, 0.0);
|
||||||
camera->setRotation(85.0, -30.0);
|
camera->setRotation(85.0, -30.0);
|
||||||
@ -97,8 +95,7 @@ void MainState::update(float deltaTime) {
|
|||||||
|
|
||||||
if (camera->getType() == nf::Camera::Type::FIRST_PERSON && (app->isMouseClicked(NFI_LEFTMOUSE) || app->isMouseHeld(NFI_RIGHTMOUSE))) {
|
if (camera->getType() == nf::Camera::Type::FIRST_PERSON && (app->isMouseClicked(NFI_LEFTMOUSE) || app->isMouseHeld(NFI_RIGHTMOUSE))) {
|
||||||
entities.push_back(new nf::Entity);
|
entities.push_back(new nf::Entity);
|
||||||
entities.back()->create(nf::BaseAssets::sphere, nf::Entity::Type::DYNAMIC);
|
entities.back()->create(nf::BaseAssets::sphere, camera->getPosition() + camera->getRotation() * 5.0, nf::Entity::Type::DYNAMIC);
|
||||||
entities.back()->setPosition(camera->getPosition() + camera->getRotation() * 5.0);
|
|
||||||
entities.back()->setVelocity(camera->getRotation() * 100.0f);
|
entities.back()->setVelocity(camera->getRotation() * 100.0f);
|
||||||
entities.back()->setMass(1000.0f);
|
entities.back()->setMass(1000.0f);
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(ProjectDir)dep\include\</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(ProjectDir)dep\include\</AdditionalIncludeDirectories>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
@ -94,6 +95,7 @@
|
|||||||
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(ProjectDir)dep\include\</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir)src\include\;$(ProjectDir)dep\include\</AdditionalIncludeDirectories>
|
||||||
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
<ObjectFileName>$(IntDir)obj\</ObjectFileName>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -16,8 +16,8 @@ namespace nf {
|
|||||||
m_stateChange(false),
|
m_stateChange(false),
|
||||||
m_stateChangeStarted(false)
|
m_stateChangeStarted(false)
|
||||||
{
|
{
|
||||||
NFLog("Creating NF application");
|
NFLog("Constructing application");
|
||||||
NFLog("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);
|
NFLog("Width: " + std::to_string(m_currentConfig.width) + ", Height: " + std::to_string(m_currentConfig.height) + ", Fullscreen: " + (m_currentConfig.fullscreen ? "true" : "false") + ", Title: " + m_currentConfig.title);
|
||||||
|
|
||||||
if (getApp(true) != nullptr)
|
if (getApp(true) != nullptr)
|
||||||
NFError("Cannot create two NF Application objects!");
|
NFError("Cannot create two NF Application objects!");
|
||||||
@ -78,7 +78,9 @@ namespace nf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::run() {
|
void Application::run() {
|
||||||
|
NFLog("Running application...");
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
Debug::startTimer();
|
||||||
SetThreadDescription(GetCurrentThread(), L"Input Thread");
|
SetThreadDescription(GetCurrentThread(), L"Input Thread");
|
||||||
#endif
|
#endif
|
||||||
if (m_defaultState.empty())
|
if (m_defaultState.empty())
|
||||||
@ -111,6 +113,9 @@ namespace nf {
|
|||||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||||
}
|
}
|
||||||
mainThread.join();
|
mainThread.join();
|
||||||
|
#ifdef _DEBUG
|
||||||
|
Debug::stopTimer();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::hasCustomWindowIcon() {
|
bool Application::hasCustomWindowIcon() {
|
||||||
@ -118,10 +123,12 @@ namespace nf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::changeState(const std::string& stateName) {
|
void Application::changeState(const std::string& stateName) {
|
||||||
|
if (m_stateChange) return;
|
||||||
if (m_states.find(stateName) == m_states.end())
|
if (m_states.find(stateName) == m_states.end())
|
||||||
NFError("State \"" + (std::string)stateName + (std::string)"\" doesn't exist!");
|
NFError("State \"" + (std::string)stateName + (std::string)"\" doesn't exist!");
|
||||||
m_stateChange = true;
|
m_stateChange = true;
|
||||||
m_nextState = m_states[stateName];
|
m_nextState = m_states[stateName];
|
||||||
|
NFLog("Changing to state \"" + stateName + (std::string)"\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
Gamestate* Application::getCurrentState() {
|
Gamestate* Application::getCurrentState() {
|
||||||
@ -300,7 +307,6 @@ namespace nf {
|
|||||||
|
|
||||||
void Application::quit() {
|
void Application::quit() {
|
||||||
m_quit = true;
|
m_quit = true;
|
||||||
NFLog("Exiting NF application");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::runMainGameThread() {
|
void Application::runMainGameThread() {
|
||||||
@ -343,12 +349,11 @@ namespace nf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_audio->stopAllSounds();
|
|
||||||
m_currentState->stop();
|
m_currentState->stop();
|
||||||
delete sIntro;
|
|
||||||
delete m_physics;
|
delete m_physics;
|
||||||
delete m_audio;
|
delete m_audio;
|
||||||
delete m_renderer;
|
delete m_renderer;
|
||||||
|
delete sIntro;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::doStateChange() {
|
void Application::doStateChange() {
|
||||||
@ -445,6 +450,7 @@ namespace nf {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_CLOSE: {
|
case WM_CLOSE: {
|
||||||
|
NFLog("Exiting NF application");
|
||||||
DestroyWindow(hWnd);
|
DestroyWindow(hWnd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -456,12 +462,5 @@ namespace nf {
|
|||||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
|
||||||
for (std::pair<std::string, Gamestate*> state : m_states) {
|
|
||||||
Gamestate* curr = state.second;
|
|
||||||
delete curr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Application* Application::currentApp = nullptr;
|
Application* Application::currentApp = nullptr;
|
||||||
}
|
}
|
@ -59,7 +59,6 @@ namespace nf {
|
|||||||
unsigned int cubemapCount = 0;
|
unsigned int cubemapCount = 0;
|
||||||
unsigned int buttonCount = 0;
|
unsigned int buttonCount = 0;
|
||||||
while (packContents.size()) {
|
while (packContents.size()) {
|
||||||
size_t startingPos = packContents.find_first_of("#NFASSET ") + 9;
|
|
||||||
packContents = packContents.substr(9);
|
packContents = packContents.substr(9);
|
||||||
size_t endAssetNamePos = packContents.find_first_of('\n');
|
size_t endAssetNamePos = packContents.find_first_of('\n');
|
||||||
std::string assetName = packContents.substr(0, endAssetNamePos);
|
std::string assetName = packContents.substr(0, endAssetNamePos);
|
||||||
@ -206,7 +205,6 @@ namespace nf {
|
|||||||
NFError("Could not find full button set in pack \"" + (std::string)packName + (std::string)"\"!");
|
NFError("Could not find full button set in pack \"" + (std::string)packName + (std::string)"\"!");
|
||||||
|
|
||||||
while (packContentsOBJ.size()) {
|
while (packContentsOBJ.size()) {
|
||||||
size_t startingPos = packContentsOBJ.find_first_of("#NFASSET ") + 9;
|
|
||||||
packContentsOBJ = packContentsOBJ.substr(9);
|
packContentsOBJ = packContentsOBJ.substr(9);
|
||||||
size_t endAssetNamePos = packContentsOBJ.find_first_of('\n');
|
size_t endAssetNamePos = packContentsOBJ.find_first_of('\n');
|
||||||
std::string assetName = packContentsOBJ.substr(0, endAssetNamePos);
|
std::string assetName = packContentsOBJ.substr(0, endAssetNamePos);
|
||||||
@ -223,7 +221,6 @@ namespace nf {
|
|||||||
assetContents = packContentsOBJ;
|
assetContents = packContentsOBJ;
|
||||||
packContentsOBJ = "";
|
packContentsOBJ = "";
|
||||||
}
|
}
|
||||||
size_t assetSize = assetContents.size();
|
|
||||||
|
|
||||||
if (extension == "obj") {
|
if (extension == "obj") {
|
||||||
AModel* model = new AModel;
|
AModel* model = new AModel;
|
||||||
@ -236,6 +233,7 @@ namespace nf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assetContents = assetContents.substr(assetContents.find("\n") + 1);
|
assetContents = assetContents.substr(assetContents.find("\n") + 1);
|
||||||
|
size_t assetSize = assetContents.size();
|
||||||
model->data = new char[assetSize];
|
model->data = new char[assetSize];
|
||||||
std::memcpy(model->data, &assetContents[0], assetSize);
|
std::memcpy(model->data, &assetContents[0], assetSize);
|
||||||
model->size = assetSize;
|
model->size = assetSize;
|
||||||
|
@ -17,7 +17,7 @@ namespace nf {
|
|||||||
NFError("Could not initialize COM!");
|
NFError("Could not initialize COM!");
|
||||||
hr = XAudio2Create(&m_engine);
|
hr = XAudio2Create(&m_engine);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
NFError("Could not initialize the audio engine!");
|
NFError("Could not initialize audio engine!");
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
XAUDIO2_DEBUG_CONFIGURATION debug = { 0 };
|
XAUDIO2_DEBUG_CONFIGURATION debug = { 0 };
|
||||||
debug.TraceMask = XAUDIO2_LOG_ERRORS | XAUDIO2_LOG_WARNINGS;
|
debug.TraceMask = XAUDIO2_LOG_ERRORS | XAUDIO2_LOG_WARNINGS;
|
||||||
@ -25,12 +25,16 @@ namespace nf {
|
|||||||
m_engine->SetDebugConfiguration(&debug, 0);
|
m_engine->SetDebugConfiguration(&debug, 0);
|
||||||
#endif
|
#endif
|
||||||
hr = m_engine->CreateMasteringVoice(&m_masterVoice);
|
hr = m_engine->CreateMasteringVoice(&m_masterVoice);
|
||||||
if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
|
if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) {
|
||||||
m_isActive = false;
|
m_isActive = false;
|
||||||
else if (SUCCEEDED(hr))
|
NFLog("Audio engine not initialized since no audio devices found");
|
||||||
|
}
|
||||||
|
else if (SUCCEEDED(hr)) {
|
||||||
m_isActive = true;
|
m_isActive = true;
|
||||||
|
NFLog("Initialized audio engine");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
NFError("Could not initialize the audio engine!");
|
NFError("Could not initialize audio engine!");
|
||||||
m_threadRunning = true;
|
m_threadRunning = true;
|
||||||
m_thread = std::thread(&AudioEngine::runAudioThread, this);
|
m_thread = std::thread(&AudioEngine::runAudioThread, this);
|
||||||
}
|
}
|
||||||
@ -42,10 +46,11 @@ namespace nf {
|
|||||||
return false;
|
return false;
|
||||||
else if (hr == S_OK) {
|
else if (hr == S_OK) {
|
||||||
m_isActive = true;
|
m_isActive = true;
|
||||||
|
NFLog("Initialized audio engine");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NFError("Could not initialize audio!");
|
NFError("Could not initialize audio engine!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,6 +67,9 @@ namespace nf {
|
|||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_isActive)
|
||||||
|
return;
|
||||||
|
|
||||||
DWORD cm;
|
DWORD cm;
|
||||||
m_masterVoice->GetChannelMask(&cm);
|
m_masterVoice->GetChannelMask(&cm);
|
||||||
X3DAUDIO_HANDLE x3d;
|
X3DAUDIO_HANDLE x3d;
|
||||||
@ -192,6 +200,7 @@ namespace nf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AudioEngine::~AudioEngine() {
|
AudioEngine::~AudioEngine() {
|
||||||
|
stopAllSounds();
|
||||||
m_threadRunning = false;
|
m_threadRunning = false;
|
||||||
m_thread.join();
|
m_thread.join();
|
||||||
m_engine->Release();
|
m_engine->Release();
|
||||||
|
@ -24,6 +24,7 @@ namespace nf {
|
|||||||
|
|
||||||
if (physics)
|
if (physics)
|
||||||
app->getPhysicsEngine()->newScene();
|
app->getPhysicsEngine()->newScene();
|
||||||
|
NFTimerLoad;
|
||||||
onEnter();
|
onEnter();
|
||||||
|
|
||||||
m_loading = false;
|
m_loading = false;
|
||||||
|
@ -22,10 +22,11 @@ namespace nf {
|
|||||||
m_member = true;
|
m_member = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::create(Asset* modelAsset, Type type) {
|
void Entity::create(Asset* modelAsset, const Vec3& position, Type type) {
|
||||||
if (m_constructed)
|
if (m_constructed)
|
||||||
NFError("Entity already created!");
|
NFError("Entity already created!");
|
||||||
m_constructed = true;
|
m_constructed = true;
|
||||||
|
setPosition(position);
|
||||||
m_type = type;
|
m_type = type;
|
||||||
AModel* model;
|
AModel* model;
|
||||||
if ((model = dynamic_cast<AModel*>(modelAsset)) == nullptr)
|
if ((model = dynamic_cast<AModel*>(modelAsset)) == nullptr)
|
||||||
|
@ -140,7 +140,7 @@ namespace nf {
|
|||||||
callbacks.close_func = v_close;
|
callbacks.close_func = v_close;
|
||||||
callbacks.tell_func = v_tell;
|
callbacks.tell_func = v_tell;
|
||||||
|
|
||||||
int open = ov_open_callbacks(&memFile, &file, nullptr, 0, callbacks);
|
ov_open_callbacks(&memFile, &file, nullptr, 0, callbacks);
|
||||||
char* buff = new char[65536 * 1000];
|
char* buff = new char[65536 * 1000];
|
||||||
|
|
||||||
int stream = 0;
|
int stream = 0;
|
||||||
@ -164,7 +164,6 @@ namespace nf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t Sound::loadWAV(std::string& data) {
|
size_t Sound::loadWAV(std::string& data) {
|
||||||
unsigned int fileSize = *(unsigned int*)&data[4];
|
|
||||||
size_t fmtPos;
|
size_t fmtPos;
|
||||||
if ((fmtPos = data.find("fmt")) == std::string::npos)
|
if ((fmtPos = data.find("fmt")) == std::string::npos)
|
||||||
NFError("WAV not of correct format!");
|
NFError("WAV not of correct format!");
|
||||||
|
@ -30,6 +30,7 @@ namespace nf {
|
|||||||
m_stepSize(1.0f / 60.0f),
|
m_stepSize(1.0f / 60.0f),
|
||||||
m_accumulator(0.0)
|
m_accumulator(0.0)
|
||||||
{
|
{
|
||||||
|
NFLog("Initializing physics engine...");
|
||||||
m_err = new PhysicsErrorCallback;
|
m_err = new PhysicsErrorCallback;
|
||||||
m_foundation = PxCreateFoundation(PX_PHYSICS_VERSION, m_alloc, *m_err);
|
m_foundation = PxCreateFoundation(PX_PHYSICS_VERSION, m_alloc, *m_err);
|
||||||
if (!m_foundation)
|
if (!m_foundation)
|
||||||
@ -54,6 +55,8 @@ namespace nf {
|
|||||||
m_dispacher = PxDefaultCpuDispatcherCreate(threads);
|
m_dispacher = PxDefaultCpuDispatcherCreate(threads);
|
||||||
|
|
||||||
m_defaultMat = m_phy->createMaterial(0.5f, 0.5f, 0.0f);
|
m_defaultMat = m_phy->createMaterial(0.5f, 0.5f, 0.0f);
|
||||||
|
|
||||||
|
NFLog("Initialized physics engine");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsEngine::newScene() {
|
void PhysicsEngine::newScene() {
|
||||||
|
@ -34,6 +34,7 @@ namespace nf {
|
|||||||
m_fadeText(true),
|
m_fadeText(true),
|
||||||
m_fadeOutComplete(false)
|
m_fadeOutComplete(false)
|
||||||
{
|
{
|
||||||
|
NFLog("Initializing renderer...");
|
||||||
m_hdc = GetDC(m_app->getWindow());
|
m_hdc = GetDC(m_app->getWindow());
|
||||||
PIXELFORMATDESCRIPTOR pfd = {
|
PIXELFORMATDESCRIPTOR pfd = {
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
@ -123,6 +124,8 @@ namespace nf {
|
|||||||
m_quadVAO->finishBufferLayout();
|
m_quadVAO->finishBufferLayout();
|
||||||
m_quadIB = new IndexBuffer(quadIB, 6);
|
m_quadIB = new IndexBuffer(quadIB, 6);
|
||||||
m_loadingText.create("NFLoadingText", Vec2(0.025f, 0.044f), Vec3(0.7f));
|
m_loadingText.create("NFLoadingText", Vec2(0.025f, 0.044f), Vec3(0.7f));
|
||||||
|
|
||||||
|
NFLog("Initialized renderer");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::setFade(bool in, bool out, bool text) {
|
void Renderer::setFade(bool in, bool out, bool text) {
|
||||||
@ -165,21 +168,15 @@ namespace nf {
|
|||||||
glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)m_app->getConfig().width / (float)m_app->getConfig().height, 0.1f, 1000.0f);
|
glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)m_app->getConfig().width / (float)m_app->getConfig().height, 0.1f, 1000.0f);
|
||||||
camera->update(m_gBufferShader, m_lightingShader, m_cubemapShader);
|
camera->update(m_gBufferShader, m_lightingShader, m_cubemapShader);
|
||||||
|
|
||||||
|
if (m_lGame.size()) {
|
||||||
//First, fill the gBuffer with entities
|
//First, fill the gBuffer with entities
|
||||||
m_gBufferShader->setUniform("proj", proj);
|
m_gBufferShader->setUniform("proj", proj);
|
||||||
m_gBuffer->render(m_lGame, m_gBufferShader);
|
m_gBuffer->render(m_lGame, m_gBufferShader);
|
||||||
|
|
||||||
//Light entities using the gBuffer
|
//Light entities using the gBuffer
|
||||||
size_t lightsRemaining = m_lights.size();
|
size_t lightsRemaining = m_lights.size();
|
||||||
if (!lightsRemaining) {
|
|
||||||
m_quadVAO->bind();
|
|
||||||
m_quadIB->bind();
|
|
||||||
m_lightingShader->bind();
|
|
||||||
m_gBuffer->bindTextures(m_lightingShader);
|
|
||||||
glDrawElements(GL_TRIANGLES, m_quadIB->getCount(), GL_UNSIGNED_INT, nullptr);
|
|
||||||
}
|
|
||||||
unsigned int drawCount = 0;
|
unsigned int drawCount = 0;
|
||||||
while (lightsRemaining > 0) {
|
do {
|
||||||
size_t currLightsDrawn;
|
size_t currLightsDrawn;
|
||||||
if (lightsRemaining > m_texSlots)
|
if (lightsRemaining > m_texSlots)
|
||||||
currLightsDrawn = m_texSlots;
|
currLightsDrawn = m_texSlots;
|
||||||
@ -203,21 +200,25 @@ namespace nf {
|
|||||||
m_quadIB->bind();
|
m_quadIB->bind();
|
||||||
m_lightingShader->bind();
|
m_lightingShader->bind();
|
||||||
m_gBuffer->bindTextures(m_lightingShader);
|
m_gBuffer->bindTextures(m_lightingShader);
|
||||||
|
#ifdef _DEBUG
|
||||||
|
m_lightingShader->validate();
|
||||||
|
#endif
|
||||||
glDrawElements(GL_TRIANGLES, m_quadIB->getCount(), GL_UNSIGNED_INT, nullptr);
|
glDrawElements(GL_TRIANGLES, m_quadIB->getCount(), GL_UNSIGNED_INT, nullptr);
|
||||||
m_lights.erase(m_lights.begin(), m_lights.begin() + currLightsDrawn);
|
m_lights.erase(m_lights.begin(), m_lights.begin() + currLightsDrawn);
|
||||||
drawCount++;
|
drawCount++;
|
||||||
}
|
} while (lightsRemaining > 0);
|
||||||
m_lGame.clear();
|
m_lGame.clear();
|
||||||
m_lights.clear();
|
m_lights.clear();
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glDepthFunc(GL_LESS);
|
glDepthFunc(GL_LESS);
|
||||||
|
}
|
||||||
|
|
||||||
//Draw the cubemap if one is currently set
|
//Draw the cubemap if one is currently set
|
||||||
if (m_cubemap != nullptr) {
|
if (m_cubemap != nullptr) {
|
||||||
m_cubemapShader->setUniform("proj", proj);
|
m_cubemapShader->setUniform("proj", proj);
|
||||||
m_cubemap->render(m_cubemapShader);
|
m_cubemap->render(m_cubemapShader);
|
||||||
}
|
|
||||||
m_cubemap = nullptr;
|
m_cubemap = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
//Draw UI elements
|
//Draw UI elements
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
@ -297,6 +298,7 @@ namespace nf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::loadBaseAssets() {
|
void Renderer::loadBaseAssets() {
|
||||||
|
NFLog("Loading base assets...");
|
||||||
m_baseAP.load("base.nfpack");
|
m_baseAP.load("base.nfpack");
|
||||||
const char* gBufferVertex = m_baseAP.get("gBufferVertex.shader")->data;
|
const char* gBufferVertex = m_baseAP.get("gBufferVertex.shader")->data;
|
||||||
const char* gBufferFragment = m_baseAP.get("gBufferFragment.shader")->data;
|
const char* gBufferFragment = m_baseAP.get("gBufferFragment.shader")->data;
|
||||||
@ -334,6 +336,8 @@ namespace nf {
|
|||||||
BaseAssets::cubemap = (ACubemap*)m_baseAP.get("default.cm");
|
BaseAssets::cubemap = (ACubemap*)m_baseAP.get("default.cm");
|
||||||
BaseAssets::font = (AFont*)m_baseAP.get("default.ttf");
|
BaseAssets::font = (AFont*)m_baseAP.get("default.ttf");
|
||||||
BaseAssets::button = (AButton*)m_baseAP.get("default.button");
|
BaseAssets::button = (AButton*)m_baseAP.get("default.button");
|
||||||
|
|
||||||
|
NFLog("Base assets loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::createShadowMaps() {
|
void Renderer::createShadowMaps() {
|
||||||
@ -371,7 +375,6 @@ namespace nf {
|
|||||||
glm::mat4 lightView;
|
glm::mat4 lightView;
|
||||||
glm::mat4 lightSpaceMat;
|
glm::mat4 lightSpaceMat;
|
||||||
bool directionalRendered = false;
|
bool directionalRendered = false;
|
||||||
unsigned int directionalSlot = 0; //TODO: Test this
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_shadowMapFBO);
|
glBindFramebuffer(GL_FRAMEBUFFER, m_shadowMapFBO);
|
||||||
for (unsigned int i = 0; i < count; i++) {
|
for (unsigned int i = 0; i < count; i++) {
|
||||||
Light::Type type = m_lights[i]->getType();
|
Light::Type type = m_lights[i]->getType();
|
||||||
|
@ -19,47 +19,79 @@ namespace nf {
|
|||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
NFDEBUGINIT;
|
NFDEBUGINIT;
|
||||||
|
|
||||||
|
void Debug::startTimer() {
|
||||||
|
m_timerStarted = true;
|
||||||
|
m_initTime = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug::stopTimer() {
|
||||||
|
m_timerStarted = false;
|
||||||
|
}
|
||||||
|
|
||||||
void Debug::LogImp(const char* in) {
|
void Debug::LogImp(const char* in) {
|
||||||
std::chrono::duration<float> time = getCurrentTime();
|
if(m_timerStarted)
|
||||||
std::printf("[%.4f] NF Log: %s\n", time.count(), in);
|
printCurrentTime();
|
||||||
|
std::printf("NF Log: %s\n", in);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debug::LogImp(const std::string& in) {
|
void Debug::LogImp(const std::string& in) {
|
||||||
std::chrono::duration<float> time = getCurrentTime();
|
if (m_timerStarted)
|
||||||
std::printf("[%.4f] NF Log: ", time.count());
|
printCurrentTime();
|
||||||
|
std::printf("NF Log: ");
|
||||||
std::cout << in << "\n";
|
std::cout << in << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debug::LogImp(int in) {
|
void Debug::LogImp(int in) {
|
||||||
std::chrono::duration<float> time = getCurrentTime();
|
if (m_timerStarted)
|
||||||
std::printf("[%.4f] NF Log: %i\n", time.count(), in);
|
printCurrentTime();
|
||||||
|
std::printf("NF Log: %i\n", in);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debug::LogImp(float in) {
|
void Debug::LogImp(float in) {
|
||||||
std::chrono::duration<float> time = getCurrentTime();
|
if (m_timerStarted)
|
||||||
std::printf("[%.4f] NF Log: %.4f\n", time.count(), in);
|
printCurrentTime();
|
||||||
|
std::printf("NF Log: %.4f\n", in);
|
||||||
}
|
}
|
||||||
//TODO: Test every Error in release mode
|
//TODO: Test every Error in release mode
|
||||||
void Debug::ErrorImp(const char* in, const char* filename, int line) {
|
void Debug::ErrorImp(const char* in, const char* filename, int line) {
|
||||||
std::chrono::duration<float> time = getCurrentTime();
|
if (m_timerStarted)
|
||||||
|
printCurrentTime();
|
||||||
static HANDLE cmd = GetStdHandle(STD_OUTPUT_HANDLE);
|
static HANDLE cmd = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
SetConsoleTextAttribute(cmd, FOREGROUND_RED);
|
SetConsoleTextAttribute(cmd, FOREGROUND_RED);
|
||||||
std::printf("[%.4f] NF Error (%s, %i): %s\n", time.count(), filename, line, in);
|
std::printf("NF Error (%s, %i): %s\n", filename, line, in);
|
||||||
SetConsoleTextAttribute(cmd, 7);
|
SetConsoleTextAttribute(cmd, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Debug::ErrorImp(const std::string& in, const char* filename, int line) {
|
void Debug::ErrorImp(const std::string& in, const char* filename, int line) {
|
||||||
std::chrono::duration<float> time = getCurrentTime();
|
if (m_timerStarted)
|
||||||
|
printCurrentTime();
|
||||||
static HANDLE cmd = GetStdHandle(STD_OUTPUT_HANDLE);
|
static HANDLE cmd = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
SetConsoleTextAttribute(cmd, FOREGROUND_RED);
|
SetConsoleTextAttribute(cmd, FOREGROUND_RED);
|
||||||
std::printf("[%.4f] NF Error (%s, %i): ", time.count(), filename, line);
|
std::printf("NF Error (%s, %i): ", filename, line);
|
||||||
std::cout << in << "\n";
|
std::cout << in << "\n";
|
||||||
SetConsoleTextAttribute(cmd, 7);
|
SetConsoleTextAttribute(cmd, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::chrono::duration<float> Debug::getCurrentTime() {
|
void Debug::printCurrentTime() {
|
||||||
std::chrono::steady_clock::time_point now = std::chrono::high_resolution_clock::now();
|
std::chrono::steady_clock::time_point now = std::chrono::high_resolution_clock::now();
|
||||||
return now - m_initTime;
|
std::chrono::duration<float> dur = now - m_initTime;
|
||||||
|
std::printf("[%.4f] ", dur.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer::Timer(const std::string& function, bool onEnter) {
|
||||||
|
m_funcName = function;
|
||||||
|
m_initTime = std::chrono::steady_clock::now();
|
||||||
|
m_loading = onEnter;
|
||||||
|
if (!m_loading)
|
||||||
|
NFLog("Started timing \"" + m_funcName + (std::string)"\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer::~Timer() {
|
||||||
|
std::chrono::duration<float> dur = std::chrono::steady_clock::now() - m_initTime;
|
||||||
|
if (!m_loading)
|
||||||
|
NFLog("\"" + m_funcName + (std::string)"\" took " + std::to_string(dur.count()) + (std::string)" seconds.");
|
||||||
|
else
|
||||||
|
NFLog("Loading took " + std::to_string(dur.count()) + (std::string)" seconds.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
|
//This is the main header for the entire engine.
|
||||||
#pragma once
|
#pragma once
|
||||||
//TODO: Rework this file to only contain functions the frontend will need to access
|
|
||||||
//Maybe a implementation define here?
|
|
||||||
|
|
||||||
//TODO: Prevent including other headers other than this one
|
|
||||||
|
|
||||||
#ifndef NFIMPL
|
#ifndef NFIMPL
|
||||||
#define NFIMPL 1
|
#define NFIMPL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "nf/Config.h"
|
#include "nf/Config.h"
|
||||||
|
@ -177,7 +177,6 @@ namespace nf {
|
|||||||
void getMouseDiff(int& x, int& y);
|
void getMouseDiff(int& x, int& y);
|
||||||
static Application* getApp(bool first = false);
|
static Application* getApp(bool first = false);
|
||||||
#endif
|
#endif
|
||||||
~Application();
|
|
||||||
private:
|
private:
|
||||||
void registerWindowClass();
|
void registerWindowClass();
|
||||||
RECT getWindowRect() const;
|
RECT getWindowRect() const;
|
||||||
|
@ -53,6 +53,7 @@ namespace nf {
|
|||||||
/**
|
/**
|
||||||
* @brief Creates an entity
|
* @brief Creates an entity
|
||||||
* @param modelAsset A model Asset pointer
|
* @param modelAsset A model Asset pointer
|
||||||
|
* @param position Initial position vector
|
||||||
* @param type Type of entity; Defaults to Type::STATIC
|
* @param type Type of entity; Defaults to Type::STATIC
|
||||||
*
|
*
|
||||||
* This function will initialize an entity by loading its associated model from
|
* This function will initialize an entity by loading its associated model from
|
||||||
@ -61,7 +62,7 @@ namespace nf {
|
|||||||
* @warning Calling this function twice before the state exits will result in an
|
* @warning Calling this function twice before the state exits will result in an
|
||||||
* error. See @ref isConstructed.
|
* error. See @ref isConstructed.
|
||||||
*/
|
*/
|
||||||
void create(Asset* modelAsset, Type type = Type::STATIC);
|
void create(Asset* modelAsset, const Vec3& position, Type type = Type::STATIC);
|
||||||
/**
|
/**
|
||||||
* @brief Queries whether or not the entity has been created
|
* @brief Queries whether or not the entity has been created
|
||||||
* @return If the entity has been created
|
* @return If the entity has been created
|
||||||
|
@ -14,10 +14,10 @@ namespace nf {
|
|||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A state NF can be in that includes a collection of objects and user-defined
|
* @brief An engine state that includes a world, objects, and user-defined
|
||||||
* behavior
|
* behavior
|
||||||
*
|
*
|
||||||
* Every user-defined state inherits from this class.
|
* Every state inherits from this class.
|
||||||
*/
|
*/
|
||||||
class Gamestate {
|
class Gamestate {
|
||||||
public:
|
public:
|
||||||
@ -37,7 +37,7 @@ namespace nf {
|
|||||||
* @brief Update function
|
* @brief Update function
|
||||||
* @param deltaTime Amount of time the previous frame took to produce in seconds
|
* @param deltaTime Amount of time the previous frame took to produce in seconds
|
||||||
*
|
*
|
||||||
* This function is called every frame. It is called before render.
|
* This function is called every frame. It is called before @ref render.
|
||||||
*
|
*
|
||||||
* The deltaTime parameter's purpose is to create non-frame-dependant gameplay. This
|
* The deltaTime parameter's purpose is to create non-frame-dependant gameplay. This
|
||||||
* number should be multiplied with user numbers likes velocities. Doing this will
|
* number should be multiplied with user numbers likes velocities. Doing this will
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Nothin' Fancy namespace
|
* @brief Nothin' Fancy namespace
|
||||||
*
|
*
|
||||||
* Every class and struct lives inside of this namespace
|
* Every class and struct lives inside of this namespace.
|
||||||
*
|
*
|
||||||
* It could be useful to `using` this namespace:
|
* It could be useful to `using` this namespace:
|
||||||
*
|
*
|
||||||
@ -20,7 +20,15 @@ namespace nf {
|
|||||||
//Strips __FILE__ down to only the name of the file
|
//Strips __FILE__ down to only the name of the file
|
||||||
#define __FILENAME__ strrchr(__FILE__, '\\') + 1
|
#define __FILENAME__ strrchr(__FILE__, '\\') + 1
|
||||||
//Initializes static variables needed for debugging
|
//Initializes static variables needed for debugging
|
||||||
#define NFDEBUGINIT std::chrono::steady_clock::time_point Debug::m_initTime = std::chrono::high_resolution_clock::now();
|
#define NFDEBUGINIT std::chrono::steady_clock::time_point Debug::m_initTime = std::chrono::high_resolution_clock::now(); \
|
||||||
|
bool Debug::m_timerStarted = false
|
||||||
|
/**
|
||||||
|
* @defgroup macros Macros
|
||||||
|
*
|
||||||
|
* Macros to aid in debugging and developing with NF
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
/**
|
/**
|
||||||
* Pauses the engine for a set amount of seconds
|
* Pauses the engine for a set amount of seconds
|
||||||
*/
|
*/
|
||||||
@ -44,10 +52,32 @@ namespace nf {
|
|||||||
#define NFError(x) {nf::Debug::ErrorImp(x,__FILENAME__, __LINE__);\
|
#define NFError(x) {nf::Debug::ErrorImp(x,__FILENAME__, __LINE__);\
|
||||||
__debugbreak();}
|
__debugbreak();}
|
||||||
/**
|
/**
|
||||||
* @brief Handles NFLog and NFError calls
|
* A timer useful for timing functions
|
||||||
|
*
|
||||||
|
* To time a function, place this macro at the beginning of it:
|
||||||
|
*
|
||||||
|
* ~~~
|
||||||
|
* void myFunc() {
|
||||||
|
* NFTimer;
|
||||||
|
* //Rest of function to be timed...
|
||||||
|
* } //Prints here
|
||||||
|
* ~~~
|
||||||
|
*
|
||||||
|
* The result will be logged when the scope it's declared in ends.
|
||||||
*/
|
*/
|
||||||
|
#define NFTimer nf::Timer _nfTimer(__func__)
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#ifndef NFIMPL
|
||||||
|
#define NFTimerLoad nf::Timer _nfTimer(__func__, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
class Debug {
|
class Debug {
|
||||||
public:
|
public:
|
||||||
|
static void startTimer();
|
||||||
|
static void stopTimer();
|
||||||
|
|
||||||
static void LogImp(const char* in);
|
static void LogImp(const char* in);
|
||||||
static void LogImp(const std::string& in);
|
static void LogImp(const std::string& in);
|
||||||
static void LogImp(int in);
|
static void LogImp(int in);
|
||||||
@ -57,8 +87,20 @@ __debugbreak();}
|
|||||||
[[noreturn]]
|
[[noreturn]]
|
||||||
static void ErrorImp(const std::string& in, const char* filename, int line);
|
static void ErrorImp(const std::string& in, const char* filename, int line);
|
||||||
private:
|
private:
|
||||||
|
static void printCurrentTime();
|
||||||
static std::chrono::steady_clock::time_point m_initTime;
|
static std::chrono::steady_clock::time_point m_initTime;
|
||||||
static std::chrono::duration<float> getCurrentTime();
|
static bool m_timerStarted;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Timer {
|
||||||
|
public:
|
||||||
|
Timer(const std::string& function, bool onEnter = false);
|
||||||
|
|
||||||
|
~Timer();
|
||||||
|
private:
|
||||||
|
std::chrono::steady_clock::time_point m_initTime;
|
||||||
|
bool m_loading;
|
||||||
|
std::string m_funcName;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
#define NFDEBUGINIT
|
#define NFDEBUGINIT
|
||||||
@ -67,6 +109,8 @@ __debugbreak();}
|
|||||||
#define NFLog(x)
|
#define NFLog(x)
|
||||||
#define NFError(x) {MessageBox(FindWindow(L"NFClass", NULL), toWide(x).data(), L"NF Engine Error", MB_OK | MB_ICONERROR);\
|
#define NFError(x) {MessageBox(FindWindow(L"NFClass", NULL), toWide(x).data(), L"NF Engine Error", MB_OK | MB_ICONERROR);\
|
||||||
std::exit(-1);}
|
std::exit(-1);}
|
||||||
|
#define NFTimer
|
||||||
|
#define NFTimerLoad
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -364,10 +408,11 @@ std::exit(-1);}
|
|||||||
float w;
|
float w;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef NFIMPL
|
||||||
const std::wstring toWide(const char* in);
|
const std::wstring toWide(const char* in);
|
||||||
const std::wstring toWide(const std::string& in);
|
const std::wstring toWide(const std::string& in);
|
||||||
|
|
||||||
Vec4 degToQuat(const Vec3& in);
|
Vec4 degToQuat(const Vec3& in);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes a stream of bytes as as std::string into a file in a specified location
|
* @brief Writes a stream of bytes as as std::string into a file in a specified location
|
||||||
|
@ -169,7 +169,7 @@ HTML_HEADER = header.html
|
|||||||
HTML_FOOTER = footer.html
|
HTML_FOOTER = footer.html
|
||||||
HTML_STYLESHEET =
|
HTML_STYLESHEET =
|
||||||
HTML_EXTRA_STYLESHEET = theme.css
|
HTML_EXTRA_STYLESHEET = theme.css
|
||||||
HTML_EXTRA_FILES = favicon.png
|
HTML_EXTRA_FILES = images/favicon.png
|
||||||
HTML_COLORSTYLE_HUE = 30
|
HTML_COLORSTYLE_HUE = 30
|
||||||
HTML_COLORSTYLE_SAT = 100
|
HTML_COLORSTYLE_SAT = 100
|
||||||
HTML_COLORSTYLE_GAMMA = 80
|
HTML_COLORSTYLE_GAMMA = 80
|
||||||
@ -199,7 +199,7 @@ QHP_SECT_FILTER_ATTRS =
|
|||||||
QHG_LOCATION =
|
QHG_LOCATION =
|
||||||
GENERATE_ECLIPSEHELP = NO
|
GENERATE_ECLIPSEHELP = NO
|
||||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||||
DISABLE_INDEX = NO
|
DISABLE_INDEX = YES
|
||||||
GENERATE_TREEVIEW = YES
|
GENERATE_TREEVIEW = YES
|
||||||
FULL_SIDEBAR = NO
|
FULL_SIDEBAR = NO
|
||||||
ENUM_VALUES_PER_LINE = 4
|
ENUM_VALUES_PER_LINE = 4
|
||||||
|
BIN
docs/images/applifetime.png
Normal file
BIN
docs/images/applifetime.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
BIN
docs/images/blankapp.png
Normal file
BIN
docs/images/blankapp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@ -4,11 +4,12 @@
|
|||||||
<navindex>
|
<navindex>
|
||||||
<tab type="mainpage" visible="yes" title=""/>
|
<tab type="mainpage" visible="yes" title=""/>
|
||||||
<tab type="pages" visible="yes" title="" intro=""/>
|
<tab type="pages" visible="yes" title="" intro=""/>
|
||||||
<tab type="modules" visible="yes" title="" intro=""/>
|
<tab type="modules" visible="no" title="" intro=""/>
|
||||||
<tab type="namespaces" visible="no" title="API">
|
<tab type="namespaces" visible="no" title="API">
|
||||||
<tab type="namespacelist" visible="yes" title="API" intro="Here, you can find a list of every useful class to use in NF."/>
|
<tab type="namespacelist" visible="yes" title="API" intro="Here, you can find a list of every useful class to use in NF."/>
|
||||||
<tab type="namespacemembers" visible="no" title="" intro=""/>
|
<tab type="namespacemembers" visible="no" title="" intro=""/>
|
||||||
</tab>
|
</tab>
|
||||||
|
<tab type="user" url="@ref macros" title="Macros" intro=""/>
|
||||||
<tab type="concepts" visible="yes" title="">
|
<tab type="concepts" visible="yes" title="">
|
||||||
</tab>
|
</tab>
|
||||||
<tab type="interfaces" visible="yes" title="">
|
<tab type="interfaces" visible="yes" title="">
|
||||||
@ -35,7 +36,7 @@
|
|||||||
<tab type="filelist" visible="no" title="" intro=""/>
|
<tab type="filelist" visible="no" title="" intro=""/>
|
||||||
<tab type="globals" visible="no" title="" intro=""/>
|
<tab type="globals" visible="no" title="" intro=""/>
|
||||||
</tab>
|
</tab>
|
||||||
<tab type="examples" visible="yes" title="" intro=""/>
|
<tab type="examples" visible="yes" title="Snippets" intro="Here, you can find a list of snippets that showcase different features of the engine."/>
|
||||||
</navindex>
|
</navindex>
|
||||||
|
|
||||||
<!-- Layout definition for a class page -->
|
<!-- Layout definition for a class page -->
|
||||||
|
@ -6,13 +6,127 @@ This tutorial aims to teach the basics of the engine and how to use it.
|
|||||||
First, follow the steps on the @ref install page. Once the template MSVC project is setup,
|
First, follow the steps on the @ref install page. Once the template MSVC project is setup,
|
||||||
you can begin here.
|
you can begin here.
|
||||||
|
|
||||||
@section nfArch NF Engine Architecture
|
@section nfArch Engine Architecture
|
||||||
|
|
||||||
|
An NF app is made up of a set of states represented by the nf::Gamestate class. When
|
||||||
|
an nf::Application is running, it is either running a state or loading one. Below is an
|
||||||
|
image that describes what the main thread of an NF app would be typically doing in
|
||||||
|
the program's lifetime.
|
||||||
|
|
||||||
|
@image html applifetime.png "The lifetime of a typical NF app" width=20%
|
||||||
|
|
||||||
|
Using the engine's architecture, you might not even write any functions that are called
|
||||||
|
from `main`. Most of the code that programs the engine's behavior should be called in
|
||||||
|
your state's [update function](@ref nf::Gamestate::update).
|
||||||
|
|
||||||
|
To allow a translate unit to use the engine, you must include `NothinFancy.h`. This
|
||||||
|
header contains every class and function.
|
||||||
|
|
||||||
@section createConfig Creating a Config
|
@section createConfig Creating a Config
|
||||||
|
|
||||||
@todo The tutorial page
|
The first step to creating an app is creating an nf::Config. A config describes how the
|
||||||
|
engine should display on the screen. nf::Config has these fields:
|
||||||
|
|
||||||
|
- `width` - The width of the window if `fullscreen` is set to `false`
|
||||||
|
- `height` - The height of the window if `fullscreen` is set to `false`
|
||||||
|
- `fullscreen` - `true` sets the display to the size of the monitor the app is
|
||||||
|
- `title` - The title of the window shown on the caption bar and taskbar
|
||||||
|
opened on
|
||||||
|
|
||||||
|
To create a 1280 by 720 window with a title of "NF Example", you would write:
|
||||||
|
|
||||||
|
~~~cpp
|
||||||
|
nf::Config conf;
|
||||||
|
conf.width = 1280;
|
||||||
|
conf.height = 720;
|
||||||
|
conf.fullscreen = false;
|
||||||
|
conf.title = "NF Example";
|
||||||
|
|
||||||
|
//Or...
|
||||||
|
|
||||||
|
nf::Config conf2{ 1280, 720, false, "NF Example" };
|
||||||
|
~~~
|
||||||
|
|
||||||
|
We then pass this config to an nf::Application
|
||||||
|
|
||||||
|
@section createApp Creating and Configuring an Application
|
||||||
|
|
||||||
|
The nf::Application class represents an instance of the engine. This is the point where
|
||||||
|
you will attach your states and run the engine.
|
||||||
|
|
||||||
|
@note In a program and on a single machine, there can only be one single instance of
|
||||||
|
this class at a time. Attempting to create mulitple will result in an error.
|
||||||
|
|
||||||
|
The constructor takes in the nf::Config we previously created:
|
||||||
|
|
||||||
|
~~~cpp
|
||||||
|
nf::Application app(conf);
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Constructing an application doesn't do much. It merely allows you to access the member
|
||||||
|
functions to setup your application.
|
||||||
|
|
||||||
|
Here are some functions you might want to call at this point:
|
||||||
|
|
||||||
|
- [setWindowIcon](@ref nf::Application::setWindowIcon) - Sets the icon of the window
|
||||||
|
- [setWindowCursor](@ref nf::Application::setWindowCursor) - Sets the cursor's image
|
||||||
|
when it is visible and inside the window
|
||||||
|
|
||||||
|
And here are the functions you **must** call before an app can run:
|
||||||
|
|
||||||
|
- [addState](@ref nf::Application::addState) - Adds a state to an app so that it can
|
||||||
|
access it later by a user-defined string identifier
|
||||||
|
- [setDefaultState](@ref nf::Application::setDefaultState) - Sets the state to load
|
||||||
|
after the logo state exits
|
||||||
|
|
||||||
|
Once these functions have been called, the app can be run:
|
||||||
|
|
||||||
|
~~~cpp
|
||||||
|
CustomGamestate* customState = new CustomGamestate; //Inherits nf::Gamestate
|
||||||
|
app.addState(customState, "State 1"); //"State One" is this state's identifier.
|
||||||
|
app.setDefaultState("State 1"); //Will error without this
|
||||||
|
app.run(); //Blocks until exit
|
||||||
|
~~~
|
||||||
|
|
||||||
|
@section createGamestate Creating a Gamestate
|
||||||
|
|
||||||
|
To create a gamestate, you must create a class that publicly inherits nf::Gamestate
|
||||||
|
and overrides its four virtual functions:
|
||||||
|
|
||||||
|
- [onEnter](@ref nf::Gamestate::onEnter) - Called when the state is loading; Where member
|
||||||
|
objects are initialized
|
||||||
|
- [update](@ref nf::Gamestate::update) - Called every frame after loading is complete;
|
||||||
|
Where custom behavior is defined
|
||||||
|
- [render](@ref nf::Gamestate::render) - Called after update; Selects what to render
|
||||||
|
- [onExit](@ref nf::Gamestate::onExit) - Called when the state is unloaded
|
||||||
|
|
||||||
|
A gamestate class might look something like this:
|
||||||
|
|
||||||
|
~~~cpp
|
||||||
|
class CustomGamestate : public nf::Gamestate {
|
||||||
|
public:
|
||||||
|
void onEnter() override;
|
||||||
|
void update(float deltaTime) override; //Note the parameter
|
||||||
|
void render(nf::Renderer& renderer) override;
|
||||||
|
void onExit() override;
|
||||||
|
|
||||||
|
//Implementations somewhere else...
|
||||||
|
|
||||||
|
private:
|
||||||
|
//Member objects here...
|
||||||
|
};
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Once an app has been setup and run with an empty state, you should be met with a black screen
|
||||||
|
after the logo state:
|
||||||
|
|
||||||
|
@image html blankapp.png "A blank gamestate" width=50%
|
||||||
|
|
||||||
|
Congratulations! You now have a basic NF app running. Now we can add objects to our world.
|
||||||
|
|
||||||
|
@section createEntities Adding 3D Objects
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@section createUI Creating a UI
|
@section createUI Creating a UI
|
||||||
|
|
||||||
@ -20,4 +134,4 @@ you can begin here.
|
|||||||
|
|
||||||
@todo Lighting page?
|
@todo Lighting page?
|
||||||
|
|
||||||
@section packaging Packaging Your Game
|
@section packaging Packaging Your App
|
@ -314,7 +314,7 @@ pre.fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.fragment {
|
div.fragment {
|
||||||
padding: 0 0 1px 0; /*Fixed: last line underline overlap border*/
|
padding: 5px 0 5px 5px; /*Fixed: last line underline overlap border*/
|
||||||
margin: 4px 8px 4px 2px;
|
margin: 4px 8px 4px 2px;
|
||||||
background-color: #FDFCFB;
|
background-color: #FDFCFB;
|
||||||
border: 1px solid #E5D5C4;
|
border: 1px solid #E5D5C4;
|
||||||
@ -322,9 +322,9 @@ div.fragment {
|
|||||||
|
|
||||||
div.line {
|
div.line {
|
||||||
font-family: monospace, fixed;
|
font-family: monospace, fixed;
|
||||||
font-size: 13px;
|
font-size: 15px;
|
||||||
min-height: 13px;
|
min-height: 13px;
|
||||||
line-height: 1.0;
|
line-height: 1.1;
|
||||||
text-wrap: unrestricted;
|
text-wrap: unrestricted;
|
||||||
white-space: -moz-pre-wrap; /* Moz */
|
white-space: -moz-pre-wrap; /* Moz */
|
||||||
white-space: -pre-wrap; /* Opera 4-6 */
|
white-space: -pre-wrap; /* Opera 4-6 */
|
||||||
|
Reference in New Issue
Block a user