Initial
This commit is contained in:
commit
62d2de747e
59 changed files with 130940 additions and 0 deletions
22
Code blocks projekt/modules/auxiliary/auxFunctions.c
Normal file
22
Code blocks projekt/modules/auxiliary/auxFunctions.c
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "auxFunctions.h"
|
||||
|
||||
|
||||
extern inline float randomWithinBorders(float base, float variance);
|
||||
extern inline int randomIntWithinBorders(int base, int variance);
|
||||
|
||||
extern inline int randomPlusOrMinus();
|
||||
|
||||
extern inline int larger(int a, int b);
|
||||
extern inline int smaller(int a, int b);
|
||||
|
||||
extern inline float largerF(float a, float b);
|
||||
extern inline float smallerF(float a, float b);
|
||||
|
||||
extern inline void putInsideInterval(int min, int* a, int max);
|
||||
extern inline void putInsideIntervalF(float min, float* a, float max);
|
||||
|
||||
extern inline float dist(int a, int b);
|
||||
extern inline float fDist(float a, float b);
|
||||
|
||||
extern inline float square(float a);
|
||||
|
||||
22
Code blocks projekt/modules/auxiliary/auxFunctions.c.save
Normal file
22
Code blocks projekt/modules/auxiliary/auxFunctions.c.save
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "auxFunctions.h"
|
||||
|
||||
|
||||
extern inline float randomWithinBorders(float base, float variance);
|
||||
extern inline int randomIntWithinBorders(int base, int variance);
|
||||
|
||||
extern inline int randomPlusOrMinus();
|
||||
|
||||
extern inline int larger(int a, int b);
|
||||
extern inline int smaller(int a, int b);
|
||||
|
||||
extern inline float largerF(float a, float b);
|
||||
extern inline float smallerF(float a, float b);
|
||||
|
||||
extern inline void putInsideInterval(int min, int* a, int max);
|
||||
extern inline void putInsideIntervalF(float min, float* a, float max);
|
||||
|
||||
extern inline float dist(int a, int b);
|
||||
extern inline float fDist(float a, float b);
|
||||
|
||||
extern inline float square(float a);
|
||||
|
||||
58
Code blocks projekt/modules/auxiliary/auxFunctions.h
Normal file
58
Code blocks projekt/modules/auxiliary/auxFunctions.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#ifndef AUXFUNCTIONS_H_INCLUDED
|
||||
#define AUXFUNCTIONS_H_INCLUDED
|
||||
|
||||
#include "../global.h"
|
||||
|
||||
inline float randomWithinBorders(float base, float variance) {
|
||||
int intVariance = (int)(1e4 * variance);
|
||||
return (1e4 * base + (rand() % (2 * intVariance + 1) - intVariance)) / 1e4;
|
||||
}
|
||||
|
||||
inline int randomIntWithinBorders(int base, int variance) {
|
||||
return base + (rand() % (2 * variance + 1) - variance);
|
||||
}
|
||||
|
||||
inline int randomPlusOrMinus() {
|
||||
return rand() % 2 ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
inline int larger(int a, int b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
inline int smaller(int a, int b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
inline float largerF(float a, float b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
inline float smallerF(float a, float b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
|
||||
inline void putInsideInterval(int min, int* a, int max) {
|
||||
*a = largerF(min, smallerF(*a, max));
|
||||
}
|
||||
|
||||
inline void putInsideIntervalF(float min, float* a, float max) {
|
||||
*a = largerF(min, smallerF(*a, max));
|
||||
}
|
||||
|
||||
|
||||
inline float dist(int a, int b) {
|
||||
return sqrt(a*a + b*b);
|
||||
}
|
||||
|
||||
inline float fDist(float a, float b) {
|
||||
return sqrt(a*a + b*b);
|
||||
}
|
||||
|
||||
inline float square(float a) {
|
||||
return a*a;
|
||||
}
|
||||
|
||||
#endif // AUXFUNCTIONS_H_INCLUDED
|
||||
64
Code blocks projekt/modules/auxiliary/auxFunctions.h.save
Normal file
64
Code blocks projekt/modules/auxiliary/auxFunctions.h.save
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#ifndef AUXFUNCTIONS_H_INCLUDED
|
||||
#define AUXFUNCTIONS_H_INCLUDED
|
||||
|
||||
#include "../global.h"
|
||||
|
||||
inline float randomWithinBorders(float base, float variance) {
|
||||
int intVariance = (int)(1e4 * variance);
|
||||
return (1e4 * base + (rand() % (2 * intVariance + 1) - intVariance)) / 1e4;
|
||||
}
|
||||
|
||||
inline int randomIntWithinBorders(int base, int variance) {
|
||||
return base + (rand() % (2 * variance + 1) - variance);
|
||||
}
|
||||
|
||||
inline int randomPlusOrMinus() {
|
||||
return rand() % 2 ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
inline int larger(int a, int b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
inline int smaller(int a, int b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
inline float largerF(float a, float b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
inline float smallerF(float a, float b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
|
||||
inline void putInsideInterval(int min, int* a, int max) {
|
||||
*a = largerF(min, smallerF(*a, max));
|
||||
}
|
||||
|
||||
inline void putInsideIntervalF(float min, float* a, float max) {
|
||||
*a = largerF(min, smallerF(*a, max));
|
||||
}
|
||||
|
||||
|
||||
inline float dist(int a, int b) {
|
||||
return sqrt(a*a + b*b);
|
||||
}
|
||||
|
||||
inline float fDist(float a, float b) {
|
||||
return sqrt(a*a + b*b);
|
||||
}
|
||||
|
||||
inline float square(float a) {
|
||||
return a*a;
|
||||
}
|
||||
|
||||
//++print + int = print xd
|
||||
inline void print(int a) {
|
||||
printf("%d\n", a);
|
||||
}
|
||||
|
||||
|
||||
#endif // AUXFUNCTIONS_H_INCLUDED
|
||||
73
Code blocks projekt/modules/auxiliary/auxSDL.c
Normal file
73
Code blocks projekt/modules/auxiliary/auxSDL.c
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#include "auxSDL.h"
|
||||
|
||||
mousePos mouse; /**< Az egér koordinátáit tárolja, így egyszerűbb, mint közvetlen az eventek figyelése. */
|
||||
|
||||
|
||||
/** \brief https://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlcreatecursor.html
|
||||
* Hogy erre miért van szükség, az egy nagyon jó kérdés. Ha ehelyett a "SDL_ShowCursor(SDL_DISABLE);"-t
|
||||
* használnám az egér random ugrálna néha néha, így viszont ezt nem teszi.
|
||||
*/
|
||||
static SDL_Cursor* createCursor() {
|
||||
Uint8 data[4*32] = {0};
|
||||
Uint8 mask[4*32] = {0};
|
||||
return SDL_CreateCursor(data, mask, 32, 32, 0, 0);
|
||||
}
|
||||
|
||||
/** \brief Létrehozza a játék futtatásához szükséges környezetet.
|
||||
* Megnézi az elérhető legnagyobb felbontást, azzal a felbontással létrehoz egy ablakot, illetve
|
||||
* meghív pár, az inicializáláshoz szükséges függvényt.
|
||||
* \return kurzor amit fel kell később szabadítanunk
|
||||
*/
|
||||
SDL_Cursor* openWindow() {
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
||||
SDL_Rect** screenSizes = SDL_ListModes(NULL, SDL_FULLSCREEN);
|
||||
|
||||
screen = SDL_SetVideoMode(screenSizes[0] -> w, screenSizes[0] -> h, 0, SDL_FULLSCREEN);
|
||||
|
||||
if (!screen) {
|
||||
fprintf(stderr, "Nem sikerult megnyitni az ablakot!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SDL_WM_SetCaption("Platform játék", "Schmelczer András: Platform játék");
|
||||
SDL_Cursor* cursor = createCursor();
|
||||
SDL_SetCursor(cursor);
|
||||
openFonts();
|
||||
SDL_WM_GrabInput(SDL_GRAB_FULLSCREEN);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
///A játék időzítéséhez szükséges.
|
||||
Uint32 timer(Uint32 ms, void* param) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_USEREVENT;
|
||||
SDL_PushEvent(&event);
|
||||
return ms;
|
||||
}
|
||||
|
||||
///Frissití az egér pozicióját.
|
||||
void setMousePosition(Uint16 x, Uint16 y) {
|
||||
mouse.x = x;
|
||||
mouse.y = y;
|
||||
}
|
||||
|
||||
///Visszaadja az egérpoziciót.
|
||||
mousePos getMousePosition() {
|
||||
return mouse;
|
||||
}
|
||||
|
||||
///Lerajzolja a képernyőre az egeret, erre azért van szükség, mert az SDL csak fekete-fehér egérmutatót kezel.
|
||||
void drawMouse(bool isBW) {
|
||||
Sint16 x1 = mouse.x - mouseSize / 2;
|
||||
Sint16 x2 = mouse.x + mouseSize / 2;
|
||||
Sint16 y1 = mouse.y - mouseSize / 2;
|
||||
Sint16 y2 = mouse.y + mouseSize / 2;
|
||||
boxColor(screen, x1, y1, x2, y2, isBW ? 0x7F7F7FFF : 0xFFFF00FF);
|
||||
}
|
||||
|
||||
///Egy téglalap felett van-e az egérmutató közepe?
|
||||
bool isMouseOverRect(int xCenter, int yCenter, int xSize, int ySize) {
|
||||
return
|
||||
screen -> w / 100.0 * (xCenter - xSize) < mouse.x && mouse.x < screen -> w / 100.0 * (xCenter + xSize) &&
|
||||
screen -> h / 100.0 * (yCenter - ySize) < mouse.y && mouse.y < screen -> h / 100.0 * (yCenter + ySize);
|
||||
}
|
||||
80
Code blocks projekt/modules/auxiliary/auxSDL.c.save
Normal file
80
Code blocks projekt/modules/auxiliary/auxSDL.c.save
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#include "auxSDL.h"
|
||||
|
||||
mousePos mouse; /**< Az egér koordinátáit tárolja, így egyszerűbb, mint közvetlen az eventek figyelése. */
|
||||
|
||||
|
||||
/** \brief https://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlcreatecursor.html
|
||||
* Hogy erre miért van szükség, az egy nagyon jó kérdés. Ha ehelyett a "SDL_ShowCursor(SDL_DISABLE);"-t
|
||||
* használnám az egér random ugrálna néha néha, így viszont ezt nem teszi.
|
||||
*/
|
||||
static SDL_Cursor* createCursor() {
|
||||
Uint8 data[4*32] = {0};
|
||||
Uint8 mask[4*32] = {0};
|
||||
return SDL_CreateCursor(data, mask, 32, 32, 0, 0);
|
||||
}
|
||||
|
||||
/** \brief Létrehozza a játék futtatásához szükséges környezetet.
|
||||
* Megnézi az elérhető legnagyobb felbontást, azzal a felbontással létrehoz egy ablakot, illetve
|
||||
* meghív pár, az inicializáláshoz szükséges függvényt.
|
||||
* \return kurzor amit fel kell később szabadítanunk
|
||||
*/
|
||||
SDL_Cursor* openWindow() {
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
||||
SDL_Rect** screenSizes = SDL_ListModes(NULL, SDL_FULLSCREEN);
|
||||
|
||||
screen = SDL_SetVideoMode(screenSizes[0] -> w, screenSizes[0] -> h, 0, SDL_FULLSCREEN);
|
||||
|
||||
if (!screen) {
|
||||
fprintf(stderr, "Nem sikerult megnyitni az ablakot!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SDL_WM_SetCaption("Platform játék", "Schmelczer András: Platform játék");
|
||||
SDL_Cursor* cursor = createCursor();
|
||||
SDL_SetCursor(cursor);
|
||||
openFonts();
|
||||
SDL_WM_GrabInput(SDL_GRAB_FULLSCREEN);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
///A játék időzítéséhez szükséges.
|
||||
Uint32 timer(Uint32 ms, void* param) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_USEREVENT;
|
||||
SDL_PushEvent(&event);
|
||||
return ms;
|
||||
}
|
||||
|
||||
///Frissití az egér pozicióját.
|
||||
void setMousePosition(Uint16 x, Uint16 y) {
|
||||
mouse.x = x;
|
||||
mouse.y = y;
|
||||
}
|
||||
|
||||
///Visszaadja az egérpoziciót.
|
||||
mousePos getMousePosition() {
|
||||
return mouse;
|
||||
}
|
||||
|
||||
///Lerajzolja a képernyőre az egeret, erre azért van szükség, mert az SDL csak fekete-fehér egérmutatót kezel.
|
||||
void drawMouse(bool isBW) {
|
||||
Sint16 x1 = mouse.x - mouseSize / 2;
|
||||
Sint16 x2 = mouse.x + mouseSize / 2;
|
||||
Sint16 y1 = mouse.y - mouseSize / 2;
|
||||
Sint16 y2 = mouse.y + mouseSize / 2;
|
||||
boxColor(screen, x1, y1, x2, y2, isBW ? 0x7F7F7FFF : 0xFFFF00FF);
|
||||
}
|
||||
|
||||
bool isMouseOver(int yStart, int ySize, int y) {
|
||||
|
||||
return
|
||||
(float) screen -> h / 100 * (yStart + (y - 0.5) * ySize) < mouse.y &&
|
||||
mouse.y < (float) screen -> h / 100 * (yStart + (y + 0.5) * ySize);
|
||||
}
|
||||
|
||||
///Egy téglalap felett van-e az egérmutató közepe?
|
||||
bool isMouseOverRect(int xCenter, int yCenter, int xSize, int ySize) {
|
||||
return
|
||||
screen -> w / 100.0 * (xCenter - xSize) < mouse.x && mouse.x < screen -> w / 100.0 * (xCenter + xSize) &&
|
||||
screen -> h / 100.0 * (yCenter - ySize) < mouse.y && mouse.y < screen -> h / 100.0 * (yCenter + ySize);
|
||||
}
|
||||
20
Code blocks projekt/modules/auxiliary/auxSDL.h
Normal file
20
Code blocks projekt/modules/auxiliary/auxSDL.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef AUXSDL_H_INCLUDED
|
||||
#define AUXSDL_H_INCLUDED
|
||||
|
||||
#include "../global.h"
|
||||
#include "unicodePrint.h"
|
||||
|
||||
#define mouseSize 20 /**< Az egérmutató négyzetnek az oldalhosszusága. */
|
||||
|
||||
typedef struct mousePos {
|
||||
Uint16 x, y;
|
||||
} mousePos;
|
||||
|
||||
SDL_Cursor* openWindow();
|
||||
Uint32 timer(Uint32 ms, void* param);
|
||||
void setMousePosition(Uint16 x, Uint16 y);
|
||||
mousePos getMousePosition();
|
||||
void drawMouse(bool isBW);
|
||||
bool isMouseOverRect(int xCenter, int yCenter, int xSize, int ySize);
|
||||
|
||||
#endif // AUXSDL_H_INCLUDED
|
||||
21
Code blocks projekt/modules/auxiliary/auxSDL.h.save
Normal file
21
Code blocks projekt/modules/auxiliary/auxSDL.h.save
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef AUXSDL_H_INCLUDED
|
||||
#define AUXSDL_H_INCLUDED
|
||||
|
||||
#include "../global.h"
|
||||
#include "unicodePrint.h"
|
||||
|
||||
#define mouseSize 20 /**< Az egérmutató négyzetnek az oldalhosszusága. */
|
||||
|
||||
typedef struct mousePos {
|
||||
Uint16 x, y;
|
||||
} mousePos;
|
||||
|
||||
SDL_Cursor* openWindow();
|
||||
Uint32 timer(Uint32 ms, void* param);
|
||||
void setMousePosition(Uint16 x, Uint16 y);
|
||||
mousePos getMousePosition();
|
||||
void drawMouse(bool isBW);
|
||||
bool isMouseOver(int yStart, int ySize, int y);
|
||||
bool isMouseOverRect(int xCenter, int yCenter, int xSize, int ySize);
|
||||
|
||||
#endif // AUXSDL_H_INCLUDED
|
||||
84
Code blocks projekt/modules/auxiliary/unicodePrint.c
Normal file
84
Code blocks projekt/modules/auxiliary/unicodePrint.c
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#include "unicodePrint.h"
|
||||
|
||||
|
||||
///Indításnál betölti a szükséges betűtípusokat.
|
||||
void openFonts() {
|
||||
SDL_EnableUNICODE(1);
|
||||
TTF_Init();
|
||||
fontSmaller = TTF_OpenFont("resources/Roboto-Thin.ttf", 40);
|
||||
fontSmall = TTF_OpenFont("resources/Roboto-Thin.ttf", 48);
|
||||
fontSmallBold = TTF_OpenFont("resources/Roboto-Light.ttf", 53);
|
||||
fontLarge = TTF_OpenFont("resources/Roboto-Thin.ttf", 120);
|
||||
}
|
||||
|
||||
///Ha már nem kellenek, felszabadítja a betűtípusokat.
|
||||
void freeFonts() {
|
||||
TTF_CloseFont(fontSmaller);
|
||||
TTF_CloseFont(fontSmall);
|
||||
TTF_CloseFont(fontSmallBold);
|
||||
TTF_CloseFont(fontLarge);
|
||||
}
|
||||
|
||||
///Itt tárolom a használható karaktereket. Eldönti, hogy a bemenet köztük van-e.
|
||||
bool isValidChar(Uint16 chr) {
|
||||
if(('A' <= chr && chr <= 'Z') || ('a' <= chr && chr <= 'z') || ('0' <= chr && chr <= '9')) return true;
|
||||
|
||||
Uint16 validChars[] = L"öüóőúéáűíÖÜÓŐÚÉÁŰÍ|€ß$Łł¤<>#&@{}Đ[]đ+!%=×)(.- ";
|
||||
int i;
|
||||
for(i = 0; validChars[i] != 0; i++) if(chr == validChars[i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
///Az egyszerűbb kezelhetőség miatt kell. Visszadja az enumhoz tartozó ttf-et.
|
||||
TTF_Font* selectFont(fontType fontType) {
|
||||
switch(fontType) {
|
||||
case tiny:
|
||||
return fontSmaller;
|
||||
case small:
|
||||
return fontSmall;
|
||||
case smallBold:
|
||||
return fontSmallBold;
|
||||
case large:
|
||||
default:
|
||||
return fontLarge;
|
||||
}
|
||||
}
|
||||
|
||||
///A százalékot a képernyő mérete alapján átváltja pixelekre.
|
||||
Sint16 percentageToPx(int percentage, bool isWidth) {
|
||||
return (int)((float)percentage/100 * (isWidth ? screen -> w: screen -> h));
|
||||
}
|
||||
|
||||
/** \brief Uint16-ból álló stringet összefűz.
|
||||
* A két paramétert egy harmadik dinamikusan foglalt stringben fűzi össze.
|
||||
* \param string eleje
|
||||
* \param string vége
|
||||
* \return string konkatenált
|
||||
*/
|
||||
Uint16* concatUnicode(const Uint16 a[], const Uint16 b[]) {
|
||||
int aLength, bLength;
|
||||
for(aLength = 0; a[aLength] != 0; aLength++)
|
||||
;
|
||||
for(bLength = 0; b[bLength] != 0; bLength++)
|
||||
;
|
||||
|
||||
Uint16* newStr = (Uint16*) malloc((aLength + bLength - 1 + 100) * sizeof(Uint16));
|
||||
int i = 0, ai, bi;
|
||||
for(ai = 0; ai < aLength; ai++)
|
||||
newStr[i++] = a[ai];
|
||||
for(bi = 0; bi < bLength; bi++)
|
||||
newStr[i++] = b[bi];
|
||||
newStr[i] = 0;
|
||||
|
||||
return newStr;
|
||||
}
|
||||
|
||||
///A megjelenítendő szöveg közepét kell megadni x,y-ként. A szöveget Uint16*-ban, a betűtipust pedig a betűtipus enumból. Ugyan mindent x = 50-nel hívunk meg, ez később változhat, ezért hagyom meg paraméternek.
|
||||
void unicodePrintCentered(Uint16 textToWrite[], int x, int y, fontType fontType) {
|
||||
TTF_Font* currentFont = selectFont(fontType);
|
||||
SDL_FreeSurface(text);
|
||||
text = TTF_RenderUNICODE_Blended(currentFont, textToWrite, (SDL_Color) {255, 255, 255});
|
||||
SDL_BlitSurface(text, NULL, screen, &(SDL_Rect){percentageToPx(x, true) - text -> w / 2, percentageToPx(y, false) - text -> h / 2, 0, 0});
|
||||
}
|
||||
84
Code blocks projekt/modules/auxiliary/unicodePrint.c.save
Normal file
84
Code blocks projekt/modules/auxiliary/unicodePrint.c.save
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#include "unicodePrint.h"
|
||||
|
||||
|
||||
///Indításnál betölti a szükséges betűtípusokat.
|
||||
void openFonts() {
|
||||
SDL_EnableUNICODE(1);
|
||||
TTF_Init();
|
||||
fontSmaller = TTF_OpenFont("resources/Roboto-Thin.ttf", 40);
|
||||
fontSmall = TTF_OpenFont("resources/Roboto-Thin.ttf", 48);
|
||||
fontSmallBold = TTF_OpenFont("resources/Roboto-Light.ttf", 53);
|
||||
fontLarge = TTF_OpenFont("resources/Roboto-Thin.ttf", 120);
|
||||
}
|
||||
|
||||
///Ha már nem kellenek, felszabadítja a betűtípusokat.
|
||||
void freeFonts() {
|
||||
TTF_CloseFont(fontSmaller);
|
||||
TTF_CloseFont(fontSmall);
|
||||
TTF_CloseFont(fontSmallBold);
|
||||
TTF_CloseFont(fontLarge);
|
||||
}
|
||||
|
||||
///Itt tárolom a használható karaktereket. Eldönti, hogy a bemenet köztük van-e.
|
||||
bool isValidChar(Uint16 chr) {
|
||||
if(('A' <= chr && chr <= 'Z') || ('a' <= chr && chr <= 'z') || ('0' <= chr && chr <= '9')) return true;
|
||||
|
||||
Uint16 validChars[] = L"öüóőúéáűíÖÜÓŐÚÉÁŰÍ|€ß$Łł¤<>#&@{}Đ[]đ+!%=×)(.- ";
|
||||
int i;
|
||||
for(i = 0; validChars[i] != 0; i++) if(chr == validChars[i])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
///Az egyszerűbb kezelhetőség miatt kell. Visszadja az enumhoz tartozó ttf-et.
|
||||
TTF_Font* selectFont(fontType fontType) {
|
||||
switch(fontType) {
|
||||
case tiny:
|
||||
return fontSmaller;
|
||||
case small:
|
||||
return fontSmall;
|
||||
case smallBold:
|
||||
return fontSmallBold;
|
||||
case large:
|
||||
default:
|
||||
return fontLarge;
|
||||
}
|
||||
}
|
||||
|
||||
///A százalékot a képernyő mérete alapján átváltja pixelekre.
|
||||
Sint16 percentageToPx(int percentage, bool isWidth) {
|
||||
return (int)((float)percentage/100 * (isWidth ? screen -> w: screen -> h));
|
||||
}
|
||||
|
||||
/** \brief Uint16-ból álló stringet összefűz.
|
||||
* A két paramétert egy harmadik dinamikusan foglalt stringben fűzi össze.
|
||||
* \param string eleje
|
||||
* \param string vége
|
||||
* \return string konkatenált
|
||||
*/
|
||||
Uint16* concatUnicode(const Uint16 a[], const Uint16 b[]) {
|
||||
int aLength, bLength;
|
||||
for(aLength = 0; a[aLength] != 0; aLength++)
|
||||
;
|
||||
for(bLength = 0; b[bLength] != 0; bLength++)
|
||||
;
|
||||
|
||||
Uint16* newStr = (Uint16*) malloc((aLength + bLength - 1 + 100) * sizeof(Uint16));
|
||||
int i = 0, ai, bi;
|
||||
for(ai = 0; ai < aLength; ai++)
|
||||
newStr[i++] = a[ai];
|
||||
for(bi = 0; bi < bLength; bi++)
|
||||
newStr[i++] = b[bi];
|
||||
newStr[i] = 0;
|
||||
|
||||
return newStr;
|
||||
}
|
||||
|
||||
///A megjelenítendő szöveg közepét kell megadni x,y-ként. A szöveget Uint16*-ban, a betűtipust pedig a betűtipus enumból. Ugyan mindent x = 50-nel hívunk meg, ez később változhat, ezért hagyom meg paraméternek.
|
||||
void unicodePrintCentered(Uint16 textToWrite[], int x, int y, fontType fontType) {
|
||||
TTF_Font* currentFont = selectFont(fontType);
|
||||
SDL_FreeSurface(text);
|
||||
text = TTF_RenderUNICODE_Blended(currentFont, textToWrite, (SDL_Color) {255, 255, 255});
|
||||
SDL_BlitSurface(text, NULL, screen, &(SDL_Rect){percentageToPx(x, true) - text -> w / 2, percentageToPx(y, false) - text -> h / 2, 0, 0});
|
||||
}
|
||||
16
Code blocks projekt/modules/auxiliary/unicodePrint.h
Normal file
16
Code blocks projekt/modules/auxiliary/unicodePrint.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef UNICODEPRINT_H_INCLUDED
|
||||
#define UNICODEPRINT_H_INCLUDED
|
||||
|
||||
#include "../global.h"
|
||||
|
||||
typedef enum fontType {
|
||||
tiny, small, smallBold, large
|
||||
} fontType;
|
||||
|
||||
void openFonts();
|
||||
void freeFonts();
|
||||
bool isValidChar(Uint16 chr);
|
||||
Uint16* concatUnicode(const Uint16 a[], const Uint16 b[]);
|
||||
void unicodePrintCentered(Uint16 textToWrite[], int x, int y, fontType fontType);
|
||||
|
||||
#endif // UNICODEPRINT_H_INCLUDED
|
||||
16
Code blocks projekt/modules/auxiliary/unicodePrint.h.save
Normal file
16
Code blocks projekt/modules/auxiliary/unicodePrint.h.save
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef UNICODEPRINT_H_INCLUDED
|
||||
#define UNICODEPRINT_H_INCLUDED
|
||||
|
||||
#include "../global.h"
|
||||
|
||||
typedef enum fontType {
|
||||
tiny, small, smallBold, large
|
||||
} fontType;
|
||||
|
||||
void openFonts();
|
||||
void freeFonts();
|
||||
bool isValidChar(Uint16 chr);
|
||||
Uint16* concatUnicode(const Uint16 a[], const Uint16 b[]);
|
||||
void unicodePrintCentered(Uint16 textToWrite[], int x, int y, fontType fontType);
|
||||
|
||||
#endif // UNICODEPRINT_H_INCLUDED
|
||||
326
Code blocks projekt/modules/camera.c
Normal file
326
Code blocks projekt/modules/camera.c
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
#include "camera.h"
|
||||
|
||||
#define focalLength 0.05 /**< gyújtótáv [m] */
|
||||
#define sensorSize 0.07 /**< szenzor hosszabb oldalának a fele [m] */
|
||||
#define renderObjectsPerCube 10 /**< max( (projectile + player + enemy) / m^3), erről később bővebben. */
|
||||
|
||||
vector3D cameraPosition; /**< A kamera térbeli helyvektora. */
|
||||
float magnification, columns, rows; /**< Ennyi látszik a pályából [m]. */
|
||||
bool watchBounds = false; /**< Feldarabolós rajzolás van-e? */
|
||||
float leftBound, rightBound, upperBound, lowerBound; /**< Darabolás határai. */
|
||||
int leftMostBound, rightMostBound, topBound, bottomBound;
|
||||
renderObject*** renderMap = NULL; /**< Darabolás mátrixa. */
|
||||
|
||||
|
||||
///A feldarabolós rajzoláshoz szükséges mátrixot szabadítja fel.
|
||||
void freeRenderMap() {
|
||||
if(renderMap != NULL) {
|
||||
free(renderMap[0][0]);
|
||||
free(renderMap[0]);
|
||||
free(renderMap);
|
||||
}
|
||||
}
|
||||
|
||||
///A feldarabolós rajzoláshoz szükséges mátrixot mallocolja.
|
||||
static void initRenderMap() {
|
||||
renderMap = (renderObject***) malloc(sizeof(renderObject**));
|
||||
renderMap[0] = (renderObject**) malloc(sizeof(renderObject*));
|
||||
renderMap[0][0] = (renderObject*) malloc(sizeof(renderObject));
|
||||
}
|
||||
|
||||
/** \brief Kiszámolja a kamera poziciója és a képernyő mérete alapján, hogy mennyi látszik a pályából.
|
||||
*
|
||||
* Elsősorban ezeket a változókat változtatja:
|
||||
* columns, rows = képernyőn megjelenő oszlopok és sorok száma,
|
||||
* magnification = megmondja egy méter a kamera "szenzorán" hány pixelnek felel meg (jó soknak)
|
||||
*
|
||||
* Hasonló háromszögek alapján kiszámolja mennyi látszik a pályából:
|
||||
* sensor size
|
||||
* |
|
||||
* V
|
||||
* ----
|
||||
* \ |
|
||||
* \ | <- focalLength
|
||||
* \|
|
||||
* |
|
||||
* |\
|
||||
* | \
|
||||
* Z -> | \
|
||||
* | \
|
||||
* | \
|
||||
* -------------
|
||||
* columns
|
||||
*
|
||||
* Ezek alapján reallocolja a darabolós mátrixot.
|
||||
*
|
||||
*/
|
||||
static void calculateRowsAndColumns() {
|
||||
magnification = (float) screen -> w / 2 / sensorSize;
|
||||
columns = 2 * cameraPosition.z * sensorSize / focalLength;
|
||||
//hogy a négyzet négyzet is maradjon
|
||||
rows = (float)screen -> h / screen -> w * columns;
|
||||
|
||||
if(renderMap == NULL) initRenderMap();
|
||||
|
||||
int xSize = (int)columns + 4; //a nagyobb testek átlóghatnak a képernyő határán
|
||||
int ySize = (int)rows + 4;
|
||||
int iSize = renderObjectsPerCube;
|
||||
|
||||
renderObject* innerTmp = (renderObject*) realloc(renderMap[0][0], xSize * ySize * iSize * sizeof(renderObject));
|
||||
renderObject** outerTmp = (renderObject**) realloc(renderMap[0], xSize * ySize * sizeof(renderObject*));
|
||||
renderMap = (renderObject***) realloc(renderMap, xSize * sizeof(renderObject**));
|
||||
|
||||
renderMap[0] = outerTmp;
|
||||
|
||||
int x;
|
||||
for(x = 1; x < xSize; x++)
|
||||
renderMap[x] = renderMap[0] + x * ySize;
|
||||
|
||||
renderMap[0][0] = innerTmp;
|
||||
|
||||
renderObject empty;
|
||||
empty.doesExist = false;
|
||||
|
||||
int y, i = 0;
|
||||
int j;
|
||||
for(x = 0; x < xSize; x++)
|
||||
for(y = 0; y < ySize; y++) {
|
||||
renderMap[x][y] = renderMap[0][0] + i++ * iSize;
|
||||
for(j = 0; j < iSize; j++) renderMap[x][y][j] = empty;
|
||||
}
|
||||
}
|
||||
|
||||
///A játékost követi a kamerával, nem hagyja, hogy a pálya alá lásson.
|
||||
void followPlayerWithCamera() {
|
||||
renderObject player = getPlayerRenderObject();
|
||||
cameraPosition.x = (2 * player.position.x + player.size.x) / 2;
|
||||
cameraPosition.y = (player.position.y < rows / 2 ? rows / 2 : player.position.y) + 1;
|
||||
}
|
||||
|
||||
///A menüben használt kamerát állítja be, visszaadja a columns-t és rows-t is.
|
||||
void menuCamera(int* getColumns, int* getRows) {
|
||||
cameraPosition.z = cameraDeltaZDistanceStart;
|
||||
calculateRowsAndColumns();
|
||||
*getColumns = columns;
|
||||
*getRows = rows;
|
||||
cameraPosition.x = columns / 2;
|
||||
cameraPosition.y = rows / 2;
|
||||
}
|
||||
|
||||
///Visszaadja, hogy hány oszlop látszik a pályából.
|
||||
int getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
/** \brief A kamera dollyzását végzi, a kamerát mozgatja
|
||||
* A dolly állását staticban tárolja, ezért új dolly eseteén először egy restart = true-val kell meghívni,
|
||||
* \param ms eltelt idő
|
||||
* \param kell-e újrakezdés?
|
||||
* \return elérte-e a végállást?
|
||||
* Minden frameban újraszámolja a rows&coulmns-t,
|
||||
*/
|
||||
bool cameraDollyZ(int deltaTime, bool restart) {
|
||||
static int timePassed;
|
||||
if(restart) timePassed = 0;
|
||||
|
||||
bool done = true;
|
||||
|
||||
timePassed += deltaTime;
|
||||
|
||||
float t = (float)(cameraDollyTime - timePassed) / cameraDollyTime;
|
||||
float cube = t*t*t;
|
||||
|
||||
float currentZ = cameraDeltaZDistanceEnd + (cameraDeltaZDistanceStart - cameraDeltaZDistanceEnd) * cube;
|
||||
|
||||
if(currentZ <= cameraDeltaZDistanceEnd) {
|
||||
currentZ = cameraDeltaZDistanceEnd;
|
||||
done = false;
|
||||
}
|
||||
|
||||
cameraPosition.z = currentZ;
|
||||
calculateRowsAndColumns();
|
||||
return done;
|
||||
}
|
||||
|
||||
/** \brief Térbeli pontból síkbelit képez.
|
||||
* A 3D-s pont koordinátái és a kamera alapján kiszámolja, hogy a kamera 2D-s szenzorán hol jelenik meg a pont.
|
||||
* Geometriailag leírva, a két ponton (point, cameraPosition) átmenő egyenes egyenletének, és a 'szenzor' vízszintesének metszéspontja
|
||||
* a keresett pontunk. A lent és a linken is látható egyenletet először a tér x-z, majd az y-z vetületére alkalmazzuk,
|
||||
* és megkapjuk a térbeli pontunk megfelelő síkbeli leképezést.
|
||||
* Ez interaktívan ábrázolva így néz ki: https://www.desmos.com/calculator/8qjvkptjmn
|
||||
* \param Térvektor típusú pont
|
||||
* \return Síkvektor típusú pont
|
||||
* A visszaadott pontnak int koordinátái vannak, hiszen valamelyik pixel koordinátáit jelöli.
|
||||
* Ez a függvény igazából egy camera obscura modellje.
|
||||
*/
|
||||
intVector2D get2DPoint(vector3D point) {
|
||||
//Ha watchBounds = true, csak egy megadott kockán belül adja vissza az értéket (rajzol), ez a feldarabolás miatt fontos
|
||||
if(watchBounds) {
|
||||
putInsideIntervalF(leftBound, &point.x, rightBound);
|
||||
putInsideIntervalF(lowerBound, &point.y, upperBound);
|
||||
}
|
||||
|
||||
//Ezt a két kifejezést újra felhasználjuk
|
||||
float zDist = point.z - cameraPosition.z;
|
||||
float zDistFromHole = zDist - focalLength;
|
||||
float dx = (cameraPosition.x * zDistFromHole + focalLength * point.x) / zDist - cameraPosition.x;
|
||||
float dy = (cameraPosition.y * zDistFromHole + focalLength * point.y) / zDist - cameraPosition.y;
|
||||
|
||||
//Megfelelően tükrözzük a kapot pontot, és a méterben kapott értéket átváltjuk pixelekre
|
||||
intVector2D resultPoint = {
|
||||
(int)(screen -> w / 2 - magnification * dx),
|
||||
(int)(screen -> h / 2 + magnification * dy)
|
||||
};
|
||||
|
||||
return resultPoint;
|
||||
}
|
||||
|
||||
/** \brief Lerajzol egy négyszöget
|
||||
* A bemenetként kapott 4 pont alkotta négyszöget rajzolja ki.
|
||||
* \param síkvektor a csúcshoz
|
||||
* \param síkvektor b csúcshoz
|
||||
* \param síkvektor c csúcshoz
|
||||
* \param síkvektor d csúcshoz
|
||||
* \param szín négyszög színe
|
||||
* Ezt egyszer kitöltéssel csinálja, egyszer pedig anti-aliasing poligonnal,
|
||||
* hogy a rajz széle ne legyen recegős.
|
||||
*/
|
||||
static void drawTetragon(intVector2D a, intVector2D b, intVector2D c, intVector2D d, color color) {
|
||||
Sint16 xCoords[4] = {(Sint16)a.x, (Sint16)b.x, (Sint16)c.x, (Sint16)d.x};
|
||||
Sint16 yCoords[4] = {(Sint16)a.y, (Sint16)b.y, (Sint16)c.y, (Sint16)d.y};
|
||||
|
||||
filledPolygonRGBA(screen, xCoords, yCoords, 4, color.r, color.g, color.b, color.a);
|
||||
aapolygonRGBA(screen, xCoords, yCoords, 4, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
/** \brief Lerajzol egy téglatestet
|
||||
* A kamera modul lényege, a rajzolást végzi el az eddigi függvények segítségével.
|
||||
* \param test téglatest adatai
|
||||
* \param bool melyik oldalakat kell rajzolni?
|
||||
* Végez egy plusz ellenőrést is, nem csak a paraméterben megadott tömb alapján nem rajzol oldalakat,
|
||||
* azokat se rajzolja le, amiket a helyzetük miatt biztosan nem láthat a kamera.
|
||||
*/
|
||||
void drawCuboid(renderObject object, bool sides[]) {
|
||||
intVector2D vertexes[8];
|
||||
//A téglatestet bejárva megkeressük a csúcsait
|
||||
int i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
vertexes[i] = get2DPoint(object.position);
|
||||
switch(i % 4) {
|
||||
case 0:
|
||||
object.position.x += object.size.x;
|
||||
break;
|
||||
case 1:
|
||||
object.position.y += object.size.y;
|
||||
break;
|
||||
case 2:
|
||||
object.position.x -= object.size.x;
|
||||
break;
|
||||
case 3:
|
||||
object.position.y -= object.size.y;
|
||||
}
|
||||
if(i == 3) object.position.z += object.size.z;
|
||||
}
|
||||
|
||||
//alja
|
||||
if(sides[0] && object.position.y > cameraPosition.y) drawTetragon(vertexes[0], vertexes[4], vertexes[5], vertexes[1], object.colors.dark);
|
||||
//bal oldali lap
|
||||
if(sides[1] && object.position.x > cameraPosition.x) drawTetragon(vertexes[0], vertexes[3], vertexes[7], vertexes[4], object.colors.dark);
|
||||
//jobb oldali lap
|
||||
if(sides[2] && object.position.x + object.size.x < cameraPosition.x) drawTetragon(vertexes[1], vertexes[2], vertexes[6], vertexes[5], object.colors.dark);
|
||||
//teteje
|
||||
if(sides[3] && object.position.y + object.size.y < cameraPosition.y) drawTetragon(vertexes[3], vertexes[7], vertexes[6], vertexes[2], object.colors.light);
|
||||
//eleje
|
||||
if(sides[4]) drawTetragon(vertexes[4], vertexes[5], vertexes[6], vertexes[7], object.colors.normal);
|
||||
}
|
||||
|
||||
/// Az egy m^3-ben lévő testeket rajzolja le
|
||||
static void drawPlace(int x, int* y, int direction, int bound) {
|
||||
bool sides[5] = {true, true, true, true, true};
|
||||
|
||||
renderObject toDraw = getBlockRenderObject(x, y, direction, bound, sides);
|
||||
if(toDraw.doesExist) {
|
||||
watchBounds = false;
|
||||
drawCuboid(toDraw, sides);
|
||||
watchBounds = true;
|
||||
}
|
||||
else {
|
||||
int i = 0;
|
||||
toDraw = renderMap[x - leftMostBound][*y - bottomBound][i];
|
||||
while(toDraw.doesExist && i < renderObjectsPerCube) {
|
||||
drawCuboid(toDraw, sides);
|
||||
i++;
|
||||
toDraw = renderMap[x - leftMostBound][*y - bottomBound][i];
|
||||
}
|
||||
|
||||
renderObject player = getPlayerRenderObject();
|
||||
|
||||
if(
|
||||
(x == (int)floor(player.position.x) || x == (int)floor(player.position.x + player.size.x)) &&
|
||||
(*y == (int)floor(player.position.y) || *y == (int)floor(player.position.y + player.size.y))
|
||||
)
|
||||
drawCuboid(player, sides);
|
||||
}
|
||||
}
|
||||
|
||||
///Az egy oszlopban lévő testeket rajzolja le, a részecskéket mozgatja közvetlen
|
||||
static void drawY(int deltaTime, int x) {
|
||||
int y;
|
||||
|
||||
for(y = topBound; y > cameraPosition.y; y--) {
|
||||
upperBound = y + 1;
|
||||
lowerBound = y;
|
||||
drawPlace(x, &y, -1, (int)cameraPosition.y);
|
||||
}
|
||||
for(y = bottomBound; y <= cameraPosition.y; y++) {
|
||||
upperBound = y + 1;
|
||||
lowerBound = y;
|
||||
drawPlace(x, &y, 1, (int)cameraPosition.y + 1);
|
||||
}
|
||||
watchBounds = false;
|
||||
drawParticles(x, bottomBound, topBound, deltaTime);
|
||||
watchBounds = true;
|
||||
}
|
||||
|
||||
/** \brief Lerajzolja a teljes látható játékteret.
|
||||
* A megfelelő rajzoláshoz figyelni kell a testek takarására, nem mindegy ezért, hogy milyen sorrendben rajzoljuk őket.
|
||||
* A részecskéknél ezzel nincs probléma, azokat bármilyen sorrendben rajzolhatjuk. Ők a játékteret kitakarják, egymásnál viszont nem látszik,
|
||||
* hogy melyik takrja melyiket, ezért azokat elég a játéktér után bármilyen sorrendben lerajzolni.
|
||||
* A térképet alkotó kockáknál már nem ilyen egyszeű a helyzet. Azokat 4 irányból kell rajzolni, bal lentről, jobb lentről, bal fentről, illetve jobb fentről középre.
|
||||
* Ha ebben a négy lépésben rajzoljuk őket (ezek között a sorrend nem számít) akkor mindig a legfesőket rajzoljuk utoljára, és így valósnak néz ki az eredmény.
|
||||
* A játékos, a lövedékek, illetve az ellenségek viszont sajnos nincsenek egy négyzethálóhoz kötve. Így gyakran megesik, hogy az egyik felüket a pálya
|
||||
* egyik kockája előtt, a másikat pedig az után, de még a kövektező előtt kéne rajzolni. Ezt nem tudjuk megcsinálni, hatalmas erőforrásba kerülne ez a majdnem pixelről
|
||||
* pixelre történő szkennelés. A pályát továbbra is m^3-ént szeretnénk lerajzolni. Hogy ez megfelelően nézzen ki, minden köbméterben csak az abban a kockában lévő dolgokat
|
||||
* szeretnénk megrajzolni. Ehhez fel kell "darabolnunk" a játékost, a lövedékeket, illetve az ellenségeket is. A darabolás azt jelenti, hogy egy mátrix minden cellájába
|
||||
* beírjuk, hogy az adott kockában melyik, milyen tulajdonsággal rendelkező testek lógnak be. Rajzolásnál pedig a testeknek mindig csak az adott kockabeli részét rajzoljuk le.
|
||||
* Mivel a kockákat jó sorrendben rajzoljuk, így a bennük levő "testekrészeket" is jó sorrendbe fogjuk rajzolni. A problémát megoldottuk.
|
||||
* \param ms eltelt idő
|
||||
* Ez a függvény elvégzi a részecskék, a pálya, illetve minden más test rajzolását is. A részecskék mozgatása innen van meghívva.
|
||||
*/
|
||||
void drawMap(int deltaTime) {
|
||||
leftMostBound = (int)(cameraPosition.x - (float)columns / 2) - 1;
|
||||
rightMostBound = (int)(cameraPosition.x + (float)columns / 2) + 1;
|
||||
topBound = (int)(cameraPosition.y + (float)rows / 2 + 1);
|
||||
bottomBound = (int)(cameraPosition.y - (float)rows / 2 - 1);
|
||||
|
||||
int y, x;
|
||||
|
||||
for(x = leftMostBound; x < rightMostBound; x++)
|
||||
for(y = bottomBound; y < topBound; y++)
|
||||
getFloatersRenderObject(x, y, renderMap[x - leftMostBound][y - bottomBound], renderObjectsPerCube);
|
||||
|
||||
float slicer = cameraPosition.x;
|
||||
watchBounds = true;
|
||||
for(x = leftMostBound; x <= slicer; x++) {
|
||||
leftBound = x - 0.005;
|
||||
rightBound = x + 1 + 0.005;
|
||||
drawY(deltaTime, x);
|
||||
}
|
||||
for(x = rightMostBound; x > slicer - 1; x--) {
|
||||
leftBound = x - 0.005;
|
||||
rightBound = x + 1 + 0.005;
|
||||
drawY(deltaTime, x);
|
||||
}
|
||||
|
||||
watchBounds = false;
|
||||
}
|
||||
326
Code blocks projekt/modules/camera.c.save
Normal file
326
Code blocks projekt/modules/camera.c.save
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
#include "camera.h"
|
||||
|
||||
#define focalLength 0.05 /**< gyújtótáv [m] */
|
||||
#define sensorSize 0.07 /**< szenzor hosszabb oldalának a fele [m] */
|
||||
#define renderObjectsPerCube 10 /**< max( (projectile + player + enemy) / m^3), erről később bővebben. */
|
||||
|
||||
vector3D cameraPosition; /**< A kamera térbeli helyvektora. */
|
||||
float magnification, columns, rows; /**< Ennyi látszik a pályából [m]. */
|
||||
bool watchBounds = false; /**< Feldarabolós rajzolás van-e? */
|
||||
float leftBound, rightBound, upperBound, lowerBound; /**< Darabolás határai. */
|
||||
int leftMostBound, rightMostBound, topBound, bottomBound;
|
||||
renderObject*** renderMap = NULL; /**< Darabolás mátrixa. */
|
||||
|
||||
|
||||
///A feldarabolós rajzoláshoz szükséges mátrixot szabadítja fel.
|
||||
void freeRenderMap() {
|
||||
if(renderMap != NULL) {
|
||||
free(renderMap[0][0]);
|
||||
free(renderMap[0]);
|
||||
free(renderMap);
|
||||
}
|
||||
}
|
||||
|
||||
///A feldarabolós rajzoláshoz szükséges mátrixot mallocolja.
|
||||
static void initRenderMap() {
|
||||
renderMap = (renderObject***) malloc(sizeof(renderObject**));
|
||||
renderMap[0] = (renderObject**) malloc(sizeof(renderObject*));
|
||||
renderMap[0][0] = (renderObject*) malloc(sizeof(renderObject));
|
||||
}
|
||||
|
||||
/** \brief Kiszámolja a kamera poziciója és a képernyő mérete alapján, hogy mennyi látszik a pályából.
|
||||
*
|
||||
* Elsősorban ezeket a változókat változtatja:
|
||||
* columns, rows = képernyőn megjelenő oszlopok és sorok száma,
|
||||
* magnification = megmondja egy méter a kamera "szenzorán" hány pixelnek felel meg (jó soknak)
|
||||
*
|
||||
* Hasonló háromszögek alapján kiszámolja mennyi látszik a pályából:
|
||||
* sensor size
|
||||
* |
|
||||
* V
|
||||
* ----
|
||||
* \ |
|
||||
* \ | <- focalLength
|
||||
* \|
|
||||
* |
|
||||
* |\
|
||||
* | \
|
||||
* Z -> | \
|
||||
* | \
|
||||
* | \
|
||||
* -------------
|
||||
* columns
|
||||
*
|
||||
* Ezek alapján reallocolja a darabolós mátrixot.
|
||||
*
|
||||
*/
|
||||
static void calculateRowsAndColumns() {
|
||||
magnification = (float) screen -> w / 2 / sensorSize;
|
||||
columns = 2 * cameraPosition.z * sensorSize / focalLength;
|
||||
//hogy a négyzet négyzet is maradjon
|
||||
rows = (float)screen -> h / screen -> w * columns;
|
||||
|
||||
if(renderMap == NULL) initRenderMap();
|
||||
|
||||
int xSize = (int)columns + 4; //a nagyobb testek átlóghatnak a képernyő határán
|
||||
int ySize = (int)rows + 4;
|
||||
int iSize = renderObjectsPerCube;
|
||||
|
||||
renderObject* innerTmp = (renderObject*) realloc(renderMap[0][0], xSize * ySize * iSize * sizeof(renderObject));
|
||||
renderObject** outerTmp = (renderObject**) realloc(renderMap[0], xSize * ySize * sizeof(renderObject*));
|
||||
renderMap = (renderObject***) realloc(renderMap, xSize * sizeof(renderObject**));
|
||||
|
||||
renderMap[0] = outerTmp;
|
||||
|
||||
int x;
|
||||
for(x = 1; x < xSize; x++)
|
||||
renderMap[x] = renderMap[0] + x * ySize;
|
||||
|
||||
renderMap[0][0] = innerTmp;
|
||||
|
||||
renderObject empty;
|
||||
empty.doesExist = false;
|
||||
|
||||
int y, i = 0;
|
||||
int j;
|
||||
for(x = 0; x < xSize; x++)
|
||||
for(y = 0; y < ySize; y++) {
|
||||
renderMap[x][y] = renderMap[0][0] + i++ * iSize;
|
||||
for(j = 0; j < iSize; j++) renderMap[x][y][j] = empty;
|
||||
}
|
||||
}
|
||||
|
||||
///A játékost követi a kamerával, nem hagyja, hogy a pálya alá lásson.
|
||||
void followPlayerWithCamera() {
|
||||
renderObject player = getPlayerRenderObject();
|
||||
cameraPosition.x = (2 * player.position.x + player.size.x) / 2;
|
||||
cameraPosition.y = (player.position.y < rows / 2 ? rows / 2 : player.position.y) + 1;
|
||||
}
|
||||
|
||||
///A menüben használt kamerát állítja be, visszaadja a columns-t és rows-t is.
|
||||
void menuCamera(int* getColumns, int* getRows) {
|
||||
cameraPosition.z = cameraDeltaZDistanceStart;
|
||||
calculateRowsAndColumns();
|
||||
*getColumns = columns;
|
||||
*getRows = rows;
|
||||
cameraPosition.x = columns / 2;
|
||||
cameraPosition.y = rows / 2;
|
||||
}
|
||||
|
||||
///Visszaadja, hogy hány oszlop látszik a pályából.
|
||||
int getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
/** \brief A kamera dollyzását végzi, a kamerát mozgatja
|
||||
* A dolly állását staticban tárolja, ezért új dolly eseteén először egy restart = true-val kell meghívni,
|
||||
* \param ms eltelt idő
|
||||
* \param kell-e újrakezdés?
|
||||
* \return elérte-e a végállást?
|
||||
* Minden frameban újraszámolja a rows&coulmns-t,
|
||||
*/
|
||||
bool cameraDollyZ(int deltaTime, bool restart) {
|
||||
static int timePassed;
|
||||
if(restart) timePassed = 0;
|
||||
|
||||
bool done = true;
|
||||
|
||||
timePassed += deltaTime;
|
||||
|
||||
float t = (float)(cameraDollyTime - timePassed) / cameraDollyTime;
|
||||
float cube = t*t*t;
|
||||
|
||||
float currentZ = cameraDeltaZDistanceEnd + (cameraDeltaZDistanceStart - cameraDeltaZDistanceEnd) * cube;
|
||||
|
||||
if(currentZ <= cameraDeltaZDistanceEnd) {
|
||||
currentZ = cameraDeltaZDistanceEnd;
|
||||
done = false;
|
||||
}
|
||||
|
||||
cameraPosition.z = currentZ;
|
||||
calculateRowsAndColumns();
|
||||
return done;
|
||||
}
|
||||
|
||||
/** \brief Térbeli pontból síkbelit képez.
|
||||
* A 3D-s pont koordinátái és a kamera alapján kiszámolja, hogy a kamera 2D-s szenzorán hol jelenik meg a pont.
|
||||
* Geometriailag leírva, a két ponton (point, cameraPosition) átmenő egyenes egyenletének, és a 'szenzor' vízszintesének metszéspontja
|
||||
* a keresett pontunk. A lent és a linken is látható egyenletet először a tér x-z, majd az y-z vetületére alkalmazzuk,
|
||||
* és megkapjuk a térbeli pontunk megfelelő síkbeli leképezést.
|
||||
* Ez interaktívan ábrázolva így néz ki: https://www.desmos.com/calculator/8qjvkptjmn
|
||||
* \param Térvektor típusú pont
|
||||
* \return Síkvektor típusú pont
|
||||
* A visszaadott pontnak int koordinátái vannak, hiszen valamelyik pixel koordinátáit jelöli.
|
||||
* Ez a függvény igazából egy camera obscura modellje.
|
||||
*/
|
||||
intVector2D get2DPoint(vector3D point) {
|
||||
//Ha watchBounds = true, csak egy megadott kockán belül adja vissza az értéket (rajzol), ez a feldarabolás miatt fontos
|
||||
if(watchBounds) {
|
||||
putInsideIntervalF(leftBound, &point.x, rightBound);
|
||||
putInsideIntervalF(lowerBound, &point.y, upperBound);
|
||||
}
|
||||
|
||||
//Ezt a két kifejezést újra felhasználjuk
|
||||
float zDist = point.z - cameraPosition.z;
|
||||
float zDistFromHole = zDist - focalLength;
|
||||
float dx = (cameraPosition.x * zDistFromHole + focalLength * point.x) / zDist - cameraPosition.x;
|
||||
float dy = (cameraPosition.y * zDistFromHole + focalLength * point.y) / zDist - cameraPosition.y;
|
||||
|
||||
//Megfelelően tükrözzük a kapot pontot, és a méterben kapott értéket átváltjuk pixelekre
|
||||
intVector2D resultPoint = {
|
||||
(int)(screen -> w / 2 - magnification * dx),
|
||||
(int)(screen -> h / 2 + magnification * dy)
|
||||
};
|
||||
|
||||
return resultPoint;
|
||||
}
|
||||
|
||||
/** \brief Lerajzol egy négyszöget
|
||||
* A bemenetként kapott 4 pont alkotta négyszöget rajzolja ki.
|
||||
* \param síkvektor a csúcshoz
|
||||
* \param síkvektor b csúcshoz
|
||||
* \param síkvektor c csúcshoz
|
||||
* \param síkvektor d csúcshoz
|
||||
* \param szín négyszög színe
|
||||
* Ezt egyszer kitöltéssel csinálja, egyszer pedig anti-aliasing poligonnal,
|
||||
* hogy a rajz széle ne legyen recegős.
|
||||
*/
|
||||
static void drawTetragon(intVector2D a, intVector2D b, intVector2D c, intVector2D d, color color) {
|
||||
Sint16 xCoords[4] = {(Sint16)a.x, (Sint16)b.x, (Sint16)c.x, (Sint16)d.x};
|
||||
Sint16 yCoords[4] = {(Sint16)a.y, (Sint16)b.y, (Sint16)c.y, (Sint16)d.y};
|
||||
|
||||
filledPolygonRGBA(screen, xCoords, yCoords, 4, color.r, color.g, color.b, color.a);
|
||||
aapolygonRGBA(screen, xCoords, yCoords, 4, color.r, color.g, color.b, color.a);
|
||||
}
|
||||
|
||||
/** \brief Lerajzol egy téglatestet
|
||||
* A kamera modul lényege, a rajzolást végzi el az eddigi függvények segítségével.
|
||||
* \param test téglatest adatai
|
||||
* \param bool melyik oldalakat kell rajzolni?
|
||||
* Végez egy plusz ellenőrést is, nem csak a paraméterben megadott tömb alapján nem rajzol oldalakat,
|
||||
* azokat se rajzolja le, amiket a helyzetük miatt biztosan nem láthat a kamera.
|
||||
*/
|
||||
void drawCuboid(renderObject object, bool sides[]) {
|
||||
intVector2D vertexes[8];
|
||||
//A téglatestet bejárva megkeressük a csúcsait
|
||||
int i;
|
||||
for(i = 0; i < 8; i++) {
|
||||
vertexes[i] = get2DPoint(object.position);
|
||||
switch(i % 4) {
|
||||
case 0:
|
||||
object.position.x += object.size.x;
|
||||
break;
|
||||
case 1:
|
||||
object.position.y += object.size.y;
|
||||
break;
|
||||
case 2:
|
||||
object.position.x -= object.size.x;
|
||||
break;
|
||||
case 3:
|
||||
object.position.y -= object.size.y;
|
||||
}
|
||||
if(i == 3) object.position.z += object.size.z;
|
||||
}
|
||||
|
||||
//alja
|
||||
if(sides[0] && object.position.y > cameraPosition.y) drawTetragon(vertexes[0], vertexes[4], vertexes[5], vertexes[1], object.colors.dark);
|
||||
//bal oldali lap
|
||||
if(sides[1] && object.position.x > cameraPosition.x) drawTetragon(vertexes[0], vertexes[3], vertexes[7], vertexes[4], object.colors.dark);
|
||||
//jobb oldali lap
|
||||
if(sides[2] && object.position.x + object.size.x < cameraPosition.x) drawTetragon(vertexes[1], vertexes[2], vertexes[6], vertexes[5], object.colors.dark);
|
||||
//teteje
|
||||
if(sides[3] && object.position.y + object.size.y < cameraPosition.y) drawTetragon(vertexes[3], vertexes[7], vertexes[6], vertexes[2], object.colors.light);
|
||||
//eleje
|
||||
if(sides[4]) drawTetragon(vertexes[4], vertexes[5], vertexes[6], vertexes[7], object.colors.normal);
|
||||
}
|
||||
|
||||
/// Az egy m^3-ben lévő testeket rajzolja le
|
||||
static void drawPlace(int x, int* y, int direction, int bound) {
|
||||
bool sides[5] = {true, true, true, true, true};
|
||||
|
||||
renderObject toDraw = getBlockRenderObject(x, y, direction, bound, sides);
|
||||
if(toDraw.doesExist) {
|
||||
watchBounds = false;
|
||||
drawCuboid(toDraw, sides);
|
||||
watchBounds = true;
|
||||
}
|
||||
else {
|
||||
int i = 0;
|
||||
toDraw = renderMap[x - leftMostBound][*y - bottomBound][i];
|
||||
while(toDraw.doesExist && i < renderObjectsPerCube) {
|
||||
drawCuboid(toDraw, sides);
|
||||
i++;
|
||||
toDraw = renderMap[x - leftMostBound][*y - bottomBound][i];
|
||||
}
|
||||
|
||||
renderObject player = getPlayerRenderObject();
|
||||
|
||||
if(
|
||||
(x == (int)floor(player.position.x) || x == (int)floor(player.position.x + player.size.x)) &&
|
||||
(*y == (int)floor(player.position.y) || *y == (int)floor(player.position.y + player.size.y))
|
||||
)
|
||||
drawCuboid(player, sides);
|
||||
}
|
||||
}
|
||||
|
||||
///Az egy oszlopban lévő testeket rajzolja le, a részecskéket mozgatja közvetlen
|
||||
static void drawY(int deltaTime, int x) {
|
||||
int y;
|
||||
|
||||
for(y = topBound; y > cameraPosition.y; y--) {
|
||||
upperBound = y + 1;
|
||||
lowerBound = y;
|
||||
drawPlace(x, &y, -1, (int)cameraPosition.y);
|
||||
}
|
||||
for(y = bottomBound; y <= cameraPosition.y; y++) {
|
||||
upperBound = y + 1;
|
||||
lowerBound = y;
|
||||
drawPlace(x, &y, 1, (int)cameraPosition.y + 1);
|
||||
}
|
||||
watchBounds = false;
|
||||
drawParticles(x, bottomBound, topBound, deltaTime);
|
||||
watchBounds = true;
|
||||
}
|
||||
|
||||
/** \brief Lerajzolja a teljes látható játékteret.
|
||||
* A megfelelő rajzoláshoz figyelni kell a testek takarására, nem mindegy ezért, hogy milyen sorrendben rajzoljuk őket.
|
||||
* A részecskéknél ezzel nincs probléma, azokat bármilyen sorrendben rajzolhatjuk. Ők a játékteret kitakarják, egymásnál viszont nem látszik,
|
||||
* hogy melyik takrja melyiket, ezért azokat elég a játéktér után bármilyen sorrendben lerajzolni.
|
||||
* A térképet alkotó kockáknál már nem ilyen egyszeű a helyzet. Azokat 4 irányból kell rajzolni, bal lentről, jobb lentről, bal fentről, illetve jobb fentről középre.
|
||||
* Ha ebben a négy lépésben rajzoljuk őket (ezek között a sorrend nem számít) akkor mindig a legfesőket rajzoljuk utoljára, és így valósnak néz ki az eredmény.
|
||||
* A játékos, a lövedékek, illetve az ellenségek viszont sajnos nincsenek egy négyzethálóhoz kötve. Így gyakran megesik, hogy az egyik felüket a pálya
|
||||
* egyik kockája előtt, a másikat pedig az után, de még a kövektező előtt kéne rajzolni. Ezt nem tudjuk megcsinálni, hatalmas erőforrásba kerülne ez a majdnem pixelről
|
||||
* pixelre történő szkennelés. A pályát továbbra is m^3-ént szeretnénk lerajzolni. Hogy ez megfelelően nézzen ki, minden köbméterben csak az abban a kockában lévő dolgokat
|
||||
* szeretnénk megrajzolni. Ehhez fel kell "darabolnunk" a játékost, a lövedékeket, illetve az ellenségeket is. A darabolás azt jelenti, hogy egy mátrix minden cellájába
|
||||
* beírjuk, hogy az adott kockában melyik, milyen tulajdonsággal rendelkező testek lógnak be. Rajzolásnál pedig a testeknek mindig csak az adott kockabeli részét rajzoljuk le.
|
||||
* Mivel a kockákat jó sorrendben rajzoljuk, így a bennük levő "testekrészeket" is jó sorrendbe fogjuk rajzolni. A problémát megoldottuk.
|
||||
* \param ms eltelt idő
|
||||
* Ez a függvény elvégzi a részecskék, a pálya, illetve minden más test rajzolását is. A részecskék mozgatása innen van meghívva.
|
||||
*/
|
||||
void drawMap(int deltaTime) {
|
||||
leftMostBound = (int)(cameraPosition.x - (float)columns / 2) - 1;
|
||||
rightMostBound = (int)(cameraPosition.x + (float)columns / 2) + 1;
|
||||
topBound = (int)(cameraPosition.y + (float)rows / 2 + 1);
|
||||
bottomBound = (int)(cameraPosition.y - (float)rows / 2 - 1);
|
||||
|
||||
int y, x;
|
||||
|
||||
for(x = leftMostBound; x < rightMostBound; x++)
|
||||
for(y = bottomBound; y < topBound; y++)
|
||||
getFloatersRenderObject(x, y, renderMap[x - leftMostBound][y - bottomBound], renderObjectsPerCube);
|
||||
|
||||
float slicer = cameraPosition.x;
|
||||
watchBounds = true;
|
||||
for(x = leftMostBound; x <= slicer; x++) {
|
||||
leftBound = x - 0.005;
|
||||
rightBound = x + 1 + 0.005;
|
||||
drawY(deltaTime, x);
|
||||
}
|
||||
for(x = rightMostBound; x > slicer - 1; x--) {
|
||||
leftBound = x - 0.005;
|
||||
rightBound = x + 1 + 0.005;
|
||||
drawY(deltaTime, x);
|
||||
}
|
||||
|
||||
watchBounds = false;
|
||||
}
|
||||
24
Code blocks projekt/modules/camera.h
Normal file
24
Code blocks projekt/modules/camera.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef CAMERA_H_INCLUDED
|
||||
#define CAMERA_H_INCLUDED
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "floaters.h"
|
||||
#include "player.h"
|
||||
#include "map.h"
|
||||
#include "particles.h"
|
||||
|
||||
#define cameraDeltaZDistanceStart 25 /**<dolly start táv [m]*/
|
||||
#define cameraDeltaZDistanceEnd 14 /**<dolly end táv [m]*/
|
||||
#define cameraDollyTime 3250 /**<[ms]*/
|
||||
|
||||
void freeRenderMap();
|
||||
void followPlayerWithCamera();
|
||||
void menuCamera(int* getColumns, int* getRows);
|
||||
int getColumns();
|
||||
bool cameraDollyZ(int deltaTime, bool restart);
|
||||
intVector2D get2DPoint(vector3D point);
|
||||
void drawCuboid(renderObject object, bool sides[]);
|
||||
void drawMap(int deltaTime);
|
||||
|
||||
#endif // CAMERA_H_INCLUDED
|
||||
24
Code blocks projekt/modules/camera.h.save
Normal file
24
Code blocks projekt/modules/camera.h.save
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef CAMERA_H_INCLUDED
|
||||
#define CAMERA_H_INCLUDED
|
||||
|
||||
#include "global.h"
|
||||
|
||||
#include "floaters.h"
|
||||
#include "player.h"
|
||||
#include "map.h"
|
||||
#include "particles.h"
|
||||
|
||||
#define cameraDeltaZDistanceStart 25 /**<dolly start táv [m]*/
|
||||
#define cameraDeltaZDistanceEnd 15 /**<dolly end táv [m]*/
|
||||
#define cameraDollyTime 3250 /**<[ms]*/
|
||||
|
||||
void freeRenderMap();
|
||||
void followPlayerWithCamera();
|
||||
void menuCamera(int* getColumns, int* getRows);
|
||||
int getColumns();
|
||||
bool cameraDollyZ(int deltaTime, bool restart);
|
||||
intVector2D get2DPoint(vector3D point);
|
||||
void drawCuboid(renderObject object, bool sides[]);
|
||||
void drawMap(int deltaTime);
|
||||
|
||||
#endif // CAMERA_H_INCLUDED
|
||||
17
Code blocks projekt/modules/camera.h.save-failed
Normal file
17
Code blocks projekt/modules/camera.h.save-failed
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include "global.h"
|
||||
|
||||
|
||||
#ifndef CAMERA_H_INCLUDED
|
||||
#define CAMERA_H_INCLUDED
|
||||
|
||||
|
||||
void followPlayerWCamera();
|
||||
bool cameraDollyZ(int deltaTime);
|
||||
intVector2D get2DPoint(vector3D point);
|
||||
void drawCuboid(renderObject object, bool sides[]);
|
||||
void drawMap(int deltaTime);
|
||||
void calculateRowsAndColumns();
|
||||
int getCamMinZDist();
|
||||
|
||||
|
||||
#endif // CAMERA_H_INCLUDED
|
||||
56
Code blocks projekt/modules/color.c
Normal file
56
Code blocks projekt/modules/color.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include "color.h"
|
||||
|
||||
#define baseHue 30 /**< A kockák átlagos színezetsége. */
|
||||
#define hueVariance 20 /**< A kockák színezetségének átlagostól vlaó eltérése. */
|
||||
#define baseSaturation 0.75 /**< A kockák átlagos telítettsége. */
|
||||
#define baseLightness 0.6 /**< A kockák átlagos fényessége. */
|
||||
#define lightnessStep 0.08 /**< A kockák oldalainak háromféle fényesség értéke van, ezzel szimuláljuk a fény-árnyékot. */
|
||||
|
||||
|
||||
///Ez a függvény majdnem teljes egészében erről az oldalról származik: https://www.programmingalgorithms.com/algorithm/hsl-to-rgb?lang=C
|
||||
static float hueToRgb(float v1, float v2, float vH) {
|
||||
if (vH < 0) vH += 1;
|
||||
if (vH > 1) vH -= 1;
|
||||
if ((6 * vH) < 1) return (v1 + (v2 - v1) * 6 * vH);
|
||||
if ((2 * vH) < 1) return v2;
|
||||
if ((3 * vH) < 2) return (v1 + (v2 - v1) * ((2.0f / 3) - vH) * 6);
|
||||
return v1;
|
||||
}
|
||||
|
||||
///Ez a függvény majdnem teljes egészében erről az oldalról származik: https://www.programmingalgorithms.com/algorithm/hsl-to-rgb?lang=C
|
||||
static color hslToRgb(int h, float s, float l) {
|
||||
color rgb;
|
||||
if (s == 0) rgb.r = rgb.g = rgb.b = (unsigned char)(l * 255);
|
||||
else {
|
||||
float v1, v2;
|
||||
float hue = (float)h / 360;
|
||||
|
||||
v2 = (l < 0.5) ? (l * (1 + s)) : ((l + s) - (l * s));
|
||||
v1 = 2 * l - v2;
|
||||
|
||||
rgb.r = (unsigned char)(255 * hueToRgb(v1, v2, hue + (1.0 / 3)));
|
||||
rgb.g = (unsigned char)(255 * hueToRgb(v1, v2, hue));
|
||||
rgb.b = (unsigned char)(255 * hueToRgb(v1, v2, hue - (1.0 / 3)));
|
||||
rgb.a = 255;
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
|
||||
/** \brief Véletlenszerűre színez egy kockát.
|
||||
* \return színek
|
||||
* Az alapszín, és hueVariance alapján meghatároz
|
||||
* véletlenszerűen egy színezetséget, és az ahhoz a színezetséghez tartozó világosabb és sötétebb
|
||||
* árnyalatú színeket is, majd ezeket RGBA-ba kódolja.
|
||||
* Egy random hue-val készített paletta sokkal jobban néz ki, mint egy random RGB-vel készített.
|
||||
*/
|
||||
colors createBlockColor() {
|
||||
int hue = randomIntWithinBorders(baseHue, hueVariance);
|
||||
|
||||
if(hue < 0) hue += 360;
|
||||
|
||||
return (colors) {
|
||||
hslToRgb(hue, baseSaturation, baseLightness + lightnessStep),
|
||||
hslToRgb(hue, baseSaturation, baseLightness),
|
||||
hslToRgb(hue, baseSaturation, baseLightness - lightnessStep)
|
||||
};
|
||||
}
|
||||
56
Code blocks projekt/modules/color.c.save
Normal file
56
Code blocks projekt/modules/color.c.save
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include "color.h"
|
||||
|
||||
#define baseHue 30 /**< A kockák átlagos színezetsége. */
|
||||
#define hueVariance 20 /**< A kockák színezetségének átlagostól vlaó eltérése. */
|
||||
#define baseSaturation 0.75 /**< A kockák átlagos telítettsége. */
|
||||
#define baseLightness 0.6 /**< A kockák átlagos fényessége. */
|
||||
#define lightnessStep 0.08 /**< A kockák oldalainak háromféle fényesség értéke van, ezzel szimuláljuk a fény-árnyékot. */
|
||||
|
||||
|
||||
///Ez a függvény majdnem teljes egészében erről az oldalról származik: https://www.programmingalgorithms.com/algorithm/hsl-to-rgb?lang=C
|
||||
static float hueToRgb(float v1, float v2, float vH) {
|
||||
if (vH < 0) vH += 1;
|
||||
if (vH > 1) vH -= 1;
|
||||
if ((6 * vH) < 1) return (v1 + (v2 - v1) * 6 * vH);
|
||||
if ((2 * vH) < 1) return v2;
|
||||
if ((3 * vH) < 2) return (v1 + (v2 - v1) * ((2.0f / 3) - vH) * 6);
|
||||
return v1;
|
||||
}
|
||||
|
||||
///Ez a függvény majdnem teljes egészében erről az oldalról származik: https://www.programmingalgorithms.com/algorithm/hsl-to-rgb?lang=C
|
||||
static color hslToRgb(int h, float s, float l) {
|
||||
color rgb;
|
||||
if (s == 0) rgb.r = rgb.g = rgb.b = (unsigned char)(l * 255);
|
||||
else {
|
||||
float v1, v2;
|
||||
float hue = (float)h / 360;
|
||||
|
||||
v2 = (l < 0.5) ? (l * (1 + s)) : ((l + s) - (l * s));
|
||||
v1 = 2 * l - v2;
|
||||
|
||||
rgb.r = (unsigned char)(255 * hueToRgb(v1, v2, hue + (1.0 / 3)));
|
||||
rgb.g = (unsigned char)(255 * hueToRgb(v1, v2, hue));
|
||||
rgb.b = (unsigned char)(255 * hueToRgb(v1, v2, hue - (1.0 / 3)));
|
||||
rgb.a = 255;
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
|
||||
/** \brief Véletlenszerűre színez egy kockát.
|
||||
* \return színek
|
||||
* Az alapszín, és hueVariance alapján meghatároz
|
||||
* véletlenszerűen egy színezetséget, és az ahhoz a színezetséghez tartozó világosabb és sötétebb
|
||||
* árnyalatú színeket is, majd ezeket RGBA-ba kódolja.
|
||||
* Egy random hue-val készített paletta sokkal jobban néz ki, mint egy random RGB-vel készített.
|
||||
*/
|
||||
colors createBlockColor() {
|
||||
int hue = randomIntWithinBorders(baseHue, hueVariance);
|
||||
|
||||
if(hue < 0) hue += 360;
|
||||
|
||||
return (colors) {
|
||||
hslToRgb(hue, baseSaturation, baseLightness + lightnessStep),
|
||||
hslToRgb(hue, baseSaturation, baseLightness),
|
||||
hslToRgb(hue, baseSaturation, baseLightness - lightnessStep)
|
||||
};
|
||||
}
|
||||
8
Code blocks projekt/modules/color.h
Normal file
8
Code blocks projekt/modules/color.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef COLOR_H_INCLUDED
|
||||
#define COLOR_H_INCLUDED
|
||||
|
||||
#include "global.h"
|
||||
|
||||
colors createBlockColor();
|
||||
|
||||
#endif // COLOR_H_INCLUDED
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue