Introducción a C++

1

Todo lo que aprenderás sobre C++

2

¿Qué es programar y por qué aprender C++?

Conceptos Generales de C++

3

La Historia de C++ y sus diferencias con C

Preparando el entorno de trabajo

4

Instalando Codeblocks

5

Pasos para instalar en mac

6

Ejecutando nuestro primer programa

7

¿Qué son las librerías STD? - Portada del Proyecto

Manejo de memoria

8

¿Qué es la memoria y tipos de datos?

9

Alojando variables en memoria

10

¿Cómo usar operadores?

11

¿Qué son los apuntadores?

12

Reto: Escribir un programa que calcule áreas.

Entrada de datos y funciones

13

¿Cómo introducir datos a nuestro programa?

14

¿Cómo usar condicionales?

15

Usando condicionales

16

¿Cómo encapsular código en funciones ?

17

¿Qué son los parámetros y como usarlos?

18

Reto: Juego narrativo implementando condicionales y entrada de datos.

Loops y arreglos

19

¿Qué son los arreglos?

20

¿Qué son los Loops?

21

Programando Loops

22

Loops , arreglos y arreglos bidimensionales

23

Dibujando el mapa de nuestro juego con arreglos

24

Manipulando mi jugador con inputs en arreglos unidimensionales

25

Arreglos bidimensionales

26

Reto: Moviendo a mi personaje en mi arreglo bidimensional

Lectura de Archivos

27

Creando y leyendo un archivo externo

28

Leyendo archivos externos

29

Reto: En el mapa, crear punto de inicio y salida del jugador

Programación Orientada a Objetos

30

¿Qué es POO?

31

Definiendo una clase y creando sus instancias

32

Encapsulación

33

Abstracción

34

Herencia

35

Propiedades de clase en herencia

36

Polimorfismo

Finalizando nuestro proyecto

37

Creación de personaje y archivo de encabezado

38

Moviendo mi personaje con entrada de datos

39

Mapa

40

Interacción entre el personaje y el mapa

41

Paredes

42

Optimizando trazado de mapa

43

Colisiones

44

Creando nuestra portada de juego

45

Tesoro y victoria

46

Conclusiones

47

Proyecto final

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Colisiones

43/47
Recursos

Las colisiones en los videojuegos NO existen, solo son una abstracción de las colisiones para simular su comportamiento. En vez de programar el choque de nuestros elementos, vamos a crear algunas variables (lastMoveX y lastMoveY) para guardar los movimientos de nuestros jugadores y regresarlos al movimiento anterior en caso de que su último movimiento los haga “chocar” contra una pared.

Aportes 23

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Si quieren obtener el efecto pacman (Entrar por un lado y salir por el otro), puede usar el operador módulo para calcular la posición en x, y.

void Player::CallInput()
{
    char UserInput = ' ';
    cin >> UserInput;

    lastY=y;
    lastX=x;

    UserInput = tolower(UserInput);
    switch(UserInput)
    {
    case 'w':
        y = ((y - 1)%15+15)%15;
	//Deberia solo ser: (y-1)%15. Pero al momento de ser negativo el operador módulo deja de funcionar en mi c++
        break;
    case 's':
        y = (y + 1)%15;
        break;
    case 'd':
        x = (x + 1)%10;
        break;
    case 'a':
        x = ((x - 1)%10+10)%10;
        break;
    }
}

En el codigo del video hay un error al momento de guardar las coordenadas anteriores que tuvo el jugador, el profesor guarda estas coordenadas dentro del case, y es un error porque si te mueves primero con ‘s’ la coordenada incrementara, bien si el siguiente movimiento es con ‘d’ solo actualizará la coordenada x de ese ‘d’ mas no actualizará el incremento de ‘s’ anteriormente. La solución rapida que encontre fue actualizar las dos coordenadas afuera del case.

Pienso que sería mejor evaluar primero antes de cambiar una coordenada, yo lo implementaría así.

Hmmm… A mi me gusta la opción de simular el movimiento del jugador y evaluar si el movimiento es válido antes de moverlo realmente. En la práctica es casi igual, debemos crear una variable de nextMove y en caso de que todo salga mal pos no mover nada pero si el movimiento es válido ahí si moverlo…

La opcion mas optima es:

1.- Guardar la coordenada anterior antes del movimiento para en caso de no ser valido volver al anterior

–> Por que, por que los procesos son mas simples de identificar, en caso de que no pueda hacerlo, simplemente se de vuelva a la ultima, seria como un sensor de movimiento al momento de chocar retrocede y intenta por otro eje o otro angulo.

El unico error en el codigo del video es que iniciando el juego como el jugador no esta dibujado no lo dibuja hasta que pongas un movimiento valido!, lo solucione de la siguiente manera

bool GameMap::SetPlayerAxis(int *axis){

    if(cells[axis[1]][axis[0]].IsBlocked() == false){
        if(PlayerCell != NULL){
            PlayerCell->id = ' ';
        };
        PlayerCell = &cells[axis[1]][axis[0]];
        PlayerCell->id = '3';
        return true;
    }else{
        if(PlayerCell == NULL){
            PlayerCell = &cells[1][1];
            PlayerCell->id = '3';
        };
        std::cout << "WHOOPS!, te diste de frente contra una pared" <<std::endl;
        return false;
    }
    
};

Cabe acotar que he notado un movimiento extraño cuando colisionas con una pared existe la posiblidad de o que regrese x o y mal o que no se mueva en el siguiente movimiento por alguna razon que desconozco quizas es por mi funcion para tomar x y y.

int * Player::GetAxis(){
    static int axis[2];
    
    axis[0] = x;
    axis[1] = y;
    
    return axis;
};```

Realice varios Test en diferentes colisiones dentro del código que ha pasado Eri y como todo juego en ciertos lugares se presentas bugs, que inexplicablemente solo suceden en esos lugares y al colisionar en esas coordenadas exactas, creo que acá empieza el desafío en los juegos ya que se debe probar todo para evitar estos fallos.

Interesante

Tengan cuidado al colocar el if del IsBlocked, debe ser como puso el profe Eri:

if(!cells[PlayerY][PlayerX].IsBlocked())

El primer índice es de columnas y el segundo es de filas, perdí un par de horas por ese error tonto pero ahora comprendo mejor el código xD

La manera en la que implemente las colisiones fue mediante dos switch en el archivo de Player.cpp en la funcion de Player::CallInput()

switch(x){
        case 0: x += 1;
            break;
        case 9: x -= 1;
            break;
    }           
    switch(y){
        case 1: y += 1;
            break;
        case 14: y -= 1;
            break;
    }```

como se hace para que salgan varios mapas aleatorios?

Yo considero que se debería ir a la posición anterior para que continúe con la trayectoria inicial.

Creo que estoy de acuerdo con los aportes anteriores; lo haría desde el jugador, validando si se puede mover o no

Cuando presiono “D” me bota del juego y no entiendo por qué, eso que ni siquiera colisiona con alguna pared

Pienso que deberia resolverse de una 4ta forma: Deberiamos acceder al metodo IsBlocked publico para que asi se pueda acceder desde el player y evitar siquiera avanzar. Se ahorran recursos.

Hecho

`#include <iostream>
#include "Player.h"
#include "Mapaceldas.h"
#include "Gamemapa.h"

using namespace std;

int main()
{
 cout << "inicaia el juego" <<endl;
    bool isGameOver = false;
    Player heroe;
    Gamemapa MAP;
    heroe.entrada();



     while(isGameOver==false)
    {
       // loop de nuestro juego. cada vuelta del loop de nuestro juego vamos aa llamar el heroe.
        heroe.entrada();
        //actulizado de informacion heroe a mapa
       if(MAP.setplayer(heroe.x , heroe.y))
       {
       //aqui dibujamos el mapa
        MAP.drawmap();
       }

       else
        { heroe.Reset();
          MAP.drawmap();}

    }



    return 0;
}````

Si vas a hacer lo mismo dentro de todas las condiciones, es mejor quitarlo. Don’t repeat yourself:

#include <iostream>
#include "Player.h"
#include "MapCell.h"
#include "GameMap.h"

using namespace std;

int main()
{
    bool gameContinue = true;
    GameMap Map;
    Player hero;

    cout << "Inicia el juego:" << endl;
    while ( gameContinue ) {
        hero.CallInput();

        if ( !Map.setPlayerCell(hero.x, hero.y) ) {
            hero.resetToSafePosition();
        }

        Map.draw();
    }

    return 0;
}

Explicando los tres casos de solución e incluso se podría generar otras formas adicionales de manejar las colisiones y actualizar las coordenadas tiene sentido en cuanto a la forma en que Eri le da manejo en su forma de programar, asi mismo con la practica cada programador evolucionara en sus soluciones e inplementaciones a medida que se adquiere experiencia.

Yo cree las colisiones así: ( ‘H’ es el caracter que estoy usando como pared en mi laberinto )

#include "Player.h"
#include <iostream>
#include "GameMap.h"

using namespace std;

Player::Player()
{
    pos_x = 4;
    pos_y = 2;
}

void Player::Move(GameMap* maze)
{
    char input = ' ';
    cin >> input;

    switch(input){
    case 'w':
        if (maze->cells[pos_y-1][pos_x].id != 'H'){
            pos_y--;
        }
        break;
    case 'a':
        if (maze->cells[pos_y][pos_x-1].id != 'H'){
            pos_x--;
        }
        break;
    case 's':
        if (maze->cells[pos_y+1][pos_x].id != 'H'){
            pos_y++;
        }
        break;
    case 'd':
        if (maze->cells[pos_y][pos_x+1].id != 'H'){
            pos_x++;
        }
        break;
    }
    cout << pos_x << "," << pos_y << endl;
}


Yo dejaría la segunda, porque así simplemente no puedes avanzar


//Valida si el movimiento es valido viendo si no se desborda de los limites del mapa
bool Player:: IsValidMovement(char Mov)
{
    GameMap NewGameMap;

    int MaxBorderX = 9;
    int MaxBorderY = 14;
    int MinBorder = 0;

    switch(Mov)
    {
    case 'd':
        if(HeroPosX + 1 > MaxBorderX)
        {
            return false;
        }
        else if(NewGameMap.GetMapCell((HeroPosX + 1), HeroPosY).IsBlocked())
        {

            return false;
        }
        break;

    case 'a':
        if(HeroPosX - 1 < MinBorder)
        {
            return false;
        }
        else if(NewGameMap.GetMapCell((HeroPosX - 1), HeroPosY).IsBlocked())
        {

            return false;
        }
        break;

    case 'w':
        if(HeroPosY - 1 < MinBorder)
        {
            return false;
        }
        else if(NewGameMap.GetMapCell(HeroPosX, (HeroPosY - 1)).IsBlocked())
        {

            return false;
        }
        break;

    case 's':
        if(HeroPosY + 1 > MaxBorderY)
        {
            return false;
        }
        else if(NewGameMap.GetMapCell(HeroPosX, (HeroPosY + 1)).IsBlocked())
        {

            return false;
        }
        break;

    //Cualquier opción que no sea una de las anteriores
    default:
        return true;
        break;
    }



    return true;
}```

Yo haría que al detectar colisión, haya una funcion que le reste a la Posición X o Y según sea el caso (lo digo porque en el anterior reto con el mapa le puse colisiones con este método).

gracias!