Ya sube las rampas. Aun queda por acabar
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -68,8 +68,8 @@ private:
|
||||
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> 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<line_t> rightSlopes; // Lista con todas las rampas que suben hacia la derecha
|
||||
std::vector<d_line_t> leftSlopes; // Lista con todas las rampas que suben hacia la izquierda
|
||||
std::vector<d_line_t> 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
|
||||
|
||||
79
source/test.cpp
Normal file
79
source/test.cpp
Normal 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
48
source/test.h
Normal 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
|
||||
121
source/utils.cpp
121
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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user