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 */
218 Menu::current()->draw();
219 Menu::current()->action();
221 if(Menu::current() == leveleditor_menu)
223 switch (leveleditor_menu->check())
226 Menu::set_current(0);
229 update_subset_settings_menu();
236 else if(Menu::current() == level_settings_menu)
238 switch (level_settings_menu->check())
241 apply_level_settings_menu();
242 Menu::set_current(leveleditor_menu);
250 else if(Menu::current() == select_tilegroup_menu)
253 switch (it = select_tilegroup_menu->check())
258 if(select_tilegroup_menu->item[it].kind == MN_ACTION)
259 cur_tilegroup = select_tilegroup_menu->item[it].text;
261 Menu::set_current(0);
266 else if(Menu::current() == subset_load_menu)
268 switch (i = subset_load_menu->check())
275 le_level_subset.load(level_subsets.item[i-2]);
276 leveleditor_menu->item[3].kind = MN_GOTO;
278 le_world.arrays_free();
279 le_current_level = new Level;
280 if(le_current_level->load(le_level_subset.name.c_str(), le_level) != 0)
286 le_current_level->load_gfx();
287 le_world.activate_bad_guys();
290 Menu::set_current(leveleditor_menu);
295 else if(Menu::current() == subset_new_menu)
297 if(subset_new_menu->item[2].input[0] == '\0')
298 subset_new_menu->item[3].kind = MN_DEACTIVE;
301 subset_new_menu->item[3].kind = MN_ACTION;
303 switch (i = subset_new_menu->check())
306 st_subset::create(subset_new_menu->item[2].input);
307 le_level_subset.load(subset_new_menu->item[2].input);
308 leveleditor_menu->item[3].kind = MN_GOTO;
310 le_world.arrays_free();
311 le_current_level = new Level;
312 if(le_current_level->load(le_level_subset.name.c_str(), le_level) != 0)
318 le_current_level->load_gfx();
319 le_world.activate_bad_guys();
320 subset_new_menu->item[2].change_input("");
321 // FIXME:? show_menu = true;
322 Menu::set_current(leveleditor_menu);
327 else if(Menu::current() == subset_settings_menu)
329 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 )
330 subset_settings_menu->item[5].kind = MN_DEACTIVE;
332 subset_settings_menu->item[5].kind = MN_ACTION;
334 switch (i = subset_settings_menu->check())
337 save_subset_settings_menu();
338 //FIXME:show_menu = true;
339 Menu::set_current(leveleditor_menu);
345 mouse_cursor->draw();
347 printf("done: %i\n", done);
356 ++global_frame_counter;
359 now_time = SDL_GetTicks();
360 if (now_time < last_time + FPS)
361 SDL_Delay(last_time + FPS - now_time); /* delay some time */
372 level_subsets = dsubdirs("/levels", "info");
378 /* level_changed = NO;*/
381 le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
382 le_level_changed = false;
383 le_current_level = NULL;
386 le_mouse_pressed[LEFT] = false;
387 le_mouse_pressed[RIGHT] = false;
389 le_selection = new Surface(datadir + "/images/leveleditor/select.png", USE_ALPHA);
391 select_tilegroup_menu_effect.init(false);
394 le_save_level_bt = new Button("/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
395 le_exit_bt = new Button("/images/icons/exit.png","Exit", SDLK_F6,screen->w-32,32);
396 le_next_level_bt = new Button("/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
397 le_previous_level_bt = new Button("/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
398 le_rubber_bt = new Button("/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
399 le_select_mode_one_bt = new Button ("/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
400 le_select_mode_two_bt = new Button("/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,64);
401 le_test_level_bt = new Button("/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
402 le_settings_bt = new Button("/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
403 le_move_left_bt = new Button("/images/icons/left.png","Move left",SDLK_LEFT,0,0);
404 le_move_right_bt = new Button("/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
405 le_tilegroup_bt = new Button("/images/icons/tilegroup.png","Select Tilegroup", SDLK_F7,screen->w-64,80);
407 le_tilemap_panel = new ButtonPanel(screen->w-64,screen->h-32,32,32);
408 le_tilemap_panel->set_button_size(32,10);
409 le_tilemap_panel->additem(new Button("/images/icons/bkgrd.png","Background",SDLK_F4,0,0),TM_BG);
410 le_tilemap_panel->additem(new Button("/images/icons/intact.png","Interactive",SDLK_F4,0,0),TM_IA);
411 le_tilemap_panel->additem(new Button("/images/icons/frgrd.png","Foreground",SDLK_F4,0,0),TM_FG);
413 leveleditor_menu = new Menu();
414 subset_load_menu = new Menu();
415 subset_new_menu = new Menu();
416 subset_settings_menu = new Menu();
417 level_settings_menu = new Menu();
418 select_tilegroup_menu = new Menu();
420 leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
421 leveleditor_menu->additem(MN_HL,"",0,0);
422 leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0);
423 leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu);
424 leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
425 leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
426 leveleditor_menu->additem(MN_HL,"",0,0);
427 leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0);
429 Menu::set_current(leveleditor_menu);
431 subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
432 subset_load_menu->additem(MN_HL, "", 0, 0);
434 for(i = 0; i < level_subsets.num_items; ++i)
436 subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0);
438 subset_load_menu->additem(MN_HL,"",0,0);
439 subset_load_menu->additem(MN_BACK,"Back",0,0);
441 subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
442 subset_new_menu->additem(MN_HL,"",0,0);
443 subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0);
444 subset_new_menu->additem(MN_ACTION,"Create",0,0);
445 subset_new_menu->additem(MN_HL,"",0,0);
446 subset_new_menu->additem(MN_BACK,"Back",0,0);
448 subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
449 subset_settings_menu->additem(MN_HL,"",0,0);
450 subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0);
451 subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0);
452 subset_settings_menu->additem(MN_HL,"",0,0);
453 subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0);
454 subset_settings_menu->additem(MN_HL,"",0,0);
455 subset_settings_menu->additem(MN_BACK,"Back",0,0);
457 level_settings_menu->arrange_left = true;
458 level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
459 level_settings_menu->additem(MN_HL,"",0,0);
460 level_settings_menu->additem(MN_TEXTFIELD,"Name ",0,0);
461 level_settings_menu->additem(MN_TEXTFIELD,"Author ",0,0);
462 level_settings_menu->additem(MN_STRINGSELECT,"Theme ",0,0);
463 level_settings_menu->additem(MN_STRINGSELECT,"Song ",0,0);
464 level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0);
465 level_settings_menu->additem(MN_NUMFIELD,"Length ",0,0);
466 level_settings_menu->additem(MN_NUMFIELD,"Time ",0,0);
467 level_settings_menu->additem(MN_NUMFIELD,"Gravity",0,0);
468 level_settings_menu->additem(MN_NUMFIELD,"Top Red ",0,0);
469 level_settings_menu->additem(MN_NUMFIELD,"Top Green ",0,0);
470 level_settings_menu->additem(MN_NUMFIELD,"Top Blue ",0,0);
471 level_settings_menu->additem(MN_NUMFIELD,"Bottom Red ",0,0);
472 level_settings_menu->additem(MN_NUMFIELD,"Bottom Green",0,0);
473 level_settings_menu->additem(MN_NUMFIELD,"Bottom Blue",0,0);
474 level_settings_menu->additem(MN_HL,"",0,0);
475 level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0);
477 select_tilegroup_menu->arrange_left = true;
478 select_tilegroup_menu->additem(MN_LABEL,"Select Tilegroup",0,0);
479 select_tilegroup_menu->additem(MN_HL,"",0,0);
480 std::vector<TileGroup>* tilegroups = TileManager::tilegroups();
481 for(std::vector<TileGroup>::iterator it = tilegroups->begin(); it != tilegroups->end(); ++it )
484 select_tilegroup_menu->additem(MN_ACTION,const_cast<char*>((*it).name.c_str()),0,0);
485 tilegroups_map[(*it).name] = new ButtonPanel(screen->w - 64,96, 64, 318);
487 for(std::vector<int>::iterator sit = (*it).tiles.begin(); sit != (*it).tiles.end(); ++sit, ++i)
488 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));
490 select_tilegroup_menu->additem(MN_HL,"",0,0);
492 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
497 void update_level_settings_menu()
502 level_settings_menu->item[2].change_input(le_current_level->name.c_str());
503 level_settings_menu->item[3].change_input(le_current_level->author.c_str());
504 sprintf(str,"%d",le_current_level->width);
506 string_list_copy(level_settings_menu->item[4].list, dsubdirs("images/themes", "solid0.png"));
507 string_list_copy(level_settings_menu->item[5].list, dfiles("music/",NULL, "-fast"));
508 string_list_copy(level_settings_menu->item[6].list, dfiles("images/background",NULL, NULL));
509 string_list_add_item(level_settings_menu->item[6].list,"");
510 if((i = string_list_find(level_settings_menu->item[4].list,le_current_level->theme.c_str())) != -1)
511 level_settings_menu->item[3].list->active_item = i;
512 if((i = string_list_find(level_settings_menu->item[5].list,le_current_level->song_title.c_str())) != -1)
513 level_settings_menu->item[4].list->active_item = i;
514 if((i = string_list_find(level_settings_menu->item[6].list,le_current_level->bkgd_image.c_str())) != -1)
515 level_settings_menu->item[5].list->active_item = i;
517 level_settings_menu->item[7].change_input(str);
518 sprintf(str,"%d",le_current_level->time_left);
519 level_settings_menu->item[8].change_input(str);
520 sprintf(str,"%2.0f",le_current_level->gravity);
521 level_settings_menu->item[9].change_input(str);
522 sprintf(str,"%d",le_current_level->bkgd_top.red);
523 level_settings_menu->item[10].change_input(str);
524 sprintf(str,"%d",le_current_level->bkgd_top.green);
525 level_settings_menu->item[11].change_input(str);
526 sprintf(str,"%d",le_current_level->bkgd_top.blue);
527 level_settings_menu->item[12].change_input(str);
528 sprintf(str,"%d",le_current_level->bkgd_bottom.red);
529 level_settings_menu->item[13].change_input(str);
530 sprintf(str,"%d",le_current_level->bkgd_bottom.green);
531 level_settings_menu->item[14].change_input(str);
532 sprintf(str,"%d",le_current_level->bkgd_bottom.blue);
533 level_settings_menu->item[15].change_input(str);
536 void update_subset_settings_menu()
538 subset_settings_menu->item[2].change_input(le_level_subset.title.c_str());
539 subset_settings_menu->item[3].change_input(le_level_subset.description.c_str());
542 void apply_level_settings_menu()
547 le_current_level->name = level_settings_menu->item[2].input;
548 le_current_level->author = level_settings_menu->item[3].input;
550 if(le_current_level->bkgd_image.compare(string_list_active(level_settings_menu->item[6].list)) != 0)
552 le_current_level->bkgd_image = string_list_active(level_settings_menu->item[6].list);
556 if(le_current_level->theme.compare(string_list_active(level_settings_menu->item[4].list)) != 0)
558 le_current_level->theme = string_list_active(level_settings_menu->item[4].list);
564 le_current_level->free_gfx();
565 le_current_level->load_gfx();
568 le_current_level->song_title = string_list_active(level_settings_menu->item[5].list);
570 le_current_level->change_size(atoi(level_settings_menu->item[7].input));
571 le_current_level->time_left = atoi(level_settings_menu->item[8].input);
572 le_current_level->gravity = atof(level_settings_menu->item[9].input);
573 le_current_level->bkgd_top.red = atoi(level_settings_menu->item[10].input);
574 le_current_level->bkgd_top.green = atoi(level_settings_menu->item[11].input);
575 le_current_level->bkgd_top.blue = atoi(level_settings_menu->item[12].input);
576 le_current_level->bkgd_bottom.red = atoi(level_settings_menu->item[13].input);
577 le_current_level->bkgd_bottom.green = atoi(level_settings_menu->item[14].input);
578 le_current_level->bkgd_bottom.blue = atoi(level_settings_menu->item[15].input);
581 void save_subset_settings_menu()
583 le_level_subset.title = subset_settings_menu->item[2].input;
584 le_level_subset.description = subset_settings_menu->item[3].input;
585 le_level_subset.save();
588 void le_goto_level(int levelnb)
590 le_world.arrays_free();
592 le_current_level->cleanup();
593 if(le_current_level->load(le_level_subset.name.c_str(), levelnb) != 0)
595 le_current_level->load(le_level_subset.name.c_str(), le_level);
604 le_current_level->free_gfx();
605 le_current_level->load_gfx();
607 le_world.activate_bad_guys();
612 /*if(level_changed == true)
613 if(askforsaving() == CANCEL)
616 SDL_EnableKeyRepeat(0, 0); // disables key repeating
619 delete leveleditor_menu;
620 delete subset_load_menu;
621 delete subset_new_menu;
622 delete subset_settings_menu;
623 delete level_settings_menu;
624 delete select_tilegroup_menu;
625 delete le_save_level_bt;
627 delete le_test_level_bt;
628 delete le_next_level_bt;
629 delete le_previous_level_bt;
630 delete le_move_right_bt;
631 delete le_move_left_bt;
633 delete le_select_mode_one_bt;
634 delete le_select_mode_two_bt;
635 delete le_settings_bt;
636 delete le_tilegroup_bt;
637 delete le_tilemap_panel;
639 if(le_current_level != NULL)
641 le_current_level->free_gfx();
642 le_current_level->cleanup();
643 le_world.arrays_free();
647 void le_drawinterface()
652 if(le_current_level != NULL)
654 /* draw a grid (if selected) */
657 for(x = 0; x < 19; x++)
658 fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
659 for(y = 0; y < 15; y++)
660 fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
664 if(le_selection_mode == CURSOR)
665 le_selection->draw( cursor_x - pos_x, cursor_y);
666 else if(le_selection_mode == SQUARE)
669 le_highlight_selection();
670 /* draw current selection */
671 w = selection.x2 - selection.x1;
672 h = selection.y2 - selection.y1;
673 fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
674 fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
675 fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
676 fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
680 /* draw button bar */
681 fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
682 Tile::draw(19 * 32, 14 * 32, le_current_tile);
684 if(TileManager::instance()->get(le_current_tile)->editor_images.size() > 0)
685 TileManager::instance()->get(le_current_tile)->editor_images[0]->draw( 19 * 32, 14 * 32);
687 if(le_current_level != NULL)
689 le_save_level_bt->draw();
691 le_test_level_bt->draw();
692 le_next_level_bt->draw();
693 le_previous_level_bt->draw();
694 le_rubber_bt->draw();
695 le_select_mode_one_bt->draw();
696 le_select_mode_two_bt->draw();
697 le_settings_bt->draw();
698 le_move_right_bt->draw();
699 le_move_left_bt->draw();
700 le_tilegroup_bt->draw();
701 if(!cur_tilegroup.empty())
702 tilegroups_map[cur_tilegroup]->draw();
703 le_tilemap_panel->draw();
705 sprintf(str, "%d/%d", le_level,le_level_subset.levels);
706 white_text->drawf(str, -10, 16, A_RIGHT, A_TOP, 0);
708 white_small_text->draw("F1 for Help", 10, 430, 1);
713 white_small_text->draw("No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
715 white_small_text->draw("No Level Subset loaded", 10, 430, 1);
722 unsigned int y,x,i,s;
725 /* Draw the real background */
726 if(le_current_level->bkgd_image[0] != '\0')
729 le_current_level->img_bkgd->draw_part(s,0,0,0,
730 le_current_level->img_bkgd->w - s - 32, le_current_level->img_bkgd->h);
731 le_current_level->img_bkgd->draw_part(0,0,screen->w - s - 32 ,0,s,
732 le_current_level->img_bkgd->h);
736 drawgradient(le_current_level->bkgd_top, le_current_level->bkgd_bottom);
739 /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
741 for (y = 0; y < 15; ++y)
742 for (x = 0; x < 20; ++x)
745 if(active_tm == TM_BG)
750 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->bg_tiles[y][x + (int)(pos_x / 32)],a);
752 if(active_tm == TM_IA)
757 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->ia_tiles[y][x + (int)(pos_x / 32)],a);
759 if(active_tm == TM_FG)
764 Tile::draw(32*x - fmodf(pos_x, 32), y * 32, le_current_level->fg_tiles[y][x + (int)(pos_x / 32)],a);
766 /* draw whats inside stuff when cursor is selecting those */
767 /* (draw them all the time - is this the right behaviour?) */
768 if(TileManager::instance()->get(le_current_level->ia_tiles[y][x + (int)(pos_x / 32)])->editor_images.size() > 0)
769 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);
773 /* Draw the Bad guys: */
774 for (i = 0; i < le_world.bad_guys.size(); ++i)
776 /* to support frames: img_bsod_left[(frame / 5) % 4] */
779 le_world.bad_guys[i].draw();
783 /* Draw the player: */
784 /* for now, the position is fixed at (100, 240) */
785 tux_right[(global_frame_counter / 5) % 3]->draw( 100 - pos_x, 240);
788 void le_checkevents()
795 keymod = SDL_GetModState();
797 while(SDL_PollEvent(&event))
801 Menu::current()->event(event);
805 mouse_cursor->set_state(MC_NORMAL);
807 /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
808 if(event.type == SDL_KEYDOWN
809 || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION)
810 && (event.motion.x > 0
811 && event.motion.x < screen->w - 64 &&
812 event.motion.y > 0 && event.motion.y < screen->h)))
816 case SDL_KEYDOWN: // key pressed
817 key = event.key.keysym.sym;
822 cursor_x -= KEY_CURSOR_SPEED;
824 cursor_x -= KEY_CURSOR_FASTSPEED;
826 if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
827 pos_x = cursor_x - MOUSE_LEFT_MARGIN;
832 cursor_x += KEY_CURSOR_SPEED;
834 cursor_x += KEY_CURSOR_FASTSPEED;
836 if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
837 pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
842 cursor_y -= KEY_CURSOR_SPEED;
844 cursor_y -= KEY_CURSOR_FASTSPEED;
851 cursor_y += KEY_CURSOR_SPEED;
853 cursor_y += KEY_CURSOR_FASTSPEED;
855 if(cursor_y > screen->h-32)
856 cursor_y = screen->h-32;
869 cursor_x = (le_current_level->width * 32) - 32;
873 le_show_grid = !le_show_grid;
879 case SDL_KEYUP: /* key released */
880 switch(event.key.keysym.sym)
889 case SDL_MOUSEBUTTONDOWN:
890 if(event.button.button == SDL_BUTTON_LEFT)
892 le_mouse_pressed[LEFT] = true;
894 selection.x1 = event.motion.x + pos_x;
895 selection.y1 = event.motion.y;
896 selection.x2 = event.motion.x + pos_x;
897 selection.y2 = event.motion.y;
899 else if(event.button.button == SDL_BUTTON_RIGHT)
901 le_mouse_pressed[RIGHT] = true;
904 case SDL_MOUSEBUTTONUP:
905 if(event.button.button == SDL_BUTTON_LEFT)
906 le_mouse_pressed[LEFT] = false;
907 else if(event.button.button == SDL_BUTTON_RIGHT)
908 le_mouse_pressed[RIGHT] = false;
910 case SDL_MOUSEMOTION:
917 cursor_x = ((int)(pos_x + x) / 32) * 32;
918 cursor_y = ((int) y / 32) * 32;
920 if(le_mouse_pressed[LEFT])
922 selection.x2 = x + pos_x;
926 if(le_mouse_pressed[RIGHT])
928 pos_x += -1 * event.motion.xrel;
932 case SDL_QUIT: // window closed
941 if(le_current_level != NULL)
943 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 &&
944 event.motion.y > 0 && event.motion.y < screen->h)))
946 le_mouse_pressed[LEFT] = false;
947 le_mouse_pressed[RIGHT] = false;
951 /* Check for button events */
952 le_test_level_bt->event(event);
953 if(le_test_level_bt->get_state() == BUTTON_CLICKED)
955 le_save_level_bt->event(event);
956 if(le_save_level_bt->get_state() == BUTTON_CLICKED)
957 le_current_level->save(le_level_subset.name.c_str(),le_level);
958 le_exit_bt->event(event);
959 if(le_exit_bt->get_state() == BUTTON_CLICKED)
961 Menu::set_current(leveleditor_menu);
963 le_next_level_bt->event(event);
964 if(le_next_level_bt->get_state() == BUTTON_CLICKED)
966 if(le_level < le_level_subset.levels)
968 le_goto_level(++le_level);
975 sprintf(str,"Level %d doesn't exist.",le_level+1);
976 white_text->drawf(str,0,-18,A_HMIDDLE,A_VMIDDLE,2);
977 white_text->drawf("Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2);
978 red_text->drawf("(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2);
982 while(SDL_PollEvent(&event))
985 case SDL_KEYDOWN: // key pressed
986 switch(event.key.keysym.sym)
989 new_lev.init_defaults();
990 new_lev.save(le_level_subset.name.c_str(),++le_level);
991 le_level_subset.levels = le_level;
992 le_goto_level(le_level);
1009 le_previous_level_bt->event(event);
1010 if(le_previous_level_bt->get_state() == BUTTON_CLICKED)
1013 le_goto_level(--le_level);
1015 le_rubber_bt->event(event);
1016 if(le_rubber_bt->get_state() == BUTTON_CLICKED)
1017 le_current_tile = 0;
1018 le_select_mode_one_bt->event(event);
1019 if(le_select_mode_one_bt->get_state() == BUTTON_CLICKED)
1020 le_selection_mode = CURSOR;
1021 le_select_mode_two_bt->event(event);
1022 if(le_select_mode_two_bt->get_state() == BUTTON_CLICKED)
1023 le_selection_mode = SQUARE;
1025 le_tilegroup_bt->event(event);
1026 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1028 Menu::set_current(select_tilegroup_menu);
1029 select_tilegroup_menu_effect.start(200);
1030 select_tilegroup_menu->set_pos(screen->w - 64,100,-0.5,0.5);
1033 le_settings_bt->event(event);
1034 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1036 update_level_settings_menu();
1037 Menu::set_current(level_settings_menu);
1039 if(!cur_tilegroup.empty())
1040 if((pbutton = tilegroups_map[cur_tilegroup]->event(event)) != NULL)
1042 if(pbutton->get_state() == BUTTON_CLICKED)
1044 le_current_tile = pbutton->get_tag();
1047 if((pbutton = le_tilemap_panel->event(event)) != NULL)
1049 if(pbutton->get_state() == BUTTON_CLICKED)
1051 active_tm = static_cast<TileMapType>(pbutton->get_tag());
1057 le_settings_bt->event(event);
1058 if(le_settings_bt->get_state() == BUTTON_CLICKED)
1060 Menu::set_current(0);
1062 le_tilegroup_bt->event(event);
1063 if(le_tilegroup_bt->get_state() == BUTTON_CLICKED)
1065 Menu::set_current(0);
1070 if(!Menu::current())
1072 le_move_left_bt->event(event);
1073 le_move_right_bt->event(event);
1075 if(le_mouse_pressed[LEFT])
1077 le_change(cursor_x, cursor_y, active_tm, le_current_tile);
1082 if(!Menu::current())
1084 if(le_move_left_bt->get_state() == BUTTON_PRESSED)
1088 else if(le_move_left_bt->get_state() == BUTTON_HOVER)
1093 if(le_move_right_bt->get_state() == BUTTON_PRESSED)
1097 else if(le_move_right_bt->get_state() == BUTTON_HOVER)
1105 void le_highlight_selection()
1109 if(selection.x1 < selection.x2)
1119 if(selection.y1 < selection.y2)
1135 fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1138 void le_change(float x, float y, int tm, unsigned int c)
1140 if(le_current_level != NULL)
1146 /* level_changed = true; */
1148 switch(le_selection_mode)
1151 le_current_level->change(x,y,tm,c);
1156 /* if there is a bad guy over there, remove it */
1157 for(i = 0; i < le_world.bad_guys.size(); ++i)
1158 if(xx == le_world.bad_guys[i].base.x/32 && yy == le_world.bad_guys[i].base.y/32)
1159 le_world.bad_guys.erase(le_world.bad_guys.begin() + i);
1161 if(c == '0') /* if it's a bad guy */
1162 le_world.add_bad_guy(xx*32, yy*32, BAD_BSOD);
1164 le_world.add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1166 le_world.add_bad_guy(xx*32, yy*32, BAD_MONEY);
1170 if(selection.x1 < selection.x2)
1180 if(selection.y1 < selection.y2)
1196 /* if there is a bad guy over there, remove it */
1197 for(i = 0; i < le_world.bad_guys.size(); ++i)
1198 if(le_world.bad_guys[i].base.x/32 >= x1 && le_world.bad_guys[i].base.x/32 <= x2
1199 && le_world.bad_guys[i].base.y/32 >= y1 && le_world.bad_guys[i].base.y/32 <= y2)
1200 le_world.bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(&le_world.bad_guys[i]));
1202 for(xx = x1; xx <= x2; xx++)
1203 for(yy = y1; yy <= y2; yy++)
1205 le_current_level->change(xx*32, yy*32, tm, c);
1207 if(c == '0') // if it's a bad guy
1208 le_world.add_bad_guy(xx*32, yy*32, BAD_BSOD);
1210 le_world.add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1212 le_world.add_bad_guy(xx*32, yy*32, BAD_MONEY);
1223 le_current_level->save("test", le_level);
1225 GameSession session("test",le_level, ST_GL_TEST);
1228 Menu::set_current(leveleditor_menu);
1229 le_world.arrays_free();
1230 le_current_level->load_gfx();
1231 le_world.activate_bad_guys();
1237 unsigned int i, done_;
1239 " - This is SuperTux's built-in level editor -",
1240 "It has been designed to be light and easy to use from the start.",
1242 "When you first load the level editor you are given a menu where you",
1243 "can load level subsets, create a new level subset, edit the current",
1244 "subset's settings, or simply quit the editor. You can access this menu",
1245 "from the level editor at any time by pressing the escape key.",
1247 "To your right is your button bar. The center of this contains many",
1248 "tiles you can use to make your level. To select a tile, click on it",
1249 "with your left mouse button; your selection will be shown in the",
1250 "bottom right corner of the button box. Click anywhere on your level",
1251 "with the left mouse button to place that tile down. If you right click",
1252 "a tile in the button bar, you can find out what its keyboard shortcut",
1253 "is. The three buttons FGD, BGD and EMY let you pick from foreground,",
1254 "background, and enemy tiles. The eraser lets you remove tiles.",
1255 "The left and right arrow keys scroll back and forth through your level.",
1256 "The button with the wrench and screwdriver, lets you change the",
1257 "settings of your level, including how long it is or what music it will",
1258 "play. When you are ready to give your level a test, click on the little",
1259 "running Tux. If you like the changes you have made to your level,",
1260 "press the red save key to keep them.",
1261 "To change which level in your subset you are editing, press the white",
1262 "up and down arrow keys at the top of the button box.",
1264 "Have fun making levels! If you make some good ones, send them to us on",
1265 "the SuperTux mailing list!",
1270 blue_text->drawf("- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1272 for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1273 white_small_text->draw(text[i], 5, 80+(i*white_small_text->h), 1);
1275 gold_text->drawf("Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
1283 done_ = wait_for_event(event);