Código!!
Para el que haya echado un vistazo al pdf que sigo, notará que he hecho un copy-paste impresionante, y
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; } } } }