python 《從入門到實踐》第十三章接球

python3    編譯器 pycharm

man.py

import pygame
from pygame.sprite import Sprite

class Mans(Sprite):
   def __init__(self,screen):
      super(Mans, self).__init__()
      self.screen=screen
      self.image_ori=pygame.image.load(r'images\man.jpg')
      self.image=pygame.transform.smoothscale(self.image_ori,(40,60))
      self.rect=self.image.get_rect()
      self.screen_rect=self.screen.get_rect()
      self.rect.centerx=self.screen_rect.centerx
      self.rect.bottom=self.screen_rect.bottom
      self.moving_right=False
      self.moving_left=False
      self.x=float(self.rect.centerx)

   def blitme(self):
      self.screen.blit(self.image,self.rect)


   def update(self):
      if self.moving_right and self.rect.right<=self.screen_rect.right:
         self.x+=0.5
      if self.moving_left and self.rect.left>0:
         self.x-=0.5
      self.rect.x=self.x
class Settings():
   def __init__(self):
      self.bg_color=(230,230,230)
      self.caption='ball game'
      self.available_times=3
      self.game_active=True

ball.py

import pygame
from random import randint
from pygame.sprite import Sprite

class Balls(Sprite):
   def __init__(self,screen):
      super(Balls, self).__init__()
      self.screen=screen
      self.image_ori=pygame.image.load(r'images\ball.jpg')
      self.image=pygame.transform.smoothscale(self.image_ori,(30,30))
      self.screen_rect=self.screen.get_rect()
      self.rect=self.image.get_rect()
      self.rect.top=self.screen_rect.top
      self.left=self.rect.width
      self.right=self.screen_rect.width-self.rect.width
      self.rect.centerx=randint(self.left,self.right)
      self.y=float(self.rect.y)

   def blitme(self):
      self.screen.blit(self.image,self.rect)
   def update(self):
      self.y+=0.2
      self.rect.y=self.y

get_fun.py

import sys
import pygame
from pygame.sprite import Sprite
from ball import Balls


def check_keydown_event(event,man):
      if event.key==pygame.K_RIGHT:
         man.moving_right=True
      elif event.key==pygame.K_LEFT:
         man.moving_left=True

def check_keyup_event(event,man):
      if event.key==pygame.K_RIGHT:
         man.moving_right=False
      elif event.key==pygame.K_LEFT:
         man.moving_left=False

def check_event(man):
   for event in pygame.event.get():
      if event.type == pygame.QUIT:
         sys.exit()
      elif event.type==pygame.KEYDOWN:
         check_keydown_event(event, man)
      elif event.type==pygame.KEYUP:
         check_keyup_event(event,man)

def update_ball(ball,human,screen,ai_settings):
      ball.update()
      collisions=pygame.sprite.groupcollide(human,ball,False,True)
      for b in ball.copy():
         if b.rect.top>=b.screen_rect.bottom:
            ball.remove(b)
            ai_settings.available_times-=1
      if ai_settings.available_times==0:
         ai_settings.game_active=False
      if len(ball)==0 :
         b=Balls(screen)
         ball.add(b)


def update_screen(screen,man,ball,bg_color):
   screen.fill(bg_color)
   ball.draw(screen)
   man.blitme()
   pygame.display.flip()

catch.py

import pygame
from man import Mans
from ball import Balls
import get_fun as gf
from pygame.sprite import Group
from settings import Settings


def catch():
   pygame.init()
   screen=pygame.display.set_mode((400,600))
   ai_settings=Settings()
   pygame.display.set_caption(ai_settings.caption)
   man=Mans(screen)
   ball=Balls(screen)
   balls=Group()
   balls.add(ball)
   human=Group()
   human.add(man)
   while True:
      gf.check_event(man)
      if ai_settings.game_active:
         gf.update_ball(balls,human,screen,ai_settings)
         human.update()
      gf.update_screen(screen,man,balls,ai_settings.bg_color)
catch()

這個程序可以完整的模擬出接球、球消失的情形併產生新的球,並對接不到球三次進行處理。

但在編程過程中,遇到了幾個問題。

一、是對balls和human這兩個Group的調用,讓他們移動的函數名只能設置爲update,如過換成其他函數名,就會報錯。

如將human.py裏的update函數改爲move,主函數裏同樣修改,報錯如下:

AttributeError: 'Group' object has no attribute 'move'

原因未知,求指教。

二、是處理三次借不到球的計算。

該問題的處理是在get_fun.py的update_ball中完成的,該函數最初設計的樣子如下

def update_ball(ball,human,screen,ai_settings):
      ball.update()
      collisions=pygame.sprite.groupcollide(human,ball,False,True)
      touch=False
      for b in ball.sprites():
         if b.rect.top>b.screen_rect.bottom:
            touch=True
            ai_settings.available_times-=1
         else:touch=False
      if ai_settings.available_times==0:
         ai_settings.game_active=False
      if len(ball)==0 or touch:
         b=Balls(screen)
         ball.add(b)

這裏本意是用一個bool來控制到達底邊的情況,但是由於,沒有將原來的Ball中的ball刪去,因此這個程序運行了一次球掉到底端後,Ball中會有兩個精靈,造成第二個球掉下來的時候,還有一個球在bottom以下,因此在第二個球掉了一個像素之後,ai_settings.available_times就減到0了。要注意刪除無用的精靈。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章