Compare commits
32 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 | ||
|
b4aac4d41b | ||
|
cde0ae9bc9 |
1
.gitignore
vendored
@ -9,6 +9,7 @@ sdl2-config
|
||||
*.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
BIN
bin/assets/images/bar_texture.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
bin/assets/images/l_arrow_button.png
Normal file
After Width: | Height: | Size: 2.5 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/upload.png
Normal file
After Width: | Height: | Size: 620 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
178
breakout.c
@ -1,11 +1,11 @@
|
||||
#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"
|
||||
@ -19,8 +19,15 @@ 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 BRAEKOUT_CountdownTexturePath "assets/images/text.png"
|
||||
#define BRAEKOUT_PausedTexturePath "assets/images/paused.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
|
||||
@ -29,12 +36,16 @@ extern int width, height;
|
||||
#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 BALL_TextureCount = 9;
|
||||
int BREAKOUT_CountdownTextureCount = 4;
|
||||
@ -53,6 +64,9 @@ 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){
|
||||
if (!BREAKOUT_IsInit) {
|
||||
@ -61,9 +75,9 @@ void BREAKOUT_INITIALIZE(SDL_Renderer * renderer){
|
||||
BALL_Initialize(renderer);
|
||||
PADDLE_Initialize(renderer);
|
||||
BLOCK_Initialize(renderer);
|
||||
BREAKOUT_CountdownTexture = IMG_LoadTexture(renderer, BRAEKOUT_CountdownTexturePath);
|
||||
BREAKOUT_CountdownTexture = IMG_LoadTexture(renderer, BREAKOUT_CountdownTexturePath);
|
||||
if (!BREAKOUT_CountdownTexture) printf("Countdown texture failed to load!\n");
|
||||
BREAKOUT_PausedTexture = IMG_LoadTexture(renderer, BRAEKOUT_PausedTexturePath);
|
||||
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));
|
||||
@ -72,11 +86,35 @@ void BREAKOUT_INITIALIZE(SDL_Renderer * renderer){
|
||||
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"));
|
||||
@ -93,24 +131,28 @@ 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;
|
||||
@ -142,6 +184,28 @@ void TEXTURE_RenderCentered(SDL_Renderer * renderer, SDL_Texture * texture, floa
|
||||
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;
|
||||
if ((scenery->StartCountdown)-- > 0) return;
|
||||
@ -151,18 +215,23 @@ void BREAKOUT_Update(Scenery * scenery, const Uint8 * keystate){
|
||||
PADDLE_ResetPosition(&(scenery->paddle));
|
||||
scenery->StartCountdown = 240;
|
||||
scenery->IsGameOver = false;
|
||||
scenery->Frames = 0;
|
||||
if (--(scenery->Lives) <= 0)
|
||||
GAME_ChangeState(GameOver);
|
||||
else
|
||||
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;
|
||||
}
|
||||
if ((scenery->Frames) % BREAKOUT_PushIntervale == 0) {
|
||||
BREAKOUT_PushNewRow(scenery);
|
||||
}
|
||||
PADDLE_Update(&(scenery->paddle), scenery, keystate); // Update paddle before ball because paddle is not static!
|
||||
BALL_Update(&(scenery->ball), scenery);
|
||||
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){
|
||||
@ -175,7 +244,7 @@ void BREAKOUT_Draw(Scenery * scenery, SDL_Renderer * renderer){
|
||||
BREAKOUT_DrawLivesHUD(renderer, scenery);
|
||||
if (scenery->IsPaused) {
|
||||
TEXTURE_RenderCentered(renderer, BREAKOUT_PausedTexture, 0.5f);
|
||||
} else if ((scenery->StartCountdown) > 0) { // ! Render Z-Layer !
|
||||
} else if ((scenery->StartCountdown) > 0) { // ! Render Z-Layer !
|
||||
TEXTURE_RenderCenteredSpriteSheet(renderer, BREAKOUT_CountdownTexture, (BREAKOUT_CountdownSourceRects + (((scenery->StartCountdown) - 1) / 60)), 1.0f);
|
||||
}
|
||||
}
|
||||
@ -197,6 +266,12 @@ void BREAKOUT_DrawLivesHUD(SDL_Renderer * renderer, Scenery * scenery){
|
||||
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);
|
||||
@ -211,7 +286,7 @@ void BREAKOUT_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++) {
|
||||
@ -246,7 +321,7 @@ void BALL_Initialize(SDL_Renderer * renderer){
|
||||
|
||||
Ball BALL_CreateDefault(){
|
||||
return (Ball) {
|
||||
.Location = (Vector) {.x = (width / 2) - 15, .y = height - 132 },
|
||||
.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,
|
||||
@ -258,8 +333,8 @@ Ball BALL_CreateDefault(){
|
||||
}
|
||||
|
||||
void BALL_ResetPosition(Ball * obj){
|
||||
(obj->Location).x = width / 2 - 15;
|
||||
(obj->Location).y = height - 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));
|
||||
}
|
||||
@ -280,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
|
||||
@ -307,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 */
|
||||
|
||||
@ -350,8 +434,8 @@ 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){
|
||||
@ -372,7 +456,7 @@ void BALL_MoveAwayFromBoundaries(Ball * obj){
|
||||
|
||||
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
|
||||
@ -384,6 +468,7 @@ bool BALL_CollideWithPaddle(Ball * obj, Paddle * paddle){
|
||||
RECT_SetTargetPos(&(obj->TargetRect), &(obj->Location));
|
||||
}
|
||||
(obj->Momentum) = VECTOR_ChangeScaleTo((obj->Momentum), (obj->Speed));
|
||||
BALL_PlayCollisionSound();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -396,6 +481,13 @@ void BALL_AdaptSpeedGradient(Ball * obj, int FrameCount){
|
||||
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));
|
||||
@ -415,6 +507,7 @@ 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)++;
|
||||
@ -426,6 +519,7 @@ void BALL_Update(Ball * obj, Scenery * scenery){
|
||||
}
|
||||
}
|
||||
if ((obj->Location).y > height) { // Collide with box boundaries
|
||||
Mix_PlayChannel(-1, BREAKOUT_DeathSound, 0);
|
||||
scenery->IsGameOver = true;
|
||||
printf("Ball called game_over!\n");
|
||||
} else BALL_CollideWithBorders(obj);
|
||||
@ -525,11 +619,17 @@ void PADDLE_MoveSmooth(Paddle * obj){
|
||||
(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){
|
||||
@ -550,6 +650,9 @@ void PADDLE_Update(Paddle * obj, Scenery * scenery, const Uint8 * keystate){
|
||||
((obj->TargetRect).x) += (obj->Speed);
|
||||
}
|
||||
break;
|
||||
case Automatic:
|
||||
PADDLE_MoveAuto(scenery);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown Paddle Control Mode: %d!\n", obj->Mode);
|
||||
break;
|
||||
@ -605,11 +708,12 @@ 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
|
||||
}
|
||||
|
||||
@ -632,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){
|
||||
}
|
||||
|
18
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,26 +34,29 @@ 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, Frames, Score, DestroyedBlocks;
|
||||
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);
|
||||
void BREAKOUT_StartMusic();
|
||||
void BREAKOUT_PauseMusic();
|
||||
void BREAKOUT_TogglePause(Scenery * scenery);
|
||||
void BREAKOUT_KeyPressed(Scenery * scenery, SDL_KeyboardEvent * b);
|
||||
Scenery BREAKOUT_CreateDefault();
|
||||
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);
|
||||
@ -66,11 +71,12 @@ 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();
|
||||
@ -83,15 +89,17 @@ 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_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();
|
||||
|
108
gameover.c
@ -9,47 +9,63 @@
|
||||
|
||||
#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
|
||||
|
||||
#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>
|
||||
extern char * Username;
|
||||
extern char * Password;
|
||||
extern bool LoggedIn;
|
||||
|
||||
#include "breakout.h"
|
||||
#include "vector.h"
|
||||
#include "background.h"
|
||||
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;
|
||||
@ -70,17 +86,61 @@ void GAMEOVER_Initialize(SDL_Renderer * renderer){
|
||||
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));
|
||||
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;
|
||||
|
||||
@ -100,9 +160,22 @@ void GAMEOVER_Draw(SDL_Renderer * renderer, Scenery * scenery){
|
||||
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;
|
||||
xOffset += target.w - 1;
|
||||
}
|
||||
} /* GAMEOVER_Draw */
|
||||
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;
|
||||
@ -137,7 +210,7 @@ void SCORE_DrawHUD(SDL_Renderer * renderer, Scenery * scenery){
|
||||
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;
|
||||
xOffset += target.w - 1;
|
||||
}
|
||||
} /* SCORE_DrawHUD */
|
||||
|
||||
@ -145,9 +218,14 @@ 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
|
||||
|
@ -14,9 +14,15 @@
|
||||
#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();
|
||||
|
94
highscores.c
@ -7,10 +7,13 @@
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include "highscores.h"
|
||||
#include "main.h"
|
||||
|
||||
#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;
|
||||
@ -18,6 +21,7 @@ SDL_Texture * HIGHSCORES_TableTexture;
|
||||
SDL_Rect HIGHSCORES_TotalRect;
|
||||
TTF_Font * HIGHSCORES_FontFamily = NULL;
|
||||
SDL_Surface * tempSurface;
|
||||
SDL_Rect HIGHSCORES_ReturnButtonRect;
|
||||
|
||||
void HIGHSCORES_Initialize(){
|
||||
printf("Initializing Highscores...\n");
|
||||
@ -25,9 +29,12 @@ void HIGHSCORES_Initialize(){
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
||||
@ -51,14 +58,22 @@ void printFontStyle(TTF_Font * ffont){
|
||||
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(){
|
||||
printf("De-initializing Highscores...\n");
|
||||
TTF_CloseFont(HIGHSCORES_FontFamily);
|
||||
HIGHSCORES_FontFamily = NULL; // to be safe...
|
||||
SDL_DestroyTexture(HIGHSCORES_TableTexture);
|
||||
SDL_FreeSurface(tempSurface);
|
||||
free(HIGHSCORES_UserList);
|
||||
@ -109,13 +124,12 @@ bool HIGHSCORES_UploadScore(char * username, int score){
|
||||
char * line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
char * name, * scorestring;
|
||||
|
||||
sprintf(buffer, "bhi upload %s %s %d", HIGHSCORES_OutputFilePath, username, score);
|
||||
printf("BHI called with \"%s\"\n", buffer);
|
||||
printf("Call BHI interface:\n");
|
||||
// printf("BHI called with \"%s\"\n", buffer);
|
||||
// printf("Call BHI interface:\n");
|
||||
system(buffer);
|
||||
printf("BHI interface quit!\nBHI output handling...\n");
|
||||
// printf("BHI interface quit!\nBHI output handling...\n");
|
||||
FILE * fp = fopen(HIGHSCORES_OutputFilePath, "r");
|
||||
if (fp == NULL) {
|
||||
fclose(fp);
|
||||
@ -130,10 +144,70 @@ bool HIGHSCORES_UploadScore(char * username, int score){
|
||||
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;
|
||||
@ -145,8 +219,10 @@ 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')
|
||||
return;
|
||||
|
@ -10,11 +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
|
||||
|
210
main.c
@ -2,10 +2,12 @@
|
||||
#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"
|
||||
@ -16,6 +18,10 @@
|
||||
#include "settings.h"
|
||||
#include "background.h"
|
||||
|
||||
#define MAIN_MenuMusicPath "assets/sounds/menu_music.wav"
|
||||
#define MAIN_AccountSaveFilePath "account.cfg"
|
||||
#define MAIN_FadeTime 1000
|
||||
|
||||
#include "main.h"
|
||||
|
||||
// Default Render Size (Upscaled for bigger monitors)
|
||||
@ -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);
|
||||
@ -78,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);
|
||||
@ -99,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(){
|
||||
@ -115,7 +286,6 @@ void HandleSDLEvents(){
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
mousePress(event.button);
|
||||
button_clicked(event.button, gameState);
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
windowChanged(event.window);
|
||||
@ -125,6 +295,20 @@ void HandleSDLEvents(){
|
||||
} /* HandleSDLEvents */
|
||||
|
||||
void mousePress(SDL_MouseButtonEvent b){ // Debug prop
|
||||
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) {
|
||||
@ -132,7 +316,7 @@ void mousePress(SDL_MouseButtonEvent b){ // Debug prop
|
||||
} 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);
|
||||
@ -175,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());
|
||||
@ -185,6 +374,8 @@ 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);
|
||||
@ -193,23 +384,28 @@ void INITIALIZE() {
|
||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
printf("Renderer was created!\n");
|
||||
BREAKOUT_INITIALIZE(renderer);
|
||||
scenery = BREAKOUT_CreateDefault();
|
||||
GAME_Restart();
|
||||
Load_Textures(renderer);
|
||||
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();
|
||||
BREAKOUT_DestroyObject(&scenery);
|
||||
BREAKOUT_DEINITIALIZE();
|
||||
Mix_CloseAudio();
|
||||
TTF_Quit();
|
||||
IMG_Quit();
|
||||
printf("Quitting SDL_IMG finished!\n");
|
||||
|
15
main.h
@ -29,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
|
130
settings.c
@ -3,47 +3,91 @@
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
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_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;
|
||||
|
||||
Uint32 Mousestate;
|
||||
|
||||
bool Settings_IsInit = false;
|
||||
bool IsLock=false;
|
||||
|
||||
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,10.0f,20.0f,&BS);
|
||||
Initialize_Slider(400,700,Scalar_width,Bar_width,Slider_height,0,1,&BT);
|
||||
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 = 130, .w=470, .h=150};
|
||||
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, Scenery * scenery) {
|
||||
double x;
|
||||
|
||||
SDL_RenderCopy(renderer, Settings_Texture, NULL, &Settings_rect);
|
||||
SDL_RenderCopy(renderer, Settings_Ball_Texture, NULL, &Settings_Ball_rect);
|
||||
Draw_Slider(renderer, &BV);
|
||||
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_Ballstate(renderer, scenery);
|
||||
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.Speed = x;
|
||||
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;
|
||||
@ -53,18 +97,29 @@ void Settings_Deinitialize(){
|
||||
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);
|
||||
SDL_RenderCopy(renderer, Bar_Texture, NULL, &beta->Bar_rect);
|
||||
int x, y;
|
||||
Uint32 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);
|
||||
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);
|
||||
@ -75,23 +130,50 @@ void Draw_Slider(SDL_Renderer * renderer, Slider * beta){
|
||||
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_RenderDrawRect(renderer, &beta->Scalar_rect);
|
||||
SDL_RenderCopy(renderer, Scalar_Button_Texture0, NULL, &beta->Scalar_rect);
|
||||
}
|
||||
} /* Draw_Slider */
|
||||
|
||||
void Draw_Ballstate(SDL_Renderer * renderer, Scenery * scenery){
|
||||
BALL_Draw(renderer, &(scenery->ball));
|
||||
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->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 };
|
||||
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 = x + beta->Scalar_rect.w / 2;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
22
settings.h
@ -8,26 +8,42 @@
|
||||
#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;
|
||||
bool IsLock;
|
||||
double Slider_value,min,max;
|
||||
} Slider;
|
||||
|
||||
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,Scenery* scenery);
|
||||
|
||||
void Draw_Slider(SDL_Renderer* renderer,Slider* beta);
|
||||
|
||||
void Draw_Ballstate(SDL_Renderer* renderer,Scenery* scenery);
|
||||
void Draw_Stepslider(SDL_Renderer* renderer,Stepslider* beta);
|
||||
|
||||
void Settings_Initialize (SDL_Renderer* renderer);
|
||||
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);
|
||||
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 Settings_Return();
|
||||
|
||||
#endif
|
||||
|
21
startmenu.c
@ -6,6 +6,7 @@
|
||||
#include "main.h"
|
||||
|
||||
extern float XScale, YScale;
|
||||
extern SDL_Rect Return_Button_rect;
|
||||
|
||||
SDL_Texture * TITLE_Texture;
|
||||
SDL_Texture * PLAYBUTTON_Texture;
|
||||
@ -52,16 +53,14 @@ void Startmenu_Draw(SDL_Renderer * renderer) {
|
||||
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, &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);
|
||||
|
||||
|