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;
1233 else if(event.type == SDL_QUIT) /* window closing */
1239 if(le_world != NULL)
1241 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 &&
1242 event.motion.y > 0 && event.motion.y < screen->h)))
1244 le_mouse_pressed[LEFT] = false;
1245 le_mouse_pressed[RIGHT] = false;
1247 if(!Menu::current())
1249 /* Check for button events */
1250 le_test_level_bt->event(event);
1251 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1253 le_save_level_bt->event(event);
1254 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1255 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1256 le_exit_bt->event(event);
1257 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1259 Menu::set_current(leveleditor_menu);
1261 le_next_level_bt->event(event);
1262 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1264 if(le_level < le_level_subset->levels)
1266 le_goto_level(le_level+1);
1272 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1273 if(confirm_dialog(str))
1275 new_lev.init_defaults();
1276 new_lev.save(le_level_subset->name.c_str(),le_level+1);
1277 le_level_subset->levels = le_level;
1278 le_goto_level(le_level);
1282 le_previous_level_bt->event(event);
1283 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1286 le_goto_level(le_level -1);
1288 le_rubber_bt->event(event);
1289 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1292 if(!cur_objects.empty())
1294 le_object_select_bt->event(event);
1295 if(le_object_select_bt->get_state() == BUTTON_CLICKED)
1297 MouseCursor::set_current(mouse_select_object);
1300 le_object_properties_bt->event(event);
1301 if(le_object_properties_bt->get_state() == BUTTON_CLICKED)
1303 le_change_object_properties(selected_game_object);
1308 if(le_selection_mode == SQUARE)
1310 le_select_mode_one_bt->event(event);
1311 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1312 le_selection_mode = CURSOR;
1316 le_select_mode_two_bt->event(event);
1317 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1318 le_selection_mode = SQUARE;
1320 ButtonPanelMap::iterator it;
1321 le_tilegroup_bt->event(event);
1322 switch (le_tilegroup_bt->get_state())
1324 case BUTTON_CLICKED:
1325 Menu::set_current(select_tilegroup_menu);
1326 select_tilegroup_menu_effect.start(200);
1327 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1329 case BUTTON_WHEELUP:
1330 if(cur_tilegroup.empty())
1332 cur_tilegroup = tilegroups_map.begin()->first;
1336 it = tilegroups_map.find(cur_tilegroup);
1337 if((++it) == tilegroups_map.end())
1339 cur_tilegroup = tilegroups_map.begin()->first;
1343 cur_tilegroup = (*it).first;
1349 case BUTTON_WHEELDOWN:
1350 it = tilegroups_map.find(cur_tilegroup);
1351 if(it == tilegroups_map.begin())
1353 cur_tilegroup = tilegroups_map.rbegin()->first;
1357 if(--it != --tilegroups_map.begin())
1358 cur_tilegroup = (*it).first;
1360 cur_tilegroup = tilegroups_map.rbegin()->first;
1368 le_objects_bt->event(event);
1369 switch (le_objects_bt->get_state())
1371 case BUTTON_CLICKED:
1372 Menu::set_current(select_objects_menu);
1373 select_objects_menu_effect.start(200);
1374 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1376 case BUTTON_WHEELUP:
1377 it = objects_map.find(cur_objects);
1378 if(it == objects_map.end())
1380 cur_objects = objects_map.begin()->first;
1384 if(++it != objects_map.end())
1385 cur_objects = (*it).first;
1387 cur_objects = objects_map.begin()->first;
1391 case BUTTON_WHEELDOWN:
1392 it = objects_map.find(cur_objects);
1393 if(it == objects_map.begin())
1395 cur_objects = objects_map.rbegin()->first;
1399 if(--it != --objects_map.begin())
1400 cur_objects = (*it).first;
1402 cur_objects = objects_map.rbegin()->first;
1411 le_settings_bt->event(event);
1412 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1414 update_level_settings_menu();
1415 Menu::set_current(level_settings_menu);
1417 if(!cur_tilegroup.empty())
1419 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1421 if(pbutton->get_state() == BUTTON_CLICKED)
1423 le_current.Tile(pbutton->get_tag());
1427 else if(!cur_objects.empty())
1429 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1431 if(pbutton->get_state() == BUTTON_CLICKED)
1433 le_current.Object(pbutton->get_game_object());
1438 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1440 if(pbutton->get_state() == BUTTON_CLICKED)
1442 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1448 le_settings_bt->event(event);
1449 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1451 Menu::set_current(0);
1453 le_tilegroup_bt->event(event);
1454 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1456 Menu::set_current(0);
1458 le_objects_bt->event(event);
1459 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1461 Menu::set_current(0);
1466 if(!Menu::current() && !show_minimap)
1468 if(le_mouse_pressed[LEFT])
1470 if(MouseCursor::current() != mouse_select_object)
1472 if(le_current.IsTile())
1473 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1476 else if(le_mouse_clicked[LEFT])
1478 if(MouseCursor::current() == mouse_select_object)
1481 bool object_got_hit = false;
1482 base_type cursor_base;
1483 if(le_current.IsTile())
1485 cursor_base.x = cursor_x;
1486 cursor_base.y = cursor_y;
1488 else if(le_current.IsObject())
1490 cursor_base.x = cursor_x + pos_x;
1491 cursor_base.y = cursor_y + pos_x;
1493 cursor_base.width = 32;
1494 cursor_base.height = 32;
1496 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1497 if(rectcollision(cursor_base,(*it)->base))
1499 selected_game_object = (*it);
1500 object_got_hit = true;
1506 selected_game_object = NULL;
1507 le_object_properties_bt->set_active(false);
1510 le_object_properties_bt->set_active(true);
1512 MouseCursor::set_current(mouse_cursor);
1517 if(le_current.IsObject())
1519 le_level_changed = true;
1520 std::string type = le_current.obj->type();
1521 if(type == "BadGuy")
1523 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1525 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1526 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1531 le_mouse_clicked[LEFT] = false;
1537 if(!Menu::current())
1539 show_minimap = false;
1541 le_move_left_bt->event(event);
1542 le_move_right_bt->event(event);
1543 switch(le_move_left_bt->get_state())
1545 case BUTTON_PRESSED:
1547 show_minimap = true;
1551 show_minimap = true;
1553 case BUTTON_CLICKED:
1554 show_minimap = true;
1560 switch(le_move_right_bt->get_state())
1562 case BUTTON_PRESSED:
1564 show_minimap = true;
1568 show_minimap = true;
1570 case BUTTON_CLICKED:
1571 show_minimap = true;
1581 void le_highlight_selection()
1585 if(selection.x1 < selection.x2)
1595 if(selection.y1 < selection.y2)
1611 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1614 void le_change(float x, float y, int tm, unsigned int c)
1616 if(le_world != NULL)
1622 le_level_changed = true;
1624 switch(le_selection_mode)
1627 le_world->get_level()->change(x,y,tm,c);
1629 base_type cursor_base;
1632 cursor_base.width = 32;
1633 cursor_base.height = 32;
1635 /* if there is a bad guy over there, remove it */
1636 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1637 if(rectcollision(cursor_base,(*it)->base))
1640 le_world->bad_guys.erase(it);
1641 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1647 if(selection.x1 < selection.x2)
1657 if(selection.y1 < selection.y2)
1673 /* if there is a bad guy over there, remove it */
1674 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1675 it != le_world->bad_guys.end(); /* will be at end of loop */)
1677 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1678 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1681 it = le_world->bad_guys.erase(it);
1682 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1692 for(xx = x1; xx <= x2; xx++)
1693 for(yy = y1; yy <= y2; yy++)
1695 le_world->get_level()->change(xx*32, yy*32, tm, c);
1707 //Make sure a time value is set when testing the level
1708 if(le_world->get_level()->time_left == 0)
1709 le_world->get_level()->time_left = 250;
1711 le_world->get_level()->save("test", le_level);
1713 GameSession session("test",le_level, ST_GL_TEST);
1715 player_status.reset();
1717 music_manager->halt_music();
1719 Menu::set_current(NULL);
1720 World::set_current(le_world);
1725 bool tmp_show_grid = le_show_grid;
1726 int temp_le_selection_mode = le_selection_mode;
1727 le_selection_mode = NONE;
1728 show_selections = true;
1729 le_show_grid = false;
1730 le_help_shown = true;
1732 drawgradient(Color(0,0,0), Color(255,255,255));
1736 unsigned int i, done_;
1739 " - Supertux level editor tutorial - ",
1741 "To make your map, click the ",
1742 "tilegroup button and choose a ",
1744 "Pick a tile and simply hold down ",
1745 "the left mouse button over the map",
1746 "to \"paint\" your selection over",
1749 "There are three layers for painting",
1750 "tiles upon, Background layer,",
1751 "the Interactive layer, and the",
1752 "Foreground layer, which can be",
1753 "toggled by the BkGrd, IntAct and",
1754 "FrGrd buttons. The Foreground and",
1755 "Background layers do not effect",
1756 "Tux in the gameplay, but lie in",
1757 "front of him or lie behind him in",
1763 " - Supertux level editor tutorial - ",
1765 "The tiles placed on",
1766 "the Interactive layer are those",
1767 "which actually effect Tux in the",
1770 "Click the objects menu to put ",
1771 "bad guys and other objects in the",
1772 "game. Unlike placing tiles, you",
1773 "cannot \"paint\" enemies. Click",
1774 "them onto the screen one at a time.",
1776 "To change the settings of your",
1777 "level, click the button with the",
1778 "screwdriver and wrench. From here",
1779 "you can change the background,",
1780 "music, length of the level,",
1786 " - Supertux level editor tutorial - ",
1788 "You may have more than one level.",
1789 "Pressing the up and down buttons",
1790 "above the button bar lets you",
1791 "choose which one you are working on.",
1793 "If you would like to speed up your",
1794 "level editing, a useful trick is",
1795 "to learn the keyboard shortcuts.",
1796 "They are easy to learn, just right-",
1797 "click on the buttons.",
1799 "Have fun making levels! If you make",
1800 "some good ones, send them to us on",
1801 "the SuperTux mailing list!",
1807 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1809 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1810 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1812 gold_text->drawf("Press Anything to Continue - Page 1/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1820 done_ = wait_for_event(event);
1824 drawgradient(Color(0,0,0), Color(255,255,255));
1828 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1830 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1831 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1833 gold_text->drawf("Press Anything to Continue - Page 2/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1841 done_ = wait_for_event(event);
1845 drawgradient(Color(0,0,0), Color(255,255,255));
1849 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1851 for(i = 0; i < sizeof(text3)/sizeof(char *); i++)
1852 white_text->draw(text3[i], 5, 80+(i*white_text->h), 1);
1854 gold_text->drawf("Press Anything to Continue - Page 3/3", 0, 0, A_LEFT, A_BOTTOM, 1);
1862 done_ = wait_for_event(event);
1866 show_selections = true;
1867 le_show_grid = tmp_show_grid;
1868 le_selection_mode = temp_le_selection_mode;
1869 le_help_shown = false;