SDL2 example
[mirrors/Programs.git] / c / pong / pong.c
1 /* hPong 0.3
2 * <~~Harvie 2oo8
3 * Released under Creative Commons
4 *
5 * Requirements:
6 * - stty
7 * - ansi terminal with resolution >= 80x24 characters
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <signal.h>
13
14 //Settings
15 char pixchar = '#';
16
17 int turntime = 25; //Time of turn in ms (inverted speed)
18 int debugturntime = 0; //Turntime for debuging
19
20 unsigned char padsize = 1; //Size of pad
21 char padspeed = 2; //Speed of pad (pixels per keypress)
22
23 unsigned char ui_skill_l = 255; //Skill of UI = (0-255); 0=disabled, 255=godmode
24 unsigned char ui_skill_r = 200; //Skill of UI = (0-255); 0=disabled, 255=godmode
25 unsigned char debug = 0; //UI Debug mode
26
27 unsigned char music = 0; //Enable music? (Bool)
28 char music_cmd[] ="while true; do mplayer /usr/share/chiptunes/* >/dev/null 2>&1; done;";
29
30 unsigned char arduino = 0; //Enable Arduino? (Bool)
31 char arduinodev[] = "/dev/ttyUSB0";
32
33 //Stadium
34 unsigned char *stadium_bitmap[] = {
35 "#### hPong 0.3 ################################################",
36 "# | #",
37 "# #",
38 "# | #",
39 "# #",
40 "# | #",
41 "# #",
42 "# | #",
43 "# #",
44 "# | #",
45 "# #",
46 "# | #",
47 "# #",
48 "# | #",
49 "# #",
50 "# | #",
51 "########################################### <~~Harvie 2oo8 ####"};
52 char stadium_lines = 17; //15+2
53 char stadium_width = 63; //60+2+1
54
55 //Banners
56 unsigned char banner_start[] =
57 "\n\n\n\n\n\n\n\n\n\n\n"
58 " ## #### by: <~~Harvie 2oo8\n"
59 " ## # #\n"
60 " ## ## ## #### ### #### ###\n"
61 " ####### ###### # # # # # # #\n"
62 " ## ## ## # ### # # ####\n"
63 " ## ## ## #\n"
64 " ## Press any key to start! ###\n";
65
66 unsigned char banner_lose[] =
67 "\n\n\n\n\n\n\n\n\n\n\n\n\n"
68 " ### # # ### # # # ### #\n"
69 " # # # # # # # # # #\n"
70 " # # ### ### ### # # #\n"
71 " # # # # # # # # #\n"
72 " ### # # ### # # # # #\n"
73 "\n"
74 " Score: %d : %d\n"
75 " (Press Any Key to continue...)\n";
76
77 //Numbers
78 char stadium_offset = 7;
79 char score_space[] = " ";
80 unsigned char *num_bitmaps[]={
81 "#### ## ## ####", //0
82 " # # # # #", //1...
83 "### ##### ###",
84 "### #### ####",
85 " # # ### # ",
86 "#### ### ####",
87 "#### #### ####",
88 "### # # # # ",
89 "#### ##### ####",
90 "#### #### ####"}; //9
91
92 //Other Values
93 char stadium_max; //Set by init()
94
95 char ball_c = 1; //x
96 char ball_l = 0; //y
97 char ballmove_c = 1; //x
98 char ballmove_l = 1; //y
99
100 char player_l = 7; //Left
101 char player_r = 7; //Right
102
103 unsigned int score_l = 0;
104 unsigned int score_r = 0;
105
106 //Misc
107 char loop=0;
108 char temp;
109 FILE *musicfd = NULL;
110 FILE *arduinofd = NULL;
111
112 //Functions
113 void blank() {
114 printf("\033[2J"); //Clear screen
115 printf("\033[0;0H"); //L:C = 0:0
116 }
117
118 void quit() {
119 if(arduino) fclose(arduinofd);
120 ualarm(0, 0);
121 system("stty icanon");
122 blank();
123 printf("hPong exited! Scrore was %d : %d\n<~~Harvie 2oo8\n", score_l, score_r);
124 exit(255);
125 if(music) pclose(musicfd);
126 }
127
128 void music_start() {
129 if( (musicfd = popen(music_cmd, "r"))==NULL ) {
130 printf("Cannot initialize music\n");
131 quit();
132 }
133 }
134
135 void win(char player) {
136 switch(player) {
137 case 'l':
138 score_l++;
139 ball_l = 2; ball_c = stadium_width-3; ballmove_c = -1;
140 break;
141
142 case 'r':
143 score_r++;
144 ball_l = 2; ball_c = 3; ballmove_c = 1;
145 break;
146 }
147 blank();
148 printf(banner_lose, score_l, score_r);
149 if(!debug) sleep(1);
150 if(!arduino && (ui_skill_l == 0 || ui_skill_r == 0)) getchar();
151 blank();
152 }
153
154 void reset_scr() {
155 printf("\033[0;0H"); //L:C = 0:0
156 }
157
158 void pixel(char c, char line, char col) {
159 printf("\033[%d;%dH", line, col);
160 putchar(c);
161 printf("\033[0;0H"); //L:C = 0:0
162 }
163
164 void draw_stadium() {
165 unsigned char i, x, sl, sr;
166 sl = score_l%10; sr = score_r%10;
167 for(i=0;i<stadium_offset;i++) {
168 printf("\033[K");
169 if(i>=1 && i<=5) {
170 x = (i-1)*3;
171 printf("%s%c%c%c . %c%c%c", score_space,
172 num_bitmaps[sl][x], num_bitmaps[sl][x+1], num_bitmaps[sl][x+2],
173 num_bitmaps[sr][x], num_bitmaps[sr][x+1], num_bitmaps[sr][x+2]
174 );
175 }
176 putchar('\n');
177 }
178 for(i=0;i<stadium_lines;i++) printf("%s\033[K\n", stadium_bitmap[i]);
179 printf("\033[K");
180 }
181
182 void recalc() {
183 //UI - follow ball
184 if((unsigned char)rand() < ui_skill_l) { //Left
185 if(player_l < ball_l) player_l++;
186 if(player_l > ball_l) player_l--;
187 }
188
189 if((unsigned char)rand() < ui_skill_r) { //Right
190 if(player_r < ball_l) player_r++;
191 if(player_r > ball_l) player_r--;
192 }
193
194 //Move ball
195 ball_c += ballmove_c;
196 ball_l += ballmove_l;
197
198 //Pong (horizontal)
199 if(ball_c == 1) { //left
200 if(abs(ball_l-player_l) <= padsize+1) {
201 ballmove_c = -ballmove_c;
202 ball_c++;
203 } else {
204 win('r');
205 }
206 }
207
208 if(ball_c == stadium_width-3) { //right
209 if(abs(ball_l-player_r) <= padsize+1) {
210 ballmove_c = -ballmove_c;
211 ball_c--;
212 } else {
213 win('l');
214 }
215 }
216
217 //Bounce ball (vertical)
218 if(ball_l >= stadium_max || ball_l <= 0) ballmove_l = -ballmove_l;
219 }
220
221 void redraw() {
222 char i;
223 //Clear
224 reset_scr();
225
226 //Stadium
227 draw_stadium();
228
229 //Check player pos limits
230 if(player_r < 0) player_r = 0;
231 if(player_r > stadium_max) player_r = stadium_max;
232
233 if(player_l < 0) player_l = 0;
234 if(player_l > stadium_max) player_l = stadium_max;
235
236 //Pads
237 for(i=-padsize;i<padsize+1;i++) pixel(pixchar, stadium_offset+2+i+player_l, 2);
238 for(i=-padsize;i<padsize+1;i++) pixel(pixchar, stadium_offset+2+i+player_r, stadium_width-1);
239
240 //Ball
241 pixel(pixchar, stadium_offset+2+ball_l, 2+ball_c);
242 fflush(stdout);
243 }
244
245 void splash() {
246 blank();
247 puts(banner_start);
248 getchar();
249 blank();
250 }
251
252 void control(unsigned char key) {
253 switch(key) {
254 case 'A': player_r-=padspeed; break; //A = Arrow UP
255 case 'B': player_r+=padspeed; break; //B = Arrow DOWN
256 case 'q': case 'Q':
257 loop=0;
258 quit();
259 break;
260 case 'e': case 'E': player_l-=padspeed; break; //e key
261 case 'd': case 'D': player_l+=padspeed; break; //D key
262 }
263
264 redraw();
265 }
266
267 void alarm_handle(int signo) {
268 recalc();
269 redraw();
270 if(signo == SIGTERM || signo == SIGINT || signo == SIGQUIT) quit();
271 }
272
273 void init() {
274 //Blank screen
275 blank();
276 //Init random generator
277 srand(time(NULL));
278 //Disable both input buffers
279 setbuf(stdin, NULL);
280 system("stty -icanon");
281 //Handle alarm (timer)
282 signal(SIGALRM, alarm_handle);
283 signal(SIGINT, alarm_handle); signal(SIGTERM, alarm_handle); signal(SIGQUIT, alarm_handle);
284 //Compute lower sprite position in stadium
285 stadium_max = stadium_lines - 3;
286 //Debug mode
287 if(debug) turntime = debugturntime;
288 //Open Arduino
289 if( arduino&&((arduinofd=fopen(arduinodev,"rb"))==NULL) ) {
290 printf("Cannot open %s\n", arduinodev);
291 exit(255);
292 }
293 }
294
295 //Main... Short & simple ;)
296 int main() {
297 init();
298 splash();
299
300 //Music
301 if(music) music_start();
302
303 loop = 1;
304 ualarm(turntime*1000+1, turntime*1000+1);
305 while(loop) {
306 if(arduino) player_r = getc(arduinofd); //Arduino
307 else control(getchar()); //Keyboard
308 }
309 quit();
310 }
311
This page took 0.462925 seconds and 4 git commands to generate.