2015年2月22日 星期日

pygtk cairo動畫(續)執行續,不同物件中信號傳遞

這是一個用move_object.py就完成的,一個不起眼的小遊戲,當然有興趣改一改,可做成其他遊戲,按這下載原碼
執行速度尚可,再來是想讓move_object.py這模組執行更順,才會具續下一步,寫這只是純好玩的,有興趣可拿來修改,參考都很歡迎




move_object.py,用選擇性參數,初始化物件,x=None,y=None,_RECEVER_COLLISION_=None,_RECEVER_MOVE_=None,這4參數可給,可不給,跟java多重建構子功能一樣
,最後_RECEVER_COLLISION_=None,_RECEVER_MOVE_=None,這2參數採用不具方式,用來設定方法,讓使用者在主程式實做,前面是碰撞發送,後者是移動發送,若2者都不給,就是非碰撞物,不做信號實做
    #建構式,用來初始化物件
    def __init__(self,main_obj,frame,darea,image_path,x=None,y=None,_RECEVER_COLLISION_=None,_RECEVER_MOVE_=None):

來看這2參數實際運作,下面getattr(self.main_obj,self.RECEVER_MOVE)(self),呼叫主程式self.main_obj的不具名方法,把本身當參數(self)
主程式,產生move_object物件時把"SEND_move_bullet"當參數,因此_RECEVER_MOVE_就是SEND_move_bullet,此時move_object.py不具名方法就是SEND_move_bullet,就變成self.main_obj.SEND_move_bullet(self),所以主程式就必須實做SEND_move_bullet這個方法(如下面狀況)
主程式
...............................
move_bullet=move_object.move_object(self,self.framme1,self.darea,p,x,y,None,"SEND_move_bullet")

...................
def SEND_move_bullet(self,move_object):
...........................

move_object.py程式


##############################碰撞時透過thread發送信號,把本身和碰撞物當參數,否則送出本身##        
    def SEND_MOVE_SIGNAL(self):
        d="RECEVER"
        if(self.check_yes):
            if(self.is_check_move):#判斷是否要實作移動發送
             #self.main_obj.RECEVER_MOVE(self)
             getattr(self.main_obj,self.RECEVER_MOVE)(self)

###############和其他是否碰撞,若碰撞回傳True,否則False###################################
    def check_collision(self,other_obj):
                  ...................................

          if(self.check_collision_p(xo,yo,xo1,yo1,xs,ys,xs1,ys1)):
              if(self.is_collision_check):
               #在這實作碰撞發送,若碰撞,送出本身和被撞物
               getattr(self.main_obj,self.RECEVER_COLLISION)(self,other_obj)
                           .............................

本遊戲中機台,子彈,飛碟,是碰撞物,因此要實做碰撞或移動發送,也可2者皆做,這裡我才用機台,和子彈是作移動發送,飛碟是作碰撞發送,如下,只要使用move_object這模組,就可完成不同動畫了


    #畫出機台
    def draw_body(self):
          if(len(self.move_list_body)<1 br="">            p="body.png"
            w,h=self.get_frame_w_h()
            #最後2個參數不給,給None代表不作碰撞接收,但作移動發送SEND_move_body,0,0是要產生的位置,也可用set_move_to_xy放到想要位置
            self.move_body=move_object.move_object(self,self.framme1,self.darea,p,w/2-20,h-60,None,"SEND_move_body")
            self.move_list_body.append(self.move_body)
    #畫出子彈
    def draw_bullet(self):        #if key == gtk.keysyms.Right:self.generate()
     if(len(self.move_list_bullet)<6 and="" len="" self.move_list_body="">0):
          p="bullet.png"
          #最後2個參數實作接收移動發送,收移動發送後碰撞檢查
          w,h=self.move_body.get_width_height()[0]/2,self.move_body.get_width_height()[1]
          x,y=self.move_body.get_xy()[0]+w,self.move_body.get_xy()[1]-h
          move_bullet=move_object.move_object(self,self.framme1,self.darea,p,x,y,None,"SEND_move_bullet")
          move_bullet.set_move_type("直線向上")
          move_bullet.set_move_speed(0.005)
          move_bullet.set_explosion_png("boom2.png")
          self.move_list_bullet.append(move_bullet)
          #加到列表list      
  


    #畫出隨機飛碟
    def generate(self):
          p="logo"+str(random.randint(1,5))+".png"
          #最後2個參數實作接收移動發送後碰撞檢查RECEVER_collision和None不作移動發送,代表check碰撞,不給座標None,None,位置會隨機產生
          move_fly=move_object.move_object(self,self.framme1,self.darea,p,None,None,"RECEVER_collision_fly",None)
          speed=float(random.randint(1,100))/100
          move_fly.set_move_speed(speed)
          if(random.randint(1,100) >50 ):
              move_fly.set_move_type("亂數")
          else:
              move_fly.set_move_type("直線X")
          #加到列表list
          self.move_list_fly.append(move_fly)


然後下面實做SEND_move_body,SEND_move_body移動發送,RECEVER_collision_fly碰撞接收,機台單純發送移動,送給move_list_signal做逐一送給飛碟做碰撞檢查,子彈打到最上方就從list移走並爆炸,否則送給move_list_signal做逐一送給飛碟做碰撞檢查,當飛碟檢查到碰撞發生時,RECEVER_collision_fly會收到信號,做碰撞後的後續處理,讓它爆炸,從list移走,增加分數,等等後續處理


##########################################移動發送,碰撞接收實作######################################################
    #接收移動動畫信號,移動物移動時會收到信號,送到move_list_signal作檢查,參數為移動物
    def SEND_move_body(self,move_object):

        #接到移動物,送過來信號,送給move_list_signal逐一檢查碰撞
      
        self.move_list_signal.check_collision(move_object,self.move_list_fly)
    #接收移動動畫信號,移動物移動時會收到信號,送到move_list_signal作檢查,參數為移動物
    def SEND_move_bullet(self,move_object):
        #print(move_object.get_xy()[1])
        #接到移動物,送過來信號,超過視窗上方就移走bullet,否則,送給move_list_signal逐一檢查碰撞
        if(move_object.get_xy()[1]<0-move_object .get_xy="" br="">            #True打到最上面會爆炸,設False到最上面不會爆炸
            if(move_object in self.move_list_bullet):self.move_list_signal.kill_move_obj(move_object,True,self.move_list_bullet)
        else:          
            self.move_list_signal.check_collision(move_object,self.move_list_fly)
    #接收移動物和碰撞物,碰撞時會收到信號,參數為移動物和碰撞物送給move_list_signal移走移動物,和碰撞物
    #飛碟是作碰撞,第一個參數傳本身,第2個參數傳實作移動,發送的是機台或子彈
    def RECEVER_collision_fly(self,c_object,move_object):
        #print(c_object.get_name())
        #更改了爆炸圖片,大隻飛碟爆炸不同
        if(c_object.get_name()=="logo4.png"):c_object.set_explosion_png("boom1.png")
      
        #self.move_body=None
        #從list中移走移動物,和碰撞物,True代表產生爆炸畫面,若不要爆炸畫面設False,注意是那個list移走,否則不會爆炸
        self.move_list_signal.kill_move_obj(c_object,True,self.move_list_fly)
        if(move_object in self.move_list_body):
            self.move_list_signal.kill_move_obj(move_object,True,self.move_list_body)
            self.GAME_OVER()
            self.score=0
        if(move_object in self.move_list_bullet):
            #設子彈爆炸不一樣,畫面較逼真
            #move_object.set_explosion_png("boom2.png")
            self.move_list_signal.kill_move_obj(move_object,True,self.move_list_bullet)
            self.score=self.score+1
            self.show_score()
            if(self.score>self.score_high):self.score_high=self.score#不要在執行續中呼叫

沒有留言: