From edaa59af7d4eeabd6d1623f7c47b267b156875b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Valor=20Mart=C3=ADnez?= Date: Sat, 10 Sep 2022 18:26:24 +0200 Subject: [PATCH] Ya sube las rampas. Aun queda por acabar --- source/game.cpp | 8 ++- source/game.h | 2 + source/player.cpp | 33 +++++++++++-- source/player.h | 1 + source/room.cpp | 66 +++++++++++++++++++++++-- source/room.h | 16 +++++- source/test.cpp | 79 ++++++++++++++++++++++++++++++ source/test.h | 48 ++++++++++++++++++ source/utils.cpp | 121 ++++++++++++++++++++++++++++++++++++++++++++++ source/utils.h | 23 ++++++++- 10 files changed, 386 insertions(+), 11 deletions(-) create mode 100644 source/test.cpp create mode 100644 source/test.h diff --git a/source/game.cpp b/source/game.cpp index 20c369c..7d29492 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -27,6 +27,7 @@ Game::Game(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, D eventHandler = new SDL_Event(); text = new Text(asset->get("smb2.png"), asset->get("smb2.txt"), renderer); music = JA_LoadMusic(asset->get("game.ogg").c_str()); + test = new Test(renderer, screen, asset, debug); // Inicializa el resto de variables ticks = 0; @@ -55,6 +56,8 @@ Game::~Game() delete player; delete eventHandler; delete text; + + delete test; } // Comprueba los eventos de la cola @@ -72,6 +75,8 @@ void Game::checkEventHandler() } else if ((eventHandler->type == SDL_KEYDOWN) and (eventHandler->key.repeat == 0)) { + //test->update(); + switch (eventHandler->key.keysym.scancode) { case SDL_SCANCODE_ESCAPE: @@ -184,6 +189,7 @@ void Game::render() // Debug info renderDebugInfo(); + //test->render(); // Actualiza la pantalla screen->blit(); @@ -193,7 +199,7 @@ void Game::render() void Game::updateDebugInfo() { debug->add("X = " + std::to_string((int)player->x) + ", Y = " + std::to_string((int)player->y)); - debug->add("VX = " + std::to_string(player->vx).substr(0,4) + ", VY = " + std::to_string(player->vy).substr(0,4)); + debug->add("VX = " + std::to_string(player->vx).substr(0, 4) + ", VY = " + std::to_string(player->vy).substr(0, 4)); debug->add("STATE = " + std::to_string(player->state)); } diff --git a/source/game.h b/source/game.h index 7466326..20ac63c 100644 --- a/source/game.h +++ b/source/game.h @@ -14,6 +14,7 @@ #include "jail_audio.h" #include "scoreboard.h" #include "debug.h" +#include "test.h" #ifndef GAME_H #define GAME_H @@ -43,6 +44,7 @@ private: int playerLives; // Lleva la cuenta de ls vidas restantes del jugador int itemsPicked; // Lleva la cuenta de los objetos recogidos Uint32 clock; // Cuenta el tiempo que dura la partida + Test *test; // Actualiza el juego, las variables, comprueba la entrada, etc. void update(); diff --git a/source/player.cpp b/source/player.cpp index 6df638e..f472c72 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -49,6 +49,8 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren colliderPoints.insert(colliderPoints.end(), {p, p, p, p, p, p, p, p}); underFeet.insert(underFeet.end(), {p, p}); feet.insert(feet.end(), {p, p}); + + line = {0, 0, 0, 0}; } // Destructor @@ -68,6 +70,8 @@ void Player::render() SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); SDL_RenderDrawPoint(renderer, underFeet[0].x, underFeet[0].y); SDL_RenderDrawPoint(renderer, underFeet[1].x, underFeet[1].y); + + SDL_RenderDrawLine(renderer, line.x1, line.y1, line.x2, line.y2); } } @@ -243,7 +247,7 @@ void Player::move() proj.h = h - 1; proj.w = ceil(abs(vx)); // Para evitar que tenga un ancho de 0 pixels - // Comprueba la colisión + // Comprueba la colisión con las superficies const int pos = room->checkRightSurfaces(&proj); // Calcula la nueva posición @@ -255,6 +259,15 @@ void Player::move() { // Si hay colisión lo mueve hasta donde no colisiona x = pos + 1; } + + // Si ha tocado alguna rampa, asciende + v_line_t leftSide = {(int)x, (int)y, (int)y + h - 1}; + const int ly = room->checkLeftSlopes(&leftSide); + if (ly > -1) + { + y = ly - h; + setState(s_standing); + } } // Se mueve hacia la derecha @@ -279,6 +292,15 @@ void Player::move() { // Si hay colisión lo mueve hasta donde no colisiona x = pos - w; } + + // Si ha tocado alguna rampa, asciende + v_line_t rightSide = {(int)x + w - 1, (int)y, (int)y + h - 1}; + const int ry = room->checkRightSlopes(&rightSide); + if (ry > -1) + { + y = ry - h; + setState(s_standing); + } } // Si ha salido del suelo, el jugador cae @@ -313,7 +335,7 @@ void Player::move() } // Se mueve hacia abajo - if (vy > 0.0f) + else if (vy > 0.0f) { // Crea el rectangulo de proyección en el eje X para ver si colisiona SDL_Rect proj; @@ -322,7 +344,7 @@ void Player::move() proj.h = ceil(vy); // Para evitar que tenga una altura de 0 pixels proj.w = w - 1; - // Comprueba la colisión + // Comprueba la colisión con los muros const int pos = room->checkTopSurfaces(&proj); // Calcula la nueva posición @@ -511,11 +533,16 @@ bool Player::isOnFloor() updateFeet(); + // Comprueba las superficies for (auto f : underFeet) { onFloor |= room->checkTopSurfaces(&f); } + // Comprueba las rampas + onFloor |= room->checkLeftSlopes(&underFeet[0]); + onFloor |= room->checkRightSlopes(&underFeet[1]); + if (onFloor) { debug->add("ONFLOOR"); diff --git a/source/player.h b/source/player.h index 841d5dd..eaf62ab 100644 --- a/source/player.h +++ b/source/player.h @@ -62,6 +62,7 @@ public: SDL_Rect lastPosition; // Contiene la ultima posición del jugador, por si hay que deshacer algun movimiento int jump_ini; // Valor del eje Y en el que se inicia el salto float maxVY; // Velocidad máxima que puede alcanzar al desplazarse en vertical + line_t line; // Comprueba las entradas y modifica variables void checkInput(); diff --git a/source/room.cpp b/source/room.cpp index e0cae06..18a0cb4 100644 --- a/source/room.cpp +++ b/source/room.cpp @@ -488,7 +488,7 @@ void Room::fillMapTexture() } // LeftSlopes - if (true) + if (false) { for (auto l : leftSlopes) { @@ -907,7 +907,7 @@ void Room::setLeftSlopes() while (found.size() > 0) { - line_t line; + d_line_t line; line.x1 = (found[0] % mapWidth) * tileSize; line.y1 = (found[0] / mapWidth) * tileSize; int lookingFor = found[0] + mapWidth + 1; @@ -948,7 +948,7 @@ void Room::setRightSlopes() while (found.size() > 0) { - line_t line; + d_line_t line; line.x1 = ((found[0] % mapWidth) * tileSize) + tileSize - 1; line.y1 = (found[0] / mapWidth) * tileSize; int lookingFor = found[0] + mapWidth - 1; @@ -966,7 +966,7 @@ void Room::setRightSlopes() } line.x2 = (lastOneFound % mapWidth) * tileSize; line.y2 = ((lastOneFound / mapWidth) * tileSize) + tileSize - 1; - leftSlopes.push_back(line); + rightSlopes.push_back(line); } } @@ -1037,5 +1037,63 @@ bool Room::checkTopSurfaces(SDL_Point *p) } } + return false; +} + +// Comprueba las colisiones +int Room::checkLeftSlopes(v_line_t *line) +{ + for (auto s : leftSlopes) + { + const SDL_Point p = checkCollision(s, *line); + if (p.x != -1) + { + return p.y; + } + } + + return -1; +} + +// Comprueba las colisiones +bool Room::checkLeftSlopes(SDL_Point *p) +{ + for (auto s : leftSlopes) + { + if (checkCollision(*p, s)) + { + return true; + } + } + + return false; +} + +// Comprueba las colisiones +int Room::checkRightSlopes(v_line_t *line) +{ + for (auto s : rightSlopes) + { + const SDL_Point p = checkCollision(s, *line); + if (p.x != -1) + { + return p.y; + } + } + + return -1; +} + +// Comprueba las colisiones +bool Room::checkRightSlopes(SDL_Point *p) +{ + for (auto s : rightSlopes) + { + if (checkCollision(*p, s)) + { + return true; + } + } + return false; } \ No newline at end of file diff --git a/source/room.h b/source/room.h index 759bb56..ba0c6d5 100644 --- a/source/room.h +++ b/source/room.h @@ -68,8 +68,8 @@ private: std::vector topSurfaces; // Lista con las superficies superiores de la habitación std::vector leftSurfaces; // Lista con las superficies laterales de la parte izquierda de la habitación std::vector rightSurfaces; // Lista con las superficies laterales de la parte derecha de la habitación - std::vector leftSlopes; // Lista con todas las rampas que suben hacia la izquierda - std::vector rightSlopes; // Lista con todas las rampas que suben hacia la derecha + std::vector leftSlopes; // Lista con todas las rampas que suben hacia la izquierda + std::vector rightSlopes; // Lista con todas las rampas que suben hacia la derecha int tileSize; // Ancho del tile en pixels int mapWidth; // Ancho del mapa en tiles @@ -172,6 +172,18 @@ public: // Comprueba las colisiones bool checkTopSurfaces(SDL_Point *p); + + // Comprueba las colisiones + int checkLeftSlopes(v_line_t *line); + + // Comprueba las colisiones + bool checkLeftSlopes(SDL_Point *p); + + // Comprueba las colisiones + int checkRightSlopes(v_line_t *line); + + // Comprueba las colisiones + bool checkRightSlopes(SDL_Point *p); }; #endif diff --git a/source/test.cpp b/source/test.cpp new file mode 100644 index 0000000..a468151 --- /dev/null +++ b/source/test.cpp @@ -0,0 +1,79 @@ +#include "test.h" + +// Constructor +Test::Test(SDL_Renderer *renderer, Screen *screen, Asset *asset, Debug *debug) +{ + // Copia la dirección de los objetos + this->renderer = renderer; + this->screen = screen; + this->asset = asset; + this->debug = debug; + + // Inicializa variables + for (int i = 0; i < 4; ++i) + { + point_t p; + p.x = rand() % 256; + p.y = rand() % 192; + p.vx = (float)((rand() % 10) + 1) / 10.0f; + p.vy = (float)((rand() % 10) + 1) / 10.0f; + rand() % 2 == 0 ? p.dx = -1 : p.dx = 1; + rand() % 2 == 0 ? p.dy = -1 : p.dy = 1; + p.vx *= p.dx; + p.vy *= p.dy; + points.push_back(p); + } +} + +// Destructor +Test::~Test() +{ +} + +// Actualiza las variables +void Test::update() +{ + for (int i = 0; i < points.size(); ++i) + { + points[i].x += points[i].vx; + points[i].y += points[i].vy; + + if (points[i].x > 255) + { + points[i].x = 255; + points[i].vx = -(float)((rand() % 10) + 1) / 10.0f; + } + else if (points[i].x < 0) + { + points[i].x = 0; + points[i].vx = (float)((rand() % 10) + 1) / 10.0f; + } + + if (points[i].y > 191) + { + points[i].y = 191; + points[i].vy = -(float)((rand() % 10) + 1) / 10.0f; + } + else if (points[i].y < 0) + { + points[i].y = 0; + points[i].vy = (float)((rand() % 10) + 1) / 10.0f; + } + std::string text = "P" + std::to_string(i) + ": x=" + std::to_string(points[i].x).substr(0,3) + " y=" + std::to_string(points[i].y).substr(0,3) + " vx=" + std::to_string(points[i].vx).substr(0,3) + " vy=" + std::to_string(points[i].vy).substr(0,3); + debug->add(text); + } +} + +// Dibuja en pantalla +void Test::render() +{ + SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); + line_t l1 = {(int)points[0].x, (int)points[0].y, (int)points[1].x, (int)points[1].y}; + line_t l2 = {(int)points[2].x, (int)points[2].y, (int)points[3].x, (int)points[3].y}; + SDL_RenderDrawLine(renderer, l1.x1, l1.y1, l1.x2, l1.y2); + SDL_RenderDrawLine(renderer, l2.x1, l2.y1, l2.x2, l2.y2); + + SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); + SDL_Point p = checkCollision(l1, l2); + SDL_RenderDrawPoint(renderer, p.x, p.y); +} \ No newline at end of file diff --git a/source/test.h b/source/test.h new file mode 100644 index 0000000..13cc1d3 --- /dev/null +++ b/source/test.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include "const.h" +#include "utils.h" +#include "screen.h" +#include "asset.h" +#include "text.h" +#include "debug.h" +#include +#include + +#ifndef TEST_H +#define TEST_H + +struct point_t +{ + float x, y; + float vx, vy; + int dx, dy; +}; + +// Clase Test +class Test +{ +private: + SDL_Renderer *renderer; // El renderizador de la ventana + Screen *screen; // Objeto encargado de dibujar en pantalla + Asset *asset; // Objeto con los ficheros de recursos + Debug *debug; + + std::vector points; + +public: + // Constructor + Test(SDL_Renderer *renderer, Screen *screen, Asset *asset, Debug *debug); + + // Destructor + ~Test(); + + // Actualiza las variables + void update(); + + // Dibuja en pantalla + void render(); +}; + +#endif diff --git a/source/utils.cpp b/source/utils.cpp index 8d6be6c..76016cf 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -227,6 +227,127 @@ bool checkCollision(h_line_t &l, SDL_Point &p) return true; } +// Detector de colisiones entre dos lineas +SDL_Point checkCollision(line_t &l1, line_t &l2) +{ + const float x1 = l1.x1; + const float y1 = l1.y1; + const float x2 = l1.x2; + const float y2 = l1.y2; + + const float x3 = l2.x1; + const float y3 = l2.y1; + const float x4 = l2.x2; + const float y4 = l2.y2; + + // calculate the direction of the lines + float uA = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + float uB = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + + // if uA and uB are between 0-1, lines are colliding + if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) + { + // Calcula la intersección + const float x = x1 + (uA * (x2 - x1)); + const float y = y1 + (uA * (y2 - y1)); + + return {(int)round(x), (int)round(y)}; + } + return {-1, -1}; +} + +// Detector de colisiones entre dos lineas +SDL_Point checkCollision(d_line_t &l1, v_line_t &l2) +{ + const float x1 = l1.x1; + const float y1 = l1.y1; + const float x2 = l1.x2; + const float y2 = l1.y2; + + const float x3 = l2.x; + const float y3 = l2.y1; + const float x4 = l2.x; + const float y4 = l2.y2; + + // calculate the direction of the lines + float uA = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + float uB = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + + // if uA and uB are between 0-1, lines are colliding + if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) + { + // Calcula la intersección + const float x = x1 + (uA * (x2 - x1)); + const float y = y1 + (uA * (y2 - y1)); + + return {(int)x, (int)y}; + } + return {-1, -1}; +} + +// Detector de colisiones entre una linea diagonal y una vertical +/*bool checkCollision(d_line_t &l1, v_line_t &l2) +{ + // Normaliza la linea diagonal + normalizeLine(l1); + + // Comprueba si la linea vertical esta a la izquierda de la linea diagonal + if (l2.x < l1.x1) + { + return false; + } + + // Comprueba si la linea vertical esta a la derecha de la linea diagonal + if (l2.x > l1.x2) + { + return false; + } + + // Inacabada + return true; +}*/ + +// Normaliza una linea diagonal +void normalizeLine(d_line_t &l) +{ + // Las lineas diagonales van de izquierda a derecha + // x2 mayor que x1 + if (l.x2 < l.x1) + { + const int x = l.x1; + const int y = l.y1; + l.x1 = l.x2; + l.y1 = l.y2; + l.x2 = x; + l.y2 = y; + } +} + +// Detector de colisiones entre un punto y una linea diagonal +bool checkCollision(SDL_Point &p, d_line_t &l) +{ + // Comprueba si el punto está en alineado con la linea + if (abs(p.x - l.x1) != abs(p.y - l.y1)) + { + return false; + } + + // Comprueba si está a la derecha de la linea + if (p.x > l.x1 && p.x > l.x2) + { + return false; + } + + // Comprueba si está a la izquierda de la linea + if (p.x < l.x1 && p.x < l.x2) + { + return false; + } + + // En caso contrario, el punto está en la linea + return true; +} + // Devuelve un color_t a partir de un string color_t stringToColor(std::string str) { diff --git a/source/utils.h b/source/utils.h index 6a72185..be647f3 100644 --- a/source/utils.h +++ b/source/utils.h @@ -46,10 +46,16 @@ struct v_line_t int x, y1, y2; }; +// Estructura para definir una linea diagonal +struct d_line_t +{ + int x1, y1, x2, y2; +}; + // Estructura para definir una linea struct line_t { - int x1, x2, y1, y2; + int x1, y1, x2, y2; }; // Estructura para definir un color @@ -104,6 +110,21 @@ bool checkCollision(v_line_t &l, SDL_Rect &r); // Detector de colisiones entre una linea horizontal y un punto bool checkCollision(h_line_t &l, SDL_Point &p); +// Detector de colisiones entre dos lineas +SDL_Point checkCollision(line_t &l1, line_t &l2); + +// Detector de colisiones entre dos lineas +SDL_Point checkCollision(d_line_t &l1, v_line_t &l2); + +// Detector de colisiones entre una linea diagonal y una vertical +//bool checkCollision(d_line_t &l1, v_line_t &l2); + +// Detector de colisiones entre un punto y una linea diagonal +bool checkCollision(SDL_Point &p, d_line_t &l); + +// Normaliza una linea diagonal +void normalizeLine(d_line_t &l); + // Devuelve un color_t a partir de un string color_t stringToColor(std::string str);