summaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorSteph Enders <smenders@gmail.com>2022-06-15 23:36:43 -0400
committerSteph Enders <smenders@gmail.com>2022-06-21 15:20:33 -0400
commit09615be926efb7302bc348aa66feccb694b23ba8 (patch)
tree0adf5eeb39312649c4adc288e051d5251428a2c2 /src/main.cpp
v0.1.0 - Initial Commit
Create dng - a maze/puzzle game enging using Lua and SFML --- Initial setup commit This setups up the project for messing around with C++ and Lua bindings. So far this project just prints the defined dng map and lets you move the character around. What this fails to do is actually provide any reason to use Lua at the moment. So I need to figure out some way of enabling logic on the processing side of things. Fixup warning from IntelliJ Added onUpdate logic to move the enemies etc Created some algorithm logic for enemy movement Allowed for default overrides Made shortest path alg more efficent In the previous commit this algo waited until the "success" step came up in the queue. Now we have the check during the push - and if an hits we return true from the push_moves fn. Since we're only interested in the initial move (since we check moves every frame) we can only return true and then use the current step as the origin position to diff against the start to get the dx,dy Add scene controls and win/loss scenarios Setup ability to check collisions and transition game scene Remove SFML for now Create level 2 Fixup - Can now have levels without a proc.lua Checked existence of wrong file for loading defaults Add readme and ignore build files Setup so it can build on debian Reformat bill merge Make installable You can now do: `sudo make install` and have it publish and distribute the dng lua files to the share dir Bump version to 0.3.1 Opps forgot to unignore dng folder Force local version if in current dir This should allow development to ALWAYS prefer the local version of the lib - so if you have an installed version it won't override local changes Set version to 0.3.2 Bump version to 0.3.3 Update to use SFML (for gameplay) Intro/Win/Loss not supported yet Remove install logic for now + make mov overrides Allow for restart on win/loss Add scroll viewport and max window sizes Display win/loss (need restart view fix) Fix recenter view on restart v0.4.0 - SFML Dynamic text rescale This isn't the best since we rescale it every frame we render it on, we should render all the text once and remember it. If we want to support "resizing" we can do that in its own logic loop MessageBox + Filesystem lookups for files Created MessageBox which is a helper class to allow for printing any dialog in a scalable way. Added path overrides for lua files as well as the ability to seek the filesystem for specific paths for the fonts and such. Set version to 0.4.2 Creating submodules? Added SFML as third party lib Use git submodules for dependencies Set license to zlib/png Add thirdparty licenses and include in package Set version to 0.1.0
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp278
1 files changed, 278 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..99f8603
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,278 @@
+//========================================================================
+// dng
+//------------------------------------------------------------------------
+// Copyright (c) 2022 Steph Enders <steph@senders.io>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "CApi.h"
+#include "Level.h"
+#include "LuaApi.h"
+#include "MessageBox.h"
+#include "SfmlUtils.h"
+#ifdef __linux__
+#include "linux/res.h"
+#endif
+#include "lua.hpp"
+#include <SFML/Graphics.hpp>
+#include <cmath>
+#include <filesystem>
+#include <iostream>
+
+std::shared_ptr<Level> lvl;
+
+Scene scene;
+const int MAX_WIDTH = static_cast<int>(SPRITE_SIZE) * 20 * 4;
+const int MAX_HEIGHT = static_cast<int>(SPRITE_SIZE) * 20 * 3;
+
+int main(int argc, char **argv) {
+
+ if (argc <= 1) {
+ std::cerr << "Must pass in path to level directory" << std::endl;
+ return -1;
+ }
+
+ auto res = get_resources();
+
+ std::string lvl_pfx = argv[1];
+
+ std::filesystem::path mapFile{lvl_pfx + "/dng.map"};
+ std::filesystem::path luaFile{lvl_pfx + "/proc.lua"};
+
+ lvl = std::make_shared<Level>();
+ scene = Scene::INTRO;
+
+ lvl->loadLevelFromFile(mapFile.c_str());
+
+ lua_State *L_lvl = luaL_newstate();
+ luaL_openlibs(L_lvl);
+ init_c_api(L_lvl);
+
+ lua_State *L_default = luaL_newstate();
+ luaL_openlibs(L_default);
+ init_c_api(L_default);
+
+ if (std::filesystem::exists(res.defaultsFile) &&
+ luaL_dofile(L_default, res.defaultsFile.c_str()) != LUA_OK) {
+ std::cout << "Failed to load default proc" << std::endl;
+ luaL_error(L_default, "Error: %s", lua_tostring(L_default, -1));
+ return EXIT_FAILURE;
+ }
+
+ // Initialize to default
+ LState *l_state = init_default(L_default);
+
+ if (std::filesystem::exists(luaFile) &&
+ luaL_dofile(L_lvl, luaFile.c_str()) == LUA_OK) {
+ override_file_fns(L_lvl, l_state);
+ } else if (std::filesystem::exists(luaFile)) {
+ std::cout << "[C] No Good" << std::endl;
+ luaL_error(L_lvl, "Error: %s\n", lua_tostring(L_lvl, -1));
+ return EXIT_FAILURE;
+ }
+
+ float ZOOM = 0.5f;
+ sf::Vector2f mapBounds = {static_cast<float>(lvl->getWidth()) * SPRITE_SIZE,
+ static_cast<float>(lvl->getHeight()) * SPRITE_SIZE};
+ int width = static_cast<int>(static_cast<float>(lvl->getWidth()) / ZOOM *
+ SPRITE_SIZE / ZOOM);
+ int height = static_cast<int>(static_cast<float>(lvl->getHeight()) / ZOOM *
+ SPRITE_SIZE / ZOOM);
+ bool useViewport = false;
+ if (width > MAX_WIDTH) {
+ width = MAX_WIDTH;
+ useViewport = true;
+ }
+ if (height > MAX_HEIGHT) {
+ height = MAX_HEIGHT;
+ useViewport = true;
+ }
+
+ sf::RenderWindow window(sf::VideoMode(width, height), "dng");
+ window.setMouseCursorVisible(false);
+ window.setFramerateLimit(30);
+ sf::View view(window.getDefaultView());
+ view.zoom(ZOOM);
+ view.setSize(view.getSize() * ZOOM);
+ view.setViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
+ if (useViewport) {
+ view.setCenter(to_position(lvl->player) +
+ sf::Vector2f(SPRITE_SIZE / 2.f, SPRITE_SIZE / 2.f));
+ } else {
+ view.setCenter(view.getSize() / 2.f);
+ }
+
+ window.setView(view);
+ sf::Clock deltaClock;
+ sf::Font font;
+ font.loadFromFile(res.fontFile);
+
+ MessageBox intro;
+ MessageBox win;
+ MessageBox loss;
+
+ do {
+ sf::Event event{};
+ float dt = deltaClock.restart().asSeconds();
+
+ while (window.pollEvent(event)) {
+ if (event.type == sf::Event::Closed ||
+ sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) {
+ window.close();
+ }
+ if (!lua_onkeypress(l_state->onkeypress, get_key(event))) {
+ window.close();
+ }
+ }
+
+ if (scene == Scene::INTRO) {
+ if (!lua_onintro(l_state->onintro)) {
+ window.close();
+ }
+ } else if (scene == Scene::LEVEL) {
+ if (!lua_onupdate(l_state->onupdate, dt)) {
+ window.close();
+ }
+ } else if (scene == Scene::WIN) {
+ lua_onwin(l_state->onwin);
+ // window.close();
+ } else if (scene == Scene::LOSS) {
+ lua_onloss(l_state->onloss);
+ }
+
+ // Render
+ if (useViewport) {
+ // Reinitialize center view
+ if (scene == INTRO) {
+ if (useViewport) {
+ view.setCenter(to_position(lvl->player) +
+ sf::Vector2f(SPRITE_SIZE / 2.f, SPRITE_SIZE / 2.f));
+ } else {
+ view.setCenter(view.getSize() / 2.f);
+ }
+ }
+ sf::Vector2f newPos = to_position(lvl->player) + // center
+ sf::Vector2f(SPRITE_SIZE / 2.f, SPRITE_SIZE / 2.f);
+ sf::Vector2f diff =
+ newPos - (lvl->player.sprite.getPosition() +
+ sf::Vector2f(SPRITE_SIZE / 2.f, SPRITE_SIZE / 2.f));
+
+ if (diff.x > 0.f && newPos.x > view.getSize().x / 2.f) {
+ view.move({diff.x, 0.f});
+ }
+ if (diff.y > 0.f && newPos.y > view.getSize().y / 2.f) {
+ view.move({0.f, diff.y});
+ }
+ if (diff.x < 0.f && newPos.x < view.getCenter().x) {
+ view.move({diff.x, 0.f});
+ }
+ if (diff.y < 0.f && newPos.y < view.getCenter().y) {
+ view.move({0.f, diff.y});
+ }
+ // readjust for OB
+ if (view.getCenter().x - view.getSize().x / 2.f < 0.f) {
+ view.move({(view.getCenter().x - view.getSize().x / 2.f) * -1.f, 0.f});
+ }
+ if (view.getCenter().y - view.getSize().y / 2.f < 0.f) {
+ view.move({0.f, (view.getCenter().y - view.getSize().y / 2.f) * -1.f});
+ }
+ if (view.getCenter().x + view.getSize().x / 2.f > mapBounds.x) {
+ view.move(
+ {-1 * ((view.getCenter().x + view.getSize().x / 2.f) - mapBounds.x),
+ 0.f});
+ }
+ if (view.getCenter().y + view.getSize().y / 2.f > mapBounds.y) {
+ view.move({0.f, -1 * ((view.getCenter().y + view.getSize().y / 2.f) -
+ mapBounds.y)});
+ }
+ }
+
+ window.clear(BLANK_COLOR);
+ window.setView(view);
+ for (auto &rect : lvl->displayMap) {
+ window.draw(rect);
+ }
+ if (scene == Scene::LEVEL) {
+ for (auto &enemy : lvl->enemyPositions) {
+ enemy.sprite.setPosition(to_position(enemy));
+ window.draw(enemy.sprite);
+ }
+ for (auto &treasure : lvl->treasurePositions) {
+ treasure.sprite.setPosition(to_position(treasure));
+ window.draw(treasure.sprite);
+ }
+ }
+
+ if (scene != Scene::LOSS) {
+ lvl->player.sprite.setPosition(to_position(lvl->player));
+ window.draw(lvl->player.sprite);
+ }
+ if (scene == Scene::WIN) {
+ window.setView(window.getDefaultView());
+ if (win.msgs.empty()) {
+ win = initializeMessageBox({{"You Win!", LARGE_TEXT},
+ {"press [space] to restart", SMALL_TEXT}},
+ font, window.getSize());
+ }
+
+ window.draw(win.box);
+ for (auto &msg : win.msgs) {
+ window.draw(msg);
+ }
+ window.setView(view);
+ }
+ if (scene == Scene::LOSS) {
+ window.setView(window.getDefaultView());
+ if (loss.msgs.empty()) {
+ loss = initializeMessageBox({{"You Lose!", LARGE_TEXT},
+ {"press [space] to restart", SMALL_TEXT}},
+ font, window.getSize());
+ }
+
+ window.draw(loss.box);
+ for (auto &msg : loss.msgs) {
+ window.draw(msg);
+ }
+ window.setView(view);
+ }
+ if (scene == INTRO) {
+ window.setView(window.getDefaultView());
+ if (intro.msgs.empty()) {
+ intro = initializeMessageBox(
+ {{"Start!", LARGE_TEXT}, {"press [space]", SMALL_TEXT}}, font,
+ window.getSize());
+ }
+
+ window.draw(intro.box);
+ for (auto &msg : intro.msgs) {
+ window.draw(msg);
+ }
+ window.setView(view);
+ }
+ window.setView(view);
+ window.display();
+ } while (window.isOpen());
+
+ std::cout << "[C] Quit" << std::endl;
+
+ return EXIT_SUCCESS;
+}