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;
}
}
}
}

