4 // Copyright (C) 2003 Ricardo Cruz <rick2@aeiou.pt>
5 // Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
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.
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.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <SDL_image.h>
30 #include "leveleditor.h"
43 #include "resources.h"
44 #include "music_manager.h"
46 /* definitions to aid development */
48 /* definitions that affect gameplay */
49 #define KEY_CURSOR_SPEED 32
50 #define KEY_CURSOR_FASTSPEED 64
52 /* when pagedown/up pressed speed:*/
53 #define PAGE_CURSOR_SPEED 13*32
55 #define MOUSE_LEFT_MARGIN 80
56 #define MOUSE_RIGHT_MARGIN (560-32)
57 /* right_margin should noticed that the cursor is 32 pixels,
58 so it should subtract that value */
59 #define MOUSE_POS_SPEED 20
62 #define SELECT_W 2 // size of the selections lines
63 #define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A)
65 /* own declerations */
66 /* crutial ones (main loop) */
69 int le_load_level_subset(char *filename);
71 void le_drawinterface();
72 void le_checkevents();
73 void le_change(float x, float y, int tm, unsigned int c);
76 void le_set_defaults(void);
77 void le_activate_bad_guys(void);
78 void le_goto_level(int levelnb);
79 void le_highlight_selection();
81 void apply_level_settings_menu();
82 void update_subset_settings_menu();
83 void save_subset_settings_menu();
87 TileOrObject() : tile(0), obj(NULL) { is_tile = true; };
89 void Tile(unsigned int set_to) { tile = set_to; is_tile = true; }
90 void Object(GameObject* pobj) { obj = pobj; is_tile = false; }
91 //Returns true for a tile
92 bool IsTile() { return is_tile; };
93 //Returns true for a GameObject
94 bool IsObject() { return !is_tile; };
97 void Init() { tile = 0; obj = NULL; is_tile = true; };
99 bool is_tile; //true for tile (false for object)
104 /* leveleditor internals */
105 static string_list_type level_subsets;
106 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
107 static bool show_minimap;
108 static bool show_selections;
109 static bool le_help_shown;
110 static int pos_x, cursor_x, cursor_y, fire;
112 static World* le_world;
113 static LevelSubset* le_level_subset;
114 static int le_show_grid;
116 static Surface* le_selection;
118 static TileOrObject le_current;
119 static bool le_mouse_pressed[2];
120 static bool le_mouse_clicked[2];
121 static Button* le_save_level_bt;
122 static Button* le_exit_bt;
123 static Button* le_test_level_bt;
124 static Button* le_next_level_bt;
125 static Button* le_previous_level_bt;
126 static Button* le_move_right_bt;
127 static Button* le_move_left_bt;
128 static Button* le_rubber_bt;
129 static Button* le_select_mode_one_bt;
130 static Button* le_select_mode_two_bt;
131 static Button* le_settings_bt;
132 static Button* le_tilegroup_bt;
133 static Button* le_objects_bt;
134 static Button* le_object_select_bt;
135 static Button* le_object_properties_bt;
136 static ButtonPanel* le_tilemap_panel;
137 static Menu* leveleditor_menu;
138 static Menu* subset_load_menu;
139 static Menu* subset_new_menu;
140 static Menu* subset_settings_menu;
141 static Menu* level_settings_menu;
142 static Menu* select_tilegroup_menu;
143 static Menu* select_objects_menu;
144 static Timer select_tilegroup_menu_effect;
145 static Timer select_objects_menu_effect;
146 static Timer display_level_info;
147 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
148 static ButtonPanelMap tilegroups_map;
149 static ButtonPanelMap objects_map;
150 static std::string cur_tilegroup;
151 static std::string cur_objects;
152 static MouseCursor* mouse_select_object;
153 static GameObject* selected_game_object;
155 static square selection;
156 static int le_selection_mode;
157 static SDL_Event event;
158 TileMapType active_tm;
160 int leveleditor(char* filename)
162 int last_time, now_time, i;
171 clearscreen(0, 0, 0);
174 music_manager->halt_music();
176 while (SDL_PollEvent(&event))
180 if(le_load_level_subset(filename))
185 last_time = SDL_GetTicks();
190 if(Menu::current() == select_tilegroup_menu)
192 if(select_tilegroup_menu_effect.check())
194 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
198 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
200 else if(Menu::current() == select_objects_menu)
202 if(select_objects_menu_effect.check())
204 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
207 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
212 /* making events results to be in order */
215 if(pos_x > (le_world->get_level()->width * 32) - screen->w)
216 pos_x = (le_world->get_level()->width * 32) - screen->w;
222 clearscreen(0, 0, 0);
224 /* draw editor interface */
227 Menu* menu = Menu::current();
233 if(menu == leveleditor_menu)
235 switch (leveleditor_menu->check())
237 case MNID_RETURNLEVELEDITOR:
239 Menu::set_current(0);
241 Menu::set_current(leveleditor_menu);
243 case MNID_SUBSETSETTINGS:
244 update_subset_settings_menu();
246 case MNID_QUITLEVELEDITOR:
251 else if(menu == level_settings_menu)
253 switch (level_settings_menu->check())
256 apply_level_settings_menu();
257 Menu::set_current(NULL);
264 else if(menu == select_tilegroup_menu)
267 switch (it = select_tilegroup_menu->check())
272 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
273 Menu::set_current(0);
280 else if(menu == select_objects_menu)
283 switch (it = select_objects_menu->check())
288 cur_objects = select_objects_menu->get_item_by_id(it).text;
291 Menu::set_current(0);
296 else if(menu == subset_load_menu)
298 switch (i = subset_load_menu->check())
305 if(le_load_level_subset(level_subsets.item[i-1]))
311 else if(menu == subset_new_menu)
313 if(subset_new_menu->item[2].input[0] == '\0')
314 subset_new_menu->item[3].kind = MN_DEACTIVE;
317 subset_new_menu->item[3].kind = MN_ACTION;
319 switch (i = subset_new_menu->check())
321 case MNID_CREATESUBSET:
322 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
323 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
324 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
326 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
328 Menu::set_current(subset_settings_menu);
333 else if(menu == subset_settings_menu)
335 if(le_level_subset->title.compare(subset_settings_menu->get_item_by_id(MNID_SUBSETTITLE).input) == 0 && le_level_subset->description.compare(subset_settings_menu->get_item_by_id(MNID_SUBSETDESCRIPTION).input) == 0 )
336 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
338 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
340 switch (i = subset_settings_menu->check())
342 case MNID_SUBSETSAVECHANGES:
343 save_subset_settings_menu();
344 Menu::set_current(leveleditor_menu);
350 MouseCursor::current()->draw();
358 ++global_frame_counter;
361 now_time = SDL_GetTicks();
362 if (now_time < last_time + FPS)
363 SDL_Delay(last_time + FPS - now_time); /* delay some time */
371 int le_load_level_subset(char *filename)
373 le_level_subset->load(filename);
374 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
378 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
380 Menu::set_current(NULL);
389 leveleditor_menu = new Menu();
390 subset_load_menu = new Menu();
391 subset_new_menu = new Menu();
392 subset_settings_menu = new Menu();
393 level_settings_menu = new Menu();
394 select_tilegroup_menu = new Menu();
395 select_objects_menu = new Menu();
397 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
398 leveleditor_menu->additem(MN_HL,"",0,0);
399 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
400 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
401 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
402 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
403 leveleditor_menu->additem(MN_HL,"",0,0);
404 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
406 Menu::set_current(leveleditor_menu);
408 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
409 subset_load_menu->additem(MN_HL, "", 0, 0);
411 for(i = 0; i < level_subsets.num_items; ++i)
413 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
415 subset_load_menu->additem(MN_HL,"",0,0);
416 subset_load_menu->additem(MN_BACK,"Back",0,0);
418 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
419 subset_new_menu->additem(MN_HL,"",0,0);
420 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
421 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
422 subset_new_menu->additem(MN_HL,"",0,0);
423 subset_new_menu->additem(MN_BACK,"Back",0,0);
425 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
426 subset_settings_menu->additem(MN_HL,"",0,0);
427 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
428 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
429 subset_settings_menu->additem(MN_HL,"",0,0);
430 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
431 subset_settings_menu->additem(MN_HL,"",0,0);
432 subset_settings_menu->additem(MN_BACK,"Back",0,0);
434 level_settings_menu->arrange_left = true;
435 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
436 level_settings_menu->additem(MN_HL,"",0,0);
437 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
438 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
439 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
440 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
441 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
442 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
443 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
444 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
445 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
446 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
447 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
448 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
449 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
450 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
451 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue ",0,0,MNID_BottomBlue);
452 level_settings_menu->additem(MN_HL,"",0,0);
453 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
455 select_tilegroup_menu->arrange_left = true;
456 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
457 select_tilegroup_menu->additem(MN_HL,"",0,0);
458 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
460 for(std::set<TileGroup>::iterator it = tilegroups->begin();
461 it != tilegroups->end(); ++it )
463 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
465 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
468 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
469 sit != (*it).tiles.end(); ++sit, ++i)
471 std::string imagefile = "/images/tilesets/" ;
472 bool only_editor_image = false;
473 if(!TileManager::instance()->get(*sit)->filenames.empty())
475 imagefile += TileManager::instance()->get(*sit)->filenames[0];
477 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
479 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
480 only_editor_image = true;
484 imagefile += "notile.png";
486 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
488 if(!only_editor_image)
489 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
491 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
492 button->add_icon(imagefile,32,32);
494 tilegroups_map[it->name]->additem(button, *sit);
497 select_tilegroup_menu->additem(MN_HL,"",0,0);
499 select_objects_menu->arrange_left = true;
500 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
501 select_objects_menu->additem(MN_HL,"",0,0);
502 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
503 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
505 for(int i = 0; i < NUM_BadGuyKinds; ++i)
507 BadGuy bad_tmp(0,0,BadGuyKind(i),false);
508 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
509 objects_map["BadGuys"]->manipulate_button(i)->set_game_object(new BadGuy(objects_map["BadGuys"]->manipulate_button(i)->get_pos().x,objects_map["BadGuys"]->manipulate_button(i)->get_pos().y,BadGuyKind(i),false));
512 select_objects_menu->additem(MN_HL,"",0,0);
520 level_subsets = dsubdirs("/levels", "level1.stl");
521 le_level_subset = new LevelSubset;
524 selected_game_object = NULL;
528 show_selections = true;
533 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
534 le_level_changed = false;
535 le_help_shown = false;
537 le_mouse_pressed[LEFT] = false;
538 le_mouse_pressed[RIGHT] = false;
540 le_mouse_clicked[LEFT] = false;
541 le_mouse_clicked[RIGHT] = false;
543 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
545 select_tilegroup_menu_effect.init(false);
546 select_objects_menu_effect.init(false);
547 display_level_info.init(false);
550 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
551 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F10,screen->w-32,32);
552 le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
553 le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
554 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
555 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
556 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
557 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
558 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
559 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
560 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
561 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
562 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F8,screen->w-64,80);
563 le_object_select_bt = new Button("/images/icons/select-one.png","Select an Object", SDLK_s, screen->w - 64, screen->h-98);
564 le_object_properties_bt = new Button("/images/icons/properties.png","Edit object properties", SDLK_p, screen->w - 32, screen->h-98);
565 le_object_properties_bt->set_active(false);
567 mouse_select_object = new MouseCursor(datadir + "/images/status/select-cursor.png",1);
568 mouse_select_object->set_mid(16,16);
570 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
571 le_tilemap_panel->set_button_size(32,10);
572 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
573 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
574 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
575 le_tilemap_panel->highlight_last(true);
576 le_tilemap_panel->set_last_clicked(TM_IA);
582 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
588 void update_level_settings_menu()
593 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
594 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
596 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
597 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
598 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
599 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
600 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
601 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
603 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
604 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
605 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
606 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
607 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
608 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
610 sprintf(str,"%d",le_world->get_level()->width);
611 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
612 sprintf(str,"%d",le_world->get_level()->time_left);
613 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
614 sprintf(str,"%2.0f",le_world->get_level()->gravity);
615 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
616 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
617 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
618 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
619 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
620 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
621 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
622 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
623 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
624 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
625 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
626 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
627 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
628 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
629 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
632 void update_subset_settings_menu()
634 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
635 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
638 void apply_level_settings_menu()
643 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
644 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
646 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
648 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
652 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
654 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
659 le_world->get_level()->load_gfx();
662 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
664 le_world->get_level()->change_size(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
665 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
666 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
667 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
668 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
669 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
670 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
671 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
672 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
673 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
676 void save_subset_settings_menu()
678 le_level_subset->title = subset_settings_menu->item[2].input;
679 le_level_subset->description = subset_settings_menu->item[3].input;
680 le_level_subset->save();
683 void le_unload_level()
690 sprintf(str,"Save changes to level %d of %s?",le_level,le_level_subset->name.c_str());
691 if(confirm_dialog(str))
693 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
698 le_level_changed = false;
701 void le_goto_level(int levelnb)
704 le_world = new World(le_level_subset->name, levelnb);
705 display_level_info.start(2500);
711 SDL_EnableKeyRepeat(0, 0); // disables key repeating
715 delete leveleditor_menu;
716 delete subset_load_menu;
717 delete subset_new_menu;
718 delete subset_settings_menu;
719 delete level_settings_menu;
720 delete select_tilegroup_menu;
721 delete select_objects_menu;
722 delete le_save_level_bt;
724 delete le_test_level_bt;
725 delete le_next_level_bt;
726 delete le_previous_level_bt;
727 delete le_move_right_bt;
728 delete le_move_left_bt;
730 delete le_select_mode_one_bt;
731 delete le_select_mode_two_bt;
732 delete le_settings_bt;
733 delete le_tilegroup_bt;
734 delete le_objects_bt;
735 delete le_tilemap_panel;
736 delete le_object_select_bt;
737 delete le_object_properties_bt;
738 delete mouse_select_object;
740 delete le_level_subset;
743 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
744 i != tilegroups_map.end(); ++i)
748 for(ButtonPanelMap::iterator i = objects_map.begin();
749 i != objects_map.end(); ++i)
755 void le_drawminimap()
761 if(screen->w - 64 > le_world->get_level()->width * 4)
763 else if(screen->w - 64 > le_world->get_level()->width * 2)
767 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
769 for (int y = 0; y < 15; ++y)
770 for (int x = 0; x < le_world->get_level()->width; ++x)
773 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
775 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
777 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
781 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, 15*4, 200, 200, 200, 128);
783 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
784 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, 15*4, 200, 200, 200, 200);
785 fillrect(left_offset + (pos_x/32)*mini_tile_width + 19*mini_tile_width - 2, 0, 2, 15*4, 200, 200, 200, 200);
786 fillrect(left_offset + (pos_x/32)*mini_tile_width, 15*4-2, 19*mini_tile_width, 2, 200, 200, 200, 200);
790 void le_drawinterface()
797 /* draw a grid (if selected) */
800 for(x = 0; x < 19; x++)
801 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
802 for(y = 0; y < 15; y++)
803 fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
807 if(show_minimap) // use_gl because the minimap isn't shown correctly in software mode. Any idea? FIXME Possible reasons: SDL_SoftStretch is a hack itsself || an alpha blitting issue SDL can't handle in software mode
810 if(show_selections && MouseCursor::current() != mouse_select_object)
812 if(le_selection_mode == CURSOR)
814 if(le_current.IsTile())
815 le_selection->draw( cursor_x - pos_x, cursor_y);
817 else if(le_selection_mode == SQUARE)
820 le_highlight_selection();
821 /* draw current selection */
822 w = selection.x2 - selection.x1;
823 h = selection.y2 - selection.y1;
824 fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
825 fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
826 fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
827 fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
832 /* draw button bar */
833 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
835 if(le_current.IsTile())
837 Tile::draw(19 * 32, 14 * 32, le_current.tile);
838 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
839 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
841 if(le_current.IsObject() && MouseCursor::current() != mouse_select_object)
843 le_current.obj->draw_on_screen(19 * 32, 14 * 32);
844 le_current.obj->draw_on_screen(cursor_x,cursor_y);
847 if(mouse_select_object && selected_game_object != NULL)
849 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y,selected_game_object->base.width,3,255,0,0,255);
850 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y,3,selected_game_object->base.height,255,0,0,255);
851 fillrect(selected_game_object->base.x-pos_x,selected_game_object->base.y+selected_game_object->base.height,selected_game_object->base.width,3,255,0,0,255);
852 fillrect(selected_game_object->base.x-pos_x+selected_game_object->base.width,selected_game_object->base.y,3,selected_game_object->base.height,255,0,0,255);
857 le_save_level_bt->draw();
859 le_test_level_bt->draw();
860 le_next_level_bt->draw();
861 le_previous_level_bt->draw();
862 le_rubber_bt->draw();
863 if(le_selection_mode == SQUARE)
864 le_select_mode_one_bt->draw();
865 else if(le_selection_mode == CURSOR)
866 le_select_mode_two_bt->draw();
867 le_settings_bt->draw();
868 le_move_right_bt->draw();
869 le_move_left_bt->draw();
870 le_tilegroup_bt->draw();
871 le_objects_bt->draw();
872 if(!cur_tilegroup.empty())
873 tilegroups_map[cur_tilegroup]->draw();
874 else if(!cur_objects.empty())
876 objects_map[cur_objects]->draw();
879 le_tilemap_panel->draw();
881 if(!cur_objects.empty())
883 le_object_select_bt->draw();
884 le_object_properties_bt->draw();
887 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
888 white_text->drawf(str, (le_level_subset->levels < 10) ? -10 : 0, 16, A_RIGHT, A_TOP, 0);
891 white_small_text->draw("F1 for Help", 10, 430, 1);
893 if(display_level_info.check())
894 white_text->drawf(le_world->get_level()->name.c_str(), 0, 0, A_HMIDDLE, A_TOP, 0);
899 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
901 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
911 /* Draw the real background */
912 if(le_world->get_level()->bkgd_image[0] != '\0')
914 s = (int)((float)pos_x * ((float)le_world->get_level()->bkgd_speed/100.0f)) % screen->w;
915 le_world->get_level()->img_bkgd->draw_part(s,0,0,0,
916 le_world->get_level()->img_bkgd->w - s - 32, le_world->get_level()->img_bkgd->h);
917 le_world->get_level()->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
918 le_world->get_level()->img_bkgd->h);
922 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
925 if(le_current.IsTile())
927 Tile::draw(cursor_x-pos_x, cursor_y,le_current.tile,128);
928 if(!TileManager::instance()->get(le_current.tile)->images.empty())
929 fillrect(cursor_x-pos_x,cursor_y,TileManager::instance()->get(le_current.tile)->images[0]->w,TileManager::instance()->get(le_current.tile)->images[0]->h,50,50,50,50);
931 if(le_current.IsObject())
933 le_current.obj->move_to(cursor_x, cursor_y);
936 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
938 for (y = 0; y < 15; ++y)
939 for (x = 0; x < 20; ++x)
942 if(active_tm == TM_BG)
947 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->bg_tiles[y][x + (int)(pos_x / 32)],a);
949 if(active_tm == TM_IA)
954 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)],a);
956 if(active_tm == TM_FG)
961 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->fg_tiles[y][x + (int)(pos_x / 32)],a);
963 /* draw whats inside stuff when cursor is selecting those */
964 /* (draw them all the time - is this the right behaviour?) */
965 Tile* edit_image = TileManager::instance()->get(le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)]);
966 if(edit_image && !edit_image->editor_images.empty())
967 edit_image->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
971 /* Draw the Bad guys: */
972 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
974 /* to support frames: img_bsod_left[(frame / 5) % 4] */
981 /* Draw the player: */
982 /* for now, the position is fixed at (100, 240) */
983 largetux.walk_right->draw( 100 - pos_x, 240);
986 void le_change_object_properties(GameObject *pobj)
988 Surface* cap_screen = Surface::CaptureScreen();
989 Menu* object_properties_menu = new Menu();
992 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
993 object_properties_menu->additem(MN_HL,"",0,0);
995 if(pobj->type() == "BadGuy")
997 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
998 object_properties_menu->additem(MN_STRINGSELECT,"Kind",0,0,1);
999 for(int i = 0; i < NUM_BadGuyKinds; ++i)
1001 string_list_add_item(object_properties_menu->get_item_by_id(1).list,badguykind_to_string(static_cast<BadGuyKind>(i)).c_str());
1003 object_properties_menu->get_item_by_id(1).list->active_item = i;
1005 object_properties_menu->additem(MN_TOGGLE,"StayOnPlatform",pbad->stay_on_platform,0,2);
1008 object_properties_menu->additem(MN_HL,"",0,0);
1009 object_properties_menu->additem(MN_ACTION,"Ok",0,0,3);
1011 Menu::set_current(object_properties_menu);
1017 while (SDL_PollEvent(&event))
1019 object_properties_menu->event(event);
1022 cap_screen->draw(0,0);
1024 object_properties_menu->draw();
1025 object_properties_menu->action();
1027 switch (object_properties_menu->check())
1030 if(pobj->type() == "BadGuy")
1032 BadGuy* pbad = dynamic_cast<BadGuy*>(pobj);
1033 pbad->kind = badguykind_from_string(string_list_active(object_properties_menu->get_item_by_id(1).list));
1034 pbad->stay_on_platform = object_properties_menu->get_item_by_id(2).toggled;
1036 std::list<BadGuy*>::iterator it;
1037 for(it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1040 le_world->get_level()->badguy_data[i].kind = pbad->kind;
1041 le_world->get_level()->badguy_data[i].stay_on_platform = pbad->stay_on_platform;
1043 (*it) = new BadGuy(le_world->get_level()->badguy_data[i].x,le_world->get_level()->badguy_data[i].y,le_world->get_level()->badguy_data[i].kind,le_world->get_level()->badguy_data[i].stay_on_platform);
1051 if(Menu::current() == NULL)
1054 mouse_cursor->draw();
1060 Menu::set_current(0);
1061 delete object_properties_menu;
1065 void le_checkevents()
1072 keymod = SDL_GetModState();
1074 while(SDL_PollEvent(&event))
1076 if (Menu::current())
1078 Menu::current()->event(event);
1079 if(!le_world && !Menu::current())
1080 Menu::set_current(leveleditor_menu);
1084 mouse_cursor->set_state(MC_NORMAL);
1086 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
1087 if(event.type == SDL_KEYDOWN
1088 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
1089 && (event.motion.x > 0
1090 && event.motion.x < screen->w - 64 &&
1091 event.motion.y > 0 && event.motion.y < screen->h)))
1095 case SDL_KEYDOWN: // key pressed
1096 key = event.key.keysym.sym;
1100 Menu::set_current(leveleditor_menu);
1104 cursor_x -= KEY_CURSOR_SPEED;
1106 cursor_x -= KEY_CURSOR_FASTSPEED;
1108 if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
1109 pos_x = cursor_x - MOUSE_LEFT_MARGIN;
1114 cursor_x += KEY_CURSOR_SPEED;
1116 cursor_x += KEY_CURSOR_FASTSPEED;
1118 if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
1119 pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
1124 cursor_y -= KEY_CURSOR_SPEED;
1126 cursor_y -= KEY_CURSOR_FASTSPEED;
1133 cursor_y += KEY_CURSOR_SPEED;
1135 cursor_y += KEY_CURSOR_FASTSPEED;
1137 if(cursor_y > screen->h-32)
1138 cursor_y = screen->h-32;
1144 if(le_world != NULL)
1152 cursor_x = (le_world->get_level()->width * 32) - 32;
1156 le_show_grid = !le_show_grid;
1162 case SDL_KEYUP: /* key released */
1163 switch(event.key.keysym.sym)
1172 case SDL_MOUSEBUTTONDOWN:
1173 if(event.button.button == SDL_BUTTON_LEFT)
1175 le_mouse_pressed[LEFT] = true;
1177 selection.x1 = event.motion.x + pos_x;
1178 selection.y1 = event.motion.y;
1179 selection.x2 = event.motion.x + pos_x;
1180 selection.y2 = event.motion.y;
1182 else if(event.button.button == SDL_BUTTON_RIGHT)
1184 le_mouse_pressed[RIGHT] = true;
1187 case SDL_MOUSEBUTTONUP:
1188 if(event.button.button == SDL_BUTTON_LEFT)
1190 le_mouse_pressed[LEFT] = false;
1191 le_mouse_clicked[LEFT] = true;
1193 else if(event.button.button == SDL_BUTTON_RIGHT)
1195 le_mouse_pressed[RIGHT] = false;
1196 le_mouse_clicked[RIGHT] = true;
1199 case SDL_MOUSEMOTION:
1201 if(!Menu::current())
1206 if(le_current.IsTile())
1208 cursor_x = ((int)(pos_x + x) / 32) * 32;
1209 cursor_y = ((int) y / 32) * 32;
1217 if(le_mouse_pressed[LEFT])
1219 selection.x2 = x + pos_x;
1223 if(le_mouse_pressed[RIGHT])
1225 pos_x += -1 * event.motion.xrel;
1229 case SDL_QUIT: // window closed
1238 if(le_world != NULL)
1240 if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > screen->w-64 && event.motion.x < screen->w &&
1241 event.motion.y > 0 && event.motion.y < screen->h)))
1243 le_mouse_pressed[LEFT] = false;
1244 le_mouse_pressed[RIGHT] = false;
1246 if(!Menu::current())
1248 /* Check for button events */
1249 le_test_level_bt->event(event);
1250 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1252 le_save_level_bt->event(event);
1253 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1254 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1255 le_exit_bt->event(event);
1256 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1258 Menu::set_current(leveleditor_menu);
1260 le_next_level_bt->event(event);
1261 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1263 if(le_level < le_level_subset->levels)
1265 le_goto_level(le_level+1);
1271 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1272 if(confirm_dialog(str))
1274 new_lev.init_defaults();
1275 new_lev.save(le_level_subset->name.c_str(),le_level+1);
1276 le_level_subset->levels = le_level;
1277 le_goto_level(le_level);
1281 le_previous_level_bt->event(event);
1282 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1285 le_goto_level(le_level -1);
1287 le_rubber_bt->event(event);
1288 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1291 if(!cur_objects.empty())
1293 le_object_select_bt->event(event);
1294 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1296 MouseCursor::set_current(mouse_select_object);
1299 le_object_properties_bt->event(event);
1300 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1302 le_change_object_properties(selected_game_object);
1307 if(le_selection_mode == SQUARE)
1309 le_select_mode_one_bt->event(event);
1310 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1311 le_selection_mode = CURSOR;
1315 le_select_mode_two_bt->event(event);
1316 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1317 le_selection_mode = SQUARE;
1319 ButtonPanelMap::iterator it;
1320 le_tilegroup_bt->event(event);
1321 switch (le_tilegroup_bt->get_state())
1323 case BUTTON_CLICKED:
1324 Menu::set_current(select_tilegroup_menu);
1325 select_tilegroup_menu_effect.start(200);
1326 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1328 case BUTTON_WHEELUP:
1329 if(cur_tilegroup.empty())
1331 cur_tilegroup = tilegroups_map.begin()->first;
1335 it = tilegroups_map.find(cur_tilegroup);
1336 if((++it) == tilegroups_map.end())
1338 cur_tilegroup = tilegroups_map.begin()->first;
1342 cur_tilegroup = (*it).first;
1348 case BUTTON_WHEELDOWN:
1349 it = tilegroups_map.find(cur_tilegroup);
1350 if(it == tilegroups_map.begin())
1352 cur_tilegroup = tilegroups_map.rbegin()->first;
1356 if(--it != --tilegroups_map.begin())
1357 cur_tilegroup = (*it).first;
1359 cur_tilegroup = tilegroups_map.rbegin()->first;
1367 le_objects_bt->event(event);
1368 switch (le_objects_bt->get_state())
1370 case BUTTON_CLICKED:
1371 Menu::set_current(select_objects_menu);
1372 select_objects_menu_effect.start(200);
1373 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1375 case BUTTON_WHEELUP:
1376 it = objects_map.find(cur_objects);
1377 if(it == objects_map.end())
1379 cur_objects = objects_map.begin()->first;
1383 if(++it != objects_map.end())
1384 cur_objects = (*it).first;
1386 cur_objects = objects_map.begin()->first;
1390 case BUTTON_WHEELDOWN:
1391 it = objects_map.find(cur_objects);
1392 if(it == objects_map.begin())
1394 cur_objects = objects_map.rbegin()->first;
1398 if(--it != --objects_map.begin())
1399 cur_objects = (*it).first;
1401 cur_objects = objects_map.rbegin()->first;
1410 le_settings_bt->event(event);
1411 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1413 update_level_settings_menu();
1414 Menu::set_current(level_settings_menu);
1416 if(!cur_tilegroup.empty())
1418 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1420 if(pbutton->get_state() == BUTTON_CLICKED)
1422 le_current.Tile(pbutton->get_tag());
1426 else if(!cur_objects.empty())
1428 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1430 if(pbutton->get_state() == BUTTON_CLICKED)
1432 le_current.Object(pbutton->get_game_object());
1437 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1439 if(pbutton->get_state() == BUTTON_CLICKED)
1441 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1447 le_settings_bt->event(event);
1448 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1450 Menu::set_current(0);
1452 le_tilegroup_bt->event(event);
1453 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1455 Menu::set_current(0);
1457 le_objects_bt->event(event);
1458 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1460 Menu::set_current(0);
1465 if(!Menu::current() && !show_minimap)
1467 if(le_mouse_pressed[LEFT])
1469 if(MouseCursor::current() != mouse_select_object)
1471 if(le_current.IsTile())
1472 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1475 else if(le_mouse_clicked[LEFT])
1477 if(MouseCursor::current() == mouse_select_object)
1480 bool object_got_hit = false;
1481 base_type cursor_base;
1482 if(le_current.IsTile())
1484 cursor_base.x = cursor_x;
1485 cursor_base.y = cursor_y;
1487 else if(le_current.IsObject())
1489 cursor_base.x = cursor_x + pos_x;
1490 cursor_base.y = cursor_y + pos_x;
1492 cursor_base.width = 32;
1493 cursor_base.height = 32;
1495 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1496 if(rectcollision(cursor_base,(*it)->base))
1498 selected_game_object = (*it);
1499 object_got_hit = true;
1505 selected_game_object = NULL;
1506 le_object_properties_bt->set_active(false);
1509 le_object_properties_bt->set_active(true);
1511 MouseCursor::set_current(mouse_cursor);
1516 if(le_current.IsObject())
1518 le_level_changed = true;
1519 std::string type = le_current.obj->type();
1520 if(type == "BadGuy")
1522 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1524 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1525 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1530 le_mouse_clicked[LEFT] = false;
1536 if(!Menu::current())
1538 show_minimap = false;
1540 le_move_left_bt->event(event);
1541 le_move_right_bt->event(event);
1542 switch(le_move_left_bt->get_state())
1544 case BUTTON_PRESSED:
1546 show_minimap = true;
1550 show_minimap = true;
1552 case BUTTON_CLICKED:
1553 show_minimap = true;
1559 switch(le_move_right_bt->get_state())
1561 case BUTTON_PRESSED:
1563 show_minimap = true;
1567 show_minimap = true;
1569 case BUTTON_CLICKED:
1570 show_minimap = true;
1580 void le_highlight_selection()
1584 if(selection.x1 < selection.x2)
1594 if(selection.y1 < selection.y2)
1610 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1613 void le_change(float x, float y, int tm, unsigned int c)
1615 if(le_world != NULL)
1621 le_level_changed = true;
1623 switch(le_selection_mode)
1626 le_world->get_level()->change(x,y,tm,c);
1628 base_type cursor_base;
1631 cursor_base.width = 32;
1632 cursor_base.height = 32;
1634 /* if there is a bad guy over there, remove it */
1635 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1636 if(rectcollision(cursor_base,(*it)->base))
1639 le_world->bad_guys.erase(it);
1640 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1646 if(selection.x1 < selection.x2)
1656 if(selection.y1 < selection.y2)
1672 /* if there is a bad guy over there, remove it */
1673 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1674 it != le_world->bad_guys.end(); /* will be at end of loop */)
1676 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1677 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1680 it = le_world->bad_guys.erase(it);
1681 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1691 for(xx = x1; xx <= x2; xx++)
1692 for(yy = y1; yy <= y2; yy++)
1694 le_world->get_level()->change(xx*32, yy*32, tm, c);
1706 //Make sure a time value is set when testing the level
1707 if(le_world->get_level()->time_left == 0)
1708 le_world->get_level()->time_left = 250;
1710 le_world->get_level()->save("test", le_level);
1712 GameSession session("test",le_level, ST_GL_TEST);
1714 player_status.reset();
1716 music_manager->halt_music();
1718 Menu::set_current(NULL);
1719 World::set_current(le_world);
1724 bool tmp_show_grid = le_show_grid;
1725 show_selections = true;
1726 le_show_grid = false;
1727 le_help_shown = true;
1729 drawgradient(Color(0,0,0), Color(255,255,255));
1733 unsigned int i, done_;
1736 " - Supertux level editor tutorial - ",
1738 "To make your map, click the ",
1739 "tilegroup button and choose a ",
1741 "Pick a tile and simply hold down ",
1742 "the left mouse button over the map",
1743 "to \"paint\" your selection over",
1746 "There are three layers for painting",
1747 "tiles upon, Background layer,",
1748 "the Interactive layer, and the",
1749 "Foreground layer, which can be",
1750 "toggled by the BkGrd, IntAct and",
1751 "FrGrd buttons. The Foreground and",
1752 "Background layers do not effect",
1753 "Tux in the gameplay, but lie in",
1754 "front of him or lie behind him in",
1760 " - Supertux level editor tutorial - ",
1762 "The tiles placed on",
1763 "the Interactive layer are those",
1764 "which actually effect Tux in the",
1767 "Click the objects menu to put ",
1768 "bad guys and other objects in the",
1769 "game. Unlike placing tiles, you",
1770 "cannot \"paint\" enemies. Click",
1771 "them onto the screen one at a time.",
1773 "To change the settings of your",
1774 "level, click the button with the",
1775 "screwdriver and wrench. From here",
1776 "you can change the background,",
1777 "music, length of the level,",
1783 " - Supertux level editor tutorial - ",
1785 "You may have more than one level.",
1786 "Pressing the up and down buttons",
1787 "above the button bar lets you",
1788 "choose which one you are working on.",
1790 "If you would like to speed up your",
1791 "level editing, a useful trick is",
1792 "to learn the keyboard shortcuts.",
1793 "They are easy to learn, just right-",
1794 "click on the buttons.",
1796 "Have fun making levels! If you make",
1797 "some good ones, send them to us on",
1798 "the SuperTux mailing list!",
1804 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1806 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1807 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1809 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1817 done_ = wait_for_event(event);
1821 drawgradient(Color(0,0,0), Color(255,255,255));
1825 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1827 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1828 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1830 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1838 done_ = wait_for_event(event);
1842 drawgradient(Color(0,0,0), Color(255,255,255));
1846 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1848 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1849 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1851 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1859 done_ = wait_for_event(event);
1863 show_selections = true;
1864 le_show_grid = tmp_show_grid;
1865 le_help_shown = false;