Created
May 22, 2018 12:37
-
-
Save fernandozamoraj/05c6ad533ded5fd6b803df82b8247e61 to your computer and use it in GitHub Desktop.
Pong.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <windows.h> | |
#include <conio.h> | |
#include <string.h> | |
void print_at_xy(int x, int y, char *val); | |
void display_score(); | |
void init(); | |
int zero_lives(); | |
void set_game_state_over(); | |
void update_ball(); | |
char get_input(); | |
void update_player(char); | |
int ball_collides_with_bat(); | |
void increment_score(); | |
int ball_is_out_bounds(); | |
void decrement_lives(); | |
void draw(); | |
void clean_up(); | |
int ball_collides_with_wall(); | |
int ball_collides_with_ceiling(); | |
void capture_previous_pos(); | |
void clear_screen(); | |
void reset_ball(); | |
void display_message(const char *); | |
HANDLE _output_handle; | |
void hidecursor() | |
{ | |
_output_handle = GetStdHandle(STD_OUTPUT_HANDLE); | |
CONSOLE_CURSOR_INFO info; | |
info.dwSize = 100; | |
info.bVisible = FALSE; | |
SetConsoleCursorInfo(_output_handle, &info); | |
} | |
int SCREEN_WIDTH; | |
int SCREEN_HEIGHT; | |
int bat_y; | |
int bat_x; | |
int BAT_WIDTH; | |
int BAT_SPEED; | |
int ball_x; | |
int ball_y; | |
int lives; | |
int game_state; | |
int GAME_STATE_OVER; | |
int GAME_STATE_PLAYING; | |
int GOAL_POINTS; | |
int delta_x; | |
int delta_y; | |
int score; | |
char ball_string[2]; | |
char bat_string[20]; | |
char game_over_string[30]; | |
int prev_bat_x; | |
int prev_bat_y; | |
int prev_ball_x; | |
int prev_ball_y; | |
int main(){ | |
init(); | |
printf("\ninit"); | |
system("@cls||clear"); | |
//1000/30 | |
//game loop | |
while(1){ | |
clear_screen(); | |
if(zero_lives()){ | |
set_game_state_over(); | |
print_at_xy(SCREEN_WIDTH/2 - 10, SCREEN_HEIGHT/2, game_over_string); | |
display_message("Enter 'q' to quit..."); | |
} | |
char ch = get_input(); | |
//clear screen and quit | |
if(game_state == GAME_STATE_OVER && ch == 'q'){ | |
system("@cls||clear"); | |
break; | |
} | |
if(game_state == GAME_STATE_PLAYING){ | |
clear_screen(); | |
capture_previous_pos(); | |
update_ball(); | |
update_player(ch); | |
if(ball_collides_with_wall()){ | |
delta_x *= -1; | |
} | |
if(ball_collides_with_ceiling()){ | |
delta_y *= -1; | |
} | |
if(ball_collides_with_bat()){ | |
display_message("OH YEAH!!!"); | |
if(delta_y > 0){ | |
delta_y *= -1; | |
} | |
increment_score(); | |
} | |
if(ball_is_out_bounds()){ | |
decrement_lives(); | |
reset_ball(); | |
display_message("OOPSIE!!"); | |
} | |
draw(); | |
Sleep(100); | |
} | |
} | |
clean_up(); | |
} | |
void init(){ | |
score = 0; | |
lives = 3; | |
GOAL_POINTS = 10; | |
GAME_STATE_OVER = 1; | |
GAME_STATE_PLAYING = 2; | |
SCREEN_WIDTH = 40; | |
SCREEN_HEIGHT = 20; | |
bat_y = SCREEN_HEIGHT; | |
BAT_WIDTH = 8; | |
BAT_SPEED = 2; | |
bat_x = (SCREEN_WIDTH/2) - (BAT_WIDTH/2); | |
delta_x = 1; | |
delta_y = -1; | |
ball_x = (SCREEN_WIDTH/2); | |
ball_y = SCREEN_HEIGHT; | |
game_state = GAME_STATE_PLAYING; | |
strcpy(bat_string, "========"); | |
strcpy(ball_string, "O"); | |
strcpy(game_over_string, "GAME OVER"); | |
hidecursor(); | |
prev_bat_x = bat_x; | |
prev_bat_y = bat_y; | |
prev_ball_x = ball_x; | |
prev_ball_y = ball_y; | |
} | |
void reset_ball(){ | |
ball_x = SCREEN_WIDTH/2; | |
ball_y = SCREEN_HEIGHT; | |
delta_x = -1; | |
delta_y = -1; | |
} | |
int zero_lives(){ | |
if(lives == 0){ | |
return 1; | |
} | |
return 0; | |
} | |
void set_game_state_over(){ | |
game_state = GAME_STATE_OVER; | |
} | |
void update_ball(){ | |
ball_x += delta_x; | |
ball_y += delta_y; | |
} | |
char get_input(){ | |
char ch = 0; | |
if(kbhit()){ | |
ch = getch(); | |
} | |
return ch; | |
} | |
void update_player(char ch){ | |
if(ch == 'j' || ch == 'J') | |
{ | |
bat_x -= BAT_SPEED; | |
} | |
else if(ch == 'k' || ch =='K'){ | |
bat_x += BAT_SPEED; | |
} | |
if(bat_x < 0){ | |
bat_x = 0; | |
} | |
if(bat_x + BAT_WIDTH > SCREEN_WIDTH){ | |
bat_x = SCREEN_WIDTH - BAT_WIDTH; | |
} | |
} | |
int ball_collides_with_bat(){ | |
if(bat_y == ball_y || (bat_y == ball_y-1)){ | |
if(bat_x <= ball_x && (bat_x + BAT_WIDTH) >= ball_x){ | |
return 1; | |
} | |
} | |
return 0; | |
} | |
void increment_score(){ | |
score += GOAL_POINTS; | |
} | |
int ball_is_out_bounds(){ | |
if(ball_y > SCREEN_HEIGHT + 3){ | |
return 1; | |
} | |
return 0; | |
} | |
void decrement_lives(){ | |
lives--; | |
} | |
void draw(){ | |
print_at_xy(ball_x, ball_y, ball_string); | |
print_at_xy(bat_x, bat_y, bat_string); | |
display_score(); | |
} | |
void print_at_xy(int x, int y, char *val) | |
{ | |
COORD coord; | |
coord.X = x; | |
coord.Y = y; | |
SetConsoleCursorPosition(_output_handle, coord); | |
printf("%s", (const char *)val); | |
fflush(stdout); | |
} | |
void display_score(){ | |
char buffer[50] = {0}; | |
sprintf(buffer, "SCORE: %4d LIVES: %d", score, lives); | |
print_at_xy(0, 0, buffer); | |
} | |
int ball_collides_with_wall(){ | |
return ball_x <= 0 || (ball_x-1) >= SCREEN_WIDTH; | |
} | |
int ball_collides_with_ceiling(){ | |
return ball_y <= 0; | |
} | |
void capture_previous_pos(){ | |
prev_ball_x = ball_x; | |
prev_ball_y = ball_y; | |
prev_bat_x = bat_x; | |
prev_bat_y = bat_y; | |
} | |
void clear_screen(){ | |
char buffer[] = " "; | |
print_at_xy(prev_ball_x, prev_ball_y, buffer); | |
print_at_xy(prev_bat_x, prev_bat_y, buffer); | |
print_at_xy(0, 0, buffer); | |
} | |
void display_message(const char *message){ | |
char buffer[100] = {0}; | |
strcpy(buffer, message); | |
print_at_xy(SCREEN_WIDTH/2 - strlen(message)/2, | |
SCREEN_HEIGHT/2 - 1, buffer); | |
} | |
void clean_up(){ | |
printf("Thanks for playing."); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment