1 /* --------------------------------------------------------------------
2 EXTREME TUXRACER
3 
4 Copyright (C) 1999-2001 Jasmin F. Patry (Tuxracer)
5 Copyright (C) 2010 Extreme Tux Racer Team
6 
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 ---------------------------------------------------------------------*/
17 
18 #ifdef HAVE_CONFIG_H
19 #include <etr_config.h>
20 #endif
21 
22 #include "game_over.h"
23 #include "audio.h"
24 #include "ogl.h"
25 #include "view.h"
26 #include "course_render.h"
27 #include "env.h"
28 #include "hud.h"
29 #include "track_marks.h"
30 #include "particles.h"
31 #include "gui.h"
32 #include "font.h"
33 #include "spx.h"
34 #include "game_ctrl.h"
35 #include "translation.h"
36 #include "score.h"
37 #include "race_select.h"
38 #include "event.h"
39 #include "winsys.h"
40 #include "physics.h"
41 #include "tux.h"
42 
43 CGameOver GameOver;
44 
45 static CKeyframe *final_frame;
46 static int highscore_pos = MAX_SCORES;
47 
QuitGameOver()48 void QuitGameOver() {
49 	if (g_game.game_type == PRACTICING) {
50 		State::manager.RequestEnterState(RaceSelect);
51 	} else {
52 		State::manager.RequestEnterState(Event);
53 	}
54 }
55 
Keyb(sf::Keyboard::Key key,bool release,int x,int y)56 void CGameOver::Keyb(sf::Keyboard::Key key, bool release, int x, int y) {
57 	if (release) return;
58 	if (key == sf::Keyboard::Enter || key == sf::Keyboard::Escape) QuitGameOver();
59 }
60 
Mouse(int button,int state,int x,int y)61 void CGameOver::Mouse(int button, int state, int x, int y) {
62 	QuitGameOver();
63 }
64 
65 
GameOverMessage(const CControl * ctrl)66 void GameOverMessage(const CControl *ctrl) {
67 	int fwidth = 500;
68 
69 	int leftframe = (Winsys.resolution.width - fwidth) / 2;
70 	int topframe = 80;
71 
72 	const sf::Color& backcol = colWhite;
73 	static const sf::Color framecol(178, 178, 255);
74 
75 	if (param.use_papercut_font > 0) FT.SetSize(28);
76 	else FT.SetSize(22);
77 	if (g_game.raceaborted) {
78 		DrawFrameX(leftframe, topframe, fwidth, 100, 4, backcol, framecol, 0.5f);
79 		FT.SetColor(colDBlue);
80 		FT.DrawString(CENTER, topframe+30, Trans.Text(25));
81 	} else {
82 		int firstMarker = leftframe + 60;
83 		int secondMarker = leftframe + 310;
84 		DrawFrameX(leftframe, topframe, fwidth, 210, 4, backcol, framecol, 0.5f);
85 
86 		if (param.use_papercut_font > 0) FT.SetSize(20);
87 		else FT.SetSize(14);
88 		if (g_game.race_result >= 0 || g_game.game_type != CUPRACING) FT.SetColor(colDBlue);
89 		else FT.SetColor(colDRed);
90 
91 		sf::String line = Trans.Text(84) + ":  ";
92 		FT.DrawString(firstMarker, topframe + 15, line);
93 		line = Int_StrN(g_game.score);
94 		line += "  pts";
95 		FT.DrawString(secondMarker, topframe + 15, line);
96 
97 		line = Trans.Text(85) + ":  ";
98 		FT.DrawString(firstMarker, topframe + 40, line);
99 		line = Int_StrN(g_game.herring);
100 		if (g_game.game_type == CUPRACING) {
101 			line += "  (";
102 			line += Int_StrN(g_game.race->herrings.x);
103 			line += ')';
104 		}
105 		FT.DrawString(secondMarker, topframe + 40, line);
106 
107 		line = Trans.Text(86) + ":  ";
108 		FT.DrawString(firstMarker, topframe + 65, line);
109 		line = Float_StrN(g_game.time, 2);
110 		line += "  s";
111 		if (g_game.game_type == CUPRACING) {
112 			line += "  (";
113 			line += Float_StrN(g_game.race->time.x, 2);
114 			line += ')';
115 		}
116 		FT.DrawString(secondMarker, topframe + 65, line);
117 
118 		line = Trans.Text(87) + ":  ";
119 		FT.DrawString(firstMarker, topframe + 90, line);
120 		line = Float_StrN(ctrl->way, 2);
121 		line += "  m";
122 		FT.DrawString(secondMarker, topframe + 90, line);
123 
124 		line = Trans.Text(88) + ":  ";
125 		FT.DrawString(firstMarker, topframe + 115, line);
126 		line = Float_StrN(ctrl->way / g_game.time * 3.6, 2);
127 		line += "  km/h";
128 		FT.DrawString(secondMarker, topframe + 115, line);
129 
130 		if (param.use_papercut_font > 0) FT.SetSize(28);
131 		else FT.SetSize(22);
132 		if (g_game.game_type == CUPRACING) {
133 			FT.DrawString(CENTER, topframe + 150, Trans.Text(22 + g_game.race_result)); // Text IDs 21 - 24; race_results is in [-1; 2]
134 		} else {
135 			if (highscore_pos < MAX_SCORES) {
136 				line = Trans.Text(89) + ' ';
137 				line += Int_StrN(highscore_pos + 1);
138 				line += ' ' + Trans.Text(90);
139 				FT.DrawString(CENTER, topframe+150, line);
140 			}
141 		}
142 	}
143 }
144 
145 // =========================================================================
Enter()146 void CGameOver::Enter() {
147 	if (!g_game.raceaborted) highscore_pos = Score.CalcRaceResult();
148 
149 	if (g_game.game_type == CUPRACING) {
150 		if (g_game.race_result >= 0) {
151 			Music.PlayTheme(g_game.theme_id, MUS_WONRACE);
152 		} else {
153 			Music.PlayTheme(g_game.theme_id, MUS_LOSTRACE);
154 		}
155 	} else {
156 		if (g_game.raceaborted) {
157 			Music.PlayTheme(g_game.theme_id, MUS_LOSTRACE);
158 		} else {
159 			Music.PlayTheme(g_game.theme_id, MUS_WONRACE);
160 		}
161 	}
162 
163 
164 	if (g_game.raceaborted || !g_game.use_keyframe) {
165 		final_frame = nullptr;
166 	} else {
167 		if (g_game.game_type == CUPRACING) {
168 			if (g_game.race_result < 0)
169 				final_frame = g_game.character->GetKeyframe(LOSTRACE);
170 			else final_frame = g_game.character->GetKeyframe(WONRACE);
171 		} else final_frame = g_game.character->GetKeyframe(FINISH);
172 
173 		if (!g_game.raceaborted) {
174 			const CControl *ctrl = g_game.player->ctrl;
175 			final_frame->Init(ctrl->cpos, -0.18);
176 		}
177 	}
178 	SetStationaryCamera(true);
179 }
180 
181 
Loop(float time_step)182 void CGameOver::Loop(float time_step) {
183 	CControl *ctrl = g_game.player->ctrl;
184 	int width = Winsys.resolution.width;
185 	int height = Winsys.resolution.height;
186 
187 	ClearRenderContext();
188 	Env.SetupFog();
189 
190 	update_view(ctrl, 0);
191 
192 	if (final_frame != nullptr) final_frame->Update(time_step);
193 
194 	SetupViewFrustum(ctrl);
195 	Env.DrawSkybox(ctrl->viewpos);
196 	Env.DrawFog();
197 	Env.SetupLight();
198 
199 	RenderCourse();
200 	DrawTrackmarks();
201 	DrawTrees();
202 
203 	UpdateWind(time_step);
204 	UpdateSnow(time_step, ctrl);
205 	DrawSnow(ctrl);
206 
207 	g_game.character->shape->Draw();
208 
209 	{
210 		ScopedRenderMode rm(GUI);
211 		if (final_frame != nullptr) {
212 			if (!final_frame->active) GameOverMessage(ctrl);
213 		} else GameOverMessage(ctrl);
214 	}
215 	DrawHud(ctrl);
216 	Reshape(width, height);
217 	Winsys.SwapBuffers();
218 }
219