En esta parte del SFML, veremos cómo crear nuestra primera aplicación básica de SFML. En el corazón de cada aplicación SFML se encuentra el RenderWindow que proporciona una forma de dibujar cosas en la pantalla y recibir eventos de entrada del usuario.
Como siempre, hay un video HD de este tutorial aquí.
En el corazón de cada juego no trivial está el ciclo del juego. En algunos motores de juegos, está escondido dentro del motor, pero siempre está ahí en alguna parte. En SFML es su responsabilidad implementar, que es lo que haremos hoy. Un bucle de juego es un concepto bastante simple… es un bucle que se ejecuta una y otra vez hasta que se completa el juego. Cada vez que pasa por el bucle, la pantalla se borra y se dibujan nuevos gráficos (esto se conoce como cuadro, por lo que cuando escucha Cuadros por segundo, esto es a lo que se refiere). Hay varias otras tareas que un juego es responsable de manejar… entrada y física, por nombrar solo dos.
Comencemos con una aplicación muy simple:
#include "SFML/Graphics.hpp" int main(int argc, char ** argv) { sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo"); while (true) { renderWindow.clear(); renderWindow.display(); } }
Esto representa la aplicación SFML significativa más simple que puede crear. Creamos una nueva RenderWindow, pasando tanto sus dimensiones como su título. Luego, simplemente hacemos un bucle para siempre y cada vez que pasamos por el bucle limpiamos la ventana y luego la dibujamos de nuevo con una llamada a display().
Cuando ejecute este código, obtendrá una ventana negra de 640 × 480 en la pantalla; sin embargo, si intenta mover o cerrar esta ventana, notará rápidamente que algo anda mal. No responde a ninguna de tus acciones. De hecho, si pierde el enfoque (haga clic en una ventana diferente), ¡ni siquiera podrá volver a enfocarlo! Esto se debe a que no estamos respondiendo a ningún evento. Cambiemos un poco las cosas para que la ventana responda un poco más. En lugar de simplemente repetir para siempre, crearemos un bucle de juego un poco más inteligente.
sf::Event event; while(renderWindow.isOpen()){ // Check for all the events that occured since the last frame. while (renderWindow.pollEvent(event)){ //Handle events here if (event.type == sf::Event::EventType::Closed) renderWindow.close(); } renderWindow.clear(); renderWindow.display(); }
Ahora su ventana responde correctamente a los eventos, se puede mover y, lo que es más importante, se puede cerrar. Echemos un vistazo rápido a lo que hemos hecho aquí.
En primer lugar, en lugar de hacer un bucle para siempre, hacemos un bucle hasta que nuestra RenderWindow se cierra. A continuación, dentro de este ciclo, hemos implementado otro ciclo while que llama a pollEvent. pollEvent verifica todos los eventos que ocurrieron desde la última vez que se llamó a pollEvent. Se llama dentro de un ciclo while porque es posible que hayan ocurrido múltiples eventos desde el último paso por el ciclo externo. pollEvent() devolverá falso cuando no existan más eventos. Existen eventos para cosas como las acciones del mouse y el teclado o el cambio de tamaño de la ventana. En este caso particular, estamos comprobando si EventType está cerrado, lo que significa que se ha producido una solicitud de cierre. En el caso de que lo haga, llamamos a renderWindow.close(), lo que dará como resultado que la próxima verificación de isOpen() devuelva falso, finalizando así nuestro juego.
Cubriremos los eventos con más detalle más adelante, pero para tener una idea de qué tipos de eventos existen, haga clic aquí. Hay dos cosas muy importantes a tener en cuenta en este bucle de juego. ¿Observe que el sf::Event se declara fuera del ciclo? Este código se va a llamar MUCHO. Nunca coloque asignaciones variables, incluso las basadas en pilas como esta, dentro de un bucle de alta frecuencia si se puede evitar. En segundo lugar, observe cómo las llamadas clear() y display() están fuera del ciclo interno pollEvent(). ¡Esto también es importante, ya que de lo contrario su pantalla solo se actualizará cuando ocurra un evento!
Hay un último concepto importante que cubrir antes de pasar al siguiente tutorial… el tiempo. Es bastante común que un motor de juego proporcione el tiempo transcurrido desde el último cuadro. Este valor es muy útil para todo tu juego como veremos en breve. En SFML, sin embargo, está lanzando su propio bucle de juego, por lo que también está lanzando su propio sistema de seguimiento de tiempo. Sin embargo, no se preocupe, el proceso es extremadamente simple. Veamos una última muestra completa que también realiza un seguimiento del tiempo transcurrido por cuadro.
#include "SFML/Graphics.hpp" #include <iostream> int main(int argc, char ** argv) { sf::RenderWindow renderWindow(sf::VideoMode(640, 480), "SFML Demo"); sf::Event event; // A Clock starts counting as soon as it's created sf::Clock clock; while(renderWindow.isOpen()){ // Check for all the events that occured since the last frame. while (renderWindow.pollEvent(event)){ //Handle events here if (event.type == sf::Event::EventType::Closed) renderWindow.close(); } // A microsecond is 1/1,000,000th of a second, 1000 microseconds == 1 millisecond std::cout << "Elapsed time since previous frame(microseconds): " << clock.getElapsedTime().asMicroseconds() << std::endl; // Start the countdown over. Think of laps on a stop watch. clock.restart(); renderWindow.clear(); renderWindow.display(); } }
Notarás la adición de un sf::Reloj a nuestro juego. El reloj proporciona la hora más precisa que el sistema operativo subyacente es capaz de dar (diferentes temporizadores tienen diferentes resoluciones, ¡y este temporizador debe ser muy preciso!). Tan pronto como se declara, comienza a contar. Piense en sf::Clock como un cronómetro que se inicia automáticamente. En cada «vuelta» puede leer el tiempo transcurrido usando getElapsedTime() y puede comenzar una nueva vuelta llamando a restart(). En este ejemplo obtenemos el tiempo transcurrido en microsegundos. Hay 1000 microsegundos en un milisegundo y 1000 milisegundos en un segundo, por lo que un microsegundo es una millonésima de segundo. Como dije, ¡necesitamos precisión!
Ese es el proceso de crear una aplicación SFML muy simple, limpiar y mostrar la ventana, rastrear cuánto tiempo transcurrió y manejar eventos. En el próximo tutorial, veremos los eventos un poco más de cerca y veremos cuál es la mejor manera de manejar la entrada del teclado.
El video
Programación SFML CPP Tutorial 2D