added basic map generator configuration
This commit is contained in:
parent
1ae8fc77f7
commit
8fa6c82b58
9 changed files with 270 additions and 64 deletions
|
@ -6,7 +6,7 @@ iterations=1000
|
|||
hill_size=10
|
||||
max_lakes=40
|
||||
villages=800
|
||||
players=6
|
||||
players=2
|
||||
min_lake_height=500
|
||||
lake_size=150
|
||||
river_frequency=20
|
||||
|
|
|
@ -322,6 +322,14 @@ display_type="Display:"
|
|||
full_screen="Full Screen"
|
||||
windowed="Windowed"
|
||||
|
||||
map_generator="Map Generator"
|
||||
regenerate_map="Regenerate"
|
||||
generator_settings="Settings..."
|
||||
|
||||
num_players="Players"
|
||||
map_width="Width"
|
||||
map_height="Height"
|
||||
|
||||
hotkeys_button="Hotkeys"
|
||||
action_quit="Quit Game"
|
||||
action_unitlist="Unit List"
|
||||
|
|
143
src/mapgen.cpp
143
src/mapgen.cpp
|
@ -9,10 +9,17 @@
|
|||
#include <ctime>
|
||||
#include <vector>
|
||||
|
||||
#include "events.hpp"
|
||||
#include "font.hpp"
|
||||
#include "language.hpp"
|
||||
#include "mapgen.hpp"
|
||||
#include "pathfind.hpp"
|
||||
#include "show_dialog.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include "widgets/button.hpp"
|
||||
#include "widgets/slider.hpp"
|
||||
|
||||
//function to generate a random map, from a string which describes
|
||||
//the generator to use and its arguments
|
||||
std::string random_generate_map(const std::string& parms)
|
||||
|
@ -685,9 +692,141 @@ default_map_generator::default_map_generator(const config& game_config)
|
|||
}
|
||||
}
|
||||
|
||||
bool default_map_generator::allow_user_config() const { return false; }
|
||||
bool default_map_generator::allow_user_config() const { return true; }
|
||||
|
||||
void default_map_generator::user_config(display& disp) {}
|
||||
void default_map_generator::user_config(display& disp)
|
||||
{
|
||||
const events::resize_lock prevent_resizing;
|
||||
const events::event_context dialog_events_context;
|
||||
|
||||
const int width = 600;
|
||||
const int height = 400;
|
||||
const int xpos = disp.x()/2 - width/2;
|
||||
const int ypos = disp.y()/2 - height/2;
|
||||
|
||||
SDL_Rect dialog_rect = {xpos-10,ypos-10,width+20,height+20};
|
||||
surface_restorer restorer(&disp.video(),dialog_rect);
|
||||
|
||||
gui::draw_dialog_frame(xpos,ypos,width,height,disp);
|
||||
|
||||
SDL_Rect title_rect = font::draw_text(NULL,disp.screen_area(),24,font::NORMAL_COLOUR,
|
||||
string_table["map_generator"],0,0);
|
||||
|
||||
gui::button close_button(disp,string_table["close_window"]);
|
||||
|
||||
close_button.set_x(xpos + width/2 - close_button.width()/2);
|
||||
close_button.set_y(ypos + height - close_button.height()-14);
|
||||
|
||||
const std::string& players_label = string_table["num_players"] + ":";
|
||||
const std::string& width_label = string_table["map_width"] + ":";
|
||||
const std::string& height_label = string_table["map_height"] + ":";
|
||||
|
||||
SDL_Rect players_rect = font::draw_text(NULL,disp.screen_area(),14,font::NORMAL_COLOUR,players_label,0,0);
|
||||
SDL_Rect width_rect = font::draw_text(NULL,disp.screen_area(),14,font::NORMAL_COLOUR,width_label,0,0);
|
||||
SDL_Rect height_rect = font::draw_text(NULL,disp.screen_area(),14,font::NORMAL_COLOUR,height_label,0,0);
|
||||
|
||||
const int horz_margin = 5;
|
||||
const int text_right = xpos + horz_margin + maximum<int>(maximum<int>(players_rect.w,width_rect.w),height_rect.w);
|
||||
|
||||
players_rect.x = text_right - players_rect.w;
|
||||
width_rect.x = text_right - width_rect.w;
|
||||
height_rect.x = text_right - height_rect.w;
|
||||
|
||||
const int vertical_margin = 20;
|
||||
players_rect.y = ypos + title_rect.h + vertical_margin*2;
|
||||
width_rect.y = players_rect.y + players_rect.h + vertical_margin;
|
||||
height_rect.y = width_rect.y + width_rect.h + vertical_margin;
|
||||
|
||||
const int max_players = 9;
|
||||
|
||||
const int right_space = 100;
|
||||
|
||||
const int slider_left = text_right + 10;
|
||||
const int slider_right = xpos + width - horz_margin - right_space;
|
||||
SDL_Rect slider_rect = { slider_left,players_rect.y,slider_right-slider_left,players_rect.h};
|
||||
gui::slider players_slider(disp,slider_rect,gui::slider::normalize(nplayers_,2,max_players));
|
||||
|
||||
const int min_width = 20;
|
||||
const int max_width = 80;
|
||||
const int min_height = 20;
|
||||
const int max_height = 80;
|
||||
|
||||
slider_rect.y = width_rect.y;
|
||||
gui::slider width_slider(disp,slider_rect,gui::slider::normalize(width_,min_height,max_height));
|
||||
|
||||
slider_rect.y = height_rect.y;
|
||||
gui::slider height_slider(disp,slider_rect,gui::slider::normalize(height_,min_width,max_width));
|
||||
|
||||
|
||||
for(bool draw = true;; draw = false) {
|
||||
int mousex, mousey;
|
||||
const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
|
||||
|
||||
const bool left_button = mouse_flags&SDL_BUTTON_LMASK;
|
||||
|
||||
if(close_button.process(mousex,mousey,left_button)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const double new_players = players_slider.process(mousex,mousey,left_button);
|
||||
if(new_players >= 0.0) {
|
||||
nplayers_ = gui::slider::denormalize(new_players,2,max_players);
|
||||
std::cerr << "set players to " << nplayers_ << "," << new_players << "\n";
|
||||
draw = true;
|
||||
}
|
||||
|
||||
const double new_width = width_slider.process(mousex,mousey,left_button);
|
||||
if(new_width >= 0.0) {
|
||||
width_ = gui::slider::denormalize(new_width,min_width,max_width);
|
||||
draw = true;
|
||||
}
|
||||
|
||||
const double new_height = height_slider.process(mousex,mousey,left_button);
|
||||
if(new_height >= 0.0) {
|
||||
height_ = gui::slider::denormalize(new_height,min_height,max_height);
|
||||
draw = true;
|
||||
}
|
||||
|
||||
if(draw) {
|
||||
|
||||
gui::draw_dialog_frame(xpos,ypos,width,height,disp);
|
||||
|
||||
title_rect = font::draw_text(&disp,disp.screen_area(),24,font::NORMAL_COLOUR,
|
||||
string_table["map_generator"],xpos+(width-title_rect.w)/2,ypos+10);
|
||||
|
||||
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,players_label,players_rect.x,players_rect.y);
|
||||
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,width_label,width_rect.x,width_rect.y);
|
||||
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,height_label,height_rect.x,height_rect.y);
|
||||
|
||||
std::stringstream players_str;
|
||||
players_str << nplayers_;
|
||||
|
||||
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,players_str.str(),
|
||||
slider_right+horz_margin,players_rect.y);
|
||||
|
||||
std::stringstream width_str;
|
||||
width_str << width_;
|
||||
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,width_str.str(),
|
||||
slider_right+horz_margin,width_rect.y);
|
||||
|
||||
std::stringstream height_str;
|
||||
height_str << height_;
|
||||
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,height_str.str(),
|
||||
slider_right+horz_margin,height_rect.y);
|
||||
|
||||
players_slider.draw();
|
||||
width_slider.draw();
|
||||
height_slider.draw();
|
||||
close_button.draw();
|
||||
|
||||
update_rect(xpos,ypos,width,height);
|
||||
}
|
||||
|
||||
disp.update_display();
|
||||
SDL_Delay(10);
|
||||
events::pump();
|
||||
}
|
||||
}
|
||||
|
||||
std::string default_map_generator::name() const { return "default"; }
|
||||
|
||||
|
|
|
@ -269,8 +269,8 @@ int play_multiplayer(display& disp, game_data& units_data, config cfg,
|
|||
state.gold = 100;
|
||||
|
||||
// Dialog width and height
|
||||
int width=600;
|
||||
int height=290;
|
||||
int width=640;
|
||||
int height=340;
|
||||
|
||||
int cur_selection = -1;
|
||||
int cur_villagegold = 1;
|
||||
|
@ -363,15 +363,26 @@ int play_multiplayer(display& disp, game_data& units_data, config cfg,
|
|||
launch_game.set_xy((disp.x()/2)-launch_game.width()*2-19,(disp.y()-height)/2+height-29);
|
||||
cancel_game.set_xy((disp.x()/2)+cancel_game.width()+19,(disp.y()-height)/2+height-29);
|
||||
|
||||
gui::button regenerate_map(disp,string_table["regenerate_map"]);
|
||||
regenerate_map.set_xy(rect.x+6,rect.y+30+(3*fog_game.height())+6);
|
||||
regenerate_map.backup_background();
|
||||
|
||||
gui::button generator_settings(disp,string_table["generator_settings"]);
|
||||
generator_settings.set_xy(rect.x+6,rect.y+30+(4*fog_game.height())+8);
|
||||
generator_settings.backup_background();
|
||||
|
||||
//player amount number background
|
||||
rect.x = ((disp.x()-width)/2+10)+35;
|
||||
rect.y = (disp.y()-height)/2+235;
|
||||
rect.w = 145;
|
||||
rect.h = 25;
|
||||
SDL_Surface* playernum_bg=get_surface_portion(disp.video().getSurface(), rect);
|
||||
surface_restorer playernum_bg(&disp.video(),rect);
|
||||
|
||||
update_whole_screen();
|
||||
|
||||
//the current map generator
|
||||
map_generator* generator = NULL;
|
||||
|
||||
CKey key;
|
||||
config* level_ptr = NULL;
|
||||
for(;;) {
|
||||
|
@ -464,6 +475,9 @@ int play_multiplayer(display& disp, game_data& units_data, config cfg,
|
|||
update_rect(rect);
|
||||
}
|
||||
|
||||
//work out if we have to generate a new map
|
||||
bool map_changed = false;
|
||||
|
||||
//Villages can produce between 1 and 10 gold a turn
|
||||
//FIXME: Should never be a - number, but it is sometimes
|
||||
int check_villagegold=1+int(9*villagegold_slider.process(mousex,mousey,left_button));
|
||||
|
@ -483,68 +497,22 @@ int play_multiplayer(display& disp, game_data& units_data, config cfg,
|
|||
}
|
||||
|
||||
if(maps_menu.selection() != cur_selection) {
|
||||
map_changed = true;
|
||||
generator = NULL;
|
||||
|
||||
cur_selection = maps_menu.selection();
|
||||
if(size_t(maps_menu.selection()) != options.size()-1) {
|
||||
level_ptr = levels[maps_menu.selection()];
|
||||
|
||||
std::string map_data = (*level_ptr)["map_data"];
|
||||
std::string& map_data = (*level_ptr)["map_data"];
|
||||
if(map_data == "" && (*level_ptr)["map"] != "") {
|
||||
map_data = read_file("data/maps/" + (*level_ptr)["map"]);
|
||||
}
|
||||
|
||||
//if the map should be randomly generated
|
||||
if(map_data == "" && (*level_ptr)["map_generation"] != "") {
|
||||
map_data = random_generate_map((*level_ptr)["map_generation"]);
|
||||
|
||||
//record the map data of the map, so that when we send to
|
||||
//remote clients, they will use the given map, and won't try
|
||||
//to generate their own.
|
||||
(*level_ptr)["map_data"] = map_data;
|
||||
if((*level_ptr)["map_generation"] != "") {
|
||||
generator = get_map_generator((*level_ptr)["map_generation"]);
|
||||
}
|
||||
|
||||
gamemap map(cfg,map_data);
|
||||
|
||||
//if there are less sides in the configuration than there are starting
|
||||
//positions, then generate the additional sides
|
||||
const int map_positions = map.num_valid_starting_positions();
|
||||
std::cerr << "map_positions: " << map_positions << "\n";
|
||||
for(int pos = level_ptr->get_children("side").size(); pos < map_positions; ++pos) {
|
||||
std::cerr << "adding side...\n";
|
||||
config& side = level_ptr->add_child("side");
|
||||
side["enemy"] = "1";
|
||||
char buf[50];
|
||||
sprintf(buf,"%d",(pos+1));
|
||||
side["side"] = buf;
|
||||
side["team_name"] = buf;
|
||||
side["canrecruit"] = "1";
|
||||
side["controller"] = "human";
|
||||
}
|
||||
|
||||
const scoped_sdl_surface mini(image::getMinimap(145,145,map));
|
||||
|
||||
if(mini != NULL) {
|
||||
rect.x = ((disp.x()-width)/2+10)+35;
|
||||
rect.y = (disp.y()-height)/2+80;
|
||||
rect.w = 145;
|
||||
rect.h = 145;
|
||||
SDL_BlitSurface(mini, NULL, disp.video().getSurface(), &rect);
|
||||
update_rect(rect);
|
||||
}
|
||||
|
||||
//Display the number of players
|
||||
rect.x = ((disp.x()-width)/2+10)+35;
|
||||
rect.y = (disp.y()-height)/2+235;
|
||||
rect.w = 145;
|
||||
rect.h = 25;
|
||||
SDL_BlitSurface(playernum_bg, NULL, disp.video().getSurface(), &rect);
|
||||
config& level = *level_ptr;
|
||||
const int nsides = level.get_children("side").size();
|
||||
|
||||
std::stringstream players;
|
||||
players << "Players: " << nsides;
|
||||
font::draw_text(&disp,disp.screen_area(),12,font::GOOD_COLOUR,
|
||||
players.str(),rect.x+45,rect.y);
|
||||
update_rect(rect);
|
||||
}else{
|
||||
const scoped_sdl_surface disk(image::get_image("misc/disk.png",image::UNSCALED));
|
||||
|
||||
|
@ -561,13 +529,79 @@ int play_multiplayer(display& disp, game_data& units_data, config cfg,
|
|||
rect.y = (disp.y()-height)/2+235;
|
||||
rect.w = 145;
|
||||
rect.h = 25;
|
||||
SDL_BlitSurface(playernum_bg, NULL, disp.video().getSurface(), &rect);
|
||||
playernum_bg.restore();
|
||||
font::draw_text(&disp,disp.screen_area(),12,font::GOOD_COLOUR,
|
||||
" Load Map ",rect.x+45,rect.y);
|
||||
update_rect(rect);
|
||||
}
|
||||
}
|
||||
|
||||
if(generator != NULL && generator->allow_user_config() && generator_settings.process(mousex,mousey,left_button)) {
|
||||
generator->user_config(disp);
|
||||
}
|
||||
|
||||
if(generator != NULL && (map_changed || regenerate_map.process(mousex,mousey,left_button))) {
|
||||
//generate the random map
|
||||
(*level_ptr)["map_data"] = generator->create_map(std::vector<std::string>());
|
||||
map_changed = true;
|
||||
}
|
||||
|
||||
if(map_changed) {
|
||||
if(generator != NULL) {
|
||||
generator_settings.draw();
|
||||
regenerate_map.draw();
|
||||
} else {
|
||||
generator_settings.hide();
|
||||
regenerate_map.hide();
|
||||
}
|
||||
|
||||
const std::string& map_data = (*level_ptr)["map_data"];
|
||||
|
||||
gamemap map(cfg,map_data);
|
||||
|
||||
//if there are less sides in the configuration than there are starting
|
||||
//positions, then generate the additional sides
|
||||
const int map_positions = map.num_valid_starting_positions();
|
||||
std::cerr << "map_positions: " << map_positions << "\n";
|
||||
for(int pos = level_ptr->get_children("side").size(); pos < map_positions; ++pos) {
|
||||
std::cerr << "adding side...\n";
|
||||
config& side = level_ptr->add_child("side");
|
||||
side["enemy"] = "1";
|
||||
char buf[50];
|
||||
sprintf(buf,"%d",(pos+1));
|
||||
side["side"] = buf;
|
||||
side["team_name"] = buf;
|
||||
side["canrecruit"] = "1";
|
||||
side["controller"] = "human";
|
||||
}
|
||||
|
||||
const scoped_sdl_surface mini(image::getMinimap(145,145,map));
|
||||
|
||||
if(mini != NULL) {
|
||||
rect.x = ((disp.x()-width)/2+10)+35;
|
||||
rect.y = (disp.y()-height)/2+80;
|
||||
rect.w = 145;
|
||||
rect.h = 145;
|
||||
SDL_BlitSurface(mini, NULL, disp.video().getSurface(), &rect);
|
||||
update_rect(rect);
|
||||
}
|
||||
|
||||
//Display the number of players
|
||||
rect.x = ((disp.x()-width)/2+10)+35;
|
||||
rect.y = (disp.y()-height)/2+235;
|
||||
rect.w = 145;
|
||||
rect.h = 25;
|
||||
playernum_bg.restore();
|
||||
config& level = *level_ptr;
|
||||
const int nsides = level.get_children("side").size();
|
||||
|
||||
std::stringstream players;
|
||||
players << "Players: " << nsides;
|
||||
font::draw_text(&disp,disp.screen_area(),12,font::GOOD_COLOUR,
|
||||
players.str(),rect.x+45,rect.y);
|
||||
update_rect(rect);
|
||||
}
|
||||
|
||||
events::pump();
|
||||
disp.video().flip();
|
||||
SDL_Delay(20);
|
||||
|
|
|
@ -373,10 +373,10 @@ void show_preferences_dialog(display& disp)
|
|||
|
||||
log_scope("show_preferences_dialog");
|
||||
|
||||
const int xpos = disp.x()/2 - 300;
|
||||
const int ypos = disp.y()/2 - 200;
|
||||
const int width = 600;
|
||||
const int height = 400;
|
||||
const int xpos = disp.x()/2 - width/2;
|
||||
const int ypos = disp.y()/2 - height/2;
|
||||
|
||||
//make sure that the frame buffer is restored to its original state
|
||||
//when the dialog closes. Not const, because we might want to cancel
|
||||
|
|
|
@ -100,12 +100,22 @@ bool button::checked() const
|
|||
return state_ == PRESSED || state_ == PRESSED_ACTIVE;
|
||||
}
|
||||
|
||||
void button::backup_background()
|
||||
{
|
||||
const SDL_Rect area = {x_,y_,w_,h_};
|
||||
restorer_ = surface_restorer(&display_->video(),area);
|
||||
}
|
||||
|
||||
void button::hide()
|
||||
{
|
||||
restorer_.restore();
|
||||
}
|
||||
|
||||
void button::draw()
|
||||
{
|
||||
if(type_ == TYPE_CHECK) {
|
||||
restorer_.restore();
|
||||
const SDL_Rect area = {x_,y_,w_,h_};
|
||||
restorer_ = surface_restorer(&display_->video(),area);
|
||||
hide();
|
||||
backup_background();
|
||||
}
|
||||
|
||||
SDL_Surface* image = image_;
|
||||
|
|
|
@ -50,6 +50,9 @@ public:
|
|||
|
||||
bool process(int mousex, int mousey, bool button);
|
||||
|
||||
void backup_background();
|
||||
void hide();
|
||||
|
||||
private:
|
||||
surface_restorer restorer_;
|
||||
std::string label_;
|
||||
|
|
|
@ -66,6 +66,16 @@ int slider::height(display& disp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
double slider::normalize(int value, int min_value, int max_value)
|
||||
{
|
||||
return (double(value) - double(min_value))/double(max_value - min_value);
|
||||
}
|
||||
|
||||
int slider::denormalize(double value, int min_value, int max_value)
|
||||
{
|
||||
return min_value + int(value*double(max_value - min_value));
|
||||
}
|
||||
|
||||
void slider::draw()
|
||||
{
|
||||
drawn_ = true;
|
||||
|
|
|
@ -42,6 +42,8 @@ public:
|
|||
slider& operator=(const slider& o);
|
||||
|
||||
static int height(display& disp);
|
||||
static double normalize(int value, int min_value, int max_value);
|
||||
static int denormalize(double value, int min_value, int max_value);
|
||||
|
||||
void draw();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue