La pelota del pong.

5 views
Skip to first unread message

Rafael Muñoz

unread,
Nov 3, 2007, 2:42:26 PM11/3/07
to SDL en Español
Buenas, estaba yo haciendo un pong siguiendo un tutorial de internet.
Es bastante simple, tenemos dos paletas en los lados pegadas a los
bordes de las pantallas que son rectángulos blancos de 50x5 pixels y
una pelota que es un cuadrado de 4x4 pixels blancos. Bueno pues en el
tutorial me dicen que tengo que reiniciar en cada frame la anchura y
la altura de la pelota porque sino se me encoje. Borre la parte de
reiniciar las dimensiones y la pelota se me encoje cada vez que
rebota, hasta desaparecer, y la verdad es que no entiendo el por qué,
parece un fallo. El codigo tiene unas 500 lineas pro eso no lo cuelgo.
Si necesitais algun fragmento lo pongo u os lo mando.

Gracias de antemano, un saludo.

Roberto Albornoz

unread,
Nov 3, 2007, 3:11:04 PM11/3/07
to sdl...@googlegroups.com


No sera por casualidad un curso que usa Fenix como lenguaje?

Bueno sea como sea, habría que ver el código, para ver si realmente existe un error.

Eso de que se encoja la pelota en cada frame, debe suceder simplemente porque eso está programado, nada es mágico :D

Saludos!

Rafael Muñoz

unread,
Nov 3, 2007, 7:35:45 PM11/3/07
to SDL en Español
http://www.linuxdevcenter.com/pub/a/linux/2005/12/15/clone-pong-using-sdl.html?page=last

Este es el tutorial, esta en c++. Voy a postear el programa completo,
está más o menos ordenado.

On 3 nov, 20:11, "Roberto Albornoz" <ralbor...@gmail.com> wrote:

Rafael Muñoz

unread,
Nov 3, 2007, 7:38:59 PM11/3/07
to SDL en Español
/*
PLEASE NOTE: the program will require SDL.dll ans SDL_ttf which is
located in
dev-c++'s dll directory. You have to copy it to your
program's home directory or the path. This will give
errors like "undefined SDL_Init()"
It also needs Gothic true type font.
*/

//Standard library headers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

//SDL headers
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>

//Macro definitions
#define SCREEN_WIDTH 640 // width of the screen in pixels
#define SCREEN_HEIGHT 480 // height of the screen in pixels

//Width, height and starting x and y coordinates of ball
#define BALL_W 4
#define BALL_H 4
#define BALL_X ( SCREEN_WIDTH / 2 ) -2
#define BALL_Y ( SCREEN_HEIGHT / 2 ) -2

//Width, height and starting x and y coordinates of player 1's paddle
#define P1_W 5
#define P1_H 50
#define P1_X 0
#define P1_Y ( SCREEN_HEIGHT / 2 ) - (P1_H / 2)

//Width, height and starting x and y coordinates of player 2's paddle
#define P2_W 5
#define P2_H 50
#define P2_X ( SCREEN_WIDTH -1 ) - (P2_W)
#define P2_Y ( SCREEN_HEIGHT / 2 ) - (P2_H/2)

//Default paddle speed for players
#define P1_SPEED 4
#define P2_SPEED 4

//Set the dir parameter to movePaddle()
#define DIR_UP 1
#define DIR_DOWN 2

//Set the points to win
#define GAME_POINTS 10

//Set the message size, font location and display time
#define MSG_FONT "c:/WINDOWS/Fonts/Gothic.ttf"
#define MSG_SIZE 18
#define MSG_TIME 1500

//Number of milliseconds that game will sleep at the end of the game
loop;
//the higher number, the slower the game speed. Note that you will
probably
//want to change BALL_SPEED, P1_SPEED and P2_SPEED when you change
this.
#define GAME_SPEED 20
#define BALL_SPEED 7 // total change in x an y in the slope
#define SLOPE_MAX_DY 5 // the maximum change-in-y in the slope


//Structure definitions
typedef struct {

int p1;
int p2;

int game_points;

} Score;

typedef struct {

int dx;
int dy;
} Slope;


typedef struct {

int running; // Is the game running?
int game_speed; // The game speed
int ball_speed; // Number of pixels the ball can move an once
int slope_max_dy; // maximum value for change-in-y component
of the slope

SDL_Surface *screen; //Main window

SDL_Rect ball; //Ball
Slope slope; //slope of the line repesenting the ball's path
Score score; //Score of de game

TTF_Font *font; //message font

SDL_Rect p1; //Player 1's paddle
SDL_Rect p2; //Player 2'a paddle

int p1_speed; //Player 1's paddle speed
int p2_speed; //Player 2's paddle speed

int num_rects; //Number of rectangles to update
SDL_Rect rects[16]; //Rectangles to update

Uint32 black; //The colour black
Uint32 white; //The colour white
} GameData;

//Function definitions
int cleanUp(int err);
void genSlope( GameData *game );
void moveBall( GameData *game );
void resetSprites( GameData *game, int erase );
void movePaddle( GameData *game, int player, int dir);

//Main program
int main(int argc, char **argv){
//Declare variables
SDL_Event event; //SDL event
GameData game; // Game data
Uint8 *keystate; //Keyboard state

//Initialise game data
game.running = 1;
game.game_speed = GAME_SPEED;
game.slope_max_dy = SLOPE_MAX_DY;
game.ball_speed = BALL_SPEED;
game.p1_speed = P1_SPEED;
game.p2_speed = P2_SPEED;
game.num_rects = 0;
game.score.p1 = 0;
game.score.p2 = 0;
game.score.game_points = GAME_POINTS;

//Parse command-line arguments

//Initialise SDL
if( SDL_Init(SDL_INIT_VIDEO) != 0 ){
fprintf(stderr,"Could not ininitalise SDL: %
\n",SDL_GetError());
return 1;
}//if(Could not init video)

//Initialise TTF engine and load a font
TTF_Init();
if((game.font = TTF_OpenFont(MSG_FONT, MSG_SIZE))==NULL){

fprintf(stderr, "Could not open font: %s\n", MSG_FONT);
return cleanUp( 2 );

}//if( could not load font)

if( (game.screen=SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 8,
SDL_SWSURFACE))==NULL ){
fprintf(stderr, "Could not set SDL video mode %\n",
SDL_GetError());
return cleanUp( 1 );
}// if(Could not set mode)

//Set window caption and set off the mouse cursor
SDL_WM_SetCaption("SDL Pong","SDL Pong");
SDL_ShowCursor( SDL_DISABLE );

//Get black and white colors
game.black=SDL_MapRGB(game.screen->format, 0x00, 0x00, 0x00);
game.white=SDL_MapRGB(game.screen->format, 0xff, 0xff, 0xff);

//Initialise sprite locations
resetSprites( &game, 0 );

//Randomly generates the starting slope
genSlope( &game );


//Main loop
while(1){
//Re(draw) the screen
if(game.num_rects){

SDL_UpdateRects( game.screen, game.num_rects, game.rects);
game.num_rects=0;
}//if (Updating the screen)

//Handle events(keyboard input, mainly)
while( SDL_PollEvent( &event )){

if(event.type==SDL_QUIT||
(event.type==SDL_KEYDOWN&&event.key.keysym.sym==SDLK_ESCAPE))
game.running = 0;}

if(game.running == 0)
break;
// while(handling events)

//Move sprites about

//Grab a keystate snapshot
keystate=SDL_GetKeyState( NULL );

//Has player 1 requested a move?
if(keystate[SDLK_a])
movePaddle( &game , 1, DIR_UP);
else if(keystate[SDLK_z])
movePaddle( &game, 1, DIR_DOWN);

//Has player 2 requested a move?
if(keystate[SDLK_QUOTE])
movePaddle( &game , 2, DIR_UP);
else if(keystate[SDLK_SLASH])
movePaddle( &game, 2, DIR_DOWN);

//Move the ball
moveBall( &game );

//Give the cpu a break
SDL_Delay( GAME_SPEED );

}//While gameloop

//Victory!
return cleanUp( 0 );
}// main()

/* Function: cleanUp()
*
* Clearly tears down SDL in preparation for an exit
*
* Paremeters:
*
* err - Unix-style error code.
*
* Returns:
* err parameter
*/

int cleanUp(int err){

TTF_Quit();
SDL_Quit();

return err;

}// cleanUp()

/* Function: resetSprites()
*
* Moves all sprites back to their starting positions
*
* Parameters:
*
* *game - GameData
* erase - if true, sprites will be erased first
*/

void resetSprites( GameData *game, int erase ){

//Erase sprites from current locations?
if(erase){

SDL_FillRect( game->screen, &(game->ball), game->black );
SDL_FillRect( game->screen, &(game->p1), game->black );
SDL_FillRect( game->screen, &(game->p2), game->black );
game->rects[game->num_rects++]=game->ball;
game->rects[game->num_rects++]=game->p1;
game->rects[game->num_rects++]=game->p2;

}//if (erasing sprites)

//The ball is a 2x2 sprite, centered both horizontally and
vertically
game->ball.x=BALL_X;
game->ball.y=BALL_Y;
game->ball.w=BALL_W;
game->ball.h=BALL_H;

//Player 1's paddle is a 5x50 veltical sprite, flush left and
centered vertically
game->p1.x=P1_X;
game->p1.y=P1_Y;
game->p1.w=P1_W;
game->p1.h=P1_H;

//Player 2's paddle is a 5x50 vertical sprite, flush right and
centered vertically
game->p2.x=P2_X;
game->p2.y=P2_Y;
game->p2.w=P2_W;
game->p2.h=P2_H;

//Draw the playing field
SDL_FillRect( game->screen, &(game->ball), game->white );
SDL_FillRect( game->screen, &(game->p1), game->white );
SDL_FillRect( game->screen, &(game->p2), game->white );
game->rects[game->num_rects++]= game->ball;
game->rects[game->num_rects++]= game->p1;
game->rects[game->num_rects++]= game->p2;
} //resetSprites()

/* Function movePaddle()
*
* Moves a player's paddle
*
* Parameters:
*
* *game - game data
* player - player number
* dir - direction of the move(DIR_UP or DIR_DOWN)
*/

void movePaddle( GameData *game, int player, int dir){

int new_y;
int moved;

SDL_Rect tmp;
SDL_Rect *rect = (player == 1 ? &(game->p1) : &(game->p2));
//NOTE-----This is a compact version of an if selection.
// Structure: ---------Works like IF
// <condition> ? <true_expresion> : <false_expresion>

int speed = (player == 1 ? game->p1_speed : game->p2_speed);

//Compute the new y coordinate of the rectangle and the pixels
moved
new_y = ( dir == DIR_UP ? (rect->y - speed) : (rect->y +
speed));
moved = ( dir == DIR_UP ? (rect->y - new_y) : (new_y - rect-
>y));

//If we get to the edge of the screen stop moving
if( (dir == DIR_UP) && (new_y < 0) ){
new_y = 0;
moved = rect->y -new_y;
} // if moving up less than speed

else if( (dir == DIR_DOWN) && (new_y > SCREEN_HEIGHT - rect->h))
{
new_y = SCREEN_HEIGHT - rect->h;
moved = new_y - rect->y;
} // moving down less than speed

//If we have not moved just return
if( moved == 0)
return;

//Erase the top or the bottom lines of the paddle
tmp.x = rect->x;
tmp.y = ( dir == DIR_UP ? (rect->y + rect->h - moved) : (rect-
>y));
tmp.w = rect->w;
tmp.h = moved;

SDL_FillRect( game->screen, &tmp, game->black);
game->rects[game->num_rects++] = tmp;

//Apply the new y coordinate of the rectangle
rect->y = new_y;

//Draw the bottom(or the top) new lines of the paddle
tmp.y = ( dir == DIR_UP ? rect->y : (rect->y + rect->h -moved));

SDL_FillRect( game->screen, &tmp, game->white);
game->rects[game->num_rects++]=tmp;

} // Move paddles


/* Function: genSlope()
*
* Randomly generates the slope of the vector of ball's travel
*
* Parameters:
*
* *game - game data
*/

void genSlope( GameData *game ){

//Seed the random current generator with the current unix
timestamp
srand( time( NULL ) );

//Generate the change-in-y component of the slope randomly
game->slope.dy =
1 + (int)((float)game->slope_max_dy*rand()/(RAND_MAX + 1.0));

//The change-in-y component of the slope is
//whatever is left on the "budget"
game->slope.dx = game->ball_speed - game->slope.dy;

//Flip a coin for x and y directions
if( (int)( 2.0*rand() / (RAND_MAX + 1.0) ) )
game->slope.dx *= -1;
if( (int)( 2.0*rand() / (RAND_MAX + 1.0) ) )
game->slope.dy *= -1;

} // genSlope()

/* Function: moveBall()
*
* moves the ball
*
* Parameters:
*
* *game - game data
*/

void moveBall( GameData *game ){
//Erase the current ball
SDL_FillRect( game->screen, &(game->ball), game->black);
game->rects[game->num_rects++]=game->ball;

//Move the ball ( reset height and width, as going off the
screen seems
//to compress them)
game->ball.x += game->slope.dx;
game->ball.y += game->slope.dy;
game->ball.w = BALL_W;
game->ball.h = BALL_H;

//If the ball hits the top or te bottop wall, bounce it
if(( game->ball.y <=0 )||( game->ball.y >=(SCREEN_HEIGHT - game-
>ball.h))){
game->slope.dy *= -1;
} //Ball bouncing off top or bottom wall


//Fix paddles lenght for low angle hits
int ext_paddle=(game->slope.dy*game->slope.dx/(game->ball.x -
P2_W +1)) +1;
ext_paddle = (ext_paddle<0 ? ext_paddle*-1 : ext_paddle);


//If the ball has hit a player's paddle, bounce it
if (((game->ball.x <= game->p1.w) &&
(game->ball.y >= game->p1.y -ext_paddle) &&
((game->ball.y + game->ball.h) <= game->p1.y + game->p1.h +
ext_paddle ))

||

(game->ball.x >= (SCREEN_WIDTH - (game->p2.w + (game->ball.w)))
&&
(game->ball.y >= game->p2.y - ext_paddle &&
((game->ball.y + game->ball.h) <= game->p2.y + game->p2.h +
ext_paddle)))){


//Brake the ball to fix superposition of ball and paddle
if(game->ball.x <= P1_W)
game->ball.x = P1_W ;
if(game->ball.x >= SCREEN_WIDTH - P2_W - BALL_W)
game->ball.x = SCREEN_WIDTH - P2_W - BALL_W -1;

//Add a sound effect here?
game->slope.dx *= -1;
} // If(bouncing off paddle)

//if the ball hits the right or the left wall, score a point
//to the right player and then return the ball to the center
else if( game->ball.x < 0 || game->ball.x > (SCREEN_WIDTH - game-
>ball.w)){

SDL_Color white = {0xff, 0xff, 0xff, 0};

SDL_Rect rect_msg = {SCREEN_WIDTH/2 - 90, 100, 200,
50};
SDL_Rect rect_score_p1 = {100, 200, 150,
50};
SDL_Rect rect_score_p2 = {SCREEN_WIDTH - 200, 200, 150,
50};

SDL_Rect rects[3];

char str_msg[32], str_score_p1[16], str_score_p2[16];
SDL_Surface *text_msg, *text_score_p1, *text_score_p2;

if( game->ball.x < 0)
game->score.p2++;
else if(game->ball.x > (SCREEN_WIDTH - game->ball.w))
game->score.p1++;

//write scoring messages
snprintf(str_msg, 32, "Jugador %d marca!",
( (game->ball.x<0) ? 2 : 1 ));

snprintf( str_score_p1, 16, "Jugador 1: %d ", game-
>score.p1);
snprintf( str_score_p2, 16, "Jugador 2: %d ", game-
>score.p2);

text_msg = TTF_RenderText_Solid( game->font,
str_msg, white);
text_score_p1 = TTF_RenderText_Solid( game->font,
str_score_p1, white);
text_score_p2 = TTF_RenderText_Solid( game->font,
str_score_p2, white);

//Display scoring messages
rects[0]= rect_msg;
rects[1]= rect_score_p1;
rects[2]= rect_score_p2;

SDL_BlitSurface( text_msg, NULL, game->screen,
&rect_msg);
SDL_BlitSurface( text_score_p1, NULL, game->screen,
&rect_score_p1);
SDL_BlitSurface( text_score_p2, NULL, game->screen,
&rect_score_p2);

SDL_UpdateRects(game->screen, 3, rects);

//Dispaly score for a while
SDL_Delay(MSG_TIME);

//Erase scoring mesages
SDL_FillRect(game->screen, &rect_msg, game->black);
SDL_FillRect(game->screen, &rect_score_p1, game->black);
SDL_FillRect(game->screen, &rect_score_p2, game->black);

SDL_UpdateRects( game->screen, 3, rects);


//Has someone just won the game?
if(game->score.p1 == game->score.game_points||
game->score.p2 == game->score.game_points){

//Display the final score
snprintf( str_msg, 32, "Gana el jugador %d!!",
((game->ball.x < 0) ? 2 : 1));

snprintf( str_score_p1, 16, "Jugador 1: %d ", game-
>score.p1);
snprintf( str_score_p2, 16, "Jugador 2: %d ", game-
>score.p2);

text_msg = TTF_RenderText_Solid( game->font,
str_msg, white);
text_score_p1 = TTF_RenderText_Solid( game->font,
str_score_p1, white);
text_score_p1 = TTF_RenderText_Solid( game->font,
str_score_p2, white);

rects[0]= rect_msg;
rects[1]= rect_score_p1;
rects[2]= rect_score_p2;

SDL_BlitSurface( text_msg, NULL, game-
>screen, &rect_msg);
SDL_BlitSurface( text_score_p1, NULL, game->screen,
&rect_score_p1);
SDL_BlitSurface( text_score_p2, NULL, game->screen,
&rect_score_p2);

SDL_UpdateRects(game->screen, 3, rects);

//Pause for a while
//SDL_Delay(MSG_TIME*2);

//End the game
game->running=0;
return;
}//if (Game over!)

//return the paddles and the ball to their starting
positions
resetSprites( game, 1 );

//generate a new slope
genSlope(game);
}// else if (score!)

SDL_FillRect( game->screen, &(game->ball), game->white);
game->rects[game->num_rects++]=game->ball;

} //moveBall()

On 4 nov, 00:35, Rafael Muñoz <raud...@gmail.com> wrote:
> http://www.linuxdevcenter.com/pub/a/linux/2005/12/15/clone-pong-using...

Rafael Muñoz

unread,
Nov 3, 2007, 7:41:36 PM11/3/07
to SDL en Español
Si en la funcion move ball eliminamos las lineas

game->ball.w = BALL_W;
game->ball.h = BALL_H;

entonces al rebotar la pelota se encoje y no tengo ni idea de por qué.

> ...
>
> leer más »

Roberto Albornoz

unread,
Nov 3, 2007, 8:30:48 PM11/3/07
to sdl...@googlegroups.com
Hola de nuevo:

Primero no veo la necesidad de comentar esas líneas, si lo haces la pelota no tendrá dimensiones (valor cero), o quizás quede con valores aleatorios para su ancho y alto, lo que provocaría que la detección de colisiones con los paddles sea incorrecta y/o veas una pelota gigante moviéndose en la pantalla.

Compilé el código, solo cambie la línea donde se busca la fuente ttf, para que lo haga en el directorio actual.

#define MSG_FONT "Gothic.ttf"

Y arregle unos fprintf, ya que faltaba el %s que imprimía el error detectado, lo demás quedó intacto.

Mira te dejo el proyecto para Dev-C++ y Code::Blocks junto al código fuente, ejecutable, fuente ttf y las DLLs necesarias, funciona perfectamente! =)

http://blogrcaf.com/programas/pong.zip


Saludos!

----------------------------------------
Roberto Albornoz Figueroa
http://www.blogrcaf.com
ralb...@gmail.com

Reply all
Reply to author
Forward
0 new messages