Gracias de antemano, un saludo.
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:
//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...
entonces al rebotar la pelota se encoje y no tengo ni idea de por qué.
> ...
>
> leer más »