From dea16e00040c13c60d62c1194e313ac4c31e8413 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sun, 25 Sep 2022 14:09:37 +0200 Subject: [PATCH] =?UTF-8?q?Las=20superficies=20automaticas=20ya=20arrastra?= =?UTF-8?q?n.=20Falta=20definir=20el=20sentido=20y=20la=20animaci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/player.cpp | 75 ++++++++++++++++++++++++++++--------- source/player.h | 4 ++ source/room.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++++- source/room.h | 10 +++++ 4 files changed, 166 insertions(+), 18 deletions(-) diff --git a/source/player.cpp b/source/player.cpp index 1aee173..e910936 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -21,6 +21,7 @@ Player::Player(player_t ini, std::string tileset, std::string animation, SDL_Ren onBorder = false; border = BORDER_TOP; invincible = true; + autoMovement = false; alive = true; maxFallHeight = BLOCK * 4; paused = false; @@ -151,29 +152,41 @@ void Player::update() // Comprueba las entradas y modifica variables void Player::checkInput() { - // Solo comprueba las entradas de dirección cuando está dsobre una superficie + // Solo comprueba las entradas de dirección cuando está sobre una superficie if (state != s_standing) { return; } - if (input->checkInput(INPUT_LEFT, REPEAT_TRUE)) - { - vx = -0.6f; - sprite->setFlip(SDL_FLIP_HORIZONTAL); - } + if (!autoMovement) + { // Comprueba las entradas de desplazamiento lateral solo en el caso de no estar enganchado a una superficie automatica + if (input->checkInput(INPUT_LEFT, REPEAT_TRUE)) + { + vx = -0.6f; + sprite->setFlip(SDL_FLIP_HORIZONTAL); + } - else if (input->checkInput(INPUT_RIGHT, REPEAT_TRUE)) - { + else if (input->checkInput(INPUT_RIGHT, REPEAT_TRUE)) + { + vx = 0.6f; + sprite->setFlip(SDL_FLIP_NONE); + } + + else + { // No se pulsa ninguna dirección + vx = 0.0f; + if (isOnAutoSurface()) + { // Si deja de moverse sobre una superficie se engancha + autoMovement = true; + } + } + } + else + { // El movimiento lo proporciona la superficie vx = 0.6f; sprite->setFlip(SDL_FLIP_NONE); } - else - { - vx = 0.0f; - } - if (input->checkInput(INPUT_UP, REPEAT_TRUE)) { setState(s_jumping); @@ -407,6 +420,9 @@ void Player::move() if (state == s_standing && !isOnFloor()) { setState(s_falling); + + // Deja de estar enganchado a la superficie automatica + autoMovement = false; } // Se mueve hacia arriba @@ -448,12 +464,15 @@ void Player::move() r = proj; - // Comprueba la colisión con los muros - const int pos = room->checkTopSurfaces(&proj); + // Comprueba la colisión con las superficies normales y las automáticas + const int pos = std::max(room->checkTopSurfaces(&proj), room->checkAutoSurfaces(&proj)); if (pos > -1) - { // Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre el suelo + { // Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie y = pos - h; setState(s_standing); + + // Deja de estar enganchado a la superficie automatica + autoMovement = false; } else { // Si no hay colisión con los muros, comprueba la colisión con las rampas @@ -466,7 +485,7 @@ void Player::move() { // No está saltando y hay colisión con una rampa // Calcula la nueva posición y = p - h; - setState(s_standing); + setState(s_standing); } else { // No está saltando y no hay colisón con una rampa @@ -548,6 +567,7 @@ bool Player::isOnFloor() for (auto f : underFeet) { onFloor |= room->checkTopSurfaces(&f); + onFloor |= room->checkAutoSurfaces(&f); } // Comprueba las rampas @@ -572,6 +592,27 @@ bool Player::isOnFloor() return onFloor || onSlopeL || onSlopeR; } +// Comprueba si el jugador esta sobre una superficie automática +bool Player::isOnAutoSurface() +{ + bool onAutoSurface = false; + + updateFeet(); + + // Comprueba las superficies + for (auto f : underFeet) + { + onAutoSurface |= room->checkAutoSurfaces(&f); + } + + if (onAutoSurface) + { + debug->add("ON_AUTO_SURFACE"); + } + + return onAutoSurface; +} + // Comprueba si el jugador está sobre una rampa hacia abajo bool Player::isOnDownSlope() { diff --git a/source/player.h b/source/player.h index 584594e..cc67576 100644 --- a/source/player.h +++ b/source/player.h @@ -59,6 +59,7 @@ public: bool onBorder; // Indica si el jugador esta en uno de los cuatro bordes de la pantalla int border; // Indica en cual de los cuatro bordes se encuentra bool invincible; // Si es invencible, no puede morir + bool autoMovement; // Indica si esta siendo arrastrado por una superficie automatica bool paused; // Indica si el jugador esta en modo pausa SDL_Rect lastPosition; // Contiene la ultima posición del jugador, por si hay que deshacer algun movimiento int jumpIni; // Valor del eje Y en el que se inicia el salto @@ -104,6 +105,9 @@ public: // Comprueba si el jugador tiene suelo debajo de los pies bool isOnFloor(); + // Comprueba si el jugador esta sobre una superficie automática + bool isOnAutoSurface(); + // Comprueba si el jugador está sobre una rampa hacia abajo bool isOnDownSlope(); diff --git a/source/room.cpp b/source/room.cpp index 6697ea6..80a3140 100644 --- a/source/room.cpp +++ b/source/room.cpp @@ -38,6 +38,7 @@ Room::Room(std::string file, SDL_Renderer *renderer, Screen *screen, Asset *asse setRightSurfaces(); setLeftSlopes(); setRightSlopes(); + setAutoSurfaces(); // Busca los tiles animados setAnimatedTiles(); @@ -582,6 +583,7 @@ void Room::fillMapTexture() for (auto l : leftSurfaces) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); + SDL_SetRenderDrawColor(renderer, 0, 0, 255, 0xFF); SDL_RenderDrawLine(renderer, l.x, l.y1, l.x, l.y2); } } @@ -592,6 +594,7 @@ void Room::fillMapTexture() for (auto l : rightSurfaces) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); + SDL_SetRenderDrawColor(renderer, 255, 255, 0, 0xFF); SDL_RenderDrawLine(renderer, l.x, l.y1, l.x, l.y2); } } @@ -602,6 +605,7 @@ void Room::fillMapTexture() for (auto l : leftSlopes) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); + SDL_SetRenderDrawColor(renderer, 0, 255, 255, 0xFF); SDL_RenderDrawLine(renderer, l.x1, l.y1, l.x2, l.y2); } } @@ -612,9 +616,20 @@ void Room::fillMapTexture() for (auto l : rightSlopes) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); + SDL_SetRenderDrawColor(renderer, 255, 0, 255, 0xFF); SDL_RenderDrawLine(renderer, l.x1, l.y1, l.x2, l.y2); } } + + // AutoSurfaces + if (true) + { + for (auto l : autoSurfaces) + { + SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); + SDL_RenderDrawLine(renderer, l.x1, l.y, l.x2, l.y); + } + } } // **** @@ -628,7 +643,10 @@ void Room::renderMap() SDL_RenderCopy(renderer, mapTexture, nullptr, nullptr); // Dibuja los tiles animados - renderAnimatedTiles(); + if (!debug->getEnabled()) + { + renderAnimatedTiles(); + } } // Dibuja los enemigos en pantalla @@ -1087,6 +1105,53 @@ void Room::setRightSlopes() } } +// Calcula las superficies automaticas +void Room::setAutoSurfaces() +{ + std::vector tile; + + // Busca todos los tiles de tipo animado + // Hay que recorrer la habitación por filas (excepto los de la primera fila) + for (int i = mapWidth; i < (int)tilemap.size(); ++i) + { + if (getTile(i) == t_animated) + { + tile.push_back(i); + + // Si llega al final de la fila, introduce un separador + if (i % mapWidth == mapWidth - 1) + { + tile.push_back(-1); + } + } + } + + // Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies + int i = 0; + int lastOne = 0; + while (i < (int)tile.size()) + { + h_line_t line; + line.x1 = (tile[i] % mapWidth) * tileSize; + line.y = (tile[i] / mapWidth) * tileSize; + lastOne = i; + i++; + + while (tile[i] == tile[i - 1] + 1) + { + lastOne = i; + i++; + } + + line.x2 = ((tile[lastOne] % mapWidth) * tileSize) + tileSize - 1; + autoSurfaces.push_back(line); + if (tile[i] == -1) + { // Si el siguiente elemento es un separador, hay que saltarlo + i++; + } + } +} + // Localiza todos los tiles animados de la habitación void Room::setAnimatedTiles() { @@ -1190,6 +1255,20 @@ int Room::checkBottomSurfaces(SDL_Rect *rect) return -1; } +// Comprueba las colisiones +int Room::checkAutoSurfaces(SDL_Rect *rect) +{ + for (auto s : autoSurfaces) + { + if (checkCollision(s, *rect)) + { + return s.y; + } + } + + return -1; +} + // Comprueba las colisiones bool Room::checkTopSurfaces(SDL_Point *p) { @@ -1204,6 +1283,20 @@ bool Room::checkTopSurfaces(SDL_Point *p) return false; } +// Comprueba las colisiones +bool Room::checkAutoSurfaces(SDL_Point *p) +{ + for (auto s : autoSurfaces) + { + if (checkCollision(s, *p)) + { + return true; + } + } + + return false; +} + // Comprueba las colisiones int Room::checkLeftSlopes(v_line_t *line) { diff --git a/source/room.h b/source/room.h index 2d52294..d2a0099 100644 --- a/source/room.h +++ b/source/room.h @@ -83,6 +83,7 @@ private: std::vector rightSlopes; // Lista con todas las rampas que suben hacia la derecha int counter; // Contador para lo que haga falta std::vector aTile; // Vector con los indices de tiles animados + std::vector autoSurfaces; // Lista con las superficies automaticas de la habitación int tileSize; // Ancho del tile en pixels int mapWidth; // Ancho del mapa en tiles @@ -125,6 +126,9 @@ private: // Encuentra todas las rampas que suben hacia la derecha void setRightSlopes(); + // Calcula las superficies automaticas + void setAutoSurfaces(); + // Localiza todos los tiles animados de la habitación void setAnimatedTiles(); @@ -198,9 +202,15 @@ public: // Comprueba las colisiones int checkBottomSurfaces(SDL_Rect *rect); + // Comprueba las colisiones + int checkAutoSurfaces(SDL_Rect *rect); + // Comprueba las colisiones bool checkTopSurfaces(SDL_Point *p); + // Comprueba las colisiones + bool checkAutoSurfaces(SDL_Point *p); + // Comprueba las colisiones int checkLeftSlopes(v_line_t *line);