about summary refs log blame commit diff stats
path: root/src/title.c
blob: c5a15cee2b29fcecd390b420b082aac364fd8a2c (plain) (tree)
1
2
3
4
5
6
7
8

                 
                           
              

                  
 
                                    








                                                                                    
 
                                
                                          
                                                                  


                                                                                                           
                                                                     
                                                                    
     





                                                          
                                                                                                  


                                                                                                                                     
                                                                     

                
 

                            
                                                                                            

                                                                                   
                                                                            
 
                                                                       

                                                 
     

              
                    
                                                                                                                 

                                  
                                    
     
              

 
                                                







                                                                                                           
 


                                                                                                                                     
                                                                 


                                                                   


                                              



                                                                                            



                                                                             

                                                                          

                           


                                
                                    

                                             
                                                     

                                                                      



                                                   




                                                         

                                                                                      













                                                              






                                                                                   
 




                                                                         


                                                                        
                                                     
                                                                                                                                



                                          
                               
                                                                           















                                                                                             







                                                                              
                         


                                                                                    
     
           

 


                                                                         
                        
 











                              


























                                                              






                                                                      
                              
                                                       
                                                    

                                                                                      
        




















                                                                                   
 



                                                    
                                                                     






                                                              



                                                         
                                                              









                                                                                                              
                                                          
                                                              









                                                                                                              
                         
                                                       

















                                                                                  
                                                                                


                     
                                                               


                                                                                               
                             







                                                                           



                         


 

                    



                                       
 
                       
                                       
 
                                 


                   















                          
                                   
      


                             

                        


                                                               
                                  

                                                



                                                                

                              
 

                                                          
                                                              



                                                                       
        
                            
                                                   

                                                                                         
 




















                                                                                   
 

                                                
                       
                                                          
                                         


                                                         
                       
                                                          
                                         
             

                                                         
                   


                                                          





                                                          
                            

             


                                    

                                                                         






                                                         
                                 
                                                                
                                       

                                  
                                                     
                                               
                                                   
                                                                                                                     
                                                                                                                                    



                                                                            










                                                                               
                        
                                                                                           

                     


                              
 
#include "pong.h"

struct LeaderboardEntries {
    int Score;
    char Name[16];
};

struct LeaderboardEntries Top10[10];

static int compare_int(const void *Score1, const void *Score2) {
    const struct LeaderboardEntries *Entry1 = *(struct LeaderboardEntries**) Score1;
    const struct LeaderboardEntries *Entry2 = *(struct LeaderboardEntries**) Score2;
    if (Entry1->Score > Entry2->Score) {
        return -1;
    }
    return +1;
}

static int order_leaderboard() {
    // Find leaderboard file, and open it.
    char *LeaderboardDirectory = SDL_GetPrefPath("iotib", "Pong");
    char LeaderboardFilePath[8192];
    snprintf(LeaderboardFilePath, sizeof(LeaderboardFilePath), "%s/leaderboard.txt", LeaderboardDirectory);
    FILE *LeaderboardFile;
    if((LeaderboardFile = fopen(LeaderboardFilePath, "r")) == NULL) {
        return(1); //If it doesn't exist yet, we don't need to care.
    }
    // Check if file is empty.
    fscanf(LeaderboardFile, "\n");
    if(feof(LeaderboardFile)) {
	return(1);
    }
    rewind(LeaderboardFile); //If not , rewind the stream.
    // Init a temporary pointer to store scores and names into. This will be organized into Top10.
    struct LeaderboardEntries *TmpStore[UINT16_MAX*2];
    for (int size = 0; size < (UINT16_MAX*2); size++) //If there's 131,000 entries, I dunno what to tell you. You really like pong...
        TmpStore[size] = malloc(sizeof(struct LeaderboardEntries)); 
    if(*TmpStore == NULL) { //Check if memory got assigned correctly.
        exit(1);
    }

    // Load Scores and Names
    int size = 0;
    for (int a = 0; !feof(LeaderboardFile); a++, size++) { //Load data from file into array.
        fscanf(LeaderboardFile, "%s %d\n", TmpStore[a]->Name, &TmpStore[a]->Score);
    }
    qsort(TmpStore, size, sizeof(struct LeaderboardEntries *), compare_int);

    for(int i = 0; i < size; i++) { //Copy first 10 elements into top10
	strcpy(Top10[i].Name, TmpStore[i]->Name);
	Top10[i].Score = TmpStore[i]->Score;
    }

    // Cleanup
    // Free TmpStore
    free(*TmpStore); //Truth be told, I dunno if this even works, since the amount of memory used is kilobytes...
    // Close leaderboard file.
    if (LeaderboardFile != NULL) {
	    fclose(LeaderboardFile);
    }
    return(0);
}

static void score_screen(Camera2D *MainCamera) {
    // Find leaderboard file, and open it.
    char *LeaderboardDirectory = SDL_GetPrefPath("iotib", "Pong");
    char LeaderboardFilePath[8192];
    snprintf(LeaderboardFilePath, sizeof(LeaderboardFilePath), "%s/leaderboard.txt", LeaderboardDirectory);
    FILE *LeaderboardFile;
    if((LeaderboardFile = fopen(LeaderboardFilePath, "r")) == NULL) {
        return; //If it doesn't exist yet, we don't need to care.
    }

    // Init a temporary pointer to store scores and names into. This will be organized into Top10.
    struct LeaderboardEntries *Scores[UINT16_MAX*2];
    for (int size = 0; size < (UINT16_MAX*2); size++) //If there's 131,000 entries, I dunno what to tell you. You really like pong...
        Scores[size] = malloc(sizeof(struct LeaderboardEntries));
    if(*Scores == NULL) { //Check if memory got assigned correctly.
        exit(1);
    }
    for (int i = 0; i < (UINT16_MAX*2); i++) {
        strcpy(Scores[i]->Name, " ");
    }

    // Load Scores and Names
    int size = 0;
    for (int a = 0; !feof(LeaderboardFile); a++, size++) { //Load data from file into array.
        fscanf(LeaderboardFile, "%s %d", Scores[a]->Name, &Scores[a]->Score);
	if(feof(LeaderboardFile)) {
		break;
	}
    }
    qsort(Scores, size, sizeof(struct LeaderboardEntries *), compare_int);

    //Begin drawing scores.
    //Mouse
    bool LookingAtScores = true;
    bool MouseCursorIn = true;
    SetMousePosition(1280/2, 720/2);
    Vector2 OldPosition = GetMousePosition();
    Vector2 NewPosition = GetMousePosition();
    Rectangle MouseCursor = {1280/2.0f,720/2.0f,1,1};
    Texture2D MouseCursorSprite = LoadTexture("resources/cursor.png");

    //Page Buttons Rectangles
    Rectangle PrevPage = {5, 720-50, 70, 45};
    Rectangle NextPage = {1280-70, 720-50, 70, 45};

    int Page = 0;
    bool EndOfPages = false;
    while(LookingAtScores == true && GameGoing == true) {
        // Update Camera
        MainCamera->zoom = GetScreenHeight()/720.0f;
	MainCamera->offset = (Vector2){GetScreenWidth()/2.0f, GetScreenHeight()/2.0f};
	MainCamera->target = (Vector2){1280/2.0f, 720/2.0f};

        //Mouse
        if (MouseCursorIn == true) {
            OldPosition = NewPosition;
            NewPosition = GetMousePosition();
            MouseCursor.y -= OldPosition.y-NewPosition.y;
            MouseCursor.x -= OldPosition.x-NewPosition.x;
            if (MouseCursor.y >= 720 || MouseCursor.y <= 0) {
                MouseCursor.y += OldPosition.y-NewPosition.y;
            }
            if (MouseCursor.x >= 1280 || MouseCursor.x <= 0) {
                MouseCursor.x += OldPosition.x-NewPosition.x;
            }
        }
        if (IsKeyPressed(KEY_ESCAPE)) {
            EnableCursor();
            MouseCursorIn = false;
        } else if (IsCursorOnScreen() && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
            DisableCursor();
            MouseCursorIn = true;
        }

        EndOfPages = false;
        BeginDrawing();
            ClearBackground(BLACK);
            BeginMode2D(*MainCamera);
                DrawRectangle(0, 0, 1280, 720, (Color){20, 20, 20, 255});
		// Scores
		int a = 0;
                for (int i = 1+(10*Page); i <= 10+(10*Page); i++, a++) {
                    if(Scores[i-1]->Name[0] != ' ') {
                        DrawText(TextFormat("%d. %s: %d", i, Scores[i-1]->Name, Scores[i-1]->Score), 460, 60+(50*a), 48, WHITE);
                    } else {
                        EndOfPages = true;
                    }
                }
		// Page Buttons
		if(CheckCollisionRecs(MouseCursor, PrevPage) && Page > 0) {
			DrawRectangleRec(PrevPage, RED);
			if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
				if(Page > 0) {
					Page--;
				}
			}
		} else if(CheckCollisionRecs(MouseCursor, NextPage) && EndOfPages == false) {
			DrawRectangleRec(NextPage, RED);
			if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
				if(EndOfPages == false) {
					Page++;
				}
			}
		}
                DrawText("<--", 5, 720-50, 48, WHITE);
                DrawText("-->", 1280-70, 720-50, 48, WHITE);
		//Exit Button
		if(CheckCollisionRecs(MouseCursor, (Rectangle){0,0,42,120})) {
			DrawRectangle(0, 0, 42, 120, RED);
			if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
				LookingAtScores = false;
			}
		}
		DrawText("<", 0, 0, 128, WHITE);
		// Cursor
                DrawTexture(MouseCursorSprite, MouseCursor.x, MouseCursor.y, WHITE);
            EndMode2D();
        EndDrawing();
    }
    return;
}

static void settings(Camera2D *MainCamera, Mix_Music *TitleScreenMusic) {
    bool SettingsGoing = true;
    int MusicBarY = 50;
    int SoundBarY = 150;

    Rectangle MusicBar[10] = {
        {50,MusicBarY,50,50},
        {105,MusicBarY,50,50},
        {160,MusicBarY,50,50},
        {215,MusicBarY,50,50},
        {270,MusicBarY,50,50},
        {325,MusicBarY,50,50},
        {380,MusicBarY,50,50},
        {435,MusicBarY,50,50},
        {490,MusicBarY,50,50},
        {545,MusicBarY,50,50},
    };
    
    Rectangle SoundBar[10] = {
        {50,SoundBarY,50,50},
        {105,SoundBarY,50,50},
        {160,SoundBarY,50,50},
        {215,SoundBarY,50,50},
        {270,SoundBarY,50,50},
        {325,SoundBarY,50,50},
        {380,SoundBarY,50,50},
        {435,SoundBarY,50,50},
        {490,SoundBarY,50,50},
        {545,SoundBarY,50,50},
    };

    // Back Selection
    Rectangle BackButton = {
        0,0,42,120
    };

    //Screen Buttons
    int ScreenButtonLength = 250;
    Rectangle ScreenButtons[3] = {
        {95, 242, ScreenButtonLength, 42},
        {95, 284, ScreenButtonLength, 42},
        {95, 326, ScreenButtonLength, 42}
    };
    SetMousePosition(GetScreenWidth()/2, GetScreenHeight()/2);
    // Mouse
    Rectangle MouseCursor = {
        1280/2.0f,720/2.0f,1,1
    };
    Vector2 OldPosition = GetMousePosition();
    Vector2 NewPosition = GetMousePosition();
    Texture2D MouseCursorSprite = LoadTexture("resources/cursor.png");
    bool MouseCursorIn = true;
    while(SettingsGoing == true && GameGoing == true) {
        MainCamera->zoom = GetScreenHeight()/720.0f;
        MainCamera->offset = (Vector2){GetScreenWidth()/2.0f, GetScreenHeight()/2.0f};
	    MainCamera->target = (Vector2){1280/2.0f, 720/2.0f};
	
        //Mouse
        if (MouseCursorIn == true) {
            OldPosition = NewPosition;
            NewPosition = GetMousePosition();
            MouseCursor.y -= OldPosition.y-NewPosition.y;
            MouseCursor.x -= OldPosition.x-NewPosition.x;
            if (MouseCursor.y >= 720 || MouseCursor.y <= 0) {
                MouseCursor.y += OldPosition.y-NewPosition.y;
            }
            if (MouseCursor.x >= 1280 || MouseCursor.x <= 0) {
                MouseCursor.x += OldPosition.x-NewPosition.x;
            }
        }

        if (IsKeyPressed(KEY_ESCAPE)) {
            EnableCursor();
            MouseCursorIn = false;
        } else if (IsCursorOnScreen() && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
            DisableCursor();
            MouseCursorIn = true;
        }

        Mix_VolumeMusic(GlobalSettings.MusicVolume);
        BeginDrawing();
        ClearBackground(BLACK);
        BeginMode2D(*MainCamera);
            DrawRectangle(0, 0, 1280, 720, (Color){20, 20, 20, 255});
            // Back Button
            if (CheckCollisionRecs(MouseCursor, BackButton)) {
                DrawRectangleRec(BackButton, RED);
                if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
                    SettingsGoing = false;
                }
            }

            // Music
            DrawText("Music Volume:", 50, 10, 42, WHITE);
            DrawText("<", 0,0,128,WHITE);
            DrawRectangle(45, MusicBarY-5, 555, 60, DARKGRAY);
            for(int i = 0; i < 10; i++) {
                if (CheckCollisionRecs(MouseCursor, MusicBar[i]) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
                    GlobalSettings.MusicVolume = i*10;
                }
                if(i <= (GlobalSettings.MusicVolume/10)) {
                    DrawRectangleRec(MusicBar[i], RED);
                }
            }

            // Sound
            DrawText("Sound Volume:", 50, 108, 42, WHITE);
            DrawRectangle(45, SoundBarY-5, 555, 60, DARKGRAY);
            DrawText("<", 0,0,128,WHITE);
            for(int i = 0; i < 10; i++) {
                if (CheckCollisionRecs(MouseCursor, SoundBar[i]) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
                    play_audio(SOUND_BOUNCE);
                    GlobalSettings.SoundVolume = i*10;
                }
                if(i <= (GlobalSettings.SoundVolume/10)) {
                    DrawRectangleRec(SoundBar[i], RED);
                }
            }
            // Fullscreen
            DrawRectangle(95, 243, 250, 125, DARKGRAY);
            bool MouseHovering = false;
            for(int i = 0; i < 3; i++) {
                if(CheckCollisionRecs(MouseCursor, ScreenButtons[i])) {
                    DrawRectangleRec(ScreenButtons[i], RED);
                    MouseHovering = true;
                    if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
                        GlobalSettings.Fullscreen = i;
                        set_screen_mode();
                    }
                }
            }
            if (MouseHovering == false) {
                DrawRectangleRec(ScreenButtons[GlobalSettings.Fullscreen], GREEN);
            }
            DrawText("Screen Mode:", 50, 205, 42, WHITE);
            DrawText("Windowed", 100, 242, 42, WHITE);
            DrawText("Fullscreen", 100, 284, 42, WHITE);
            DrawText("Borderless", 100, 326, 42, WHITE);
	    DrawTexture(MouseCursorSprite, MouseCursor.x, MouseCursor.y, WHITE);
        EndMode2D();
        EndDrawing();
    }
    char *SettingsDirectory = SDL_GetPrefPath("iotib", "Pong");
    char SettingsFilePath[8192];
    snprintf(SettingsFilePath, sizeof(SettingsFilePath), "%s/settings.txt", SettingsDirectory);
    FILE *SettingsFile;
    // Put save to file here.
    if ((SettingsFile = fopen(SettingsFilePath, "w")) == NULL) {
        fprintf(stderr, "Unable to create settings file.\n");
        exit(1);
    }
    fprintf(SettingsFile, "sound_volume %d\n", GlobalSettings.SoundVolume);
    fprintf(SettingsFile, "music_volume %d\n", GlobalSettings.MusicVolume);
    fprintf(SettingsFile, "fullscreen %d", GlobalSettings.Fullscreen);
    fclose(SettingsFile);
    return;
}

static void help_text() {

}

int title_screen() {
    // Init Camera
    Camera2D MainCamera;
    MainCamera.offset = (Vector2){0,0};
    MainCamera.target = (Vector2){0,0};
    MainCamera.rotation = 0.0f;

    // Load leaderboard
    int NoScores = order_leaderboard();

    bool TitleScreenGoing = true;
    int Choice = 0;

    // Selection
    Rectangle Versus = {
        20, 150, 230, 48
    };
    Rectangle Marathon = {
        20, 200, 230, 48
    };
    Rectangle Settings = {
        20, 250, 230, 48
    };
    Rectangle Help = {
        20, 300, 230, 48
    };
    Rectangle Exit = {
        20, 350, 230, 48
    };
    Rectangle Mouse = {
        1280.0f/2, 720.0f/2, 10, 10
    };
    Rectangle AllScores = {
	595, 720-155, 400, 55
    };
    Rectangle *Selected;
    Selected = &Versus;

    //Music
    Mix_Music *TitleMusic = Mix_LoadMUS("resources/title.wav");
    Mix_PlayMusic(TitleMusic, -1);
    Mix_VolumeMusic(GlobalSettings.MusicVolume);

    // Mouse
    Vector2 OldPosition = GetMousePosition();
    Vector2 NewPosition = GetMousePosition();
    Texture2D MouseCursor = LoadTexture("resources/cursor.png");
    bool MouseCursorIn = true;
    DisableCursor();

    while(TitleScreenGoing == true && GameGoing == true) {
        
	printf("%lf, %d\n", GetTime(), SDL_AtomicGet(&Ticks));
        if (WindowShouldClose()) { //Quit Game if the window is closed.
            GameGoing = false;
            TitleScreenGoing = false;
        }
	
	    // Update Camera
        MainCamera.zoom = GetScreenHeight()/720.0f;
	    MainCamera.offset = (Vector2){GetScreenWidth()/2.0f, GetScreenHeight()/2.0f};
	    MainCamera.target = (Vector2){1280/2.0f, 720/2.0f};

        //Mouse
        if (MouseCursorIn == true) {
            OldPosition = NewPosition;
            NewPosition = GetMousePosition();
            Mouse.y -= OldPosition.y-NewPosition.y;
            Mouse.x -= OldPosition.x-NewPosition.x;
            if (Mouse.y >= 720 || Mouse.y <= 0) {
                Mouse.y += OldPosition.y-NewPosition.y;
            }
            if (Mouse.x >= 1280 || Mouse.x <= 0) {
                Mouse.x += OldPosition.x-NewPosition.x;
            }
        }
        
        if (IsKeyPressed(KEY_ESCAPE)) {
            EnableCursor();
            MouseCursorIn = false;
        } else if (IsCursorOnScreen() && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
            DisableCursor();
            MouseCursorIn = true;
        }

        if (CheckCollisionRecs(Mouse, Versus)) {
            Selected = &Versus;
            Choice = 0;
            if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
                TitleScreenGoing = false;
            }
        } else if (CheckCollisionRecs(Mouse, Marathon)) {
            Selected = &Marathon;
            Choice = 1;
            if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
                TitleScreenGoing = false;
            }
        } else if (CheckCollisionRecs(Mouse, Settings)) {
            Selected = &Settings;
        Choice = 0;
            if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
                settings(&MainCamera, TitleMusic);
            }
        } else if (CheckCollisionRecs(Mouse, Help)) {
            Selected = &Help;
        } else if (CheckCollisionRecs(Mouse, Exit)) {
            Selected = &Exit;
            if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
                GameGoing = false;
                Choice = -1;
            }
        }
        BeginDrawing();
            ClearBackground(BLACK);
            BeginMode2D(MainCamera);
                DrawRectangleRec(Mouse, YELLOW);
                DrawRectangle(0, 0, 1280, 720, (Color){20, 20, 20, 255});
                DrawRectangleRec(*Selected, RED);
                DrawText("PONG", 0, 0, 128, WHITE);
                DrawText("Versus", 20, 150, 48, WHITE);
                DrawText("Marathon", 20, 200, 48, WHITE);
                DrawText("Settings", 20, 250, 48, WHITE);
                DrawText("Help", 20, 300, 48, WHITE);
                DrawText("Exit", 20, 350, 48, WHITE);
                if(Choice == 1) {
                    DrawText("Leaderboard:", 600, 0, 48, WHITE);
                    if(NoScores == 1) {
                        goto skip;
                    }
		    printf("%c\n", Top10[0].Name[0]);
                    char LeaderboardText[1024];
                    for (int i = 1; i <= 10; i++) {
                        if(Top10[i-1].Name[0] != '\0') { //If name is blank, that means we're at the end of the list.
                            snprintf(LeaderboardText, sizeof(LeaderboardText), "%d: %s : %d", i, Top10[i-1].Name, Top10[i-1].Score);
                            DrawText(LeaderboardText, 600, 50*i, 48, WHITE);
                        }
                    }
                }
		skip:
		if (Choice == 1) {
			if(CheckCollisionRecs(Mouse, AllScores)) {
				DrawRectangleRec(AllScores, RED);
				if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
					score_screen(&MainCamera);
				}
			}
			DrawText("See All Scores...", 600, 720-150, 48, WHITE);
		}
            	DrawTexture(MouseCursor, Mouse.x, Mouse.y, WHITE);
            EndMode2D();
            DrawText(VersionString, GetScreenWidth()-400, GetScreenHeight()-32, 32, GREEN);
        EndDrawing();
    }
    Mix_HaltMusic();
    Mix_FreeMusic(TitleMusic);
    return Choice;
}