diff --git a/source/A4B1/main.cpp b/source/A4B1/main.cpp index f6221be..9a6da0d 100644 --- a/source/A4B1/main.cpp +++ b/source/A4B1/main.cpp @@ -1,293 +1,584 @@ #include "raylib.h" #include +#include +#include + +struct Bala +{ + Vector2 posicion; + Vector2 direccion; + float velocidad; + bool activa; +}; + +struct Entidad +{ + Vector2 posicion; + Vector2 velocidad; + float radio; +}; + +struct Pared +{ + Rectangle rectangulo; +}; + +const float MUNDO_ANCHO = 1000.0f; +const float MUNDO_ALTO = 650.0f; + +const float BORDE = 35.0f; +const float RADIO_JUGADOR = 18.0f; +const float RADIO_ENEMIGO = 20.0f; + +float Limitar(float valor, float minimo, float maximo) +{ + if (valor < minimo) + return minimo; + + if (valor > maximo) + return maximo; + + return valor; +} + +Vector2 Normalizar(Vector2 v) +{ + float largo = sqrtf(v.x * v.x + v.y * v.y); + + if (largo <= 0.0001f) + return {0.0f, 0.0f}; + + return { + v.x / largo, + v.y / largo + }; +} + +float Distancia(Vector2 a, Vector2 b) +{ + float x = a.x - b.x; + float y = a.y - b.y; + + return sqrtf(x * x + y * y); +} + +bool CirculoRectangulo(Vector2 centro, float radio, Rectangle rect) +{ + float puntoX = Limitar( + centro.x, + rect.x, + rect.x + rect.width + ); + + float puntoY = Limitar( + centro.y, + rect.y, + rect.y + rect.height + ); + + float dx = centro.x - puntoX; + float dy = centro.y - puntoY; + + return dx * dx + dy * dy < radio * radio; +} + +void DibujarBorde(float escalaX, float escalaY) +{ + Rectangle borde = { + BORDE * escalaX, + BORDE * escalaY, + (MUNDO_ANCHO - BORDE * 2.0f) * escalaX, + (MUNDO_ALTO - BORDE * 2.0f) * escalaY + }; + + DrawRectangleRoundedLines( + borde, + 0.08f, + 16, + WHITE + ); +} + +void RebotarBorde(Entidad& entidad) +{ + float izquierda = BORDE + entidad.radio; + float derecha = MUNDO_ANCHO - BORDE - entidad.radio; + float arriba = BORDE + entidad.radio; + float abajo = MUNDO_ALTO - BORDE - entidad.radio; + + if (entidad.posicion.x < izquierda) + { + entidad.posicion.x = izquierda; + + if (entidad.velocidad.x < 0.0f) + entidad.velocidad.x *= -1.0f; + } + + if (entidad.posicion.x > derecha) + { + entidad.posicion.x = derecha; + + if (entidad.velocidad.x > 0.0f) + entidad.velocidad.x *= -1.0f; + } + + if (entidad.posicion.y < arriba) + { + entidad.posicion.y = arriba; + + if (entidad.velocidad.y < 0.0f) + entidad.velocidad.y *= -1.0f; + } + + if (entidad.posicion.y > abajo) + { + entidad.posicion.y = abajo; + + if (entidad.velocidad.y > 0.0f) + entidad.velocidad.y *= -1.0f; + } +} + +void RebotarPared(Entidad& entidad, const std::vector& paredes) +{ + for (const Pared& pared : paredes) + { + if (!CirculoRectangulo( + entidad.posicion, + entidad.radio, + pared.rectangulo)) + { + continue; + } + + float izquierda = pared.rectangulo.x; + float derecha = pared.rectangulo.x + pared.rectangulo.width; + float arriba = pared.rectangulo.y; + float abajo = pared.rectangulo.y + pared.rectangulo.height; + + float dIzquierda = fabsf(entidad.posicion.x - izquierda); + float dDerecha = fabsf(entidad.posicion.x - derecha); + float dArriba = fabsf(entidad.posicion.y - arriba); + float dAbajo = fabsf(entidad.posicion.y - abajo); + + float menor = std::min( + std::min(dIzquierda, dDerecha), + std::min(dArriba, dAbajo) + ); + + if (menor == dIzquierda) + { + entidad.posicion.x = izquierda - entidad.radio; + entidad.velocidad.x = -fabsf(entidad.velocidad.x); + } + else if (menor == dDerecha) + { + entidad.posicion.x = derecha + entidad.radio; + entidad.velocidad.x = fabsf(entidad.velocidad.x); + } + else if (menor == dArriba) + { + entidad.posicion.y = arriba - entidad.radio; + entidad.velocidad.y = -fabsf(entidad.velocidad.y); + } + else + { + entidad.posicion.y = abajo + entidad.radio; + entidad.velocidad.y = fabsf(entidad.velocidad.y); + } + } +} int main() { - const int pantallaAncho = 800; - const int pantallaAlto = 600; - - InitWindow( - pantallaAncho, - pantallaAlto, - "Attacks for Bombs 1" + SetConfigFlags( + FLAG_WINDOW_RESIZABLE | + FLAG_VSYNC_HINT ); - SetTargetFPS(60); + InitWindow( + 1100, + 750, + "A4B1" + ); - // ========================= - // JUGADOR - // ========================= + SetTargetFPS(120); - float x = 400.0f; - float y = 300.0f; + Entidad jugador = { + {220.0f, 325.0f}, + {0.0f, 0.0f}, + RADIO_JUGADOR + }; - float tamaño = 50.0f; - float velocidad = 300.0f; + Entidad enemigo = { + {780.0f, 325.0f}, + {210.0f, 145.0f}, + RADIO_ENEMIGO + }; - // ========================= - // DIRECCIÓN DEL JUGADOR - // ========================= + std::vector balas; - float direccionX = 1.0f; - float direccionY = 0.0f; - - // ========================= - // PROYECTIL - // ========================= - - float proyectilX = 0.0f; - float proyectilY = 0.0f; - - float proyectilAncho = 20.0f; - float proyectilAlto = 8.0f; - - float proyectilVelocidad = 600.0f; - - bool proyectilActivo = false; - - // Dirección congelada del proyectil - float proyectilDireccionX = 0.0f; - float proyectilDireccionY = 0.0f; - - // ========================= - // ENEMIGO - // ========================= - - float enemigoX = 600.0f; - float enemigoY = 300.0f; - - float enemigoTamaño = 50.0f; - - // ========================= - // CONTADOR - // ========================= + std::vector paredes = { + {{280.0f, 150.0f, 180.0f, 14.0f}}, + {{540.0f, 150.0f, 180.0f, 14.0f}}, + {{280.0f, 486.0f, 180.0f, 14.0f}}, + {{540.0f, 486.0f, 180.0f, 14.0f}}, + {{240.0f, 230.0f, 14.0f, 150.0f}}, + {{746.0f, 230.0f, 14.0f, 150.0f}}, + {{450.0f, 245.0f, 100.0f, 14.0f}}, + {{450.0f, 391.0f, 100.0f, 14.0f}} + }; int impactos = 0; - - // ========================= - // BUCLE PRINCIPAL - // ========================= + float tiempoDisparo = 0.0f; while (!WindowShouldClose()) { - float deltaTime = GetFrameTime(); + float dt = GetFrameTime(); - // ========================= - // MOUSE - // ========================= + if (IsKeyPressed(KEY_F11)) + ToggleFullscreen(); + + int anchoPantalla = GetScreenWidth(); + int altoPantalla = GetScreenHeight(); + + float escalaX = anchoPantalla / MUNDO_ANCHO; + float escalaY = altoPantalla / MUNDO_ALTO; Vector2 mouse = GetMousePosition(); - // Dirección del jugador hacia el mouse - float angulo = - atan2(mouse.y - y, mouse.x - x); + Vector2 mouseMundo = { + mouse.x / escalaX, + mouse.y / escalaY + }; - direccionX = cos(angulo); - direccionY = sin(angulo); + Vector2 direccionMira = Normalizar({ + mouseMundo.x - jugador.posicion.x, + mouseMundo.y - jugador.posicion.y + }); - // ========================= - // MOVIMIENTO - // ========================= + Vector2 movimiento = { + 0.0f, + 0.0f + }; if (IsKeyDown(KEY_W)) - { - x += direccionX * velocidad * deltaTime; - y += direccionY * velocidad * deltaTime; - } + movimiento.y -= 1.0f; if (IsKeyDown(KEY_S)) - { - x -= direccionX * velocidad * deltaTime; - y -= direccionY * velocidad * deltaTime; - } + movimiento.y += 1.0f; if (IsKeyDown(KEY_A)) - { - x += direccionY * velocidad * deltaTime; - y -= direccionX * velocidad * deltaTime; - } + movimiento.x -= 1.0f; if (IsKeyDown(KEY_D)) + movimiento.x += 1.0f; + + movimiento = Normalizar(movimiento); + + Vector2 derecha = { + -direccionMira.y, + direccionMira.x + }; + + Vector2 movimientoRelativo = { + derecha.x * movimiento.x + + direccionMira.x * (-movimiento.y), + + derecha.y * movimiento.x + + direccionMira.y * (-movimiento.y) + }; + + jugador.velocidad = { + movimientoRelativo.x * 300.0f, + movimientoRelativo.y * 300.0f + }; + + jugador.posicion.x += + jugador.velocidad.x * dt; + + jugador.posicion.y += + jugador.velocidad.y * dt; + + RebotarBorde(jugador); + RebotarPared(jugador, paredes); + + tiempoDisparo -= dt; + + if (IsKeyDown(KEY_SPACE) && + tiempoDisparo <= 0.0f) { - x -= direccionY * velocidad * deltaTime; - y += direccionX * velocidad * deltaTime; + if (direccionMira.x != 0.0f || + direccionMira.y != 0.0f) + { + Bala bala; + + bala.posicion = { + jugador.posicion.x + + direccionMira.x * 27.0f, + + jugador.posicion.y + + direccionMira.y * 27.0f + }; + + bala.direccion = direccionMira; + bala.velocidad = 850.0f; + bala.activa = true; + + balas.push_back(bala); + + tiempoDisparo = 0.11f; + } } - // ========================= - // LÍMITES DEL JUGADOR - // ========================= + enemigo.posicion.x += + enemigo.velocidad.x * dt; - float mitad = tamaño / 2.0f; + enemigo.posicion.y += + enemigo.velocidad.y * dt; - if (x < mitad) - x = mitad; + RebotarBorde(enemigo); + RebotarPared(enemigo, paredes); - if (x > pantallaAncho - mitad) - x = pantallaAncho - mitad; - - if (y < mitad) - y = mitad; - - if (y > pantallaAlto - mitad) - y = pantallaAlto - mitad; - - // ========================= - // DISPARAR - // ========================= - - if (IsKeyPressed(KEY_SPACE) && !proyectilActivo) + for (Bala& bala : balas) { - proyectilActivo = true; + if (!bala.activa) + continue; - // El proyectil aparece en el jugador - proyectilX = x; - proyectilY = y; + bala.posicion.x += + bala.direccion.x * + bala.velocidad * + dt; - // Guardamos la dirección EXACTA - // que tenía el jugador al disparar - proyectilDireccionX = direccionX; - proyectilDireccionY = direccionY; - } + bala.posicion.y += + bala.direccion.y * + bala.velocidad * + dt; - // ========================= - // MOVIMIENTO DEL PROYECTIL - // ========================= - - if (proyectilActivo) - { - proyectilX += - proyectilDireccionX * - proyectilVelocidad * - deltaTime; - - proyectilY += - proyectilDireccionY * - proyectilVelocidad * - deltaTime; - - // ========================= - // COLISIÓN CON ENEMIGO - // ========================= - - Rectangle proyectilRect = + if (bala.posicion.x < BORDE || + bala.posicion.x > MUNDO_ANCHO - BORDE || + bala.posicion.y < BORDE || + bala.posicion.y > MUNDO_ALTO - BORDE) { - proyectilX - proyectilAncho / 2.0f, - proyectilY - proyectilAlto / 2.0f, - proyectilAncho, - proyectilAlto - }; + bala.activa = false; + continue; + } - Rectangle enemigoRect = + for (const Pared& pared : paredes) { - enemigoX - enemigoTamaño / 2.0f, - enemigoY - enemigoTamaño / 2.0f, - enemigoTamaño, - enemigoTamaño - }; + if (CheckCollisionPointRec( + bala.posicion, + pared.rectangulo)) + { + bala.activa = false; + break; + } + } - if (CheckCollisionRecs( - proyectilRect, - enemigoRect)) + if (!bala.activa) + continue; + + if (Distancia( + bala.posicion, + enemigo.posicion) + < enemigo.radio + 6.0f) { impactos++; - proyectilActivo = false; - } + enemigo.velocidad.x += + bala.direccion.x * 300.0f; - // ========================= - // SALIR DE LA PANTALLA - // ========================= + enemigo.velocidad.y += + bala.direccion.y * 300.0f; - if ( - proyectilX < 0 || - proyectilX > pantallaAncho || - proyectilY < 0 || - proyectilY > pantallaAlto - ) - { - proyectilActivo = false; + float velocidad = sqrtf( + enemigo.velocidad.x * + enemigo.velocidad.x + + enemigo.velocidad.y * + enemigo.velocidad.y + ); + + if (velocidad > 600.0f) + { + enemigo.velocidad.x = + enemigo.velocidad.x / + velocidad * + 600.0f; + + enemigo.velocidad.y = + enemigo.velocidad.y / + velocidad * + 600.0f; + } + + bala.activa = false; } } - // ========================= - // DIBUJAR - // ========================= + balas.erase( + std::remove_if( + balas.begin(), + balas.end(), + [](const Bala& bala) + { + return !bala.activa; + } + ), + balas.end() + ); BeginDrawing(); - ClearBackground(WHITE); + ClearBackground({ + 18, + 18, + 22, + 255 + }); - // ========================= - // CONTADOR - // ========================= - - DrawText( - TextFormat("Impactos: %d", impactos), - 10, - 10, - 25, - BLACK - ); - - // ========================= - // ENEMIGO - // ========================= - - DrawRectangle( - enemigoX - enemigoTamaño / 2.0f, - enemigoY - enemigoTamaño / 2.0f, - enemigoTamaño, - enemigoTamaño, - BLUE - ); - - // ========================= - // PROYECTIL - // ========================= - - if (proyectilActivo) + for (const Pared& pared : paredes) { - float anguloProyectil = - atan2( - proyectilDireccionY, - proyectilDireccionX - ) * RAD2DEG; + Rectangle r = { + pared.rectangulo.x * escalaX, + pared.rectangulo.y * escalaY, + pared.rectangulo.width * escalaX, + pared.rectangulo.height * escalaY + }; - DrawRectanglePro( + DrawRectangleRounded( + r, + 0.3f, + 8, { - proyectilX, - proyectilY, - proyectilAncho, - proyectilAlto - }, + 45, + 45, + 52, + 255 + } + ); + + DrawRectangleRoundedLines( + r, + 0.3f, + 8, { - proyectilAncho / 2.0f, - proyectilAlto / 2.0f - }, - anguloProyectil, - BLACK + 120, + 120, + 130, + 255 + } ); } - // ========================= - // JUGADOR - // ========================= + DibujarBorde( + escalaX, + escalaY + ); - DrawRectanglePro( - { - x, - y, - tamaño, - tamaño - }, - { - mitad, - mitad - }, - angulo * RAD2DEG, + Vector2 jugadorPantalla = { + jugador.posicion.x * escalaX, + jugador.posicion.y * escalaY + }; + + Vector2 enemigoPantalla = { + enemigo.posicion.x * escalaX, + enemigo.posicion.y * escalaY + }; + + float escalaRadio = + std::min(escalaX, escalaY); + + DrawCircleV( + jugadorPantalla, + jugador.radio * escalaRadio, RED ); + DrawCircleV( + enemigoPantalla, + enemigo.radio * escalaRadio, + BLUE + ); + + Vector2 mira = { + jugadorPantalla.x + + direccionMira.x * + 38.0f * + escalaX, + + jugadorPantalla.y + + direccionMira.y * + 38.0f * + escalaY + }; + + DrawLineEx( + jugadorPantalla, + mira, + 4.0f, + WHITE + ); + + for (const Bala& bala : balas) + { + Vector2 posicion = { + bala.posicion.x * escalaX, + bala.posicion.y * escalaY + }; + + DrawCircleV( + posicion, + 5.0f * escalaRadio, + YELLOW + ); + } + + DrawRectangle( + 15, + 15, + 230, + 110, + Fade(BLACK, 0.75f) + ); + + DrawText( + TextFormat( + "IMPACTOS: %d", + impactos + ), + 28, + 27, + 22, + WHITE + ); + + DrawText( + TextFormat( + "FPS: %d", + GetFPS() + ), + 28, + 57, + 20, + GREEN + ); + + DrawText( + "WASD MOVER", + 28, + 87, + 16, + LIGHTGRAY + ); + + DrawText( + "ESPACIO DISPARAR", + 28, + 106, + 16, + LIGHTGRAY + ); + EndDrawing(); } diff --git a/source/Pacman/main.cpp b/source/Pacman/main.cpp deleted file mode 100644 index d1690b3..0000000 --- a/source/Pacman/main.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "raylib.h" -#include - -int main() -{ - // Tamaño de la ventana - const int pantallaAncho = 800; - const int pantallaAlto = 600; - - // Crear ventana - InitWindow( - pantallaAncho, - pantallaAlto, - "Attacks for Bombs 1" - ); - - // Limitar a 60 FPS - SetTargetFPS(60); - - // Posición del jugador - float x = 400.0f; - float y = 300.0f; - - // Tamaño del jugador - float tamaño = 50.0f; - - // Velocidad del jugador - float velocidad = 300.0f; - - while (!WindowShouldClose()) - { - // Tiempo que pasó desde el frame anterior - float deltaTime = GetFrameTime(); - - // Posición del mouse - Vector2 mouse = GetMousePosition(); - - // Dirección hacia el mouse - float angulo = - atan2(mouse.y - y, mouse.x - x); - - float direccionX = cos(angulo); - float direccionY = sin(angulo); - - // Movimiento hacia adelante - if (IsKeyDown(KEY_W)) - { - x += direccionX * velocidad * deltaTime; - y += direccionY * velocidad * deltaTime; - } - - // Movimiento hacia atrás - if (IsKeyDown(KEY_S)) - { - x -= direccionX * velocidad * deltaTime; - y -= direccionY * velocidad * deltaTime; - } - - // Movimiento hacia la izquierda - if (IsKeyDown(KEY_A)) - { - x += direccionY * velocidad * deltaTime; - y -= direccionX * velocidad * deltaTime; - } - - // Movimiento hacia la derecha - if (IsKeyDown(KEY_D)) - { - x -= direccionY * velocidad * deltaTime; - y += direccionX * velocidad * deltaTime; - } - - // Límites de la pantalla - float mitad = tamaño / 2.0f; - - if (x < mitad) - x = mitad; - - if (x > pantallaAncho - mitad) - x = pantallaAncho - mitad; - - if (y < mitad) - y = mitad; - - if (y > pantallaAlto - mitad) - y = pantallaAlto - mitad; - - // Dibujar - BeginDrawing(); - - // Fondo blanco - ClearBackground(WHITE); - - // Dibujar jugador - DrawRectanglePro( - { - x, - y, - tamaño, - tamaño - }, - { - mitad, - mitad - }, - angulo * RAD2DEG, - RED - ); - - EndDrawing(); - } - - // Cerrar ventana - CloseWindow(); - - return 0; -} \ No newline at end of file