El código al que hacía referencia es el de pruebas.cpp, en la parte donde se evalúa el tipo de evento agregué el código que mostré para procesar los clics del ratón, por eso no puse todo:
- Código: Seleccionar todo
/* Pilas engine - Un motor de videojuegos
*
* Copyright 2010 - Hugo Ruscitti
* Licencia: LGPLv3 (vea http://www.gnu.org/licenses/lgpl.html)
* Website - http://www.pilas-engine.com.ar
*
* El motor original está creado en Python,
* esta es la implementación en C++
* Lea el archivo AUTORES para saber quiénes la realizan.
*/
#include "actores.h"
#include "texto.h"
#include "sonido.h"
#include <vector>
using std::vector;
#include <iostream>
using std::cout;
using std::endl;
int main( int argc, char* argv[] )
{
// Crea la ventana principal
sf::RenderWindow ventana( sf::VideoMode( 800, 600 ), "PilasC++" );
// Crea un nuevo actor de ejemplo
Pilas::Mono mono;
// Lo coloca al centro de la pantalla
mono.establecer_x( 400 );
mono.establecer_y( 300 );
// Agranda 300% la imagen del mono
mono.establecer_escala( 3 );
// Actores en pantalla
vector< Pilas::Actor* >actores;
// Agrega actores al vector
actores.push_back( &mono );
// Texto en pantalla
sf::Font fuente;
fuente.LoadFromFile( "data/FreeMono.ttf" );
Pilas::Texto mensaje( "Hola PilasC++\nPulsa [A] [B] o [C]", fuente, 20 );
mensaje.establecer_color( sf::Color( 255, 255, 255 ) );
//Creamos el evento solo una vez mejor
// Procesa eventos.
sf::Event evento;
// Ciclo principal
while( ventana.IsOpened() ) {
while( ventana.GetEvent( evento ) ) {
// Cierre de ventana
if ( evento.Type == sf::Event::Closed )
ventana.Close();
// Presión de teclas. Mejor un switch, ya que nos evitamos tener que
//ejecutar todos los condiciones en caso de que se de un evento
else if ( evento.Type == sf::Event::KeyPressed ) {
switch (evento.Key.Code)
{
case sf::Key::Escape:
ventana.Close();
break;
case sf::Key::A:
mono.establecer_rotacion( 0 );
mono.normal();
break;
case sf::Key::B:
// Gira imagen 45° en sentido horario
mono.establecer_rotacion( 45 );
mono.gritar();
break;
case sf::Key::C:
// Gira imagen 45° en sentido antihorario
mono.establecer_rotacion( -45 );
mono.sonreir();
break;
default:
break;
}
}
else if ( evento.Type == sf::Event::MouseButtonPressed )
{
int* ptr = &evento.MouseMove.Y;
cout << "Clic de ratón en: " << evento.MouseButton.X << ", " << evento.MouseButton.Y << endl;
cout << "Clic de ratón en: " << evento.MouseMove.Y << ", " << *( ptr + 1 ) << endl;
cout << "Ratón en: " << ventana.GetInput().GetMouseX() << ", " << ventana.GetInput().GetMouseY() << endl;
}
}
// Limpia la pantalla
ventana.Clear();
// Dibuja los actores
for ( unsigned i = 0; i < actores.size(); i++ )
{
ventana.Draw( *actores[ i ] );
}
// Mensajes de texto
ventana.Draw( mensaje );
// Actualiza pantalla
ventana.Display();
sf::Sleep( 0.1 );
}
return EXIT_SUCCESS;
}
Ahora, sobre las señales, tengo nuevamente dudas al comparar con la versión Python, en la que se definen clases para cada "comportamiento" pero, tal como con BaseActor, estas clases hacen uso de variables que no se heredan ni están declaradas, así se puede definir la clase SeguirAlMouse:
- Código: Seleccionar todo
class SeguirAlMouse:
"Hace que un actor siga la posición del mouse en todo momento."
def __init__(self):
pilas.eventos.mueve_mouse.connect(self.move)
def move(self, sender, x, y, signal):
self.x = x
self.y = y
¿Cómo replicaríamos eso en C++? Había pensado en que, si se pudiera hacer una clase similar, después se crearía una nueva clase heredando de esta y del actor o elemento deseado:
- Código: Seleccionar todo
class MonoSigueClics : public Pilas::Mono, public Pilas::SeguirAlMouse
...
El detalle, ¿de dónde debería heredar SeguirAlMouse para poder tener los atributos que la versión Python y que no haya que reescribir lo que se desea hacer en la función?
No se puede heredar de sf::Drawable, es abstracta, de sf::Sprite tampoco porque luego faltaría especificar si estamos modificando los atributos de Mono o de Sprite.
Entonces, lo que pensaba era que se deberían tener funciones virtuales para los eventos, y podrían estar dentro de una clase donde solo se tengan funciones virtuales, después crear una nueva clase mezclando esta clase abstracta y la de interés:
- Código: Seleccionar todo
class EventosRaton
{
virtual void al_hacer_clic( boton, x, y );
virtual void al_soltar_boton( boton, x, y );
virtual void al _mover_raton( x, y );
};
class MonoSigueClics : public Mono, public EventosRaton
{
void al_hacer_clic( boton, x, y )
{
if ( boton == izquierdo )
{
establecer_x( x );
establecer_y( y );
}
}
}
El detalle aquí es que no sería "combinar" con una clase que "sigue clics", sino de una que puede recibir valores relacionados con el evento del ratón y entonces escribir en su redefinición el código para mover el actor a la posición que se quiere.
¿Qué opinan?