]> code.bitgloo.com Git - clyne/gamedev.git/commitdiff
ui improvements
authorClyne Sullivan <tullivan99@gmail.com>
Tue, 3 Nov 2015 13:45:29 +0000 (08:45 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Tue, 3 Nov 2015 13:45:29 +0000 (08:45 -0500)
Changelog
include/common.h
include/ui.h
include/world.h
main.cpp
shader.frag
src/entities.cpp
src/inventory.cpp
src/ui.cpp
src/world.cpp
test.frag

index d53ac1399fde327e0684d4cae70538c64dea7e87..e2da060afd80c78b575135e4b1f02f98cc3efcbe 100644 (file)
--- a/Changelog
+++ b/Changelog
        - improved shaders (can now see drawn objects)
        - re-organized Goals.txt
        - began working on game concept/design/plot/everything (in google doc)
+
+11/3/2015:
+==========
+
+       - added world gen based off of functions
+       - added cutting to black
+       - added typewriter-esque text drawing
+       - documented ui.h
+       - continued work on GLSL shaders
index b016020393c9cb74fcf861ee08e674f0451a4c35..db60dd6b15560488d83d21aa58b5b872fb70a62b 100644 (file)
@@ -58,7 +58,7 @@ typedef struct {
 
 #define GAME_NAME              "Independent Study v.0.3 alpha"
 
-#define SCREEN_WIDTH   1280
+#define SCREEN_WIDTH   1200
 #define SCREEN_HEIGHT  720
 
 //#define FULLSCREEN
index 79ca9a7a7f1e2be6596b351880b88954a947cf28..6ebbd1fabb366d0076b75a8bf94da662e00a393b 100644 (file)
@@ -2,39 +2,87 @@
 #define UI_H
 
 #include <common.h>
-#include <cstdarg> // For putText()
+#include <cstdarg>
 
-#include <world.h> // World-switching stuff
-#include <ft2build.h> // FreeType stuff
+#include <world.h>
+#include <ft2build.h>
 #include FT_FREETYPE_H
 
 #define DEBUG
 
-namespace ui { // Functions are kept in a namespace simply
-                               // for organization
+namespace ui {
+
+       /*
+        *      Contains the coordinates of the mouse in the window.
+       */
 
        extern vec2 mouse;
 
+       /*
+        *      These flags are used elsewhere.
+       */
+
        extern bool debug;
        extern bool posFlag;
-       extern bool dialogBoxExists;
        extern unsigned int fontSize;
 
-       void initFonts(void);   // Checks for and initializes the FreeType 2 library
+       /*
+        *      Initializes the FreeType system.
+       */
+
+       void initFonts(void);
+       
+       /*
+        *      Sets the current font/font size.
+       */
+       
+       void setFontFace(const char *ttf);
+       void setFontSize(unsigned int size);
+       
+       /*
+        *      Draws a string of text at the given coordinates.
+       */
+       
+       float putString(const float x,const float y,const char *s);
+       
+       /*
+        *      Draws a formatted string at the given coordinates.
+       */
+       
+       float putText(const float x,const float y,const char *str,...);
+       
+       /*
+        *      Creates a dialogBox text string (format: `name`: `text`). This function simply sets up
+        *      variables that are drawn in ui::draw(). When the dialog box exists player control is
+        *      limited until a right click is given, closing the box.
+       */
+       
+       void dialogBox(const char *name,const char *text,...);
+       
+       /*
+        *      Draws a larger string in the center of the screen. Drawing is done inside this function.
+       */
+       
+       void importantText(const char *text,...);
+       
+       /*
+        *      Draw various UI elements (dialogBox, player health)
+       */
+       
+       void draw(void);
        
-       void setFontFace(const char *ttf);              // Checks and unpacks the TTF file for use by putString() and putText()
-       void setFontSize(unsigned int size);    // Sets the size of the currently loaded font to 'size' pixels
+       /*
+        *      Handle keyboard/mouse events.
+       */
        
-       float putString(const float x,const float y,const char *s);             // Draws the string 's' to the coordinates ('x','y'). The height (and therefore the width)
-                                                                                                                                       // are determined by what's currently set by setFontSize()
-       float putText(const float x,const float y,const char *str,...); // Draws the formatted string 'str' using putString()
+       void handleEvents(void);
        
-       void dialogBox(const char *name,const char *text,...);                  // Prepares a dialog box to be drawn (its drawn as a black background at the top of the
-                                                                                                                                       // screen and then 'text' is putString()'d
+       /*
+        *      Toggle the black overlay thing.
+       */
        
-       void draw(void);                                                                                                // Draws things like dialogBox's if necessary
+       void toggleBlack(void);
        
-       void handleEvents(void);        // Handles keyboard and mouse events
 }
 
 #endif // UI_H
index 85b02c9419a309af4d02bdbdf6e51c599de9c646..81ec33587265cff224ed5c226e8ee5622688ece9 100644 (file)
@@ -82,6 +82,7 @@ public:
        */
        
        virtual void generate(unsigned int width);
+       void generateFunc(unsigned int width,unsigned int (*func)(unsigned int));
        
        /*
         *      Looks for the furthest back layer in this world and adds a new layer of width `width` behind it.
index 56aed17f8609a17d05c77cb37f2be986bceefcc9..dee78c78f82822e641235fa4021be8fe0f405f15 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -8,21 +8,21 @@
 
 /*
  *     TICKS_PER_SEC & MSEC_PER_TICK
- * 
+ *
  *     The game's main loop mainly takes care of two things: drawing to the
  *     screen and handling game logic, from user input to world gravity stuff.
  *     The call for rendering is made every time the main loop loops, and then
  *     uses interpolation for smooth drawing to the screen. However, the call
  *     for logic would be preferred to be run every set amount of time.
- *  
-
+ *
+ *
  *     The logic loop is currently implemented to run at a certain interval
  *     that we call a 'tick'. As one may now guess, TICKS_PER_SEC defines the
  *     amount of ticks that should be made every second. MSEC_PER_TICK then
  *     does a simple calculation of how many milliseconds elapse per each
  *     'tick'. Simple math is then done in the main loop using MSEC_PER_TICK
  *     to call the logic handler when necessary.
- * 
+ *
 */
 
 #define TICKS_PER_SEC 20
 
 /*
  *     window & mainGLContext
- * 
+ *
  *     In order to draw using SDL and its openGL facilities SDL requires
  *     an SDL_Window object, which spawns a window for the program to draw
  *     to. Once the SDL_Window is initialized, an SDL_GLContext is made so
  *     that openGL calls can be made to SDL. The game requires both of these
  *     variables to initialize.
- * 
+ *
 */
 
 SDL_Window    *window = NULL;
@@ -47,20 +47,20 @@ SDL_GLContext  mainGLContext = NULL;
  *     background image. Currently there is only one background image for the
  *     main world; this will be changed and bgImage likely removed once better
  *     backgrounds are implemented.
- * 
+ *
 */
 
 static GLuint  bgDay, bgNight, bgMtn, bgTreesFront, bgTreesMid, bgTreesFar;
 
 /*
  *     gameRunning
- * 
+ *
  *     This is one of the most important variables in the program. The main
  *     loop of the game is set to break once this variable is set to false.
  *     The only call to modify this variable is made in src/ui.cpp, where it
  *     is set to false if either an SDL_QUIT message is received (the user
  *     closes the window through their window manager) or if escape is pressed.
- * 
+ *
 */
 
 bool gameRunning;
@@ -71,20 +71,20 @@ bool gameRunning;
  *                                             variable. This should only be changed when layer switch
  *                                             buttons are pressed (see src/ui.cpp), or when the player
  *                                             enters a Structure/Indoor World (see src/ui.cpp again).
- * 
+ *
  *     player                  -       This points to a Player object, containing everything for
  *                                             the player. Most calls made with currentWorld require a
  *                                             Player object as an argument, and glOrtho is set based
  *                                             off of the player's coordinates. This is probably the one
  *                                             Entity-derived object that is not pointed to in the entity
  *                                             array.
- * 
+ *
  *     entity                   -      Contains pointers to 'all' entities that have been created in
  *                                             the game, including NPCs, Structures, and Mobs. World draws
  *                                             and entity handling done by the world cycle through entities
  *                                             using this array. Entities made that aren't added to this
  *                                             array probably won't be noticable by the game.
- * 
+ *
 */
 
 World                                                          *currentWorld=NULL;
@@ -94,9 +94,9 @@ extern std::vector<Entity *   >        entity;
 /*
  *     tickCount contains the number of ticks generated since main loop entrance.
  *     This variable might be used anywhere.
- * 
+ *
  *     deltaTime is used for interpolation stuff.
- * 
+ *
  *     Pretty sure these variables are considered static as they might be externally
  *     referenced somewhere.
 */
@@ -107,13 +107,13 @@ unsigned int deltaTime = 0;
 /*
  *
 */
+
 GLuint fragShader;
 GLuint shaderProgram;
 
 /*
  *     names is used to open a file containing all possible NPC names. It is externally
  *     referenced in src/entities.cpp for getting random names.
- *
 */
 
 FILE *names;
@@ -121,7 +121,6 @@ FILE *names;
 /*
  *     These variables are used by SDL_mixer to create sound.
  *     horn is not currently used, although it may be set.
- * 
 */
 
 Mix_Music *music;
@@ -130,35 +129,34 @@ Mix_Chunk *horn;
 /*
  *     loops is used for texture animation. It is believed to be passed to entity
  *     draw functions, although it may be externally referenced instead.
- * 
 */
 
 unsigned int loops = 0;        // Used for texture animation
 
 /*
  *     initEverything
- * 
+ *
  *     Before the main loop, things like the player, entities, and worlds should
  *     be created. This game has not reached the point that these can be scripted
  *     or programmed, so this function substitues for that. It is defined in
  *     src/gameplay.cpp.
- * 
+ *
 */
 
 extern void initEverything(void);
 
 /*
  *     mainLoop is in fact the main loop, which runs 'infinitely' (as long as gameRunning
-
-
-
+ *
+ *
+ *
  *     is set). Each loop updates timing values (tickCount and deltaTime), runs logic()
  *     if MSEC_PER_TICK milliseconds have passed, and then runs render().
- * 
+ *
  *     logic handles all user input and entity/world physics.
- * 
+ *
  *     render handles all drawing to the window, calling draw functions for everything.
- * 
+ *
 */
 
 void logic(void);
@@ -184,7 +182,7 @@ std::string readFile(const char *filePath) {
     return content;
 }
 
-/* 
+/*
  *     This offset is used as the player offset in the world drawing so
  *     everything can be moved according to the player
 */
@@ -192,12 +190,12 @@ vec2 offset;
 
 /*
  *     millis
- * 
+ *
  *     We've encountered many problems when attempting to create delays for triggering
  *     the logic function. As a result, we decided on using the timing libraries given
  *     by <chrono> in the standard C++ library. This function simply returns the amount
  *     of milliseconds that have passed sine the epoch.
- * 
+ *
 */
 
 #ifdef __WIN32__
@@ -224,62 +222,60 @@ static vec2 star[100];
 /*******************************************************************************
  * MAIN ************************************************************************
  *******************************************************************************/
+
 int main(int argc, char *argv[]){
        gameRunning=false;
-       
+
        /*
         *      (Attempt to) Initialize SDL libraries so that we can use SDL facilities and eventually
         *      make openGL calls. Exit if there was an error.
-        * 
        */
-       
+
        if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0){
                std::cout << "SDL was not able to initialize! Error: " << SDL_GetError() << std::endl;
                return -1;
        }
-       
+
        // Run SDL_Quit when main returns
-    atexit(SDL_Quit);
-    
-    /*
-     * (Attempt to) Initialize SDL_image libraries with IMG_INIT_PNG so that we can load PNG
-     * textures for the entities and stuff.
-     *
-    */
-    
-    if(!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)){
+       atexit(SDL_Quit);
+
+       /*
+        *      (Attempt to) Initialize SDL_image libraries with IMG_INIT_PNG so that we can load PNG
+        *      textures for the entities and stuff.
+       */
+
+       if(!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)){
                std::cout << "Could not init image libraries! Error: " << IMG_GetError() << std::endl;
                return -1;
        }
-       
+
        // Run IMG_Quit when main returns
        atexit(IMG_Quit);
-       
+
        /*
         *      (Attempt to) Initialize SDL_mixer libraries for loading and playing music/sound files.
-        * 
+        *
        */
-       
+
        if(Mix_OpenAudio( 44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0){
                std::cout << "SDL_mixer could not initialize! Error: " << Mix_GetError() << std::endl;
        }
-       
+
        // Run Mix_Quit when main returns
        atexit(Mix_Quit);
-    
-    /*
-     * Create a window for SDL to draw to. Most parameters are the default, except for the
-     * following which are defined in include/common.h:
-     * 
-     * GAME_NAME               the name of the game that is displayed in the window title bar
-     * SCREEN_WIDTH    the width of the created window
-     * SCREEN_HEIGHT   the height of the created window
-     * FULLSCREEN              makes the window fullscreen
-     * 
-    */
-    
-    window = SDL_CreateWindow(GAME_NAME,
+
+       /*
+        *      Create a window for SDL to draw to. Most parameters are the default, except for the
+        *      following which are defined in include/common.h:
+        *
+        *      GAME_NAME               the name of the game that is displayed in the window title bar
+        *      SCREEN_WIDTH    the width of the created window
+        *      SCREEN_HEIGHT   the height of the created window
+        *      FULLSCREEN              makes the window fullscreen
+        *
+       */
+
+       window = SDL_CreateWindow(GAME_NAME,
                                                          SDL_WINDOWPOS_UNDEFINED,      // Spawn the window at random (undefined) x and y coordinates
                                                          SDL_WINDOWPOS_UNDEFINED,      //
                                                          SCREEN_WIDTH,
@@ -288,35 +284,35 @@ int main(int argc, char *argv[]){
 #ifdef FULLSCREEN
                                                          | SDL_WINDOW_FULLSCREEN
 #endif // FULLSCREEN
-                              );
-    
+                                 );
+
     /*
      * Exit if the window cannot be created
     */
-    
+
     if(window==NULL){
                std::cout << "The window failed to generate! SDL_Error: " << SDL_GetError() << std::endl;
         return -1;
     }
-    
+
     /*
      * Create the SDL OpenGL context. Once created, we are allowed to use OpenGL functions.
      * Saving this context to mainGLContext does not appear to be necessary as mainGLContext
      * is never referenced again.
-     * 
+     *
     */
-    
+
     if((mainGLContext = SDL_GL_CreateContext(window)) == NULL){
                std::cout << "The OpenGL context failed to initialize! SDL_Error: " << SDL_GetError() << std::endl;
         return -1;
     }
-       
+
        /*
         *      Initialize GLEW libraries, and exit if there was an error.
         *      Not sure what they're for yet.
-        * 
+        *
        */
-       
+
        GLenum err;
 #ifndef __WIN32__
        glewExperimental = GL_TRUE;
@@ -364,6 +360,7 @@ int main(int argc, char *argv[]){
        /*
         *      Initializes our shaders so that the game has shadows.
        */
+       
        #ifdef SHADERS
                std::cout << "Initializing shaders!" << std::endl;
 
@@ -449,6 +446,10 @@ int main(int argc, char *argv[]){
        
        initInventorySprites();
        
+       /*
+        *      Generate coordinates for stars that are drawn at night.
+       */
+       
        unsigned int i;
        for(i=0;i<100;i++){
                star[i].x=getRand()%currentWorld->getTheWidth()-currentWorld->getTheWidth()/2;
@@ -557,7 +558,29 @@ void mainLoop(void){
        render();       // Call the render loop
 }
 
+extern bool fadeEnable;
+static unsigned char fadeIntensity = 0;
+
 void render(){
+       
+        /*
+         *     This offset variable is what we use to move the camera and locked
+         *     objects on the screen so they always appear to be in the same relative area
+        */
+       
+       offset = player->loc;
+       offset.x += player->width/2;
+
+       /*
+        *      If the camera will go off of the left  or right of the screen we want to lock it so we can't
+        *  see past the world render
+       */
+       
+       if(player->loc.x - SCREEN_WIDTH/2 < currentWorld->getTheWidth() * -0.5f)
+               offset.x = ((currentWorld->getTheWidth() * -0.5f) + SCREEN_WIDTH / 2) + player->width / 2;
+       if(player->loc.x + SCREEN_WIDTH/2 > currentWorld->getTheWidth() *  0.5f)
+               offset.x = ((currentWorld->getTheWidth() *  0.5f) - SCREEN_WIDTH / 2) + player->width / 2;
+
        /*
         *      These functions run everyloop to update the current stacks presets
         *
@@ -594,29 +617,16 @@ void render(){
         *      glLoadIdentity  This scales the current matrix back to the origin so the
         *                                      translations are seen normally on a stack.
        */
-
-        /*
-         *     This offset variable is what we use to move the camera and locked
-         *     objects on the screen so they always appear to be in the same relative area
-        */
-       offset = player->loc;
-       offset.x += player->width/2;
-
-       /*
-        *      If the camera will go off of the left  or right of the screen we want to lock it so we can't
-        *  see past the world render
-       */
-       if(player->loc.x - SCREEN_WIDTH/2 < currentWorld->getTheWidth()*-0.5f)offset.x = ((currentWorld->getTheWidth()*-0.5f) + SCREEN_WIDTH/2) + player->width/2;
-       if(player->loc.x + SCREEN_WIDTH/2 > currentWorld->getTheWidth()*0.5f)offset.x = ((currentWorld->getTheWidth()*0.5f) - SCREEN_WIDTH/2) + player->width/2;
-       glMatrixMode(GL_PROJECTION);                                    //set the matrix mode as projection so we can set the ortho size and the camera settings later on
-       glPushMatrix();                                                                 //push the  matrix to the top of the matrix stack
-       glLoadIdentity();                                                               //replace the entire matrix stack with the updated GL_PROJECTION mode
+       
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadIdentity();
        glOrtho((offset.x-SCREEN_WIDTH/2),(offset.x+SCREEN_WIDTH/2),0,SCREEN_HEIGHT,-1,1);
-       glMatrixMode(GL_MODELVIEW);                                     //set the matrix to modelview so we can draw objects
-       glPushMatrix();                                                                 //push the  matrix to the top of the matrix stack
-       glLoadIdentity();                                                               //replace the entire matrix stack with the updated GL_MODELVIEW mode
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       glLoadIdentity();
        glEnable(GL_STENCIL_TEST);
-       glPushMatrix();                                                                 //basically here we put a blank canvas (new matrix) on the screen to draw on
+       glPushMatrix();
        
        /*
         * glPushAttrib         This passes attributes to the renderer so it knows what it can
@@ -660,26 +670,41 @@ void render(){
 
        glDisable(GL_TEXTURE_2D);
 
+       /*
+        *      Draws stars if it is an appropriate time of day for them.
+       */
+
        if(((weather==DARK )&(tickCount%DAY_CYCLE)<DAY_CYCLE/2)   ||
           ((weather==SUNNY)&(tickCount%DAY_CYCLE)>DAY_CYCLE*.75) ){
-               if(tickCount%DAY_CYCLE){        
+                  
+               if(tickCount%DAY_CYCLE){        // The above if statement doesn't check for exact midnight.
+                               
                        glColor4ub(255,255,255,255);
                        for(unsigned int i=0;i<100;i++){
                                glRectf(star[i].x+offset.x*.9,star[i].y,star[i].x+offset.x*.9+HLINE,star[i].y+HLINE);
                        }
+                       
                }
        }
 
+       /*
+        *      Calculate the Y to start drawing the background at, and a value for how shaded the
+        *      background elements should be. 
+       */
+
        int base = 40 - (int)worldGetYBase(currentWorld);
        int shade = worldShade*2;
 
        glEnable(GL_TEXTURE_2D);
 
+       /*
+        *      Draw the mountains.
+       */
+
        glBindTexture(GL_TEXTURE_2D, bgMtn);
        glBegin(GL_QUADS);
        safeSetColorA(150-shade,150-shade,150-shade,220);
-       //glColor4ub(150,150,150,220);
-               for(int i = 0; i <= currentWorld->getTheWidth()/1920; i++){
+       for(int i = 0; i <= currentWorld->getTheWidth()/1920; i++){
                glTexCoord2i(0,1);glVertex2i((currentWorld->getTheWidth()*-0.5f)+(1920 * i)+offset.x*.85,base);
                glTexCoord2i(1,1);glVertex2i((currentWorld->getTheWidth()*-0.5f)+(1920 * (i+1))+offset.x*.85,base);
                glTexCoord2i(1,0);glVertex2i((currentWorld->getTheWidth()*-0.5f)+(1920 * (i+1))+offset.x*.85,base+1080);
@@ -687,11 +712,13 @@ void render(){
        }
        glEnd();
 
+       /*
+        *      Draw three layers of trees.
+       */
 
        glBindTexture(GL_TEXTURE_2D, bgTreesFar);
        glBegin(GL_QUADS);
        safeSetColorA(100-shade,100-shade,100-shade,240);
-       //glColor4ub(100,100,100,240);
        for(int i = 0; i <= currentWorld->getTheWidth()/1920; i++){
                glTexCoord2i(0,1);glVertex2i((currentWorld->getTheWidth()*-0.5f)+(1920 * i)+offset.x*.6,base);
                glTexCoord2i(1,1);glVertex2i((currentWorld->getTheWidth()*-0.5f)+(1920 * (i+1))+offset.x*.6,base);
@@ -703,7 +730,6 @@ void render(){
        glBindTexture(GL_TEXTURE_2D, bgTreesMid);
        glBegin(GL_QUADS);
        safeSetColorA(150-shade,150-shade,150-shade,250);
-       //glColor4ub(150,150,150,250);
        for(int i = 0; i <= currentWorld->getTheWidth()/1920; i++){
                glTexCoord2i(0,1);glVertex2i((currentWorld->getTheWidth()*-0.5f)+(1920 * i)+offset.x*.4,base);
                glTexCoord2i(1,1);glVertex2i((currentWorld->getTheWidth()*-0.5f)+(1920 * (i+1))+offset.x*.4,base);
@@ -715,7 +741,6 @@ void render(){
        glBindTexture(GL_TEXTURE_2D, bgTreesFront);
        glBegin(GL_QUADS);
        safeSetColorA(255-shade,255-shade,255-shade,255);
-       //glColor4ub(255,255,255,255);
        for(int i = 0; i <= currentWorld->getTheWidth()/1920; i++){
                glTexCoord2i(0,1);glVertex2i((currentWorld->getTheWidth()*-0.5f)+(1920 * i)+offset.x*.25,base);
                glTexCoord2i(1,1);glVertex2i((currentWorld->getTheWidth()*-0.5f)+(1920 * (i+1))+offset.x*.25,base);
@@ -734,25 +759,25 @@ void render(){
 
        currentWorld->draw(player);
 
+       /*
+        *      Apply shaders if desired.
+       */
+
        #ifdef SHADERS
+       
                glUseProgramObjectARB(shaderProgram);
                glUniform2f(glGetUniformLocation(shaderProgram, "lightLocation"), 640,100);
                glUniform3f(glGetUniformLocation(shaderProgram, "lightColor"), 1,1,1);
                glUniform1f(glGetUniformLocation(shaderProgram, "lightStrength"), 100 + (1000-(shade*10)));
                std::cout << 100 + (1000-(shade*10)) << std::endl;
-               //glBlendFunc(GL_ONE, GL_ONE);
-       #endif //SHADERS
-
-       glColor4ub(0,0,0,200);
-       glRectf(offset.x-SCREEN_WIDTH/2,0,offset.x+SCREEN_WIDTH/2,SCREEN_HEIGHT);
-
-       #ifdef SHADERS
+               glColor4ub(0,0,0,200);
+               glRectf(offset.x-SCREEN_WIDTH/2,0,offset.x+SCREEN_WIDTH/2,SCREEN_HEIGHT);
                glUseProgramObjectARB(0);
+               
        #endif //SHADERS
        
        player->inv->draw();
 
-
        /*
         *      Draw UI elements. This includes the player's health bar and the dialog box.
        */
@@ -794,21 +819,36 @@ void render(){
                                glVertex2i(SCREEN_WIDTH/2+offset.x, player->loc.y);
                        glEnd();
                }
-                                       
+
        }
-       
+
        /*
         *      Draw a white triangle as a replacement for the mouse's cursor.
        */
-       
+
        glColor3ub(255,255,255);
-       
+
        glBegin(GL_TRIANGLES);
                glVertex2i(ui::mouse.x                   ,ui::mouse.y             );
                glVertex2i(ui::mouse.x+HLINE*3.5,ui::mouse.y              );
                glVertex2i(ui::mouse.x                   ,ui::mouse.y-HLINE*3.5);
        glEnd();
 
+       /*
+        *      Here we draw a black overlay if it's been requested.
+       */
+
+       if(fadeIntensity){
+               glColor4ub(0,0,0,fadeIntensity);
+               glRectf(player->loc.x-SCREEN_WIDTH,
+                               SCREEN_HEIGHT,
+                               player->loc.x+SCREEN_WIDTH,
+                               0);
+               if(fadeIntensity == 255){
+                       ui::importantText("The screen is black.");
+               }
+       }
+
        /**************************
        ****  END RENDERING   ****
        **************************/
@@ -829,143 +869,147 @@ void render(){
 }
 
 void logic(){
-       
+
        /*
         *      NPCSelected is used to insure that only one NPC is made interactable with the mouse
         *      if, for example, multiple entities are occupying one space.
        */
-       
+
        static bool NPCSelected = false;
-       
+
        /*
         *      Handle user input (keyboard & mouse).
        */
-       
+
        ui::handleEvents();
-       
+
        /*
         *      Run the world's detect function. This handles the physics of the player and any entities
         *      that exist in this world.
        */
-       
+
        currentWorld->detect(player);
        if(player->loc.y<.02)gameRunning=false;
-       
+
        /*
         *      Entity logic: This loop finds every entity that is alive and in the current world. It then
         *      basically runs their AI functions depending on what type of entity they are. For NPCs,
         *      click detection is done as well for NPC/player interaction.
-        * 
+        *
        */
-       
+
        for(int i = 0 ; i < entity.size(); i++){
                if(!entity[i]->alive)std::cout<<"Entity "<<i<<" is not alive!"<<std::endl;
-               
+
                /*
                 *      Check if the entity is in this world and is alive.
                */
-               
+
                if(entity[i]->inWorld == currentWorld &&
                   entity[i]->alive){
-                       
+
                        /*
                         *      Switch on the entity's type and handle them accordingly
                        */
-                       
+
                        switch(entity[i]->type){
-                               
+
                        case NPCT:      // Handle NPCs
-                       
+
                                /*
                                 *      Make the NPC 'wander' about the world if they're allowed to do so.
                                 *      Entity->canMove is modified when a player interacts with an NPC so
                                 *      that the NPC doesn't move when it talks to the player.
-                                * 
+                                *
                                */
-                               
+
                                if(entity[i]->canMove)
                                        NPCp(entity[i])->wander((rand() % 120 + 30));
-                               
+
                                /*
                                 *      Don't bother handling the NPC if another has already been handled.
                                */
-                               
+
                                if(NPCSelected){
                                        entity[i]->near=false;
                                        break;
                                }
-                               
+
                                /*
                                 *      Check if the NPC is under the mouse.
                                */
-                               
+
                                if(ui::mouse.x >= entity[i]->loc.x                                              &&
                                   ui::mouse.x <= entity[i]->loc.x + entity[i]->width   &&
                                   ui::mouse.y >= entity[i]->loc.y                                              &&
                                   ui::mouse.y <= entity[i]->loc.y + entity[i]->width   ){
-                                          
+
                                        /*
                                         *      Check of the NPC is close enough to the player for interaction to be
                                         *      considered legal. In other words, require the player to be close to
-                                        *      the NPC in order to interact with it. 
-                                        * 
+                                        *      the NPC in order to interact with it.
+                                        *
                                         *      This uses the Pythagorean theorem to check for NPCs within a certain
                                         *      radius (40 HLINEs) of the player's coordinates.
-                                        * 
-                                       */   
-                                       
+                                        *
+                                       */
+
                                        if(pow((entity[i]->loc.x - player->loc.x),2) + pow((entity[i]->loc.y - player->loc.y),2) <= pow(40*HLINE,2)){
-                                               
+
                                                /*
                                                 *      Set Entity->near so that this NPC's name is drawn under them, and toggle NPCSelected
                                                 *      so this NPC is the only one that's clickable.
                                                */
-                                               
+
                                                entity[i]->near=true;
                                                NPCSelected=true;
-                                               
+
                                                /*
                                                 *      Check for a right click, and allow the NPC to interact with the
                                                 *      player if one was made.
                                                */
-                                               
+
                                                if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT)){
-                                                       
+
                                                        NPCp(entity[i])->interact();
                                                        //Mix_PlayChannel( -1, horn, 0);        // Audio feedback
-                                                       
+
                                                }
                                        }
-                                       
+
                                /*
                                 *      Hide the NPC's name if the mouse isn't on the NPC.
                                */
-                               
+
                                }else entity[i]->near=false;
-                               
+
                                break;  // End case NPCT
-                               
+
                        case MOBT:      // Handle Mobs
-                       
+
                                /*
                                 *      Run the Mob's AI function.
                                */
-                       
+
                                switch(entity[i]->subtype){
                                case MS_RABBIT:
                                case MS_BIRD:
                                        Mobp(entity[i])->wander((rand()%240 + 15));     // Make the mob wander
                                        break;
                                }
-                               
+
                                break;  // End case MOBT
-                               
+
                        default:break;
-                       
+
                        }
                }
        }
-       
+
+       /*
+        *      Switch between day and night (SUNNY and DARK) if necessary.
+       */
+
        if(!(tickCount%DAY_CYCLE)||!tickCount){
                if(weather==SUNNY){
                        weather=DARK;
@@ -973,15 +1017,31 @@ void logic(){
                        weather=SUNNY;
                }
        }
-       
+
+       /*
+        *      Calculate an in-game shading value (as opposed to GLSL shading).
+       */
+
        #define PI 3.1415926535
        worldShade=50*sin((tickCount+(DAY_CYCLE/2))/(DAY_CYCLE/PI));
-       
+
+       /*
+        *      Transition to and from black if necessary.
+       */
+
+       if(fadeEnable){
+                        if(fadeIntensity < 160)fadeIntensity+=5;
+               else if(fadeIntensity < 255)fadeIntensity+=1;
+       }else{
+                        if(fadeIntensity > 150)fadeIntensity-=1;
+               else if(fadeIntensity)          fadeIntensity-=5;
+       }
+
        /*
         *      Increment a loop counter used for animating sprites.
        */
-       
+
        loops++;
-       tickCount++;
-       NPCSelected=false;
+       tickCount++;            // Used for day/night cycles
+       NPCSelected=false;      // See above
 }
index 6f90a5f9cea2503751c9650318a7313e7a6e11bc..857c6b9b213577b03c751becf0a41037d8d3f639 100644 (file)
@@ -1,4 +1,4 @@
-#version 130\r
+#version 120\r
 \r
 uniform vec2 lightLocation;\r
 uniform vec3 lightColor;\r
@@ -17,4 +17,4 @@ void main(){
        vec4 color = vec4(0, 0, 0, 0.8f - pow(attenuation, 3)) * vec4(lightColor, 1);\r
        \r
        gl_FragColor = color;\r
-}
\ No newline at end of file
+}\r
index 42ed5a9e547fd4fd1b44108a94f7fc8990b0fcde..acc45bdcd1cdb5ee983b7bd68905fc726d1aba11 100644 (file)
@@ -176,7 +176,7 @@ void Entity::draw(void){            //draws the entities
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
        if(near){
-               ui::setFontSize(10);
+               ui::setFontSize(14);
                ui::putText(loc.x,loc.y-ui::fontSize-HLINE/2,"%s",name);
        }
 }
index 11f2ad797566a4d2be8d3e878423ff279fed0b99..cb33deb6d2e549537072713870ff5bdca2c1fd6f 100644 (file)
@@ -92,7 +92,7 @@ int Inventory::takeItem(ITEM_ID id,unsigned char count){
 void Inventory::draw(void){
        unsigned int i=0;
        float y=SCREEN_HEIGHT/2,xoff;
-       ui::setFontSize(12);
+       ui::setFontSize(14);
        ui::putText(offset.x-SCREEN_WIDTH/2,y,"Inventory:");
        while(item[i].count){
                y-=HLINE*12;
index d138a0a30d1e890421257936ace3bf6f62a36726..a089c5fb956c45c47bb0706b1a2bd5b4f2f8c2e4 100644 (file)
@@ -16,6 +16,8 @@ static GLuint       ftex;
 
 static char *dialogBoxText;
 
+bool fadeEnable = false;
+
 namespace ui {
        vec2 mouse;
        bool debug=false;
@@ -139,6 +141,23 @@ namespace ui {
                }while(s[++i]);
                return xo;
        }
+       char *typeOut(char *str){
+               static unsigned int sinc,linc,size;
+               static char *ret = NULL;
+               unsigned int i;
+               if(!ret || size != strlen(str)){
+                       size=strlen(str);
+                       ret=(char *)calloc(size,sizeof(char));
+                       linc=0;
+                       sinc=2;
+               }
+               if(++sinc==3){
+                       sinc=0;
+                       strncpy(ret+linc,str+linc,1);
+                       if(linc<size)linc++;
+               }
+               return ret;
+       }
        float putText(const float x,const float y,const char *str,...){ // putText() simply runs 'str' and the extra arguments though
                va_list args;                                                                                           // vsnprintf(), which'll store the complete string to a buffer
                char *buf;                                                                                                      // that's then passed to putString()
@@ -167,6 +186,21 @@ namespace ui {
                vsnprintf(dialogBoxText+name_len+2,512-name_len-2,text,dialogArgs);
                va_end(dialogArgs);
        }
+       void importantText(const char *text,...){
+               va_list textArgs;
+               char *ttext;
+               va_start(textArgs,text);
+               ttext=(char *)calloc(512,sizeof(char));
+               vsnprintf(ttext,512,text,textArgs);
+               va_end(textArgs);
+               setFontSize(24);
+               char *rtext;
+               rtext=typeOut(ttext);
+               putString(player->loc.x+player->width/2-SCREEN_WIDTH/2,
+                                 SCREEN_HEIGHT/2+fontSize,
+                                 rtext);
+               free(ttext);
+       }
        void draw(void){
                float x,y;
                if(dialogBoxExists){
@@ -174,10 +208,12 @@ namespace ui {
                        x=player->loc.x-SCREEN_WIDTH/2+HLINE*8;
                        y=SCREEN_HEIGHT-HLINE*8;
                        glRectf(x,y,x+SCREEN_WIDTH-HLINE*16,y-SCREEN_HEIGHT/4);
-                       setFontSize(12);
-                       putString(x+HLINE,y-fontSize-HLINE,dialogBoxText);
+                       char *rtext;
+                       rtext=typeOut(dialogBoxText);
+                       setFontSize(16);
+                       putString(x+HLINE,y-fontSize-HLINE,rtext);
                }
-               setFontSize(12);
+               setFontSize(14);
                putText(((SCREEN_WIDTH/2)+offset.x)-125,SCREEN_HEIGHT-fontSize,"Health: %u/%u",player->health>0?(unsigned)player->health:0,
                                                                                                                                                                                        (unsigned)player->maxHealth);
                if(player->alive){
@@ -269,8 +305,9 @@ namespace ui {
                                        player->inv->useItem();
                                }
                                if(SDL_KEY==SDLK_c){
-                                       dialogBox("","You pressed `c`, but nothing happened.");
+                                       dialogBox("","You pressed `c`, but nothing happened?");
                                }
+                               if(SDL_KEY==SDLK_p)toggleBlack();
                                if(SDL_KEY==SDLK_LSHIFT)player->speed = debug?4:3;                                                      // Sprint
                                if(SDL_KEY==SDLK_LCTRL)player->speed = .5;
                        }
@@ -304,4 +341,8 @@ namespace ui {
                        }
                }
        }
+       
+       void toggleBlack(void){
+               fadeEnable ^= true;
+       }
 }
index 36993b0d6b1d847471b8eca7ed5fd3fc0b715770..0ec0f35ef9bec05fbb08adaec4f5d106efa57fe7 100644 (file)
@@ -33,6 +33,14 @@ float worldGetYBase(World *w){
 }
 
 World::World(void){
+       /*
+        *      Nullify pointers to other worlds.
+       */
+       
+       behind  =
+       infront =
+       toLeft  =
+       toRight = NULL;
 }
 
 void World::generate(unsigned int width){      // Generates the world and sets all variables contained in the World class.
@@ -129,15 +137,21 @@ void World::generate(unsigned int width){ // Generates the world and sets all va
        */
        
        x_start=0 - getWidth(this) / 2;
-       
-       /*
-        *      Nullify pointers to other worlds.
-       */
-       
-       behind  =
-       infront =
-       toLeft  =
-       toRight = NULL;
+}
+
+void World::generateFunc(unsigned int width,unsigned int (*func)(unsigned int)){
+       unsigned int i;
+       if((lineCount = width) <= 0)
+               abort();
+       line=(struct line_t *)calloc(lineCount,sizeof(struct line_t));
+       for(i=0;i<lineCount;i++){
+               line[i].y=func(i);
+               line[i].color=rand() % 20 + 100;
+               line[i].gh[0]=(getRand() % 16) / 3.5 + 2;
+               line[i].gh[1]=(getRand() % 16) / 3.5 + 2;
+               line[i].gs=true;
+       }
+       x_start=0 - getWidth(this) / 2;
 }
 
 World::~World(void){
index 131a3e6c4c4fcec431739d0cc84802e35c8f4978..c30ef4d78504e6b986071f0ca6ea4726b0902840 100644 (file)
--- a/test.frag
+++ b/test.frag
@@ -1,4 +1,4 @@
-#version 130\r
+#version 120\r
 void main(){\r
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\r
-}
\ No newline at end of file
+}\r