2020年9月12日星期六

95A 《零基礎入門學習Python》筆記 第095講:Pygame:飛機大戰6 上

     《零基礎入門學習Python》筆記      第095講:Pygame:飛機大戰6

今天繼續飛機大戰的開發,遊戲每30秒就隨機下放一個補給包,可能是超級子彈或者全屏炸彈。
補給包有自己的圖片(如下圖),也有自己的運行軌跡(由上而下)
因此,我們可以單獨寫一個模塊來實現:命名為supply
  1. #supply.py
  2. import pygame
  3. from random import *
  4. class Bullet_Supply(pygame.sprite.Sprite):
  5. def __init__(self, bg_size):
  6. pygame.sprite.Sprite.__init__(self)
  7. self.image = pygame.image.load("images/bullet_supply.png").convert_alpha()
  8. self.rect = self.image.get_rect()
  9. self.width, self.height = bg_size[0], bg_size[1]
  10. self.rect.left, self.rect.bottom = \
  11. randint(0, self.width - self.rect.width), -100 #水平方向随机,垂直方向-100
  12. self.speed = 5
  13. self.active = False
  14. self.mask = pygame.mask.from_surface(self.image)
  15. def move(self):
  16. if self.rect.top < self.height:
  17. self.rect.top += self.speed
  18. else:
  19. self.active = False
  20. def reset(self):
  21. self.active = True
  22. self.rect.left, self.rect.bottom = \
  23. randint(0, self.width - self.rect.width), -100
  24. class Bomb_Supply(pygame.sprite.Sprite):
  25. def __init__(self, bg_size):
  26. pygame.sprite.Sprite.__init__(self)
  27. self.image = pygame.image.load("images/bomb_supply.png").convert_alpha()
  28. self.rect = self.image.get_rect()
  29. self.width, self.height = bg_size[0], bg_size[1]
  30. self.rect.left, self.rect.bottom = \
  31. randint(0, self.width - self.rect.width), -100
  32. self.speed = 5
  33. self.active = False
  34. self.mask = pygame.mask.from_surface(self.image)
  35. def move(self):
  36. if self.rect.top < self.height:
  37. self.rect.top += self.speed
  38. else:
  39. self.active = False
  40. def reset(self):
  41. self.active = True
  42. self.rect.left, self.rect.bottom = \
  43. randint(0, self.width - self.rect.width), -100
接下來我們在main 模塊中實現這個補給包:
實例化補給包並這只補給包發放定時器,定時器每30秒觸發一次。
  1. # 每30秒发放一个补给包
  2. bullet_supply = supply.Bullet_Supply(bg_size)
  3. bomb_supply = supply.Bomb_Supply(bg_size)
  4. SUPPLY_TIME = USEREVENT
  5. pygame.time.set_timer(SUPPLY_TIME, 30 * 1000)
  1. #响应补给包事件
  2. elif event.type == SUPPLY_TIME:
  3. supply_sound.play()
  4. if choice([True, False]):
  5. bomb_supply.reset()
  6. else:
  7. bullet_supply.reset()
  1. # 绘制全屏炸弹补给并检测是否获得
  2. if bomb_supply.active:
  3. bomb_supply.move()
  4. screen.blit(bomb_supply.image, bomb_supply.rect)
  5. if pygame.sprite.collide_mask(bomb_supply, me):
  6. get_bomb_sound.play()
  7. if bomb_num < 3:
  8. bomb_num += 1
  9. bomb_supply.active = False
  10. # 绘制超级子弹补给并检测是否获得
  11. if bullet_supply.active:
  12. bullet_supply.move()
  13. screen.blit(bullet_supply.image, bullet_supply.rect)
  14. if pygame.sprite.collide_mask(bullet_supply, me):
  15. get_bullet_sound.play()
  16. #发射超级子弹
  17. bullet_supply.active = False
接下來有個細節問題,就是遊戲運行起來之後,當我們按暫停時,背景音樂還存在,而且還會聽到補給發放的聲音,因為補給發放是在事件觸發那裡寫的,而暫停管的是下面的主邏輯部分,這就導致了一個問題,因為用戶暫停,是希望遊戲真正的安靜下來。
  1. elif event.type == MOUSEBUTTONDOWN:
  2. if event.button == 1 and paused_rect.collidepoint(event.pos):
  3. paused = not paused
  4. if paused:
  5. pygame.time.set_timer(SUPPLY_TIME, 0)
  6. pygame.mixer.music.pause()
  7. pygame.mixer.pause()
  8. else:
  9. pygame.time.set_timer(SUPPLY_TIME, 30 * 1000)
  10. pygame.mixer.music.unpause()
  11. pygame.mixer.unpause()
好了,接下來我們來講講超級子彈,當我們接收到超級子彈補給的時候,子彈由原來的單髮變成了雙發,子彈的速度相對也會提高一些。
我們先在bullet 模塊中添加一個Bullet2 類
  1. class Bullet2(pygame.sprite.Sprite):
  2. def __init__(self, position):
  3. pygame.sprite.Sprite.__init__(self)
  4. self.image = pygame.image.load("images/bullet2.png").convert_alpha()
  5. self.rect = self.image.get_rect()
  6. self.rect.left, self.rect.top = position
  7. self.speed = 14
  8. self.active = False
  9. self.mask = pygame.mask.from_surface(self.image)
  10. def move(self):
  11. self.rect.top -= self.speed
  12. if self.rect.top < 0:
  13. self.active = False
  14. def reset(self, position):
  15. self.rect.left, self.rect.top = position
  16. self.active = True
超級子彈的使用時長為18秒,過了這個時間,就自動變為普通子彈。
因此我們需要一個超級子彈的定時器,另外,我們還需要一個變量來表示子彈的類型。
  1. # 超级子弹定时器
  2. DOUBLE_BULLET_TIME = USEREVENT + 1
  3. # 标志是否使用超级子弹
  4. is_double_bullet = False
然後生成超級子彈
  1. # 生成超级子弹
  2. bullet2 = []
  3. bullet2_index = 0
  4. BULLET2_NUM = 8
  5. for i in range(BULLET2_NUM//2):
  6. bullet2.append(bullet.Bullet2((me.rect.centerx-33, me.rect.centery)))
  7. bullet2.append(bullet.Bullet2((me.rect.centerx+30, me.rect.centery)))
然後響應事件
  1. #响应超级子弹事件
  2. elif event.type == DOUBLE_BULLET_TIME:
  3. is_double_bullet = False
  4. pygame.time.set_timer(DOUBLE_BULLET_TIME, 0)
  1. # 绘制超级子弹补给并检测是否获得
  2. if bullet_supply.active:
  3. bullet_supply.move()
  4. screen.blit(bullet_supply.image, bullet_supply.rect)
  5. if pygame.sprite.collide_mask(bullet_supply, me):
  6. get_bullet_sound.play()
  7. #发射超级子弹18秒
  8. is_double_bullet = True
  9. pygame.time.set_timer(DOUBLE_BULLET_TIME, 18 * 1000)
  10. bullet_supply.active = False
然後修改發射子彈部分
  1. # 发射子弹
  2. if not(delay % 10):
  3. bullet_sound.play()
  4. if is_double_bullet:
  5. bullets = bullet2
  6. bullets[bullet2_index].reset((me.rect.centerx-33, me.rect.centery))
  7. bullets[bullet2_index+1].reset((me.rect.centerx+30, me.rect.centery))
  8. bullet2_index = (bullet2_index + 2) % BULLET2_NUM
  9. else:
  10. bullets = bullet1
  11. bullets[bullet1_index].reset(me.rect.midtop)
  12. bullet1_index = (bullet1_index + 1) % BULLET1_NUM

0 留言:

發佈留言