Ya sube las rampas. Aun queda por acabar

This commit is contained in:
2022-09-10 18:26:24 +02:00
parent 2ccb02258c
commit edaa59af7d
10 changed files with 386 additions and 11 deletions

View File

@@ -27,6 +27,7 @@ Game::Game(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, D
eventHandler = new SDL_Event(); eventHandler = new SDL_Event();
text = new Text(asset->get("smb2.png"), asset->get("smb2.txt"), renderer); text = new Text(asset->get("smb2.png"), asset->get("smb2.txt"), renderer);
music = JA_LoadMusic(asset->get("game.ogg").c_str()); music = JA_LoadMusic(asset->get("game.ogg").c_str());
test = new Test(renderer, screen, asset, debug);
// Inicializa el resto de variables // Inicializa el resto de variables
ticks = 0; ticks = 0;
@@ -55,6 +56,8 @@ Game::~Game()
delete player; delete player;
delete eventHandler; delete eventHandler;
delete text; delete text;
delete test;
} }
// Comprueba los eventos de la cola // Comprueba los eventos de la cola
@@ -72,6 +75,8 @@ void Game::checkEventHandler()
} }
else if ((eventHandler->type == SDL_KEYDOWN) and (eventHandler->key.repeat == 0)) else if ((eventHandler->type == SDL_KEYDOWN) and (eventHandler->key.repeat == 0))
{ {
//test->update();
switch (eventHandler->key.keysym.scancode) switch (eventHandler->key.keysym.scancode)
{ {
case SDL_SCANCODE_ESCAPE: case SDL_SCANCODE_ESCAPE:
@@ -184,6 +189,7 @@ void Game::render()
// Debug info // Debug info
renderDebugInfo(); renderDebugInfo();
//test->render();
// Actualiza la pantalla // Actualiza la pantalla
screen->blit(); screen->blit();
@@ -193,7 +199,7 @@ void Game::render()
void Game::updateDebugInfo() void Game::updateDebugInfo()
{ {
debug->add("X = " + std::to_string((int)player->x) + ", Y = " + std::to_string((int)player->y)); 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)); debug->add("STATE = " + std::to_string(player->state));
} }

View File

@@ -14,6 +14,7 @@
#include "jail_audio.h" #include "jail_audio.h"
#include "scoreboard.h" #include "scoreboard.h"
#include "debug.h" #include "debug.h"
#include "test.h"
#ifndef GAME_H #ifndef GAME_H
#define GAME_H #define GAME_H
@@ -43,6 +44,7 @@ private:
int playerLives; // Lleva la cuenta de ls vidas restantes del jugador int playerLives; // Lleva la cuenta de ls vidas restantes del jugador
int itemsPicked; // Lleva la cuenta de los objetos recogidos int itemsPicked; // Lleva la cuenta de los objetos recogidos
Uint32 clock; // Cuenta el tiempo que dura la partida Uint32 clock; // Cuenta el tiempo que dura la partida
Test *test;
// Actualiza el juego, las variables, comprueba la entrada, etc. // Actualiza el juego, las variables, comprueba la entrada, etc.
void update(); void update();

View File

@@ -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}); colliderPoints.insert(colliderPoints.end(), {p, p, p, p, p, p, p, p});
underFeet.insert(underFeet.end(), {p, p}); underFeet.insert(underFeet.end(), {p, p});
feet.insert(feet.end(), {p, p}); feet.insert(feet.end(), {p, p});
line = {0, 0, 0, 0};
} }
// Destructor // Destructor
@@ -68,6 +70,8 @@ void Player::render()
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderDrawPoint(renderer, underFeet[0].x, underFeet[0].y); SDL_RenderDrawPoint(renderer, underFeet[0].x, underFeet[0].y);
SDL_RenderDrawPoint(renderer, underFeet[1].x, underFeet[1].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.h = h - 1;
proj.w = ceil(abs(vx)); // Para evitar que tenga un ancho de 0 pixels 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); const int pos = room->checkRightSurfaces(&proj);
// Calcula la nueva posición // Calcula la nueva posición
@@ -255,6 +259,15 @@ void Player::move()
{ // Si hay colisión lo mueve hasta donde no colisiona { // Si hay colisión lo mueve hasta donde no colisiona
x = pos + 1; 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 // Se mueve hacia la derecha
@@ -279,6 +292,15 @@ void Player::move()
{ // Si hay colisión lo mueve hasta donde no colisiona { // Si hay colisión lo mueve hasta donde no colisiona
x = pos - w; 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 // Si ha salido del suelo, el jugador cae
@@ -313,7 +335,7 @@ void Player::move()
} }
// Se mueve hacia abajo // 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 // Crea el rectangulo de proyección en el eje X para ver si colisiona
SDL_Rect proj; SDL_Rect proj;
@@ -322,7 +344,7 @@ void Player::move()
proj.h = ceil(vy); // Para evitar que tenga una altura de 0 pixels proj.h = ceil(vy); // Para evitar que tenga una altura de 0 pixels
proj.w = w - 1; proj.w = w - 1;
// Comprueba la colisión // Comprueba la colisión con los muros
const int pos = room->checkTopSurfaces(&proj); const int pos = room->checkTopSurfaces(&proj);
// Calcula la nueva posición // Calcula la nueva posición
@@ -511,11 +533,16 @@ bool Player::isOnFloor()
updateFeet(); updateFeet();
// Comprueba las superficies
for (auto f : underFeet) for (auto f : underFeet)
{ {
onFloor |= room->checkTopSurfaces(&f); onFloor |= room->checkTopSurfaces(&f);
} }
// Comprueba las rampas
onFloor |= room->checkLeftSlopes(&underFeet[0]);
onFloor |= room->checkRightSlopes(&underFeet[1]);
if (onFloor) if (onFloor)
{ {
debug->add("ONFLOOR"); debug->add("ONFLOOR");

View File

@@ -62,6 +62,7 @@ public:
SDL_Rect lastPosition; // Contiene la ultima posición del jugador, por si hay que deshacer algun movimiento 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 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 float maxVY; // Velocidad máxima que puede alcanzar al desplazarse en vertical
line_t line;
// Comprueba las entradas y modifica variables // Comprueba las entradas y modifica variables
void checkInput(); void checkInput();

View File

@@ -488,7 +488,7 @@ void Room::fillMapTexture()
} }
// LeftSlopes // LeftSlopes
if (true) if (false)
{ {
for (auto l : leftSlopes) for (auto l : leftSlopes)
{ {
@@ -907,7 +907,7 @@ void Room::setLeftSlopes()
while (found.size() > 0) while (found.size() > 0)
{ {
line_t line; d_line_t line;
line.x1 = (found[0] % mapWidth) * tileSize; line.x1 = (found[0] % mapWidth) * tileSize;
line.y1 = (found[0] / mapWidth) * tileSize; line.y1 = (found[0] / mapWidth) * tileSize;
int lookingFor = found[0] + mapWidth + 1; int lookingFor = found[0] + mapWidth + 1;
@@ -948,7 +948,7 @@ void Room::setRightSlopes()
while (found.size() > 0) while (found.size() > 0)
{ {
line_t line; d_line_t line;
line.x1 = ((found[0] % mapWidth) * tileSize) + tileSize - 1; line.x1 = ((found[0] % mapWidth) * tileSize) + tileSize - 1;
line.y1 = (found[0] / mapWidth) * tileSize; line.y1 = (found[0] / mapWidth) * tileSize;
int lookingFor = found[0] + mapWidth - 1; int lookingFor = found[0] + mapWidth - 1;
@@ -966,7 +966,7 @@ void Room::setRightSlopes()
} }
line.x2 = (lastOneFound % mapWidth) * tileSize; line.x2 = (lastOneFound % mapWidth) * tileSize;
line.y2 = ((lastOneFound / mapWidth) * tileSize) + tileSize - 1; 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; return false;
} }

View File

@@ -68,8 +68,8 @@ private:
std::vector<h_line_t> topSurfaces; // Lista con las superficies superiores de la habitación std::vector<h_line_t> topSurfaces; // Lista con las superficies superiores de la habitación
std::vector<v_line_t> leftSurfaces; // Lista con las superficies laterales de la parte izquierda de la habitación std::vector<v_line_t> leftSurfaces; // Lista con las superficies laterales de la parte izquierda de la habitación
std::vector<v_line_t> rightSurfaces; // Lista con las superficies laterales de la parte derecha de la habitación std::vector<v_line_t> rightSurfaces; // Lista con las superficies laterales de la parte derecha de la habitación
std::vector<line_t> leftSlopes; // Lista con todas las rampas que suben hacia la izquierda std::vector<d_line_t> leftSlopes; // Lista con todas las rampas que suben hacia la izquierda
std::vector<line_t> rightSlopes; // Lista con todas las rampas que suben hacia la derecha std::vector<d_line_t> rightSlopes; // Lista con todas las rampas que suben hacia la derecha
int tileSize; // Ancho del tile en pixels int tileSize; // Ancho del tile en pixels
int mapWidth; // Ancho del mapa en tiles int mapWidth; // Ancho del mapa en tiles
@@ -172,6 +172,18 @@ public:
// Comprueba las colisiones // Comprueba las colisiones
bool checkTopSurfaces(SDL_Point *p); 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 #endif

79
source/test.cpp Normal file
View File

@@ -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);
}

48
source/test.h Normal file
View File

@@ -0,0 +1,48 @@
#pragma once
#include <SDL2/SDL.h>
#include "const.h"
#include "utils.h"
#include "screen.h"
#include "asset.h"
#include "text.h"
#include "debug.h"
#include <vector>
#include <string>
#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<point_t> 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

View File

@@ -227,6 +227,127 @@ bool checkCollision(h_line_t &l, SDL_Point &p)
return true; 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 // Devuelve un color_t a partir de un string
color_t stringToColor(std::string str) color_t stringToColor(std::string str)
{ {

View File

@@ -46,10 +46,16 @@ struct v_line_t
int x, y1, y2; int x, y1, y2;
}; };
// Estructura para definir una linea diagonal
struct d_line_t
{
int x1, y1, x2, y2;
};
// Estructura para definir una linea // Estructura para definir una linea
struct line_t struct line_t
{ {
int x1, x2, y1, y2; int x1, y1, x2, y2;
}; };
// Estructura para definir un color // 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 // Detector de colisiones entre una linea horizontal y un punto
bool checkCollision(h_line_t &l, SDL_Point &p); 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 // Devuelve un color_t a partir de un string
color_t stringToColor(std::string str); color_t stringToColor(std::string str);