17 #define STREQ(a, b) (!strcmp((a),(b)))
20 #define SPRITE_PIXELS_PER_SECOND 200
21 #define NUM_MILLISECONDS 1000;
25 /* global variables */
27 /* TODO no global variables
28 Have a type in each file?
29 Then use that type to decide if it can be branded?
30 Or only be able to brand cows.
41 IMG_COW_YELLOW_WITH_RED_OUTLINE
,
48 const char *image_names
[NUM_IMAGES
] = {
56 IMG_DIR
"cow_yellow_with_red_outline",
57 IMG_DIR
"kangaroo_black",
58 IMG_DIR
"kangaroo_grey",
59 IMG_DIR
"kangaroo_red"
64 SDL_Cursor
*cursor_arrow
;
65 SDL_Cursor
*cursor_wheelhouse
;
66 SDL_Cursor
*cursor_wheelhouse_transparent
;
67 SDL_Cursor
*cursor_wheelhouse_inverted
;
68 SDL_Cursor
*cursor_wheelhouse_black_with_white_lines
;
73 SDL_Surface
*brand_wheelhouse
;
74 SDL_Surface
*brand_wheelhouse_transparent
;
75 SDL_Surface
*brand_wheelhouse_inverted
;
76 SDL_Surface
*brand_wheelhouse_black_with_white_lines
;
80 static void init_sdl(bool fullscreen
);
81 static void handle_args(int argc
, char *argv
[], bool *fullscreen
);
82 static void print_help(void);
83 static void print_usage(void);
84 static SDL_Surface
*get_background();
85 static struct cursors
setup_cursors(void);
86 static struct brands
setup_brands(void);
87 static void close_sprites(struct sprite
**sprites
);
88 static void play_game(SDL_Surface
*screen
, SDL_Surface
*back
, struct sprite
**sprites
, struct cursors
*cursors
, struct brands
*brands
);
89 static void handle_events(SDL_Surface
*screen
, int *quit
, int *pause
, bool *mouse_clicked
, int *x_mouse
, int *y_mouse
, struct cursors
*cursors
, struct brands
*brands
, SDL_Surface
**brand
);
90 static void move(struct sprite
*sprites
[], int *pause
, double elapsed_ticks
);
91 static Uint32
get_elapsed_ticks(void);
92 static void main_draw(struct sprite
**sprites
, SDL_Surface
*brand
);
93 static void check_branded(SDL_Rect
*src
, struct sprite
**sprites
, int x_mouse
, int y_mouse
);
95 static void set_icon(void);
96 static struct sprite
**setup_img(SDL_Surface
*screen
);
97 static struct sprite
*load_img(int i
, SDL_Surface
*screen
, unsigned int x_scale
, unsigned int y_scale
);
98 static void draw_image(SDL_Surface
*img
, SDL_Surface
*screen
, int x
, int y
);
99 static void draw_background(SDL_Surface
*back
, SDL_Surface
*screen
);
101 int main(int argc
, char *argv
[])
104 handle_args(argc
, argv
, &fullscreen
);
106 init_sdl(fullscreen
);
108 struct cursors cursors
= setup_cursors();
109 struct brands brands
= setup_brands();
111 SDL_Surface
*screen
= SDL_GetVideoSurface();
112 SDL_Surface
*background
= get_background();
114 struct sprite
**sprites
= setup_img(screen
);
116 play_game(screen
, background
, sprites
, &cursors
, &brands
);
118 close_sprites(sprites
);
119 SDL_FreeSurface(screen
);
120 SDL_FreeSurface(background
);
121 /* SDL_FreeSurface(brand); */
126 static void init_sdl(bool fullscreen
)
130 if (SDL_Init(SDL_INIT_VIDEO
) < 0) {
131 printf("Unable to initialize SDL: %s\n", SDL_GetError());
137 SDL_WM_SetCaption("jody", "jody");
140 if (SDL_SetVideoMode(SCREEN_WIDTH
, SCREEN_HEIGHT
, 32, SDL_HWSURFACE
| SDL_DOUBLEBUF
| (fullscreen
? SDL_FULLSCREEN
: 0)) == NULL
) {
141 printf("Unable to set video mode: %s\n", SDL_GetError());
146 static SDL_Surface
*get_background(void)
148 char background_dir
[] = {IMG_DIR
"background"};
149 char *background_path
;
150 if (asprintf(&background_path
, "%s/1.png", background_dir
) < 0) {
152 "\nError: I could not load the background image: %s\n"
153 "The Simple DirectMedia error that occurred was:\n"
154 "%s\n\n", background_dir
, SDL_GetError());
157 SDL_Surface
*background
= load_image(background_path
);
161 static void handle_args(int argc
, char *argv
[], bool *fullscreen
)
165 for (int i
= 1; i
< argc
; i
++) {
166 if (STREQ(argv
[i
], "--fullscreen") || STREQ(argv
[i
], "-f")) {
168 } else if (STREQ(argv
[i
], "--help") || STREQ(argv
[i
], "-h")) {
171 } else if (STREQ(argv
[i
], "--usage") || STREQ(argv
[i
], "-u")) {
181 static struct cursors
setup_cursors(void)
183 struct cursors cursors
;
185 cursors
.cursor_arrow
= create_cursor_arrow();
186 if (!cursors
.cursor_arrow
) {
187 printf("Unable to create_cursor_arrow\n");
191 cursors
.cursor_wheelhouse
= create_wheelhouse_cursor();
192 if (!cursors
.cursor_wheelhouse
) {
193 printf("Unable to create_cursor_arrow\n");
197 cursors
.cursor_wheelhouse_transparent
= create_wheelhouse_cursor_transparent();
198 if (!cursors
.cursor_wheelhouse_transparent
) {
199 printf("Unable to create_cursor_arrow\n");
203 cursors
.cursor_wheelhouse_inverted
= create_wheelhouse_cursor_inverted();
204 if (!cursors
.cursor_wheelhouse_inverted
) {
205 printf("Unable to create_wheelhouse_cursor_inverted\n");
209 cursors
.cursor_wheelhouse_black_with_white_lines
= create_wheelhouse_cursor_black_with_white_lines();
210 if (!cursors
.cursor_wheelhouse_black_with_white_lines
) {
211 printf("Unable to create_wheelhouse_cursor_black_with_white_lines\n");
218 static struct brands
setup_brands(void)
220 struct brands brands
;
222 brands
.brand_wheelhouse
= create_wheelhouse_image();
223 if (!brands
.brand_wheelhouse
) {
224 printf("Unable to create brand_wheelhouse\n");
228 brands
.brand_wheelhouse_transparent
= load_image(IMG_DIR
"wheelhouse_image_transparent.png");
229 if (!brands
.brand_wheelhouse_transparent
) {
230 printf("Unable to load brand_wheelhouse_transparent\n");
234 brands
.brand_wheelhouse_inverted
= load_image(IMG_DIR
"wheelhouse_image_inverted.png");
235 if (!brands
.brand_wheelhouse_inverted
) {
236 printf("Unable to load brand_wheelhouse_inverted\n");
240 brands
.brand_wheelhouse_black_with_white_lines
= load_image(IMG_DIR
"wheelhouse_image_black_with_white_lines.png");
241 if (!brands
.brand_wheelhouse_black_with_white_lines
) {
242 printf("Unable to brand_wheelhouse_black_with_white_lines\n");
249 static void close_sprites(struct sprite
**sprites
)
251 for (int i
= 0; i
< NUM_IMAGES
; i
++) {
253 free_sprite(sprites
[i
]);
260 SDL_Surface
*icon
= IMG_Load(IMG_DIR
"icon.png");
263 "\nError: I could not load the icon image: %s\n"
264 "The Simple DirectMedia error that occurred was:\n"
265 "%s\n\n", IMG_DIR
"icon.png", SDL_GetError());
269 SDL_WM_SetIcon(icon
, NULL
);
271 SDL_FreeSurface(icon
);
274 static struct sprite
**setup_img(SDL_Surface
*screen
)
276 struct sprite
**sprites
= xcalloc(NUM_IMAGES
, sizeof(struct sprite
*));
279 unsigned int x_scale
= RAND_MAX
/ SCREEN_WIDTH
;
280 unsigned int y_scale
= RAND_MAX
/ SCREEN_HEIGHT
;
282 for (int i
= 0; i
< NUM_IMAGES
; i
++) {
283 sprites
[i
] = load_img(i
, screen
, x_scale
, y_scale
);
288 static struct sprite
*load_img(int i
, SDL_Surface
*screen
, unsigned int x_scale
, unsigned int y_scale
)
290 printf("image_names[i] = [%s]\n", image_names
[i
]);
291 struct sprite_base
*base
= base_init(image_names
[i
]);
294 "\nError: I couldn't initialise:\n"
296 "The Simple DirectMedia error that occurred was:\n"
297 "%s\n\n", image_names
[i
], SDL_GetError());
300 struct sprite
*sprite
= sprite_init(base
, screen
);
301 if (sprite
== NULL
) {
303 "\nError: I couldn't initialise the sprite:\n"
305 "The Simple DirectMedia error that occurred was:\n"
306 "%s\n\n", image_names
[i
], SDL_GetError());
310 unsigned int x
= random();
312 unsigned int y
= random();
315 /* Put clouds in the sky; animals on the ground. */
316 int half
= SCREEN_HEIGHT
/ 2;
317 /* printf("half\t%d", half); */
318 /* printf("\timage_names[i]\t%s", image_names[i]); */
319 if (i
== IMG_CLOUD
) {
320 printf("\tmatched!");
322 y
= base
->image_height
;
325 y
= SCREEN_HEIGHT
- base
->image_height
;
327 printf("\ty\t%d\n", y
);
330 set_speed(sprite
, 1);
334 static void play_game(SDL_Surface
*screen
, SDL_Surface
*back
, struct sprite
**sprites
, struct cursors
*cursors
, struct brands
*brands
)
337 /* keep track of frames and time */
338 int start_time
, end_time
;
339 start_time
= time(NULL
);
340 int frames_drawn
= 0;
342 /* 126 = width of 1 cow of the 3 cow tile; 95 = height of cow */
349 /* game loop logic: events, logic and rendering */
355 SDL_Surface
*brand
= NULL
;
357 mouse_clicked
= false;
358 handle_events(screen
, &quit
, &pause
, &mouse_clicked
, &x_mouse
, &y_mouse
, cursors
, brands
, &brand
);
361 /* ... check branded */
363 check_branded(&src
, sprites
, x_mouse
, y_mouse
);
365 /* ... handle collisions */
367 /* ... set statuses */
370 Uint32 elapsed_ticks
= get_elapsed_ticks();
371 move(sprites
, &pause
, elapsed_ticks
);
374 draw_background(back
, screen
);
375 main_draw(sprites
, brand
);
379 if (SDL_Flip(screen
) == -1)
383 end_time
= time(NULL
);
384 if (start_time
== end_time
) end_time
++;
386 /* Display the average framerate. */
387 printf("Drew %i frames in %i seconds, for a framerate of %.2f fps.\n",
388 frames_drawn
, end_time
-start_time
, (float)frames_drawn
/(float)(end_time
-start_time
));
391 static void print_help(void)
395 "Version " VERSION
"\n"
396 "Copyright 2006 Jonathan Wheelhouse\n"
401 " SPACE or p - toggle pause\n"
402 " arrow keys - move person\n"
403 " f - toggle fullscreen\n"
404 " 1 - arrow cursor\n"
405 " 2 - wheelhouse cursor\n"
406 " 3 - transparent wheelhouse cursor\n"
407 " 4 - inverted wheelhouse cursor\n"
408 " 5 - black with white lines wheelhouse cursor\n"
409 " Mouse Movement - Move branding iron.\n"
410 " Any Mouse Button - Brand!\n"
412 "Run with \"--usage or -u\" for command-line options...\n"
416 static void print_usage(void)
418 printf("\nUsage: jody [--fullscreen] | [--help (-h) | --usage (-u)]\n\n"
419 " --fullscreen or -f - Display in full screen instead of a window, if possible.\n"
423 static void handle_events(SDL_Surface
*screen
, int *quit
, int *pause
, bool *mouse_clicked
, int *x_mouse
, int *y_mouse
, struct cursors
*cursors
, struct brands
*brands
, SDL_Surface
**brand
)
426 while (SDL_PollEvent(&event
) > 0) {
427 if (event
.type
== SDL_QUIT
) {
429 } else if (event
.type
== SDL_KEYDOWN
) {
430 switch (event
.key
.keysym
.sym
) {
436 SDL_SetCursor(cursors
->cursor_arrow
);
439 SDL_SetCursor(cursors
->cursor_wheelhouse
);
440 *brand
= brands
->brand_wheelhouse
;
443 SDL_SetCursor(cursors
->cursor_wheelhouse_transparent
);
444 *brand
= brands
->brand_wheelhouse_transparent
;
447 SDL_SetCursor(cursors
->cursor_wheelhouse_inverted
);
448 *brand
= brands
->brand_wheelhouse_inverted
;
451 SDL_SetCursor(cursors
->cursor_wheelhouse_black_with_white_lines
);
452 *brand
= brands
->brand_wheelhouse_black_with_white_lines
;
455 SDL_WM_ToggleFullScreen(screen
);
464 } else if (event
.type
== SDL_MOUSEBUTTONDOWN
) {
465 if (event
.button
.button
== SDL_BUTTON_LEFT
) {
466 *mouse_clicked
= true;
467 *x_mouse
= event
.button
.x
;
468 *y_mouse
= event
.button
.y
;
474 static void check_branded(SDL_Rect
*src
, struct sprite
**sprites
, int x_mouse
, int y_mouse
)
476 for (int i
= 0; i
< NUM_IMAGES
; i
++) {
477 double x_rhs
= sprites
[i
]->x
+ src
->w
;
478 double y_bot
= sprites
[i
]->y
+ src
->h
;
480 if (sprites
[i
]->sprite_base
->can_be_branded
&& !sprites
[i
]->is_branded
)
481 if (x_mouse
>= sprites
[i
]->x
&& x_mouse
<= x_rhs
&& y_mouse
>= sprites
[i
]->y
&& y_mouse
<= y_bot
)
482 sprites
[i
]->is_branded
= true;
486 static void move(struct sprite
*sprites
[], int *pause
, double elapsed_ticks
)
488 for (int i
= 0; i
< NUM_IMAGES
; i
++) {
490 double elapsed_seconds
= elapsed_ticks
/ NUM_MILLISECONDS
;
491 double distance
= SPRITE_PIXELS_PER_SECOND
* elapsed_seconds
;
492 xadd(sprites
[i
], distance
);
497 static Uint32
get_elapsed_ticks(void)
499 static Uint32 prev_ticks
= 0;
500 static Uint32 cur_ticks
= 0;
501 prev_ticks
= cur_ticks
;
502 cur_ticks
= SDL_GetTicks();
503 Uint32 elapsed_ticks
= cur_ticks
- prev_ticks
;
504 return elapsed_ticks
;
507 static void main_draw(struct sprite
**sprites
, SDL_Surface
*brand
)
509 for (int i
= 0; i
< NUM_IMAGES
; i
++) {
510 draw(sprites
[i
], brand
);
514 /* static SDL_Rect calc_dest(struct image *image) */
518 /* /\* Move the cow horizontally. *\/ */
519 /* image->x += X_DIST * time_scale; */
520 /* if (image->x > SCREEN_WIDTH) */
522 /* dest.x = image->x; */
524 /* /\* Move the cow vertically and randomly. *\/ */
525 /* /\* Add check for top and bottom; do something sensible */
526 /* like bounce off. *\/ */
528 /* unsigned int odd = random() % 2; */
533 /* dist = - Y_DIST; */
535 /* image->y += dist * time_scale; */
536 /* if (image->y > SCREEN_HEIGHT || image->y < 0) */
537 /* image->y = SCREEN_HEIGHT / 2; */
539 /* dest.y = image->y; */
544 /* static SDL_Surface *image_load(char *file) */
546 /* SDL_Surface *temp1, *temp2; */
547 /* temp1 = IMG_Load(file); */
548 /* if (temp1 == NULL) { */
549 /* fprintf(stderr, */
550 /* "\nError: 'static SDL_Surface * image_load' function couldn't load a graphics file:\n" */
552 /* "The Simple DirectMedia error that occurred was:\n" */
553 /* "%s\n\n", file, SDL_GetError()); */
556 /* temp2 = SDL_DisplayFormat(temp1); */
557 /* SDL_FreeSurface(temp1); */
561 /* static SDL_Surface *init_images() */
563 /* return image_load(IMG_DIR "background.png"); */
566 static void draw_image(SDL_Surface
*img
, SDL_Surface
*screen
, int x
, int y
)
571 SDL_BlitSurface(img
, NULL
, screen
, &dest
);
574 static void draw_background(SDL_Surface
*back
, SDL_Surface
*screen
)
576 draw_image(back
, screen
, 0, 0);