]> git.localhorst.tv Git - sdl-test8.git/blob - src/pong/Match.cpp
5754b36c51c5b51564202d31619eddc3b920ff79
[sdl-test8.git] / src / pong / Match.cpp
1 /*
2  * Match.cpp
3  *
4  *  Created on: Apr 9, 2012
5  *      Author: holy
6  */
7
8 #include "Match.h"
9
10 #include "../app/Control.h"
11
12 #include <sstream>
13 #include <stdexcept>
14 #include <utility>
15 #include <SDL/SDL.h>
16
17 using app::Control;
18 using app::Timer;
19 using game::Collision;
20 using game::Entity;
21 using std::runtime_error;
22 using std::stringstream;
23 using std::vector;
24
25
26 namespace pong {
27
28 Match::Match(void)
29 : ctrl(0)
30 , scoreFont(TTF_OpenFont("data/font/Magra-Regular.ttf", 30))
31 , leftScoreText(0)
32 , rightScoreText(0)
33 , paddleSpeed(150)
34 , worldWidth(800)
35 , worldHeight(480)
36 , ball(10)
37 , secondBall(7)
38 , thirdBall(5)
39 , leftPaddle(10, 100)
40 , rightPaddle(10, 100)
41 , topWall(800, 10)
42 , bottomWall(800, 10)
43 , leftWall(10, 480)
44 , rightWall(10, 480)
45 , entities()
46 , collisions()
47 , updateScore(true) {
48
49         if (!scoreFont) {
50                 throw runtime_error("failed to load score font");
51         }
52
53         ball.Translate(Entity::Vector(400, 240));
54         ball.Accelerate(Entity::Vector(180, 180));
55 //      ball.SetMaxVelocity(500.0f);
56
57         secondBall.Translate(Entity::Vector(300, 240));
58         secondBall.Accelerate(Entity::Vector(-50, -50), 1);
59 //      secondBall.SetMaxVelocity(600.0f);
60
61         thirdBall.Translate(Entity::Vector(200, 440));
62         thirdBall.Accelerate(Entity::Vector(60, 40));
63
64         leftPaddle.Translate(Entity::Vector(5, 200));
65         rightPaddle.Translate(Entity::Vector(795, 280));
66
67         leftPaddle.SetMovementSpeed(Entity::Vector(0, paddleSpeed));
68         rightPaddle.SetMovementSpeed(Entity::Vector(0, paddleSpeed));
69
70         topWall.Translate(Entity::Vector(400, -5));
71         rightWall.Translate(Entity::Vector(805, 240));
72         bottomWall.Translate(Entity::Vector(400, 485));
73         leftWall.Translate(Entity::Vector(-5, 240));
74
75         entities.reserve(9);
76         entities.push_back(&ball);
77         entities.push_back(&secondBall);
78         entities.push_back(&thirdBall);
79         entities.push_back(&leftPaddle);
80         entities.push_back(&rightPaddle);
81         entities.push_back(&topWall);
82         entities.push_back(&bottomWall);
83         entities.push_back(&leftWall);
84         entities.push_back(&rightWall);
85
86         collisions.reserve(2 * entities.size());
87 }
88
89 Match::~Match(void) {
90
91 }
92
93
94 void Match::EnterState(Control *c, SDL_Surface *screen) {
95         ctrl = c;
96 }
97
98 void Match::ExitState(void) {
99         if (scoreFont) {
100                 TTF_CloseFont(scoreFont);
101                 scoreFont = 0;
102         }
103 }
104
105 void Match::HandleEvent(const SDL_Event &e) {
106         if (e.type == SDL_KEYDOWN) {
107                 if (e.key.keysym.sym == SDLK_w) {
108                         leftPaddle.StartMovingUp();
109                 } else if (e.key.keysym.sym == SDLK_s) {
110                         leftPaddle.StartMovingDown();
111                 } else if (e.key.keysym.sym == SDLK_UP) {
112                         rightPaddle.StartMovingUp();
113                 } else if (e.key.keysym.sym == SDLK_DOWN) {
114                         rightPaddle.StartMovingDown();
115                 }
116         } else if (e.type == SDL_KEYUP) {
117                 if (e.key.keysym.sym == SDLK_w) {
118                         leftPaddle.StopMovingUp();
119                 } else if (e.key.keysym.sym == SDLK_s) {
120                         leftPaddle.StopMovingDown();
121                 } else if (e.key.keysym.sym == SDLK_UP) {
122                         rightPaddle.StopMovingUp();
123                 } else if (e.key.keysym.sym == SDLK_DOWN) {
124                         rightPaddle.StopMovingDown();
125                 } else if (e.key.keysym.sym == SDLK_q) {
126                         if (ctrl) ctrl->Quit();
127                 }
128         }
129 }
130
131 void Match::UpdateWorld(const Timer &timer) {
132         UpdateEntities(timer);
133         CheckCollisions(timer);
134         HandleCollisions(timer);
135 }
136
137 void Match::UpdateEntities(const Timer &timer) {
138         for (vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
139                 (*i)->Update(timer);
140         }
141 }
142
143 void Match::CheckCollisions(const Timer &timer) {
144         Entity::Ray normal;
145         for (vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
146                 for (vector<Entity *>::const_iterator j(i + 1); j != end; ++j) {
147                         if ((*i)->CheckCollision(**j, normal)) {
148                                 collisions.push_back(Collision(*i, *j, normal));
149                         }
150                 }
151         }
152 }
153
154 void Match::HandleCollisions(const Timer &timer) {
155         for (vector<Collision>::const_iterator i(collisions.begin()), end(collisions.end()); i != end; ++i) {
156                 Entity::CollisionResponse(*(i->left), i->normal, *(i->right));
157         }
158         // TODO: resolve collisions of static objects
159         for (vector<Collision>::const_iterator i(collisions.begin()), end(collisions.end()); i != end; ++i) {
160                 i->left->Collide(*i->right, i->normal);
161                 i->right->Collide(*i->left, i->normal);
162         }
163         if (!collisions.empty()) {
164                 updateScore = true;
165         }
166         collisions.clear();
167 }
168
169
170 void Match::Render(SDL_Surface *screen) {
171         SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
172         for (vector<Entity *>::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) {
173                 (*i)->Render(screen);
174         }
175         RenderHUD(screen);
176 }
177
178 void Match::RenderHUD(SDL_Surface *screen) {
179         if (updateScore) {
180                 UpdateScore(screen);
181                 updateScore = false;
182         }
183         RenderScore(screen);
184 }
185
186 void Match::RenderScore(SDL_Surface *screen) {
187         SDL_Rect dest = { 2, 2, 0, 0 };
188         SDL_BlitSurface(leftScoreText, 0, screen, &dest);
189
190         dest.x = screen->w - rightScoreText->w - 2;
191         SDL_BlitSurface(rightScoreText, 0, screen, &dest);
192 }
193
194 void Match::UpdateScore(SDL_Surface *screen) {
195         if (!scoreFont) return;
196         if (leftScoreText) SDL_FreeSurface(leftScoreText);
197         if (rightScoreText) SDL_FreeSurface(rightScoreText);
198
199         SDL_Color color;
200         color.r = 0xFF;
201         color.g = 0xFF;
202         color.b = 0xFF;
203
204         stringstream s;
205         s << rightWall.HitCount();
206         leftScoreText = TTF_RenderUTF8_Blended(scoreFont, s.str().c_str(), color);
207
208         s.str("");
209         s << leftWall.HitCount();
210         rightScoreText = TTF_RenderUTF8_Blended(scoreFont, s.str().c_str(), color);
211 }
212
213 }