Anuncios

Bienvenidos sean a este post, hoy veremos como implementar al primer estado.

Anuncios

Hasta el post anterior vimos como implementar los estados pero hoy veremos al primero de estos estados en accion. Usaremos el proyecto que vinimos trabajando. Sino lo poseen, les dejo un link para descargarlo:

Proyecto Juego

Anuncios

Descarguen el archivo y extraigan el contenido en el PC. Lo unico que deben hacer es revincular a SDL y SDL_Image. Para ello, les recomiendo este post donde comento como hacerlo para SDL y este otro post donde hago lo mismo para SDL_Image. Una vez que este todo funcionando correctamente, podemos continuar.

Anuncios

Para esta modificacion vamos a utilizar dos botones, les dejo los ejemplos de como pueden crearlos:

Anuncios

Este seria para el estado de Jugar, veamos la imagen del siguiente boton

Anuncios

Estos son dos ejemplos de como pueden crear las laminas de sprites para representar los tres posibles estados de los botones para nuestro menu de inicio. Si no tienen ganas de hacerlos les dejo un archivo donde estan las dos imagenes que usaremos en el proyecto:

Anuncios

Estos deberiamos extraerlos en la carpeta assets donde estuvimos extrayendo todas nuestras imagenes hasta ahora. Con esto ya tenemos todo lo relacionado a lo externo del codigo, pasemos al mismo.

Anuncios

Nuestro primer paso sera agregar una nueva clase a la cual llamaremos BotonMenu, una vez creada agregaremos el siguiente codigo en el archivo de encabezado:

BotonMenu.h

#pragma once
#ifndef __BotonMenu__
#define __BotonMenu__
#include "SDLObjetoJuego.h"
#include "ManejarEntradas.h"
#include "CargadorParams.h"

class BotonMenu : public SDLObjetoJuego
{
public:
	BotonMenu(const CargadorParams*);
	virtual void dibujar();
	virtual void actualizar();
	virtual void limpiar();

private:
	enum estado_boton {
		MOUSE_FUERA = 0,
		MOUSE_SOBRE = 1,
		CLICKEADO = 2
	};
};

#endif // !__BotonMenu__
Anuncios

Primero incluiremos tres de las clases que generamos, luego haremos a nuestra clase heredera de SDLObjetoJuego. El siguiente paso sera declarar en la parte publica los prototipos de algunas funciones, el primero que declaramos es un nuevo constructor de la clase. En esta recibiremos un parametro de tipo CargadorParams y despues tenemos tres funciones para dibujar, actualizar y limpiar.

Anuncios

En la parte privada crearemos un enum donde contendra las tres posibilidades de nuestro mouse sobre la imagen. Esto es para cuando el mouse no esta sobre la imagen, cuando el mouse esta sobre y cuando hacemos click sobre el boton respectivamente. Nuestro siguiente paso sera la definicion de estas funciones en el archivo .cpp agregando el siguiente codigo:

BotonMenu.cpp

#include "BotonMenu.h"
#include "Vector2D.h"

BotonMenu::BotonMenu(const CargadorParams* pParams):
	SDLObjetoJuego(pParams) {
	m_frameActual = MOUSE_FUERA;
}

void BotonMenu::dibujar() {
	SDLObjetoJuego::dibujar();
}

void BotonMenu::actualizar() {
	Vector2D* pPosMouse = Controles::instanciar()->getPosicionMouse();

	if (pPosMouse->getX() < (m_posicion.getX() + m_ancho)
		&& pPosMouse->getX() > m_posicion.getX()
		&& pPosMouse->getY() < (m_posicion.getY() + m_alto)
		&& pPosMouse->getY() > m_posicion.getY()) {
		m_frameActual = MOUSE_SOBRE;
		if (Controles::instanciar()->getEstadoBotonMouse(IZQUIERDO)) {
			m_frameActual = CLICKEADO;
		}
	}
	else {
		m_frameActual = MOUSE_FUERA;
	}
}

void BotonMenu::limpiar() {
	SDLObjetoJuego::limpiar();
}
Anuncios
Anuncios

Como dijimos en este archivo definiremos los prototipos de las funciones, el primero que definimos es nuestro constructor donde en base a los datos que recibimos iniciamos a SDLObjetoJuego con los mismos. En el bloque del constructor, iniciamos a m_frameActual con el valor de MOUSE_FUERA porque consideramos que el mouse no va a estar arriba de la imagen. Por lo tanto, usara el primer frame de nuestra lamina de sprites. Luego tenemos la definicion de dibujar pero en este caso usaremos la funcion dibujar de SDLObjetoJuego. Luego tenemos la funcion actualizar pero esta sera un poco mas compleja, veamos como es:

void BotonMenu::actualizar() {
	Vector2D* pPosMouse = Controles::instanciar()->getPosicionMouse();

	if (pPosMouse->getX() < (m_posicion.getX() + m_ancho)
		&& pPosMouse->getX() > m_posicion.getX()
		&& pPosMouse->getY() < (m_posicion.getY() + m_alto)
		&& pPosMouse->getY() > m_posicion.getY()) {
		m_frameActual = MOUSE_SOBRE;
		if (Controles::instanciar()->getEstadoBotonMouse(IZQUIERDO)) {
			m_frameActual = CLICKEADO;
		}
	}
	else {
		m_frameActual = MOUSE_FUERA;
	}
}
Anuncios
Anuncios

Primero crearemos un objeto de tipo Vector2D llamado pPosMouse que usaremos para saber la posicion del mouse en nuestra ventana mediante la funcion getPosicionMouse de la clase ManejadorEntradas. Una vez obtenido el valor de la posicion del mouse usaremos un condicional donde verificamos si se encuentra dentro de los margenes de la imagen. En caso de ser verdadero, primero estableceremos que m_frameActual pase al frame correspondiente a cuando estamos sobre la imagen (MOUSE_SOBRE), y despues tenemos un condicional donde verificamos si presionamos el boton izquierdo del mouse. Si se cumple la condicion, cambia el valor de m_frameActual al valor de CLICKEADO, y en caso contrario (es decir que no estamos sobre la imagen) estableceremos a m_frameActual nuevamente con el valor de MOUSE_FUERA. Por ultimo, tenemos a la funcion limpiar que al igual que dibujar la haremos llamar al limpiar de SDLObjetoJuego. Con esto tenemos concluida nuestra nueva clase pasemos a la siguiente modificacion.

Anuncios

Para seguir trabajando con este post debemos ir al archivo de encabezado de EstadoMenu, primero agregaremos las siguientes lineas para incluir estos archivos:

#include <vector>
#include "ObjetoJuego.h"
#include "Juego.h"
#include "BotonMenu.h"
Anuncios

Con esto accederemos a estas clases, nuestro siguiente paso sera agregar en su parte privada la siguiente linea:

std::vector<ObjetoJuego*> m_objetosJuego;
Anuncios

Este sera para crear una coleccion donde almacenaremos nuestros objetos del juego. Nuestro siguiente paso sera ir a EstadoMenu.cpp donde modificaremos algunas funciones. La primera que modificaremos es actualizar (el cual esta vacio) con el siguiente codigo:

void EstadoMenu::actualizar(){
	for (int i = 0; i < m_objetosJuego.size(); i++)
		m_objetosJuego[i]->actualizar();
}
Anuncios

Aqui pasaremos por todos los objetos almacenados en m_objetosJuego y usaremos la funcion actualizar de ObjetoJuego. Nuestra siguiente modificacion sera en la funcion renderizar que tambien esta en blanco y ahora agregaremos el siguiente codigo:

void EstadoMenu::renderizar(){
	for (int i = 0; i < m_objetosJuego.size(); i++)
		m_objetosJuego[i]->dibujar();
}
Anuncios

Este es igual a la funcion anterior pero esta vez usaremos a la funcion dibujar de ObjetoJuego. Nuestra siguiente modificacion sera la funcion enIngreso donde tenemos actualmente este codigo:

bool EstadoMenu::enIngreso() {
	OutputDebugStringA("Ingresando al Estado del menu\n");
	return true;
}
Anuncios

Y lo reemplazaremos por este:

bool EstadoMenu::enIngreso() {
	if (!Elmanejador::instanciar()->cargar("assets/jugar.png", "botonJugar",
		Eljuego::instanciar()->getRenderer())) {
		return false;
	}
	if (!Elmanejador::instanciar()->cargar("assets/salir.png", "botonSalir",
		Eljuego::instanciar()->getRenderer())) {
		return false;
	}

	ObjetoJuego* boton1 = new BotonMenu(new CargadorParams(100, 100, 400, 100, 
		"botonJugar"));
	ObjetoJuego* boton2 = new BotonMenu(new CargadorParams(100, 300, 400, 100, 
		"botonSalir"));
	m_objetosJuego.push_back(boton1);
	m_objetosJuego.push_back(boton2);

	OutputDebugStringA("Ingresando al Estado del menu\n");
	return true;
}
Anuncios
Anuncios

Tenemos dos condicionales donde verificamos si no se pudieron cargar las dos imagenes correspondientes a los botones que mostraremos en el menu. En ambos casos si falla la carga, usaremos un return false para salir de la funcion. En caso contrario, consideramos que se han cargado los dos y continuaremos con la creacion de los botones. Para ello, crearemos objetos de tipo ObjetoJuego para los cuales usaremos el constructor del BotonMenu y en este crearemos los objetos de tipo CargadorParams y ahi le pasaremos todos los datos de cada uno de los botones. Repasemos los atributos que pasamos:

  • la ubicacion en el eje X
  • la ubicacion en el eje Y
  • el ancho de la imagen
  • el alto de la imagen
  • el id de la textura o imagen
Anuncios

Despues de creados los dos objetos mediante push_back los agregaremos a la coleccion que creamos anteriormente. Por ultimo, dejamos el mensaje de notificacion en la salida de depuracion y por ultimo devolvemos un true para salir correctamente de la funcion. Nuestra siguiente modificacion sera en la funcion enSalida, veamos su codigo actual:

bool EstadoMenu::enSalida() {
	OutputDebugStringA("Saliendo del Estado del menu\n");
	return true;
}
Anuncios

Y lo modificaremos de la siguiente manera:

bool EstadoMenu::enSalida() {
	for (int i = 0; i < m_objetosJuego.size(); i++)
		m_objetosJuego[i]->limpiar();

	m_objetosJuego.clear();
	Elmanejador::instanciar()->limpiaMapaTexturas("botonJugar");
	Elmanejador::instanciar()->limpiaMapaTexturas("botonSalir");

	OutputDebugStringA("Saliendo del Estado del menu\n");
	return true;
}
Anuncios

Mediante un bucle pasaremos por todos los elementos de m_objetosJuego y por cada uno usaremos a limpiar para eliminarlos. Despues usaremos a clear para limpiar la coleccion, y por ultimo usaremos una funcion para eliminar las texturas o imagenes de los dos botones. Al final, seguimos manteniendo el mensaje en la salida de depuracion. La funcion limpiaMapaTexturas no existe y por ende nos quedara con error, pero para solucionar esto debemos ir primero a ManejarTexturas.h y agregaremos la siguiente linea en la parte publica:

void limpiaMapaTexturas(std::string);
Anuncios

Lo siguiente sera ir a ManejarTexturas.cpp y definiremos a esta funcion con el siguiente bloque:

void ManejarTexturas::limpiaMapaTexturas(std::string id) {
	m_mapaTextura.erase(id);
}
Anuncios

Esta funcion se encarga de eliminar la imagen o textura informada en id del mapa de texturas. Con esto tenemos completo nuestras ultimas modificaciones, podemos compilarlo y ver como funciona hasta ahora mediante el siguiente video

Anuncios

En el video podemos ver como los menus reaccionan a nuestro tres tipos de acciones, ya sea pasar por arriba, clickearlo o salir del mismo, con esto ya hicimos un gran avance en nuestros estados pero esto aun no termina es recien el comienzo.

Anuncios

En resumen, hoy hemos implementado un menu de inicio controlado con FSM, como poder controlar mediante las clases anteriores la implementacion del mismo, como podemos monitorear donde esta nuestro mouse para saber que estado debe tener el boton. Espero les haya sido de utilidad y les dejo un link a GitHub donde estan los codigos creados hoy:

Implementando el Menu / GitHub

Les dejo algunas de mis redes sociales para seguirme o recibir una notificacion cada vez que subo un nuevo post:

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50