mis primeros pasos con SDL
por
- 03/10/2008 a las 17:12 (2297 Visitas)
Hola, hace unos días me puse a chapurrear con C y SDL así que aún ando bastante verde, he decidido colgar aquí mi código para que la gente pueda opinar, mejorar y aprender. Mi intención es hacer como un wiki de mis códigos, y que cada uno pueda poner lo que quiera como comentario y así yo iré cambiando el código original para ir mejorandolo.
El código que voy a colgar es un Pong muy básico -por algo hay que empezar-, el cual he comentado un poco para que se pueda entender, imagino que el código será bastante basura pero espero que entre todos pueda quedar algo decente y entendible. Entender que es la primera vez que programo con SDL, y que mi experiencia con C es bastante corta. Bueno aquí os dejo el código. ¡Espero que no me tiréis muchas piedras!
Código:#include <stdio.h> #include <stdlib.h> #include <SDL/SDL.h> #include "SDL/SDL_ttf.h" //definimos y inicializamos las constantes const int alto=480; const int largo=800; const int pos=445; const int posE=21; //definimos variables globales int col=1; //enumerado dirección enum direccion{izquierda, derecha, ninguna}; // Structure definitions // Definimos la estrucutra barraPong, que representará la barra del jugador y la barra del enemigo (máquina). struct barraPong{ SDL_Rect area; SDL_Color color; int vel; int aceleracion; int puntuacion; } jugador={{50,pos,120,15},{255,255,255},0,0}, enemigo={{50,posE,120,15},{255,255,255},0,0}; // Definimos la estructura pelota ( que en realidad es un rectángulo). struct pelota{ SDL_Rect area; SDL_Color color; //Vector de direccion float vectX; float vectY; }pelota={{50,70,10,10},{254,254,254},1,1}; // Function definitions // Definimos la función colisión, que detecta si hay una colisión entre dos rectángulos. int colision(SDL_Rect *r1, SDL_Rect *r2){ return(((r1->x+r1->w)>r2->x)&&((r1->y+r1->h)>r2->y)&&((r2->x+r2->w)>r1->x)&&((r2->y+r2->h)>r1->y)); } /* Definimos la función moverBarra, a la que se le pasa un puntero de tipo barraPong y una dirección hacia la que se va a mover la barra si la dirección es ninguna la barra no se mueve, pero comprueba si hay colisiones. */ void moverBarra(barraPong *barra, direccion dir){ int desplazamiento=10; float rozamiento=0.18; //si la barra se mueve hacia la izquierda o a la derecha... if((dir==izquierda&&barra->area.x-desplazamiento>0)||(dir==derecha&&barra->area.x+barra->area.w+desplazamiento<largo)){ //si hay colision if(colision(&pelota.area, &barra->area)){ //cambiamos el sentido vertical de la pelota pelota.vectY= (-pelota.vectY); //añadimos velocidad horizontal en funcion del rozamiento con la barra if(dir==izquierda)pelota.vectX-=(rozamiento*desplazamiento); if(dir==derecha)pelota.vectX+=(rozamiento*desplazamiento); if(pelota.vectY<0&&pelota.area.y>430){ pelota.area.y=pos-10; }else if(pelota.vectY>0&&pelota.area.y<40){ pelota.area.y=posE+10; } //cambiamos el color de la barra por el color de la pelota en ese instante barra->color.r=pelota.color.r; barra->color.g=pelota.color.g; barra->color.b=pelota.color.b; } //desplazamos la barra lateralmente if(dir==izquierda)barra->area.x-=desplazamiento; if(dir==derecha)barra->area.x+=desplazamiento; //si no se mueve pero hay colision.. }else if(colision(&pelota.area, &barra->area)) { pelota.vectY= (-pelota.vectY); if(pelota.vectY<0&&pelota.area.y>430){ pelota.area.y=pos-10; }else if(pelota.vectY>0&&pelota.area.y<40){ pelota.area.y=posE+10; } //cambiamos el color de la barra por el color de la pelota en ese instante barra->color.r=pelota.color.r; barra->color.g=pelota.color.g; barra->color.b=pelota.color.b; } } /* Definimos la función moverEnemigo Esta función se encargará de hacer que la máquina mueva la barra de una forma "inteligente" */ void moverEnemigo(barraPong *barra){ int factor=30; // La máquina solo muve su barra si la pelota va en sentido ascendente y ha superado una altura de 350px if(pelota.area.y<350&&pelota.vectY<0){ if((pelota.area.x+pelota.area.w)>(enemigo.area.x+enemigo.area.w-factor)){ moverBarra(&enemigo, derecha); }else if(pelota.area.x<enemigo.area.x+factor){ moverBarra(&enemigo, izquierda); }else{ moverBarra(&enemigo,ninguna); } } } // Definimos la función nuevoJuego void nuevoJuego(){ SDL_Delay(2000); pelota.area.x=50; pelota.area.y=70; pelota.area.h=10; pelota.area.w=10; pelota.vectX=1; pelota.vectY=1; } /* Definimos la función cambiaColor Esta función cambia aleatoreamente el color de la pelota */ void cambiarColor(){ pelota.color.r+=rand()%15; pelota.color.g+=rand()%15; pelota.color.b+=rand()%15; if(pelota.color.r>=255) pelota.color.r=0; if(pelota.color.g>=255) pelota.color.g=0; if(pelota.color.b>=255) pelota.color.b=0; } /* Definimos la función moverPelota Esta función mueve la pelota y suma las puntuaciones de los jugadores cuando marcan un tanto. */ void moverPelota(){ int mult=2; // Si la pelota está en el borde de arriba suma un punto a la máquina. if(pelota.area.y>alto-10){ enemigo.puntuacion+=1; nuevoJuego(); } // Si la pelota está en el borde de abajo suma un punto al jugador. if(pelota.area.y<10){ jugador.puntuacion+=1; nuevoJuego(); } // Si la pelota toca alguna de las paredes rebota cambiando el sentido de la velocidad horizontal. if(pelota.area.x+pelota.area.w+(mult*pelota.vectX)>largo-5||pelota.area.x+(mult*pelota.vectX)<5){ pelota.vectX=(-pelota.vectX); } // Se aplican los movimientos a la pelota. pelota.area.x=(int)(pelota.area.x+(mult*pelota.vectX)); pelota.area.y=(int)(pelota.area.y+(mult*pelota.vectY)); // Llamamos a la función cambiaColor para cambiar el color de la pelota. cambiarColor(); } // *************************************************** // ****** AQUÍ EMPIEZA A EJECUTARSE EL PROGRAMA ****** // *************************************************** int main(int argc, char *argv[]) { // Declare variables int done=0; SDL_Surface *screen, *ttext; Uint8 *keys=SDL_GetKeyState(NULL); SDL_Rect dest={0,0,largo,alto},fondo={50,50,largo-100,alto-100}; SDL_Event event; // Parse command-line arguments // Se inicializa SDL if(SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO<0)){ printf("No se pude iniciar SDL: %s\n", SDL_GetError()); exit(1); } screen = SDL_SetVideoMode(largo,alto,24,SDL_HWSURFACE|SDL_DOUBLEBUF); // se comprueba si se ha podido inicializar la pantalla. if(screen==NULL){ printf("No se ha podido iniciar el modo gráfico"); exit(1); } if(TTF_Init()<0){ printf("No se ha podido iniciar SDL_ttf: %s\n",SDL_GetError()); exit(1); } direccion dir; TTF_Font *fuente; // Cargamos la fuente del texto que vamos a usar en el juego // En el caso de que quieras utilizar otra fuente deberás cambiar el nombre del archivo. fuente=TTF_OpenFont("ROBOM.ttf",45); SDL_Color bgcolor={255,255,255},fgcolor={0,0,0}; while(done==0){ //pinta el fondo SDL_FillRect(screen, &dest,SDL_MapRGB(screen->format,0,0,0)); SDL_FillRect(screen, &fondo,SDL_MapRGB(screen->format,255,255,255)); char msg[30]; sprintf(msg," Jugador: %d",jugador.puntuacion); SDL_Rect desttext1={50,50,largo-450,alto-100}; ttext=TTF_RenderText_Shaded(fuente,msg,fgcolor,bgcolor); SDL_BlitSurface(ttext,NULL,screen,&desttext1); sprintf(msg," Maquina: %d", enemigo.puntuacion); SDL_Rect desttext2={400,50,largo-450,alto-100}; ttext=TTF_RenderText_Shaded(fuente,msg,fgcolor,bgcolor); SDL_BlitSurface(ttext,NULL,screen,&desttext2); //se dibuja la barra del jugador. SDL_FillRect(screen, &jugador.area, SDL_MapRGB(screen->format, jugador.color.r, jugador.color.g, jugador.color.b)); //se dibuja la barra de la máquina. SDL_FillRect(screen, &enemigo.area, SDL_MapRGB(screen->format, enemigo.color.r, enemigo.color.g, enemigo.color.b)); //se dibuja la pelota. SDL_FillRect(screen, &pelota.area, SDL_MapRGB(screen->format, pelota.color.r, pelota.color.g, pelota.color.b)); SDL_Flip(screen); // se comprueba si se ha producido un evento if(SDL_PollEvent(&event)){ // se manejan los eventos de teclado //si se presiona una tecla... if(event.type==SDL_KEYDOWN){ //si se pulsa escape done=1 (salimos del juego). if(keys[SDLK_ESCAPE]==1){ done=1; } //si se pulsa izquierda ... if(keys[SDLK_LEFT]==1){ dir=izquierda; //si se pulsa derecha... }else if(keys[SDLK_RIGHT]==1){ dir=derecha; } // si se suelta una tecla... }else if(event.type==SDL_KEYUP){ dir=ninguna; } } // Llamamos a moverBarra, pasándole como parámetro la barra del jugador. moverBarra(&jugador,dir); // Llamamos a moverBarra, pasándole como parámetro la barra de la máquina. moverEnemigo(&enemigo); // Llamamos a moverPelota. moverPelota(); SDL_Delay(10); } return 0; }