Games-FrozenBubble

 view release on metacpan or  search on metacpan

bin/frozen-bubble  view on Meta::CPAN

    };

    my %latestangle = ();  #- for smoothing, need to handle last angle only

    while (@$msg) {
        my $m = shift @$msg;
        my $player = $pdata{id2p}{$m->{id}};
        if (!$player) {
            printf "Network protocol error: player with id '%d' doesn't exist. You're not a regular Frozen-Bubble client, aren't you?\n", ord($m->{id});
            die 'quit';
        }
        if ($pdata{$player}{left}) {
            print STDERR "$pdata{$player}{nick}: you don't exist (anymore), go away!\n";
            next;
        }
        my ($command, $params) = $m->{msg} =~ /^(.)(.*)/;
        dbgnet("message received: from=$player message=$m->{msg}");
        if ($command eq 'l') {
            iter_players { #- need iter_players to get the small graphics change for free
                if ($::p eq $player) {
                    $pdata{$::p}{left} = 1;
                    $pdata{$::p}{still_game_messages} = 0;
                    lose($::p);
                }
            };
        } elsif ($command eq 'f') {
            $check_action_possible->($m, $player) or last;
            $actions{$player}{mp_fire} = 1;
            ($angle{$player}, $pdata{$player}{nextcolor}) = $params =~ /(.+):(.+)/;
        } elsif ($command eq 'r') {
            $actions{$player}{left} = 0;
            $actions{$player}{right} = 0;
            $actions{$player}{center} = 0;
            if ($params eq 'l') {
                $actions{$player}{left} = 1;
            } elsif ($params eq 'r') {
                $actions{$player}{right} = 1;
            } elsif ($params eq 'c') {
                $actions{$player}{center} = 1;
            }
        } elsif ($command eq 'a') {
            $latestangle{$player} = $params;
        } elsif ($command eq 's') {
            $check_action_possible->($m, $player) or last;
            #- we can't rely on locally animated launched bubble, to ensure game
            #- consistency we transmit stick positions
            $actions{$player}{mp_stick} = 1;
            ($pdata{$player}{stickcx}, $pdata{$player}{stickcy}, $pdata{$player}{stickcol}, my $newrootcols) = $params =~ /(.+):(.+):(.+):(.*)/;
            @{$pdata{$player}{nextcolors}} = split / /, $newrootcols;
        } elsif ($command eq 'g') {
            my ($destplayer, $numb) = $params =~ /(.+):(.+)/;
            iter_players {
                if ($pdata{$::p}{nick} eq $destplayer) {
                    update_malus(\&remove_image_from_background, $::p);
                    push @{$pdata{$::p}{malus}}, ($frame) x $numb;
                    update_malus(\&put_image_to_background, $::p);
                }
            };
        } elsif ($command eq 'm') {
            #- we may receive new malus bubbles after a distant player is dead already
            #- ignore them instead of wrongly overlaying frozen bubbles
            if ($pdata{$player}{state} eq 'ingame') {
                my ($num, $cx, $cy, $sticky) = $params =~ /(.+):(.+):(.+):(.+)/;
                my $b = create_bubble_given_img_num($num);
                $b->{cx} = $cx;
                $b->{cy} = $cy;
                $b->{'stick_y'} = $sticky;
                iter_players { #- need iter_players to get the small graphics change for free
                    if ($::p eq $player) {
                        calc_real_pos($b, $::p);
                        push @{$malus_bubble{$player}}, $b;
                        malus_change(-1, $player);
                    }
                };
            }
        } elsif ($command eq 'M') {
            my ($cx, $sticky) = $params =~ /(.+):(.+)/;
            #- if network cuts several malussticks in two parts, it's possible that
            #- one malusstick from the first part trigger a lose; at next game run,
            #- the player has lost and his malus bubbles were cleaned up, so malusstick
            #- is not possible, but this is no big deal
            if ($pdata{$player}{state} eq 'ingame') {
                foreach (@{$malus_bubble{$player}}) {
                    if ($_->{cx} == $cx && $_->{'stick_y'} == $sticky) {
                        $_->{mp_stick} = 1;
                        goto ok_malusstick;
                    }
                }
                die "could not find malus bubble to malusstick!\n";
              ok_malusstick:
            }
        } elsif ($command eq 'F') {
            #- this is coming too soon. it needs to be collected in the algo to restart a game.
            unshift @$msg, $m;
            last;
        } elsif ($command eq 't') {
            $pdata{current_chat_messages}{$player} = $params;
            $pdata{$player}{chat_msg_delay} = 500;
            play_sound('chatted');
            redraw_chat_message_if_needed($player);
            push @update_rects, $apprects{main};
        } elsif ($command eq 'A') {
            if ($params eq '') {
                @{$pdata{attackingme}} = difference2($pdata{attackingme}, [ $player ]);
            } else {
                if ($params eq $pdata{p1}{nick}) {
                    if (!member($player, @{$pdata{attackingme}})) {
                        push @{$pdata{attackingme}}, $player;
                    }
                } else {
                    @{$pdata{attackingme}} = difference2($pdata{attackingme}, [ $player ]);
                }
            }
            redraw_attackingme();
        } else {
            print STDERR "****** Unrecognized command: $m->{msg}\n";
        }
    }

    foreach my $player (keys %latestangle) {
        #- try to smoothen on network lag

bin/frozen-bubble  view on Meta::CPAN

                       });
                my $xb;
                my $yb;
                my $r;
                $set_next_position->();
              find_ok_position:
                while (1) {
                    $xb = $xc - $wb/2;
                    $yb = $yc - $hb/2;
                    #- check that background rectangle does not overlap any existing rectangle (spots or other labels)
                    $r = SDL::Rect->new($xb, $yb, $wb, $hb);
                    foreach my $rect (@rectangles) {
                        if ($rect->x >= $xb && $wb > $rect->x - $xb
                            || $xb >= $rect->x && $rect->w > $xb - $rect->x) {
                            #- x overlap
                            if ($rect->y >= $yb && $hb > $rect->y - $yb
                                || $yb >= $rect->y && $rect->h > $yb - $rect->y) {
                                $set_next_position->();
                                while ($xb < 20 || $xb + $wb > 620 || $yb < 20 || $yb + $hb > 320) {
                                    $set_next_position->();
                                    if ($index_positions > 100) {
                                        #- abandon, map is crowded
                                        return;
                                    }
                                }
                                if ($index_positions > 100) {
                                    #- abandon, map is crowded
                                    return;
                                }
                                next find_ok_position;
                            }
                        }
                    }
                    last;
                }
                #- draw a line between the spot and the center of the label
                Games::FrozenBubble::CStuff::draw_line($app, $xspot, $yspot, $xc, $yc, $label_line_color);
                #- draw the label background and the label in another pass to handle overwriting of labels over lines
                push @labels, { x => $xc - $sizing->[2]/2 - $sizing->[0], y => $yc - $sizing->[3]/2 - $sizing->[1], text => $text, backrect1 => $r,
                                backrect2 => SDL::Rect->new($xb + 1, $yb + 1, $wb - 2, $hb - 2) };
                push @rectangles, $r;
            }
        } \@wholist, \@free_geolocs;

        foreach (@labels) {
                SDL::Video::fill_rect($app, $_->{backrect1}, $label_outer_color);
                SDL::Video::fill_rect($app, $_->{backrect2}, $label_background_color);
            print_('netdialogs_servermsg', $app, $_->{x}, $_->{y}, $_->{text});
        }

        #- actions (chat, joins, create)
        my $y = $smg_starty;
        foreach my $action (@actions) {
            if ($action->{selected}) {
                put_image($imgbin{highlight_server}, 6, $y-1);
            }
            print_($action->{readonly} ? 'netdialogs_servermsg' : 'netdialogs', $app, $smg_startx, $y, $action->{name}, 520);
            $y += $smg_lineheight;
        }

        #- selfspot will need to properly erase selection overlay
        if ($mylatitude && !$private) {
            save_back_spot($mylatitude, $mylongitude, $imgbin{netspot_self}[0], \$back_selfspot);
            if ($index_selfspot >= 0) {
                print_spot($mylatitude, $mylongitude, 'free', $imgbin{netspot_self}[$index_selfspot], \$back_selfspot);
            }
        }

        #- chat entry
        erase_line($smg_starty_chat, $imgbin{back_netgame});
        if ($curaction->() && $curaction->()->{action} eq 'CHAT') {
            callback_entry('print', { xpos => $smg_startx, ypos => $smg_starty_chat, maxlen => 520, prefix => loc("Say: "), font => 'netdialogs' });
        }

        #- available players in server, or list of players in game
        erase_line($smg_starty_players, $imgbin{back_netgame});
        if ($ingame) {
            print_('netdialogs', $app, $smg_startx, $smg_starty_players, loc("Players in game: %s", $players_in_game), 520);
        } else {
            print_('netdialogs', $app, $smg_startx, $smg_starty_players, loc("Available Players: %s", i18n_number($free_players)), 520);
        }

        #- status messages
        smg_printstatus();
    };
    my $print_selfspot = sub {
        if ($mylatitude && !$private) {
            $index_selfspot >= 0 and print_spot($mylatitude, $mylongitude, 'free', $imgbin{netspot_self}[$index_selfspot], \$back_selfspot);
            $index_selfspot++;
            if ($index_selfspot == @{$imgbin{netspot_self}}) {
                my ($x, $y) = get_spot_location($mylatitude, $mylongitude);
                put_image($back_selfspot, $x - 10, $y - 10);
                $index_selfspot = -15;
            }
        }
    };

    my $myoldnick;
    my $list = sub {
        my ($firsttime) = @_;
        $state eq 'game_select' or return;
        my @games;
        my @old_wholist = @wholist;
        eval {
            ($free_players, undef, my $freenicks, undef, my $playing_geolocs, @games) = Games::FrozenBubble::Net::list();
            @wholist = ();
            @free_geolocs = ();
            @playing_geolocs = ();
            foreach (split ',', $freenicks) {
                my ($nick, undef, $latitude, $longitude) = $_ =~ /([^:]+)(:([^:]+):([^:]+))?/;
                push @wholist, $nick;
                if (defined($latitude) && $latitude =~ /^-?\d+\.?\d*$/ && $longitude =~ /^-?\d+\.?\d*$/) {
                    push @free_geolocs, [ $latitude, $longitude ];
                } else {
                    push @free_geolocs, [];
                }
            }
            foreach (split ',', $playing_geolocs) {
                my ($latitude, $longitude) = $_ =~ /([^:]+):([^:]+)/;
                $latitude =~ /^-?\d+\.?\d*$/ && $longitude =~ /^-?\d+\.?\d*$/ and push @playing_geolocs, [ $latitude, $longitude ];
            }



( run in 1.209 second using v1.01-cache-2.11-cpan-140bd7fdf52 )