Desarrollo de videojuegos para PSP con C++ y SDL/Leyendo la entrada de PSP


El problema de SDL_Joystick editar

Teóricamente, como la mayoría de tutoriales apuntan, podemos usar SDL_Joystick para manejar la entrada del jugador. Se nos presenta una equivalencia entre botones de joystick y de PSP para que podamos manejarla pero lo cierto es que, o soy tremendamente torpe, o este sistema no funciona del todo bien.


Alternativa editar

Finalmente, para $Granny's bloodbath$ decidí cambiar la implementación de la clase que manejaba la entrada del jugador (utilizando la API de las librerías de PSP) sin cambiar su interfaz, de ese modo me adaptaba a las circunstancias de PSP sin afectar al resto del sistema.

Las clases que utilicé son las siguientes y funcionan bastante bien:

keyboard.h:


/*
    This file is part of Granny's Bloodbath.

    Granny's Bloodbath is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Granny's Bloodbath is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Granny's Bloodbath.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _KEYBOARD_
#define _KEYBOARD_

#include <pspkernel.h>
#include <pspctrl.h>
#include <valarray>
#include <map>

//! Gestiona el teclado, consultamos teclas pulsadas

/**
	@author David Saltares Marquez
	@version 1.0
	
	Clase que sigue el patron de diseno Singleton (una sola instancia accesible
	desde todo el sistema).
	Lleva el control de que teclas estan pulsadas en un momento determinado,
	cuales se sueltan y cuales se vuelven a presionar.
	
	Ejemplo de uso
	
	\code
		// Game loop
		while(!quit){
			keyboard->update() // Equivalente a Keyboard::get_instance()->update();
			
			if(keyboard->pressed(Keyboard::KEY_UP)) // Si pulsamos arriba
				...
			if(keyboard->released(Keyboard::KEY_HIT)) // Si dejamos de pulsar golpear
				...
			if(keyboard->newpressed(Keyboard:KEY_SHOOT)) // Si antes soltamos y
								      // ahora pulsamos disparar
		}
	\endcode
*/
class Keyboard{
	public:
		
		/**
			Controles del teclado utilizados en el juego
		*/
		enum keys{
			KEY_UP,
			KEY_DOWN,
			KEY_RIGHT,
			KEY_LEFT,
			KEY_SHOOT,
			KEY_HIT,
			KEY_KNEEL,
			KEY_EXIT,
			KEY_ENTER
		};
		
		/**
			@return Si es la primera vez que se usa Keyboard crea su instancia y
			la devuelve. Sino simplemente la devuelve.
		*/
		static Keyboard* get_instance(){
			/* Si es la primera vez que necesitamos Keyboard, lo creamos */
			if(_instance == 0)
				_instance = new Keyboard;
			return _instance;
		}
		
		/**
			Actualiza el estado del teclado. Debe llamarse una vez al comienzo
			del game loop.
		*/
		void update();
		
		/**
			@param key Tecla a consultar
			
			@return true si la tecla esta pulsada, false en caso contrario.
		*/
		bool pressed(keys key);
		
		/**
			@param key Tecla a consultar
			
			@return true si la tecla estaba antes pulsada en la ultima actualizacion
			y ahora no lo esta, false en caso contrario.
		*/
		bool released(keys key);
		
		/**
			@param key Tecla a consultar
			
			@return true si la tecla no estaba pulsada en la ultima actualizacion y
			ahora lo esta, false en caso contrario.
		*/
		bool newpressed(keys key);
		
		/**
			@return true si se ha producido algun evento de salida, false en caso
			contrario
		*/
		bool quit();

		void set_quit() {_quit = true;}
		
	protected:
		Keyboard();
		~Keyboard();
		Keyboard(const Keyboard& k);
		Keyboard& operator = (const Keyboard& k);
	private:
		static Keyboard* _instance;
		std::weeee<bool> actual_keyboard;
		std::valarray<bool> old_keyboard;
		bool _quit;
		std::map<keys, PspCtrlButtons> configured_keys;
		SceCtrlData buttonInput;
		int n_keys;
};

#define keyboard Keyboard::get_instance()

#endif


keyboard.cpp:


#include <iostream>
#include <algorithm>
#include "keyboard.h"

using namespace std;

Keyboard* Keyboard::_instance = 0;

Keyboard::Keyboard()
{
	/* Configuracion predeterminada */
	configured_keys[KEY_UP] = PSP_CTRL_UP;
	configured_keys[KEY_DOWN] = PSP_CTRL_DOWN;
	configured_keys[KEY_LEFT] = PSP_CTRL_LEFT;
	configured_keys[KEY_RIGHT] = PSP_CTRL_RIGHT;
	configured_keys[KEY_HIT] = PSP_CTRL_CROSS;
	configured_keys[KEY_SHOOT] = PSP_CTRL_CIRCLE;
	configured_keys[KEY_EXIT] = PSP_CTRL_SELECT;
	configured_keys[KEY_ENTER] = PSP_CTRL_START;
	
	/* Inicializamos el estado del teclado */
	n_keys = configured_keys.size();
	actual_keyboard.resize(n_keys);
	old_keyboard.resize(n_keys);
	
	for(int i = 0; i < n_keys; ++i){
		actual_keyboard[false];
		old_keyboard[false];
	}
	
	_quit = false;

	sceCtrlSetSamplingCycle(0);
	sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
}

Keyboard::~Keyboard()
{
}

		
void Keyboard::update()
{	
	/* Ahora el teclado nuevo es el viejo */
	old_keyboard = actual_keyboard;

	/* Actualizamos el estado de la entrada PSP */
	sceCtrlPeekBufferPositive(&buttonInput, 1); 
	
	/* Actualizamos el estado del teclado */
	for(map<keys, PspCtrlButtons>::iterator i = configured_keys.begin();
		i != configured_keys.end(); ++i)
			actual_keyboard[i->first] = (buttonInput.Buttons & i->second)?
							actual_keyboard[i->first] = true :
								actual_keyboard[i->first] = false;
}
		
bool Keyboard::pressed(keys key)
{
	/* Devolvemos si la tecla indicada esta pulsada */
	return actual_keyboard[key];
}
				
bool Keyboard::released(keys key)
{
	/* Comprobamos si la tecla indicada no esta pulsada y antes si */
	return (!actual_keyboard[key] && old_keyboard[key]);
}
		
bool Keyboard::newpressed(keys key)
{
	/* Comprobamos si la tecla indicada esta pulsada y antes no */
	return (actual_keyboard[key] && !old_keyboard[key]);
}

bool Keyboard::quit()
{
	return _quit;
}


← La pantalla Leyendo la entrada de PSP Conclusiones →