diff --git a/Button.cpp b/Button.cpp new file mode 100644 index 0000000..4672323 --- /dev/null +++ b/Button.cpp @@ -0,0 +1,76 @@ +#include "Button.h" +#include +#include "Util.h" +#include "Vector.h" +#include "Cursor.h" + +Button::Button(const std::string & text, Vec2f position, float width, float height) : Text(text,position) +{ + this->width = width; + this->height = height; + this->planePosition = position; + + cursorOnButton = false; + alfa = 0.5f; + background = Vec3f(10, 10, 10); + //foreground = Vec3f(255, 255, 255); + this->setColor(Vec3f(255, 255, 255)); + + this->position.x += width / 2 - textWidth / 2; + this->position.y += height / 2 - textHeight / 2; +} + +Button::~Button() +{ + /*if (action != nullptr) + delete action;*/ +} + +void Button::draw(void) +{ + + glColor4f(background.x/255.0f, background.y / 255.0f, background.z / 255.0f, alfa); + + glBegin(GL_QUADS); + glVertex2f(planePosition.x, planePosition.y); + glVertex2f(planePosition.x, planePosition.y + height); + glVertex2f(planePosition.x + width, planePosition.y + height); + glVertex2f(planePosition.x + width, planePosition.y); + glEnd(); + + /*glColor4f(foreground.x / 255.0f, foreground.y / 255.0f, foreground.z / 255.0f, 1.0f); + Util::glutBitmapString(text, position.x, position.y+height/2+14/2);*/ + Text::draw(); +} + +void Button::update(int x, int y) +{ + cursorOnButton = + (x > planePosition.x && x < planePosition.x + width) && + y > planePosition.y && y < planePosition.y + height; + + + if (cursorOnButton) + alfa = 1.0f; + else + alfa = 0.5f; + + if (cursorOnButton && Cursor::getInstance()->clicked) + if(action != nullptr) + action(this); +} + +void Button::addAction(action_function action) +{ + this->action = action; +} + +void Button::setForeground(Vec3f color) +{ + this->setColor(color); +} + +void Button::setBackground(Vec3f color) +{ + background = color; +} diff --git a/Button.h b/Button.h new file mode 100644 index 0000000..27d617e --- /dev/null +++ b/Button.h @@ -0,0 +1,30 @@ +#pragma once +#include "Text.h" + + + +class Button : public Text +{ +private: + typedef void(*action_function)(Button* b); + float width, height; + Vec3f background; + Vec2f planePosition; + bool cursorOnButton; + float alfa; + action_function action = nullptr; +public: + Button(const std::string &text, Vec2f position, float width, float height); + ~Button(); + + + + void draw(); + void update(int x, int y); + + void addAction(action_function action); + + void setForeground(Vec3f color); + void setBackground(Vec3f color); +}; + diff --git a/CrystalPoint.cpp b/CrystalPoint.cpp index 867a0b6..f72d400 100644 --- a/CrystalPoint.cpp +++ b/CrystalPoint.cpp @@ -5,23 +5,33 @@ #include #include "WorldHandler.h" #include "Player.h" +#include "Cursor.h" +#include "Menu.h" +#include "Text.h" +#include "Vector.h" +#include "Button.h" int CrystalPoint::width = 0; int CrystalPoint::height = 0; SoundSystem CrystalPoint::sound_system; +bool state = false; + + void CrystalPoint::init() { player = Player::getInstance(); worldhandler = WorldHandler::getInstance(); - //cursor = Cursor::getInstance(); + cursor = Cursor::getInstance(); + + menu = new Menu(); + buildMenu(); lastFrameTime = 0; + state = true; glClearColor(0.7f, 0.7f, 1.0f, 1.0f); - - mousePosition = Vec2f(width / 2, height / 2); } @@ -39,9 +49,10 @@ void CrystalPoint::draw() glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + worldhandler->draw(); - - //cursor->draw(); + if(!state) + menu->draw(); glutSwapBuffers(); } @@ -53,41 +64,45 @@ void CrystalPoint::update() float deltaTime = frameTime - lastFrameTime; lastFrameTime = frameTime; - if (keyboardState.special[GLUT_KEY_LEFT] && !prevKeyboardState.special[GLUT_KEY_LEFT]) - worldhandler->PreviousWorld(); - if (keyboardState.special[GLUT_KEY_RIGHT] && !prevKeyboardState.special[GLUT_KEY_RIGHT]) - worldhandler->NextWorld(); - if (keyboardState.keys[27]) - exit(0); + if (state) + { + if (keyboardState.special[GLUT_KEY_LEFT] && !prevKeyboardState.special[GLUT_KEY_LEFT]) + worldhandler->PreviousWorld(); + if (keyboardState.special[GLUT_KEY_RIGHT] && !prevKeyboardState.special[GLUT_KEY_RIGHT]) + worldhandler->NextWorld(); + if (keyboardState.keys[27]) + state = false; - Player* player = Player::getInstance(); + Player* player = Player::getInstance(); - player->rotation.y += mouseOffset.x / 10.0f; - player->rotation.x += mouseOffset.y / 10.0f; - if (player->rotation.x > 90) - player->rotation.x = 90; - if (player->rotation.x < -90) - player->rotation.x = -90; + player->rotation.y += mouseOffset.x / 10.0f; + player->rotation.x += mouseOffset.y / 10.0f; + if (player->rotation.x > 90) + player->rotation.x = 90; + if (player->rotation.x < -90) + player->rotation.x = -90; - float speed = 10; + float speed = 10; - Vec3f oldPosition = player->position; - if (keyboardState.keys['a']) player->setPosition(0, deltaTime*speed, false); - if (keyboardState.keys['d']) player->setPosition(180, deltaTime*speed, false); - if (keyboardState.keys['w']) player->setPosition(90, deltaTime*speed, false); - if (keyboardState.keys['s']) player->setPosition(270, deltaTime*speed, false); - if (keyboardState.keys['q']) player->setPosition(1, deltaTime*speed, true); - if (keyboardState.keys['e']) player->setPosition(-1, deltaTime*speed, true); + Vec3f oldPosition = player->position; + if (keyboardState.keys['a']) player->setPosition(0, deltaTime*speed, false); + if (keyboardState.keys['d']) player->setPosition(180, deltaTime*speed, false); + if (keyboardState.keys['w']) player->setPosition(90, deltaTime*speed, false); + if (keyboardState.keys['s']) player->setPosition(270, deltaTime*speed, false); + if (keyboardState.keys['q']) player->setPosition(1, deltaTime*speed, true); + if (keyboardState.keys['e']) player->setPosition(-1, deltaTime*speed, true); - if (!worldhandler->isPlayerPositionValid()) - player->position = oldPosition; + if (!worldhandler->isPlayerPositionValid()) + player->position = oldPosition; + player->position.y = worldhandler->getHeight(player->position.x, player->position.z) + 1.7f; + worldhandler->update(deltaTime); + } + else + { + menu->update(); + cursor->update(cursor->mousePosition + mouseOffset); + } - 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; @@ -96,6 +111,28 @@ void CrystalPoint::update() sound_system.SetListener(player->position, Vec3f(), Vec3f()); } +void CrystalPoint::buildMenu() +{ + Button* start = new Button("Resume", Vec2f(1920 / 2 - 50, 1080 / 2 - 30), 100, 50); + auto toWorld = [](Button* b) + { + state = true; + }; + start->addAction(toWorld); + menu->AddMenuElement(start); + + + Button* test = new Button("Exit", Vec2f(1920 / 2 - 50, 1080 / 2 + 30), 100, 50); + test->addAction([](Button* b) + { + exit(0); + }); + menu->AddMenuElement(test); + Text* t = new Text("Pause", Vec2f(1920 / 2 - Util::glutTextWidth("Pause") / 2, 1080 / 2 - 75)); + t->setColor(Vec3f(255, 255, 0)); + menu->AddMenuElement(t); +} + KeyboardState::KeyboardState() diff --git a/CrystalPoint.h b/CrystalPoint.h index 5437d5c..c22f3f5 100644 --- a/CrystalPoint.h +++ b/CrystalPoint.h @@ -3,6 +3,8 @@ class WorldHandler; class SoundSystem; class Player; +class Cursor; +class Menu; #include "Vector.h" #include "SoundSystem.h" @@ -25,6 +27,9 @@ public: WorldHandler* worldhandler; Player* player; + Cursor* cursor; + + Menu* menu; static int width, height; KeyboardState keyboardState; @@ -36,7 +41,9 @@ public: float lastFrameTime; static SoundSystem& GetSoundSystem() { return sound_system; } + private: static SoundSystem sound_system; + void buildMenu(); }; \ No newline at end of file diff --git a/CrystalPoint.vcxproj b/CrystalPoint.vcxproj index 9cde889..e6702fa 100644 --- a/CrystalPoint.vcxproj +++ b/CrystalPoint.vcxproj @@ -154,6 +154,7 @@ + @@ -164,18 +165,23 @@ + + + + + @@ -186,6 +192,8 @@ + + @@ -193,6 +201,8 @@ + + @@ -201,14 +211,12 @@ - - - - + + diff --git a/CrystalPoint.vcxproj.filters b/CrystalPoint.vcxproj.filters index 356087f..8a2269b 100644 --- a/CrystalPoint.vcxproj.filters +++ b/CrystalPoint.vcxproj.filters @@ -22,6 +22,9 @@ {9c655946-3f99-44ea-bc97-2817656954e0} + + {e7a88896-78e1-4544-bfc8-cfd55323728e} + @@ -87,6 +90,21 @@ Source Files + + Source Files\Menu + + + Source Files\Menu + + + Source Files\Menu + + + Source Files\Menu + + + Source Files\Menu + @@ -152,6 +170,21 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -166,18 +199,12 @@ Source Files\json - - Source Files\json - - + Resource Files - - Resource Files - - + Resource Files diff --git a/Cursor.cpp b/Cursor.cpp index 6f2d5b2..d5ce794 100644 --- a/Cursor.cpp +++ b/Cursor.cpp @@ -8,10 +8,13 @@ Cursor* Cursor::instance = NULL; Cursor::Cursor() { enabled = false; + mousePosition = Vec2f(CrystalPoint::width / 2, CrystalPoint::height / 2); + clicked = false; } Cursor::~Cursor() { + } Cursor* Cursor::getInstance(void) @@ -54,5 +57,24 @@ void Cursor::draw(void) void Cursor::update(Vec2f newPosition) { + if (newPosition.x < 0) + newPosition.x = 0; + + if (newPosition.y < 0) + newPosition.y = 0; + + if (newPosition.x > CrystalPoint::width) + newPosition.x = CrystalPoint::width; + + if (newPosition.y > CrystalPoint::height) + newPosition.y = CrystalPoint::height; + mousePosition = newPosition; + + if (clicked) + clicked = !clicked; + if (state != prev) + if(state == GLUT_UP) + clicked = true; + prev = state; } diff --git a/Cursor.h b/Cursor.h index 78764f0..dd0835e 100644 --- a/Cursor.h +++ b/Cursor.h @@ -8,9 +8,9 @@ private: static Cursor* instance; bool enabled; - Vec2f mousePosition; -public: +public: + Vec2f mousePosition; ~Cursor(); static Cursor* getInstance(void); @@ -18,6 +18,10 @@ public: void enable(bool enable); bool isEnabled(void); + bool clicked; + int state, prev; + + void draw(void); void update(Vec2f newPosition); }; diff --git a/Interface.cpp b/Interface.cpp index a1d83e4..0f912de 100644 --- a/Interface.cpp +++ b/Interface.cpp @@ -5,9 +5,7 @@ #include #include "Player.h" - -//Prototype -void glutBitmapString(std::string str, int x, int y); +#include "Util.h" Interface::Interface() { @@ -87,7 +85,7 @@ void Interface::draw() //Text: level glColor4f(1.0f, 1.0f, 0.1f, 1.0); - glutBitmapString("Level: " + std::to_string(player->level), 490, 900); + Util::glutBitmapString("Level: " + std::to_string(player->level), 490, 900); for (int i = 0; i < maxCrystals; i++) { @@ -118,13 +116,4 @@ void Interface::draw() 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/Main.cpp b/Main.cpp index b7c7c06..f593110 100644 --- a/Main.cpp +++ b/Main.cpp @@ -4,6 +4,11 @@ #include #include "Vector.h" +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +#include "Cursor.h" + void configureOpenGL(void); CrystalPoint* app; @@ -50,6 +55,17 @@ int main(int argc, char* argv[]) glutPassiveMotionFunc(mousemotion); glutMotionFunc(mousemotion); + auto mouseclick = [](int button, int state, + int x, int y) + { + if (button == GLUT_LEFT_BUTTON) + Cursor::getInstance()->state = state; + + //std::cout << "Left button is down" << std::endl; + }; + + glutMouseFunc(mouseclick); + CrystalPoint::height = GLUT_WINDOW_HEIGHT; CrystalPoint::width = GLUT_WINDOW_WIDTH; @@ -66,7 +82,8 @@ void configureOpenGL() glutInitWindowSize(800, 600); //glutInitWindowPosition(glutGet(GLUT_WINDOW_WIDTH) / 2 - 800/2, glutGet(GLUT_WINDOW_HEIGHT) / 2 - 600/2); glutCreateWindow("Crystal Point"); - //glutFullScreen(); + glutFullScreen(); + //Depth testing glEnable(GL_DEPTH_TEST); diff --git a/Menu.cpp b/Menu.cpp new file mode 100644 index 0000000..083a9db --- /dev/null +++ b/Menu.cpp @@ -0,0 +1,59 @@ +#include +#include "Menu.h" +#include "CrystalPoint.h" + +Menu::Menu() +{ + cursor = Cursor::getInstance(); +} + + +Menu::~Menu() +{ +} + +void Menu::draw(void) +{ + //Switch view to Ortho + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, CrystalPoint::width, CrystalPoint::height, 0, -10, 10); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + + glColor4f(60/255.0f, 60/255.0f, 60/255.0f, 0.8f); + glBegin(GL_QUADS); + glVertex2f(0,0); + glVertex2f(0, CrystalPoint::height); + glVertex2f(CrystalPoint::width, CrystalPoint::height); + glVertex2f(CrystalPoint::width, 0); + glEnd(); + + + for (MenuElement* e : elements) + { + e->draw(); + } + + cursor->draw(); + + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); +} + +void Menu::update() +{ + for (MenuElement* e : elements) + { + e->update(cursor->mousePosition.x, cursor->mousePosition.y); + } +} + +void Menu::AddMenuElement(MenuElement * e) +{ + elements.push_back(e); +} diff --git a/Menu.h b/Menu.h new file mode 100644 index 0000000..afed8ee --- /dev/null +++ b/Menu.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include "MenuElement.h" +#include "Cursor.h" + +class Menu +{ +private: + std::vector elements; + Cursor* cursor; +public: + Menu(); + ~Menu(); + + void draw(void); + void update(void); + + void AddMenuElement(MenuElement* e); +}; + diff --git a/MenuElement.cpp b/MenuElement.cpp new file mode 100644 index 0000000..e5bc349 --- /dev/null +++ b/MenuElement.cpp @@ -0,0 +1,12 @@ +#include "MenuElement.h" + +MenuElement::MenuElement(Vec2f position) +{ + hover = false; + this->position = position; +} + + +MenuElement::~MenuElement() +{ +} diff --git a/MenuElement.h b/MenuElement.h new file mode 100644 index 0000000..4f09c21 --- /dev/null +++ b/MenuElement.h @@ -0,0 +1,17 @@ +#pragma once +#include "Vector.h" +#include + +class MenuElement +{ +protected: + bool hover; + Vec2f position; +public: + MenuElement(Vec2f position); + ~MenuElement(); + + virtual void draw(void) {}; + virtual void update(int x, int y) {}; +}; + diff --git a/Model.cpp b/Model.cpp index caf7979..8fa61d5 100644 --- a/Model.cpp +++ b/Model.cpp @@ -1,6 +1,5 @@ #include "Model.h" -#define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" #include diff --git a/Skybox.cpp b/Skybox.cpp index bd91a23..8a9b958 100644 --- a/Skybox.cpp +++ b/Skybox.cpp @@ -1,6 +1,7 @@ #include "cmath" #include +#include "Util.h" #include "stb_image.h" #include "Skybox.h" #include @@ -25,12 +26,12 @@ Skybox::~Skybox() void Skybox::init() { - skybox[SKY_LEFT] = loadTexture(folder + "left.png"); - skybox[SKY_BACK] = loadTexture(folder + "back.png"); - skybox[SKY_RIGHT] = loadTexture(folder + "right.png"); - skybox[SKY_FRONT] = loadTexture(folder + "front.png"); - skybox[SKY_TOP] = loadTexture(folder + "top.png"); - skybox[SKY_BOTTOM] = loadTexture(folder + "bottom.png"); + skybox[SKY_LEFT] = Util::loadTexture(folder + "left.png"); + skybox[SKY_BACK] = Util::loadTexture(folder + "back.png"); + skybox[SKY_RIGHT] = Util::loadTexture(folder + "right.png"); + skybox[SKY_FRONT] = Util::loadTexture(folder + "front.png"); + skybox[SKY_TOP] = Util::loadTexture(folder + "top.png"); + skybox[SKY_BOTTOM] = Util::loadTexture(folder + "bottom.png"); } void Skybox::draw() diff --git a/Skybox.h b/Skybox.h index 84c5a98..0f0cbbf 100644 --- a/Skybox.h +++ b/Skybox.h @@ -14,6 +14,8 @@ public: void init(); void draw(); + void update(float deltaTime, int, int); GLuint loadTexture(const std::string &fileName); + }; diff --git a/Text.cpp b/Text.cpp new file mode 100644 index 0000000..67afd42 --- /dev/null +++ b/Text.cpp @@ -0,0 +1,31 @@ +#include "Text.h" + + +Text::Text(const std::string &text, Vec2f position) : MenuElement(position) +{ + this->text = text; + color = Vec3f(50, 150, 150); + textHeight = 14; + textWidth = Util::glutTextWidth(text); +} + + +Text::~Text() +{ +} + +void Text::draw() +{ + glColor4f(color.x/255.0f, color.y/255.0f, color.z/255.0f, 1.0f); + Util::glutBitmapString(text, position.x-1, position.y+textHeight); +} + +void Text::update(int x, int y) +{ + //Do nothing +} + +void Text::setColor(Vec3f color) +{ + this->color = color; +} diff --git a/Text.h b/Text.h new file mode 100644 index 0000000..b24bb25 --- /dev/null +++ b/Text.h @@ -0,0 +1,23 @@ +#pragma once +#include "MenuElement.h" +#include "Vector.h" +#include "Util.h" + +class Text : public MenuElement +{ +private: + std::string text; + Vec3f color; +protected: + int textWidth; + int textHeight; +public: + Text(const std::string &text, Vec2f position); + ~Text(); + + virtual void draw(); + virtual void update(int x, int y); + + void setColor(Vec3f color); +}; + diff --git a/Util.cpp b/Util.cpp new file mode 100644 index 0000000..5f052de --- /dev/null +++ b/Util.cpp @@ -0,0 +1,65 @@ +#include "Util.h" +#include "stb_image.h" + +Util::Util() +{ + +} + + +Util::~Util() +{ +} + +GLuint Util::loadTexture(const std::string &filename) +{ + int width, height, bpp; + + stbi_set_flip_vertically_on_load(true); + unsigned char* imgData = stbi_load(filename.c_str(), &width, &height, &bpp, 4); + GLuint num; + glGenTextures(1, &num); + glBindTexture(GL_TEXTURE_2D, num); + + glTexImage2D(GL_TEXTURE_2D, + 0, //level + GL_RGBA, //internal format + width, //width + height, //height + 0, //border + GL_RGBA, //data format + GL_UNSIGNED_BYTE, //data type + imgData); //data + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + stbi_image_free(imgData); + return num; +} + +void Util::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]); + } +} + +int Util::glutTextWidth(const std::string str) +{ + int total = 0; + for (int i = 0; i < str.size(); i++) + { + total += glutBitmapWidth(GLUT_BITMAP_HELVETICA_18, str[i]); + } + return total; +} + +//int Util::glutTextHeight() +//{ +// return glutBitmapHeight(GLUT_BITMAP_HELVETICA_18); +//} + diff --git a/Util.h b/Util.h new file mode 100644 index 0000000..54089ee --- /dev/null +++ b/Util.h @@ -0,0 +1,16 @@ +#pragma once +#include +#include + +class Util +{ +private: + Util(); + ~Util(); +public: + static GLuint loadTexture(const std::string &filename); + static void glutBitmapString(std::string str, int x, int y); + static int glutTextWidth(const std::string str); + //static int glutTextHeight(); +}; + diff --git a/World.cpp b/World.cpp index c3141c1..5df11dc 100644 --- a/World.cpp +++ b/World.cpp @@ -214,6 +214,7 @@ World::~World() music->Stop(); delete music; delete skybox; + delete portal; } std::pair World::getObjectFromValue(int val)