/*
balls.c
SDL Example
A simple, pachinko-style game
Bill Kendrick
1/2000
*/
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#include <mixer.h>
/* Constraints: */
#define MAX_BALLS 5
#define MAX_PEGS 32
/* Typedefs: */
typedef struct ball_type {
int alive;
int x, y;
int xm, ym;
} ball_type;
typedef struct peg_type {
int alive;
int x, y;
} peg_type;
/* Global variables: */
ball_type balls[MAX_BALLS];
peg_type pegs[MAX_PEGS];
/* Local function prototypes: */
SDL_Surface * load_and_convert(char * file);
void addball(int x, int y);
void addpeg(int x, int y);
void clearballs(void);
void clearpegs(void);
/* --- MAIN --- */
int main(int argc, char * argv[])
{
SDL_Event event;
SDLKey key;
SDL_Surface * screen, * ball, * peg;
SDL_Rect dest;
int i, j, done, paused;
Uint32 last_time;
Mix_Chunk * tink;
/* Init SDL: */
if (SDL_Init(SDL_INIT_AUDIO |
SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "Init: %s\n",
SDL_GetError());
exit(1);
}
/* Open display: */
screen = SDL_SetVideoMode(320, 240,
16, 0);
if (screen == NULL)
{
fprintf(stderr, "Video: %s\n",
SDL_GetError());
exit(1);
}
/* Set window title: */
SDL_WM_SetCaption("SDL Demo: Balls",
"Balls");
/* Load graphics: */
ball = load_and_convert("ball.bmp");
peg = load_and_convert("peg.bmp");
/* Initialize Mixer: */
if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY,
MIX_DEFAULT_FORMAT,
2, 512) < 0)
{
fprintf(stderr,
"Can't open audio: %s\n",
SDL_GetError());
exit(1);
}
/* Load sounds: */
tink = Mix_LoadWAV("tink.wav");
if (tink == NULL)
{
fprintf(stderr,
"Can't open tink.wav: %s\n",
SDL_GetError());
exit(1);
}
/* Initialize balls and pegs: */
clearballs();
clearpegs();
/* --- MAIN LOOP: --- */
done = 0;
paused = 0;
do
{
/* Get the time at the beginning
of this iteration: */
last_time = SDL_GetTicks();
/* Handle all queued events: */
while (SDL_PollEvent(&event) > 0)
{
if (event.type == SDL_QUIT)
{
/* Quit request - quit! */
done = 1;
}
else if (event.type ==
SDL_KEYDOWN)
{
/* Keypress: */
key = event.key.keysym.sym;
if (key == SDLK_ESCAPE)
{
/* Escape - quit! */
done = 1;
}
else if (key == SDLK_SPACE)
{
/* Space - Un/pause! */
paused = !paused;
}
else if (key == SDLK_TAB)
{
/* Tab - Clear pegs: */
clearpegs();
}
}
else if (event.type ==
SDL_MOUSEBUTTONDOWN)
{
if (event.button.button == 1)
{
/* Left click! Add a ball! */
addball(event.button.x,
event.button.y);
}
else
{
/* Not left! Add a peg! */
addpeg(event.button.x,
event.button.y);
}
}
}
/* Move all balls: */
if (!paused)
{
for (i = 0; i < MAX_BALLS; i++)
{
if (balls[i].alive)
{
/* Apply gravity: */
balls[i].ym++;
/* Keep speeds in bounds: */
if (balls[i].ym > 24)
balls[i].ym = 24;
else if (balls[i].ym < -24)
balls[i].ym = -24;
if (balls[i].xm > 24)
balls[i].xm = 24;
else if (balls[i].xm < -24)
balls[i].xm = -24;
/* Move ball: */
balls[i].x = (balls[i].x +
balls[i].xm);
balls[i].y = (balls[i].y +
balls[i].ym);
/* If it dropped off the
screen, kill it: */
if (balls[i].y >= 240)
balls[i].alive = 0;
/* See if it hit a peg: */
for (j = 0;
j < MAX_PEGS;
j++)
{
if (pegs[j].alive &&
balls[i].x >=
pegs[j].x - 24 &&
balls[i].x <=
pegs[j].x + 40 &&
balls[i].y >=
pegs[j].y - 16 &&
balls[i].y <=
pegs[j].y + 24)
{
/* Bounce! */
balls[i].ym =
-abs(balls[i].ym - 1);
balls[i].xm =
((balls[i].x -
pegs[j].x) / 4) *
((abs(balls[i].xm) + 4)
/ 4);
/* Play sound: */
if (abs(balls[i].ym) > 1)
Mix_PlayChannel(-1,
tink,
0);
}
}
}
}
}
/* Erase entire screen: */
SDL_FillRect(screen, NULL,
SDL_MapRGB(screen->format,
255,
255,
255));
/* Draw all balls: */
for (i = 0; i < MAX_BALLS; i++)
{
if (balls[i].alive)
{
dest.x = balls[i].x;
dest.y = balls[i].y;
dest.w = 32;
dest.h = 32;
SDL_BlitSurface(ball,
NULL,
screen,
&dest);
}
}
/* Draw all pegs: */
for (i = 0; i < MAX_PEGS; i++)
{
if (pegs[i].alive)
{
dest.x = pegs[i].x;
dest.y = pegs[i].y;
dest.w = 32;
dest.h = 32;
SDL_BlitSurface(peg,
NULL,
screen,
&dest);
}
}
/* Update the entire screen: */
SDL_Flip(screen);
/* Pause until it's time for the
next frame: */
if (SDL_GetTicks() < last_time + 20)
{
SDL_Delay(last_time + 20 -
SDL_GetTicks());
}
}
while (done == 0);
/* Close up and quit: */
SDL_Quit();
return(0);
}
/* Load and convert a bitmap: */
SDL_Surface * load_and_convert(char * file)
{
SDL_Surface * temp, * surf;
/* Load: */
temp = SDL_LoadBMP(file);
if (surf == NULL)
{
fprintf(stderr,
"Can't load %s: %s\n",
file, SDL_GetError());
exit(1);
}
/* Convert: */
surf = SDL_DisplayFormat(temp);
if (surf == NULL)
{
fprintf(stderr,
"Can't convert %s: %s\n",
file, SDL_GetError());
exit(1);
}
/* Make 100% white transparent: */
if (SDL_SetColorKey(surf, (SDL_SRCCOLORKEY),
SDL_MapRGB(surf->format,
255,
255,
255)) < 0)
{
fprintf(stderr,
"Can't set colorkey %s: %s\n",
file, SDL_GetError());
exit(1);
}
/* Free: */
SDL_FreeSurface(temp);
/* Return: */
return(surf);
}
/* Add a ball: */
void addball(int x, int y)
{
int i, found;
/* Find an empty slot in the array: */
found = -1;
for (i = 0;
i < MAX_BALLS && found == -1;
i++)
{
if (balls[i].alive == 0)
found = i;
}
/* Fill in the slot: */
if (found != -1)
{
balls[found].alive = 1;
balls[found].x = x - 16;
balls[found].y = y - 16;
balls[found].xm = 0;
balls[found].ym = 0;
}
}
/* Add a peg: */
void addpeg(int x, int y)
{
int i, found;
/* Find an empty slot in the array: */
found = -1;
for (i = 0;
i < MAX_PEGS && found == -1;
i++)
{
if (pegs[i].alive == 0)
found = i;
}
/* Fill in the slot: */
if (found != -1)
{
pegs[found].alive = 1;
pegs[found].x = x - 16;
pegs[found].y = y - 16;
}
}
/* Clear all balls: */
void clearballs(void)
{
int i;
for (i = 0; i < MAX_BALLS; i++)
balls[i].alive = 0;
}
/* Clear all pegs: */
void clearpegs(void)
{
int i;
for (i = 0; i < MAX_PEGS; i++)
pegs[i].alive = 0;
}
|