SDL en C bajo GNU/Linux 007 – Dibujando una lluvia de estrellas


  
Es posible que mucha gente recuerde “el juego de la mariquita”. Aquí puede verse un ejemplo de estos juegos en los que movías una mariquita (o lo que fuese) por la pantalla para ir creando zonas cerradas que mostrasen un fragmento de una imagen oculta. Normalmente eran fotos porno por cierto: https://www.youtube.com/watch?v=EJSUA88b9zo
  
Para hacer algo similar primero hemos de saber como dibujar un simple pixel en pantalla.
Descarga el código aquí: pixel.zip
  
El código creo que se entiende bien si has seguido estos artículos ya que solamente incorporamos un par de funciones nuevas. Si no has leído los anteriores artículos te lo recomiendo: https://mierda.tv/?s=SDL+en+C
  
Examinemos el código para dibujar un fondo negro y sobre este fondo un pixel rojo en la posición x=20 e y=20 :
  

#include <SDL.h>
#include <stdbool.h>

int main(int argc, char ** argv) {

	SDL_Window * ventana;
	SDL_Renderer * render;
	SDL_Event evento;
	bool quit = false;
		
	SDL_Rect fondo = { 0, 0, 640, 480 }; // un rectangulo que ocupará toda la ventana.
	SDL_Rect pixel = { 0, 0, 1, 1 }; // posicionado en 0,0 con ancho 1 y alto 1, es decir, un pixel arriba a la izquierda.

	/* // Otra forma 
	SDL_Rect pixel; 
	pixel.x = 0; // posición x
	pixel.y = 0; // posición y
	pixel.w = 1; // ancho
	pixel.h = 1; // alto
	*/
	
	SDL_Init(SDL_INIT_VIDEO);
	ventana = SDL_CreateWindow("Ejemplo de dibujar pixel en pantalla",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_OPENGL);

	if (ventana == NULL) { printf("No se pudo crear la ventana: %s\n", SDL_GetError());	return 1; }
	
	render = SDL_CreateRenderer(ventana, -1, 0);
	
	SDL_SetRenderDrawColor(render, 1, 1, 1, 255); // RGB será negro. El cuarto valor es alpha. 255 es opaco.
	SDL_RenderFillRect(render, &fondo);
	SDL_RenderDrawPoint(render, 0, 0);
        SDL_RenderPresent(render); // presentamos el render del fondo.
	SDL_RenderClear(render); // limpiamos

	SDL_SetRenderDrawColor(render, 255, 0, 0, 255); // RGB será rojo. El cuarto valor es alpha. 255 es opaco.
	SDL_RenderFillRect(render, &pixel);
        SDL_RenderDrawPoint(render, 20, 20); // lo posicionamos arriba a la izquierda en x=20 e y=20
        SDL_RenderPresent(render); // presentamos el render del pixel rojo
        SDL_RenderClear(render); // limpiamos
	

	while (!quit) {
		SDL_WaitEvent(&evento);

		switch (evento.type) {
			case SDL_QUIT:
				quit = true;
				break;
		}


	}

}

  
Al ejecutarlo tendremos algo así (se ve poco el pixel rojo pero se tiene que ver si limpias un poco tu pantalla):
  

  

Estás son las funciones nuevas que no habíamos usado aún en esta serie de tutoriales ( o lo que sean):

SDL_RenderFillRect

SDL_SetRenderDrawColor

SDL_RenderDrawPoint

SDL_RenderClear

	SDL_SetRenderDrawColor(render, 1, 1, 1, 255); // RGB será negro. El cuarto valor es alpha. 255 es opaco.
	SDL_RenderFillRect(render, &fondo);
	SDL_RenderDrawPoint(render, 0, 0);
        SDL_RenderPresent(render); // presentamos el render del fondo.
	SDL_RenderClear(render); // limpiamos

	SDL_SetRenderDrawColor(render, 255, 0, 0, 255); // RGB será rojo. El cuarto valor es alpha. 255 es opaco.
	SDL_RenderFillRect(render, &pixel);
        SDL_RenderDrawPoint(render, 20, 20); // lo posicionamos arriba a la izquierda en x=20 e y=20
        SDL_RenderPresent(render); // presentamos el render del pixel rojo
        SDL_RenderClear(render); // limpiamos

  
Como puede verse no requiere mucho esfuerzo. Nos permite por ejemplo crear un cielo estrellado.  
Veamos como podemos hacer un cielo estrellado o mejor, una lluvia de estrellas.
  
Para que no sea tan rollo podemos realizar una lluvia de estrellas
  
Aquí el código en un zip para descargar: lluvia
  
Aquí el código para llevar:
  

#include <SDL.h>
#include <stdbool.h>


int main(int argc, char ** argv) {

	SDL_Window * ventana;
	SDL_Renderer * render;
	SDL_Event evento;
	bool quit = false;
		
	SDL_Rect fondo = { 0, 0, 640, 480 }; // un rectangulo que ocupará toda la ventana.
 
	SDL_Rect pixel; 
	pixel.x = 0; // posición x
	pixel.y = 0; // posición y
	pixel.w = 1; // ancho
	pixel.h = 1; // alto

	int xEstrellas[100];
	int yEstrellas[100];

	int xMax = 640;	int xMin = 1;
	int yMax = 480;	int yMin = 1;

	int x,y,z;	
	for (x = 0; x < 100; x++) {	xEstrellas[x] = rand()%(xMax-xMin)+xMin; }
	for (y = 0; y < 100; y++) {	yEstrellas[y] = rand()%(yMax-yMin)+yMin; }
		
	
	SDL_Init(SDL_INIT_VIDEO);
	ventana = SDL_CreateWindow("Ejemplo de lluvia de estrellas",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_OPENGL);

	if (ventana == NULL) { printf("No se pudo crear la ventana: %s\n", SDL_GetError());	return 1; }
	
	render = SDL_CreateRenderer(ventana, -1, 0);
	
	SDL_SetRenderDrawColor(render, 1, 1, 1, 255); // RGB será negro. El cuarto valor es alpha. 255 es opaco.
	SDL_RenderFillRect(render, &fondo);
	SDL_RenderDrawPoint(render, 0, 0);
        SDL_RenderPresent(render);
	SDL_RenderClear(render);
	

	int contador2 = 1;
	while (contador2 < 10){
		for (y = 0; y < 100; y++) {	yEstrellas[y] = rand()%(yMax-yMin)+yMin; }
		int contador = 1;
		while (contador < 13) {
			for (z = 0; z < 100; z++) {
				yEstrellas[z]=yEstrellas[z]+1;
				SDL_RenderFillRect(render, &pixel);
				SDL_RenderDrawPoint(render, xEstrellas[z], yEstrellas[z]);
			}		
			SDL_Delay(50);
			if (contador >= 3 ) { SDL_SetRenderDrawColor(render, 235, 235, 235, 255); }    
			if (contador >= 4 ) { SDL_SetRenderDrawColor(render, 225, 225, 225, 255); }    
			if (contador >= 5 ) { SDL_SetRenderDrawColor(render, 215, 215, 215, 255); }    
			if (contador >= 6 ) { SDL_SetRenderDrawColor(render, 200, 200, 200, 255); }
			if (contador >= 7 ) { SDL_SetRenderDrawColor(render, 170, 170, 170, 255); }    
			if (contador >= 8 ) { SDL_SetRenderDrawColor(render, 140, 140, 140, 255); }    
			if (contador >= 9 ) { SDL_SetRenderDrawColor(render, 100, 100, 100, 255); }    
			if (contador >= 10 ) { SDL_SetRenderDrawColor(render, 60, 60, 60, 255); }    
			if (contador >= 11 ) { SDL_SetRenderDrawColor(render, 20, 20, 20, 255); }    
			if (contador >= 12 ) { SDL_SetRenderDrawColor(render, 1, 1, 1, 255); }    
			SDL_RenderPresent(render);
			contador=contador+1;
		}

		//SDL_Delay(150);

		SDL_SetRenderDrawColor(render, 1, 1, 1, 255); // RGB será negro. El cuarto valor es alpha. 255 es opaco.
		SDL_RenderFillRect(render, &fondo);
		SDL_RenderDrawPoint(render, 0, 0);
		SDL_RenderPresent(render);
		SDL_RenderClear(render);
		contador2=contador2+1;
    }



	while (!quit) {
		SDL_WaitEvent(&evento);

		switch (evento.type) {
			case SDL_QUIT:
				quit = true;
				break;
		}


	}

}

  
Código que al compilarlo ofrecerá algo así como esto:
  

  
Mucho mejor que dibujar un simple pixel generar un aray de posiciones en los que dibujarlos y simular al ser fondo negro que cada punto es una estrella. Si se usan degradados de gris se puede conseguir un efecto de profundidad (las estrellas más blancas lucen más, están más cerca, las menos blancas más lejos, las casi negras muy lejos, …).
  
En el caso del ejemplo vemos que se generarán 10 escenarios aleatorios de lluvia de estrellas en las que veremos caer las estrellas dejando un pequeño halo.
  
Ese degradado del halo puede servir como efecto en disparos. Que los disparos dejen un pequeño rastro de sus colores degradados puede ser un efecto chuli que generará o ayudará a entender el movimiento y que quede más suave.
  
Una vez sabemos dibujar un píxel en pantalla y dibujar muchos supongo que podremos imaginar ese juego del que hablaba al principio. Ir moviendo con los cursores un pixel que va dejando su rastro es algo sencillo.
  
Si no sabes como puedes mirar el post: https://mierda.tv/2017/05/07/sdl-en-c-bajo-gnulinux-005-moviendo-con-el-teclado-un-objeto/
  
Lo cierto es que me he enfrascado en el código de la lluvia de estrellas queriendo hacer algo mucho más complejo. Al final ando ya sin energía y aunque se que es una chapucilla pues funciona de igual forma.
  
Algunas veces es mejor dejar reposar una función o algún código que andas realizando y seguirlo otro día. Si te enfrascas con algo es posible que termines consiguiendo lo que querías pero si lo revisas otro día verás que lo mismo estabas haciendo las cosas más complicadas de lo que se precisa.
  
Saludos cordiales.

Deja un comentario