… | |
… | |
3 | use strict; |
3 | use strict; |
4 | use utf8; |
4 | use utf8; |
5 | |
5 | |
6 | use Time::HiRes 'time'; |
6 | use Time::HiRes 'time'; |
7 | use Event; |
7 | use Event; |
8 | |
|
|
9 | use SDL::Event; |
|
|
10 | |
|
|
11 | use SDL::Mixer; |
|
|
12 | use SDL::Sound; |
|
|
13 | use SDL::Music; |
|
|
14 | |
|
|
15 | use SDL::OpenGL; |
|
|
16 | |
8 | |
17 | use Crossfire; |
9 | use Crossfire; |
18 | use Crossfire::Protocol; |
10 | use Crossfire::Protocol; |
19 | |
11 | |
20 | use Compress::LZF; |
12 | use Compress::LZF; |
… | |
… | |
55 | our $METASERVER; |
47 | our $METASERVER; |
56 | |
48 | |
57 | our $GAUGES; |
49 | our $GAUGES; |
58 | |
50 | |
59 | our $SDL_ACTIVE; |
51 | our $SDL_ACTIVE; |
60 | our $SDL_EV; |
|
|
61 | our %SDL_CB; |
52 | our %SDL_CB; |
62 | |
53 | |
63 | our $SDL_MIXER; |
54 | our $SDL_MIXER; |
64 | our @SOUNDS; # event => file mapping |
55 | our @SOUNDS; # event => file mapping |
65 | our %AUDIO_CHUNKS; # audio files |
56 | our %AUDIO_CHUNKS; # audio files |
… | |
… | |
185 | $table->add (0, 10, new CFClient::UI::Label valign => 0, align => 1, text => "Background Music"); |
176 | $table->add (0, 10, new CFClient::UI::Label valign => 0, align => 1, text => "Background Music"); |
186 | $table->add (1, 10, my $hbox = new CFClient::UI::HBox); |
177 | $table->add (1, 10, my $hbox = new CFClient::UI::HBox); |
187 | $hbox->add (new CFClient::UI::CheckBox expand => 1, state => $CFG->{bgm_enable}, connect_changed => sub { |
178 | $hbox->add (new CFClient::UI::CheckBox expand => 1, state => $CFG->{bgm_enable}, connect_changed => sub { |
188 | $CFG->{bgm_enable} = $_[1]; |
179 | $CFG->{bgm_enable} = $_[1]; |
189 | }); |
180 | }); |
190 | $hbox->add (new CFClient::UI::Slider expand => 1, range => [$CFG->{bgm_volume}, 0, 128, 1], connect_changed => sub { |
181 | $hbox->add (new CFClient::UI::Slider expand => 1, range => [$CFG->{bgm_volume}, 0, 1, 0.1], connect_changed => sub { |
191 | $CFG->{bgm_volume} = $_[1]; |
182 | $CFG->{bgm_volume} = $_[1]; |
192 | $SDL_MIXER->music_volume ($_[1]); |
183 | CFClient::MixMusic::volume $_[1] * 128; |
193 | }); |
184 | }); |
194 | |
185 | |
195 | $table->add (1, 11, new CFClient::UI::Button expand => 1, align => 0, text => "Apply", connect_activate => sub { |
186 | $table->add (1, 11, new CFClient::UI::Button expand => 1, align => 0, text => "Apply", connect_activate => sub { |
196 | audio_shutdown (); |
187 | audio_shutdown (); |
197 | audio_init (); |
188 | audio_init (); |
… | |
… | |
399 | $FAST = $CFG->{fast}; |
390 | $FAST = $CFG->{fast}; |
400 | |
391 | |
401 | CFClient::SDL_SetVideoMode $WIDTH, $HEIGHT, $FULLSCREEN |
392 | CFClient::SDL_SetVideoMode $WIDTH, $HEIGHT, $FULLSCREEN |
402 | or die "SDL_SetVideoMode failed!\n"; |
393 | or die "SDL_SetVideoMode failed!\n"; |
403 | |
394 | |
404 | $SDL_EV = new SDL::Event; |
|
|
405 | $SDL_EV->set_unicode (1); |
|
|
406 | |
|
|
407 | $SDL_ACTIVE = 1; |
395 | $SDL_ACTIVE = 1; |
408 | |
396 | |
409 | $LAST_REFRESH = time - 0.01; |
397 | $LAST_REFRESH = time - 0.01; |
410 | |
398 | |
411 | CFClient::gl_init; |
399 | CFClient::gl_init; |
… | |
… | |
470 | } |
458 | } |
471 | |
459 | |
472 | sub video_shutdown { |
460 | sub video_shutdown { |
473 | $CFClient::UI::ROOT->{children} = []; |
461 | $CFClient::UI::ROOT->{children} = []; |
474 | undef $SDL_ACTIVE; |
462 | undef $SDL_ACTIVE; |
475 | undef $SDL_EV; |
|
|
476 | } |
463 | } |
477 | |
464 | |
478 | my $bgmusic;#TODO#hack#d# |
465 | my $bgmusic;#TODO#hack#d# |
479 | |
466 | |
480 | sub audio_init { |
467 | sub audio_init { |
481 | if ($CFG->{audio_enable}) { |
468 | if ($CFG->{audio_enable}) { |
482 | if (open my $fh, "<:utf8", CFClient::find_rcfile "sounds/config") { |
469 | if (open my $fh, "<:utf8", CFClient::find_rcfile "sounds/config") { |
483 | |
470 | |
484 | $SDL_MIXER = new SDL::Mixer |
471 | $SDL_MIXER = !CFClient::Mix_OpenAudio; |
485 | -rate => 22050, |
472 | CFClient::Mix_AllocateChannels 8; |
486 | -channels => 1, # mono |
473 | CFClient::MixMusic::volume $CFG->{bgm_volume} * 128; |
487 | -size => 512; |
|
|
488 | |
|
|
489 | $SDL_MIXER->allocate_channels (8); |
|
|
490 | |
474 | |
491 | # TODO: hack, do play loop and mood music |
475 | # TODO: hack, do play loop and mood music |
492 | if ($CFG->{bgm_enable}) { |
476 | if ($CFG->{bgm_enable}) { |
493 | $bgmusic = new SDL::Music CFClient::find_rcfile "music/game3.ogg"; |
477 | $bgmusic = new_from_file CFClient::MixMusic CFClient::find_rcfile "music/game3.ogg"; |
494 | $SDL_MIXER->play_music ($bgmusic, -1); |
478 | $bgmusic->play; |
495 | $SDL_MIXER->music_volume ($CFG->{bgm_volume}); |
|
|
496 | } |
479 | } |
497 | |
480 | |
498 | while (<$fh>) { |
481 | while (<$fh>) { |
499 | next if /^\s*#/; |
482 | next if /^\s*#/; |
500 | next if /^\s*$/; |
483 | next if /^\s*$/; |
… | |
… | |
502 | my ($file, $volume, $event) = split /\s+/, $_, 3; |
485 | my ($file, $volume, $event) = split /\s+/, $_, 3; |
503 | |
486 | |
504 | push @SOUNDS, "$volume,$file"; |
487 | push @SOUNDS, "$volume,$file"; |
505 | |
488 | |
506 | $AUDIO_CHUNKS{"$volume,$file"} ||= do { |
489 | $AUDIO_CHUNKS{"$volume,$file"} ||= do { |
507 | my $chunk = new SDL::Sound CFClient::find_rcfile "sounds/$file"; |
490 | my $chunk = new_from_file CFClient::MixChunk CFClient::find_rcfile "sounds/$file"; |
508 | $chunk->volume ($volume * 128 / 100); |
491 | $chunk->volume ($volume * 128 / 100); |
509 | $chunk |
492 | $chunk |
510 | }; |
493 | }; |
511 | } |
494 | } |
512 | } else { |
495 | } else { |
… | |
… | |
514 | } |
497 | } |
515 | } |
498 | } |
516 | } |
499 | } |
517 | |
500 | |
518 | sub audio_shutdown { |
501 | sub audio_shutdown { |
|
|
502 | CFClient::Mix_CloseAudio if $SDL_MIXER; |
519 | undef $SDL_MIXER; |
503 | undef $SDL_MIXER; |
520 | @SOUNDS = (); |
504 | @SOUNDS = (); |
521 | %AUDIO_CHUNKS = (); |
505 | %AUDIO_CHUNKS = (); |
522 | } |
506 | } |
523 | |
507 | |
… | |
… | |
536 | $want_refresh = 0; |
520 | $want_refresh = 0; |
537 | $can_refresh = 0; |
521 | $can_refresh = 0; |
538 | |
522 | |
539 | $CFClient::UI::ROOT->draw; |
523 | $CFClient::UI::ROOT->draw; |
540 | |
524 | |
541 | SDL::GLSwapBuffers; |
525 | CFClient::SDL_GL_SwapBuffers; |
542 | |
526 | |
543 | $LAST_REFRESH = $NOW; |
527 | $LAST_REFRESH = $NOW; |
544 | } |
528 | } |
545 | |
529 | |
546 | my $refresh_watcher = Event->timer (after => 0, hard => 1, interval => 1 / $MAX_FPS, cb => sub { |
530 | my $refresh_watcher = Event->timer (after => 0, hard => 1, interval => 1 / $MAX_FPS, cb => sub { |
547 | $NOW = time; |
531 | $NOW = time; |
548 | |
532 | |
549 | ($SDL_CB{$SDL_EV->type} || sub { warn "unhandled event ", $SDL_EV->type })->() |
533 | ($SDL_CB{$_->{type}} || sub { warn "unhandled event $_->{type}" })->($_) |
550 | while $SDL_EV->poll; |
534 | for CFClient::SDL_PollEvent; |
551 | |
535 | |
552 | if (%animate_object) { |
536 | if (%animate_object) { |
553 | $_->animate ($LAST_REFRESH - $NOW) for values %animate_object; |
537 | $_->animate ($LAST_REFRESH - $NOW) for values %animate_object; |
554 | $want_refresh++; |
538 | $want_refresh++; |
555 | } |
539 | } |
… | |
… | |
778 | or return; |
762 | or return; |
779 | |
763 | |
780 | my $chunk = $AUDIO_CHUNKS{$SOUNDS[$soundnum]} |
764 | my $chunk = $AUDIO_CHUNKS{$SOUNDS[$soundnum]} |
781 | or return; |
765 | or return; |
782 | |
766 | |
783 | $SDL_MIXER->play_channel (-1, $chunk); |
767 | $chunk->play; |
784 | # warn "sound $x,$y,$soundnum,$type\n";#d# |
768 | # warn "sound $x,$y,$soundnum,$type\n";#d# |
785 | } |
769 | } |
786 | |
770 | |
787 | sub conn::query { |
771 | sub conn::query { |
788 | my ($self, $flags, $prompt) = @_; |
772 | my ($self, $flags, $prompt) = @_; |
… | |
… | |
845 | }, |
829 | }, |
846 | CFClient::SDL_VIDEOEXPOSE => sub { |
830 | CFClient::SDL_VIDEOEXPOSE => sub { |
847 | refresh; |
831 | refresh; |
848 | }, |
832 | }, |
849 | CFClient::SDL_KEYDOWN => sub { |
833 | CFClient::SDL_KEYDOWN => sub { |
850 | if ($SDL_EV->key_mod & CFClient::KMOD_ALT && $SDL_EV->key_sym == 13) { |
834 | if ($_[0]{mod} & CFClient::KMOD_ALT && $_[0]{sym} == 13) { |
851 | # alt-enter |
835 | # alt-enter |
852 | video_shutdown; |
836 | video_shutdown; |
853 | $CFG->{fullscreen} = !$CFG->{fullscreen}; |
837 | $CFG->{fullscreen} = !$CFG->{fullscreen}; |
854 | video_init; |
838 | video_init; |
855 | } else { |
839 | } else { |
856 | CFClient::UI::feed_sdl_key_down_event ($SDL_EV); |
840 | CFClient::UI::feed_sdl_key_down_event ($_[0]); |
857 | } |
841 | } |
858 | }, |
842 | }, |
859 | CFClient::SDL_KEYUP => sub { |
843 | CFClient::SDL_KEYUP => sub { |
860 | CFClient::UI::feed_sdl_key_up_event ($SDL_EV); |
844 | CFClient::UI::feed_sdl_key_up_event ($_[0]); |
861 | }, |
845 | }, |
862 | CFClient::SDL_MOUSEMOTION => sub { |
846 | CFClient::SDL_MOUSEMOTION => sub { |
863 | CFClient::UI::feed_sdl_motion_event ($SDL_EV); |
847 | CFClient::UI::feed_sdl_motion_event ($_[0]); |
864 | }, |
848 | }, |
865 | CFClient::SDL_MOUSEBUTTONDOWN => sub { |
849 | CFClient::SDL_MOUSEBUTTONDOWN => sub { |
866 | CFClient::UI::feed_sdl_button_down_event ($SDL_EV); |
850 | CFClient::UI::feed_sdl_button_down_event ($_[0]); |
867 | }, |
851 | }, |
868 | CFClient::SDL_MOUSEBUTTONUP => sub { |
852 | CFClient::SDL_MOUSEBUTTONUP => sub { |
869 | CFClient::UI::feed_sdl_button_up_event ($SDL_EV); |
853 | CFClient::UI::feed_sdl_button_up_event ($_[0]); |
870 | }, |
854 | }, |
871 | CFClient::SDL_ACTIVEEVENT => sub { |
855 | CFClient::SDL_ACTIVEEVENT => sub { |
872 | # printf "active %x %x\n", $SDL_EV->active_gain, $SDL_EV->active_state;#d# |
856 | # printf "active %x %x\n", $SDL_EV->active_gain, $SDL_EV->active_state;#d# |
873 | }, |
857 | }, |
874 | ); |
858 | ); |
… | |
… | |
896 | mapsize => 100, |
880 | mapsize => 100, |
897 | host => "crossfire.schmorp.de", |
881 | host => "crossfire.schmorp.de", |
898 | say_command => 'say', |
882 | say_command => 'say', |
899 | audio_enable => 1, |
883 | audio_enable => 1, |
900 | bgm_enable => 1, |
884 | bgm_enable => 1, |
901 | bgm_volume => 64, |
885 | bgm_volume => 0.25, |
902 | ); |
886 | ); |
903 | |
887 | |
904 | while (my ($k, $v) = each %DEF_CFG) { |
888 | while (my ($k, $v) = each %DEF_CFG) { |
905 | $CFG->{$k} = $v unless exists $CFG->{$k}; |
889 | $CFG->{$k} = $v unless exists $CFG->{$k}; |
906 | } |
890 | } |
… | |
… | |
925 | video_init; |
909 | video_init; |
926 | audio_init; |
910 | audio_init; |
927 | |
911 | |
928 | Event::loop; |
912 | Event::loop; |
929 | |
913 | |
930 | END { SDL::Quit } |
914 | END { CFClient::SDL_Quit } |
931 | |
915 | |
932 | |
916 | |