diff --git a/CrystalPoint.cpp b/CrystalPoint.cpp index 765659b..a6aa67b 100644 --- a/CrystalPoint.cpp +++ b/CrystalPoint.cpp @@ -6,10 +6,14 @@ #include "WorldHandler.h" #include "Player.h" +int CrystalPoint::width = 0; +int CrystalPoint::height = 0; + void CrystalPoint::init() { player = Player::getInstance(); worldhandler = WorldHandler::getInstance(); + //cursor = Cursor::getInstance(); lastFrameTime = 0; @@ -34,23 +38,8 @@ void CrystalPoint::draw() glLoadIdentity(); worldhandler->draw(); - - //Draw Cursor - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0,width, height,0,-10,10); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glColor4f(1, cos(glutGet(GLUT_ELAPSED_TIME) / 1000.0f), sin(glutGet(GLUT_ELAPSED_TIME) / 1000.0f), 1); - - glBegin(GL_TRIANGLES); - glVertex2f(mousePosition.x, mousePosition.y); - glVertex2f(mousePosition.x+15, mousePosition.y+15); - glVertex2f(mousePosition.x+5, mousePosition.y+20); - glEnd(); + //cursor->draw(); glutSwapBuffers(); } @@ -78,7 +67,7 @@ void CrystalPoint::update() if (player->rotation.x < -90) player->rotation.x = -90; - float speed = 2; + float speed = 1; Vec3f oldPosition = player->position; if (keyboardState.keys['a']) player->setPosition(0, deltaTime*speed, false); @@ -91,11 +80,13 @@ void CrystalPoint::update() if (!worldhandler->isPlayerPositionValid()) player->position = oldPosition; - player->position.y = worldhandler->getHeight(player->position.x, player->position.z) + 2.5f; + player->position.y = worldhandler->getHeight(player->position.x, player->position.z) + 1.7f; + worldhandler->update(deltaTime); mousePosition = mousePosition + mouseOffset; + //cursor->update(mousePosition); mouseOffset = Vec2f(0, 0); prevKeyboardState = keyboardState; diff --git a/CrystalPoint.h b/CrystalPoint.h index fef6a36..da4a3b8 100644 --- a/CrystalPoint.h +++ b/CrystalPoint.h @@ -24,12 +24,11 @@ public: WorldHandler* worldhandler; Player* player; - int width, height; + static int width, height; KeyboardState keyboardState; KeyboardState prevKeyboardState; Vec2f mouseOffset; - Vec2f mousePosition; float lastFrameTime; diff --git a/CrystalPoint.vcxproj b/CrystalPoint.vcxproj index 059cfd0..6d8f904 100644 --- a/CrystalPoint.vcxproj +++ b/CrystalPoint.vcxproj @@ -152,9 +152,11 @@ + + @@ -167,9 +169,11 @@ + + diff --git a/CrystalPoint.vcxproj.filters b/CrystalPoint.vcxproj.filters index 039c7fc..fbafa70 100644 --- a/CrystalPoint.vcxproj.filters +++ b/CrystalPoint.vcxproj.filters @@ -63,6 +63,12 @@ Source Files + + Source Files + + + Source Files\World + @@ -77,9 +83,6 @@ Header Files - - Header Files - Header Files @@ -107,6 +110,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + diff --git a/Cursor.cpp b/Cursor.cpp new file mode 100644 index 0000000..69895a3 --- /dev/null +++ b/Cursor.cpp @@ -0,0 +1,58 @@ +#include "Cursor.h" +#include +#include +#include "CrystalPoint.h" + +Cursor* Cursor::instance = NULL; + +Cursor::Cursor() +{ + enabled = false; +} + +Cursor::~Cursor() +{ +} + +Cursor* Cursor::getInstance(void) +{ + if (instance == nullptr) + instance = new Cursor(); + + return instance; +} + +void Cursor::enable(bool enable) +{ + enabled = enable; +} + +bool Cursor::isEnabled(void) +{ + return enabled; +} + +void Cursor::draw(void) +{ + //Draw Cursor + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, CrystalPoint::width, CrystalPoint::height, 0, -10, 10); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glColor4f(1, cos(glutGet(GLUT_ELAPSED_TIME) / 1000.0f), sin(glutGet(GLUT_ELAPSED_TIME) / 1000.0f), 1); + + glBegin(GL_TRIANGLES); + glVertex2f(mousePosition.x, mousePosition.y); + glVertex2f(mousePosition.x + 15, mousePosition.y + 15); + glVertex2f(mousePosition.x + 5, mousePosition.y + 20); + glEnd(); +} + +void Cursor::update(Vec2f newPosition) +{ + mousePosition = newPosition; +} diff --git a/Cursor.h b/Cursor.h new file mode 100644 index 0000000..78764f0 --- /dev/null +++ b/Cursor.h @@ -0,0 +1,24 @@ +#pragma once +#include "Vector.h" + +class Cursor +{ +private: + Cursor(); + + static Cursor* instance; + bool enabled; + Vec2f mousePosition; +public: + + ~Cursor(); + + static Cursor* getInstance(void); + + void enable(bool enable); + bool isEnabled(void); + + void draw(void); + void update(Vec2f newPosition); +}; + diff --git a/Entity.cpp b/Entity.cpp index d79b247..4be3945 100644 --- a/Entity.cpp +++ b/Entity.cpp @@ -31,7 +31,7 @@ void Entity::draw() glRotatef(rotation.y, 0, 1, 0); glRotatef(rotation.z, 0, 0, 1); glScalef(scale, scale, scale); - glTranslatef(-model->center.x, 0, -model->center.z); +//collision gaat hierdoor kapot glTranslatef(-model->center.x, 0, -model->center.z); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); diff --git a/HeightMap.cpp b/HeightMap.cpp index 9be0922..8a0cad9 100644 --- a/HeightMap.cpp +++ b/HeightMap.cpp @@ -14,16 +14,14 @@ #define BLUE 2 #define ALPHA 3 -HeightMap::HeightMap(const std::string &file, float scale, World* world) +HeightMap::HeightMap(const std::string &file, World* world) { - this->scale = scale; - int bpp; unsigned char* imgData = stbi_load(file.c_str(), &width, &height, &bpp, 4); auto heightAt = [&](int x, int y) { - return (imgData[(x + y * width) * 4 ] / 256.0f) * 100.0f; + return (imgData[(x + y * width) * 4 ] / 256.0f) * 50.0f; }; auto valueAt = [&](int x, int y, int offset = 0) @@ -40,21 +38,9 @@ HeightMap::HeightMap(const std::string &file, float scale, World* world) Vec3f ba(1, heightAt(x + 1, y) - heightAt(x, y), 0); - if ((valueAt(x, y, GREEN) >= 10) && (valueAt(x,y,GREEN) <= 100)) + if (valueAt(x, y, GREEN) > 0) { - world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)), Vec3f(x*scale, heightAt(x, y), y*scale), Vec3f(0, rand() % 360, 0), 1, true)); - } - if (valueAt(x, y, GREEN) == 180 || valueAt(x, y, GREEN) == 190 || valueAt(x, y, GREEN) == 170 || valueAt(x, y, GREEN) == 250) - { - world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)), Vec3f(x*scale, heightAt(x, y), y*scale), Vec3f(0, 0, 0), 1, true)); - } - if ((valueAt(x, y, GREEN) >= 200) && (valueAt(x, y, GREEN) <= 240)) - { - world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)), Vec3f(x*scale, heightAt(x, y), y*scale), Vec3f(0, 0, 0), 1, false)); - } - if (valueAt(x, y, GREEN) == 160) - { - world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)), Vec3f(x*scale, heightAt(x, y), y*scale), Vec3f(0, 0, 0), 1, false)); + world->addLevelObject(new LevelObject(world->getObjectFromValue(valueAt(x, y, GREEN)).first, Vec3f(x, heightAt(x, y), y), Vec3f(0, rand()%360, 0), 1, world->getObjectFromValue(valueAt(x, y, GREEN)).second)); } Vec3f normal = ca.cross(ba); @@ -63,7 +49,7 @@ HeightMap::HeightMap(const std::string &file, float scale, World* world) for (int i = 0; i < 4; i++) { float h = heightAt(x + offsets[i][0], y + offsets[i][1]); - vertices.push_back(Vertex{ (float)(x + offsets[i][0])*scale, h*scale, (float)(y + offsets[i][1])*scale, + vertices.push_back(Vertex{ (float)(x + offsets[i][0]), h, (float)(y + offsets[i][1]), normal.x, normal.y, normal.z, (x + offsets[i][0]) / (float)height, (y + offsets[i][1]) / (float)width } ); } @@ -121,13 +107,17 @@ void HeightMap::Draw() float HeightMap::GetHeight(float x, float y) { - x /= scale; - y /= scale; int ix = x; int iy = y; int index = (ix + (width - 1) * iy) * 4; + if (index + 3 >= vertices.size()) + index = vertices.size() - 4; + + if (index < 0) + index = 0; + Vertex& a = vertices[index]; Vertex& b = vertices[index+1]; Vertex& c = vertices[index+3]; diff --git a/HeightMap.h b/HeightMap.h index 0f3a141..fe2e963 100644 --- a/HeightMap.h +++ b/HeightMap.h @@ -14,9 +14,8 @@ private: int width; GLuint imageIndex; - int scale; public: - HeightMap(const std::string &file, float scale, World* world); + HeightMap(const std::string &file, World* world); ~HeightMap(); void Draw(); diff --git a/Interface.cpp b/Interface.cpp new file mode 100644 index 0000000..85d2778 --- /dev/null +++ b/Interface.cpp @@ -0,0 +1,94 @@ +#include "Interface.h" +#include +#include "CrystalPoint.h" + +#include + +#include "Player.h" + +//Prototype +void glutBitmapString(std::string str, int x, int y); + +Interface::Interface() +{ +} + + +Interface::~Interface() +{ +} + +void Interface::draw() +{ + Player* player = Player::getInstance(); + + //Switch view to Ortho + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, 1000, 1000, 0, -10, 10); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + + //Draw interface + + //Health bar + glBegin(GL_QUADS); + glColor4f(0,0,0, 1.0); + glVertex2f(250, 980); + glVertex2f(250, 965); + glVertex2f(750, 965); + glVertex2f(750, 980); + glEnd(); + + glBegin(GL_QUADS); + glColor4f(1.0f, 0.1f, 0.1f, 1.0); + glVertex2f(250, 980); + glVertex2f(250, 965); + + glColor4f(1.0f, 0.5f, 0.5f, 1.0); + glVertex2f(250 + (player->health / 100 * 500), 965); + glVertex2f(250 + (player->health / 100 * 500), 980); + glEnd(); + + //XP bar + glBegin(GL_QUADS); + glColor4f(0, 0, 0, 1.0); + glVertex2f(250, 950); + glVertex2f(250, 935); + glVertex2f(750, 935); + glVertex2f(750, 950); + glEnd(); + + glBegin(GL_QUADS); + glColor4f(1.0f, 1.0f, 0.1f, 1.0); + glVertex2f(250, 950); + glVertex2f(250, 935); + + glColor4f(1.0f, 1.0f, 0.5f, 1.0); + glVertex2f(250 + (player->xp / 100 * 500), 935); + glVertex2f(250 + (player->xp / 100 * 500), 950); + glEnd(); + + //Text: level + glColor4f(1.0f, 1.0f, 0.1f, 1.0); + glutBitmapString("Level: " + std::to_string(player->level), 490, 900); + +} + +void Interface::update(float deltaTime) +{ + +} + +void glutBitmapString(std::string str, int x, int y) +{ + glRasterPos2f(x, y); + for (int i = 0; i < str.size(); i++) + { + glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, str[i]); + } +} \ No newline at end of file diff --git a/Interface.h b/Interface.h new file mode 100644 index 0000000..ddc756e --- /dev/null +++ b/Interface.h @@ -0,0 +1,11 @@ +#pragma once +class Interface +{ +public: + Interface(); + ~Interface(); + + void draw(void); + void update(float deltaTime); +}; + diff --git a/Main.cpp b/Main.cpp index b385658..d89aa26 100644 --- a/Main.cpp +++ b/Main.cpp @@ -21,7 +21,7 @@ int main(int argc, char* argv[]) glutDisplayFunc([]() { app->draw(); } ); glutIdleFunc([]() { app->update(); } ); - glutReshapeFunc([](int w, int h) { app->width = w; app->height = h; glViewport(0, 0, w, h); }); + glutReshapeFunc([](int w, int h) { CrystalPoint::width = w; CrystalPoint::height = h; glViewport(0, 0, w, h); }); //Keyboard glutKeyboardFunc([](unsigned char c, int, int) { app->keyboardState.keys[c] = true; }); @@ -29,8 +29,7 @@ int main(int argc, char* argv[]) glutSpecialFunc([](int c, int, int) { app->keyboardState.special[c] = true; }); glutSpecialUpFunc([](int c, int, int) { app->keyboardState.special[c] = false; }); - //Mouse - glutPassiveMotionFunc([](int x, int y) + auto mousemotion = [](int x, int y) { if (justMoved) { @@ -41,11 +40,18 @@ int main(int argc, char* argv[]) int dy = y - app->height / 2; if ((dx != 0 || dy != 0) && abs(dx) < 400 && abs(dy) < 400) { - app->mouseOffset = app->mouseOffset + Vec2f(dx,dy); + app->mouseOffset = app->mouseOffset + Vec2f(dx, dy); glutWarpPointer(app->width / 2, app->height / 2); justMoved = true; } - }); + }; + + //Mouse + glutPassiveMotionFunc(mousemotion); + glutMotionFunc(mousemotion); + + CrystalPoint::height = GLUT_WINDOW_HEIGHT; + CrystalPoint::width = GLUT_WINDOW_WIDTH; glutMainLoop(); return 0; @@ -57,7 +63,7 @@ void configureOpenGL() glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(800, 600); glutCreateWindow("Crystal Point"); - //glutFullScreen(); + glutFullScreen(); //Depth testing glEnable(GL_DEPTH_TEST); @@ -86,5 +92,5 @@ void configureOpenGL() glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); - glutSetCursor(GLUT_CURSOR_CROSSHAIR); + glutSetCursor(GLUT_CURSOR_NONE); } \ No newline at end of file diff --git a/Player.cpp b/Player.cpp index dcb172e..b43bd82 100644 --- a/Player.cpp +++ b/Player.cpp @@ -8,6 +8,9 @@ Player* Player::instance = NULL; Player::Player() { speed = 10; + health = 50; + xp = 75; + level = 10; } Player* Player::getInstance() diff --git a/Player.h b/Player.h index d9a2a8f..18d3fb8 100644 --- a/Player.h +++ b/Player.h @@ -23,6 +23,9 @@ public: Model* leftWeapon; Model* rightWeapon; + float health; + float xp; + int level; float speed; }; \ No newline at end of file diff --git a/World.cpp b/World.cpp index 1a9e533..c3a9500 100644 --- a/World.cpp +++ b/World.cpp @@ -3,13 +3,19 @@ #include "Entity.h" #include "json.h" #include "Model.h" +#include "CrystalPoint.h" #include #include World::World(const std::string &fileName) { + //Store player instance player = Player::getInstance(); + //Create the interface + interface = new Interface(); + + //Open world json file std::ifstream file(fileName); if(!file.is_open()) std::cout<<"Error, can't open world file - " << fileName << "\n"; @@ -27,67 +33,84 @@ World::World(const std::string &fileName) if (v["world"]["object-templates"].isNull()) std::cout << "Invalid world file: object templates - " << fileName << "\n"; - float scale = 1.0f; - if (!v["world"]["scale"].isNull()) - scale = v["world"]["scale"].asFloat(); - //Load object templates for (auto objt : v["world"]["object-templates"]) { - objecttemplates.push_back(std::pair(objt["color"], objt["file"])); + //collision + bool cancollide = true; + if (!objt["collision"].isNull()) + cancollide = objt["collision"].asBool(); + + objecttemplates.push_back(std::pair>(objt["color"], std::pair(objt["file"], cancollide))); } - heightmap = new HeightMap(v["world"]["heightmap"].asString(), scale, this); + //Generate heightmap for this world + heightmap = new HeightMap(v["world"]["heightmap"].asString(), this); + //Map different texture to heightmap if available if(!v["world"]["texture"].isNull()) heightmap->SetTexture(v["world"]["texture"].asString()); - player->position.x = v["player"]["startposition"][0].asFloat()*scale; - player->position.y = v["player"]["startposition"][1].asFloat()*scale; - player->position.z = v["player"]["startposition"][2].asFloat()*scale; - + //Set player starting position + player->position.x = v["player"]["startposition"][0].asFloat(); + player->position.y = v["player"]["startposition"][1].asFloat(); + player->position.z = v["player"]["startposition"][2].asFloat(); + //Load and place objects into world for (auto object : v["objects"]) { + //Collision bool hasCollision = true; if (!object["collide"].isNull()) hasCollision = object["collide"].asBool(); + //Rotation Vec3f rotation(0, 0, 0); if(!object["rot"].isNull()) rotation = Vec3f(object["rot"][0].asFloat(), object["rot"][1].asFloat(), object["rot"][2].asFloat()); + //Scale float scale = 1; if (!object["scale"].isNull()) scale = object["scale"].asFloat(); + //Position if (object["pos"].isNull()) std::cout << "Invalid world file: objects pos - " << fileName << "\n"; + + //File + if (object["file"].isNull()) + std::cout << "Invalid world file: objects file - " << fileName << "\n"; + //Create Vec3f position(object["pos"][0].asFloat(), object["pos"][1].asFloat(), object["pos"][2].asFloat()); - entities.push_back(new LevelObject(object["file"], position, rotation, scale, hasCollision)); + entities.push_back(new LevelObject(object["file"].asString(), position, rotation, scale, hasCollision)); } - //Enemies + //Load and place enemies into world for (auto e : v["enemies"]) { - std::string fileName = ""; - if (!e["file"].isNull()) - fileName = e["file"].asString(); - - Vec3f position(0, 0, 0); - if (!e["pos"].isNull()) - position = Vec3f(e["pos"][0].asFloat(), e["pos"][1].asFloat(), e["pos"][2].asFloat()); - + //Rotation Vec3f rotation(0, 0, 0); if (!e["rot"].isNull()) rotation = Vec3f(e["rot"][0].asFloat(), e["rot"][1].asFloat(), e["rot"][2].asFloat()); + //Scale float scale = 1.0f; if (!e["scale"].isNull()) scale = e["scale"].asFloat(); - enemies.push_back(new Enemy(fileName, position, rotation, scale)); + //Position + if (e["pos"].isNull()) + std::cout << "Invalid world file: enemies pos - " << fileName << "\n"; + + //File + if (e["file"].isNull()) + std::cout << "Invalid world file: enemies file - " << fileName << "\n"; + + //Create + Vec3f position(e["pos"][0].asFloat(), e["pos"][1].asFloat(), e["pos"][2].asFloat()); + enemies.push_back(new Enemy(e["file"].asString(), position, rotation, scale)); } } @@ -98,7 +121,7 @@ World::~World() delete heightmap; } -std::string World::getObjectFromValue(int val) +std::pair World::getObjectFromValue(int val) { for (auto i : objecttemplates) { @@ -120,10 +143,9 @@ void World::draw() float lightPosition[4] = { 0, 2, 1, 0 }; glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); - float lightAmbient[4] = { 0.5, 0.5, 0.5, 1 }; + float lightAmbient[4] = { 0.2, 0.2, 0.2, 1 }; glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); heightmap->Draw(); for (auto &enemy : enemies) @@ -131,6 +153,8 @@ void World::draw() for (auto &entity : entities) entity->draw(); + + interface->draw(); } void World::update(float elapsedTime) diff --git a/World.h b/World.h index de9c803..649e2d4 100644 --- a/World.h +++ b/World.h @@ -5,28 +5,30 @@ #include "Player.h" #include "Enemy.h" #include "LevelObject.h" +#include "Interface.h" class Entity; class World { private: - std::vector> objecttemplates; -public: - World(const std::string &fileName); - ~World(); - - std::vector entities; - std::vector enemies; + std::vector>> objecttemplates; Player* player; HeightMap* heightmap; + Interface* interface; + + std::vector entities; + std::vector enemies; +public: + World(const std::string &fileName); + ~World(); void draw(); void update(float elapsedTime); bool isPlayerPositionValid(); float getHeight(float x, float y); void addLevelObject(LevelObject* obj); - std::string getObjectFromValue(int i); + std::pair getObjectFromValue(int i); }; diff --git a/worlds/fire.json b/worlds/fire.json index 5d1368a..884df5a 100644 --- a/worlds/fire.json +++ b/worlds/fire.json @@ -2,7 +2,6 @@ "world": { "heightmap": "worlds/hell.png", "texture": "worlds/helltexture.png", - "scale": 1, "object-templates": [ { "color": 25, diff --git a/worlds/hell.png b/worlds/hell.png index 6d4789b..9cb983f 100644 Binary files a/worlds/hell.png and b/worlds/hell.png differ diff --git a/worlds/hmcs.png b/worlds/hmcs.png index 4666651..ea1bd5a 100644 Binary files a/worlds/hmcs.png and b/worlds/hmcs.png differ diff --git a/worlds/ice.json b/worlds/ice.json index 44b0137..eddb487 100644 --- a/worlds/ice.json +++ b/worlds/ice.json @@ -2,7 +2,13 @@ "world": { "heightmap": "worlds/hmcs.png", "texture": "worlds/hmcstexture.png", - "scale": 2 + "object-templates": [ + { + "color":100, + "file": "models/boom/Boom.obj", + "collision": false + } + ] }, "player": { "startposition": [ 100, 20, 100 ] diff --git a/worlds/small.json b/worlds/small.json index bd9ab49..466db7c 100644 --- a/worlds/small.json +++ b/worlds/small.json @@ -1,11 +1,11 @@ { "world": { "heightmap": "worlds/small.png", - "scale": 1, "object-templates": [ { "color":100, - "file": "models/boom/Boom.obj" + "file": "models/boom/Boom.obj", + "collision": false } ] }, diff --git a/worlds/small.png b/worlds/small.png index 72f885b..714b7cd 100644 Binary files a/worlds/small.png and b/worlds/small.png differ