To The Flag by ML (mlefebvre.fr)
play.c
Go to the documentation of this file.
1 
9 #include <stdio.h>
10 #include <math.h>
11 
12 #include <SDL/SDL.h>
13 #include <SDL/SDL_image.h>
14 #include <SDL/SDL_ttf.h>
15 
16 #include "constants.h"
17 #include "play.h"
18 
23 void playGame(SDL_Surface *w)
24 {
25  // --- DECLARE VARIABLES ---
26  LAYOUT l;
27  LAYOUT_TEXT t;
28  SUCCESS_TEXT s;
29  SDL_Event e;
30 
31  float rad = RAD_START, speed = SPEED_START;
32 
33  // --- CONTROL VARIABLE ---
34  int run = 1;
35 
36  // --- LOAD GAME ---
37  loadFont(&t, &s); // Create fonts and set parameters
38  loadLayout(&l); // Load layout images and set parameters
39  drawLine(&l, rad); // Draw the help line with init parameters
40 
41  // --- EXECUTE APPLICATION CONTINUOUSLY ---
42  while(run)
43  {
44  drawLayout(w, &l); // Draw the whole layout on the main window
45  drawText(w, &t); // Draw the angle and speed texts on the main window
46 
47  SDL_WaitEvent(&e); // Wait for the next user event
48  switch(e.type) // Test event type value
49  {
50  case SDL_QUIT: // If the user wants to close the window
51  run = 0; // Stop the application
52  break;
53  case SDL_KEYDOWN: // If the user pressed a keyboard key
54  switch(e.key.keysym.sym) // Test key value
55  {
56  case SDLK_UP: // If the user pressed the up arrow key
57  if(rad < 85) drawLine(&l, rad++); // Increase angle and redraw the help line
58  break;
59  case SDLK_DOWN: // If the user pressed the down arrow key
60  if(10 < rad) drawLine(&l, rad--); // Decrease angle and redraw the help line
61  break;
62  case SDLK_RIGHT: // If the user pressed the right arrow key
63  if(rad < 80) speed++; // Increase speed
64  break;
65  case SDLK_LEFT: // If the user pressed the left arrow key
66  if(5 < rad) speed--; // Decrease speed
67  break;
68  case SDLK_RETURN: // If the user pressed the carriage return key
69  if(shoot(w, &l, rad, speed)) // Shoot the ball for the chosen angle and speed and check if it reached the flag
70  {
71  drawResult(w, &s, SUCCESS); // Draw the success text on the main window
72  SDL_Delay(1000); // Wait for a second
73  run = 0; // End loop, get back to menu
74  }
75  else
76  {
77  drawResult(w, &s, FAIL); // Draw the fail text on the main window
78  SDL_Delay(1000); // Wait for a second
79  reloadLayout(&l); // Reload the whole layout for the next shot
80  }
81  break;
82  case SDLK_ESCAPE: // If the user pressed the carriage return key
83  run = 0; // End loop, get back to menu
84  break;
85  default: // In any other case, do nothing
86  break;
87  }
88  default: // In any other case, do nothing
89  break;
90  }
91  setParameters(&t, rad, speed); // Set parameters so that the change reflects on the window
92  }
93 
94  cleanUp(&l, &t, &s); // Free all the memory used by the layout and texts
95 }
96 
97 int shoot(SDL_Surface *w, LAYOUT *l, float a, float sp)
98 {
99  // --- DECLARE VARIABLES ---
100  SDL_Event e;
101  int x = X_START, ground_level = 0;
102  int rad = (int) a, test = 0;
103 
104  // --- CONTROL VARIABLE ---
105  int run = 1;
106 
107  a = a * PI / 180; // Convert angle from degrees to radians
108 
109  // --- EXECUTE APPLICATION CONTINUOUSLY ---
110  while(run)
111  {
112  SDL_PollEvent(&e); // Check if an event occured
113  switch(e.type) // Test event type value
114  {
115  case SDL_QUIT: // If the user wants to close the window
116  run = 0; // Stop the application
117  break;
118  case SDL_KEYDOWN: // If the user pressed a keyboard key
119  switch(e.key.keysym.sym) // Test key value
120  {
121  case SDLK_ESCAPE: // If the user pressed the carriage return key
122  run = 0; // End loop, get back to menu
123  break;
124  default: // In any other case, do nothing
125  break;
126  }
127  default: // In any other case, do nothing
128  break;
129  }
130 
131  // --- SET BALL POSITION --
132  l->pObject.x = x;
133  l->pObject.y = (Y_START - l->object->h) - ((-0.5 * G * pow(x, 2)) / pow(cos(a) * sp, 2) + tan(a) * x);
134 
135  if(x + (l->object->w / 2) <= 400) ground_level = Y_START; // Get ground_level under the ball
136  else ground_level = Y_START + GROUND_DIFF; // Y_START : first part of the layout, adding GROUND_DIFF for second part
137 
138  if(l->pObject.y <= (ground_level - l->object->h)) // If the ball is still flying
139  {
140  if((x % (100 - rad)) == X_START) // If 100, 200th... frame
141  {
142  SDL_FreeSurface(l->background); // Then delete background
143  l->background = SDL_DisplayFormat(w); // Save current window state into the background variable
144  }
145  drawLayout(w, l); // Draw the updated layout
146  x++; // Get to next frame
147  }
148  else // If the ball landed on the floor
149  {
150  x = l->pObject.x + (l->object->w / 2); // Consider ball center as ball position instead of ball left side
151  if(((l->pFlag.x - (l->object->w / 2)) <= x) && // If the ball landed on the flag
152  (x <= (l->pFlag.x + (l->object->w / 2)))) // -> ball position if within a radius around the flag
153  {
154  test = 1; // Then set test to 1
155  }
156 
157  run = 0; // End shot loop
158  }
159  SDL_Delay(GAME_SPEED); // Wait GAME_SPEED ms before next frame
160  }
161 
162  return test; // return shot success state
163 }
164 
166 {
167  s->fontPath = "data/American Captain.ttf"; // Set font path
168  s->fontColor.r = 0; // Set red component of the font
169  s->fontColor.g = 0; // Set green component of the font
170  s->fontColor.b = 0; // Set blue component of the font
171  s->font = TTF_OpenFont(s->fontPath,FONT_SIZE * 3); // Create font reference
172 
173  t->fontPath = "data/American Captain.ttf"; // Set font path
174  t->fontColor.r = 255; // Set red component of the font
175  t->fontColor.g = 255; // Set green component of the font
176  t->fontColor.b = 255; // Set blue component of the font
177  t->font = TTF_OpenFont(s->fontPath,FONT_SIZE); // Create font reference
178 
179  if((t->font != NULL) && (s->font != NULL)) // If the font where created properly
180  {
181  setParameters(t, RAD_START, SPEED_START); // Set help line parameters to start position
182 
183  t->pAngle.x = MARGIN; // Set angle text
184  t->pAngle.y = WINDOW_HEIGHT - MARGIN - t->angle->h - t->speed->h + 5; // position
185 
186  t->pSpeed.x = MARGIN; // Set angle text
187  t->pSpeed.y = WINDOW_HEIGHT - MARGIN - t->speed->h; // position
188  }
189 }
190 
191 void setParameters(LAYOUT_TEXT *t, float a, float sp)
192 {
193  sprintf(t->tAngle, "Angle : %.0f", a); // Save new angle text in the structure
194  sprintf(t->tSpeed, "Speed : %.0f", sp); // Save new speed text in the structure
195  t->angle = TTF_RenderText_Blended(t->font, t->tAngle, t->fontColor); // Render angle text for future use
196  t->speed = TTF_RenderText_Blended(t->font, t->tSpeed, t->fontColor); // Render speed text for future use
197 }
198 
200 {
201  l->background = IMG_Load("art/background.png"); // Load background image
202  l->object = IMG_Load("art/object.png"); // Load ball image
203  l->flag = IMG_Load("art/flag.png"); // Load flag image
204  l->line = IMG_Load("art/line.png"); // Load line image
205  l->point = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, 1, 32, 0, 0, 0, 0); // Create point surface
206  SDL_FillRect(l->point, NULL, SDL_MapRGB(l->point->format, 255, 0, 0)); // Fill point with red color
207 
208  // --- SET BACKGROUND POSITION ---
209  l->pBackground.x = 0; // Set background position to
210  l->pBackground.y = 0; // window's top left corner
211 
212  // --- SET FLAG POSITION ---
213  l->pFlag.x = FLAG_START + rand()%(WINDOW_WIDTH - FLAG_START); // Randomly place flag on the window
214 
215  while((400 <= l->pFlag.x) && (l->pFlag.x <= 450)) // If the flag is placed in an impossible to reach place
216  {
217  l->pFlag.x = FLAG_START + rand()%(WINDOW_WIDTH - FLAG_START); // Then change flag's position
218  }
219 
220  if(l->pFlag.x <= 399) l->pFlag.y = Y_START - l->flag->h + FLAG_HEIGHT; // Set flag y position to top or bottom
221  else l->pFlag.y = Y_START + GROUND_DIFF - l->flag->h + FLAG_HEIGHT; // part, according to x position value
222 
223  // --- SET ALL OTHER ELEMENTS' POSITION ---
224  l->pObject.x = X_START;
225  l->pObject.y = Y_START - l->object->h;
226 
227  l->pPoint.x = 0;
228  l->pPoint.y = 0;
229 
230  l->pLine.x = l->pObject.x + (l->object->w / 2);
231  l->pLine.y = l->pObject.y + (l->object->h / 2) - l->line->h;
232 }
233 
235 {
236  SDL_FreeSurface(l->background); // Delete background
237  l->background = IMG_Load("art/background.png"); // Reload init background
238  l->pObject.x = X_START; // Reset ball position
239  l->pObject.y = Y_START - l->object->h; // on the main window
240 }
241 
242 void drawLayout(SDL_Surface *w, LAYOUT *l)
243 {
244  SDL_FillRect(w, NULL, SDL_MapRGB(w->format, 0, 0, 0)); // Reset window
245  SDL_BlitSurface(l->background, NULL, w, &l->pBackground); // Append background to the main window
246  SDL_BlitSurface(l->flag, NULL, w, &l->pFlag); // Append flag to the main window
247  SDL_BlitSurface(l->object, NULL, w, &l->pObject); // Append ball to the main window
248  SDL_BlitSurface(l->line, NULL, w, &l->pLine); // Append line to the main window
249 
250  SDL_Flip(w); // Draw the main window
251 }
252 
253 void drawLine(LAYOUT *l, float a)
254 {
255  a = a * PI / 180; // Convert angle from degrees to radians
256 
257  SDL_FreeSurface(l->line); // Delete line surface
258  l->line = IMG_Load("art/line.png"); // Reload line init image
259 
260  for(int x = 0 ; x < LINE_SIZE ; x++) // For each point
261  {
262  l->pPoint.x = x * cos(a); // Calculate the x position
263  l->pPoint.y = l->line->h - (x * sin(a)); // Calculate the y position
264  SDL_BlitSurface(l->point, NULL, l->line, &l->pPoint); // Append point to the line image
265  }
266 }
267 
268 void drawText(SDL_Surface *w, LAYOUT_TEXT *t)
269 {
270  SDL_BlitSurface(t->angle, NULL, w, &t->pAngle); // Append angle text to the main window
271  SDL_BlitSurface(t->speed, NULL, w, &t->pSpeed); // Append speed text to the main window
272 
273  SDL_Flip(w); // Draw the main window
274 }
275 
276 void drawResult(SDL_Surface *w, SUCCESS_TEXT *s, int result)
277 {
278  if(result) // If the player reached the flag
279  {
280  s->fontColor.g = 255; // Change color to green
281  s->fontColor.r = 0; // and remove red
282  s->text = TTF_RenderText_Blended(s->font, "CONGRATS !", s->fontColor); // Render SUCCESS text for future use
283  }
284  else
285  {
286  s->fontColor.g = 0; // Remove green
287  s->fontColor.r = 255; // and change color to red
288  s->text = TTF_RenderText_Blended(s->font, "TRY AGAIN...", s->fontColor); // Render FAIL text for future use
289  }
290 
291  s->pText.x = WINDOW_WIDTH - MARGIN - s->text->w; // Set result text x position
292  s->pText.y = WINDOW_HEIGHT + MARGIN - s->text->h; // Set result text y position
293 
294  SDL_BlitSurface(s->text, NULL, w, &s->pText); // Append result text to the main window
295  SDL_Flip(w); // Draw the main window
296 
297  SDL_FreeSurface(s->text); // Free the allocated memory for the result text surface
298 }
299 
301 {
302  SDL_FreeSurface(l->background); // Free the allocated memory for the background surface
303  SDL_FreeSurface(l->flag); // Free the allocated memory for the flag surface
304  SDL_FreeSurface(l->line); // Free the allocated memory for the line surface
305  SDL_FreeSurface(l->object); // Free the allocated memory for the ball surface
306  SDL_FreeSurface(l->point); // Free the allocated memory for the point surface
307  SDL_FreeSurface(t->angle); // Free the allocated memory for the angle text surface
308  SDL_FreeSurface(t->speed); // Free the allocated memory for the speed text surface
309 
310  TTF_CloseFont(t->font); // Delete angle and speed text font
311  TTF_CloseFont(s->font); // Delete result text font
312 }
void reloadLayout(LAYOUT *l)
Definition: play.c:234
void playGame(SDL_Surface *w)
Definition: play.c:23
void drawText(SDL_Surface *w, LAYOUT_TEXT *t)
Definition: play.c:268
void drawLayout(SDL_Surface *w, LAYOUT *l)
Definition: play.c:242
Contains every application constants.
void loadLayout(LAYOUT *l)
Definition: play.c:199
int shoot(SDL_Surface *w, LAYOUT *l, float a, float sp)
Definition: play.c:97
Contains every functions declaration for play.c.
void loadFont(LAYOUT_TEXT *t, SUCCESS_TEXT *s)
Definition: play.c:165
void drawResult(SDL_Surface *w, SUCCESS_TEXT *s, int result)
Definition: play.c:276
void drawLine(LAYOUT *l, float a)
Definition: play.c:253
void cleanUp(LAYOUT *l, LAYOUT_TEXT *t, SUCCESS_TEXT *s)
Definition: play.c:300
Definition: play.h:26
void setParameters(LAYOUT_TEXT *t, float a, float sp)
Definition: play.c:191