Files
coffee_crisis_arcade_edition/source/utils.cpp
Sergio Valor 2cb22ed013 fix: els globos tenien un parell de setters mal asignats per culpa de buscar y reemplazar
fix: els globos verds s'inicialitzaven amb vy = 0 per gastar abs en lloc de fabs
fix: corregit un bug milenari que de sempre havia creat els balloons verds al popar al pare amb la meitat de velocitat en y. Lo que jo no se es com anava res. Supose que ara el joc serà un poc mes xungo. Quan rebotaven en el piso ja se'ls posava la velocitat bona (crec)
2024-10-20 22:58:15 +02:00

274 lines
7.8 KiB
C++

#include "utils.h"
#include <iostream>
#include <string>
#include <algorithm> // for min, clamp, find_if_not, transform
#include <cctype> // for tolower, isspace
#include <cmath> // for cos, pow, M_PI
#include <compare> // for operator<
struct JA_Music_t; // lines 7-7
struct JA_Sound_t; // lines 8-8
// Colores
const Color bg_color = {0x27, 0x27, 0x36};
const Color no_color = {0xFF, 0xFF, 0xFF};
const Color shdw_txt_color = {0x43, 0x43, 0x4F};
const Color separator_color = {0x0D, 0x1A, 0x2B};
const Color scoreboard_color = {0x2E, 0x3F, 0x47};
const Color difficulty_easy_color = {0x4B, 0x69, 0x2F};
const Color difficulty_normal_color = {0xFF, 0x7A, 0x00};
const Color difficulty_hard_color = {0x76, 0x42, 0x8A};
const Color flash_color = {0xFF, 0xFF, 0xFF};
const Color fade_color = {0x27, 0x27, 0x36};
const Color orange_color = {0xFF, 0x7A, 0x00};
// Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2)
{
const int delta_x = x2 - x1;
const int delta_y = y2 - y1;
return delta_x * delta_x + delta_y * delta_y;
}
// Detector de colisiones entre dos circulos
bool checkCollision(const Circle &a, const Circle &b)
{
// Calcula el radio total al cuadrado
int total_radius_squared = (a.r + b.r) * (a.r + b.r);
// Comprueba si la distancia entre los centros de los círculos es inferior a la suma de sus radios
return distanceSquared(a.x, a.y, b.x, b.y) < total_radius_squared;
}
// Detector de colisiones entre un circulo y un rectangulo
bool checkCollision(const Circle &a, const SDL_Rect &b)
{
// Encuentra el punto más cercano en el rectángulo
int cX = std::clamp(a.x, b.x, b.x + b.w);
int cY = std::clamp(a.y, b.y, b.y + b.h);
// Si el punto más cercano está dentro del círculo
return distanceSquared(a.x, a.y, cX, cY) < a.r * a.r;
}
// Detector de colisiones entre dos rectangulos
bool checkCollision(const SDL_Rect &a, const SDL_Rect &b)
{
const int leftA = a.x, rightA = a.x + a.w, topA = a.y, bottomA = a.y + a.h;
const int leftB = b.x, rightB = b.x + b.w, topB = b.y, bottomB = b.y + b.h;
if (bottomA <= topB)
return false;
if (topA >= bottomB)
return false;
if (rightA <= leftB)
return false;
if (leftA >= rightB)
return false;
return true;
}
// Detector de colisiones entre un punto y un rectangulo
bool checkCollision(const SDL_Point &p, const SDL_Rect &r)
{
if (p.x < r.x || p.x > r.x + r.w)
return false;
if (p.y < r.y || p.y > r.y + r.h)
return false;
return true;
}
// Convierte una cadena en un valor booleano
bool stringToBool(const std::string &str)
{
return str == "true";
}
// Convierte un valor booleano en una cadena
std::string boolToString(bool value)
{
return value ? "true" : "false";
}
// Convierte un valor booleano en una cadena "on" o "off"
std::string boolToOnOff(bool value)
{
return value ? "on" : "off";
}
// Convierte una cadena a minusculas
std::string toLower(const std::string &str)
{
std::string result = str;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c)
{ return std::tolower(c); });
return result;
}
// Dibuja un circulo
void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius)
{
const int32_t diameter = (radius * 2);
int32_t x = (radius - 1);
int32_t y = 0;
int32_t tx = 1;
int32_t ty = 1;
int32_t error = (tx - diameter);
while (x >= y)
{
// Each of the following renders an octant of the circle
SDL_RenderDrawPoint(renderer, centerX + x, centerY - y);
SDL_RenderDrawPoint(renderer, centerX + x, centerY + y);
SDL_RenderDrawPoint(renderer, centerX - x, centerY - y);
SDL_RenderDrawPoint(renderer, centerX - x, centerY + y);
SDL_RenderDrawPoint(renderer, centerX + y, centerY - x);
SDL_RenderDrawPoint(renderer, centerX + y, centerY + x);
SDL_RenderDrawPoint(renderer, centerX - y, centerY - x);
SDL_RenderDrawPoint(renderer, centerX - y, centerY + x);
if (error <= 0)
{
++y;
error += ty;
ty += 2;
}
if (error > 0)
{
--x;
tx += 2;
error += (tx - diameter);
}
}
}
// Aclara el color
Color lightenColor(const Color &color, int amount)
{
Color newColor;
newColor.r = std::min(255, color.r + amount);
newColor.g = std::min(255, color.g + amount);
newColor.b = std::min(255, color.b + amount);
return newColor;
}
// Oscurece el color
Color DarkenColor(const Color &color, int amount)
{
Color newColor;
newColor.r = std::min(255, color.r - +amount);
newColor.g = std::min(255, color.g - +amount);
newColor.b = std::min(255, color.b - +amount);
return newColor;
}
// Quita los espacioes en un string
std::string trim(const std::string &str)
{
auto start = std::find_if_not(str.begin(), str.end(), ::isspace);
auto end = std::find_if_not(str.rbegin(), str.rend(), ::isspace).base();
return (start < end ? std::string(start, end) : std::string());
}
// Función de suavizado
double easeOutQuint(double t)
{
return 1 - std::pow(1 - t, 5);
}
// Función de suavizado
double easeInOutSine(double t)
{
return -0.5 * (std::cos(M_PI * t) - 1);
}
// Comprueba si una vector contiene una cadena
bool stringInVector(const std::vector<std::string> &vec, const std::string &str)
{
return std::find(vec.begin(), vec.end(), str) != vec.end();
}
// Imprime por pantalla una linea de texto de tamaño fijo rellena con puntos
void printWithDots(const std::string &text1, const std::string &text2, const std::string &text3)
{
std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout << text1;
std::cout.width(50 - text1.length() - text3.length());
std::cout.fill('.');
std::cout << text2;
std::cout << text3 << std::endl;
}
// Carga el fichero de datos para la demo
DemoData loadDemoDataFromFile(const std::string &file_path)
{
DemoData dd;
// Indicador de éxito en la carga
auto file = SDL_RWFromFile(file_path.c_str(), "r+b");
if (!file)
{
std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
throw std::runtime_error("Fichero no encontrado: " + file_path);
}
else
{
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
printWithDots("DemoData : ", file_name, "[ LOADED ]");
// Lee todos los datos del fichero y los deja en el destino
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
{
DemoKeys dk = DemoKeys();
SDL_RWread(file, &dk, sizeof(DemoKeys), 1);
dd.push_back(dk);
}
// Cierra el fichero
SDL_RWclose(file);
}
return dd;
}
#ifdef RECORDING
// Guarda el fichero de datos para la demo
bool saveDemoFile(const std::string &file_path, const DemoData &dd)
{
auto success = true;
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
auto file = SDL_RWFromFile(file_path.c_str(), "w+b");
if (file)
{
// Guarda los datos
for (const auto &data : dd)
{
if (SDL_RWwrite(file, &data, sizeof(DemoKeys), 1) != 1)
{
std::cerr << "Error al escribir el fichero " << file_name << std::endl;
success = false;
break;
}
}
if (success)
{
std::cout << "Writing file " << file_name.c_str() << std::endl;
}
// Cierra el fichero
SDL_RWclose(file);
}
else
{
std::cout << "Error: Unable to save " << file_name.c_str() << " file! " << SDL_GetError() << std::endl;
success = false;
}
return success;
}
#endif // RECORDING