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(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);
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; };
95 void Init() { tile = 0; obj = NULL; is_tile = true; };
97 bool is_tile; //true for tile (false for object)
102 /* leveleditor internals */
103 static string_list_type level_subsets;
104 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
105 static bool show_minimap;
106 static int pos_x, cursor_x, cursor_y, fire;
108 static World* le_world;
109 static LevelSubset* le_level_subset;
110 static int le_show_grid;
112 static Surface* le_selection;
114 static TileOrObject le_current;
115 static bool le_mouse_pressed[2];
116 static bool le_mouse_clicked[2];
117 static Button* le_save_level_bt;
118 static Button* le_exit_bt;
119 static Button* le_test_level_bt;
120 static Button* le_next_level_bt;
121 static Button* le_previous_level_bt;
122 static Button* le_move_right_bt;
123 static Button* le_move_left_bt;
124 static Button* le_rubber_bt;
125 static Button* le_select_mode_one_bt;
126 static Button* le_select_mode_two_bt;
127 static Button* le_settings_bt;
128 static Button* le_tilegroup_bt;
129 static Button* le_objects_bt;
130 static ButtonPanel* le_tilemap_panel;
131 static Menu* leveleditor_menu;
132 static Menu* subset_load_menu;
133 static Menu* subset_new_menu;
134 static Menu* subset_settings_menu;
135 static Menu* level_settings_menu;
136 static Menu* select_tilegroup_menu;
137 static Menu* select_objects_menu;
138 static Timer select_tilegroup_menu_effect;
139 static Timer select_objects_menu_effect;
140 typedef std::map<std::string, ButtonPanel*> ButtonPanelMap;
141 static ButtonPanelMap tilegroups_map;
142 static ButtonPanelMap objects_map;
143 static std::string cur_tilegroup;
144 static std::string cur_objects;
146 static square selection;
147 static int le_selection_mode;
148 static SDL_Event event;
149 TileMapType active_tm;
151 int leveleditor(char* filename)
153 int last_time, now_time, i;
162 clearscreen(0, 0, 0);
165 music_manager->halt_music();
167 while (SDL_PollEvent(&event))
171 if(le_load_level(filename))
176 last_time = SDL_GetTicks();
181 if(Menu::current() == select_tilegroup_menu)
183 if(select_tilegroup_menu_effect.check())
185 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
189 select_tilegroup_menu->set_pos(screen->w - 64,66,-0.5,0.5);
191 else if(Menu::current() == select_objects_menu)
193 if(select_objects_menu_effect.check())
195 select_objects_menu->set_pos(screen->w - 64 + select_objects_menu_effect.get_left(),82,-0.5,0.5);
198 select_objects_menu->set_pos(screen->w - 64,82,-0.5,0.5);
203 /* making events results to be in order */
206 if(pos_x > (le_world->get_level()->width * 32) - screen->w)
207 pos_x = (le_world->get_level()->width * 32) - screen->w;
213 clearscreen(0, 0, 0);
215 /* draw editor interface */
218 Menu* menu = Menu::current();
224 if(menu == leveleditor_menu)
226 switch (leveleditor_menu->check())
228 case MNID_RETURNLEVELEDITOR:
230 Menu::set_current(0);
232 Menu::set_current(leveleditor_menu);
234 case MNID_SUBSETSETTINGS:
235 update_subset_settings_menu();
237 case MNID_QUITLEVELEDITOR:
242 else if(menu == level_settings_menu)
244 switch (level_settings_menu->check())
247 apply_level_settings_menu();
248 Menu::set_current(NULL);
255 else if(menu == select_tilegroup_menu)
258 switch (it = select_tilegroup_menu->check())
263 cur_tilegroup = select_tilegroup_menu->get_item_by_id(it).text;
264 Menu::set_current(0);
271 else if(menu == select_objects_menu)
274 switch (it = select_objects_menu->check())
279 cur_objects = select_objects_menu->get_item_by_id(it).text;
282 Menu::set_current(0);
287 else if(menu == subset_load_menu)
289 switch (i = subset_load_menu->check())
296 if(le_load_level(level_subsets.item[i-1]))
302 else if(menu == subset_new_menu)
304 if(subset_new_menu->item[2].input[0] == '\0')
305 subset_new_menu->item[3].kind = MN_DEACTIVE;
308 subset_new_menu->item[3].kind = MN_ACTION;
310 switch (i = subset_new_menu->check())
312 case MNID_CREATESUBSET:
313 LevelSubset::create(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
314 le_level_subset->load(subset_new_menu->get_item_by_id(MNID_SUBSETNAME).input);
315 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
317 le_world = new World(le_level_subset->name,1);
318 subset_new_menu->get_item_by_id(MNID_SUBSETNAME).change_input("");
320 Menu::set_current(subset_settings_menu);
325 else if(menu == subset_settings_menu)
327 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 )
328 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_DEACTIVE;
330 subset_settings_menu->get_item_by_id(MNID_SUBSETSAVECHANGES).kind = MN_ACTION;
332 switch (i = subset_settings_menu->check())
334 case MNID_SUBSETSAVECHANGES:
335 save_subset_settings_menu();
336 Menu::set_current(leveleditor_menu);
342 mouse_cursor->draw();
350 ++global_frame_counter;
353 now_time = SDL_GetTicks();
354 if (now_time < last_time + FPS)
355 SDL_Delay(last_time + FPS - now_time); /* delay some time */
363 int le_load_level(char *filename)
365 le_level_subset->load(filename);
366 leveleditor_menu->get_item_by_id(MNID_SUBSETSETTINGS).kind = MN_GOTO;
369 le_world = new World(filename,le_level);
371 //GameSession* session = new GameSession(datadir + "/levels/" + le_level_subset->name + "/level1.stl", 0, ST_GL_DEMO_GAME);
373 Menu::set_current(NULL);
382 leveleditor_menu = new Menu();
383 subset_load_menu = new Menu();
384 subset_new_menu = new Menu();
385 subset_settings_menu = new Menu();
386 level_settings_menu = new Menu();
387 select_tilegroup_menu = new Menu();
388 select_objects_menu = new Menu();
390 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
391 leveleditor_menu->additem(MN_HL,"",0,0);
392 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0,MNID_RETURNLEVELEDITOR);
393 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu,MNID_SUBSETSETTINGS);
394 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
395 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
396 leveleditor_menu->additem(MN_HL,"",0,0);
397 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0,MNID_QUITLEVELEDITOR);
399 Menu::set_current(leveleditor_menu);
401 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
402 subset_load_menu->additem(MN_HL, "", 0, 0);
404 for(i = 0; i < level_subsets.num_items; ++i)
406 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0, i+1);
408 subset_load_menu->additem(MN_HL,"",0,0);
409 subset_load_menu->additem(MN_BACK,"Back",0,0);
411 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
412 subset_new_menu->additem(MN_HL,"",0,0);
413 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0,MNID_SUBSETNAME);
414 subset_new_menu->additem(MN_ACTION,"Create",0,0, MNID_CREATESUBSET);
415 subset_new_menu->additem(MN_HL,"",0,0);
416 subset_new_menu->additem(MN_BACK,"Back",0,0);
418 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
419 subset_settings_menu->additem(MN_HL,"",0,0);
420 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
421 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
422 subset_settings_menu->additem(MN_HL,"",0,0);
423 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);
424 subset_settings_menu->additem(MN_HL,"",0,0);
425 subset_settings_menu->additem(MN_BACK,"Back",0,0);
427 level_settings_menu->arrange_left = true;
428 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
429 level_settings_menu->additem(MN_HL,"",0,0);
430 level_settings_menu->additem(MN_TEXTFIELD, "Name ",0,0,MNID_NAME);
431 level_settings_menu->additem(MN_TEXTFIELD, "Author ",0,0,MNID_AUTHOR);
432 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0,MNID_SONG);
433 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0,MNID_BGIMG);
434 level_settings_menu->additem(MN_STRINGSELECT,"Particle",0,0,MNID_PARTICLE);
435 level_settings_menu->additem(MN_NUMFIELD, "Length ",0,0,MNID_LENGTH);
436 level_settings_menu->additem(MN_NUMFIELD, "Time ",0,0,MNID_TIME);
437 level_settings_menu->additem(MN_NUMFIELD, "Gravity ",0,0,MNID_GRAVITY);
438 level_settings_menu->additem(MN_NUMFIELD, "Bg-Img-Speed",0,0,MNID_BGSPEED);
439 level_settings_menu->additem(MN_NUMFIELD, "Top Red ",0,0,MNID_TopRed);
440 level_settings_menu->additem(MN_NUMFIELD, "Top Green ",0,0,MNID_TopGreen);
441 level_settings_menu->additem(MN_NUMFIELD, "Top Blue ",0,0,MNID_TopBlue);
442 level_settings_menu->additem(MN_NUMFIELD, "Bottom Red ",0,0,MNID_BottomRed);
443 level_settings_menu->additem(MN_NUMFIELD, "Bottom Green",0,0,MNID_BottomGreen);
444 level_settings_menu->additem(MN_NUMFIELD, "Bottom Blue",0,0,MNID_BottomBlue);
445 level_settings_menu->additem(MN_HL,"",0,0);
446 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0,MNID_APPLY);
448 select_tilegroup_menu->arrange_left = true;
449 select_tilegroup_menu->additem(MN_LABEL,"Tilegroup",0,0);
450 select_tilegroup_menu->additem(MN_HL,"",0,0);
451 select_tilegroup_menu->additem(MN_ACTION,"asd",0,0);
452 std::set<TileGroup>* tilegroups = TileManager::tilegroups();
454 for(std::set<TileGroup>::iterator it = tilegroups->begin();
455 it != tilegroups->end(); ++it )
457 select_tilegroup_menu->additem(MN_ACTION, it->name, 0, 0, tileid);
459 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
462 for(std::vector<int>::const_iterator sit = (*it).tiles.begin();
463 sit != (*it).tiles.end(); ++sit, ++i)
465 std::string imagefile = "/images/tilesets/" ;
466 bool only_editor_image = false;
467 if(!TileManager::instance()->get(*sit)->filenames.empty())
469 imagefile += TileManager::instance()->get(*sit)->filenames[0];
471 else if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
473 imagefile += TileManager::instance()->get(*sit)->editor_filenames[0];
474 only_editor_image = true;
478 imagefile += "notile.png";
480 Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i),
482 if(!only_editor_image)
483 if(!TileManager::instance()->get(*sit)->editor_filenames.empty())
485 imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0];
486 button->add_icon(imagefile,32,32);
488 tilegroups_map[it->name]->additem(button, *sit);
491 select_tilegroup_menu->additem(MN_HL,"",0,0);
493 select_objects_menu->arrange_left = true;
494 select_objects_menu->additem(MN_LABEL,"Objects",0,0);
495 select_objects_menu->additem(MN_HL,"",0,0);
496 select_objects_menu->additem(MN_ACTION,"BadGuys",0,0,1);
497 objects_map["BadGuys"] = new ButtonPanel(screen->w - 64,96, 64, 318);
499 for(int i = 0; i < NUM_BadGuyKinds; ++i)
501 BadGuy bad_tmp(0,0,BadGuyKind(i),false);
502 objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i);
503 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));
506 select_objects_menu->additem(MN_HL,"",0,0);
514 level_subsets = dsubdirs("/levels", "info");
515 le_level_subset = new LevelSubset;
525 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
526 le_level_changed = false;
528 le_mouse_pressed[LEFT] = false;
529 le_mouse_pressed[RIGHT] = false;
531 le_mouse_clicked[LEFT] = false;
532 le_mouse_clicked[RIGHT] = false;
534 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
536 select_tilegroup_menu_effect.init(false);
537 select_objects_menu_effect.init(false);
540 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
541 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F6,screen->w-32,32);
542 le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
543 le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
544 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
545 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
546 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,48);
547 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
548 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
549 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
550 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
551 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,64);
552 le_objects_bt = new Button("/images/icons/objects.png","Select Objects", SDLK_F7,screen->w-64,80);
554 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
555 le_tilemap_panel->set_button_size(32,10);
556 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_b,0,0),TM_BG);
557 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_i,0,0),TM_IA);
558 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_f,0,0),TM_FG);
559 le_tilemap_panel->highlight_last(true);
565 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
571 void update_level_settings_menu()
576 level_settings_menu->get_item_by_id(MNID_NAME).change_input(le_world->get_level()->name.c_str());
577 level_settings_menu->get_item_by_id(MNID_AUTHOR).change_input(le_world->get_level()->author.c_str());
579 string_list_copy(level_settings_menu->get_item_by_id(MNID_SONG).list, dfiles("music/",NULL, "-fast"));
580 string_list_copy(level_settings_menu->get_item_by_id(MNID_BGIMG).list, dfiles("images/background",NULL, NULL));
581 string_list_add_item(level_settings_menu->get_item_by_id(MNID_BGIMG).list,"");
582 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"");
583 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"snow");
584 string_list_add_item(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,"clouds");
586 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_SONG).list,le_world->get_level()->song_title.c_str())) != -1)
587 level_settings_menu->get_item_by_id(MNID_SONG).list->active_item = i;
588 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_BGIMG).list,le_world->get_level()->bkgd_image.c_str())) != -1)
589 level_settings_menu->get_item_by_id(MNID_BGIMG).list->active_item = i;
590 if((i = string_list_find(level_settings_menu->get_item_by_id(MNID_PARTICLE).list,le_world->get_level()->particle_system.c_str())) != -1)
591 level_settings_menu->get_item_by_id(MNID_PARTICLE).list->active_item = i;
593 sprintf(str,"%d",le_world->get_level()->width);
594 level_settings_menu->get_item_by_id(MNID_LENGTH).change_input(str);
595 sprintf(str,"%d",le_world->get_level()->time_left);
596 level_settings_menu->get_item_by_id(MNID_TIME).change_input(str);
597 sprintf(str,"%2.0f",le_world->get_level()->gravity);
598 level_settings_menu->get_item_by_id(MNID_GRAVITY).change_input(str);
599 sprintf(str,"%d",le_world->get_level()->bkgd_speed);
600 level_settings_menu->get_item_by_id(MNID_BGSPEED).change_input(str);
601 sprintf(str,"%d",le_world->get_level()->bkgd_top.red);
602 level_settings_menu->get_item_by_id(MNID_TopRed).change_input(str);
603 sprintf(str,"%d",le_world->get_level()->bkgd_top.green);
604 level_settings_menu->get_item_by_id(MNID_TopGreen).change_input(str);
605 sprintf(str,"%d",le_world->get_level()->bkgd_top.blue);
606 level_settings_menu->get_item_by_id(MNID_TopBlue).change_input(str);
607 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.red);
608 level_settings_menu->get_item_by_id(MNID_BottomRed).change_input(str);
609 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.green);
610 level_settings_menu->get_item_by_id(MNID_BottomGreen).change_input(str);
611 sprintf(str,"%d",le_world->get_level()->bkgd_bottom.blue);
612 level_settings_menu->get_item_by_id(MNID_BottomBlue).change_input(str);
615 void update_subset_settings_menu()
617 subset_settings_menu->item[2].change_input(le_level_subset->title.c_str());
618 subset_settings_menu->item[3].change_input(le_level_subset->description.c_str());
621 void apply_level_settings_menu()
626 le_world->get_level()->name = level_settings_menu->get_item_by_id(MNID_NAME).input;
627 le_world->get_level()->author = level_settings_menu->get_item_by_id(MNID_AUTHOR).input;
629 if(le_world->get_level()->bkgd_image.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list)) != 0)
631 le_world->get_level()->bkgd_image = string_list_active(level_settings_menu->get_item_by_id(MNID_BGIMG).list);
635 if(le_world->get_level()->particle_system.compare(string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list)) != 0)
637 le_world->get_level()->particle_system = string_list_active(level_settings_menu->get_item_by_id(MNID_PARTICLE).list);
642 le_world->get_level()->load_gfx();
645 le_world->get_level()->song_title = string_list_active(level_settings_menu->get_item_by_id(MNID_SONG).list);
647 le_world->get_level()->change_size(atoi(level_settings_menu->get_item_by_id(MNID_LENGTH).input));
648 le_world->get_level()->time_left = atoi(level_settings_menu->get_item_by_id(MNID_TIME).input);
649 le_world->get_level()->gravity = atof(level_settings_menu->get_item_by_id(MNID_GRAVITY).input);
650 le_world->get_level()->bkgd_speed = atoi(level_settings_menu->get_item_by_id(MNID_BGSPEED).input);
651 le_world->get_level()->bkgd_top.red = atoi(level_settings_menu->get_item_by_id(MNID_TopRed).input);
652 le_world->get_level()->bkgd_top.green = atoi(level_settings_menu->get_item_by_id(MNID_TopGreen).input);
653 le_world->get_level()->bkgd_top.blue = atoi(level_settings_menu->get_item_by_id(MNID_TopBlue).input);
654 le_world->get_level()->bkgd_bottom.red = atoi(level_settings_menu->get_item_by_id(MNID_BottomRed).input);
655 le_world->get_level()->bkgd_bottom.green = atoi(level_settings_menu->get_item_by_id(MNID_BottomGreen).input);
656 le_world->get_level()->bkgd_bottom.blue = atoi(level_settings_menu->get_item_by_id(MNID_BottomBlue).input);
659 void save_subset_settings_menu()
661 le_level_subset->title = subset_settings_menu->item[2].input;
662 le_level_subset->description = subset_settings_menu->item[3].input;
663 le_level_subset->save();
666 void le_goto_level(int levelnb)
669 le_world = new World(le_level_subset->name, levelnb);
674 /*if(level_changed == true)
675 if(askforsaving() == CANCEL)
678 SDL_EnableKeyRepeat(0, 0); // disables key repeating
681 delete leveleditor_menu;
682 delete subset_load_menu;
683 delete subset_new_menu;
684 delete subset_settings_menu;
685 delete level_settings_menu;
686 delete select_tilegroup_menu;
687 delete select_objects_menu;
688 delete le_save_level_bt;
690 delete le_test_level_bt;
691 delete le_next_level_bt;
692 delete le_previous_level_bt;
693 delete le_move_right_bt;
694 delete le_move_left_bt;
696 delete le_select_mode_one_bt;
697 delete le_select_mode_two_bt;
698 delete le_settings_bt;
699 delete le_tilegroup_bt;
700 delete le_objects_bt;
701 delete le_tilemap_panel;
703 delete le_level_subset;
706 for(ButtonPanelMap::iterator i = tilegroups_map.begin();
707 i != tilegroups_map.end(); ++i)
711 for(ButtonPanelMap::iterator i = objects_map.begin();
712 i != objects_map.end(); ++i)
718 void le_drawminimap()
724 if(screen->w - 64 > le_world->get_level()->width * 4)
726 else if(screen->w - 64 > le_world->get_level()->width * 2)
730 int left_offset = (screen->w - 64 - le_world->get_level()->width*mini_tile_width) / 2;
732 for (int y = 0; y < 15; ++y)
733 for (int x = 0; x < le_world->get_level()->width; ++x)
736 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->bg_tiles[y][x]);
738 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->ia_tiles[y][x]);
740 Tile::draw_stretched(left_offset + mini_tile_width*x, y * 4, mini_tile_width , 4, le_world->get_level()->fg_tiles[y][x]);
744 fillrect(left_offset, 0, le_world->get_level()->width*mini_tile_width, 15*4, 200, 200, 200, 128);
746 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 19*mini_tile_width, 2, 200, 200, 200, 200);
747 fillrect(left_offset + (pos_x/32)*mini_tile_width, 0, 2, 15*4, 200, 200, 200, 200);
748 fillrect(left_offset + (pos_x/32)*mini_tile_width + 19*mini_tile_width - 2, 0, 2, 15*4, 200, 200, 200, 200);
749 fillrect(left_offset + (pos_x/32)*mini_tile_width, 15*4-2, 19*mini_tile_width, 2, 200, 200, 200, 200);
753 void le_drawinterface()
760 /* draw a grid (if selected) */
763 for(x = 0; x < 19; x++)
764 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
765 for(y = 0; y < 15; y++)
766 fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
770 if(show_minimap && use_gl) // 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
773 if(le_selection_mode == CURSOR)
774 if(le_current.IsTile())
775 le_selection->draw( cursor_x - pos_x, cursor_y);
777 le_selection->draw( cursor_x, cursor_y);
778 else if(le_selection_mode == SQUARE)
781 le_highlight_selection();
782 /* draw current selection */
783 w = selection.x2 - selection.x1;
784 h = selection.y2 - selection.y1;
785 fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
786 fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
787 fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
788 fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
792 /* draw button bar */
793 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
795 if(le_current.IsTile())
797 Tile::draw(19 * 32, 14 * 32, le_current.tile);
798 if(TileManager::instance()->get(le_current.tile)->editor_images.size() > 0)
799 TileManager::instance()->get(le_current.tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
801 if(le_current.IsObject())
803 le_current.obj->draw_on_screen(19 * 32, 14 * 32);
804 le_current.obj->draw_on_screen(cursor_x,cursor_y);
809 le_save_level_bt->draw();
811 le_test_level_bt->draw();
812 le_next_level_bt->draw();
813 le_previous_level_bt->draw();
814 le_rubber_bt->draw();
815 if(le_selection_mode == SQUARE)
816 le_select_mode_one_bt->draw();
817 else if(le_selection_mode == CURSOR)
818 le_select_mode_two_bt->draw();
819 le_settings_bt->draw();
820 le_move_right_bt->draw();
821 le_move_left_bt->draw();
822 le_tilegroup_bt->draw();
823 le_objects_bt->draw();
824 if(!cur_tilegroup.empty())
825 tilegroups_map[cur_tilegroup]->draw();
826 else if(!cur_objects.empty())
828 objects_map[cur_objects]->draw();
831 le_tilemap_panel->draw();
833 sprintf(str, "%d/%d", le_level,le_level_subset->levels);
834 white_text->drawf(str, -10, 16, A_RIGHT, A_TOP, 0);
836 white_small_text->draw("F1 for Help", 10, 430, 1);
841 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
843 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
853 /* Draw the real background */
854 if(le_world->get_level()->bkgd_image[0] != '\0')
856 s = (int)((float)pos_x * ((float)le_world->get_level()->bkgd_speed/60.)) % screen->w;
857 le_world->get_level()->img_bkgd->draw_part(s,0,0,0,
858 le_world->get_level()->img_bkgd->w - s - 32, le_world->get_level()->img_bkgd->h);
859 le_world->get_level()->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
860 le_world->get_level()->img_bkgd->h);
864 drawgradient(le_world->get_level()->bkgd_top, le_world->get_level()->bkgd_bottom);
867 if(le_current.IsTile())
869 Tile::draw(cursor_x-pos_x, cursor_y,le_current.tile,128);
870 if(!TileManager::instance()->get(le_current.tile)->images.empty())
871 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);
873 if(le_current.IsObject())
875 le_current.obj->move_to(cursor_x, cursor_y);
878 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
880 for (y = 0; y < 15; ++y)
881 for (x = 0; x < 20; ++x)
884 if(active_tm == TM_BG)
889 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->bg_tiles[y][x + (int)(pos_x / 32)],a);
891 if(active_tm == TM_IA)
896 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)],a);
898 if(active_tm == TM_FG)
903 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_world->get_level()->fg_tiles[y][x + (int)(pos_x / 32)],a);
905 /* draw whats inside stuff when cursor is selecting those */
906 /* (draw them all the time - is this the right behaviour?) */
907 if(!TileManager::instance()->get(le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images.empty())
908 TileManager::instance()->get(le_world->get_level()->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
912 /* Draw the Bad guys: */
913 for (std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it)
915 /* to support frames: img_bsod_left[(frame / 5) % 4] */
922 /* Draw the player: */
923 /* for now, the position is fixed at (100, 240) */
924 largetux.walk_right->draw( 100 - pos_x, 240);
927 void le_change_object_properties(GameObject *pobj)
929 Menu* object_properties_menu = new Menu();
931 object_properties_menu->additem(MN_LABEL,pobj->type() + " Properties",0,0);
932 object_properties_menu->additem(MN_HL,"",0,0);
933 /*object_properties_menu->additem(MN_TEXTFIELD,"Title",0,0,MNID_SUBSETTITLE);
934 object_properties_menu->additem(MN_TEXTFIELD,"Description",0,0,MNID_SUBSETDESCRIPTION);
935 object_properties_menu->additem(MN_HL,"",0,0);
936 object_properties_menu->additem(MN_ACTION,"Save Changes",0,0,MNID_SUBSETSAVECHANGES);*/
937 object_properties_menu->additem(MN_HL,"",0,0);
938 object_properties_menu->additem(MN_BACK,"Apply",0,0);
940 delete object_properties_menu;
944 void le_checkevents()
951 keymod = SDL_GetModState();
953 while(SDL_PollEvent(&event))
957 Menu::current()->event(event);
961 mouse_cursor->set_state(MC_NORMAL);
963 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
964 if(event.type == SDL_KEYDOWN
965 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
966 && (event.motion.x > 0
967 && event.motion.x < screen->w - 64 &&
968 event.motion.y > 0 && event.motion.y < screen->h)))
972 case SDL_KEYDOWN: // key pressed
973 key = event.key.keysym.sym;
977 Menu::set_current(leveleditor_menu);
980 cursor_x -= KEY_CURSOR_SPEED;
982 cursor_x -= KEY_CURSOR_FASTSPEED;
984 if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
985 pos_x = cursor_x - MOUSE_LEFT_MARGIN;
990 cursor_x += KEY_CURSOR_SPEED;
992 cursor_x += KEY_CURSOR_FASTSPEED;
994 if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
995 pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
1000 cursor_y -= KEY_CURSOR_SPEED;
1002 cursor_y -= KEY_CURSOR_FASTSPEED;
1009 cursor_y += KEY_CURSOR_SPEED;
1011 cursor_y += KEY_CURSOR_FASTSPEED;
1013 if(cursor_y > screen->h-32)
1014 cursor_y = screen->h-32;
1020 if(le_world != NULL)
1028 cursor_x = (le_world->get_level()->width * 32) - 32;
1032 le_show_grid = !le_show_grid;
1038 case SDL_KEYUP: /* key released */
1039 switch(event.key.keysym.sym)
1048 case SDL_MOUSEBUTTONDOWN:
1049 if(event.button.button == SDL_BUTTON_LEFT)
1051 le_mouse_pressed[LEFT] = true;
1053 selection.x1 = event.motion.x + pos_x;
1054 selection.y1 = event.motion.y;
1055 selection.x2 = event.motion.x + pos_x;
1056 selection.y2 = event.motion.y;
1058 else if(event.button.button == SDL_BUTTON_RIGHT)
1060 le_mouse_pressed[RIGHT] = true;
1063 case SDL_MOUSEBUTTONUP:
1064 if(event.button.button == SDL_BUTTON_LEFT)
1066 le_mouse_pressed[LEFT] = false;
1067 le_mouse_clicked[LEFT] = true;
1069 else if(event.button.button == SDL_BUTTON_RIGHT)
1071 le_mouse_pressed[RIGHT] = false;
1072 le_mouse_clicked[RIGHT] = true;
1075 case SDL_MOUSEMOTION:
1077 if(!Menu::current())
1082 if(le_current.IsTile())
1084 cursor_x = ((int)(pos_x + x) / 32) * 32;
1085 cursor_y = ((int) y / 32) * 32;
1093 if(le_mouse_pressed[LEFT])
1095 selection.x2 = x + pos_x;
1099 if(le_mouse_pressed[RIGHT])
1101 pos_x += -1 * event.motion.xrel;
1105 case SDL_QUIT: // window closed
1114 if(le_world != NULL)
1116 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 &&
1117 event.motion.y > 0 && event.motion.y < screen->h)))
1119 le_mouse_pressed[LEFT] = false;
1120 le_mouse_pressed[RIGHT] = false;
1122 if(!Menu::current())
1124 /* Check for button events */
1125 le_test_level_bt->event(event);
1126 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
1128 le_save_level_bt->event(event);
1129 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
1130 le_world->get_level()->save(le_level_subset->name.c_str(),le_level);
1131 le_exit_bt->event(event);
1132 if(le_exit_bt->get_state() == BUTTON_CLICKED)
1134 Menu::set_current(leveleditor_menu);
1136 le_next_level_bt->event(event);
1137 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
1139 if(le_level < le_level_subset->levels)
1141 le_goto_level(++le_level);
1147 sprintf(str,"Level %d doesn't exist. Create it?",le_level+1);
1148 if(confirm_dialog(str))
1150 new_lev.init_defaults();
1151 new_lev.save(le_level_subset->name.c_str(),++le_level);
1152 le_level_subset->levels = le_level;
1153 le_goto_level(le_level);
1157 le_previous_level_bt->event(event);
1158 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1161 le_goto_level(--le_level);
1163 le_rubber_bt->event(event);
1164 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1167 if(le_selection_mode == SQUARE)
1169 le_select_mode_one_bt->event(event);
1170 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1171 le_selection_mode = CURSOR;
1175 le_select_mode_two_bt->event(event);
1176 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1177 le_selection_mode = SQUARE;
1179 ButtonPanelMap::iterator it;
1180 le_tilegroup_bt->event(event);
1181 switch (le_tilegroup_bt->get_state())
1183 case BUTTON_CLICKED:
1184 Menu::set_current(select_tilegroup_menu);
1185 select_tilegroup_menu_effect.start(200);
1186 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1188 case BUTTON_WHEELUP:
1189 if(cur_tilegroup.empty())
1191 cur_tilegroup = tilegroups_map.begin()->first;
1195 it = tilegroups_map.find(cur_tilegroup);
1196 if((++it) == tilegroups_map.end())
1198 cur_tilegroup = tilegroups_map.begin()->first;
1202 cur_tilegroup = (*it).first;
1208 case BUTTON_WHEELDOWN:
1209 it = tilegroups_map.find(cur_tilegroup);
1210 if(it == tilegroups_map.begin())
1212 cur_tilegroup = tilegroups_map.rbegin()->first;
1216 if(--it != --tilegroups_map.begin())
1217 cur_tilegroup = (*it).first;
1219 cur_tilegroup = tilegroups_map.rbegin()->first;
1227 le_objects_bt->event(event);
1228 switch (le_objects_bt->get_state())
1230 case BUTTON_CLICKED:
1231 Menu::set_current(select_objects_menu);
1232 select_objects_menu_effect.start(200);
1233 select_objects_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1235 case BUTTON_WHEELUP:
1236 it = objects_map.find(cur_objects);
1237 if(it == objects_map.end())
1239 cur_objects = objects_map.begin()->first;
1243 if(++it != objects_map.end())
1244 cur_objects = (*it).first;
1246 cur_objects = objects_map.begin()->first;
1250 case BUTTON_WHEELDOWN:
1251 it = objects_map.find(cur_objects);
1252 if(it == objects_map.begin())
1254 cur_objects = objects_map.rbegin()->first;
1258 if(--it != --objects_map.begin())
1259 cur_objects = (*it).first;
1261 cur_objects = objects_map.rbegin()->first;
1270 le_settings_bt->event(event);
1271 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1273 update_level_settings_menu();
1274 Menu::set_current(level_settings_menu);
1276 if(!cur_tilegroup.empty())
1278 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1280 if(pbutton->get_state() == BUTTON_CLICKED)
1282 le_current.Tile(pbutton->get_tag());
1286 else if(!cur_objects.empty())
1288 if((pbutton = objects_map[cur_objects]->event(event)) != NULL)
1290 if(pbutton->get_state() == BUTTON_CLICKED)
1292 le_current.Object(pbutton->get_game_object());
1297 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1299 if(pbutton->get_state() == BUTTON_CLICKED)
1301 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1307 le_settings_bt->event(event);
1308 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1310 Menu::set_current(0);
1312 le_tilegroup_bt->event(event);
1313 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1315 Menu::set_current(0);
1317 le_objects_bt->event(event);
1318 if(le_objects_bt->get_state() == BUTTON_CLICKED)
1320 Menu::set_current(0);
1325 if(!Menu::current() && !show_minimap)
1327 if(le_mouse_pressed[LEFT])
1329 if(le_current.IsTile())
1330 le_change(cursor_x, cursor_y, active_tm, le_current.tile);
1332 else if(le_mouse_clicked[LEFT])
1334 if(le_current.IsObject())
1336 std::string type = le_current.obj->type();
1337 if(type == "BadGuy")
1339 BadGuy* pbadguy = dynamic_cast<BadGuy*>(le_current.obj);
1341 le_world->bad_guys.push_back(new BadGuy(cursor_x+scroll_x, cursor_y,pbadguy->kind,false));
1342 le_world->get_level()->badguy_data.push_back(le_world->bad_guys.back());
1345 le_mouse_clicked[LEFT] = false;
1350 if(!Menu::current())
1352 show_minimap = false;
1354 le_move_left_bt->event(event);
1355 le_move_right_bt->event(event);
1356 switch(le_move_left_bt->get_state())
1358 case BUTTON_PRESSED:
1360 show_minimap = true;
1364 show_minimap = true;
1366 case BUTTON_CLICKED:
1367 show_minimap = true;
1373 switch(le_move_right_bt->get_state())
1375 case BUTTON_PRESSED:
1377 show_minimap = true;
1381 show_minimap = true;
1383 case BUTTON_CLICKED:
1384 show_minimap = true;
1394 void le_highlight_selection()
1398 if(selection.x1 < selection.x2)
1408 if(selection.y1 < selection.y2)
1424 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1427 void le_change(float x, float y, int tm, unsigned int c)
1429 if(le_world != NULL)
1435 /* level_changed = true; */
1437 switch(le_selection_mode)
1440 le_world->get_level()->change(x,y,tm,c);
1442 base_type cursor_base;
1445 cursor_base.width = 32;
1446 cursor_base.height = 32;
1448 /* if there is a bad guy over there, remove it */
1449 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin(); it != le_world->bad_guys.end(); ++it, ++i)
1450 if(rectcollision(cursor_base,(*it)->base))
1453 le_world->bad_guys.erase(it);
1454 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1460 if(selection.x1 < selection.x2)
1470 if(selection.y1 < selection.y2)
1486 /* if there is a bad guy over there, remove it */
1487 for(std::list<BadGuy*>::iterator it = le_world->bad_guys.begin();
1488 it != le_world->bad_guys.end(); /* will be at end of loop */)
1490 if((*it)->base.x/32 >= x1 && (*it)->base.x/32 <= x2
1491 && (*it)->base.y/32 >= y1 && (*it)->base.y/32 <= y2)
1494 it = le_world->bad_guys.erase(it);
1495 le_world->get_level()->badguy_data.erase(le_world->get_level()->badguy_data.begin() + i);
1505 for(xx = x1; xx <= x2; xx++)
1506 for(yy = y1; yy <= y2; yy++)
1508 le_world->get_level()->change(xx*32, yy*32, tm, c);
1520 //Make sure a time value is set when testing the level
1521 if(le_world->get_level()->time_left == 0)
1522 le_world->get_level()->time_left = 250;
1524 le_world->get_level()->save("test", le_level);
1526 GameSession session("test",le_level, ST_GL_TEST);
1528 player_status.reset();
1530 music_manager->halt_music();
1532 Menu::set_current(NULL);
1533 World::set_current(le_world);
1539 unsigned int i, done_;
1542 " - Supertux level editor tutorial - ",
1544 "To make your map, click the tilegroup button and choose a tilegroup."
1545 "Pick a tile and simply hold down the left mouse button over the map",
1546 "to \"paint\" your selection over the screen.",
1547 "There are three layers for painting tiles upon, Background layer,",
1548 "the Interactive layer, and the Foreground layer, which can be toggled",
1549 "by the BkGrd, IntAct and FrGrd buttons. The Foreground and Background",
1550 "layers do not effect Tux in the gameplay, but lie in front of him or",
1551 "lie behind him in his adventures. The tiles placed on the Interactive",
1552 "layer are those which actually effect Tux in the game.",
1553 "Click the objects menu to put bad guys and other objects in the game.",
1554 "Unlike placing tiles, you cannot \"paint\" enemies. Click them onto",
1555 "the screen one at a time.",
1556 "To change the settings of your level, click the button with the",
1557 "screwdriver and wrench. From here you can change the background,",
1558 "music, length of the level, and more.",
1559 "You may have more than one levelset. Pressing the up and down buttons",
1560 "above the button bar lets you choose which one you are working on.",
1561 "If you would like to speed up your level editing, a useful trick is",
1562 "to learn the keyboard shortcuts. They are easy to learn, just right-",
1563 "Have fun making levels! If you make some good ones, send them to us on",
1564 "the SuperTux mailing list!",
1570 " - Supertux level editor tutorial - ",
1572 "To make your map, click the tilegroup button and choose a tilegroup."
1573 "APick a tile and simply hold down the left mouse button over the map",
1574 "Ato \"paint\" your selection over the screen.",
1575 "AThere are three layers for painting tiles upon, Background layer,",
1576 "the Interactive layer, and the Foreground layer, which can be toggled",
1577 "by the BkGrd, IntAct and FrGrd buttons. The Foreground and Background",
1578 "layers do not effect Tux in the gameplay, but lie in front of him or",
1579 "lie behind him in his adventures. The tiles placed on the Interactive",
1580 "layer are those which actually effect Tux in the game.",
1581 "Click the objects menu to put bad guys and other objects in the game.",
1582 "Unlike placing tiles, you cannot \"paint\" enemies. Click them onto",
1583 "the screen one at a time.",
1584 "To change the settings of your level, click the button with the",
1585 "screwdriver and wrench. From here you can change the background,",
1586 "music, length of the level, and more.",
1587 "You may have more than one levelset. Pressing the up and down buttons",
1588 "above the button bar lets you choose which one you are working on.",
1589 "If you would like to speed up your level editing, a useful trick is",
1590 "to learn the keyboard shortcuts. They are easy to learn, just right-",
1591 "Have fun making levels! If you make some good ones, send them to us on",
1592 "the SuperTux mailing list!",
1597 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1599 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1600 white_text->draw(text[i], 5, 80+(i*white_text->h), 1);
1602 gold_text->drawf("Press Any Key to Continue - Page 1/2", 0, 440, A_HMIDDLE, A_TOP, 1);
1610 done_ = wait_for_event(event);
1617 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1619 for(i = 0; i < sizeof(text2)/sizeof(char *); i++)
1620 white_text->draw(text2[i], 5, 80+(i*white_text->h), 1);
1622 gold_text->drawf("Press Any Key to Continue - Page 2/2", 0, 440, A_HMIDDLE, A_TOP, 1);
1630 done_ = wait_for_event(event);