mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-19 14:49:07 +00:00
333 lines
8.4 KiB
C++
333 lines
8.4 KiB
C++
/* $Id$ */
|
|
/*
|
|
Copyright (C) 2003 by David White <davidnwhite@optusnet.com.au>
|
|
Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
|
|
See the COPYING file for more details.
|
|
*/
|
|
|
|
#include "global.hpp"
|
|
|
|
#include "events.hpp"
|
|
#include "font.hpp"
|
|
#include "game_config.hpp"
|
|
#include "image.hpp"
|
|
#include "intro.hpp"
|
|
#include "key.hpp"
|
|
#include "language.hpp"
|
|
#include "show_dialog.hpp"
|
|
#include "sound.hpp"
|
|
#include "util.hpp"
|
|
#include "video.hpp"
|
|
#include "widgets/button.hpp"
|
|
#include "game_events.hpp"
|
|
|
|
#include <cstdlib>
|
|
#include <sstream>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
const int min_room_at_bottom = 150;
|
|
}
|
|
|
|
bool show_intro_part(display& screen, const config& part,
|
|
const std::string& scenario);
|
|
|
|
void show_intro(display& screen, const config& data, const config& level)
|
|
{
|
|
std::cerr << "showing intro sequence...\n";
|
|
|
|
//stop the screen being resized while we're in this function
|
|
const events::resize_lock stop_resizing;
|
|
const events::event_context context;
|
|
|
|
bool showing = true;
|
|
|
|
const std::string& scenario = level["name"];
|
|
|
|
for(config::all_children_iterator i = data.ordered_begin();
|
|
i != data.ordered_end() && showing; i++) {
|
|
std::pair<const std::string*, const config*> item = *i;
|
|
|
|
if(*item.first == "part") {
|
|
showing = show_intro_part(screen, (*item.second), scenario);
|
|
} else if(*item.first == "if") {
|
|
const std::string type = game_events::conditional_passed(
|
|
NULL, *item.second) ? "then":"else";
|
|
const config* const thens = (*item.second).child(type);
|
|
if(thens == NULL) {
|
|
std::cerr << "no intro story this way...\n";
|
|
return;
|
|
}
|
|
const config& selection = *thens;
|
|
show_intro(screen, selection, level);
|
|
}
|
|
}
|
|
|
|
std::cerr << "intro sequence finished...\n";
|
|
}
|
|
|
|
bool show_intro_part(display& screen, const config& part,
|
|
const std::string& scenario)
|
|
{
|
|
std::cerr << "showing intro part\n";
|
|
|
|
const std::string& music_file = part["music"];
|
|
|
|
//play music if available
|
|
if(music_file != "") {
|
|
sound::play_music(music_file);
|
|
}
|
|
|
|
CKey key;
|
|
|
|
gui::button next_button(screen,_("Next") + std::string(">>>"));
|
|
gui::button skip_button(screen,_("Skip"));
|
|
|
|
gui::draw_solid_tinted_rectangle(0,0,screen.x()-1,screen.y()-1,
|
|
0,0,0,1.0,screen.video().getSurface());
|
|
|
|
|
|
const std::string& background_name = part["background"];
|
|
const bool show_title = (part["show_title"] == "yes");
|
|
|
|
surface background(NULL);
|
|
if(background_name.empty() == false) {
|
|
background.assign(image::get_image(background_name,image::UNSCALED));
|
|
}
|
|
|
|
int textx = 200;
|
|
int texty = 400;
|
|
|
|
SDL_Rect dstrect;
|
|
|
|
if(!background.null()) {
|
|
dstrect.x = screen.x()/2 - background->w/2;
|
|
dstrect.y = screen.y()/2 - background->h/2;
|
|
dstrect.w = background->w;
|
|
dstrect.h = background->h;
|
|
|
|
if(dstrect.y + dstrect.h > screen.y() - min_room_at_bottom) {
|
|
dstrect.y = maximum<int>(0,screen.y() - dstrect.h - min_room_at_bottom);
|
|
}
|
|
|
|
SDL_BlitSurface(background,NULL,screen.video().getSurface(),&dstrect);
|
|
|
|
#ifdef USE_TINY_GUI
|
|
textx = 10;
|
|
int xbuttons = screen.x() - 50;
|
|
#else
|
|
textx = dstrect.x;
|
|
int xbuttons = dstrect.x+dstrect.w-40;
|
|
#endif
|
|
texty = dstrect.y + dstrect.h + 10;
|
|
|
|
next_button.set_location(xbuttons,dstrect.y+dstrect.h+20);
|
|
skip_button.set_location(xbuttons,dstrect.y+dstrect.h+70);
|
|
} else {
|
|
next_button.set_location(screen.x()-200,screen.y()-150);
|
|
skip_button.set_location(screen.x()-200,screen.y()-100);
|
|
}
|
|
|
|
//draw title if needed
|
|
if(show_title) {
|
|
const SDL_Rect area = {0,0,screen.x(),screen.y()};
|
|
const SDL_Rect scenario_size =
|
|
font::draw_text(NULL,area,font::SIZE_XLARGE,font::NORMAL_COLOUR,scenario,0,0);
|
|
update_rect(font::draw_text(&screen,area,font::SIZE_XLARGE,font::NORMAL_COLOUR,scenario,
|
|
dstrect.x,dstrect.y - scenario_size.h - 4));
|
|
}
|
|
|
|
update_whole_screen();
|
|
screen.video().flip();
|
|
|
|
if(!background.null()) {
|
|
//draw images
|
|
const config::child_list& images = part.get_children("image");
|
|
|
|
bool pass = false;
|
|
|
|
for(std::vector<config*>::const_iterator i = images.begin(); i != images.end(); ++i){
|
|
const std::string& xloc = (**i)["x"];
|
|
const std::string& yloc = (**i)["y"];
|
|
const std::string& image_name = (**i)["file"];
|
|
const std::string& delay_str = (**i)["delay"];
|
|
const int delay = (delay_str == "") ? 0: atoi(delay_str.c_str());
|
|
const int x = atoi(xloc.c_str());
|
|
const int y = atoi(yloc.c_str());
|
|
|
|
if(x < 0 || x >= background->w || y < 0 || y >= background->h)
|
|
continue;
|
|
|
|
if(image_name == "") continue;
|
|
surface img(image::get_image(image_name,image::UNSCALED));
|
|
if(img.null()) continue;
|
|
|
|
if ((**i)["flip"] == "yes")
|
|
img.assign(image::reverse_image(img));
|
|
|
|
SDL_Rect image_rect;
|
|
image_rect.x = x + dstrect.x;
|
|
image_rect.y = y + dstrect.y;
|
|
image_rect.w = img->w;
|
|
image_rect.h = img->h;
|
|
|
|
SDL_BlitSurface(img,NULL,screen.video().getSurface(),&image_rect);
|
|
|
|
update_rect(image_rect);
|
|
|
|
if(pass == false) {
|
|
for(int i = 0; i != 50; ++i) {
|
|
if(key[SDLK_ESCAPE] || next_button.pressed() || skip_button.pressed()) {
|
|
std::cerr << "escape pressed..\n";
|
|
return false;
|
|
}
|
|
|
|
SDL_Delay(delay/50);
|
|
|
|
events::pump();
|
|
events::raise_process_event();
|
|
events::raise_draw_event();
|
|
|
|
int a, b;
|
|
const int mouse_flags = SDL_GetMouseState(&a,&b);
|
|
if(key[SDLK_RETURN] || key[SDLK_SPACE] || mouse_flags) {
|
|
std::cerr << "key pressed..\n";
|
|
pass = true;
|
|
continue;
|
|
}
|
|
|
|
screen.video().flip();
|
|
}
|
|
}
|
|
|
|
if(key[SDLK_ESCAPE] || next_button.pressed() || skip_button.pressed()) {
|
|
std::cerr << "escape pressed..\n";
|
|
pass = true;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
const std::string& story = part["story"];
|
|
const std::vector<std::string> story_chars = split_utf8_string(story);
|
|
|
|
std::cerr << story << std::endl;
|
|
|
|
std::vector<std::string>::const_iterator j = story_chars.begin();
|
|
|
|
bool skip = false, last_key = true;
|
|
|
|
int xpos = textx, ypos = texty;
|
|
|
|
//the maximum position that text can reach before wrapping
|
|
const int max_xpos = next_button.location().x - 10;
|
|
size_t height = 0;
|
|
//std::string buf;
|
|
|
|
for(;;) {
|
|
if(j != story_chars.end()) {
|
|
//unsigned char c = *j;
|
|
if(*j == " ") {
|
|
//we're at a space, so find the next space or end-of-text,
|
|
//to find out if the next word will fit, or if it has to be wrapped
|
|
std::vector<std::string>::const_iterator end_word = std::find(j+1,story_chars.end()," ");
|
|
|
|
std::string word;
|
|
for(std::vector<std::string>::const_iterator k = j+1;
|
|
k != end_word; ++k) {
|
|
word += *k;
|
|
}
|
|
const SDL_Rect rect = font::draw_text(NULL,screen.screen_area(),
|
|
font::SIZE_PLUS,font::NORMAL_COLOUR,
|
|
word, xpos, ypos, false);
|
|
|
|
if(xpos + rect.w >= max_xpos) {
|
|
xpos = textx;
|
|
ypos += height;
|
|
++j;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// output the character
|
|
const SDL_Rect rect = font::draw_text(&screen,
|
|
screen.screen_area(),font::SIZE_PLUS,
|
|
font::NORMAL_COLOUR,*j,xpos,ypos,
|
|
false);
|
|
|
|
if(rect.h > height)
|
|
height = rect.h;
|
|
xpos += rect.w;
|
|
update_rect(rect);
|
|
|
|
++j;
|
|
if(j == story_chars.end())
|
|
skip = true;
|
|
|
|
}
|
|
|
|
const bool keydown = key[SDLK_SPACE] || key[SDLK_RETURN];
|
|
|
|
if(keydown && !last_key || next_button.pressed()) {
|
|
if(skip == true || j == story_chars.end()) {
|
|
break;
|
|
} else {
|
|
skip = true;
|
|
}
|
|
}
|
|
|
|
last_key = keydown;
|
|
|
|
if(key[SDLK_ESCAPE] || skip_button.pressed())
|
|
return false;
|
|
|
|
events::pump();
|
|
events::raise_process_event();
|
|
events::raise_draw_event();
|
|
screen.video().flip();
|
|
|
|
if(!skip || j == story_chars.end())
|
|
SDL_Delay(20);
|
|
}
|
|
|
|
gui::draw_solid_tinted_rectangle(0,0,screen.x()-1,screen.y()-1,0,0,0,1.0,
|
|
screen.video().getSurface());
|
|
|
|
return true;
|
|
}
|
|
|
|
void the_end(display& screen)
|
|
{
|
|
SDL_Rect area = screen.screen_area();
|
|
SDL_FillRect(screen.video().getSurface(),&area,0);
|
|
|
|
update_whole_screen();
|
|
screen.video().flip();
|
|
|
|
const std::string text = _("The End");
|
|
const size_t font_size = font::SIZE_XLARGE;
|
|
|
|
area = font::text_area(text,font_size);
|
|
area.x = screen.screen_area().w/2 - area.w/2;
|
|
area.y = screen.screen_area().h/2 - area.h/2;
|
|
|
|
for(size_t n = 0; n < 255; n += 5) {
|
|
const SDL_Color col = {n,n,n,n};
|
|
font::draw_text(&screen,area,font_size,col,text,area.x,area.y);
|
|
update_rect(area);
|
|
screen.video().flip();
|
|
|
|
SDL_FillRect(screen.video().getSurface(),&area,0);
|
|
|
|
SDL_Delay(10);
|
|
}
|
|
|
|
SDL_Delay(4000);
|
|
}
|