Mostrar feed RSS

Intentando hacer algo productivo

mis primeros pasos con SDL

Calificar esta entrada
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;
}
Miniaturas adjuntadas Archivos adjuntados

Enviar "mis primeros pasos con SDL" a ¡Menéame! Enviar "mis primeros pasos con SDL" a Technorati Enviar "mis primeros pasos con SDL" a Digg Enviar "mis primeros pasos con SDL" a del.icio.us Enviar "mis primeros pasos con SDL" a Google Enviar "mis primeros pasos con SDL" a Finclu Enviar "mis primeros pasos con SDL" a Copada Enviar "mis primeros pasos con SDL" a StumbleUpon Enviar "mis primeros pasos con SDL" a Reddit Enviar "mis primeros pasos con SDL" a FaceBook

Actualizado 03/10/2008 a las 23:36 por Gabs86

Categorías

Comentarios

  1. Avatar de enkonsierto
    Me parece bastante interesante tu iniciativa, proximamente (a medio plazo) me gustaría tocar sdl y le echaré un vistazo a tu código...
  2. Avatar de Gabs86
    llevo tiempo pensando en hacer un wiki de programación, pero como no hay tiempo he pensado que esto se le podía parecer. La idea del wiki sería empezar un proyecto y que cada uno modificase lo que quisiese en cada momento, por supuesto guardando una copia de la versión anterior, por si el creador del proyecto quisiese dar marcha atrás en algún momento.

    Intuyo que mi código no es bueno, pero no tengo quien me corrija los errores así que he pensado que esto también me podría ayudar a mí también. Si tiene buena acogida, podría hacer lo mismo con un tetris que estoy haciendo, y así podríamos hacer el proyecto entre varios. Un saludo!
  3. Avatar de BeaR
    Muchísimas gracias, esto ayudará a más de uno :P

    Salu2