Compare commits
52 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1fb934f7a6 | ||
|
7bafb848bb | ||
|
e55253c244 | ||
|
81dda24c4f | ||
|
693d2b7dfe | ||
|
aec3cb4882 | ||
|
0399b32cf8 | ||
|
b16c557cf0 | ||
|
afc0a96516 | ||
|
eccebfc938 | ||
|
41db97f2e3 | ||
|
9ac4e06078 | ||
|
e62f43f6da | ||
|
9a27ff1209 | ||
|
dadf5946c8 | ||
|
30f536f559 | ||
|
e67f684fa7 | ||
|
33e69b0bb4 | ||
|
2c860c2f4b | ||
|
396c8f7ddc | ||
|
629f3f94a8 | ||
|
78128033ef | ||
|
ce8a8616ad | ||
|
2329df1eca | ||
|
bb156995cd | ||
|
c407253228 | ||
|
9982290d77 | ||
|
15b0846787 | ||
|
8b8771fd41 | ||
|
85be40dcda | ||
|
2a3c056909 | ||
|
a369855a27 | ||
|
b33a6478e6 | ||
|
681b6dcd2b | ||
|
34fb88a86a | ||
|
8a449ac7cd | ||
|
df535bb7d0 | ||
|
a2af143d23 | ||
|
1c227c0dce | ||
|
6aefc442d7 | ||
|
c577dcc2d7 | ||
|
45221cb72b | ||
|
d7e5845e4e | ||
|
3b2a0c8741 | ||
|
9e1738c05d | ||
|
affda45ac5 | ||
|
9088047c68 | ||
|
fc805e5c31 | ||
|
ca643ec62f | ||
|
2ebac3c167 | ||
|
b4aac4d41b | ||
|
cde0ae9bc9 |
2
.gitignore
vendored
@ -8,6 +8,8 @@ sdl2-config
|
||||
*.o
|
||||
*.psd
|
||||
*.exe
|
||||
*.json
|
||||
*.cfg
|
||||
!bhi.exe
|
||||
.tags*
|
||||
*.txt
|
||||
|
4
Makefile
@ -1,7 +1,7 @@
|
||||
libs = -lmingw32 -lSDL2main -lSDL2 -lopengl32 -lSDL2_image -lSDL2_ttf
|
||||
libs = -lmingw32 -lSDL2main -lSDL2 -lopengl32 -lSDL2_image -lSDL2_ttf -lSDL2_mixer
|
||||
includes = -I".\include"
|
||||
compiler = gcc
|
||||
warningLevel = -Wall -Wno-unused-variable -Wno-unused-but-set-variable
|
||||
warningLevel = -Wall -Wno-parentheses
|
||||
sources = *.c
|
||||
linker = -L".\lib"
|
||||
dir = bin
|
||||
|
BIN
bin/SDL2_mixer.dll
Normal file
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 2.5 MiB |
BIN
bin/assets/images/bar_texture.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
bin/assets/images/gameover.png
Normal file
After Width: | Height: | Size: 140 KiB |
BIN
bin/assets/images/l_arrow_button.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
bin/assets/images/numbers.png
Normal file
After Width: | Height: | Size: 219 KiB |
BIN
bin/assets/images/paused.png
Normal file
After Width: | Height: | Size: 271 KiB |
BIN
bin/assets/images/r_arrow_button.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
bin/assets/images/restart_button.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
bin/assets/images/return_button.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
bin/assets/images/scalar_button_pressed.png
Normal file
After Width: | Height: | Size: 542 B |
BIN
bin/assets/images/scalar_button_unpressed.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 8.0 KiB |
BIN
bin/assets/images/text.png
Normal file
After Width: | Height: | Size: 184 KiB |
BIN
bin/assets/images/upload.png
Normal file
After Width: | Height: | Size: 620 KiB |
BIN
bin/assets/images/yourscore.png
Normal file
After Width: | Height: | Size: 222 KiB |
BIN
bin/assets/sounds/death.wav
Normal file
BIN
bin/assets/sounds/hit1.wav
Normal file
BIN
bin/assets/sounds/hit2.wav
Normal file
BIN
bin/assets/sounds/hit3.wav
Normal file
BIN
bin/assets/sounds/hit4.wav
Normal file
BIN
bin/assets/sounds/hit5.wav
Normal file
BIN
bin/assets/sounds/ingame_music.wav
Normal file
BIN
bin/assets/sounds/menu_music.wav
Normal file
BIN
bin/bhi.exe
BIN
bin/libFLAC-8.dll
Normal file
BIN
bin/libmodplug-1.dll
Normal file
BIN
bin/libmpg123-0.dll
Normal file
BIN
bin/libogg-0.dll
Normal file
BIN
bin/libvorbis-0.dll
Normal file
BIN
bin/libvorbisfile-3.dll
Normal file
432
breakout.c
@ -1,32 +1,62 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
|
||||
#include "breakout.h"
|
||||
#include "vector.h"
|
||||
#include "font.h"
|
||||
#include "gamestate.h"
|
||||
#include "gameover.h"
|
||||
#include "main.h"
|
||||
|
||||
extern float XScale, YScale;
|
||||
extern int width, height;
|
||||
|
||||
#define BALL_TexturePath "assets/images/ball.png"
|
||||
#define PADDLE_TexturePath "assets/images/paddle.png"
|
||||
#define BLOCK_TexturePath "assets/images/spritesheet.png"
|
||||
#define BALL_TexturePath "assets/images/ball.png"
|
||||
#define PADDLE_TexturePath "assets/images/paddle.png"
|
||||
#define BLOCK_TexturePath "assets/images/spritesheet.png"
|
||||
#define BREAKOUT_CountdownTexturePath "assets/images/text.png"
|
||||
#define BREAKOUT_PausedTexturePath "assets/images/paused.png"
|
||||
#define BREAKOUT_IngameSoundPath "assets/sounds/ingame_music.wav"
|
||||
#define BREAKOUT_DeathSoundPath "assets/sounds/death.wav"
|
||||
#define BREAKOUT_HitSoundPath1 "assets/sounds/hit1.wav"
|
||||
#define BREAKOUT_HitSoundPath2 "assets/sounds/hit2.wav"
|
||||
#define BREAKOUT_HitSoundPath3 "assets/sounds/hit3.wav"
|
||||
#define BREAKOUT_HitSoundPath4 "assets/sounds/hit4.wav"
|
||||
#define BREAKOUT_HitSoundPath5 "assets/sounds/hit5.wav"
|
||||
#define BALL_MinSpeed 8.0f
|
||||
#define BALL_MaxSpeed 25.0f
|
||||
#define BALL_AccelerationTime 10000
|
||||
#define PADDLE_MaxSize 300
|
||||
#define PADDLE_MinSize 50
|
||||
#define PADDLE_AccelerationTime 18000
|
||||
#define BREAKOUT_LiveHUDSize 35
|
||||
#define BREAKOUT_LiveHUDMargin 8
|
||||
#define BREAKOUT_PushIntervale 1800
|
||||
#define BREAKOUT_FadeTime 1000
|
||||
|
||||
#ifndef __nullptr__
|
||||
#define Nullptr(type) (type *)0
|
||||
#endif // __nullptr__
|
||||
|
||||
float PADDLE_SmoothFactor = 0.1f;
|
||||
float BLOCK_SmoothFactor = 0.05f;
|
||||
float BREAKOUT_LifePenalty = 0.75f;
|
||||
int BLOCK_TextureCount = 24;
|
||||
int BREAKOUT_BoxWidth, BREAKOUT_BoxHeight;
|
||||
int BALL_TextureCount = 9;
|
||||
int BREAKOUT_CountdownTextureCount = 4;
|
||||
int PADDLE_TextureCount = 9;
|
||||
SDL_Texture * BALL_Texture;
|
||||
SDL_Texture * BREAKOUT_CountdownTexture;
|
||||
SDL_Texture * PADDLE_Texture;
|
||||
SDL_Texture * BLOCK_Texture;
|
||||
SDL_Texture * BREAKOUT_PausedTexture;
|
||||
SDL_Rect * BALL_SourceRects;
|
||||
SDL_Rect * BREAKOUT_CountdownSourceRects;
|
||||
SDL_Rect * PADDLE_SourceRects;
|
||||
SDL_Rect * BLOCK_SourceRects;
|
||||
Uint8 * PADDLE_MoveLeftKeys, * PADDLE_MoveRightKeys;
|
||||
@ -34,72 +64,174 @@ bool BREAKOUT_IsInit = false;
|
||||
bool BALL_IsInit = false;
|
||||
bool PADDLE_IsInit = false;
|
||||
bool BLOCK_IsInit = false;
|
||||
Mix_Chunk * BREAKOUT_DeathSound;
|
||||
Mix_Chunk ** BREAKOUT_HitSound;
|
||||
Mix_Music * BREAKOUT_IngameMusic;
|
||||
|
||||
void BREAKOUT_INITIALIZE(SDL_Renderer * renderer, int width, int height){
|
||||
void BREAKOUT_INITIALIZE(SDL_Renderer * renderer){
|
||||
if (!BREAKOUT_IsInit) {
|
||||
printf("Initializing Game...\n");
|
||||
srand(time(NULL));
|
||||
BREAKOUT_BoxWidth = width;
|
||||
BREAKOUT_BoxHeight = height;
|
||||
BALL_Initialize(renderer);
|
||||
PADDLE_Initialize(renderer);
|
||||
BLOCK_Initialize(renderer);
|
||||
BREAKOUT_CountdownTexture = IMG_LoadTexture(renderer, BREAKOUT_CountdownTexturePath);
|
||||
if (!BREAKOUT_CountdownTexture) printf("Countdown texture failed to load!\n");
|
||||
BREAKOUT_PausedTexture = IMG_LoadTexture(renderer, BREAKOUT_PausedTexturePath);
|
||||
if (!BREAKOUT_PausedTexture) printf("Paused texture failed to load!\n");
|
||||
BREAKOUT_CountdownTextureCount = 4;
|
||||
BREAKOUT_CountdownSourceRects = (SDL_Rect *)malloc(BREAKOUT_CountdownTextureCount * sizeof(SDL_Rect));
|
||||
if (!BREAKOUT_CountdownSourceRects) printf("FATAL! Memory allocation failed!\n");
|
||||
BREAKOUT_CountdownSourceRects[0] = (SDL_Rect) {.x = 1, .y = 668, .w = 1000, .h = 732 };
|
||||
BREAKOUT_CountdownSourceRects[1] = (SDL_Rect) {.x = 1, .y = 1, .w = 242, .h = 665 };
|
||||
BREAKOUT_CountdownSourceRects[2] = (SDL_Rect) {.x = 245, .y = 1, .w = 443, .h = 665 };
|
||||
BREAKOUT_CountdownSourceRects[3] = (SDL_Rect) {.x = 690, .y = 1, .w = 443, .h = 665 };
|
||||
BREAKOUT_HitSound = malloc(5 * sizeof(Mix_Chunk *));
|
||||
BREAKOUT_HitSound[0] = Mix_LoadWAV(BREAKOUT_HitSoundPath1);
|
||||
BREAKOUT_HitSound[1] = Mix_LoadWAV(BREAKOUT_HitSoundPath2);
|
||||
BREAKOUT_HitSound[2] = Mix_LoadWAV(BREAKOUT_HitSoundPath3);
|
||||
BREAKOUT_HitSound[3] = Mix_LoadWAV(BREAKOUT_HitSoundPath4);
|
||||
BREAKOUT_HitSound[4] = Mix_LoadWAV(BREAKOUT_HitSoundPath5);
|
||||
BREAKOUT_DeathSound = Mix_LoadWAV(BREAKOUT_DeathSoundPath);
|
||||
BREAKOUT_IngameMusic = Mix_LoadMUS(BREAKOUT_IngameSoundPath);
|
||||
printf("Game initialized!\n");
|
||||
BREAKOUT_IsInit = true;
|
||||
} else printf("Game is already initialized!\n");
|
||||
} /* BREAKOUT_INITIALIZE */
|
||||
|
||||
void BREAKOUT_StartMusic(){
|
||||
printf("Attempting to start game music...\n");
|
||||
if (!Mix_PlayingMusic())
|
||||
Mix_FadeInMusic(BREAKOUT_IngameMusic, -1, BREAKOUT_FadeTime);
|
||||
else printf("Game music is already playing!\n");
|
||||
}
|
||||
|
||||
void BREAKOUT_PauseMusic(){
|
||||
printf("Attempting to pause game music...\n");
|
||||
if (Mix_PlayingMusic())
|
||||
Mix_HaltMusic();
|
||||
// Mix_FadeOutMusic(BREAKOUT_FadeTime);
|
||||
else printf("There is no game music to be paused!\n");
|
||||
}
|
||||
|
||||
// Toggle Game pause, not the music!
|
||||
void BREAKOUT_TogglePause(Scenery * scenery){
|
||||
(scenery->IsPaused) = !(scenery->IsPaused);
|
||||
printf("Game was %s!\n", ( (scenery->IsPaused) ? "paused" : "unpaused"));
|
||||
}
|
||||
|
||||
void BREAKOUT_KeyPressed(Scenery * scenery, SDL_KeyboardEvent * b){
|
||||
if ((b->keysym).scancode == SDL_SCANCODE_ESCAPE) {
|
||||
printf("Escape was pressed ingame! Toggle Pause...\n");
|
||||
BREAKOUT_TogglePause(scenery);
|
||||
}
|
||||
}
|
||||
|
||||
Scenery BREAKOUT_CreateDefault(){
|
||||
Scenery scenery;
|
||||
|
||||
scenery.StartCountdown = 240;
|
||||
scenery.TopLeftBlockColor = 0;
|
||||
scenery.IsGameOver = false;
|
||||
scenery.BlockCount = 135;
|
||||
scenery.ball = BALL_CreateDefault();
|
||||
scenery.paddle = PADDLE_CreateDefault();
|
||||
scenery.blocks = malloc(scenery.BlockCount * sizeof(Block));
|
||||
scenery.Frames = 0;
|
||||
scenery.YBlocks = 9;
|
||||
scenery.XBlocks = 15;
|
||||
scenery.Score = 0;
|
||||
if (!(scenery.blocks)) printf("FATAL! Memory allocation failed!\n");
|
||||
scenery.IsPaused = false;
|
||||
scenery.Lives = 3;
|
||||
scenery.DestroyedBlocks = 0;
|
||||
int index;
|
||||
for (int y = 0; y < 9; y++) {
|
||||
index = 15 * y;
|
||||
for (int x = 0; x < 15; x++) {
|
||||
for (int y = 0; y < scenery.YBlocks; y++) {
|
||||
index = (scenery.XBlocks) * y;
|
||||
for (int x = 0; x < scenery.XBlocks; x++) {
|
||||
scenery.blocks[x + index] = BLOCK_CreateDefault();
|
||||
scenery.blocks[x + index].TargetRect = (SDL_Rect) {.x = ((128 * x) + 2), .y = ((64 * y) + 1), .w = 124, .h = 62 };
|
||||
scenery.blocks[x + index].TextureIndex = y + x;
|
||||
scenery.blocks[x + index].DestYValue = ((64 * y) + 1);
|
||||
}
|
||||
}
|
||||
return scenery;
|
||||
} /* BREAKOUT_CreateDefault */
|
||||
|
||||
// This Function is obsolete! Do not use it!
|
||||
void BREAKOUT_ChangeSize(int width, int height){
|
||||
BREAKOUT_BoxWidth = width;
|
||||
BREAKOUT_BoxHeight = height;
|
||||
void BREAKOUT_IncreaseScoreBy(Scenery * scenery, int scoreInc){
|
||||
(scenery->Score) += scoreInc;
|
||||
}
|
||||
|
||||
void TEXTURE_RenderCenteredSpriteSheet(SDL_Renderer * renderer, SDL_Texture * texture, SDL_Rect * srcRect, float Scale){
|
||||
SDL_Rect target;
|
||||
|
||||
target.w = (int)roundf(((float)(srcRect->w)) * Scale);
|
||||
target.h = (int)roundf(((float)(srcRect->h)) * Scale);
|
||||
target.x = ((width - (target.w)) / 2);
|
||||
target.y = ((height - (target.h)) / 2);
|
||||
SDL_RenderCopy(renderer, texture, srcRect, &target);
|
||||
}
|
||||
|
||||
void TEXTURE_RenderCentered(SDL_Renderer * renderer, SDL_Texture * texture, float Scale){
|
||||
int w, h;
|
||||
SDL_Rect target;
|
||||
|
||||
SDL_QueryTexture(texture, NULL, NULL, &w, &h);
|
||||
target.w = (int)roundf(((float)w) * Scale);
|
||||
target.h = (int)roundf(((float)h) * Scale);
|
||||
target.x = ((width - (target.w)) / 2);
|
||||
target.y = ((height - (target.h)) / 2);
|
||||
SDL_RenderCopy(renderer, texture, NULL, &target);
|
||||
}
|
||||
|
||||
void BREAKOUT_PushNewRow(Scenery * scenery){
|
||||
printf("Pushing new line...\n");
|
||||
(scenery->TopLeftBlockColor)--;
|
||||
// Rotate through textures
|
||||
if ((scenery->TopLeftBlockColor) < 0) (scenery->TopLeftBlockColor) = (BLOCK_TextureCount - 1);
|
||||
else if ((scenery->TopLeftBlockColor) >= 24) (scenery->TopLeftBlockColor) = 0;
|
||||
int oldBlockCount = (scenery->BlockCount);
|
||||
(scenery->BlockCount) += (scenery->XBlocks);
|
||||
(scenery->YBlocks)++;
|
||||
scenery->blocks = realloc((scenery->blocks), (scenery->BlockCount) * sizeof(Block));
|
||||
for (size_t i = 0; i < oldBlockCount; i++) {
|
||||
(scenery->blocks)[i].DestYValue += 64;
|
||||
}
|
||||
for (size_t x = 0; x < (scenery->XBlocks); x++) {
|
||||
(scenery->blocks)[x + oldBlockCount] = BLOCK_CreateDefault();
|
||||
(scenery->blocks)[x + oldBlockCount].TargetRect = (SDL_Rect) {.x = ((128 * x) + 2), .y = -63, .w = 124, .h = 62 };
|
||||
(scenery->blocks)[x + oldBlockCount].TextureIndex = (((scenery->TopLeftBlockColor) + x) % BLOCK_TextureCount);
|
||||
(scenery->blocks)[x + oldBlockCount].DestYValue = 1;
|
||||
}
|
||||
printf("New line was pushed!\n");
|
||||
} /* BREAKOUT_PushNewRow */
|
||||
|
||||
void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){
|
||||
if (scenery->IsPaused) return; // Currently paused
|
||||
if ((scenery->StartCountdown)-- < 0)
|
||||
(scenery->StartCountdown) = 0;
|
||||
else return; // Currently Counting down
|
||||
if (scenery->IsPaused) return;
|
||||
if ((scenery->StartCountdown)-- > 0) return;
|
||||
(scenery->Frames)++;
|
||||
if (scenery->IsGameOver) {
|
||||
BALL_ResetPosition(&(scenery->ball));
|
||||
PADDLE_ResetPosition(&(scenery->paddle));
|
||||
scenery->StartCountdown = 240;
|
||||
scenery->IsGameOver = false;
|
||||
if (--(scenery->Lives) <= 0)
|
||||
printf("Game over, no lives left!\n");
|
||||
else
|
||||
GAME_ChangeState(GameOver);
|
||||
else {
|
||||
// Reduce score when there is a life left
|
||||
// scenery->Score = (int)roundf((float)(scenery->Score) * BREAKOUT_LifePenalty);
|
||||
printf("Oh oh, only %d lives left!\n", scenery->Lives);
|
||||
}
|
||||
return;
|
||||
}
|
||||
PADDLE_Update(&(scenery->paddle), keystate); // Update paddle before ball because paddle is not static!
|
||||
BALL_Update(&(scenery->ball), scenery);
|
||||
if ((scenery->Frames) % BREAKOUT_PushIntervale == 0) {
|
||||
BREAKOUT_PushNewRow(scenery);
|
||||
}
|
||||
PADDLE_Update(&(scenery->paddle), scenery, keystate); // Update paddle before ball because paddle is not static!
|
||||
for (int i = 0; i < (scenery->BlockCount); i++) {
|
||||
BLOCK_Update((scenery->blocks) + i);
|
||||
}
|
||||
BALL_Update(&(scenery->ball), scenery);
|
||||
} /* BREAKOUT_Update */
|
||||
|
||||
void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer){
|
||||
@ -108,36 +240,53 @@ void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer){
|
||||
}
|
||||
BALL_Draw(renderer, &(scenery->ball));
|
||||
PADDLE_Draw(renderer, &(scenery->paddle));
|
||||
if (scenery->IsPaused)
|
||||
FONT_RenderTextCentered(renderer, "PAUSED", 3.0f, 1);
|
||||
else if ((scenery->StartCountdown) > 0) {
|
||||
if ((scenery->StartCountdown) <= 60) {
|
||||
FONT_RenderTextCentered(renderer, "GO", 6.0f, 3);
|
||||
} else if ((scenery->StartCountdown) <= 120) {
|
||||
FONT_RenderTextCentered(renderer, "1", 6.0f, 1);
|
||||
} else if ((scenery->StartCountdown) <= 180) {
|
||||
FONT_RenderTextCentered(renderer, "2", 6.0f, 1);
|
||||
} else {
|
||||
FONT_RenderTextCentered(renderer, "3", 6.0f, 1);
|
||||
}
|
||||
SCORE_DrawHUD(renderer, scenery);
|
||||
BREAKOUT_DrawLivesHUD(renderer, scenery);
|
||||
if (scenery->IsPaused) {
|
||||
TEXTURE_RenderCentered(renderer, BREAKOUT_PausedTexture, 0.5f);
|
||||
} else if ((scenery->StartCountdown) > 0) { // ! Render Z-Layer !
|
||||
TEXTURE_RenderCenteredSpriteSheet(renderer, BREAKOUT_CountdownTexture, (BREAKOUT_CountdownSourceRects + (((scenery->StartCountdown) - 1) / 60)), 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void BREAKOUT_DrawLivesHUD(SDL_Renderer * renderer, Scenery * scenery){
|
||||
SDL_Rect tmpRect;
|
||||
|
||||
tmpRect.y = BREAKOUT_LiveHUDMargin;
|
||||
tmpRect.w = BREAKOUT_LiveHUDSize;
|
||||
tmpRect.h = BREAKOUT_LiveHUDSize;
|
||||
tmpRect.x = width - BREAKOUT_LiveHUDMargin;
|
||||
|
||||
for (int i = 0; i < (scenery->Lives); i++) {
|
||||
tmpRect.x -= (BREAKOUT_LiveHUDSize + BREAKOUT_LiveHUDMargin);
|
||||
BALL_DrawTexture(renderer, &tmpRect, (scenery->ball).TextureIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void BREAKOUT_DEINITIALIZE(){
|
||||
if (BREAKOUT_IsInit) {
|
||||
printf("De-initializing Game...\n");
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Mix_FreeChunk(BREAKOUT_HitSound[i]);
|
||||
}
|
||||
free(BREAKOUT_HitSound);
|
||||
Mix_FreeChunk(BREAKOUT_DeathSound);
|
||||
Mix_FreeMusic(BREAKOUT_IngameMusic);
|
||||
SDL_DestroyTexture(BREAKOUT_CountdownTexture);
|
||||
SDL_DestroyTexture(BREAKOUT_PausedTexture);
|
||||
free(PADDLE_MoveLeftKeys);
|
||||
free(PADDLE_MoveRightKeys);
|
||||
free(BALL_SourceRects);
|
||||
free(PADDLE_SourceRects);
|
||||
free(BLOCK_SourceRects);
|
||||
free(BREAKOUT_CountdownSourceRects);
|
||||
BALL_Deinitialize();
|
||||
PADDLE_Deinitialize();
|
||||
BLOCK_Deinitialize();
|
||||
printf("Game de-initialized!\n");
|
||||
BREAKOUT_IsInit = false;
|
||||
} else printf("Game is already de-initialized!\n");
|
||||
}
|
||||
} /* BREAKOUT_DEINITIALIZE */
|
||||
|
||||
void BREAKOUT_DestroyObject(Scenery * scenery){
|
||||
for (size_t i = 0; i < (scenery->BlockCount); i++) {
|
||||
@ -153,33 +302,49 @@ void BALL_Initialize(SDL_Renderer * renderer){
|
||||
printf("Initializing Ball...\n");
|
||||
BALL_Texture = IMG_LoadTexture(renderer, BALL_TexturePath);
|
||||
if (!BALL_Texture) printf("Ball texture failed to load!\n");
|
||||
BALL_SourceRects = (SDL_Rect *)malloc(1 * sizeof(SDL_Rect));
|
||||
BALL_TextureCount = 9;
|
||||
BALL_SourceRects = (SDL_Rect *)malloc(BALL_TextureCount * sizeof(SDL_Rect));
|
||||
if (!BALL_SourceRects) printf("FATAL! Memory allocation failed!\n");
|
||||
BALL_SourceRects[0] = (SDL_Rect) {.x = 0, .y = 0, .w = 512, .h = 512 };
|
||||
BALL_SourceRects[0] = (SDL_Rect) {.x = 1029, .y = 1029, .w = 512, .h = 512 };
|
||||
BALL_SourceRects[1] = (SDL_Rect) {.x = 1, .y = 1, .w = 512, .h = 512 };
|
||||
BALL_SourceRects[2] = (SDL_Rect) {.x = 1, .y = 515, .w = 512, .h = 512 };
|
||||
BALL_SourceRects[3] = (SDL_Rect) {.x = 1, .y = 1029, .w = 512, .h = 512 };
|
||||
BALL_SourceRects[4] = (SDL_Rect) {.x = 515, .y = 1, .w = 512, .h = 512 };
|
||||
BALL_SourceRects[5] = (SDL_Rect) {.x = 1029, .y = 1, .w = 512, .h = 512 };
|
||||
BALL_SourceRects[6] = (SDL_Rect) {.x = 515, .y = 515, .w = 512, .h = 512 };
|
||||
BALL_SourceRects[7] = (SDL_Rect) {.x = 515, .y = 1029, .w = 512, .h = 512 };
|
||||
BALL_SourceRects[8] = (SDL_Rect) {.x = 1029, .y = 515, .w = 512, .h = 512 };
|
||||
printf("Ball initialized!\n");
|
||||
BALL_IsInit = true;
|
||||
} else printf("Ball is already initialized!\n");
|
||||
}
|
||||
} /* BALL_Initialize */
|
||||
|
||||
Ball BALL_CreateDefault(){
|
||||
double rotation = (double)(rand() % 360);
|
||||
|
||||
return (Ball) {
|
||||
.Location = (Vector) {.x = BREAKOUT_BoxWidth / 2 - 15, .y = BREAKOUT_BoxHeight - 130 },
|
||||
.Momentum = (Vector) {.x = 0.0f, .y = 15.0f },
|
||||
.TargetRect = (SDL_Rect) {.x = BREAKOUT_BoxWidth / 2 - 15, .y = BREAKOUT_BoxHeight - 130, .w = 30, .h = 30 },
|
||||
.Location = (Vector) {.x = (width / 2) - 15, .y = height - 131 },
|
||||
.Momentum = (Vector) {.x = 0.0f, .y = BALL_MinSpeed },
|
||||
.TargetRect = (SDL_Rect) {.x = width / 2 - 15, .y = height - 130, .w = 30, .h = 30 },
|
||||
.Size = 15.0f,
|
||||
.Rotation = rotation,
|
||||
.RotationValue = 2,
|
||||
.Rotation = 0,
|
||||
.RotationValue = 9,
|
||||
.TextureIndex = 0,
|
||||
.Speed = 15.0f
|
||||
}; // Objekt für die Eigenschaften des Balls
|
||||
}
|
||||
|
||||
void BALL_ResetPosition(Ball * obj){
|
||||
(obj->Location).x = BREAKOUT_BoxWidth / 2 - 15;
|
||||
(obj->Location).y = BREAKOUT_BoxHeight - 130;
|
||||
(obj->Location).x = width / 2 - (obj->Size);
|
||||
(obj->Location).y = height - 101 - (2 * (obj->Size));
|
||||
RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location));
|
||||
(obj->Momentum) = VECTOR_GetScaledDirectionalUnitVector(0.0f, (obj->Speed));
|
||||
}
|
||||
|
||||
void BALL_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index){
|
||||
if (index > BALL_TextureCount || index < 0) {
|
||||
printf("Ball with unkown texture index %d aus [0,...,%d]\n", index, (BALL_TextureCount - 1));
|
||||
return;
|
||||
}
|
||||
SDL_RenderCopy(renderer, BALL_Texture, BALL_SourceRects + index, dstRect);
|
||||
}
|
||||
|
||||
void BALL_Draw(SDL_Renderer * renderer, Ball * obj){
|
||||
@ -190,16 +355,27 @@ void BALL_Draw(SDL_Renderer * renderer, Ball * obj){
|
||||
bool BALL_CollideWithRect(Ball * obj, SDL_Rect * rect){
|
||||
if (!RECT_Collide(&(obj->TargetRect), rect)) return false;
|
||||
// Already returned with false if square ball hitbox didnt collide with rect
|
||||
SDL_Point ballCenter = BALL_GetCenter(obj);
|
||||
Vector center = (Vector) {.x = ballCenter.x, .y = ballCenter.y };
|
||||
Vector unitMomentum = VECTOR_ChangeScaleTo((obj->Momentum), 1.0f);
|
||||
Vector center = BALL_GetCenter(obj);
|
||||
Vector corner;
|
||||
bool left, right, top, bottom, yMid = false, xMid = false;
|
||||
left = (ballCenter.x) < (rect->x);
|
||||
right = (ballCenter.x) > (rect->x) + (rect->w);
|
||||
top = (ballCenter.y) < (rect->y);
|
||||
bottom = (ballCenter.y) > (rect->y) + (rect->h);
|
||||
left = (center.x) < (rect->x);
|
||||
right = (center.x) > (rect->x) + (rect->w);
|
||||
top = (center.y) < (rect->y);
|
||||
bottom = (center.y) > (rect->y) + (rect->h);
|
||||
yMid = !(top || bottom);
|
||||
xMid = !(left || right);
|
||||
// Move away from hitbox from where you came from when stuck in the middle of the block at high speeds
|
||||
while (yMid && xMid) {
|
||||
(obj->Location) = VECTOR_Subtract((obj->Location), unitMomentum);
|
||||
center = BALL_GetCenter(obj);
|
||||
left = (center.x) < (rect->x);
|
||||
right = (center.x) > (rect->x) + (rect->w);
|
||||
top = (center.y) < (rect->y);
|
||||
bottom = (center.y) > (rect->y) + (rect->h);
|
||||
yMid = !(top || bottom);
|
||||
xMid = !(left || right);
|
||||
}
|
||||
if (yMid) // Hit left or right
|
||||
(obj->Momentum).x = -(obj->Momentum).x;
|
||||
if (xMid) // Hit bottom or top
|
||||
@ -217,15 +393,13 @@ bool BALL_CollideWithRect(Ball * obj, SDL_Rect * rect){
|
||||
} else if (bottom) {
|
||||
corner.y = ((rect->y) + (rect->h));
|
||||
}
|
||||
// printf("Hit corner at %.0f|%.0f!\n", corner.x, corner.y);
|
||||
// printf("Ball center at %.0f|%.0f!\n", center.x, center.y);
|
||||
// TODO: Reflection at lot
|
||||
double lot = VECTOR_GetRotation(VECTOR_GetVectorFromTo(corner, center));
|
||||
Vector cornerToMid = VECTOR_GetVectorFromTo(corner, center);
|
||||
if (VECTOR_GetMagnitude(cornerToMid) > (obj->Size)) return false;
|
||||
double lot = VECTOR_GetRotation(cornerToMid);
|
||||
double inRotation = fmod(VECTOR_GetRotation(obj->Momentum) + 180.0f, 360.0f);
|
||||
double outAngle = fmod(lot + (0.5 * (lot - inRotation)), 360.0f);
|
||||
printf("In: %.2f | Lot: %.2f | Out: %.2f\n", inRotation, lot, outAngle);
|
||||
(obj->Momentum) = VECTOR_GetScaledDirectionalUnitVector(outAngle, (obj->Speed));
|
||||
// printf("New Magnitude = %.2f\n", VECTOR_GetMagnitude((obj->Momentum)));
|
||||
return true;
|
||||
} /* BALL_CollideWithRect */
|
||||
|
||||
@ -260,14 +434,14 @@ void RECT_SetTargetPos(SDL_Rect * rect, Vector * Location){
|
||||
rect->y = (int)round(Location->y);
|
||||
}
|
||||
|
||||
SDL_Point BALL_GetCenter(Ball * obj){
|
||||
return (SDL_Point) {.x = ((obj->TargetRect).x) + (obj->Size), .y = ((obj->TargetRect).y) + (obj->Size) };
|
||||
Vector BALL_GetCenter(Ball * obj){
|
||||
return (Vector) {.x = ((obj->Location).x) + (obj->Size), .y = ((obj->Location).y) + (obj->Size) };
|
||||
}
|
||||
|
||||
void BALL_CollideWithBorders(Ball * obj){
|
||||
if ((obj->Location).y < 0.0f)
|
||||
(obj->Momentum).y = -(obj->Momentum).y;
|
||||
if ((obj->Location).x < 0.0f || (obj->Location).x > BREAKOUT_BoxWidth - (2 * (obj->Size)))
|
||||
if ((obj->Location).x < 0.0f || (obj->Location).x > width - (2 * (obj->Size)))
|
||||
(obj->Momentum).x = -(obj->Momentum).x;
|
||||
}
|
||||
|
||||
@ -276,30 +450,47 @@ void BALL_MoveAwayFromBoundaries(Ball * obj){
|
||||
((obj->Location).y)++;
|
||||
while (((obj->Location).x) < 0)
|
||||
((obj->Location).x)++;
|
||||
while ((((obj->Location).x) + ((obj->Size) * 2)) > BREAKOUT_BoxWidth)
|
||||
while ((((obj->Location).x) + ((obj->Size) * 2)) > width)
|
||||
((obj->Location).x)--;
|
||||
}
|
||||
|
||||
bool BALL_CollideWithPaddle(Ball * obj, Paddle * paddle){
|
||||
if (RECT_Collide(&(obj->TargetRect), &(paddle->TargetRect))) {
|
||||
SDL_Point ballCenter = BALL_GetCenter(obj);
|
||||
Vector ballCenter = BALL_GetCenter(obj);
|
||||
if (ballCenter.y > (paddle->TargetRect).y) // if the ball hits the paddle from the sides (or the bottom (?))
|
||||
BALL_CollideWithRect(obj, &(paddle->TargetRect));
|
||||
else
|
||||
BALL_SteerMomentum(obj, paddle); // Sets it to unit vector!
|
||||
// Following assumes that the paddle position was udated before the ball was updated
|
||||
// Following assumes that the paddle position was udated before the ball was updated
|
||||
while (RECT_Collide(&(obj->TargetRect), &(paddle->TargetRect))) { // Move away from rect in small steps
|
||||
(obj->Location) = VECTOR_Add((obj->Location), (obj->Momentum));
|
||||
BALL_MoveAwayFromBoundaries(obj);
|
||||
RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location));
|
||||
}
|
||||
(obj->Momentum) = VECTOR_ChangeScaleTo((obj->Momentum), (obj->Speed));
|
||||
BALL_PlayCollisionSound();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* BALL_CollideWithPaddle */
|
||||
|
||||
void BALL_AdaptSpeedGradient(Ball * obj, int FrameCount){
|
||||
if (FrameCount > BALL_AccelerationTime)
|
||||
obj->Speed = BALL_MaxSpeed;
|
||||
else
|
||||
obj->Speed = BALL_MinSpeed + (((double)FrameCount / (double)BALL_AccelerationTime) * (BALL_MaxSpeed - BALL_MinSpeed));
|
||||
}
|
||||
|
||||
void BALL_PlayCollisionSound(){
|
||||
int sound;
|
||||
|
||||
Mix_PlayChannel(-1, BREAKOUT_HitSound[(sound = (rand() % 5))], 0);
|
||||
printf("Collision sound %d played...\n", sound);
|
||||
}
|
||||
|
||||
void BALL_Update(Ball * obj, Scenery * scenery){
|
||||
BALL_AdaptSpeedGradient(obj, (scenery->Frames));
|
||||
(obj->Momentum) = VECTOR_ChangeScaleTo((obj->Momentum), (obj->Speed));
|
||||
Block * blocks = (scenery->blocks);
|
||||
Paddle * paddle = &(scenery->paddle);
|
||||
int BlockCount = scenery->BlockCount;
|
||||
@ -316,15 +507,22 @@ void BALL_Update(Ball * obj, Scenery * scenery){
|
||||
oldMomentum = obj->Momentum;
|
||||
oldLocation = obj->Location;
|
||||
if (BALL_CollideWithRect(obj, &(blocks[i].TargetRect))) {
|
||||
BALL_PlayCollisionSound();
|
||||
BLOCK_DealDamage(blocks + i, 1);
|
||||
if (blocks[i].HP <= 0) {
|
||||
(scenery->DestroyedBlocks)++;
|
||||
BREAKOUT_IncreaseScoreBy(scenery, (int)round((((scenery->ball).Speed) * ((scenery->ball).Speed) / 5.0f)));
|
||||
}
|
||||
(obj->Location) = VECTOR_Add(oldLocation, (obj->Momentum));
|
||||
BALL_MoveAwayFromBoundaries(obj);
|
||||
RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location));
|
||||
}
|
||||
}
|
||||
if ((obj->Location).y > BREAKOUT_BoxHeight) // Collide with box boundaries
|
||||
if ((obj->Location).y > height) { // Collide with box boundaries
|
||||
Mix_PlayChannel(-1, BREAKOUT_DeathSound, 0);
|
||||
scenery->IsGameOver = true;
|
||||
else BALL_CollideWithBorders(obj);
|
||||
printf("Ball called game_over!\n");
|
||||
} else BALL_CollideWithBorders(obj);
|
||||
RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location));
|
||||
} /* BALL_Update */
|
||||
|
||||
@ -364,27 +562,31 @@ void PADDLE_Initialize(SDL_Renderer * renderer){
|
||||
} /* PADDLE_Initialize */
|
||||
|
||||
Paddle PADDLE_CreateDefault(){
|
||||
int defaultpaddlewidth = 300;
|
||||
|
||||
return (Paddle) {
|
||||
.TargetRect = (SDL_Rect) {.x = (BREAKOUT_BoxWidth - defaultpaddlewidth) / 2, .y = BREAKOUT_BoxHeight - 100, .w = defaultpaddlewidth, .h = 30 },
|
||||
.TargetRect = (SDL_Rect) {.x = (width - PADDLE_MaxSize) / 2, .y = height - 100, .w = PADDLE_MaxSize, .h = 30 },
|
||||
.TextureIndex = 0,
|
||||
.Speed = 10,
|
||||
.SteeringAngle = 40.0f,
|
||||
.Mode = KeyboardControl
|
||||
.Mode = MouseControl
|
||||
}; // Objekt für die Eigenschaften des Balls
|
||||
}
|
||||
|
||||
void PADDLE_ResetPosition(Paddle * obj){
|
||||
(obj->TargetRect).x = (BREAKOUT_BoxWidth - ((obj->TargetRect).w)) / 2;
|
||||
(obj->TargetRect).y = BREAKOUT_BoxHeight - 100;
|
||||
(obj->TargetRect).x = (width - ((obj->TargetRect).w)) / 2;
|
||||
(obj->TargetRect).y = height - 100;
|
||||
}
|
||||
|
||||
void PADDLE_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index){
|
||||
if (index > PADDLE_TextureCount || index < 0) {
|
||||
printf("Paddle with unkown texture index %d aus [0,...,%d]\n", index, (PADDLE_TextureCount - 1));
|
||||
return;
|
||||
}
|
||||
SDL_RenderCopy(renderer, PADDLE_Texture, PADDLE_SourceRects + index, dstRect);
|
||||
}
|
||||
|
||||
void PADDLE_Draw(SDL_Renderer * renderer, Paddle * obj){
|
||||
// printf("Paddle drawn at (%d|%d)!\n", (obj->TargetRect).x, (obj->TargetRect).x);
|
||||
SDL_RenderCopy(renderer, PADDLE_Texture, PADDLE_SourceRects + (obj->TextureIndex), &(obj->TargetRect));
|
||||
// SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
// SDL_RenderDrawRect(renderer, &(obj->TargetRect));
|
||||
}
|
||||
|
||||
bool KeyPressed(const Uint8 * keystate, Uint8 * keyArray){
|
||||
@ -408,37 +610,54 @@ void DOUBLE_Constrain(double * variable, double min, double max){
|
||||
*variable = min;
|
||||
}
|
||||
|
||||
void PADDLE_Update(Paddle * obj, const Uint8 * keystate){
|
||||
bool leftKeyPressed = false, rightKeyPressed = false;
|
||||
int paddleXMid = (obj->TargetRect).x + ((obj->TargetRect).w / 2);
|
||||
int mouseX;
|
||||
void PADDLE_MoveSmooth(Paddle * obj){
|
||||
int mouseX, paddleXMid, halfPaddle = ((obj->TargetRect).w / 2);
|
||||
|
||||
SDL_GetMouseState(&mouseX, NULL);
|
||||
mouseX = (int)roundf((float)mouseX / XScale);
|
||||
paddleXMid = halfPaddle + (obj->TargetRect.x); // Current State
|
||||
(obj->TargetRect).x = paddleXMid - (int)roundf((float)(paddleXMid - mouseX) * PADDLE_SmoothFactor) - halfPaddle;
|
||||
}
|
||||
|
||||
void PADDLE_MoveAuto(Scenery * scenery){
|
||||
int paddleXMid, halfPaddle = (((scenery->paddle).TargetRect).w / 2);
|
||||
|
||||
paddleXMid = halfPaddle + ((scenery->paddle).TargetRect.x); // Current State
|
||||
((scenery->paddle).TargetRect).x = paddleXMid - (int)roundf((float)(paddleXMid - (((scenery->ball).Location).x + (rand() % 30) + ((scenery->ball).Size))) * 0.2f) - halfPaddle;
|
||||
}
|
||||
|
||||
void PADDLE_AdaptSpeedGradient(Paddle * obj, int FrameCount){
|
||||
if (FrameCount > PADDLE_AccelerationTime)
|
||||
return;
|
||||
(obj->TargetRect).w = PADDLE_MaxSize - (((double)FrameCount / (double)PADDLE_AccelerationTime) * (PADDLE_MaxSize - PADDLE_MinSize));
|
||||
}
|
||||
|
||||
void PADDLE_Update(Paddle * obj, Scenery * scenery, const Uint8 * keystate){
|
||||
PADDLE_AdaptSpeedGradient(obj, (scenery->Frames));
|
||||
bool leftKeyPressed, rightKeyPressed;
|
||||
|
||||
switch (obj->Mode) {
|
||||
case MouseControl:
|
||||
SDL_GetMouseState(&mouseX, NULL);
|
||||
mouseX = (int)roundf((float)mouseX / XScale);
|
||||
if (abs(mouseX - paddleXMid) > (obj->Speed)) {
|
||||
if (mouseX > paddleXMid)
|
||||
rightKeyPressed = true;
|
||||
else
|
||||
leftKeyPressed = true;
|
||||
}
|
||||
PADDLE_MoveSmooth(obj);
|
||||
break;
|
||||
case KeyboardControl:
|
||||
leftKeyPressed = KeyPressed(keystate, PADDLE_MoveLeftKeys);
|
||||
rightKeyPressed = KeyPressed(keystate, PADDLE_MoveRightKeys);
|
||||
|
||||
if (leftKeyPressed && (!rightKeyPressed)) {
|
||||
((obj->TargetRect).x) -= (obj->Speed);
|
||||
} else if ((!leftKeyPressed) && rightKeyPressed) {
|
||||
((obj->TargetRect).x) += (obj->Speed);
|
||||
}
|
||||
break;
|
||||
case Automatic:
|
||||
PADDLE_MoveAuto(scenery);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown Paddle Control Mode: %d!\n", obj->Mode);
|
||||
break;
|
||||
}
|
||||
|
||||
if (leftKeyPressed && (!rightKeyPressed)) {
|
||||
((obj->TargetRect).x) -= (obj->Speed);
|
||||
} else if ((!leftKeyPressed) && rightKeyPressed) {
|
||||
((obj->TargetRect).x) += (obj->Speed);
|
||||
}
|
||||
INT_Constrain(&((obj->TargetRect).x), 0, (BREAKOUT_BoxWidth - ((obj->TargetRect).w)));
|
||||
} /* switch */
|
||||
INT_Constrain(&((obj->TargetRect).x), 0, (width - ((obj->TargetRect).w)));
|
||||
} /* PADDLE_Update */
|
||||
|
||||
void PADDLE_DestroyObject(Paddle * obj){
|
||||
@ -489,14 +708,23 @@ void BLOCK_Initialize(SDL_Renderer * renderer){
|
||||
} else printf("Block is already initialized!\n");
|
||||
} /* PADDLE_Initialize */
|
||||
|
||||
Block BLOCK_CreateDefault() {
|
||||
Block BLOCK_CreateDefault(){
|
||||
return (Block) {
|
||||
.TargetRect = (SDL_Rect) {.x = 0, .y = 0, .w = 100, .h = 50 },
|
||||
.TextureIndex = (rand() % BLOCK_TextureCount),
|
||||
.HP = 1
|
||||
.HP = 1,
|
||||
.DestYValue = 0
|
||||
}; // Objekt für die Eigenschaften des Balls
|
||||
}
|
||||
|
||||
void BLOCK_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index){
|
||||
if (index > BLOCK_TextureCount || index < 0) {
|
||||
printf("Block with unkown texture index %d aus [0,...,%d]\n", index, (BLOCK_TextureCount - 1));
|
||||
return;
|
||||
}
|
||||
SDL_RenderCopy(renderer, BLOCK_Texture, BLOCK_SourceRects + index, dstRect);
|
||||
}
|
||||
|
||||
void BLOCK_Draw(SDL_Renderer * renderer, Block * obj){
|
||||
if ((obj->HP) > 0) {
|
||||
// printf("Block drawn at (%d|%d)!\n", (obj->TargetRect).x, (obj->TargetRect).y);
|
||||
@ -508,8 +736,12 @@ void BLOCK_DealDamage(Block * obj, int dmg){
|
||||
if (((obj->HP) -= dmg) <= 0) printf("Block was destroyed!\n");
|
||||
}
|
||||
|
||||
void BLOCK_MoveSmooth(Block * obj){
|
||||
((obj->TargetRect).y) -= (int)roundf((float)(((obj->TargetRect).y) - (obj->DestYValue)) * BLOCK_SmoothFactor);
|
||||
}
|
||||
|
||||
void BLOCK_Update(Block * obj){
|
||||
// Do nothing currently
|
||||
BLOCK_MoveSmooth(obj);
|
||||
}
|
||||
void BLOCK_DestroyObject(Block * obj){
|
||||
}
|
||||
|
35
breakout.h
@ -6,11 +6,13 @@
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
// Enums
|
||||
typedef enum controlModeEnum {KeyboardControl = 0, MouseControl = 1} ControlMode;
|
||||
typedef enum controlModeEnum {KeyboardControl = 0, MouseControl = 1, Automatic = 2} ControlMode;
|
||||
// End Enums
|
||||
|
||||
// Structs
|
||||
@ -32,55 +34,72 @@ typedef struct paddleStruct {
|
||||
|
||||
typedef struct blockStruct {
|
||||
SDL_Rect TargetRect;
|
||||
int TextureIndex, HP;
|
||||
int TextureIndex, HP, DestYValue;
|
||||
} Block; // Objekt für die Eigenschaften des Paddles
|
||||
|
||||
typedef struct sceneryStruct {
|
||||
Ball ball;
|
||||
Paddle paddle;
|
||||
Block * blocks;
|
||||
int BlockCount, Lives, StartCountdown;
|
||||
int BlockCount, Lives, StartCountdown, Frames, Score, DestroyedBlocks, TopLeftBlockColor, XBlocks, YBlocks;
|
||||
bool IsPaused, IsGameOver;
|
||||
} Scenery; // Objekt für die Objekte und Eigenschaften einer Szenerie
|
||||
// End Structs
|
||||
|
||||
// Prototypes
|
||||
void BREAKOUT_INITIALIZE(SDL_Renderer * renderer, int width, int height);
|
||||
void BREAKOUT_INITIALIZE(SDL_Renderer * renderer);
|
||||
void BREAKOUT_StartMusic();
|
||||
void BREAKOUT_PauseMusic();
|
||||
void BREAKOUT_TogglePause(Scenery * scenery);
|
||||
void BREAKOUT_KeyPressed(Scenery * scenery, SDL_KeyboardEvent * b);
|
||||
Scenery BREAKOUT_CreateDefault();
|
||||
void BREAKOUT_ChangeSize(int width, int height);
|
||||
void BREAKOUT_IncreaseScoreBy(Scenery * scenery, int scoreInc);
|
||||
void TEXTURE_RenderCenteredSpriteSheet(SDL_Renderer * renderer, SDL_Texture * texture, SDL_Rect * srcRect, float Scale);
|
||||
void TEXTURE_RenderCentered(SDL_Renderer * renderer, SDL_Texture * texture, float Scale);
|
||||
void BREAKOUT_PushNewRow(Scenery * scenery);
|
||||
void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate);
|
||||
void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer);
|
||||
void BREAKOUT_DrawLivesHUD(SDL_Renderer * renderer, Scenery * scenery);
|
||||
void BREAKOUT_DEINITIALIZE();
|
||||
void BREAKOUT_DestroyObject(Scenery * scenery);
|
||||
void BALL_Initialize(SDL_Renderer * renderer);
|
||||
Ball BALL_CreateDefault();
|
||||
void BALL_ResetPosition(Ball * obj);
|
||||
void BALL_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index);
|
||||
void BALL_Draw(SDL_Renderer * renderer, Ball * obj);
|
||||
bool BALL_CollideWithRect(Ball * obj, SDL_Rect * rect);
|
||||
bool RECT_Collide(SDL_Rect * rect1, SDL_Rect * rect2);
|
||||
void BALL_SteerMomentum(Ball * obj, Paddle * paddle);
|
||||
void RECT_SetTargetPos(SDL_Rect * rect, Vector * Location);
|
||||
SDL_Point BALL_GetCenter(Ball * obj);
|
||||
Vector BALL_GetCenter(Ball * obj);
|
||||
void BALL_CollideWithBorders(Ball * obj);
|
||||
void BALL_MoveAwayFromBoundaries(Ball * obj);
|
||||
bool BALL_CollideWithPaddle(Ball * obj, Paddle * paddle);
|
||||
void BALL_AdaptSpeedGradient(Ball * obj, int FrameCount);
|
||||
void BALL_PlayCollisionSound();
|
||||
void BALL_Update(Ball * obj, Scenery * scenery);
|
||||
void BALL_DestroyObject(Ball * obj);
|
||||
void BALL_Deinitialize();
|
||||
void PADDLE_Initialize(SDL_Renderer * renderer);
|
||||
Paddle PADDLE_CreateDefault();
|
||||
void PADDLE_ResetPosition(Paddle * obj);
|
||||
void PADDLE_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index);
|
||||
void PADDLE_Draw(SDL_Renderer * renderer, Paddle * obj);
|
||||
bool KeyPressed(const Uint8 * keystate, Uint8 * keyArray);
|
||||
void INT_Constrain(int * variable, int min, int max);
|
||||
void DOUBLE_Constrain(double * variable, double min, double max);
|
||||
void PADDLE_Update(Paddle * obj, const Uint8 * keystate);
|
||||
void PADDLE_MoveSmooth(Paddle * obj);
|
||||
void PADDLE_MoveAuto(Scenery * scenery);
|
||||
void PADDLE_AdaptSpeedGradient(Paddle * obj, int FrameCount);
|
||||
void PADDLE_Update(Paddle * obj, Scenery * scenery, const Uint8 * keystate);
|
||||
void PADDLE_DestroyObject(Paddle * obj);
|
||||
void PADDLE_Deinitialize();
|
||||
void BLOCK_Initialize(SDL_Renderer * renderer);
|
||||
Block BLOCK_CreateDefault() ;
|
||||
Block BLOCK_CreateDefault();
|
||||
void BLOCK_DrawTexture(SDL_Renderer * renderer, SDL_Rect * dstRect, int index);
|
||||
void BLOCK_Draw(SDL_Renderer * renderer, Block * obj);
|
||||
void BLOCK_DealDamage(Block * obj, int dmg);
|
||||
void BLOCK_MoveSmooth(Block * obj);
|
||||
void BLOCK_Update(Block * obj);
|
||||
void BLOCK_DestroyObject(Block * obj);
|
||||
void BLOCK_Deinitialize();
|
||||
|
88
font.c
@ -1,51 +1,25 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include "font.h"
|
||||
|
||||
#define FONT_FontFile1 "assets/fonts/monofur.ttf"
|
||||
#define FONT_FontFile2 "assets/fonts/ka1.ttf"
|
||||
#define FONT_FontFile3 "assets/fonts/minecraft.ttf"
|
||||
#define FONT_FontFile4 "assets/fonts/ae-bi.ttf"
|
||||
|
||||
extern int width, height;
|
||||
|
||||
int FONT_FontCount;
|
||||
SDL_Color FONT_FontColor;
|
||||
TTF_Font ** FONT_FontFamily;
|
||||
bool FONT_IsInit = false;
|
||||
TTF_Font * FONT_FontFamily = NULL;
|
||||
|
||||
void FONT_Initialize(){
|
||||
if (!FONT_IsInit) {
|
||||
printf("Initializing Font...\n");
|
||||
FONT_FontColor = (SDL_Color) {255, 255, 255 };
|
||||
FONT_FontCount = 4;
|
||||
FONT_FontFamily = (TTF_Font **)malloc(FONT_FontCount * sizeof(TTF_Font *));
|
||||
FONT_FontFamily[0] = TTF_OpenFont(FONT_FontFile1, 48);
|
||||
if (!FONT_FontFamily) printf("Font 1 could not initialize! Error: %s\n", TTF_GetError());
|
||||
else printf("Font 1 was successfully initialized!\n");
|
||||
FONT_PrintFontStyle(FONT_FontFamily[0]);
|
||||
FONT_FontFamily[1] = TTF_OpenFont(FONT_FontFile2, 48);
|
||||
if (!FONT_FontFamily) printf("Font 2 could not initialize! Error: %s\n", TTF_GetError());
|
||||
else printf("Font 2 was successfully initialized!\n");
|
||||
FONT_PrintFontStyle(FONT_FontFamily[1]);
|
||||
FONT_FontFamily[2] = TTF_OpenFont(FONT_FontFile3, 48);
|
||||
if (!FONT_FontFamily) printf("Font 3 could not initialize! Error: %s\n", TTF_GetError());
|
||||
else printf("Font 3 was successfully initialized!\n");
|
||||
FONT_PrintFontStyle(FONT_FontFamily[2]);
|
||||
FONT_FontFamily[3] = TTF_OpenFont(FONT_FontFile4, 48);
|
||||
if (!FONT_FontFamily) printf("Font 4 could not initialize! Error: %s\n", TTF_GetError());
|
||||
else printf("Font 4 was successfully initialized!\n");
|
||||
FONT_PrintFontStyle(FONT_FontFamily[3]);
|
||||
printf("Font initialized!\n");
|
||||
FONT_IsInit = true;
|
||||
} else printf("Font already initialized!\n");
|
||||
} /* FONT_Initialize */
|
||||
printf("Initializing Font...\n");
|
||||
FONT_FontColor = (SDL_Color) {255, 255, 255 };
|
||||
FONT_FontFamily = TTF_OpenFont(FONT_FontFile, 48);
|
||||
if (!FONT_FontFamily) printf("Font could not initialize! Error: %s\n", TTF_GetError());
|
||||
else printf("Font was successfully initialized!\n");
|
||||
FONT_PrintFontStyle(FONT_FontFamily);
|
||||
printf("Font initialized!\n");
|
||||
}
|
||||
|
||||
void FONT_PrintFontStyle(TTF_Font * ffont){
|
||||
int style;
|
||||
@ -68,51 +42,31 @@ void FONT_PrintFontStyle(TTF_Font * ffont){
|
||||
}
|
||||
|
||||
void FONT_Deinitialize(){
|
||||
if (FONT_IsInit) {
|
||||
printf("De-initializing Font...\n");
|
||||
for (int i = 0; i < FONT_FontCount; i++) {
|
||||
TTF_CloseFont(FONT_FontFamily[i]);
|
||||
}
|
||||
free(FONT_FontFamily);
|
||||
printf("Font de-initialized!\n");
|
||||
FONT_IsInit = false;
|
||||
} else printf("Font already de-initialized!\n");
|
||||
printf("De-initializing Font...\n");
|
||||
TTF_CloseFont(FONT_FontFamily);
|
||||
FONT_FontFamily = NULL; // to be safe...
|
||||
printf("Font de-initialized!\n");
|
||||
}
|
||||
|
||||
void FONT_RenderText(SDL_Renderer * renderer, char * text, SDL_Rect * dstRect, int index){
|
||||
void FONT_RenderText(SDL_Renderer * renderer, char * text, SDL_Rect * dstRect){
|
||||
SDL_Rect srcRect;
|
||||
|
||||
srcRect.x = 0;
|
||||
srcRect.y = 0;
|
||||
SDL_Texture * texture = FONT_GenerateTexture(renderer, text, &srcRect, index);
|
||||
SDL_Texture * texture = FONT_GenerateTexture(renderer, text, &srcRect);
|
||||
SDL_RenderCopy(renderer, texture, &srcRect, dstRect);
|
||||
SDL_DestroyTexture(texture);
|
||||
}
|
||||
|
||||
void FONT_RenderTextCentered(SDL_Renderer * renderer, char * text, float scale, int index){
|
||||
SDL_Rect srcRect, dstRect;
|
||||
|
||||
srcRect.x = 0;
|
||||
srcRect.y = 0;
|
||||
|
||||
SDL_Texture * texture = FONT_GenerateTexture(renderer, text, &srcRect, index);
|
||||
dstRect.w = (int)roundf((float)(srcRect.w) * scale);
|
||||
dstRect.h = (int)roundf((float)(srcRect.h) * scale);
|
||||
dstRect.x = (width - dstRect.w) / 2;
|
||||
dstRect.y = (height - dstRect.h) / 2;
|
||||
SDL_RenderCopy(renderer, texture, &srcRect, &dstRect);
|
||||
SDL_DestroyTexture(texture);
|
||||
}
|
||||
|
||||
SDL_Texture * FONT_GenerateTexture(SDL_Renderer * renderer, char * text, SDL_Rect * Message_rect, int index){
|
||||
SDL_Surface * tmpSurface = FONT_GenerateSurface(text, Message_rect, index);
|
||||
SDL_Texture * FONT_GenerateTexture(SDL_Renderer * renderer, char * text, SDL_Rect * Message_rect){
|
||||
SDL_Surface * tmpSurface = FONT_GenerateSurface(text, Message_rect);
|
||||
SDL_Texture * resultTexture = SDL_CreateTextureFromSurface(renderer, tmpSurface);
|
||||
|
||||
SDL_FreeSurface(tmpSurface);
|
||||
return resultTexture;
|
||||
} /* FONT_GenerateSurface */
|
||||
|
||||
SDL_Surface * FONT_GenerateSurface(char * text, SDL_Rect * Message_rect, int index){
|
||||
TTF_SizeText(FONT_FontFamily[index], text, &(Message_rect->w), &(Message_rect->h));
|
||||
return TTF_RenderText_Solid(FONT_FontFamily[index], text, FONT_FontColor);
|
||||
SDL_Surface * FONT_GenerateSurface(char * text, SDL_Rect * Message_rect){
|
||||
TTF_SizeText(FONT_FontFamily, text, &(Message_rect->w), &(Message_rect->h));
|
||||
return TTF_RenderText_Solid(FONT_FontFamily, text, FONT_FontColor);
|
||||
}
|
||||
|
14
font.h
@ -1,14 +1,20 @@
|
||||
#ifndef __font_h__
|
||||
#define __font_h__
|
||||
|
||||
#define FONT_FontFile "assets/fonts/monofur.ttf"
|
||||
|
||||
// Externs
|
||||
extern SDL_Color FONT_FontColor;
|
||||
extern TTF_Font * FONT_FontFamily;
|
||||
// End Externs
|
||||
|
||||
// Prototypes
|
||||
void FONT_Initialize();
|
||||
void FONT_PrintFontStyle(TTF_Font * ffont);
|
||||
void FONT_Deinitialize();
|
||||
void FONT_RenderText(SDL_Renderer * renderer, char * text, SDL_Rect * dstRect, int index);
|
||||
void FONT_RenderTextCentered(SDL_Renderer * renderer, char * text, float scale, int index);
|
||||
SDL_Texture * FONT_GenerateTexture(SDL_Renderer * renderer, char * text, SDL_Rect * Message_rect, int index);
|
||||
SDL_Surface * FONT_GenerateSurface(char * text, SDL_Rect * Message_rect, int index);
|
||||
void FONT_RenderText(SDL_Renderer * renderer, char * text, SDL_Rect * dstRect);
|
||||
SDL_Texture * FONT_GenerateTexture(SDL_Renderer * renderer, char * text, SDL_Rect * Message_rect);
|
||||
SDL_Surface * FONT_GenerateSurface(char * text, SDL_Rect * Message_rect);
|
||||
// End Prototypes
|
||||
|
||||
#endif // __font_h__
|
||||
|
233
gameover.c
Normal file
@ -0,0 +1,233 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include "gameover.h"
|
||||
#include "gamestate.h"
|
||||
#include "breakout.h"
|
||||
#include "vector.h"
|
||||
#include "highscores.h"
|
||||
#include "background.h"
|
||||
#include "startmenu.h"
|
||||
#include "main.h"
|
||||
|
||||
#define GAMEOVER_TexturePath "assets/images/gameover.png"
|
||||
#define GAMEOVER_NumbersTexturePath "assets/images/numbers.png"
|
||||
#define GAMEOVER_ScoreTexturePath "assets/images/yourscore.png"
|
||||
#define GAMEOVER_UploadTexturePath "assets/images/upload.png"
|
||||
#define GAMEOVER_RestartTexturePath "assets/images/restart_button.png"
|
||||
#define GAMEOVER_HUDScale 16.0f
|
||||
#define GAMEOVER_Scale 4.0f
|
||||
|
||||
extern char * Username;
|
||||
extern char * Password;
|
||||
extern bool LoggedIn;
|
||||
|
||||
extern int width, height;
|
||||
|
||||
extern SDL_Texture * HIGHSCORESBUTTON_Texture;
|
||||
extern SDL_Texture * QUITBUTTON_Texture;
|
||||
extern SDL_Rect QUITBUTTON_Rect;
|
||||
|
||||
int GAMEOVER_HUDMargin = 5;
|
||||
SDL_Texture * GAMEOVER_Texture;
|
||||
SDL_Texture * GAMEOVER_Numbers;
|
||||
SDL_Texture * GAMEOVER_ScoreTexture;
|
||||
SDL_Texture * GAMEOVER_UploadTexture;
|
||||
SDL_Texture * GAMEOVER_RestartTexture;
|
||||
SDL_Rect * GAMEOVER_NumberRects;
|
||||
SDL_Rect * GAMEOVER_UploadRects;
|
||||
SDL_Rect GAMEOVER_TargetRect;
|
||||
SDL_Rect GAMEOVER_ScoreTargetRect;
|
||||
SDL_Rect GAMEOVER_HUDScoreTargetRect;
|
||||
SDL_Rect * GAMEOVER_UploadTargetRects;
|
||||
SDL_Rect GAMEOVER_HighscoresButtonRect;
|
||||
SDL_Rect GAMEOVER_RestartButtonRect;
|
||||
int * GAMEOVER_Digits;
|
||||
bool GAMEOVER_IsInit = false;
|
||||
UploadState GAMEOVER_UploadState = Initial;
|
||||
|
||||
void GAMEOVER_Initialize(SDL_Renderer * renderer){
|
||||
if (!GAMEOVER_IsInit) {
|
||||
printf("Initializing Gameover...\n");
|
||||
GAMEOVER_UploadState = Initial;
|
||||
GAMEOVER_Texture = IMG_LoadTexture(renderer, GAMEOVER_TexturePath);
|
||||
if (!GAMEOVER_Texture) printf("Gameover Texture couldn't be loaded!\n");
|
||||
GAMEOVER_Numbers = IMG_LoadTexture(renderer, GAMEOVER_NumbersTexturePath);
|
||||
if (!GAMEOVER_Numbers) printf("Gameover Numbers couldn't be loaded!\n");
|
||||
GAMEOVER_ScoreTexture = IMG_LoadTexture(renderer, GAMEOVER_ScoreTexturePath);
|
||||
if (!GAMEOVER_ScoreTexture) printf("Gameover Score Texture couldn't be loaded!\n");
|
||||
GAMEOVER_UploadTexture = IMG_LoadTexture(renderer, GAMEOVER_UploadTexturePath);
|
||||
if (!GAMEOVER_UploadTexture) printf("Gameover Score Texture couldn't be loaded!\n");
|
||||
GAMEOVER_RestartTexture = IMG_LoadTexture(renderer, GAMEOVER_RestartTexturePath);
|
||||
if (!GAMEOVER_RestartTexture) printf("Restart Button Texture couldn't be loaded!\n");
|
||||
int w, h;
|
||||
SDL_QueryTexture(GAMEOVER_Texture, NULL, NULL, &w, &h);
|
||||
w /= 2;
|
||||
h /= 2;
|
||||
GAMEOVER_TargetRect.x = ((1920 - w) / 2);
|
||||
GAMEOVER_TargetRect.y = 50;
|
||||
GAMEOVER_TargetRect.w = w;
|
||||
GAMEOVER_TargetRect.h = h;
|
||||
GAMEOVER_NumberRects = calloc(10, sizeof(SDL_Rect));
|
||||
if (!GAMEOVER_NumberRects) printf("FATAL: Memory Allocation Failed!\n");
|
||||
GAMEOVER_NumberRects[0] = (SDL_Rect) {.x = 446, .y = 668, .w = 442, .h = 665 };
|
||||
GAMEOVER_NumberRects[1] = (SDL_Rect) {.x = 1299, .y = 1335, .w = 242, .h = 665 };
|
||||
GAMEOVER_NumberRects[2] = (SDL_Rect) {.x = 1, .y = 1, .w = 443, .h = 665 };
|
||||
GAMEOVER_NumberRects[3] = (SDL_Rect) {.x = 1, .y = 668, .w = 443, .h = 665 };
|
||||
GAMEOVER_NumberRects[4] = (SDL_Rect) {.x = 1, .y = 1335, .w = 443, .h = 665 };
|
||||
GAMEOVER_NumberRects[5] = (SDL_Rect) {.x = 446, .y = 1, .w = 443, .h = 665 };
|
||||
GAMEOVER_NumberRects[6] = (SDL_Rect) {.x = 891, .y = 1, .w = 443, .h = 665 };
|
||||
GAMEOVER_NumberRects[7] = (SDL_Rect) {.x = 890, .y = 1335, .w = 407, .h = 665 };
|
||||
GAMEOVER_NumberRects[8] = (SDL_Rect) {.x = 446, .y = 1335, .w = 442, .h = 665 };
|
||||
GAMEOVER_NumberRects[9] = (SDL_Rect) {.x = 890, .y = 668, .w = 442, .h = 665 };
|
||||
GAMEOVER_ScoreTargetRect.x = 0;
|
||||
GAMEOVER_ScoreTargetRect.y = 450;
|
||||
GAMEOVER_ScoreTargetRect.h = 183;
|
||||
GAMEOVER_ScoreTargetRect.w = 1000;
|
||||
GAMEOVER_UploadRects = malloc(4 * sizeof(SDL_Rect));
|
||||
if (!GAMEOVER_UploadRects) printf("FATAL: Memory Allocation Failed!\n");
|
||||
GAMEOVER_UploadRects[0] = (SDL_Rect) {.x = 1, .y = 1, .w = 4634, .h = 732 };
|
||||
GAMEOVER_UploadRects[1] = (SDL_Rect) {.x = 1, .y = 735, .w = 3981, .h = 734 };
|
||||
GAMEOVER_UploadRects[2] = (SDL_Rect) {.x = 1, .y = 1471, .w = 3024, .h = 666 };
|
||||
GAMEOVER_UploadRects[3] = (SDL_Rect) {.x = 3027, .y = 1471, .w = 2391, .h = 666 };
|
||||
GAMEOVER_UploadTargetRects = malloc(4 * sizeof(SDL_Rect));
|
||||
if (!GAMEOVER_UploadTargetRects) printf("FATAL: Memory Allocation Failed!\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
GAMEOVER_UploadTargetRects[i] = (SDL_Rect) {.x = 0, .y = 650, .w = ((GAMEOVER_UploadRects[i].w) / 5), .h = ((GAMEOVER_UploadRects[i].h) / 5) };
|
||||
GAMEOVER_UploadTargetRects[i].x = ((width - (GAMEOVER_UploadTargetRects[i].w)) / 2);
|
||||
}
|
||||
GAMEOVER_HUDScoreTargetRect = (SDL_Rect) {.x = GAMEOVER_HUDMargin, .y = GAMEOVER_HUDMargin, .w = 250, .h = 46 };
|
||||
GAMEOVER_Digits = malloc(25 * sizeof(int)); // Holds every digit of unsigned long long int
|
||||
GAMEOVER_HighscoresButtonRect = (SDL_Rect) {.x = 1635, .y = 896, .w = 235, .h = 134 };
|
||||
GAMEOVER_RestartButtonRect = (SDL_Rect) {.x = 842, .y = 896, .w = 235, .h = 134 };
|
||||
printf("Gameover initialized!\n");
|
||||
GAMEOVER_IsInit = true;
|
||||
} else
|
||||
printf("Gameover already initialized!\n");
|
||||
} /* GAMEOVER_Initialize */
|
||||
|
||||
void GAMEOVER_MouseClicked(SDL_MouseButtonEvent b, Scenery * scenery){
|
||||
if (b.button == SDL_BUTTON_LEFT) {
|
||||
if (LoggedIn) {
|
||||
if (GAMEOVER_UploadState == Initial || GAMEOVER_UploadState == Failed) {
|
||||
if (clickInRect(b, (GAMEOVER_UploadTargetRects + GAMEOVER_UploadState))) {
|
||||
GAMEOVER_UploadState = Uploading;
|
||||
printf("Upload was called from gameover!\n");
|
||||
if (HIGHSCORES_UploadScore(Username, (scenery->Score))) {
|
||||
GAMEOVER_UploadState = Finished;
|
||||
} else {
|
||||
GAMEOVER_UploadState = Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clickInRect(b, &QUITBUTTON_Rect)) {
|
||||
printf("Escape was called from gameover!\n");
|
||||
GAME_Escape();
|
||||
} else if (clickInRect(b, &GAMEOVER_HighscoresButtonRect)) {
|
||||
printf("Highscores was called from gameover!\n");
|
||||
GAME_ChangeState(Highscores);
|
||||
} else if (clickInRect(b, &GAMEOVER_RestartButtonRect)) {
|
||||
printf("Restart was called from gameover!\n");
|
||||
GAME_Restart();
|
||||
GAME_ChangeState(Game);
|
||||
}
|
||||
}
|
||||
} /* GAMEOVER_MouseClicked */
|
||||
|
||||
void GAMEOVER_Draw(SDL_Renderer * renderer, Scenery * scenery){
|
||||
int i, count;
|
||||
|
||||
SDL_RenderCopy(renderer, GAMEOVER_Texture, NULL, &GAMEOVER_TargetRect);
|
||||
GAMEOVER_GetDigits((scenery->Score), &count);
|
||||
int totalWidth = GAMEOVER_ScoreTargetRect.w;
|
||||
for (i = (count - 1); i >= 0; i--) {
|
||||
totalWidth += (int)roundf((float)GAMEOVER_NumberRects[i].w / GAMEOVER_Scale);
|
||||
}
|
||||
GAMEOVER_ScoreTargetRect.x = ((1920 - totalWidth) / 2);
|
||||
SDL_RenderCopy(renderer, GAMEOVER_ScoreTexture, NULL, &GAMEOVER_ScoreTargetRect);
|
||||
int xOffset = GAMEOVER_ScoreTargetRect.x + GAMEOVER_ScoreTargetRect.w;
|
||||
SDL_Rect target;
|
||||
target.y = 450;
|
||||
for (i = (count - 1); i >= 0; i--) {
|
||||
target.x = xOffset;
|
||||
target.h = (int)roundf((float)(GAMEOVER_NumberRects[GAMEOVER_Digits[i]].h) / GAMEOVER_Scale);
|
||||
target.w = (int)roundf((float)(GAMEOVER_NumberRects[GAMEOVER_Digits[i]].w) / GAMEOVER_Scale);
|
||||
SDL_RenderCopy(renderer, GAMEOVER_Numbers, (GAMEOVER_NumberRects + GAMEOVER_Digits[i]), &target);
|
||||
xOffset += target.w - 1;
|
||||
}
|
||||
if (LoggedIn) {
|
||||
SDL_RenderCopy(renderer, GAMEOVER_UploadTexture, (GAMEOVER_UploadRects + GAMEOVER_UploadState), (GAMEOVER_UploadTargetRects + GAMEOVER_UploadState));
|
||||
}
|
||||
SDL_RenderCopy(renderer, QUITBUTTON_Texture, NULL, &QUITBUTTON_Rect);
|
||||
SDL_RenderCopy(renderer, HIGHSCORESBUTTON_Texture, NULL, &GAMEOVER_HighscoresButtonRect);
|
||||
SDL_RenderCopy(renderer, GAMEOVER_RestartTexture, NULL, &GAMEOVER_RestartButtonRect);
|
||||
} /* GAMEOVER_Draw */
|
||||
|
||||
void GAMEOVER_DrawHorizontalCenter(SDL_Renderer * renderer, SDL_Texture * texture, SDL_Rect * srcRect, SDL_Rect * dstRect){
|
||||
SDL_Rect target = *dstRect;
|
||||
|
||||
target.x = ((width - target.w) / 2);
|
||||
SDL_RenderCopy(renderer, texture, srcRect, &target);
|
||||
}
|
||||
|
||||
void GAMEOVER_GetDigits(int input, int * digitCount){
|
||||
int score = input;
|
||||
int count = 0;
|
||||
|
||||
while (score != 0) {
|
||||
GAMEOVER_Digits[(count++)] = (score % 10);
|
||||
score /= 10;
|
||||
}
|
||||
if (count == 0) {
|
||||
count = 1;
|
||||
GAMEOVER_Digits[0] = 0;
|
||||
}
|
||||
*digitCount = count;
|
||||
}
|
||||
|
||||
void SCORE_DrawHUD(SDL_Renderer * renderer, Scenery * scenery){
|
||||
int i, count;
|
||||
|
||||
GAMEOVER_GetDigits((scenery->Score), &count);
|
||||
int totalWidth = GAMEOVER_HUDScoreTargetRect.w;
|
||||
for (i = (count - 1); i >= 0; i--) {
|
||||
totalWidth += (int)roundf((float)GAMEOVER_NumberRects[i].w / GAMEOVER_HUDScale);
|
||||
}
|
||||
GAMEOVER_HUDScoreTargetRect.x = GAMEOVER_HUDMargin;
|
||||
SDL_RenderCopy(renderer, GAMEOVER_ScoreTexture, NULL, &GAMEOVER_HUDScoreTargetRect);
|
||||
int xOffset = GAMEOVER_HUDScoreTargetRect.x + GAMEOVER_HUDScoreTargetRect.w;
|
||||
SDL_Rect target;
|
||||
target.y = GAMEOVER_HUDMargin;
|
||||
for (i = (count - 1); i >= 0; i--) {
|
||||
target.x = xOffset;
|
||||
target.h = (int)roundf((float)(GAMEOVER_NumberRects[GAMEOVER_Digits[i]].h) / GAMEOVER_HUDScale);
|
||||
target.w = (int)roundf((float)(GAMEOVER_NumberRects[GAMEOVER_Digits[i]].w) / GAMEOVER_HUDScale);
|
||||
SDL_RenderCopy(renderer, GAMEOVER_Numbers, (GAMEOVER_NumberRects + GAMEOVER_Digits[i]), &target);
|
||||
xOffset += target.w - 1;
|
||||
}
|
||||
} /* SCORE_DrawHUD */
|
||||
|
||||
void GAMEOVER_Deinitialize(){
|
||||
if (GAMEOVER_IsInit) {
|
||||
printf("De-initializing Gameover...\n");
|
||||
free(GAMEOVER_Digits);
|
||||
free(GAMEOVER_NumberRects);
|
||||
free(GAMEOVER_UploadRects);
|
||||
free(GAMEOVER_UploadTargetRects);
|
||||
SDL_DestroyTexture(GAMEOVER_RestartTexture);
|
||||
SDL_DestroyTexture(GAMEOVER_Texture);
|
||||
SDL_DestroyTexture(GAMEOVER_ScoreTexture);
|
||||
SDL_DestroyTexture(GAMEOVER_Numbers);
|
||||
SDL_DestroyTexture(GAMEOVER_UploadTexture);
|
||||
printf("Gameover de-initialized!\n");
|
||||
GAMEOVER_IsInit = false;
|
||||
} else
|
||||
printf("Gameover already de-initialized!\n");
|
||||
}
|
31
gameover.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef __gameover_h__
|
||||
#define __gameover_h__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include "gameover.h"
|
||||
#include "gamestate.h"
|
||||
#include "main.h"
|
||||
|
||||
// Enums
|
||||
typedef enum uploadStateEnum { Initial = 0, Uploading = 1, Finished = 2, Failed = 3 } UploadState;
|
||||
// Enums
|
||||
|
||||
// Prototypes
|
||||
void GAMEOVER_Initialize(SDL_Renderer * renderer);
|
||||
void GAMEOVER_MouseClicked(SDL_MouseButtonEvent b, Scenery * scenery);
|
||||
void GAMEOVER_Draw(SDL_Renderer * renderer, Scenery * scenery);
|
||||
void GAMEOVER_DrawHorizontalCenter(SDL_Renderer * renderer, SDL_Texture * texture, SDL_Rect * srcRect, SDL_Rect * dstRect);
|
||||
void GAMEOVER_GetDigits(int input, int * digitCount);
|
||||
void SCORE_DrawHUD(SDL_Renderer * renderer, Scenery * scenery);
|
||||
void GAMEOVER_Deinitialize();
|
||||
// End Prototypes
|
||||
|
||||
#endif // __gameover_h__
|
@ -1,6 +1,6 @@
|
||||
#ifndef __gamestate_h__
|
||||
#define __gamestate_h__
|
||||
|
||||
typedef enum gameStateEnum { MainMenu = 1, Game = 2, LevelSelect = 3, SkinSelect = 4, Settings = 5, Highscores = 6 } GameState;
|
||||
typedef enum gameStateEnum { MainMenu = 1, Game = 2, LevelSelect = 3, SkinSelect = 4, Settings = 5, Highscores = 6 , GameOver = 7 } GameState;
|
||||
|
||||
#endif
|
||||
|
187
highscores.c
@ -7,61 +7,100 @@
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include "highscores.h"
|
||||
#include "font.h"
|
||||
#include "main.h"
|
||||
|
||||
#define HIGHSCORES_FontFile "assets/fonts/monofur.ttf"
|
||||
#define HIGHSCORES_FontFile "assets/fonts/monofur.ttf"
|
||||
#define HIGHSCORES_OutputFilePath "output.txt"
|
||||
|
||||
extern SDL_Texture * Return_Button_Texture;
|
||||
|
||||
int HIGHSCORES_EntriesGot = 0;
|
||||
User * HIGHSCORES_UserList;
|
||||
SDL_Color HIGHSCORES_FontColor;
|
||||
SDL_Texture * HIGHSCORES_TableTexture;
|
||||
SDL_Rect HIGHSCORES_TotalRect;
|
||||
bool HIGHSCORES_IsInit = false;
|
||||
TTF_Font * HIGHSCORES_FontFamily = NULL;
|
||||
SDL_Surface * tempSurface;
|
||||
SDL_Rect HIGHSCORES_ReturnButtonRect;
|
||||
|
||||
void HIGHSCORES_Initialize(){
|
||||
if (!HIGHSCORES_IsInit) {
|
||||
printf("Initializing Highscores...\n");
|
||||
FONT_Initialize();
|
||||
HIGHSCORES_UserList = malloc(10 * sizeof(User));
|
||||
HIGHSCORES_TotalRect = (SDL_Rect) {.x = 0, .y = 0, .w = 1920, .h = 1080 };
|
||||
printf("Highscores initialized!\n");
|
||||
HIGHSCORES_IsInit = true;
|
||||
} else printf("Highscores already initialized!\n");
|
||||
printf("Initializing Highscores...\n");
|
||||
HIGHSCORES_FontColor = (SDL_Color) {255, 255, 255 };
|
||||
HIGHSCORES_UserList = malloc(10 * sizeof(User));
|
||||
HIGHSCORES_FontFamily = TTF_OpenFont(HIGHSCORES_FontFile, 48);
|
||||
if (!HIGHSCORES_FontFamily) printf("Font could not initialize! Error: %s\n", TTF_GetError());
|
||||
else {
|
||||
printf("Font was successfully initialized!\n");
|
||||
printFontStyle(HIGHSCORES_FontFamily);
|
||||
}
|
||||
HIGHSCORES_TotalRect = (SDL_Rect) {.x = 0, .y = 0, .w = 1920, .h = 1080 };
|
||||
HIGHSCORES_ReturnButtonRect = (SDL_Rect) {.x = 10, .y = 970, .w = 100, .h = 100 };
|
||||
printf("Highscores initialized!\n");
|
||||
}
|
||||
|
||||
void printFontStyle(TTF_Font * ffont){
|
||||
int style;
|
||||
|
||||
style = TTF_GetFontStyle(ffont);
|
||||
printf("The font style is:");
|
||||
if (style == TTF_STYLE_NORMAL)
|
||||
printf(" normal");
|
||||
else {
|
||||
if (style & TTF_STYLE_BOLD)
|
||||
printf(" bold");
|
||||
if (style & TTF_STYLE_ITALIC)
|
||||
printf(" italic");
|
||||
if (style & TTF_STYLE_UNDERLINE)
|
||||
printf(" underline");
|
||||
if (style & TTF_STYLE_STRIKETHROUGH)
|
||||
printf(" strikethrough");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void HIGHSCORES_MouseClicked(SDL_MouseButtonEvent b){
|
||||
if (b.button == SDL_BUTTON_LEFT) {
|
||||
if (clickInRect(b, &HIGHSCORES_ReturnButtonRect)) {
|
||||
GAME_ReturnToLastScreen();
|
||||
}
|
||||
}
|
||||
} /* GAMEOVER_MouseClicked */
|
||||
|
||||
void HIGHSCORES_Draw(SDL_Renderer * renderer){
|
||||
SDL_RenderCopy(renderer, HIGHSCORES_TableTexture, &HIGHSCORES_TotalRect, &HIGHSCORES_TotalRect);
|
||||
SDL_RenderCopy(renderer, Return_Button_Texture, NULL, &HIGHSCORES_ReturnButtonRect);
|
||||
} /* HIGHSCORES_Draw */
|
||||
|
||||
void HIGHSCORES_Deinitialize(){
|
||||
if (HIGHSCORES_IsInit) {
|
||||
printf("De-initializing Highscores...\n");
|
||||
FONT_Deinitialize();
|
||||
SDL_DestroyTexture(HIGHSCORES_TableTexture);
|
||||
free(HIGHSCORES_UserList);
|
||||
printf("Highscores de-initialized!\n");
|
||||
HIGHSCORES_IsInit = false;
|
||||
} else printf("Highscores already de-initialized!\n");
|
||||
printf("De-initializing Highscores...\n");
|
||||
TTF_CloseFont(HIGHSCORES_FontFamily);
|
||||
SDL_DestroyTexture(HIGHSCORES_TableTexture);
|
||||
SDL_FreeSurface(tempSurface);
|
||||
free(HIGHSCORES_UserList);
|
||||
printf("Highscores de-initialized!\n");
|
||||
}
|
||||
|
||||
void HIGHSCORES_GenerateTexture(SDL_Renderer * renderer){
|
||||
char * buffer = calloc(100, sizeof(char));
|
||||
int count = 0;
|
||||
char format[25] = "| %-4d | %-52s | %-10s |";
|
||||
char format[20] = "| %-54s | %-14s |";
|
||||
SDL_Rect Message_rect;
|
||||
SDL_Surface * HIGHSCORES_TableSurface = SDL_CreateRGBSurface(0, 1920, 1080, 32, 0, 0, 0, 0);
|
||||
|
||||
if (!HIGHSCORES_TableSurface) {
|
||||
printf("Surface wasn't created!\n");
|
||||
}
|
||||
sprintf(buffer, "| Rank | Username | Score |");
|
||||
SDL_Surface * tempSurface = FONT_GenerateSurface(buffer, &Message_rect, 0);
|
||||
Message_rect.x = 50;
|
||||
sprintf(buffer, format, "Username", "Score");
|
||||
HIGHSCORES_DrawText(buffer, &Message_rect);
|
||||
Message_rect.y = 70;
|
||||
Message_rect.x = 50;
|
||||
Message_rect.h = 50;
|
||||
Message_rect.w = 50;
|
||||
SDL_BlitSurface(tempSurface, NULL, HIGHSCORES_TableSurface, &Message_rect);
|
||||
SDL_FreeSurface(tempSurface);
|
||||
while (count < HIGHSCORES_EntriesGot) {
|
||||
sprintf(buffer, format, (count + 1), HIGHSCORES_UserList[count].Username, HIGHSCORES_UserList[count].Score);
|
||||
tempSurface = FONT_GenerateSurface(buffer, &Message_rect, 0);
|
||||
sprintf(buffer, format, HIGHSCORES_UserList[count].Username, HIGHSCORES_UserList[count].Score);
|
||||
HIGHSCORES_DrawText(buffer, &Message_rect);
|
||||
Message_rect.y = ((Message_rect.h + 15) * (count + 1)) + 140;
|
||||
Message_rect.x = 50;
|
||||
SDL_BlitSurface(tempSurface, NULL, HIGHSCORES_TableSurface, &Message_rect);
|
||||
@ -75,10 +114,100 @@ void HIGHSCORES_GenerateTexture(SDL_Renderer * renderer){
|
||||
SDL_FreeSurface(HIGHSCORES_TableSurface);
|
||||
} /* HIGHSCORES_GenerateSurface */
|
||||
|
||||
void HIGHSCORES_DrawText(char * text, SDL_Rect * Message_rect){
|
||||
TTF_SizeText(HIGHSCORES_FontFamily, text, &(Message_rect->w), &(Message_rect->h));
|
||||
tempSurface = TTF_RenderText_Solid(HIGHSCORES_FontFamily, text, HIGHSCORES_FontColor);
|
||||
}
|
||||
|
||||
bool HIGHSCORES_UploadScore(char * username, int score){
|
||||
char buffer[200];
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
sprintf(buffer, "bhi upload %s %s %d", HIGHSCORES_OutputFilePath, username, score);
|
||||
// printf("BHI called with \"%s\"\n", buffer);
|
||||
// printf("Call BHI interface:\n");
|
||||
system(buffer);
|
||||
// printf("BHI interface quit!\nBHI output handling...\n");
|
||||
FILE * fp = fopen(HIGHSCORES_OutputFilePath, "r");
|
||||
if (fp == NULL) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
if ((read = getline(&line, &len, fp)) != -1)
|
||||
if (line[0] == '0') {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
} /* HIGHSCORES_UploadScore */
|
||||
|
||||
bool HIGHSCORES_Login(char * username, char * password){
|
||||
char buffer[200];
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
sprintf(buffer, "bhi login %s %s %s", HIGHSCORES_OutputFilePath, username, password);
|
||||
// printf("BHI called with \"%s\"\n", buffer);
|
||||
printf("Logging in...\n");
|
||||
system(buffer);
|
||||
// printf("BHI interface quit!\nBHI output handling...\n");
|
||||
FILE * fp = fopen(HIGHSCORES_OutputFilePath, "r");
|
||||
if (fp == NULL) {
|
||||
fclose(fp);
|
||||
printf("Login failed: Output file \"%s\" not found!\n", HIGHSCORES_OutputFilePath);
|
||||
return false;
|
||||
}
|
||||
if ((read = getline(&line, &len, fp)) != -1) {
|
||||
if (line[0] == '0') {
|
||||
// if ((read = getline(&line, &len, fp)) != -1) {
|
||||
// printf("Error: %s\n", line);
|
||||
// }
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
} /* HIGHSCORES_Login */
|
||||
|
||||
bool HIGHSCORES_Register(char * username, char * password){
|
||||
char buffer[200];
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
sprintf(buffer, "bhi register %s %s %s", HIGHSCORES_OutputFilePath, username, password);
|
||||
// printf("BHI called with \"%s\"\n", buffer);
|
||||
printf("Registering...\n");
|
||||
system(buffer);
|
||||
// printf("BHI interface quit!\nBHI output handling...\n");
|
||||
FILE * fp = fopen(HIGHSCORES_OutputFilePath, "r");
|
||||
if (fp == NULL) {
|
||||
fclose(fp);
|
||||
printf("Registration failed: Output file \"%s\" not found!\n", HIGHSCORES_OutputFilePath);
|
||||
return false;
|
||||
}
|
||||
if ((read = getline(&line, &len, fp)) != -1) {
|
||||
if (line[0] == '0') {
|
||||
if ((read = getline(&line, &len, fp)) != -1) {
|
||||
printf("Error: %s\n", line);
|
||||
}
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
} /* HIGHSCORES_Login */
|
||||
|
||||
void HIGHSCORES_ReloadList(){
|
||||
printf("Call BHI interface:\n");
|
||||
system("bhi top output.txt");
|
||||
printf("BHI interface quit!\nBHI output handling...\n");
|
||||
// printf("BHI interface quit!\nBHI output handling...\n");
|
||||
|
||||
HIGHSCORES_EntriesGot = 0;
|
||||
FILE * fp;
|
||||
@ -90,10 +219,12 @@ void HIGHSCORES_ReloadList(){
|
||||
bool switchread = false;
|
||||
HIGHSCORES_UserList = malloc(10 * sizeof(User));
|
||||
fp = fopen("output.txt", "r");
|
||||
if (fp == NULL)
|
||||
if (fp == NULL) {
|
||||
printf("Reload failed: Output file \"%s\" not found!\n", HIGHSCORES_OutputFilePath);
|
||||
return;
|
||||
}
|
||||
if ((read = getline(&line, &len, fp)) != -1)
|
||||
if (line[0] == 0)
|
||||
if (line[0] == '0')
|
||||
return;
|
||||
int counter = 0;
|
||||
while ((read = getline(&line, &len, fp)) != -1) {
|
||||
|
@ -10,10 +10,14 @@ typedef struct userStruct {
|
||||
// Prototypes
|
||||
void HIGHSCORES_Initialize();
|
||||
void printFontStyle(TTF_Font * ffont);
|
||||
void HIGHSCORES_MouseClicked(SDL_MouseButtonEvent b);
|
||||
void HIGHSCORES_Draw(SDL_Renderer * renderer);
|
||||
void HIGHSCORES_Deinitialize();
|
||||
void HIGHSCORES_GenerateTexture(SDL_Renderer * renderer);
|
||||
void HIGHSCORES_DrawText(char * text, SDL_Rect * Message_rect);
|
||||
bool HIGHSCORES_UploadScore(char * username, int score);
|
||||
bool HIGHSCORES_Login(char * username, char * password);
|
||||
bool HIGHSCORES_Register(char * username, char * password);
|
||||
void HIGHSCORES_ReloadList();
|
||||
// End Prototypes
|
||||
|
||||
|
649
include/SDL2/SDL_mixer.h
Normal file
@ -0,0 +1,649 @@
|
||||
/*
|
||||
SDL_mixer: An audio mixer library based on the SDL library
|
||||
Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_MIXER_H_
|
||||
#define SDL_MIXER_H_
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_rwops.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_version.h"
|
||||
#include "begin_code.h"
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
|
||||
*/
|
||||
#define SDL_MIXER_MAJOR_VERSION 2
|
||||
#define SDL_MIXER_MINOR_VERSION 0
|
||||
#define SDL_MIXER_PATCHLEVEL 2
|
||||
|
||||
/* This macro can be used to fill a version structure with the compile-time
|
||||
* version of the SDL_mixer library.
|
||||
*/
|
||||
#define SDL_MIXER_VERSION(X) \
|
||||
{ \
|
||||
(X)->major = SDL_MIXER_MAJOR_VERSION; \
|
||||
(X)->minor = SDL_MIXER_MINOR_VERSION; \
|
||||
(X)->patch = SDL_MIXER_PATCHLEVEL; \
|
||||
}
|
||||
|
||||
/* Backwards compatibility */
|
||||
#define MIX_MAJOR_VERSION SDL_MIXER_MAJOR_VERSION
|
||||
#define MIX_MINOR_VERSION SDL_MIXER_MINOR_VERSION
|
||||
#define MIX_PATCHLEVEL SDL_MIXER_PATCHLEVEL
|
||||
#define MIX_VERSION(X) SDL_MIXER_VERSION(X)
|
||||
|
||||
/**
|
||||
* This is the version number macro for the current SDL_mixer version.
|
||||
*/
|
||||
#define SDL_MIXER_COMPILEDVERSION \
|
||||
SDL_VERSIONNUM(SDL_MIXER_MAJOR_VERSION, SDL_MIXER_MINOR_VERSION, SDL_MIXER_PATCHLEVEL)
|
||||
|
||||
/**
|
||||
* This macro will evaluate to true if compiled with SDL_mixer at least X.Y.Z.
|
||||
*/
|
||||
#define SDL_MIXER_VERSION_ATLEAST(X, Y, Z) \
|
||||
(SDL_MIXER_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z))
|
||||
|
||||
/* This function gets the version of the dynamically linked SDL_mixer library.
|
||||
it should NOT be used to fill a version structure, instead you should
|
||||
use the SDL_MIXER_VERSION() macro.
|
||||
*/
|
||||
extern DECLSPEC const SDL_version * SDLCALL Mix_Linked_Version(void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MIX_INIT_FLAC = 0x00000001,
|
||||
MIX_INIT_MOD = 0x00000002,
|
||||
MIX_INIT_MP3 = 0x00000008,
|
||||
MIX_INIT_OGG = 0x00000010,
|
||||
MIX_INIT_MID = 0x00000020
|
||||
} MIX_InitFlags;
|
||||
|
||||
/* Loads dynamic libraries and prepares them for use. Flags should be
|
||||
one or more flags from MIX_InitFlags OR'd together.
|
||||
It returns the flags successfully initialized, or 0 on failure.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_Init(int flags);
|
||||
|
||||
/* Unloads libraries loaded with Mix_Init */
|
||||
extern DECLSPEC void SDLCALL Mix_Quit(void);
|
||||
|
||||
|
||||
/* The default mixer has 8 simultaneous mixing channels */
|
||||
#ifndef MIX_CHANNELS
|
||||
#define MIX_CHANNELS 8
|
||||
#endif
|
||||
|
||||
/* Good default values for a PC soundcard */
|
||||
#define MIX_DEFAULT_FREQUENCY 22050
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
#define MIX_DEFAULT_FORMAT AUDIO_S16LSB
|
||||
#else
|
||||
#define MIX_DEFAULT_FORMAT AUDIO_S16MSB
|
||||
#endif
|
||||
#define MIX_DEFAULT_CHANNELS 2
|
||||
#define MIX_MAX_VOLUME SDL_MIX_MAXVOLUME /* Volume of a chunk */
|
||||
|
||||
/* The internal format for an audio chunk */
|
||||
typedef struct Mix_Chunk {
|
||||
int allocated;
|
||||
Uint8 *abuf;
|
||||
Uint32 alen;
|
||||
Uint8 volume; /* Per-sample volume, 0-128 */
|
||||
} Mix_Chunk;
|
||||
|
||||
/* The different fading types supported */
|
||||
typedef enum {
|
||||
MIX_NO_FADING,
|
||||
MIX_FADING_OUT,
|
||||
MIX_FADING_IN
|
||||
} Mix_Fading;
|
||||
|
||||
/* These are types of music files (not libraries used to load them) */
|
||||
typedef enum {
|
||||
MUS_NONE,
|
||||
MUS_CMD,
|
||||
MUS_WAV,
|
||||
MUS_MOD,
|
||||
MUS_MID,
|
||||
MUS_OGG,
|
||||
MUS_MP3,
|
||||
MUS_MP3_MAD_UNUSED,
|
||||
MUS_FLAC,
|
||||
MUS_MODPLUG_UNUSED
|
||||
} Mix_MusicType;
|
||||
|
||||
/* The internal format for a music chunk interpreted via mikmod */
|
||||
typedef struct _Mix_Music Mix_Music;
|
||||
|
||||
/* Open the mixer with a certain audio format */
|
||||
extern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels, int chunksize);
|
||||
|
||||
/* Open the mixer with specific device and certain audio format */
|
||||
extern DECLSPEC int SDLCALL Mix_OpenAudioDevice(int frequency, Uint16 format, int channels, int chunksize, const char* device, int allowed_changes);
|
||||
|
||||
/* Dynamically change the number of channels managed by the mixer.
|
||||
If decreasing the number of channels, the upper channels are
|
||||
stopped.
|
||||
This function returns the new number of allocated channels.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_AllocateChannels(int numchans);
|
||||
|
||||
/* Find out what the actual audio device parameters are.
|
||||
This function returns 1 if the audio has been opened, 0 otherwise.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_QuerySpec(int *frequency,Uint16 *format,int *channels);
|
||||
|
||||
/* Load a wave file or a music (.mod .s3m .it .xm) file */
|
||||
extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, int freesrc);
|
||||
#define Mix_LoadWAV(file) Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1)
|
||||
extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file);
|
||||
|
||||
/* Load a music file from an SDL_RWop object (Ogg and MikMod specific currently)
|
||||
Matt Campbell (matt@campbellhome.dhs.org) April 2000 */
|
||||
extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_RW(SDL_RWops *src, int freesrc);
|
||||
|
||||
/* Load a music file from an SDL_RWop object assuming a specific format */
|
||||
extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW(SDL_RWops *src, Mix_MusicType type, int freesrc);
|
||||
|
||||
/* Load a wave file of the mixer format from a memory buffer */
|
||||
extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_WAV(Uint8 *mem);
|
||||
|
||||
/* Load raw audio data of the mixer format from a memory buffer */
|
||||
extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len);
|
||||
|
||||
/* Free an audio chunk previously loaded */
|
||||
extern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk);
|
||||
extern DECLSPEC void SDLCALL Mix_FreeMusic(Mix_Music *music);
|
||||
|
||||
/* Get a list of chunk/music decoders that this build of SDL_mixer provides.
|
||||
This list can change between builds AND runs of the program, if external
|
||||
libraries that add functionality become available.
|
||||
You must successfully call Mix_OpenAudio() before calling these functions.
|
||||
This API is only available in SDL_mixer 1.2.9 and later.
|
||||
|
||||
// usage...
|
||||
int i;
|
||||
const int total = Mix_GetNumChunkDecoders();
|
||||
for (i = 0; i < total; i++)
|
||||
printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i));
|
||||
|
||||
Appearing in this list doesn't promise your specific audio file will
|
||||
decode...but it's handy to know if you have, say, a functioning Timidity
|
||||
install.
|
||||
|
||||
These return values are static, read-only data; do not modify or free it.
|
||||
The pointers remain valid until you call Mix_CloseAudio().
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_GetNumChunkDecoders(void);
|
||||
extern DECLSPEC const char * SDLCALL Mix_GetChunkDecoder(int index);
|
||||
extern DECLSPEC SDL_bool SDLCALL Mix_HasChunkDecoder(const char *name);
|
||||
extern DECLSPEC int SDLCALL Mix_GetNumMusicDecoders(void);
|
||||
extern DECLSPEC const char * SDLCALL Mix_GetMusicDecoder(int index);
|
||||
extern DECLSPEC SDL_bool SDLCALL Mix_HasMusicDecoder(const char *name);
|
||||
|
||||
/* Find out the music format of a mixer music, or the currently playing
|
||||
music, if 'music' is NULL.
|
||||
*/
|
||||
extern DECLSPEC Mix_MusicType SDLCALL Mix_GetMusicType(const Mix_Music *music);
|
||||
|
||||
/* Set a function that is called after all mixing is performed.
|
||||
This can be used to provide real-time visual display of the audio stream
|
||||
or add a custom mixer filter for the stream data.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL Mix_SetPostMix(void (SDLCALL *mix_func)(void *udata, Uint8 *stream, int len), void *arg);
|
||||
|
||||
/* Add your own music player or additional mixer function.
|
||||
If 'mix_func' is NULL, the default music player is re-enabled.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL Mix_HookMusic(void (SDLCALL *mix_func)(void *udata, Uint8 *stream, int len), void *arg);
|
||||
|
||||
/* Add your own callback for when the music has finished playing or when it is
|
||||
* stopped from a call to Mix_HaltMusic.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL Mix_HookMusicFinished(void (SDLCALL *music_finished)(void));
|
||||
|
||||
/* Get a pointer to the user data for the current music hook */
|
||||
extern DECLSPEC void * SDLCALL Mix_GetMusicHookData(void);
|
||||
|
||||
/*
|
||||
* Add your own callback when a channel has finished playing. NULL
|
||||
* to disable callback. The callback may be called from the mixer's audio
|
||||
* callback or it could be called as a result of Mix_HaltChannel(), etc.
|
||||
* do not call SDL_LockAudio() from this callback; you will either be
|
||||
* inside the audio callback, or SDL_mixer will explicitly lock the audio
|
||||
* before calling your callback.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL Mix_ChannelFinished(void (SDLCALL *channel_finished)(int channel));
|
||||
|
||||
|
||||
/* Special Effects API by ryan c. gordon. (icculus@icculus.org) */
|
||||
|
||||
#define MIX_CHANNEL_POST -2
|
||||
|
||||
/* This is the format of a special effect callback:
|
||||
*
|
||||
* myeffect(int chan, void *stream, int len, void *udata);
|
||||
*
|
||||
* (chan) is the channel number that your effect is affecting. (stream) is
|
||||
* the buffer of data to work upon. (len) is the size of (stream), and
|
||||
* (udata) is a user-defined bit of data, which you pass as the last arg of
|
||||
* Mix_RegisterEffect(), and is passed back unmolested to your callback.
|
||||
* Your effect changes the contents of (stream) based on whatever parameters
|
||||
* are significant, or just leaves it be, if you prefer. You can do whatever
|
||||
* you like to the buffer, though, and it will continue in its changed state
|
||||
* down the mixing pipeline, through any other effect functions, then finally
|
||||
* to be mixed with the rest of the channels and music for the final output
|
||||
* stream.
|
||||
*
|
||||
* DO NOT EVER call SDL_LockAudio() from your callback function!
|
||||
*/
|
||||
typedef void (SDLCALL *Mix_EffectFunc_t)(int chan, void *stream, int len, void *udata);
|
||||
|
||||
/*
|
||||
* This is a callback that signifies that a channel has finished all its
|
||||
* loops and has completed playback. This gets called if the buffer
|
||||
* plays out normally, or if you call Mix_HaltChannel(), implicitly stop
|
||||
* a channel via Mix_AllocateChannels(), or unregister a callback while
|
||||
* it's still playing.
|
||||
*
|
||||
* DO NOT EVER call SDL_LockAudio() from your callback function!
|
||||
*/
|
||||
typedef void (SDLCALL *Mix_EffectDone_t)(int chan, void *udata);
|
||||
|
||||
|
||||
/* Register a special effect function. At mixing time, the channel data is
|
||||
* copied into a buffer and passed through each registered effect function.
|
||||
* After it passes through all the functions, it is mixed into the final
|
||||
* output stream. The copy to buffer is performed once, then each effect
|
||||
* function performs on the output of the previous effect. Understand that
|
||||
* this extra copy to a buffer is not performed if there are no effects
|
||||
* registered for a given chunk, which saves CPU cycles, and any given
|
||||
* effect will be extra cycles, too, so it is crucial that your code run
|
||||
* fast. Also note that the data that your function is given is in the
|
||||
* format of the sound device, and not the format you gave to Mix_OpenAudio(),
|
||||
* although they may in reality be the same. This is an unfortunate but
|
||||
* necessary speed concern. Use Mix_QuerySpec() to determine if you can
|
||||
* handle the data before you register your effect, and take appropriate
|
||||
* actions.
|
||||
* You may also specify a callback (Mix_EffectDone_t) that is called when
|
||||
* the channel finishes playing. This gives you a more fine-grained control
|
||||
* than Mix_ChannelFinished(), in case you need to free effect-specific
|
||||
* resources, etc. If you don't need this, you can specify NULL.
|
||||
* You may set the callbacks before or after calling Mix_PlayChannel().
|
||||
* Things like Mix_SetPanning() are just internal special effect functions,
|
||||
* so if you are using that, you've already incurred the overhead of a copy
|
||||
* to a separate buffer, and that these effects will be in the queue with
|
||||
* any functions you've registered. The list of registered effects for a
|
||||
* channel is reset when a chunk finishes playing, so you need to explicitly
|
||||
* set them with each call to Mix_PlayChannel*().
|
||||
* You may also register a special effect function that is to be run after
|
||||
* final mixing occurs. The rules for these callbacks are identical to those
|
||||
* in Mix_RegisterEffect, but they are run after all the channels and the
|
||||
* music have been mixed into a single stream, whereas channel-specific
|
||||
* effects run on a given channel before any other mixing occurs. These
|
||||
* global effect callbacks are call "posteffects". Posteffects only have
|
||||
* their Mix_EffectDone_t function called when they are unregistered (since
|
||||
* the main output stream is never "done" in the same sense as a channel).
|
||||
* You must unregister them manually when you've had enough. Your callback
|
||||
* will be told that the channel being mixed is (MIX_CHANNEL_POST) if the
|
||||
* processing is considered a posteffect.
|
||||
*
|
||||
* After all these effects have finished processing, the callback registered
|
||||
* through Mix_SetPostMix() runs, and then the stream goes to the audio
|
||||
* device.
|
||||
*
|
||||
* DO NOT EVER call SDL_LockAudio() from your callback function!
|
||||
*
|
||||
* returns zero if error (no such channel), nonzero if added.
|
||||
* Error messages can be retrieved from Mix_GetError().
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, Mix_EffectDone_t d, void *arg);
|
||||
|
||||
|
||||
/* You may not need to call this explicitly, unless you need to stop an
|
||||
* effect from processing in the middle of a chunk's playback.
|
||||
* Posteffects are never implicitly unregistered as they are for channels,
|
||||
* but they may be explicitly unregistered through this function by
|
||||
* specifying MIX_CHANNEL_POST for a channel.
|
||||
* returns zero if error (no such channel or effect), nonzero if removed.
|
||||
* Error messages can be retrieved from Mix_GetError().
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f);
|
||||
|
||||
|
||||
/* You may not need to call this explicitly, unless you need to stop all
|
||||
* effects from processing in the middle of a chunk's playback. Note that
|
||||
* this will also shut off some internal effect processing, since
|
||||
* Mix_SetPanning() and others may use this API under the hood. This is
|
||||
* called internally when a channel completes playback.
|
||||
* Posteffects are never implicitly unregistered as they are for channels,
|
||||
* but they may be explicitly unregistered through this function by
|
||||
* specifying MIX_CHANNEL_POST for a channel.
|
||||
* returns zero if error (no such channel), nonzero if all effects removed.
|
||||
* Error messages can be retrieved from Mix_GetError().
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_UnregisterAllEffects(int channel);
|
||||
|
||||
|
||||
#define MIX_EFFECTSMAXSPEED "MIX_EFFECTSMAXSPEED"
|
||||
|
||||
/*
|
||||
* These are the internally-defined mixing effects. They use the same API that
|
||||
* effects defined in the application use, but are provided here as a
|
||||
* convenience. Some effects can reduce their quality or use more memory in
|
||||
* the name of speed; to enable this, make sure the environment variable
|
||||
* MIX_EFFECTSMAXSPEED (see above) is defined before you call
|
||||
* Mix_OpenAudio().
|
||||
*/
|
||||
|
||||
|
||||
/* Set the panning of a channel. The left and right channels are specified
|
||||
* as integers between 0 and 255, quietest to loudest, respectively.
|
||||
*
|
||||
* Technically, this is just individual volume control for a sample with
|
||||
* two (stereo) channels, so it can be used for more than just panning.
|
||||
* If you want real panning, call it like this:
|
||||
*
|
||||
* Mix_SetPanning(channel, left, 255 - left);
|
||||
*
|
||||
* ...which isn't so hard.
|
||||
*
|
||||
* Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
|
||||
* the panning will be done to the final mixed stream before passing it on
|
||||
* to the audio device.
|
||||
*
|
||||
* This uses the Mix_RegisterEffect() API internally, and returns without
|
||||
* registering the effect function if the audio device is not configured
|
||||
* for stereo output. Setting both (left) and (right) to 255 causes this
|
||||
* effect to be unregistered, since that is the data's normal state.
|
||||
*
|
||||
* returns zero if error (no such channel or Mix_RegisterEffect() fails),
|
||||
* nonzero if panning effect enabled. Note that an audio device in mono
|
||||
* mode is a no-op, but this call will return successful in that case.
|
||||
* Error messages can be retrieved from Mix_GetError().
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_SetPanning(int channel, Uint8 left, Uint8 right);
|
||||
|
||||
|
||||
/* Set the position of a channel. (angle) is an integer from 0 to 360, that
|
||||
* specifies the location of the sound in relation to the listener. (angle)
|
||||
* will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260).
|
||||
* Angle 0 is due north, and rotates clockwise as the value increases.
|
||||
* For efficiency, the precision of this effect may be limited (angles 1
|
||||
* through 7 might all produce the same effect, 8 through 15 are equal, etc).
|
||||
* (distance) is an integer between 0 and 255 that specifies the space
|
||||
* between the sound and the listener. The larger the number, the further
|
||||
* away the sound is. Using 255 does not guarantee that the channel will be
|
||||
* culled from the mixing process or be completely silent. For efficiency,
|
||||
* the precision of this effect may be limited (distance 0 through 5 might
|
||||
* all produce the same effect, 6 through 10 are equal, etc). Setting (angle)
|
||||
* and (distance) to 0 unregisters this effect, since the data would be
|
||||
* unchanged.
|
||||
*
|
||||
* If you need more precise positional audio, consider using OpenAL for
|
||||
* spatialized effects instead of SDL_mixer. This is only meant to be a
|
||||
* basic effect for simple "3D" games.
|
||||
*
|
||||
* If the audio device is configured for mono output, then you won't get
|
||||
* any effectiveness from the angle; however, distance attenuation on the
|
||||
* channel will still occur. While this effect will function with stereo
|
||||
* voices, it makes more sense to use voices with only one channel of sound,
|
||||
* so when they are mixed through this effect, the positioning will sound
|
||||
* correct. You can convert them to mono through SDL before giving them to
|
||||
* the mixer in the first place if you like.
|
||||
*
|
||||
* Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
|
||||
* the positioning will be done to the final mixed stream before passing it
|
||||
* on to the audio device.
|
||||
*
|
||||
* This is a convenience wrapper over Mix_SetDistance() and Mix_SetPanning().
|
||||
*
|
||||
* returns zero if error (no such channel or Mix_RegisterEffect() fails),
|
||||
* nonzero if position effect is enabled.
|
||||
* Error messages can be retrieved from Mix_GetError().
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_SetPosition(int channel, Sint16 angle, Uint8 distance);
|
||||
|
||||
|
||||
/* Set the "distance" of a channel. (distance) is an integer from 0 to 255
|
||||
* that specifies the location of the sound in relation to the listener.
|
||||
* Distance 0 is overlapping the listener, and 255 is as far away as possible
|
||||
* A distance of 255 does not guarantee silence; in such a case, you might
|
||||
* want to try changing the chunk's volume, or just cull the sample from the
|
||||
* mixing process with Mix_HaltChannel().
|
||||
* For efficiency, the precision of this effect may be limited (distances 1
|
||||
* through 7 might all produce the same effect, 8 through 15 are equal, etc).
|
||||
* (distance) is an integer between 0 and 255 that specifies the space
|
||||
* between the sound and the listener. The larger the number, the further
|
||||
* away the sound is.
|
||||
* Setting (distance) to 0 unregisters this effect, since the data would be
|
||||
* unchanged.
|
||||
* If you need more precise positional audio, consider using OpenAL for
|
||||
* spatialized effects instead of SDL_mixer. This is only meant to be a
|
||||
* basic effect for simple "3D" games.
|
||||
*
|
||||
* Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
|
||||
* the distance attenuation will be done to the final mixed stream before
|
||||
* passing it on to the audio device.
|
||||
*
|
||||
* This uses the Mix_RegisterEffect() API internally.
|
||||
*
|
||||
* returns zero if error (no such channel or Mix_RegisterEffect() fails),
|
||||
* nonzero if position effect is enabled.
|
||||
* Error messages can be retrieved from Mix_GetError().
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_SetDistance(int channel, Uint8 distance);
|
||||
|
||||
|
||||
/*
|
||||
* !!! FIXME : Haven't implemented, since the effect goes past the
|
||||
* end of the sound buffer. Will have to think about this.
|
||||
* --ryan.
|
||||
*/
|
||||
#if 0
|
||||
/* Causes an echo effect to be mixed into a sound. (echo) is the amount
|
||||
* of echo to mix. 0 is no echo, 255 is infinite (and probably not
|
||||
* what you want).
|
||||
*
|
||||
* Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
|
||||
* the reverbing will be done to the final mixed stream before passing it on
|
||||
* to the audio device.
|
||||
*
|
||||
* This uses the Mix_RegisterEffect() API internally. If you specify an echo
|
||||
* of zero, the effect is unregistered, as the data is already in that state.
|
||||
*
|
||||
* returns zero if error (no such channel or Mix_RegisterEffect() fails),
|
||||
* nonzero if reversing effect is enabled.
|
||||
* Error messages can be retrieved from Mix_GetError().
|
||||
*/
|
||||
extern no_parse_DECLSPEC int SDLCALL Mix_SetReverb(int channel, Uint8 echo);
|
||||
#endif
|
||||
|
||||
/* Causes a channel to reverse its stereo. This is handy if the user has his
|
||||
* speakers hooked up backwards, or you would like to have a minor bit of
|
||||
* psychedelia in your sound code. :) Calling this function with (flip)
|
||||
* set to non-zero reverses the chunks's usual channels. If (flip) is zero,
|
||||
* the effect is unregistered.
|
||||
*
|
||||
* This uses the Mix_RegisterEffect() API internally, and thus is probably
|
||||
* more CPU intensive than having the user just plug in his speakers
|
||||
* correctly. Mix_SetReverseStereo() returns without registering the effect
|
||||
* function if the audio device is not configured for stereo output.
|
||||
*
|
||||
* If you specify MIX_CHANNEL_POST for (channel), then this the effect is used
|
||||
* on the final mixed stream before sending it on to the audio device (a
|
||||
* posteffect).
|
||||
*
|
||||
* returns zero if error (no such channel or Mix_RegisterEffect() fails),
|
||||
* nonzero if reversing effect is enabled. Note that an audio device in mono
|
||||
* mode is a no-op, but this call will return successful in that case.
|
||||
* Error messages can be retrieved from Mix_GetError().
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_SetReverseStereo(int channel, int flip);
|
||||
|
||||
/* end of effects API. --ryan. */
|
||||
|
||||
|
||||
/* Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate
|
||||
them dynamically to the next sample if requested with a -1 value below.
|
||||
Returns the number of reserved channels.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_ReserveChannels(int num);
|
||||
|
||||
/* Channel grouping functions */
|
||||
|
||||
/* Attach a tag to a channel. A tag can be assigned to several mixer
|
||||
channels, to form groups of channels.
|
||||
If 'tag' is -1, the tag is removed (actually -1 is the tag used to
|
||||
represent the group of all the channels).
|
||||
Returns true if everything was OK.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_GroupChannel(int which, int tag);
|
||||
/* Assign several consecutive channels to a group */
|
||||
extern DECLSPEC int SDLCALL Mix_GroupChannels(int from, int to, int tag);
|
||||
/* Finds the first available channel in a group of channels,
|
||||
returning -1 if none are available.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_GroupAvailable(int tag);
|
||||
/* Returns the number of channels in a group. This is also a subtle
|
||||
way to get the total number of channels when 'tag' is -1
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_GroupCount(int tag);
|
||||
/* Finds the "oldest" sample playing in a group of channels */
|
||||
extern DECLSPEC int SDLCALL Mix_GroupOldest(int tag);
|
||||
/* Finds the "most recent" (i.e. last) sample playing in a group of channels */
|
||||
extern DECLSPEC int SDLCALL Mix_GroupNewer(int tag);
|
||||
|
||||
/* Play an audio chunk on a specific channel.
|
||||
If the specified channel is -1, play on the first free channel.
|
||||
If 'loops' is greater than zero, loop the sound that many times.
|
||||
If 'loops' is -1, loop inifinitely (~65000 times).
|
||||
Returns which channel was used to play the sound.
|
||||
*/
|
||||
#define Mix_PlayChannel(channel,chunk,loops) Mix_PlayChannelTimed(channel,chunk,loops,-1)
|
||||
/* The same as above, but the sound is played at most 'ticks' milliseconds */
|
||||
extern DECLSPEC int SDLCALL Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ticks);
|
||||
extern DECLSPEC int SDLCALL Mix_PlayMusic(Mix_Music *music, int loops);
|
||||
|
||||
/* Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions */
|
||||
extern DECLSPEC int SDLCALL Mix_FadeInMusic(Mix_Music *music, int loops, int ms);
|
||||
extern DECLSPEC int SDLCALL Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position);
|
||||
#define Mix_FadeInChannel(channel,chunk,loops,ms) Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1)
|
||||
extern DECLSPEC int SDLCALL Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ms, int ticks);
|
||||
|
||||
/* Set the volume in the range of 0-128 of a specific channel or chunk.
|
||||
If the specified channel is -1, set volume for all channels.
|
||||
Returns the original volume.
|
||||
If the specified volume is -1, just return the current volume.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_Volume(int channel, int volume);
|
||||
extern DECLSPEC int SDLCALL Mix_VolumeChunk(Mix_Chunk *chunk, int volume);
|
||||
extern DECLSPEC int SDLCALL Mix_VolumeMusic(int volume);
|
||||
|
||||
/* Halt playing of a particular channel */
|
||||
extern DECLSPEC int SDLCALL Mix_HaltChannel(int channel);
|
||||
extern DECLSPEC int SDLCALL Mix_HaltGroup(int tag);
|
||||
extern DECLSPEC int SDLCALL Mix_HaltMusic(void);
|
||||
|
||||
/* Change the expiration delay for a particular channel.
|
||||
The sample will stop playing after the 'ticks' milliseconds have elapsed,
|
||||
or remove the expiration if 'ticks' is -1
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_ExpireChannel(int channel, int ticks);
|
||||
|
||||
/* Halt a channel, fading it out progressively till it's silent
|
||||
The ms parameter indicates the number of milliseconds the fading
|
||||
will take.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_FadeOutChannel(int which, int ms);
|
||||
extern DECLSPEC int SDLCALL Mix_FadeOutGroup(int tag, int ms);
|
||||
extern DECLSPEC int SDLCALL Mix_FadeOutMusic(int ms);
|
||||
|
||||
/* Query the fading status of a channel */
|
||||
extern DECLSPEC Mix_Fading SDLCALL Mix_FadingMusic(void);
|
||||
extern DECLSPEC Mix_Fading SDLCALL Mix_FadingChannel(int which);
|
||||
|
||||
/* Pause/Resume a particular channel */
|
||||
extern DECLSPEC void SDLCALL Mix_Pause(int channel);
|
||||
extern DECLSPEC void SDLCALL Mix_Resume(int channel);
|
||||
extern DECLSPEC int SDLCALL Mix_Paused(int channel);
|
||||
|
||||
/* Pause/Resume the music stream */
|
||||
extern DECLSPEC void SDLCALL Mix_PauseMusic(void);
|
||||
extern DECLSPEC void SDLCALL Mix_ResumeMusic(void);
|
||||
extern DECLSPEC void SDLCALL Mix_RewindMusic(void);
|
||||
extern DECLSPEC int SDLCALL Mix_PausedMusic(void);
|
||||
|
||||
/* Set the current position in the music stream.
|
||||
This returns 0 if successful, or -1 if it failed or isn't implemented.
|
||||
This function is only implemented for MOD music formats (set pattern
|
||||
order number) and for OGG, FLAC, MP3_MAD, MP3_MPG and MODPLUG music
|
||||
(set position in seconds), at the moment.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_SetMusicPosition(double position);
|
||||
|
||||
/* Check the status of a specific channel.
|
||||
If the specified channel is -1, check all channels.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL Mix_Playing(int channel);
|
||||
extern DECLSPEC int SDLCALL Mix_PlayingMusic(void);
|
||||
|
||||
/* Stop music and set external music playback command */
|
||||
extern DECLSPEC int SDLCALL Mix_SetMusicCMD(const char *command);
|
||||
|
||||
/* Synchro value is set by MikMod from modules while playing */
|
||||
extern DECLSPEC int SDLCALL Mix_SetSynchroValue(int value);
|
||||
extern DECLSPEC int SDLCALL Mix_GetSynchroValue(void);
|
||||
|
||||
/* Set/Get/Iterate SoundFonts paths to use by supported MIDI backends */
|
||||
extern DECLSPEC int SDLCALL Mix_SetSoundFonts(const char *paths);
|
||||
extern DECLSPEC const char* SDLCALL Mix_GetSoundFonts(void);
|
||||
extern DECLSPEC int SDLCALL Mix_EachSoundFont(int (SDLCALL *function)(const char*, void*), void *data);
|
||||
|
||||
/* Get the Mix_Chunk currently associated with a mixer channel
|
||||
Returns NULL if it's an invalid channel, or there's no chunk associated.
|
||||
*/
|
||||
extern DECLSPEC Mix_Chunk * SDLCALL Mix_GetChunk(int channel);
|
||||
|
||||
/* Close the mixer, halting all playing audio */
|
||||
extern DECLSPEC void SDLCALL Mix_CloseAudio(void);
|
||||
|
||||
/* We'll use SDL for reporting errors */
|
||||
#define Mix_SetError SDL_SetError
|
||||
#define Mix_GetError SDL_GetError
|
||||
#define Mix_ClearError SDL_ClearError
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include "close_code.h"
|
||||
|
||||
#endif /* SDL_MIXER_H_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
BIN
lib/libSDL2_mixer.a
Normal file
BIN
lib/libSDL2_mixer.dll.a
Normal file
41
lib/libSDL2_mixer.la
Normal file
@ -0,0 +1,41 @@
|
||||
# libSDL2_mixer.la - a libtool library file
|
||||
# Generated by ltmain.sh (GNU libtool) 2.2.6
|
||||
#
|
||||
# Please DO NOT delete this file!
|
||||
# It is necessary for linking the library.
|
||||
|
||||
# The name that we can dlopen(3).
|
||||
dlname='../bin/SDL2_mixer.dll'
|
||||
|
||||
# Names of this library.
|
||||
library_names='libSDL2_mixer.dll.a'
|
||||
|
||||
# The name of the static archive.
|
||||
old_library='libSDL2_mixer.a'
|
||||
|
||||
# Linker flags that can not go in dependency_libs.
|
||||
inherited_linker_flags=''
|
||||
|
||||
# Libraries that this one depends upon.
|
||||
dependency_libs=' -L/usr/local/i686-w64-mingw32/lib -lmingw32 /usr/local/i686-w64-mingw32/lib/libSDL2.la -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lwinmm'
|
||||
|
||||
# Names of additional weak libraries provided by this library
|
||||
weak_library_names=''
|
||||
|
||||
# Version information for libSDL2_mixer.
|
||||
current=2
|
||||
age=2
|
||||
revision=0
|
||||
|
||||
# Is this an already installed library?
|
||||
installed=yes
|
||||
|
||||
# Should we warn about portability when linking against -modules?
|
||||
shouldnotlink=no
|
||||
|
||||
# Files to dlopen/dlpreopen
|
||||
dlopen=''
|
||||
dlpreopen=''
|
||||
|
||||
# Directory that this library needs to be installed in:
|
||||
libdir='/Users/slouken/release/SDL_mixer/SDL2_mixer-2.0.2/i686-w64-mingw32/lib'
|
12
lib/pkgconfig/SDL2_mixer.pc
Normal file
@ -0,0 +1,12 @@
|
||||
prefix=/usr/local/i686-w64-mingw32
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: SDL2_mixer
|
||||
Description: mixer library for Simple DirectMedia Layer
|
||||
Version: 2.0.2
|
||||
Requires: sdl2 >= 2.0.7
|
||||
Libs: -L${libdir} -lSDL2_mixer
|
||||
Cflags: -I${includedir}/SDL2
|
||||
|
261
main.c
@ -2,19 +2,25 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
|
||||
#include "breakout.h"
|
||||
#include "vector.h"
|
||||
#include "startmenu.h"
|
||||
#include "gamestate.h"
|
||||
#include "highscores.h"
|
||||
#include "gameover.h"
|
||||
#include "settings.h"
|
||||
#include "background.h"
|
||||
#include "font.h"
|
||||
|
||||
#define MAIN_MenuMusicPath "assets/sounds/menu_music.wav"
|
||||
#define MAIN_AccountSaveFilePath "account.cfg"
|
||||
#define MAIN_FadeTime 1000
|
||||
|
||||
#include "main.h"
|
||||
|
||||
@ -29,16 +35,22 @@ const Uint8 * keystate; // TODO: export all this into scenery and enemy waves
|
||||
SDL_Window * window;
|
||||
SDL_Renderer * renderer;
|
||||
SDL_Event event;
|
||||
bool running = true, fullscreen = false;
|
||||
bool running = true, fullscreen = false, LoggedIn = false;
|
||||
GameState gameState = MainMenu;
|
||||
GameState previousGameState = MainMenu;
|
||||
Scenery scenery;
|
||||
Mix_Music * MenuLoop;
|
||||
char * Username;
|
||||
char * Password;
|
||||
|
||||
int main(int argc, char * args[]){
|
||||
AttemptLogin();
|
||||
INITIALIZE();
|
||||
Uint32 fps_lasttime = SDL_GetTicks(); // the last recorded time.
|
||||
Uint32 fps_current; // the current FPS.
|
||||
Uint32 fps_frames = 0; // frames passed since the last recorded fps.
|
||||
|
||||
INITIALIZE();
|
||||
GAME_ChangeState(MainMenu);
|
||||
while (running) { // Gameloop
|
||||
HandleSDLEvents();
|
||||
DrawBackground(renderer);
|
||||
@ -56,12 +68,15 @@ int main(int argc, char * args[]){
|
||||
HIGHSCORES_Draw(renderer);
|
||||
break;
|
||||
case Settings:
|
||||
Settings_Draw(renderer);
|
||||
Settings_Draw(renderer, &scenery);
|
||||
break;
|
||||
case GameOver:
|
||||
GAMEOVER_Draw(renderer, &scenery);
|
||||
break;
|
||||
default:
|
||||
printf("Unknow state was updated: %d\n", gameState);
|
||||
break;
|
||||
}
|
||||
} /* switch */
|
||||
SDL_RenderPresent(renderer);
|
||||
fps_frames++;
|
||||
if (fps_lasttime < SDL_GetTicks() - 1000) {
|
||||
@ -75,18 +90,170 @@ int main(int argc, char * args[]){
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
bool PushNewCredentialsToSaveFile(const char * filename){
|
||||
FILE * file;
|
||||
|
||||
if (file = fopen(filename, "w")) {
|
||||
fprintf(file, "%s\n%s", Username, Password);
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GrabAccountFromSaveFile(const char * filename){
|
||||
FILE * file;
|
||||
|
||||
if (file = fopen(filename, "r")) {
|
||||
bool success = true;
|
||||
success = (fscanf(file, "%s\n%s", Username, Password) > 0);
|
||||
if (success) printf("Account save file found \"%s\"!\nAttempting automatic login for user \"%s\"...\n", MAIN_AccountSaveFilePath, Username);
|
||||
else printf("Account save file \"%s\" is invalid!\n", MAIN_AccountSaveFilePath);
|
||||
fclose(file);
|
||||
return success;
|
||||
}
|
||||
return false;
|
||||
} /* GrabAccountFromSaveFile */
|
||||
|
||||
void GAME_ReadCredentials(){
|
||||
printf("Input your username: ");
|
||||
gets(Username);
|
||||
printf("Input your password: ");
|
||||
gets(Password);
|
||||
}
|
||||
|
||||
bool GAME_Login(){
|
||||
printf("Login:\n");
|
||||
bool loginSuccess = HIGHSCORES_Login(Username, Password);
|
||||
if (loginSuccess) {
|
||||
printf("Successfully logged in as %s!\n", Username);
|
||||
LoggedIn = true;
|
||||
} else
|
||||
printf("Login failed!\n");
|
||||
return loginSuccess;
|
||||
}
|
||||
|
||||
bool GAME_Register(){
|
||||
printf("Register:\n");
|
||||
bool loginSuccess = HIGHSCORES_Register(Username, Password);
|
||||
if (loginSuccess) {
|
||||
printf("Successfully registered new account: %s!\n", Username);
|
||||
LoggedIn = true;
|
||||
} else
|
||||
printf("Registration failed!\n");
|
||||
return loginSuccess;
|
||||
}
|
||||
|
||||
void AttemptLogin(){
|
||||
Username = calloc(50, sizeof(char));
|
||||
Password = calloc(50, sizeof(char));
|
||||
int state;
|
||||
bool loginSuccess = false;
|
||||
|
||||
if (GrabAccountFromSaveFile(MAIN_AccountSaveFilePath)) {
|
||||
if (GAME_Login()) {
|
||||
printf("Automatic login succeded!\n");
|
||||
return;
|
||||
} else {
|
||||
printf("Automatic login failed! Try manually!\n");
|
||||
system("pause");
|
||||
}
|
||||
}
|
||||
while (!loginSuccess) {
|
||||
system("cls");
|
||||
printf("If you want to upload your score to the scoreboard you need to login! Enter\n\t- 1 for logging in with an existing account\n\t- 2 for creating a new account\n\t- 3 for playing unranked\n");
|
||||
state = readIntFromIO("Input>", "Invalid input! Awaited a number from 1 to 3.\n", "%d is not a valid mode!\n", 1, 3);
|
||||
switch (state) {
|
||||
case 1:
|
||||
GAME_ReadCredentials();
|
||||
loginSuccess = GAME_Login();
|
||||
break;
|
||||
case 2:
|
||||
GAME_ReadCredentials();
|
||||
loginSuccess = GAME_Register();
|
||||
break;
|
||||
case 3:
|
||||
printf("Skipping login!");
|
||||
LoggedIn = false;
|
||||
loginSuccess = true;
|
||||
break;
|
||||
default:
|
||||
printf("This should not happen! State is %d...\n", state);
|
||||
LoggedIn = false;
|
||||
loginSuccess = false;
|
||||
break;
|
||||
} /* switch */
|
||||
if (!loginSuccess) system("pause");
|
||||
}
|
||||
if (PushNewCredentialsToSaveFile(MAIN_AccountSaveFilePath)) printf("New login credentials were automatically saved!\n");
|
||||
else printf("Login credentials could not be autosaved!\n");
|
||||
} /* AttemptLogin */
|
||||
|
||||
int readIntFromIO(char * m1, char * m2, char * m3, int min, int max){
|
||||
int nitems, num;
|
||||
|
||||
while (1) {
|
||||
while (1) {
|
||||
printf(m1);
|
||||
nitems = scanf("%d", &num);
|
||||
if (nitems == 0) {
|
||||
printf(m2);
|
||||
fflush(stdin);
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((num < min) || (num > max)) {
|
||||
printf(m3, num);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fflush(stdin);
|
||||
return(num);
|
||||
} /* readIntFromIO */
|
||||
|
||||
void GAME_Escape(){
|
||||
running = false;
|
||||
printf("GAME_Escape was called!\n");
|
||||
}
|
||||
|
||||
void MENU_StartMusic(){
|
||||
printf("Attempting to start menu music...\n");
|
||||
if (!Mix_PlayingMusic())
|
||||
Mix_FadeInMusic(MenuLoop, -1, MAIN_FadeTime);
|
||||
else printf("Menu music is already playing!\n");
|
||||
}
|
||||
|
||||
void MENU_PauseMusic(){
|
||||
printf("Attempting to pause menu music...\n");
|
||||
if (Mix_PlayingMusic())
|
||||
Mix_HaltMusic();
|
||||
// Mix_FadeOutMusic(MAIN_FadeTime);
|
||||
else printf("There is no menu music to be paused!\n");
|
||||
}
|
||||
|
||||
void GAME_ChangeState(GameState state){
|
||||
if (state == Game) {
|
||||
printf("Game music starting!\n");
|
||||
MENU_PauseMusic();
|
||||
BREAKOUT_StartMusic();
|
||||
} else {
|
||||
printf("Menu music starting!\n");
|
||||
BREAKOUT_PauseMusic();
|
||||
MENU_StartMusic();
|
||||
}
|
||||
if (gameState == state) {
|
||||
printf("State wasn't changed!\n");
|
||||
return;
|
||||
}
|
||||
previousGameState = gameState;
|
||||
gameState = state;
|
||||
switch (gameState) {
|
||||
case Game:
|
||||
BALL_ResetPosition(&(scenery.ball));
|
||||
break;
|
||||
case Highscores:
|
||||
HIGHSCORES_ReloadList();
|
||||
HIGHSCORES_GenerateTexture(renderer);
|
||||
@ -96,6 +263,13 @@ void GAME_ChangeState(GameState state){
|
||||
printf("State was changed to %d!\n", gameState);
|
||||
break;
|
||||
}
|
||||
} /* GAME_ChangeState */
|
||||
void GAME_ReturnToLastScreen(){
|
||||
if (previousGameState == gameState) {
|
||||
printf("Cannot \"return\" to the same screen!\n");
|
||||
} else {
|
||||
GAME_ChangeState(previousGameState);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleSDLEvents(){
|
||||
@ -106,11 +280,12 @@ void HandleSDLEvents(){
|
||||
running = false;
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
// if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE) running = false;
|
||||
// else
|
||||
keyPress(event.key);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
mousePress(event.button);
|
||||
button_clicked(event.button, gameState);
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
windowChanged(event.window);
|
||||
@ -120,26 +295,50 @@ void HandleSDLEvents(){
|
||||
} /* HandleSDLEvents */
|
||||
|
||||
void mousePress(SDL_MouseButtonEvent b){ // Debug prop
|
||||
// if (b.button == SDL_BUTTON_LEFT) {
|
||||
// printf("Left mouse pressed at %d, %d\n", b.x, b.y);
|
||||
// } else if (b.button == SDL_BUTTON_RIGHT) {
|
||||
// printf("Right mouse pressed...\n");
|
||||
// } else {
|
||||
// printf("Unknown mouse button pressed: %d\n", b.button);
|
||||
// }
|
||||
}
|
||||
switch (gameState) {
|
||||
case GameOver:
|
||||
GAMEOVER_MouseClicked(b, &scenery);
|
||||
break;
|
||||
case MainMenu:
|
||||
STARTMENU_ButtonClicked(event.button, gameState);
|
||||
break;
|
||||
case Highscores:
|
||||
HIGHSCORES_MouseClicked(b);
|
||||
break;
|
||||
default:
|
||||
printf("Gamestate currently ignores Mouse press event: %d!\n", gameState);
|
||||
break;
|
||||
}
|
||||
if (b.button == SDL_BUTTON_LEFT) {
|
||||
printf("Left mouse pressed at %d, %d\n", b.x, b.y);
|
||||
} else if (b.button == SDL_BUTTON_RIGHT) {
|
||||
printf("Right mouse pressed...\n");
|
||||
} else {
|
||||
printf("Unknown mouse button pressed: %d\n", b.button);
|
||||
}
|
||||
} /* mousePress */
|
||||
|
||||
void keyPress(SDL_KeyboardEvent b){ // Debug prop
|
||||
// printf("Key pressed: ID is %d\n", b.keysym.scancode);
|
||||
if (b.keysym.scancode == SDL_SCANCODE_F11)
|
||||
printf("Key pressed: ID is %d\n", b.keysym.scancode);
|
||||
if (b.keysym.scancode == SDL_SCANCODE_F11 || b.keysym.scancode == SDL_SCANCODE_5) {
|
||||
toggleFullscreen();
|
||||
} else {
|
||||
switch (gameState) {
|
||||
case Game:
|
||||
BREAKOUT_KeyPressed(&scenery, &b);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void toggleFullscreen(){
|
||||
if (fullscreen)
|
||||
if (fullscreen) {
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
else
|
||||
} else {
|
||||
SDL_SetWindowFullscreen(window, 0);
|
||||
}
|
||||
fullscreen = !fullscreen;
|
||||
}
|
||||
|
||||
@ -147,6 +346,7 @@ void windowChanged(SDL_WindowEvent b){ // Debug prop
|
||||
switch (b.event) {
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
printf("Window was resized to (%d|%d)!\n", event.window.data1, event.window.data2);
|
||||
// BREAKOUT_ChangeSize(event.window.data1, event.window.data2);
|
||||
XScale = ((double)(event.window.data1) / (double)width);
|
||||
YScale = ((double)(event.window.data2) / (double)height);
|
||||
SDL_RenderSetScale(renderer, XScale, YScale);
|
||||
@ -159,7 +359,12 @@ void DrawBackground(SDL_Renderer * renderer){
|
||||
SDL_RenderClear(renderer);
|
||||
} /* DrawFrame */
|
||||
|
||||
void INITIALIZE() {
|
||||
void GAME_Restart(){
|
||||
printf("Starting new game!\n");
|
||||
scenery = BREAKOUT_CreateDefault();
|
||||
}
|
||||
|
||||
void INITIALIZE(){
|
||||
printf("Initializing started...\n");
|
||||
srand(time(NULL));
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) printf("SDL could not initialize! Error: %s\n", SDL_GetError());
|
||||
@ -169,30 +374,38 @@ void INITIALIZE() {
|
||||
else printf("IMG was successfully initialized!\n");
|
||||
if (TTF_Init() == -1) printf("TTF could not initialize! Error: %s\n", TTF_GetError());
|
||||
else printf("TTF was successfully initialized!\n");
|
||||
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) printf("Mixer could not initialize! Error %s\n", Mix_GetError());
|
||||
else printf("Mixer was successfully initialized!\n");
|
||||
|
||||
window = SDL_CreateWindow("BreakING", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
|
||||
SDL_SetWindowResizable(window, true);
|
||||
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
printf("Window was created!\n");
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
printf("Renderer was created!\n");
|
||||
BREAKOUT_INITIALIZE(renderer, width, height);
|
||||
scenery = BREAKOUT_CreateDefault();
|
||||
BREAKOUT_INITIALIZE(renderer);
|
||||
GAME_Restart();
|
||||
Load_Textures(renderer);
|
||||
FONT_Initialize();
|
||||
HIGHSCORES_Initialize();
|
||||
BACKGROUND_Initialize(renderer, width, height);
|
||||
Settings_Initialize(renderer);
|
||||
Settings_Initialize(renderer, &scenery);
|
||||
GAMEOVER_Initialize(renderer);
|
||||
MenuLoop = Mix_LoadMUS(MAIN_MenuMusicPath);
|
||||
printf("Initializing finished!\n");
|
||||
} /* INITIALIZE */
|
||||
|
||||
void QUIT(){
|
||||
printf("De-initializing started...\n");
|
||||
free(Username);
|
||||
free(Password);
|
||||
Mix_FreeMusic(MenuLoop);
|
||||
GAMEOVER_Deinitialize();
|
||||
BACKGROUND_Deinitialize();
|
||||
Settings_Deinitialize();
|
||||
HIGHSCORES_Deinitialize();
|
||||
FONT_Deinitialize();
|
||||
BREAKOUT_DestroyObject(&scenery);
|
||||
BREAKOUT_DEINITIALIZE();
|
||||
Mix_CloseAudio();
|
||||
TTF_Quit();
|
||||
IMG_Quit();
|
||||
printf("Quitting SDL_IMG finished!\n");
|
||||
|
18
main.h
@ -15,6 +15,9 @@
|
||||
#include "startmenu.h"
|
||||
#include "gamestate.h"
|
||||
#include "highscores.h"
|
||||
#include "gameover.h"
|
||||
#include "settings.h"
|
||||
#include "background.h"
|
||||
|
||||
#ifndef __nullptr__
|
||||
#define Nullptr(type) (type *)0
|
||||
@ -26,14 +29,25 @@
|
||||
#define ss "\341"
|
||||
|
||||
// Prototypes
|
||||
void GAME_ChangeState(GameState state);
|
||||
void HandleSDLEvents();
|
||||
bool PushNewCredentialsToSaveFile(const char * filename);
|
||||
bool GrabAccountFromSaveFile(const char * filename);
|
||||
void GAME_ReadCredentials();
|
||||
bool GAME_Login();
|
||||
bool GAME_Register();
|
||||
void AttemptLogin();
|
||||
int readIntFromIO(char * m1, char * m2, char * m3, int min, int max);
|
||||
void GAME_Escape();
|
||||
void MENU_StartMusic();
|
||||
void MENU_PauseMusic();
|
||||
void GAME_ChangeState(GameState state);
|
||||
void GAME_ReturnToLastScreen();
|
||||
void HandleSDLEvents();
|
||||
void mousePress(SDL_MouseButtonEvent b);
|
||||
void keyPress(SDL_KeyboardEvent b);
|
||||
void toggleFullscreen();
|
||||
void windowChanged(SDL_WindowEvent b);
|
||||
void DrawBackground(SDL_Renderer * renderer);
|
||||
void GAME_Restart();
|
||||
void INITIALIZE();
|
||||
void QUIT();
|
||||
// End Prototypes
|
||||
|
110
old/settings.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#define Slider_height 100
|
||||
#define Scalar_width 20
|
||||
#define Bar_width 400
|
||||
#define round(x) ((int) ((x) + .5))
|
||||
#define distance(x1,y1,x2,y2) ((int)(sqrt(pow(x2-x1,2)+pow(y2-y1,2))))
|
||||
|
||||
SDL_Texture* Settings_Texture;
|
||||
SDL_Texture* Settings_Return_Button_Texture;
|
||||
|
||||
SDL_Rect Settings_rect;
|
||||
SDL_Rect Settings_Return_Button_rect;
|
||||
Slider BV;
|
||||
Slider BS;
|
||||
Slider BT;
|
||||
Uint32 Mousestate;
|
||||
bool Settings_IsInit=false;
|
||||
|
||||
void Settings_Initialize (SDL_Renderer* renderer,Scenery* scenery) {
|
||||
Initialize_Slider(400,300,Scalar_width,Bar_width,Slider_height,1,2,&BV,1.5);
|
||||
Initialize_Slider(400,500,Scalar_width,Bar_width,Slider_height,30,100,&BS,scenery->ball.TargetRect.w);
|
||||
Initialize_Slider(400,700,Scalar_width,Bar_width,Slider_height,0,8,&BT,scenery->ball.TextureIndex);
|
||||
Settings_Texture = IMG_LoadTexture(renderer, "assets/images/settings_title.png");
|
||||
Settings_rect = (SDL_Rect){.x = 800, .y = 180, .w=313, .h=100};
|
||||
Settings_Return_Button_Texture = IMG_LoadTexture(renderer, "assets/images/return_button.png");
|
||||
Settings_Return_Button_rect = (SDL_Rect){.x = 200, .y = 200, .w=75, .h=75};
|
||||
Settings_IsInit = true;
|
||||
}
|
||||
|
||||
void Settings_Draw (SDL_Renderer* renderer,Scenery* scenery) {
|
||||
double x;
|
||||
scenery->ball.TargetRect.x=900;
|
||||
scenery->ball.TargetRect.y=700;
|
||||
SDL_RenderCopy(renderer, Settings_Texture, NULL, &Settings_rect);
|
||||
SDL_RenderCopy(renderer, Settings_Return_Button_Texture, NULL, &Settings_Return_Button_rect);
|
||||
Draw_Slider(renderer,&BV);
|
||||
Draw_Slider(renderer,&BS);
|
||||
Draw_Slider(renderer,&BT);
|
||||
Draw_Ballstate(renderer,scenery);
|
||||
mapping(&x,&BT);
|
||||
scenery->ball.TextureIndex=round(x);
|
||||
mapping(&x,&BS);
|
||||
scenery->ball.TargetRect.w=x;
|
||||
scenery->ball.TargetRect.h=x;
|
||||
Settings_Return();
|
||||
}
|
||||
|
||||
void Settings_Deinitialize(){
|
||||
if(Settings_IsInit){
|
||||
SDL_DestroyTexture(Settings_Texture);
|
||||
SDL_DestroyTexture(Settings_Ball_Texture);
|
||||
Settings_IsInit=false;
|
||||
}
|
||||
}
|
||||
|
||||
void Draw_Slider(SDL_Renderer* renderer,Slider* beta){
|
||||
SDL_SetRenderDrawColor(renderer,255,255,255,255);
|
||||
SDL_RenderDrawRect(renderer,&beta->Bar_rect);
|
||||
int x,y;
|
||||
Mousestate=SDL_GetMouseState(&x,&y);
|
||||
if(y<=((beta->Bar_rect.y)+(beta->Bar_rect.h))&&y>=(beta->Bar_rect.y)&&x<=(beta->Bar_rect.w+beta->Bar_rect.x)&&x>=(beta->Bar_rect.x)&&(Mousestate & SDL_BUTTON(SDL_BUTTON_LEFT))){
|
||||
SDL_RenderFillRect(renderer,&beta->Scalar_rect);
|
||||
SDL_RenderDrawRect(renderer,&beta->Scalar_rect);
|
||||
if(x>(beta->Bar_rect.x+beta->Bar_rect.w-(beta->Scalar_rect.w)/2)){
|
||||
beta->Scalar_rect.x=(beta->Bar_rect.x+beta->Bar_rect.w-(beta->Scalar_rect.w));
|
||||
beta->Slider_value=(beta->Bar_rect.x+beta->Bar_rect.w-(beta->Scalar_rect.w)/2);
|
||||
}
|
||||
else if(x<beta->Bar_rect.x+(beta->Scalar_rect.w)/2){
|
||||
beta->Scalar_rect.x=beta->Bar_rect.x;
|
||||
beta->Slider_value=beta->Bar_rect.x+(beta->Scalar_rect.w)/2;
|
||||
}
|
||||
else{
|
||||
beta->Scalar_rect.x=x-(beta->Scalar_rect.w/2);
|
||||
beta->Slider_value=x;
|
||||
}
|
||||
}
|
||||
else{
|
||||
SDL_RenderDrawRect(renderer,&beta->Scalar_rect);
|
||||
}
|
||||
}
|
||||
|
||||
void Draw_Ballstate(SDL_Renderer* renderer,Scenery* scenery){
|
||||
BALL_Draw(renderer, &(scenery->ball));
|
||||
}
|
||||
|
||||
void mapping(double *x,Slider* beta){
|
||||
*x=((beta->max-beta->min)/(beta->Bar_rect.w-(beta->Scalar_rect.w)))*(beta->Slider_value-beta->Bar_rect.x-beta->Scalar_rect.w/2)+beta->min;
|
||||
}
|
||||
|
||||
void Initialize_Slider(int x,int y,int sw,int bw,int h,double min,double max,Slider* beta,double defaultvalue){
|
||||
beta->Scalar_rect = (SDL_Rect){.x=(defaultvalue-min)/(max-min)*(bw-sw/2)+x,.y=y,.w=sw,.h=h};
|
||||
beta->Bar_rect = (SDL_Rect){.x=x,.y=y,.w=bw,.h=h};
|
||||
beta->max=max;
|
||||
beta->min=min;
|
||||
beta->Slider_value=(defaultvalue-min)/(max-min)*(bw-sw/2)+x;
|
||||
}
|
||||
|
||||
void Settings_Return(Scenery* scenery){
|
||||
int x,y;
|
||||
Mousestate=SDL_GetMouseState(&x,&y);
|
||||
if((distance(x,y,237,237)<=37)&&(Mousestate & SDL_BUTTON(SDL_BUTTON_LEFT)))
|
||||
GAME_ChangeState(MainMenu);
|
||||
}
|
38
old/settings.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef __Settings__
|
||||
|
||||
#define __Settings__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include "breakout.h"
|
||||
#include "gamestate.h"
|
||||
#include "main.h"
|
||||
|
||||
typedef struct sliderstruct {
|
||||
SDL_Rect Bar_rect;
|
||||
SDL_Rect Scalar_rect;
|
||||
double Slider_value,min,max;
|
||||
} Slider;
|
||||
|
||||
|
||||
void Settings_Draw (SDL_Renderer* renderer,Scenery* scenery);
|
||||
|
||||
void Draw_Slider(SDL_Renderer* renderer,Slider* beta);
|
||||
|
||||
void Draw_Ballstate(SDL_Renderer* renderer,Scenery* scenery);
|
||||
|
||||
void Settings_Initialize (SDL_Renderer* renderer,Scenery* scenery);
|
||||
|
||||
void Initialize_Slider(int x,int y,int sw,int bw,int h,double min,double max,Slider* beta,double defaultvalue);
|
||||
|
||||
void Settings_Deinitialize();
|
||||
|
||||
void mapping(double *x,Slider* beta);
|
||||
|
||||
void Settings_Return();
|
||||
|
||||
#endif
|
209
settings.c
@ -3,92 +3,177 @@
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#define Slider_height 100
|
||||
#define Scalar_width 20
|
||||
#define Bar_width 400
|
||||
extern float XScale, YScale;
|
||||
|
||||
#define Slider_height 100
|
||||
#define Scalar_width 20
|
||||
#define Bar_width 400
|
||||
#define round(x) ((int)((x) + .5))
|
||||
#define distance(x1,y1,x2,y2) ((int)(sqrt(pow(x2-x1,2)+pow(y2-y1,2))))
|
||||
|
||||
SDL_Texture * Settings_Texture;
|
||||
SDL_Texture * Settings_Ball_Texture;
|
||||
SDL_Texture * Settings_Skins_Texture;
|
||||
SDL_Texture * Return_Button_Texture;
|
||||
SDL_Texture * Bar_Texture;
|
||||
SDL_Texture * Scalar_Button_Texture0;
|
||||
SDL_Texture * Scalar_Button_Texture1;
|
||||
SDL_Texture * L_Arrow_Texture;
|
||||
SDL_Texture * R_Arrow_Texture;
|
||||
|
||||
SDL_Texture* Settings_Texture;
|
||||
SDL_Texture* Settings_Ball_Texture;
|
||||
|
||||
SDL_Rect Settings_rect;
|
||||
SDL_Rect Settings_Ball_rect;
|
||||
SDL_Rect Settings_Skins_rect;
|
||||
SDL_Rect Return_Button_rect;
|
||||
|
||||
Slider BV;
|
||||
Slider BS;
|
||||
Slider BT;
|
||||
Stepslider SBT;
|
||||
|
||||
bool Settings_IsInit=false;
|
||||
Uint32 Mousestate;
|
||||
|
||||
void Settings_Initialize (SDL_Renderer* renderer) {
|
||||
Initialize_Slider(400,300,Scalar_width,Bar_width,Slider_height,1,2,&BV);
|
||||
Initialize_Slider(400,500,Scalar_width,Bar_width,Slider_height,1,2,&BS);
|
||||
Initialize_Slider(400,700,Scalar_width,Bar_width,Slider_height,1,2,&BT);
|
||||
bool Settings_IsInit = false;
|
||||
bool IsLock=false;
|
||||
|
||||
void Settings_Initialize (SDL_Renderer* renderer,Scenery* scenery) {
|
||||
// Initialize_Slider(400,300,Scalar_width,Bar_width,Slider_height,1,2,&BV,1.5);
|
||||
Initialize_Slider(400,500,Scalar_width,Bar_width,Slider_height,30,100,&BS,scenery->ball.TargetRect.w);
|
||||
Initialize_Slider(400,700,Scalar_width,Bar_width,Slider_height,0,8,&BT,scenery->ball.TextureIndex);
|
||||
Initialize_Stepslider(400,300,Scalar_width,Bar_width,Slider_height,0,8,&SBT,scenery->ball.TextureIndex);
|
||||
Settings_Texture = IMG_LoadTexture(renderer, "assets/images/settings_title.png");
|
||||
Settings_rect = (SDL_Rect){.x = 800, .y = 180, .w=313, .h=100};
|
||||
Settings_Ball_Texture = IMG_LoadTexture(renderer, "assets/images/ball.png");
|
||||
Settings_Ball_rect = (SDL_Rect){.x = 1200, .y = 300, .w=100, .h=100};
|
||||
Settings_rect = (SDL_Rect){.x = 647, .y = 50, .w=626, .h=200};
|
||||
|
||||
Settings_Ball_rect = (SDL_Rect){.x = 1200, .y = 700, .w=90, .h=90};
|
||||
|
||||
Settings_Skins_Texture = IMG_LoadTexture(renderer, "assets/images/skins_button.png");
|
||||
Settings_Skins_rect = (SDL_Rect){.x = 50, .y = 710, .w=315, .h=70};
|
||||
|
||||
Return_Button_Texture = IMG_LoadTexture(renderer, "assets/images/return_button.png");
|
||||
Return_Button_rect = (SDL_Rect){.x = 200, .y = 200, .w=75, .h=75};
|
||||
|
||||
Bar_Texture = IMG_LoadTexture(renderer, "assets/images/bar_texture.png");
|
||||
Scalar_Button_Texture0 = IMG_LoadTexture(renderer, "assets/images/scalar_button_unpressed.png");
|
||||
Scalar_Button_Texture1 = IMG_LoadTexture(renderer, "assets/images/scalar_button_pressed.png");
|
||||
|
||||
R_Arrow_Texture = IMG_LoadTexture(renderer, "assets/images/r_arrow_button.png" );
|
||||
L_Arrow_Texture = IMG_LoadTexture(renderer, "assets/images/l_arrow_button.png" );
|
||||
|
||||
Settings_IsInit = true;
|
||||
}
|
||||
|
||||
void Settings_Draw (SDL_Renderer* renderer) {
|
||||
double x;
|
||||
SDL_RenderCopy(renderer, Settings_Texture, NULL, &Settings_rect);
|
||||
SDL_RenderCopy(renderer, Settings_Ball_Texture, NULL, &Settings_Ball_rect);
|
||||
Draw_Slider(renderer,&BV);
|
||||
Draw_Slider(renderer,&BS);
|
||||
Draw_Slider(renderer,&BT);
|
||||
mapping(&x,&BT);
|
||||
void Settings_Draw(SDL_Renderer * renderer, Scenery * scenery) {
|
||||
double x;
|
||||
if(!(Mousestate & SDL_BUTTON(SDL_BUTTON_LEFT))){
|
||||
IsLock=BV.IsLock=BS.IsLock=BT.IsLock=false;
|
||||
}else{
|
||||
IsLock=true;
|
||||
}
|
||||
// Draw_Slider(renderer, &BV);
|
||||
Draw_Slider(renderer, &BS);
|
||||
Draw_Slider(renderer, &BT);
|
||||
Draw_Stepslider(renderer, &SBT);
|
||||
SDL_RenderCopy(renderer, Settings_Texture, NULL, &Settings_rect);
|
||||
SDL_RenderCopy(renderer, Return_Button_Texture, NULL, &Return_Button_rect);
|
||||
SDL_RenderCopy(renderer, Settings_Skins_Texture, NULL, &Settings_Skins_rect);
|
||||
BALL_DrawTexture(renderer, &Settings_Ball_rect, scenery->ball.TextureIndex);
|
||||
Settings_Return();
|
||||
|
||||
mapping(&x, &BS);
|
||||
scenery->ball.TargetRect.w = x;
|
||||
scenery->ball.TargetRect.h = x;
|
||||
scenery->ball.Size = ((double)x / 2.0f);
|
||||
mapping(&x, &BT);
|
||||
x = round(x);
|
||||
scenery->ball.TextureIndex = x;
|
||||
}
|
||||
|
||||
void Settings_Deinitialize(){
|
||||
if(Settings_IsInit){
|
||||
SDL_DestroyTexture(Settings_Texture);
|
||||
SDL_DestroyTexture(Settings_Ball_Texture);
|
||||
Settings_IsInit=false;
|
||||
}
|
||||
if (Settings_IsInit) {
|
||||
SDL_DestroyTexture(Settings_Texture);
|
||||
SDL_DestroyTexture(Settings_Ball_Texture);
|
||||
SDL_DestroyTexture(Bar_Texture);
|
||||
SDL_DestroyTexture(Return_Button_Texture);
|
||||
SDL_DestroyTexture(Settings_Skins_Texture);
|
||||
SDL_DestroyTexture(Scalar_Button_Texture0);
|
||||
SDL_DestroyTexture(Scalar_Button_Texture1);
|
||||
Settings_IsInit = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Draw_Slider(SDL_Renderer* renderer,Slider* beta){
|
||||
SDL_SetRenderDrawColor(renderer,255,255,255,255);
|
||||
SDL_RenderDrawRect(renderer,&beta->Bar_rect);
|
||||
int x,y;
|
||||
Uint32 Mousestate=SDL_GetMouseState(&x,&y);
|
||||
if(y<=((beta->y)+(beta->h))&&y>=(beta->y)&&x<=(beta->bw+beta->x)&&x>=(beta->x)&&(Mousestate & SDL_BUTTON(SDL_BUTTON_LEFT))){
|
||||
SDL_RenderFillRect(renderer,&beta->Scalar_rect);
|
||||
SDL_RenderDrawRect(renderer,&beta->Scalar_rect);
|
||||
if(x>(beta->x+beta->bw-(beta->sw)/2)){
|
||||
beta->Scalar_rect.x=(beta->x+beta->bw-(beta->sw));
|
||||
beta->Slider_value=(beta->x+beta->bw-(beta->sw)/2);
|
||||
void Draw_Slider(SDL_Renderer * renderer, Slider * beta){
|
||||
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||||
SDL_RenderCopy(renderer, Bar_Texture, NULL, &beta->Bar_rect);
|
||||
int x, y;
|
||||
Mousestate = SDL_GetMouseState(&x, &y);
|
||||
x = round((float)x / XScale);
|
||||
y = round((float)y / YScale);
|
||||
if ((y <= ((beta->Bar_rect.y) + (beta->Bar_rect.h)) && y >= (beta->Bar_rect.y) && x <= (beta->Bar_rect.w + beta->Bar_rect.x) && x >= (beta->Bar_rect.x) && (Mousestate & SDL_BUTTON(SDL_BUTTON_LEFT)))||beta->IsLock) {
|
||||
if(!IsLock){
|
||||
beta->IsLock=true;
|
||||
IsLock=true;
|
||||
}
|
||||
if(beta->IsLock){
|
||||
SDL_RenderCopy(renderer, Scalar_Button_Texture1, NULL, &beta->Scalar_rect);
|
||||
if (x > (beta->Bar_rect.x + beta->Bar_rect.w - (beta->Scalar_rect.w) / 2)) {
|
||||
beta->Scalar_rect.x = (beta->Bar_rect.x + beta->Bar_rect.w - (beta->Scalar_rect.w));
|
||||
beta->Slider_value = (beta->Bar_rect.x + beta->Bar_rect.w - (beta->Scalar_rect.w) / 2);
|
||||
} else if (x < beta->Bar_rect.x + (beta->Scalar_rect.w) / 2) {
|
||||
beta->Scalar_rect.x = beta->Bar_rect.x;
|
||||
beta->Slider_value = beta->Bar_rect.x + (beta->Scalar_rect.w) / 2;
|
||||
} else {
|
||||
beta->Scalar_rect.x = x - (beta->Scalar_rect.w / 2);
|
||||
beta->Slider_value = x;
|
||||
}
|
||||
} else {
|
||||
SDL_RenderCopy(renderer, Scalar_Button_Texture0, NULL, &beta->Scalar_rect);
|
||||
}
|
||||
} else {
|
||||
SDL_RenderCopy(renderer, Scalar_Button_Texture0, NULL, &beta->Scalar_rect);
|
||||
}
|
||||
else if(x<beta->x+(beta->sw)/2){
|
||||
beta->Scalar_rect.x=beta->x;
|
||||
beta->Slider_value=beta->x+(beta->sw)/2;
|
||||
}
|
||||
else{
|
||||
beta->Scalar_rect.x=x-(beta->sw/2);
|
||||
beta->Slider_value=x;
|
||||
}
|
||||
}
|
||||
else{
|
||||
SDL_RenderDrawRect(renderer,&beta->Scalar_rect);
|
||||
}
|
||||
} /* Draw_Slider */
|
||||
|
||||
void Draw_Stepslider(SDL_Renderer* renderer,Stepslider* beta){
|
||||
SDL_RenderCopy(renderer, Bar_Texture, NULL, &beta->Bar_rect);
|
||||
SDL_RenderCopy(renderer, Scalar_Button_Texture0, NULL, &beta->Scalar_rect);
|
||||
SDL_RenderCopy(renderer, L_Arrow_Texture, NULL, &beta->L_Arrow_rect);
|
||||
SDL_RenderCopy(renderer, R_Arrow_Texture, NULL, &beta->R_Arrow_rect);
|
||||
}
|
||||
|
||||
void mapping(double *x,Slider* beta){
|
||||
*x=((beta->max-beta->min)/(beta->bw-(beta->sw)))*(beta->Slider_value-beta->x-beta->sw/2)+beta->min;
|
||||
void mapping(double * x, Slider * beta){
|
||||
*x = ((beta->max - beta->min) / (beta->Bar_rect.w - (beta->Scalar_rect.w))) * (beta->Slider_value - beta->Bar_rect.x - beta->Scalar_rect.w / 2) + beta->min;
|
||||
}
|
||||
|
||||
void Initialize_Slider(int x,int y,int sw,int bw,int h,double min,double max,Slider* beta){
|
||||
beta->Scalar_rect = (SDL_Rect){.x=x,.y=y,.w=sw,.h=h};
|
||||
beta->Bar_rect = (SDL_Rect){.x=x,.y=y,.w=bw,.h=h};
|
||||
beta->x=x;
|
||||
beta->y=y;
|
||||
beta->sw=sw;
|
||||
beta->bw=bw;
|
||||
beta->h=h;
|
||||
beta->max=max;
|
||||
beta->min=min;
|
||||
beta->Slider_value=x+sw/2;
|
||||
void Initialize_Slider(int x, int y, int sw, int bw, int h, double min, double max, Slider * beta,double defaultvalue){
|
||||
beta->Scalar_rect = (SDL_Rect) {.x = (defaultvalue-min)/(max-min)*(bw-sw/2)+x, .y = y, .w = sw, .h = h };
|
||||
beta->Bar_rect = (SDL_Rect) {.x = x, .y = y, .w = bw, .h = h };
|
||||
beta->max = max;
|
||||
beta->min = min;
|
||||
beta->Slider_value = (defaultvalue-min)/(max-min)*(bw-sw/2)+x;
|
||||
}
|
||||
|
||||
void Initialize_Stepslider(int x,int y,int sw,int bw,int h,double min,double max,Stepslider* beta,double defaultvalue){
|
||||
beta->Scalar_rect = (SDL_Rect) {.x = (defaultvalue-min)/(max-min)*(bw-sw/2)+x, .y = y, .w = sw, .h = h };
|
||||
beta->Bar_rect = (SDL_Rect) {.x = x, .y = y, .w = bw, .h = h };
|
||||
beta->L_Arrow_rect = (SDL_Rect) {.x = x-30-h, .y = y, .w = h, .h = h };
|
||||
beta->R_Arrow_rect = (SDL_Rect) {.x = x+bw+30, .y = y, .w = h, .h = h };
|
||||
beta->max = max;
|
||||
beta->min = min;
|
||||
beta->Slider_value = (defaultvalue-min)/(max-min)*(bw-sw/2)+x;
|
||||
}
|
||||
|
||||
void Settings_Return(){
|
||||
if(!IsLock){
|
||||
int x,y;
|
||||
Mousestate=SDL_GetMouseState(&x,&y);
|
||||
x = round((float)x / XScale);
|
||||
y = round((float)y / YScale);
|
||||
if((distance(x,y,237,237)<=37)&&(Mousestate & SDL_BUTTON(SDL_BUTTON_LEFT)))
|
||||
GAME_ChangeState(MainMenu);
|
||||
}
|
||||
}
|
||||
|
29
settings.h
@ -7,24 +7,43 @@
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <stdbool.h>
|
||||
#include "breakout.h"
|
||||
#include "gamestate.h"
|
||||
#include "main.h"
|
||||
|
||||
typedef struct sliderstruct {
|
||||
SDL_Rect Bar_rect;
|
||||
SDL_Rect Scalar_rect;
|
||||
int x,y,bw,sw,h;
|
||||
bool IsLock;
|
||||
double Slider_value,min,max;
|
||||
} Slider;
|
||||
|
||||
void Settings_Initialize (SDL_Renderer* renderer);
|
||||
typedef struct stepsliderstruct {
|
||||
SDL_Rect Bar_rect;
|
||||
SDL_Rect Scalar_rect;
|
||||
SDL_Rect L_Arrow_rect;
|
||||
SDL_Rect R_Arrow_rect;
|
||||
bool IsLock;
|
||||
double Slider_value,min,max;
|
||||
} Stepslider;
|
||||
|
||||
void Settings_Draw (SDL_Renderer* renderer);
|
||||
|
||||
void Settings_Deinitialize();
|
||||
void Settings_Draw (SDL_Renderer* renderer,Scenery* scenery);
|
||||
|
||||
void Draw_Slider(SDL_Renderer* renderer,Slider* beta);
|
||||
|
||||
void Draw_Stepslider(SDL_Renderer* renderer,Stepslider* beta);
|
||||
|
||||
void Settings_Initialize (SDL_Renderer* renderer,Scenery* scenery);
|
||||
|
||||
void Initialize_Slider(int x,int y,int sw,int bw,int h,double min,double max,Slider* beta,double defaultvalue);
|
||||
|
||||
void Initialize_Stepslider(int x,int y,int sw,int bw,int h,double min,double max,Stepslider* beta,double defaultvalue);
|
||||
|
||||
void Settings_Deinitialize();
|
||||
|
||||
void mapping(double *x,Slider* beta);
|
||||
|
||||
void Initialize_Slider(int x,int y,int sw,int bw,int h,double min,double max,Slider* beta);
|
||||
void Settings_Return();
|
||||
|
||||
#endif
|
||||
|
48
startmenu.c
@ -5,11 +5,11 @@
|
||||
#include "gamestate.h"
|
||||
#include "main.h"
|
||||
|
||||
extern float XScale, YScale;
|
||||
extern SDL_Rect Return_Button_rect;
|
||||
|
||||
SDL_Texture * TITLE_Texture;
|
||||
SDL_Texture * PLAYBUTTON_Texture;
|
||||
SDL_Texture * SKINSBUTTON_Texture;
|
||||
SDL_Texture * LEVELBUTTON_Texture;
|
||||
SDL_Texture * SETTINGSBUTTON_Texture;
|
||||
SDL_Texture * HIGHSCORESBUTTON_Texture;
|
||||
SDL_Texture * QUITBUTTON_Texture;
|
||||
@ -17,13 +17,15 @@ SDL_Texture * QUITBUTTON_Texture;
|
||||
SDL_Rect TITLE_Rect;
|
||||
SDL_Rect PLAYBUTTON_Rect;
|
||||
SDL_Rect SETTINGSBUTTON_Rect;
|
||||
SDL_Rect LEVELBUTTON_Rect;
|
||||
SDL_Rect SKINSBUTTON_Rect;
|
||||
SDL_Rect HIGHSCORESBUTTON_Rect;
|
||||
SDL_Rect QUITBUTTON_Rect;
|
||||
|
||||
int clickInRect(SDL_MouseButtonEvent b, SDL_Rect * area_rect) {
|
||||
return (((b.x) >= (area_rect->x)) && ((b.x) <= ((area_rect->x) + (area_rect->w))) && ((b.y) >= (area_rect->y)) && ((b.y) <= ((area_rect->y) + (area_rect->h))));
|
||||
int clickx, clicky;
|
||||
|
||||
clickx = (int)roundf((float)b.x / XScale);
|
||||
clicky = (int)roundf((float)b.y / YScale);
|
||||
return ((clickx >= (area_rect->x)) && (clickx <= ((area_rect->x) + (area_rect->w))) && (clicky >= (area_rect->y)) && (clicky <= ((area_rect->y) + (area_rect->h))));
|
||||
}
|
||||
|
||||
void Load_Textures(SDL_Renderer * renderer) {
|
||||
@ -31,16 +33,10 @@ void Load_Textures(SDL_Renderer * renderer) {
|
||||
TITLE_Rect = (SDL_Rect) {.x = 685, .y = 50, .w = 550, .h = 250 };
|
||||
|
||||
PLAYBUTTON_Texture = IMG_LoadTexture(renderer, "assets/images/play_button.png");
|
||||
PLAYBUTTON_Rect = (SDL_Rect) {.x = 497, .y = 400, .w = 313, .h = 178 };
|
||||
|
||||
SKINSBUTTON_Texture = IMG_LoadTexture(renderer, "assets/images/skins_button.png");
|
||||
SKINSBUTTON_Rect = (SDL_Rect) {.x = 1110, .y = 400, .w = 313, .h = 178 };
|
||||
|
||||
LEVELBUTTON_Texture = IMG_LoadTexture(renderer, "assets/images/level_button.png");
|
||||
LEVELBUTTON_Rect = (SDL_Rect) {.x = 497, .y = 700, .w = 313, .h = 178 };
|
||||
PLAYBUTTON_Rect = (SDL_Rect) {.x = 772, .y = 420, .w = 376, .h = 214 };
|
||||
|
||||
SETTINGSBUTTON_Texture = IMG_LoadTexture(renderer, "assets/images/settings_button.png");
|
||||
SETTINGSBUTTON_Rect = (SDL_Rect) {.x = 1110, .y = 700, .w = 313, .h = 178 };
|
||||
SETTINGSBUTTON_Rect = (SDL_Rect) {.x = 772, .y = 720, .w = 376, .h = 214 };
|
||||
|
||||
HIGHSCORESBUTTON_Texture = IMG_LoadTexture(renderer, "assets/images/highscores_button.png");
|
||||
HIGHSCORESBUTTON_Rect = (SDL_Rect) {.x = 1557, .y = 120, .w = 313, .h = 178 };
|
||||
@ -52,27 +48,19 @@ void Load_Textures(SDL_Renderer * renderer) {
|
||||
void Startmenu_Draw(SDL_Renderer * renderer) {
|
||||
SDL_RenderCopy(renderer, TITLE_Texture, NULL, &TITLE_Rect);
|
||||
SDL_RenderCopy(renderer, PLAYBUTTON_Texture, NULL, &PLAYBUTTON_Rect);
|
||||
SDL_RenderCopy(renderer, SKINSBUTTON_Texture, NULL, &SKINSBUTTON_Rect);
|
||||
SDL_RenderCopy(renderer, LEVELBUTTON_Texture, NULL, &LEVELBUTTON_Rect);
|
||||
SDL_RenderCopy(renderer, SETTINGSBUTTON_Texture, NULL, &SETTINGSBUTTON_Rect);
|
||||
SDL_RenderCopy(renderer, HIGHSCORESBUTTON_Texture, NULL, &HIGHSCORESBUTTON_Rect);
|
||||
SDL_RenderCopy(renderer, QUITBUTTON_Texture, NULL, &QUITBUTTON_Rect);
|
||||
}
|
||||
|
||||
void button_clicked(SDL_MouseButtonEvent b, GameState gameState) {
|
||||
if (gameState == MainMenu) {
|
||||
if (clickInRect(b, &PLAYBUTTON_Rect) == 1) {
|
||||
GAME_ChangeState(Game);
|
||||
} else if (clickInRect(b, &SKINSBUTTON_Rect) == 1) {
|
||||
GAME_ChangeState(SkinSelect);
|
||||
} else if (clickInRect(b, &LEVELBUTTON_Rect) == 1) {
|
||||
GAME_ChangeState(LevelSelect);
|
||||
} else if (clickInRect(b, &SETTINGSBUTTON_Rect) == 1) {
|
||||
GAME_ChangeState(Settings);
|
||||
} else if (clickInRect(b, &HIGHSCORESBUTTON_Rect) == 1) {
|
||||
GAME_ChangeState(Highscores);
|
||||
} else if (clickInRect(b, &QUITBUTTON_Rect) == 1) {
|
||||
GAME_Escape();
|
||||
}
|
||||
void STARTMENU_ButtonClicked(SDL_MouseButtonEvent b, GameState gameState) {
|
||||
if (clickInRect(b, &PLAYBUTTON_Rect) == 1) {
|
||||
GAME_ChangeState(Game);
|
||||
} else if (clickInRect(b, &SETTINGSBUTTON_Rect) == 1) {
|
||||
GAME_ChangeState(Settings);
|
||||
} else if (clickInRect(b, &HIGHSCORESBUTTON_Rect) == 1) {
|
||||
GAME_ChangeState(Highscores);
|
||||
} else if (clickInRect(b, &QUITBUTTON_Rect) == 1) {
|
||||
GAME_Escape();
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ void Load_Textures (SDL_Renderer* renderer);
|
||||
|
||||
void Startmenu_Draw (SDL_Renderer* renderer);
|
||||
|
||||
void button_clicked(SDL_MouseButtonEvent b, GameState gameState);
|
||||
void STARTMENU_ButtonClicked(SDL_MouseButtonEvent b, GameState gameState);
|
||||
|
||||
int clickInRect(SDL_MouseButtonEvent b, SDL_Rect* area_rect);
|
||||
|
||||
|