2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
19 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include <glib/gi18n.h>
28 #include "framework/titlescreenactivity.hpp"
29 #include "framework/app.hpp"
30 #include "misc/smartptr.hpp"
32 #include "misc/logger.hpp"
33 #include "misc/helptext.hpp"
34 #include "framework/replaymenuactivity.hpp"
35 #include "framework/commands.hpp"
36 #include "input/gameinputhandler.hpp"
37 #include "input/joystick.hpp"
38 #include "cave/caveset.hpp"
39 #include "cave/titleanimation.hpp"
40 #include "settings.hpp"
41 #include "gfx/screen.hpp"
42 #include "gfx/pixbuffactory.hpp"
43 #include "gfx/fontmanager.hpp"
44 #include "sound/sound.hpp"
47 TitleScreenActivity::TitleScreenActivity(App
*app
)
49 , PixmapStorage(*app
->screen
)
50 , scale(app
->screen
->get_pixmap_scale())
51 , image_centered_threshold(164 * scale
)
52 , frames(0), time_ms(0), animcycle(0)
54 caveset_has_levels
= app
->caveset
->has_levels();
55 cavenum
= app
->caveset
->last_selected_cave
;
56 levelnum
= app
->caveset
->last_selected_level
;
60 TitleScreenActivity::~TitleScreenActivity() {
65 void TitleScreenActivity::release_pixmaps() {
70 void TitleScreenActivity::render_animation() const {
71 if (animation
.empty()) {
72 animation
= get_title_animation_pixmap(app
->caveset
->title_screen
, app
->caveset
->title_screen_scroll
, false, *app
->screen
, app
->screen
->pixbuf_factory
);
73 /* this is required because the caveset might have changed since the last redraw, and
74 * thus the title screen might have changed, and the new title screen might have fewer
75 * frames than the original. */
81 void TitleScreenActivity::clear_animation() {
82 for (unsigned x
= 0; x
< animation
.size(); x
++)
88 void TitleScreenActivity::shown_event() {
89 int scale
= app
->screen
->get_pixmap_scale();
90 app
->screen
->set_size(scale
* 320, scale
* 200, gd_fullscreen
);
92 /* render title screen animation in memory pixmap */
95 /* height of title screen, then decide which lines to show and where */
96 image_h
= animation
[0]->get_height();
97 int font_h
= app
->font_manager
->get_font_height();
98 /* less than 2 lines left - place for only one line of text. */
99 if (app
->screen
->get_height() - image_h
< 2 * font_h
) {
101 y_caveline
= image_h
+ (app
->screen
->get_height() - image_h
- font_h
) / 2; /* centered in the small place */
103 } else if (app
->screen
->get_height() - image_h
< 3 * font_h
) {
104 /* more than 2, less than 3 - place for status bar. game name is not shown, as this will */
105 /* only be true for a game with its own title screen, and i decided that in that case it */
106 /* would make more sense. */
108 y_caveline
= image_h
+ (app
->screen
->get_height() - image_h
- font_h
* 2) / 2; /* centered there */
111 /* more than 3, less than 4 - place for everything. */
112 y_gameline
= image_h
+ (app
->screen
->get_height() - image_h
- font_h
- font_h
* 2) / 2; /* centered with cave name */
113 y_caveline
= y_gameline
+ font_h
;
114 /* if there is some place, move the cave line one pixel lower. */
115 if (y_caveline
+ 2 * font_h
< app
->screen
->get_height())
116 y_caveline
+= 1 * scale
;
120 app
->screen
->set_title(CPrintf("GDash - %s") % app
->caveset
->name
);
121 gd_music_play_random();
125 void TitleScreenActivity::hidden_event() {
130 void TitleScreenActivity::redraw_event(bool full
) const {
133 // If the screen was resized, the animation might have disappeared
136 if (y_gameline
!= -1) {
137 // TRANSLATORS: Game here is like caveset, the loaded game from which the user will select the cave to play
138 app
->blittext_n(0, y_gameline
, CPrintf("%c%s: %c%s %c%s") % GD_COLOR_INDEX_WHITE
% _("Game") % GD_COLOR_INDEX_YELLOW
% app
->caveset
->name
% GD_COLOR_INDEX_RED
% (app
->caveset
->edited
? "*" : ""));
141 int dx
= (app
->screen
->get_width() - animation
[animcycle
]->get_width()) / 2; /* centered horizontally */
143 if (animation
[animcycle
]->get_height() < image_centered_threshold
)
144 dy
= (image_centered_threshold
- animation
[animcycle
]->get_height()) / 2; /* centered vertically */
146 dy
= 0; /* top of screen, as not too much space was left for info lines */
147 app
->screen
->blit(*animation
[animcycle
], dx
, dy
);
150 if (get_active_logger().empty()) {
151 switch (which_status
) {
153 // TRANSLATORS: 40 chars max. Select the game to play.
154 app
->status_line(_("Crsr: select Space: play H: help"));
158 /* the gtk version has an editor */
159 // TRANSLATORS: 40 chars max.
160 app
->status_line(_("F: hall of fame E: editor R: replays"));
162 /* the non-gtk version has no editor */
163 // TRANSLATORS: 40 chars max.
164 app
->status_line(_("F: hall of fame R: replays"));
168 // TRANSLATORS: 40 chars max. Joy here is the joystick (that one can also select the cave)
169 app
->status_line(_("Joy: select Fire: play"));
173 app
->status_line(_("Crsr: select Space: play X: errors"));
177 if (app
->caveset
->caves
.size() == 0) {
178 app
->blittext_n(0, y_caveline
, CPrintf(_("%cNo caves.")) % GD_COLOR_INDEX_WHITE
);
180 // TRANSLATORS: Cave is the name of the cave to play
181 if (caveset_has_levels
) {
182 app
->blittext_n(0, y_caveline
, CPrintf(_("%cCave: %c%s%c/%c%d")) % GD_COLOR_INDEX_WHITE
% GD_COLOR_INDEX_YELLOW
% app
->caveset
->cave(cavenum
).name
% GD_COLOR_INDEX_WHITE
% GD_COLOR_INDEX_YELLOW
% (levelnum
+ 1));
184 app
->blittext_n(0, y_caveline
, CPrintf(_("%cCave: %c%s%c")) % GD_COLOR_INDEX_WHITE
% GD_COLOR_INDEX_YELLOW
% app
->caveset
->cave(cavenum
).name
);
188 app
->screen
->drawing_finished();
192 static int previous_selectable_cave(CaveSet
&caveset
, unsigned cavenum
) {
193 unsigned cn
= cavenum
;
196 if (gd_all_caves_selectable
|| caveset
.cave(cn
).selectable
)
200 /* if not found any suitable, return current */
205 static int next_selectable_cave(CaveSet
&caveset
, unsigned cavenum
) {
206 unsigned cn
= cavenum
;
207 while (cn
+ 1 < caveset
.caves
.size()) {
209 if (gd_all_caves_selectable
|| caveset
.cave(cn
).selectable
)
213 /* if not found any suitable, return current */
218 void TitleScreenActivity::timer_event(int ms_elapsed
) {
219 time_ms
+= ms_elapsed
;
222 animcycle
= (animcycle
+ 1) % animation
.size();
227 if (which_status
> 2 || (!Joystick::have_joystick() && which_status
== 2))
231 /* on every 5th timer event... */
232 if (frames
% 5 == 0) {
233 /* joystick or keyboard up */
234 if (caveset_has_levels
&& app
->gameinput
->up()) {
239 /* joystick or keyboard down */
240 if (caveset_has_levels
&& app
->gameinput
->down()) {
245 /* joystick or keyboard left */
246 if (app
->gameinput
->left())
247 cavenum
= previous_selectable_cave(*app
->caveset
, cavenum
);
248 /* joystick or keyboard right */
249 if (app
->gameinput
->right())
250 cavenum
= next_selectable_cave(*app
->caveset
, cavenum
);
252 /* for a fire event, maybe from the joystick, start the game immediately.
253 * when from the keyboard, we would ask the user name,
254 * but how would the user press the enter key? :) */
255 if (app
->gameinput
->fire1()) {
256 NewGameCommand
*command
= new NewGameCommand(app
, cavenum
, levelnum
);
257 command
->set_param1(gd_username
);
258 app
->enqueue_command(command
);
267 void TitleScreenActivity::keypress_event(KeyCode keycode
, int gfxlib_keycode
) {
271 app
->show_help(titlehelp
);
275 app
->show_about_info();
279 app
->enqueue_command(new ShowCaveInfoCommand(app
));
283 app
->enqueue_command(new SaveFileCommand(app
));
287 app
->enqueue_command(new SaveFileAsCommand(app
));
292 app
->enqueue_command(new SelectFileToLoadIfDiscardableCommand(app
, gd_last_folder
));
296 app
->enqueue_command(new SelectFileToLoadIfDiscardableCommand(app
, gd_system_caves_dir
));
306 app
->show_settings(gd_get_game_settings_array());
310 app
->show_settings(gd_get_keyboard_settings_array(app
->gameinput
));
314 app
->enqueue_command(new ShowHighScoreCommand(app
, NULL
, -1));
318 app
->enqueue_command(new ShowStatisticsCommand(app
));
322 app
->enqueue_command(new ShowErrorsCommand(app
, get_active_logger()));
326 app
->enqueue_command(new PushActivityCommand(app
, new ReplayMenuActivity(app
)));
330 app
->caveset
->last_selected_cave
= cavenum
;
331 app
->caveset
->last_selected_level
= levelnum
;
332 app
->input_text_and_do_command(_("Enter your name"), gd_username
.c_str(), new NewGameCommand(app
, cavenum
, levelnum
));
337 /* if edited, do as if a quit is requested. then the user will be asked if discards edit. */
338 /* otherwise, simply ask if he wants to quit. */
339 if (app
->caveset
->edited
)
342 // TRANSLATORS: Game means the application here.
343 app
->ask_yesorno_and_do_command(_("Quit game?"), _("yes"), _("no"), new PopAllActivitiesCommand(app
),
344 SmartPtr
<Command
>());