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