class Main::MultiMap::Map

Constants

Empty
Hit
Local
Missed
Remote
Wasted

Public Class Methods

new(main,map_type,nx,ny) click to toggle source
Calls superclass method
# File bin/tactical_fighter, line 201
def initialize(main,map_type,nx,ny)
        @nx=nx
        @ny=ny
        @main=main
        @map_type=map_type
        @shoot_fifo=Array.new
        @block_size=20
        @line_width=(@block_size/7).to_i
        @planes=Array.new
        @plane_count=(0.03*@nx*@ny).to_i
        @plane_count.times{|i| @planes.push(Plane.new(@nx,@ny))} if local?
        super()
        set_visible_window(false)
        add(@widget=Gtk::Fixed.new)
        set_size_request(@nx*@block_size,@ny*@block_size)
        @map=Hash.new
        for i in 1 .. @nx
                @map[i]=Hash.new
                for j in 1 .. @ny
                        @map[i][j]=Empty
                end
        end
        @widget.signal_connect('size-allocate'){|me,allocation|
                @block_size=(me.allocation.width-1)/@nx
                yblock_size=(me.allocation.height-1)/@ny
                @block_size=yblock_size if yblock_size<@block_size
                @line_width=(@block_size/7).to_i
                @xroot=me.allocation.x+(me.allocation.width-@nx*@block_size-1)/2
                @yroot=me.allocation.y+(me.allocation.height-@ny*@block_size-1)/2
        }
        @widget.signal_connect('expose-event'){|me,ev|
                cr=me.window.create_cairo_context
                #grid
                cr.set_source_rgb(0.8,0.8,0.8)
                cr.set_line_width(1)
                cr.set_line_cap(Cairo::LineCap::ROUND)
                for i in 0 .. @nx
                        for j in 0 .. @ny
                                cr.move_to(@xroot+i*@block_size,@yroot)
                                cr.line_to(@xroot+i*@block_size,@yroot+@ny*@block_size)
                                cr.move_to(@xroot,@yroot+j*@block_size)
                                cr.line_to(@xroot+@nx*@block_size,@yroot+j*@block_size)
                        end
                end
                cr.stroke
                cr.set_source_rgb(0.3,0.3,0.3)
                cr.rectangle(@xroot,@yroot,@nx*@block_size,@ny*@block_size)
                cr.stroke
                all_set?#invalidate planes
                #planes
                @planes.each{|plane| plane.draw(cr,@xroot,@yroot,@block_size)}
                for i in 1 .. @nx do
                        for j in 1 .. @ny do
                                if (cnt=count_plane_on_coordinates?(i,j))>1
                                        plane=first_plane_on_coordinates?(i,j)
                      cr.set_source_rgba(1.0*(cnt-1)/(@plane_count-1), if plane.ready? then 1 else 0 end, 1-1.0*(cnt-1)/(@plane_count-1),0.2)
                      cr.rectangle(@xroot+(i-1)*@block_size+1,@yroot+(j-1)*@block_size+1,@block_size-2,@block_size-2)
                                        cr.fill
                                end
                                #battle-map
                                case @map[i][j]
                                        when Hit then 
                                                cr.set_source_rgb(1,0,0)
                                                cr.set_line_width(@line_width)
                                                cr.set_line_cap(Cairo::LineCap::ROUND)
                                                cr.move_to(@xroot+(i-1)*@block_size+@line_width*2,@yroot+(j-1)*@block_size+@line_width*2)
                                                cr.line_to(@xroot+i*@block_size-@line_width*2,@yroot+j*@block_size-@line_width*2)
                                                cr.move_to(@xroot+i*@block_size-@line_width*2,@yroot+(j-1)*@block_size+@line_width*2)
                                                cr.line_to(@xroot+(i-1)*@block_size+@line_width*2,@yroot+j*@block_size-@line_width*2)
                                                cr.stroke
                                        when Missed then
                                                cr.set_source_rgb(0,1,0)
                                                cr.set_line_width(@line_width)
                                                cr.set_line_cap(Cairo::LineCap::ROUND)
                                                cr.arc(@xroot+(i-0.5)*@block_size, @yroot+(j-0.5)*@block_size, @block_size/3, 0, Math::PI*2)
                                                cr.stroke
                                        when Wasted then
                                                cr.set_source_rgb(1,0,0)
                                                cr.set_line_width(@line_width)
                                                cr.set_line_cap(Cairo::LineCap::ROUND)
                                                cr.arc(@xroot+(i-0.5)*@block_size, @yroot+(j-0.5)*@block_size, @block_size/3, 0 , Math::PI*2)
                                                cr.move_to(@xroot+(i-1)*@block_size+@line_width*2,@yroot+(j-1)*@block_size+@line_width*2)
                                                cr.line_to(@xroot+i*@block_size-@line_width*2,@yroot+j*@block_size-@line_width*2)
                                                cr.move_to(@xroot+i*@block_size-@line_width*2,@yroot+(j-1)*@block_size+@line_width*2)
                                                cr.line_to(@xroot+(i-1)*@block_size+@line_width*2,@yroot+j*@block_size-@line_width*2)
                                                cr.stroke
                                end
                        end
                end
                cr.stroke
                #draw the shoot_fifo
                @shoot_fifo.each_index{|ind|
                        @shoot_fifo[ind]
                        layout=cr.create_pango_layout
                        layout.text=(ind+1).to_s
                        layout.set_width(@block_size * Pango::SCALE).set_alignment(Pango::Layout::ALIGN_CENTER)
                        layout.set_font_description(Pango::FontDescription.new("Sans #{(@block_size*0.6).to_i}"))
                        cr.update_pango_layout(layout)
                        cr.move_to(@xroot+@block_size*(@shoot_fifo[ind][0]-1),@yroot+@block_size*(@shoot_fifo[ind][1]-1))
                        cr.set_source_rgba(0.9,0.1,0.1,0.5)
                        cr.show_pango_layout(layout)
                        cr.stroke
                }
                #draw round transparent charts on the map, the waste a smaller inside
                waste_ratio,hit_ratio = hit_counter

                r=@block_size-1
                xc=@xroot+@block_size
                yc=@yroot+@ny*@block_size-@block_size
                cr.set_line_width(1)
                cr.set_source_rgba(0,2,0,0.1)
                cr.move_to(xc,yc)
                cr.arc(xc,yc,r,0,Math::PI*2)
                cr.move_to(xc,yc)
                cr.fill
                cr.stroke
                if hit_ratio>0
                        cr.set_source_rgba(1,0,0,0.1)
                        cr.move_to(xc,yc)
                        cr.line_to(xc+r,yc)
                        cr.arc(xc,yc,r,0,Math::PI*2*hit_ratio)
                        cr.line_to(xc,yc)
                        cr.close_path
                        cr.fill
                        cr.stroke
                end

                r=@block_size/2-1
                xc=@xroot+@block_size
                yc=@yroot+@ny*@block_size-@block_size
                cr.set_line_width(1)
                cr.set_source_rgba(0,2,0,0.3)
                cr.move_to(xc,yc)
                cr.arc(xc,yc,r,0,Math::PI*2)
                cr.move_to(xc,yc)
                cr.fill
                cr.stroke
                if waste_ratio>0
                        cr.set_source_rgba(1,0,0,0.3)
                        cr.move_to(xc,yc)
                        cr.line_to(xc+r,yc)
                        cr.arc(xc,yc,r,0,Math::PI*2*waste_ratio)
                        cr.line_to(xc,yc)
                        cr.close_path
                        cr.fill
                        cr.stroke
                end


                #message
                message=nil
                if local?
                        message="Prepare the planes".lng if @main.place?
                        message="You Lost".lng if @main.lost?
                        message="" if @main.won?
                end
                if remote?
                        message="Shoot".lng  if @main.shoot?
                        message="Wait".lng if @main.wait?
                        message="You Won".lng if @main.won?
                        message="" if @main.lost?
                end

                unless message.nil?
                        layout=cr.create_pango_layout
                        layout.text=message
                        layout.set_width(@block_size*@nx/2 * Pango::SCALE)
                        font_size=@block_size
                        layout.set_font_description(Pango::FontDescription.new("Sans #{font_size}"))
                        cr.update_pango_layout(layout)
                        while layout.size[0]/Pango::SCALE>@block_size*@nx do
                                font_size-=1
                                layout.set_font_description(Pango::FontDescription.new("Sans #{font_size}"))
                                cr.update_pango_layout(layout)
                        end
                        cr.move_to(@xroot+(@block_size*@nx-layout.size[0]/Pango::SCALE)/2,@yroot+(@block_size*@ny-layout.size[1]/Pango::SCALE)/2)
                        cr.set_source_rgba(1,1,0,0.6)
                        cr.show_pango_layout(layout)
                        cr.stroke
                end
                true
        }
        signal_connect('button-press-event'){|me,ev|
                if ev.button == 1
                        if local? && @main.place?
                                #start moving plane
                                @xshift=((ev.x-@xroot)/@block_size).to_i+1
                                @yshift=((ev.y-@yroot)/@block_size).to_i+1
                                @dragged=false
                        end
                        if remote?
                                x=((me.allocation.x+ev.x-@xroot)/@block_size).to_i+1
                                y=((me.allocation.y+ev.y-@yroot)/@block_size).to_i+1
                                if 1<=x && x<=@nx && 1<=y && y<=@ny && @map[x][y] == Empty
                                        if @main.shoot?
                                                #shoot the enemy
                                                set_cell_state(x,y,@main.shoot_enemy(x,y))
                                                @main.wait unless @main.ended?
                                        elsif @main.wait?
                                                if @shoot_fifo.include?([x,y])
                                                        #remove from the fifo if already there
                                                        @shoot_fifo.delete([x,y])
                                                        redraw_map
                                                        else
                                                        #add to shoot fifo
                                                        @shoot_fifo.push([x,y])
                                                        redraw_cell(x,y)
                                                end
                                        end
                                end
                        end
                end
                if ev.button == 3
                        if local? && @main.place?
                                #make plane ready
                                if ev.event_type == Gdk::Event::BUTTON2_PRESS
                                        #double-right-click validate all planes
                                        @planes.each{|pl| pl.validate}
                                        redraw_map
                                        @main.ready if all_set?
                                else
                                        if plane=first_head_on_coordinates?(((ev.x-@xroot)/@block_size).to_i+1,((ev.y-@yroot)/@block_size).to_i+1)
                                                if plane.ready? then plane.invalidate else plane.validate end
                                                redraw_map
                                                @main.ready if all_set?
                                        end
                                end
                        end
                        if remote?
                                #rotate guessed enemy plane
                                x=((me.allocation.x+ev.x-@xroot)/@block_size).to_i+1
                                y=((me.allocation.y+ev.y-@yroot)/@block_size).to_i+1
                                if @map[x][y] == Wasted
                                        if plane=first_head_on_coordinates?(x,y)
                                                plane.rotate_cw(true)
                                                @planes.each{|plane| plane.validate}
                                                redraw_map
                                        end
                                end
                        end
                end
        }
        signal_connect('button-release-event'){|me,ev|
                if ev.button == 1 
                        if local? && @main.place? && !@xshift.nil? && !@yshift.nil?
                                #rotate plane
                                x=((ev.x-@xroot)/@block_size).to_i+1
                                y=((ev.y-@yroot)/@block_size).to_i+1
                                plane=first_head_on_coordinates?(@xshift,@yshift)
                                if !plane.nil? && !@dragged && !plane.ready?
                                        plane.rotate_cw
                                        redraw_map #also invalidate planes if needed
                                end
                                @xshift=nil
                                @yshift=nil
                        end
                end
        }
        signal_connect('motion-notify-event'){|me,ev|
                if local? && @main.place? && !@xshift.nil? && !@yshift.nil?
                        #move plane
                        if plane=first_head_on_coordinates?(@xshift,@yshift)
                                x=((ev.x-@xroot)/@block_size).to_i+1
                                y=((ev.y-@yroot)/@block_size).to_i+1
                                if (x!=@xshift || y!=@yshift) && !plane.ready?
                                        @xshift,@yshift=plane.move_to(x,y)
                                        if plane.head?(x,y)
                                                @dragged=true
                                                redraw_map
                                        end
                                end
                        end
                end
        }
end

Public Instance Methods

all_set?() click to toggle source
# File bin/tactical_fighter, line 511
def all_set?
        cnt=0
                for i in 1 .. @nx
                        for j in 1 .. @ny
                                if count_plane_on_coordinates?(i,j)>1
                                        first_plane_on_coordinates?(i,j).invalidate
                                        cnt+=1
                                end
                        end
                end
        good=cnt == 0
        @planes.each{|plane| good=false unless plane.ready?}
        good
end
all_wasted?() click to toggle source
# File bin/tactical_fighter, line 549
def all_wasted?
        waste_cnt=0
                for i in 1 .. @nx
                        for j in 1 .. @ny
                                waste_cnt+=1 if @map[i][j] == Wasted
                        end
                end
        waste_cnt == @plane_count
end
count_plane_on_coordinates?(x,y) click to toggle source
# File bin/tactical_fighter, line 496
def count_plane_on_coordinates?(x,y)
        cnt=0
        @planes.each{|plane| cnt+=1 if plane.on_coordinates?(x,y)}
        cnt
end
fifo_shoot() click to toggle source
# File bin/tactical_fighter, line 488
def fifo_shoot
        if @main.shoot? && coo=@shoot_fifo[0]
                #shoot the enemy from fifo
                set_cell_state(coo[0],coo[1],@main.shoot_enemy(coo[0],coo[1]))
                @shoot_fifo.delete_at(0)
                @main.wait unless @main.ended?
        end
end
first_head_on_coordinates?(x,y) click to toggle source
# File bin/tactical_fighter, line 506
def first_head_on_coordinates?(x,y)
        pl=nil
        @planes.each{|plane| pl=plane if plane.head?(x,y) && pl.nil?}
        pl
end
first_plane_on_coordinates?(x,y) click to toggle source
# File bin/tactical_fighter, line 501
def first_plane_on_coordinates?(x,y)
        pl=nil
        @planes.each{|plane| pl=plane if plane.on_coordinates?(x,y) && pl.nil?}
        pl
end
hit?(x,y) click to toggle source
# File bin/tactical_fighter, line 525
def hit?(x,y)
        cell_state=set_cell_state(x,y,if first_head_on_coordinates?(x,y)
                Wasted
                elsif first_plane_on_coordinates?(x,y)
                                Hit
                                else
                                Missed
                        end
        )
        @main.lost if all_wasted?
        cell_state
end
hit_counter() click to toggle source
# File bin/tactical_fighter, line 558
def hit_counter
        waste_cnt=0
        hit_cnt=0
        miss_cnt=0
                for i in 1 .. @nx
                        for j in 1 .. @ny
                                waste_cnt+=1 if @map[i][j] == Wasted
                                hit_cnt+=1 if @map[i][j] == Hit
                                miss_cnt+=1 if @map[i][j] == Missed
                        end
                end
        return (waste_cnt.to_f/ @plane_count.to_f),hit_cnt.to_f/(hit_cnt.to_f+miss_cnt.to_f)
        
end
local?() click to toggle source
# File bin/tactical_fighter, line 482
def local?
        @map_type == Local
end
redraw_cell(x,y) click to toggle source
# File bin/tactical_fighter, line 479
def redraw_cell(x,y)
        @widget.window.invalidate(Gdk::Rectangle.new(@xroot+@block_size*(x-1),@yroot+@block_size*(y-1),@block_size,@block_size),false)
end
redraw_map() click to toggle source
# File bin/tactical_fighter, line 476
def redraw_map
        @widget.window.invalidate(Gdk::Rectangle.new(@widget.allocation.x,@widget.allocation.y,@widget.allocation.width,@widget.allocation.height),false)
end
remote?() click to toggle source
# File bin/tactical_fighter, line 485
def remote?
        @map_type == Remote
end
set_cell_state(x,y,state) click to toggle source
# File bin/tactical_fighter, line 537
                        def set_cell_state(x,y,state)
                                @map[x][y]=state
                                xwg=@xroot+x*@block_size
                                ywg=@xroot+y*@block_size
#                               redraw_map
#                               #@widget.window.invalidate(Gdk::Rectangle.new(xwg+1,ywg+1,@block_size-2,@block_size-2),false)
                                if remote? && state==Wasted
                                        @planes.push(pp=Plane.new(@nx,@ny))
                                        pp.keep_on_map_by_rotate_only(x,y)
                                end
                                state
                        end