Simples gráficos en SDL

Código!!


Para el que haya echado un vistazo al pdf que sigo, notará que he hecho un copy-paste impresionante, y para colmo de males, no funciona CORREGIDO. Tengo que revisar mejor el código, pero algo hace que se cuelgue y tenga que cerrar por las malas la terminal.

ACTUALIZACIÓN: Tengo la manía de poner siempre las llaves en el código, el pdf no los pone cuando puede omitirlos y yo me equivoqué al escribirlos, metiendo en los if y bucles código que no correspondía.

pixels.h: Pulsa para ver/ocultar el código
// Listado: pixels.h
// Fichero de Cabecera
// Funciones para el manejo de píxeles dentro de superficies

#ifndef _PIXELS_H_
#define _PIXELS_H_

enum colores {R, G, B};

// Esta función sustituye el color del píxel (x, y) de la superficie
// surface por el color que recibe en el parámetro pixel
void PutPixel(SDL_Surface *superficie, int x, int y, Uint32 pixel);


// Esta función devuelve el color del píxel de la
// posición (x, y) de la superficie
Uint32 GetPixel(SDL_Surface *superficie, int x, int y);
#endif
pixels.c: Pulsa para ver/ocultar el código
// Listado: pixels.c
// Funciones para el manejo de píxeles dentro de superficies


#include <SDL/SDL.h>
#include "pixels.h"


void PutPixel(SDL_Surface *superficie, int x, int y, Uint32 pixel) {
 // Obtenemos la profundida de color
 int bpp = superficie->format->BytesPerPixel;

 // Obtenemos la posición del píxel a sustituir
 Uint8 *p = (Uint8 *)superficie->pixels + y * superficie->pitch + x*bpp;

 // Según sea la profundidad de color
 switch (bpp) {
  case 1: // 8 bits (256 colores)
   *p = pixel;
   break;
  case 2: // 16 bits (65536 colores o HigColor)
   *(Uint16 *)p = pixel;
   break ;
  case 3: // 24 bits (True Color)
   // Depende de la naturaleza del sistema
   // Puede ser Big Endian o Little Endian
   if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
    // Calculamos cada una de las componentes de color
    // 3 bytes, 3 posiciones
    p[R]=(pixel >> 16) & 0xFF;
    p[G]=(pixel >> 8) & 0xFF;
    p[B]=pixel & 0xFF;
   }else {
    // Calculamos cada una de las componentes de color
    // 3 byes, 3 posiciones
    p[R]=pixel & 0xFF;
    p[G]=(pixel >> 8) & 0xFF;
    p[B]=(pixel >> 16) & 0xFF;
   }
   break ;
  case 4: // 32 bits (True Color + Alpha)
   *(Uint32 *) p = pixel;
   break ;
 }
 }


Uint32 GetPixel(SDL_Surface *superficie, int x, int y) {
 // Obtenemos la profunidad de color
 int bpp = superficie->format->BytesPerPixel;

 // Obtenemos la posición del píxel a consultar
 Uint8 *p = (Uint8 *)superficie->pixels + y * superficie->pitch + x * bpp;
 
 // Según sea la profundidad de color
 switch (bpp) {
  case 1: // 256 colores
   return *p;
  
  case 2: // 65536 colores
   return *(Uint16 *)p;

  case 3: // True Color
   // Según la naturaleza del sistema
   if (SDL_BYTEORDER == SDL_BIG_ENDIAN){
    // OR entre los distintos componentes del color
    return p[R] << 16 | p[G] << 8 | p[B];
   }else{
    // OR entre los distintos componentes del color
    return p[R] | p[G] << 8 | p[B] << 16;
   }

  case 4: // True Color + Alpha
   return *(Uint32 *)p;

  default :
   return 0;
 }
 }


Recta.h: Pulsa para ver/ocultar el código
#ifndef _RECTA_H_
#define _RECTA_H_

// Dibuja una recta entre dos puntos p0 y p1 definidos por (x0, y0) y
// (x1, y1) del color definido por el parámetro color.
void Recta(SDL_Surface *superficie, int x0, int y0, int x1, int y1, Uint32 color);

#endif
recta.c: Pulsa para ver/ocultar el código
// Listado: recta.c
//
// Implementación de las funciones

#include <SDL/SDL.h>
#include <math.h>

#include "pixels.h"
#include "recta.h"

void Recta(SDL_Surface *superficie, int x0, int y0, int x1, int y1, Uint32 color) {
 // Calculamos la longitud de la recta
 int longitud = sqrt(pow((x1 - x0), 2) + pow((y1 - y0), 2));

 // La longitud no debe ser negativa
 if (longitud < 0){
  longitud = -1 * longitud;
 }
  int i = 0;
  for (i = 0; i < longitud; i++) {
   // Si es vertical aumento y
   if (x0 == x1) {
    y0++;
    PutPixel(superficie, x0, y0, color);
   }

   // Si es horizontal aumento x
   if (y0 == y1) {
    x0++;
    PutPixel(superficie, x0, y0, color);
   }
  }
 
}


cuadrado.h: Pulsa para ver/ocultar el código
// Listado: cuadrado.h
//
// Fichero de cabecera

#ifndef _RECTA_H_
#define _RECTA_H_

// Dibuja un cuadrado en la superficie, del color especificado
// en el parámetro color y con su esquina superior izquierda
// en (x, y)
void Cuadrado(SDL_Surface *superficie, int x, int y, int lado, Uint32 color);

#endif
cuadrado.c: Pulsa para ver/ocultar el código

#include <SDL/SDL.h>

#include "recta.h"
#include "cuadrado.h"

void Cuadrado(SDL_Surface *superficie, int x, int y, int lado, Uint32 color) {
 // Dibujamos las verticales paralelas
 Recta(superficie, x, y, x, y + lado, color);
 Recta(superficie, x + lado, y, x + lado, y + lado, color);

 // Dibujamos las horizontales paralelas
 Recta(superficie, x, y, x + lado, y, color);
 Recta(superficie, x, y + lado, x + lado, y + lado, color);
}


circunferencia.h: Pulsa para ver/ocultar el código
// Listado: circunferencia.h
// Función que crea un círculo en una superficie

#ifndef _CIRCUNFERENCIA_H_
#define _CIRCUNFERENCIA_H_

void Circunferencia(SDL_Surface *superficie, int x, int y, int radio, Uint32 color);

#endif
circunferencia.c: Pulsa para ver/ocultar el código
// Listado: circunferencia.c
// Creación de un círculo en una superficie de SDL

#include <SDL/SDL.h>
#include <math.h>

#include "pixels.h"

void Circunferencia(SDL_Surface *superficie, int x, int y, int radio, Uint32 color) {
 int puntos = 0;
 float angulo_exacto;
 int x0 = x;
 int y0 = y;
 int x_aux, y_aux;

 while (puntos < 256) {
  angulo_exacto = puntos * M_PI / 128;
  x = radio * cos(angulo_exacto);
  y = radio * sin(angulo_exacto);
  
  x_aux = x + radio + x0;
  y_aux = y + radio + y0;

  // Evitamos dibujar fuera de la superficie
  if (!(x_aux < 0 || y_aux < 0 || x_aux > superficie->w || y_aux > superficie->h)){
   PutPixel(superficie, x_aux, y_aux, color);
  }
   puntos++;
 }
}


main.c: Pulsa para ver/ocultar el código
// Listado: main.c
// Programa de prueba,

#include <stdio.h>
#include <time.h>
#include <SDL/SDL.h>

#include "circunferencia.h"


int main(){
 // Vamos a dibujar píxeles en pantalla
 SDL_Surface *pantalla;

 // Variables auxiliares
 Uint32 color, comprobacion;
 Uint8 *buffer;
 SDL_Event evento;

 int i;
 int pos_x, pos_y, radio;

 // Llama a SDL_Quit() al salir
 atexit(SDL_Quit);

 // Iniciamos SDL
 if (SDL_Init(SDL_INIT_VIDEO) < 0){
  fprintf(stderr, " No se pudo iniciar SDL: %s\n", SDL_GetError());
  exit(1);
 }

 // Es compatible el modo de video?
 if (SDL_VideoModeOK(640, 480, 24, SDL_SWSURFACE) == 0) {
  fprintf(stderr, "Modo no soportado: %s\n", SDL_GetError());
  exit(1);
 }
 
 // Una vez comprobado establecemos el modo de video
 pantalla = SDL_SetVideoMode(640, 480, 24, SDL_SWSURFACE);
 if (pantalla == NULL) {
  printf("SDL_SWSURFACE 640 x 480 x 24 no compatible.\n");
  printf("Error: %s\n", SDL_GetError());
 }

 // Si hay que bloquear la superficie se bloquea
 if (SDL_MUSTLOCK(pantalla)){
  SDL_LockSurface(pantalla);
 }
  
 // Vamos a dibujar píxeles rosa
 color = SDL_MapRGB(pantalla->format, 128, 128, 255);

 // Dibujamos 20 circunferencias aleatorias
 srand(time(NULL)); // Establecemos la semilla 
 for (i = 0; i < 20; i++) {
  // Número aleatorio dentro del rango
  pos_x = rand() % 640;
  pos_y = rand() % 480;
  radio = rand() % 100;
  Circunferencia(pantalla, pos_x, pos_y, radio, color);
 }

 // Actualizamos la pantalla parar mostrar el cambio
 SDL_Flip(pantalla);

 // Una vez dibujado procedemos a desbloquear la superficie
 // Siempre y cuando hubiese sido bloqueada
 if (SDL_MUSTLOCK(pantalla)){
  SDL_UnlockSurface(pantalla);
 }

 // Ahora mantenemos el resultado en pantalla
 // Hasta pulsar escape
 while(1==1) {
  // Consultamos los eventos
  while (SDL_PollEvent(&evento)) {
   if (evento.type == SDL_QUIT){ // Si es de salida
    return 0;
   }
  }
 }
}

Etiquetas: ,,. Guarda el enlace permanente.

Deja un comentario ^^