#!/opt/bin/perl use strict; use Glib; use Gtk2 -init; use SDL; use SDL::App; use SDL::Event; use SDL::Surface; use SDL::OpenGL; use SDL::OpenGL::Constants; use Crossfire; use Crossfire::Client; use Crossfire::Protocol; use Client::Util; our $VERSION = '0.1'; our $CFG; our $CONN; our $SDL_TIMER; our $SDL_APP; our $SDL_EV = new SDL::Event; our %SDL_CB; sub init_screen { # nuke all gl context data $SDL_APP = new SDL::App -flags => SDL_ANYFORMAT | SDL_HWSURFACE, -title => "Crossfire+ Client", -width => $CFG->{width}, -height => $CFG->{height}, -opengl => 1, -red_size => 8, -green_size => 8, -blue_size => 8, -double_buffer => 1, -fullscreen => $CFG->{fullscreen}, -resizeable => 0; glEnable GL_TEXTURE_2D; glTexEnv GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE; glShadeModel GL_FLAT; glDisable GL_DEPTH_TEST; glBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA; glEnable GL_BLEND; glMatrixMode GL_PROJECTION; glLoadIdentity; glOrtho 0, $CFG->{width} / 32, $CFG->{height} / 32, 0, -1 , 1; # re-bind all textures } sub start_game { $SDL_TIMER = add Glib::Timeout 1000/20, sub { while ($SDL_EV->poll) { ($SDL_CB{$SDL_EV->type} || sub { warn "unhandled event ", $SDL_EV->type })->(); } 1 }; init_screen; $CONN = new conn host => $CFG->{host}, port => $CFG->{port}; } sub stop_game { remove Glib::Source $SDL_TIMER; undef $SDL_APP; SDL::Quit; } sub refresh { glClearColor 0, 0, 0, 0; glClear GL_COLOR_BUFFER_BIT; my $map = $CONN->{map}; for my $x (0 .. $CONN->{mapw} - 1) { for my $y (0 .. $CONN->{maph} - 1) { my $cell = $map->[$x][$y] or next; my $darkness = $cell->[3] * (1 / 255); glColor $darkness, $darkness, $darkness; for my $num (grep $_, $cell->[0], $cell->[1], $cell->[2]) { my $tex = $CONN->{face}[$num]{texture} || 0; glBindTexture GL_TEXTURE_2D, $tex; glBegin GL_QUADS; glTexCoord 0, 0; glVertex $x, $y; glTexCoord 0, 1; glVertex $x, $y + 1; glTexCoord 1, 1; glVertex $x + 1, $y + 1; glTexCoord 1, 0; glVertex $x + 1, $y; glEnd; } } } SDL::GLSwapBuffers; } %SDL_CB = ( SDL_QUIT() => sub { warn "sdl quit\n";#d# exit; }, SDL_VIDEORESIZE() => sub { }, SDL_VIDEOEXPOSE() => sub { refresh; }, SDL_KEYDOWN() => sub { }, SDL_KEYUP() => sub { }, SDL_MOUSEMOTION() => sub { warn "sdl motion\n";#d# }, SDL_MOUSEBUTTONDOWN() => sub { }, SDL_MOUSEBUTTONUP() => sub { }, SDL_ACTIVEEVENT() => sub { warn "active\n";#d# }, ); @conn::ISA = Crossfire::Protocol::; sub conn::map_update { my ($self, $dirty) = @_; refresh; } sub conn::map_scroll { my ($self, $dx, $dy) = @_; refresh; } sub conn::map_clear { my ($self) = @_; refresh; } sub conn::face_update { my ($self, $num, $face) = @_; my $pb = new Gtk2::Gdk::PixbufLoader; $pb->write ($face->{image}); $pb->close; $pb = $pb->get_pixbuf; $pb = $pb->add_alpha (0, 0, 0, 0); glGetError(); my ($tex) = @{glGenTextures 1}; $face->{texture} = $tex; glBindTexture GL_TEXTURE_2D, $tex; my $glerr=glGetError(); die "a: ".gluErrorString($glerr)."\n" if $glerr; glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR; glTexParameter GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR;#_MIPMAP_LINEAR; glTexParameter GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP; glTexParameter GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP; glTexImage2D GL_TEXTURE_2D, 0, GL_RGBA8, $pb->get_width, $pb->get_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, $pb->get_pixels; my $glerr=glGetError(); die "Problem setting up 2d Texture (dimensions not a power of 2?)):".gluErrorString($glerr)."\n" if $glerr; } ############################################################################# Client::Util::read_cfg "$Crossfire::VARDIR/pclientrc"; $CFG ||= { width => 640, height => 480, fullscreen => 0, host => "crossfire.schmorp.de", port => 13327, }; Client::Util::run_config_dialog; main Gtk2;