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"
45 /* 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) */
70 void le_drawinterface();
71 void le_checkevents();
72 void le_change(float x, float y, int tm, unsigned int c);
75 void le_set_defaults(void);
76 void le_activate_bad_guys(void);
78 void le_highlight_selection();
80 void apply_level_settings_menu();
81 void update_subset_settings_menu();
82 void save_subset_settings_menu();
84 static Level* le_current_level;
86 struct LevelEditorWorld
88 std::vector<BadGuy> bad_guys;
89 void arrays_free(void)
94 void add_bad_guy(float x, float y, BadGuyKind kind)
96 bad_guys.push_back(BadGuy());
97 BadGuy& new_bad_guy = bad_guys.back();
99 new_bad_guy.init(x,y,kind);
102 void activate_bad_guys()
104 for (std::vector<BadGuyData>::iterator i = le_current_level->badguy_data.begin();
105 i != le_current_level->badguy_data.end();
108 add_bad_guy(i->x, i->y, i->kind);
113 /* leveleditor internals */
114 static string_list_type level_subsets;
115 static bool le_level_changed; /* if changes, ask for saving, when quiting*/
116 static int pos_x, cursor_x, cursor_y, fire;
118 static LevelEditorWorld le_world;
119 static st_subset le_level_subset;
120 static int le_show_grid;
122 static Surface* le_selection;
124 static unsigned int le_current_tile;
125 static bool le_mouse_pressed[2];
126 static Button* le_save_level_bt;
127 static Button* le_exit_bt;
128 static Button* le_test_level_bt;
129 static Button* le_next_level_bt;
130 static Button* le_previous_level_bt;
131 static Button* le_move_right_bt;
132 static Button* le_move_left_bt;
133 static Button* le_rubber_bt;
134 static Button* le_select_mode_one_bt;
135 static Button* le_select_mode_two_bt;
136 static Button* le_settings_bt;
137 static Button* le_tilegroup_bt;
138 static ButtonPanel* le_tilemap_panel;
139 static Menu* leveleditor_menu;
140 static Menu* subset_load_menu;
141 static Menu* subset_new_menu;
142 static Menu* subset_settings_menu;
143 static Menu* level_settings_menu;
144 static Menu* select_tilegroup_menu;
145 static Timer select_tilegroup_menu_effect;
146 static std::map<std::string, ButtonPanel* > tilegroups_map;
147 static std::string cur_tilegroup;
149 static square selection;
150 static int le_selection_mode;
151 static SDL_Event event;
152 TileMapType active_tm;
154 void le_set_defaults()
156 if(le_current_level != NULL)
160 if(le_current_level->time_left == 0)
161 le_current_level->time_left = 255;
165 int leveleditor(int levelnb)
167 int last_time, now_time, i;
175 clearscreen(0, 0, 0);
178 while (SDL_PollEvent(&event))
183 last_time = SDL_GetTicks();
188 if(Menu::current() == select_tilegroup_menu)
190 if(select_tilegroup_menu_effect.check())
192 select_tilegroup_menu->set_pos(screen->w - 64 + select_tilegroup_menu_effect.get_left(),
196 select_tilegroup_menu->set_pos(screen->w - 64,82,-0.5,0.5);
199 if(le_current_level != NULL)
201 /* making events results to be in order */
204 if(pos_x > (le_current_level->width * 32) - screen->w)
205 pos_x = (le_current_level->width * 32) - screen->w;
211 clearscreen(0, 0, 0);
213 /* draw editor interface */
216 Menu* menu = Menu::current();
222 if(menu == leveleditor_menu)
224 switch (leveleditor_menu->check())
227 Menu::set_current(0);
230 update_subset_settings_menu();
237 else if(menu == level_settings_menu)
239 switch (level_settings_menu->check())
242 apply_level_settings_menu();
243 Menu::set_current(leveleditor_menu);
251 else if(menu == select_tilegroup_menu)
254 switch (it = select_tilegroup_menu->check())
259 if(select_tilegroup_menu->item[it].kind == MN_ACTION)
260 cur_tilegroup = select_tilegroup_menu->item[it].text;
262 Menu::set_current(0);
267 else if(menu == subset_load_menu)
269 switch (i = subset_load_menu->check())
276 le_level_subset.load(level_subsets.item[i-2]);
277 leveleditor_menu->item[3].kind = MN_GOTO;
279 le_world.arrays_free();
280 le_current_level = new Level;
281 if(le_current_level->load(le_level_subset.name.c_str(), le_level) != 0)
287 le_current_level->load_gfx();
288 le_world.activate_bad_guys();
291 Menu::set_current(leveleditor_menu);
296 else if(menu == subset_new_menu)
298 if(subset_new_menu->item[2].input[0] == '\0')
299 subset_new_menu->item[3].kind = MN_DEACTIVE;
302 subset_new_menu->item[3].kind = MN_ACTION;
304 switch (i = subset_new_menu->check())
307 st_subset::create(subset_new_menu->item[2].input);
308 le_level_subset.load(subset_new_menu->item[2].input);
309 leveleditor_menu->item[3].kind = MN_GOTO;
311 le_world.arrays_free();
312 le_current_level = new Level;
313 if(le_current_level->load(le_level_subset.name.c_str(), le_level) != 0)
319 le_current_level->load_gfx();
320 le_world.activate_bad_guys();
321 subset_new_menu->item[2].change_input("");
322 // FIXME:? show_menu = true;
323 Menu::set_current(leveleditor_menu);
328 else if(menu == subset_settings_menu)
330 if(le_level_subset.title.compare(subset_settings_menu->item[2].input) == 0 && le_level_subset.description.compare(subset_settings_menu->item[3].input) == 0 )
331 subset_settings_menu->item[5].kind = MN_DEACTIVE;
333 subset_settings_menu->item[5].kind = MN_ACTION;
335 switch (i = subset_settings_menu->check())
338 save_subset_settings_menu();
339 //FIXME:show_menu = true;
340 Menu::set_current(leveleditor_menu);
346 mouse_cursor->draw();
348 printf("done: %i\n", done);
357 ++global_frame_counter;
360 now_time = SDL_GetTicks();
361 if (now_time < last_time + FPS)
362 SDL_Delay(last_time + FPS - now_time); /* delay some time */
373 level_subsets = dsubdirs("/levels", "info");
379 /* level_changed = NO;*/
382 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
383 le_level_changed = false;
384 le_current_level = NULL;
387 le_mouse_pressed[LEFT] = false;
388 le_mouse_pressed[RIGHT] = false;
390 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
392 select_tilegroup_menu_effect.init(false);
395 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
396 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F6,screen->w-32,32);
397 le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
398 le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
399 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
400 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
401 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,64);
402 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
403 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
404 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
405 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
406 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,80);
408 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
409 le_tilemap_panel->set_button_size(32,10);
410 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_F4,0,0),TM_BG);
411 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_F4,0,0),TM_IA);
412 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_F4,0,0),TM_FG);
414 leveleditor_menu = new Menu();
415 subset_load_menu = new Menu();
416 subset_new_menu = new Menu();
417 subset_settings_menu = new Menu();
418 level_settings_menu = new Menu();
419 select_tilegroup_menu = new Menu();
421 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
422 leveleditor_menu->additem(MN_HL,"",0,0);
423 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0);
424 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu);
425 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
426 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
427 leveleditor_menu->additem(MN_HL,"",0,0);
428 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0);
430 Menu::set_current(leveleditor_menu);
432 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
433 subset_load_menu->additem(MN_HL, "", 0, 0);
435 for(i = 0; i < level_subsets.num_items; ++i)
437 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0);
439 subset_load_menu->additem(MN_HL,"",0,0);
440 subset_load_menu->additem(MN_BACK,"Back",0,0);
442 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
443 subset_new_menu->additem(MN_HL,"",0,0);
444 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0);
445 subset_new_menu->additem(MN_ACTION,"Create",0,0);
446 subset_new_menu->additem(MN_HL,"",0,0);
447 subset_new_menu->additem(MN_BACK,"Back",0,0);
449 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
450 subset_settings_menu->additem(MN_HL,"",0,0);
451 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0);
452 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0);
453 subset_settings_menu->additem(MN_HL,"",0,0);
454 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0);
455 subset_settings_menu->additem(MN_HL,"",0,0);
456 subset_settings_menu->additem(MN_BACK,"Back",0,0);
458 level_settings_menu->arrange_left = true;
459 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
460 level_settings_menu->additem(MN_HL,"",0,0);
461 level_settings_menu->additem(MN_TEXTFIELD,"Name ",0,0);
462 level_settings_menu->additem(MN_TEXTFIELD,"Author ",0,0);
463 level_settings_menu->additem(MN_STRINGSELECT,"Theme ",0,0);
464 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0);
465 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0);
466 level_settings_menu->additem(MN_NUMFIELD,"Length ",0,0);
467 level_settings_menu->additem(MN_NUMFIELD,"Time ",0,0);
468 level_settings_menu->additem(MN_NUMFIELD,"Gravity",0,0);
469 level_settings_menu->additem(MN_NUMFIELD,"Top Red ",0,0);
470 level_settings_menu->additem(MN_NUMFIELD,"Top Green ",0,0);
471 level_settings_menu->additem(MN_NUMFIELD,"Top Blue ",0,0);
472 level_settings_menu->additem(MN_NUMFIELD,"Bottom Red ",0,0);
473 level_settings_menu->additem(MN_NUMFIELD,"Bottom Green",0,0);
474 level_settings_menu->additem(MN_NUMFIELD,"Bottom Blue",0,0);
475 level_settings_menu->additem(MN_HL,"",0,0);
476 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0);
478 select_tilegroup_menu->arrange_left = true;
479 select_tilegroup_menu->additem(MN_LABEL,"Select Tilegroup",0,0);
480 select_tilegroup_menu->additem(MN_HL,"",0,0);
481 std::vector<TileGroup>* tilegroups = TileManager::tilegroups();
482 for(std::vector<TileGroup>::iterator it = tilegroups->begin(); it != tilegroups->end(); ++it )
485 select_tilegroup_menu->additem(MN_ACTION,const_cast<char*>((*it).name.c_str()),0,0);
486 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
488 for(std::vector<int>::iterator sit = (*it).tiles.begin(); sit != (*it).tiles.end(); ++sit, ++i)
489 tilegroups_map[(*it).name]->additem(new Button(const_cast<char*>(("images/tilesets/" + TileManager::instance()->get(*sit)->filenames[0]).c_str()), const_cast<char*>((*it).name.c_str()),(SDLKey)(i+'a'),0,0,32,32),(*sit));
491 select_tilegroup_menu->additem(MN_HL,"",0,0);
493 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
498 void update_level_settings_menu()
503 level_settings_menu->item[2].change_input(le_current_level->name.c_str());
504 level_settings_menu->item[3].change_input(le_current_level->author.c_str());
505 sprintf(str,"%d",le_current_level->width);
507 string_list_copy(level_settings_menu->item[4].list, dsubdirs("images/themes", "solid0.png"));
508 string_list_copy(level_settings_menu->item[5].list, dfiles("music/",NULL, "-fast"));
509 string_list_copy(level_settings_menu->item[6].list, dfiles("images/background",NULL, NULL));
510 string_list_add_item(level_settings_menu->item[6].list,"");
511 if((i = string_list_find(level_settings_menu->item[4].list,le_current_level->theme.c_str())) != -1)
512 level_settings_menu->item[3].list->active_item = i;
513 if((i = string_list_find(level_settings_menu->item[5].list,le_current_level->song_title.c_str())) != -1)
514 level_settings_menu->item[4].list->active_item = i;
515 if((i = string_list_find(level_settings_menu->item[6].list,le_current_level->bkgd_image.c_str())) != -1)
516 level_settings_menu->item[5].list->active_item = i;
518 level_settings_menu->item[7].change_input(str);
519 sprintf(str,"%d",le_current_level->time_left);
520 level_settings_menu->item[8].change_input(str);
521 sprintf(str,"%2.0f",le_current_level->gravity);
522 level_settings_menu->item[9].change_input(str);
523 sprintf(str,"%d",le_current_level->bkgd_top.red);
524 level_settings_menu->item[10].change_input(str);
525 sprintf(str,"%d",le_current_level->bkgd_top.green);
526 level_settings_menu->item[11].change_input(str);
527 sprintf(str,"%d",le_current_level->bkgd_top.blue);
528 level_settings_menu->item[12].change_input(str);
529 sprintf(str,"%d",le_current_level->bkgd_bottom.red);
530 level_settings_menu->item[13].change_input(str);
531 sprintf(str,"%d",le_current_level->bkgd_bottom.green);
532 level_settings_menu->item[14].change_input(str);
533 sprintf(str,"%d",le_current_level->bkgd_bottom.blue);
534 level_settings_menu->item[15].change_input(str);
537 void update_subset_settings_menu()
539 subset_settings_menu->item[2].change_input(le_level_subset.title.c_str());
540 subset_settings_menu->item[3].change_input(le_level_subset.description.c_str());
543 void apply_level_settings_menu()
548 le_current_level->name = level_settings_menu->item[2].input;
549 le_current_level->author = level_settings_menu->item[3].input;
551 if(le_current_level->bkgd_image.compare(string_list_active(level_settings_menu->item[6].list)) != 0)
553 le_current_level->bkgd_image = string_list_active(level_settings_menu->item[6].list);
557 if(le_current_level->theme.compare(string_list_active(level_settings_menu->item[4].list)) != 0)
559 le_current_level->theme = string_list_active(level_settings_menu->item[4].list);
565 le_current_level->free_gfx();
566 le_current_level->load_gfx();
569 le_current_level->song_title = string_list_active(level_settings_menu->item[5].list);
571 le_current_level->change_size(atoi(level_settings_menu->item[7].input));
572 le_current_level->time_left = atoi(level_settings_menu->item[8].input);
573 le_current_level->gravity = atof(level_settings_menu->item[9].input);
574 le_current_level->bkgd_top.red = atoi(level_settings_menu->item[10].input);
575 le_current_level->bkgd_top.green = atoi(level_settings_menu->item[11].input);
576 le_current_level->bkgd_top.blue = atoi(level_settings_menu->item[12].input);
577 le_current_level->bkgd_bottom.red = atoi(level_settings_menu->item[13].input);
578 le_current_level->bkgd_bottom.green = atoi(level_settings_menu->item[14].input);
579 le_current_level->bkgd_bottom.blue = atoi(level_settings_menu->item[15].input);
582 void save_subset_settings_menu()
584 le_level_subset.title = subset_settings_menu->item[2].input;
585 le_level_subset.description = subset_settings_menu->item[3].input;
586 le_level_subset.save();
589 void le_goto_level(int levelnb)
591 le_world.arrays_free();
593 le_current_level->cleanup();
594 if(le_current_level->load(le_level_subset.name.c_str(), levelnb) != 0)
596 le_current_level->load(le_level_subset.name.c_str(), le_level);
605 le_current_level->free_gfx();
606 le_current_level->load_gfx();
608 le_world.activate_bad_guys();
613 /*if(level_changed == true)
614 if(askforsaving() == CANCEL)
617 SDL_EnableKeyRepeat(0, 0); // disables key repeating
620 delete leveleditor_menu;
621 delete subset_load_menu;
622 delete subset_new_menu;
623 delete subset_settings_menu;
624 delete level_settings_menu;
625 delete select_tilegroup_menu;
626 delete le_save_level_bt;
628 delete le_test_level_bt;
629 delete le_next_level_bt;
630 delete le_previous_level_bt;
631 delete le_move_right_bt;
632 delete le_move_left_bt;
634 delete le_select_mode_one_bt;
635 delete le_select_mode_two_bt;
636 delete le_settings_bt;
637 delete le_tilegroup_bt;
638 delete le_tilemap_panel;
640 if(le_current_level != NULL)
642 le_current_level->free_gfx();
643 le_current_level->cleanup();
644 le_world.arrays_free();
648 void le_drawinterface()
653 if(le_current_level != NULL)
655 /* draw a grid (if selected) */
658 for(x = 0; x < 19; x++)
659 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
660 for(y = 0; y < 15; y++)
661 fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
665 if(le_selection_mode == CURSOR)
666 le_selection->draw( cursor_x - pos_x, cursor_y);
667 else if(le_selection_mode == SQUARE)
670 le_highlight_selection();
671 /* draw current selection */
672 w = selection.x2 - selection.x1;
673 h = selection.y2 - selection.y1;
674 fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
675 fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
676 fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
677 fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
681 /* draw button bar */
682 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
683 Tile::draw(19 * 32, 14 * 32, le_current_tile);
685 if(TileManager::instance()->get(le_current_tile)->editor_images.size() > 0)
686 TileManager::instance()->get(le_current_tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
688 if(le_current_level != NULL)
690 le_save_level_bt->draw();
692 le_test_level_bt->draw();
693 le_next_level_bt->draw();
694 le_previous_level_bt->draw();
695 le_rubber_bt->draw();
696 le_select_mode_one_bt->draw();
697 le_select_mode_two_bt->draw();
698 le_settings_bt->draw();
699 le_move_right_bt->draw();
700 le_move_left_bt->draw();
701 le_tilegroup_bt->draw();
702 if(!cur_tilegroup.empty())
703 tilegroups_map[cur_tilegroup]->draw();
704 le_tilemap_panel->draw();
706 sprintf(str, "%d/%d", le_level,le_level_subset.levels);
707 white_text->drawf(str, -10, 16, A_RIGHT, A_TOP, 0);
709 white_small_text->draw("F1 for Help", 10, 430, 1);
714 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
716 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
723 unsigned int y,x,i,s;
726 /* Draw the real background */
727 if(le_current_level->bkgd_image[0] != '\0')
730 le_current_level->img_bkgd->draw_part(s,0,0,0,
731 le_current_level->img_bkgd->w - s - 32, le_current_level->img_bkgd->h);
732 le_current_level->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
733 le_current_level->img_bkgd->h);
737 drawgradient(le_current_level->bkgd_top, le_current_level->bkgd_bottom);
740 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
742 for (y = 0; y < 15; ++y)
743 for (x = 0; x < 20; ++x)
746 if(active_tm == TM_BG)
751 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->bg_tiles[y][x + (int)(pos_x / 32)],a);
753 if(active_tm == TM_IA)
758 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->ia_tiles[y][x + (int)(pos_x / 32)],a);
760 if(active_tm == TM_FG)
765 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->fg_tiles[y][x + (int)(pos_x / 32)],a);
767 /* draw whats inside stuff when cursor is selecting those */
768 /* (draw them all the time - is this the right behaviour?) */
769 if(TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images.size() > 0)
770 TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images[0]->draw( x * 32 - ((int)pos_x % 32), y*32);
774 /* Draw the Bad guys: */
775 for (i = 0; i < le_world.bad_guys.size(); ++i)
777 /* to support frames: img_bsod_left[(frame / 5) % 4] */
780 le_world.bad_guys[i].draw();
784 /* Draw the player: */
785 /* for now, the position is fixed at (100, 240) */
786 tux_right[(global_frame_counter / 5) % 3]->draw( 100 - pos_x, 240);
789 void le_checkevents()
796 keymod = SDL_GetModState();
798 while(SDL_PollEvent(&event))
802 Menu::current()->event(event);
806 mouse_cursor->set_state(MC_NORMAL);
808 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
809 if(event.type == SDL_KEYDOWN
810 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
811 && (event.motion.x > 0
812 && event.motion.x < screen->w - 64 &&
813 event.motion.y > 0 && event.motion.y < screen->h)))
817 case SDL_KEYDOWN: // key pressed
818 key = event.key.keysym.sym;
823 cursor_x -= KEY_CURSOR_SPEED;
825 cursor_x -= KEY_CURSOR_FASTSPEED;
827 if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
828 pos_x = cursor_x - MOUSE_LEFT_MARGIN;
833 cursor_x += KEY_CURSOR_SPEED;
835 cursor_x += KEY_CURSOR_FASTSPEED;
837 if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
838 pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
843 cursor_y -= KEY_CURSOR_SPEED;
845 cursor_y -= KEY_CURSOR_FASTSPEED;
852 cursor_y += KEY_CURSOR_SPEED;
854 cursor_y += KEY_CURSOR_FASTSPEED;
856 if(cursor_y > screen->h-32)
857 cursor_y = screen->h-32;
870 cursor_x = (le_current_level->width * 32) - 32;
874 le_show_grid = !le_show_grid;
880 case SDL_KEYUP: /* key released */
881 switch(event.key.keysym.sym)
890 case SDL_MOUSEBUTTONDOWN:
891 if(event.button.button == SDL_BUTTON_LEFT)
893 le_mouse_pressed[LEFT] = true;
895 selection.x1 = event.motion.x + pos_x;
896 selection.y1 = event.motion.y;
897 selection.x2 = event.motion.x + pos_x;
898 selection.y2 = event.motion.y;
900 else if(event.button.button == SDL_BUTTON_RIGHT)
902 le_mouse_pressed[RIGHT] = true;
905 case SDL_MOUSEBUTTONUP:
906 if(event.button.button == SDL_BUTTON_LEFT)
907 le_mouse_pressed[LEFT] = false;
908 else if(event.button.button == SDL_BUTTON_RIGHT)
909 le_mouse_pressed[RIGHT] = false;
911 case SDL_MOUSEMOTION:
918 cursor_x = ((int)(pos_x + x) / 32) * 32;
919 cursor_y = ((int) y / 32) * 32;
921 if(le_mouse_pressed[LEFT])
923 selection.x2 = x + pos_x;
927 if(le_mouse_pressed[RIGHT])
929 pos_x += -1 * event.motion.xrel;
933 case SDL_QUIT: // window closed
942 if(le_current_level != NULL)
944 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 &&
945 event.motion.y > 0 && event.motion.y < screen->h)))
947 le_mouse_pressed[LEFT] = false;
948 le_mouse_pressed[RIGHT] = false;
952 /* Check for button events */
953 le_test_level_bt->event(event);
954 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
956 le_save_level_bt->event(event);
957 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
958 le_current_level->save(le_level_subset.name.c_str(),le_level);
959 le_exit_bt->event(event);
960 if(le_exit_bt->get_state() == BUTTON_CLICKED)
962 Menu::set_current(leveleditor_menu);
964 le_next_level_bt->event(event);
965 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
967 if(le_level < le_level_subset.levels)
969 le_goto_level(++le_level);
976 sprintf(str,"Level %d doesn't exist.",le_level+1);
977 white_text->drawf(str,0,-18,A_HMIDDLE,A_VMIDDLE,2);
978 white_text->drawf("Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2);
979 red_text->drawf("(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2);
983 while(SDL_PollEvent(&event))
986 case SDL_KEYDOWN: // key pressed
987 switch(event.key.keysym.sym)
990 new_lev.init_defaults();
991 new_lev.save(le_level_subset.name.c_str(),++le_level);
992 le_level_subset.levels = le_level;
993 le_goto_level(le_level);
1010 le_previous_level_bt->event(event);
1011 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1014 le_goto_level(--le_level);
1016 le_rubber_bt->event(event);
1017 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1018 le_current_tile = 0;
1019 le_select_mode_one_bt->event(event);
1020 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1021 le_selection_mode = CURSOR;
1022 le_select_mode_two_bt->event(event);
1023 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1024 le_selection_mode = SQUARE;
1026 le_tilegroup_bt->event(event);
1027 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1029 Menu::set_current(select_tilegroup_menu);
1030 select_tilegroup_menu_effect.start(200);
1031 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1034 le_settings_bt->event(event);
1035 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1037 update_level_settings_menu();
1038 Menu::set_current(level_settings_menu);
1040 if(!cur_tilegroup.empty())
1041 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1043 if(pbutton->get_state() == BUTTON_CLICKED)
1045 le_current_tile = pbutton->get_tag();
1048 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1050 if(pbutton->get_state() == BUTTON_CLICKED)
1052 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1058 le_settings_bt->event(event);
1059 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1061 Menu::set_current(0);
1063 le_tilegroup_bt->event(event);
1064 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1066 Menu::set_current(0);
1071 if(!Menu::current())
1073 le_move_left_bt->event(event);
1074 le_move_right_bt->event(event);
1076 if(le_mouse_pressed[LEFT])
1078 le_change(cursor_x, cursor_y, active_tm, le_current_tile);
1083 if(!Menu::current())
1085 if(le_move_left_bt->get_state() == BUTTON_PRESSED)
1089 else if(le_move_left_bt->get_state() == BUTTON_HOVER)
1094 if(le_move_right_bt->get_state() == BUTTON_PRESSED)
1098 else if(le_move_right_bt->get_state() == BUTTON_HOVER)
1106 void le_highlight_selection()
1110 if(selection.x1 < selection.x2)
1120 if(selection.y1 < selection.y2)
1136 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1139 void le_change(float x, float y, int tm, unsigned int c)
1141 if(le_current_level != NULL)
1147 /* level_changed = true; */
1149 switch(le_selection_mode)
1152 le_current_level->change(x,y,tm,c);
1157 /* if there is a bad guy over there, remove it */
1158 for(i = 0; i < le_world.bad_guys.size(); ++i)
1159 if(xx == le_world.bad_guys[i].base.x/32 && yy == le_world.bad_guys[i].base.y/32)
1160 le_world.bad_guys.erase(le_world.bad_guys.begin() + i);
1162 if(c == '0') /* if it's a bad guy */
1163 le_world.add_bad_guy(xx*32, yy*32, BAD_BSOD);
1165 le_world.add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1167 le_world.add_bad_guy(xx*32, yy*32, BAD_MONEY);
1171 if(selection.x1 < selection.x2)
1181 if(selection.y1 < selection.y2)
1197 /* if there is a bad guy over there, remove it */
1198 for(i = 0; i < le_world.bad_guys.size(); ++i)
1199 if(le_world.bad_guys[i].base.x/32 >= x1 && le_world.bad_guys[i].base.x/32 <= x2
1200 && le_world.bad_guys[i].base.y/32 >= y1 && le_world.bad_guys[i].base.y/32 <= y2)
1201 le_world.bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(&le_world.bad_guys[i]));
1203 for(xx = x1; xx <= x2; xx++)
1204 for(yy = y1; yy <= y2; yy++)
1206 le_current_level->change(xx*32, yy*32, tm, c);
1208 if(c == '0') // if it's a bad guy
1209 le_world.add_bad_guy(xx*32, yy*32, BAD_BSOD);
1211 le_world.add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1213 le_world.add_bad_guy(xx*32, yy*32, BAD_MONEY);
1224 le_current_level->save("test", le_level);
1226 GameSession session("test",le_level, ST_GL_TEST);
1229 Menu::set_current(leveleditor_menu);
1230 le_world.arrays_free();
1231 le_current_level->load_gfx();
1232 le_world.activate_bad_guys();
1238 unsigned int i, done_;
1240 " - This is SuperTux's built-in level editor -",
1241 "It has been designed to be light and easy to use from the start.",
1243 "When you first load the level editor you are given a menu where you",
1244 "can load level subsets, create a new level subset, edit the current",
1245 "subset's settings, or simply quit the editor. You can access this menu",
1246 "from the level editor at any time by pressing the escape key.",
1248 "To your right is your button bar. The center of this contains many",
1249 "tiles you can use to make your level. To select a tile, click on it",
1250 "with your left mouse button; your selection will be shown in the",
1251 "bottom right corner of the button box. Click anywhere on your level",
1252 "with the left mouse button to place that tile down. If you right click",
1253 "a tile in the button bar, you can find out what its keyboard shortcut",
1254 "is. The three buttons FGD, BGD and EMY let you pick from foreground,",
1255 "background, and enemy tiles. The eraser lets you remove tiles.",
1256 "The left and right arrow keys scroll back and forth through your level.",
1257 "The button with the wrench and screwdriver, lets you change the",
1258 "settings of your level, including how long it is or what music it will",
1259 "play. When you are ready to give your level a test, click on the little",
1260 "running Tux. If you like the changes you have made to your level,",
1261 "press the red save key to keep them.",
1262 "To change which level in your subset you are editing, press the white",
1263 "up and down arrow keys at the top of the button box.",
1265 "Have fun making levels! If you make some good ones, send them to us on",
1266 "the SuperTux mailing list!",
1271 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1273 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1274 white_small_text->draw(text[i], 5, 80+(i*white_small_text->h), 1);
1276 gold_text->drawf("Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
1284 done_ = wait_for_event(event);