《零基礎入門學習Python》筆記 第093講:Pygame:飛機大戰4
現在處於敵強我弱的局面:敵人很多,我只要一個,無處可逃。我們就需要武器來反抗:
定義子彈:
子彈有兩種:一種是一次只發射一顆,一種是補給發放的超級子彈,一次可以射2顆子彈。子彈的運動軌跡是直線向上的,速度要略快於飛機的速度,子彈如果超出屏幕範圍的話,我們就重新繪製子彈,飛機在哪裡,子彈就重新繪製在哪裡,擊中敵機的時候,子彈也是需要重新繪製的。因此,我們給子彈添加一個active 屬性,來判斷子彈是否需要重新繪製,我們單獨定義一個bullet 模塊。
-
#bullet.py
-
import pygame
-
-
class Bullet1(pygame.sprite.Sprite):#普通子弹,一次一发
-
def __init__(self, position):
-
pygame.sprite.Sprite.__init__(self)
-
-
self.image = pygame.image.load("images/bullet1.png").convert_alpha()
-
self.rect = self.image.get_rect()
-
self.rect.left, self.rect.top = position #把飞机机头位置给子弹位置
-
self.speed = 12
-
self.active = True
-
self.mask = pygame.mask.from_surface(self.image) #非透明部分
-
-
def move(self):
-
self.rect.top -= self.speed
-
-
if self.rect.top < 0: #射出屏幕外
-
self.active = False
-
-
def reset(self, position):
-
self.rect.left, self.rect.top = position
-
self.active = True
接下來就需要在main 模塊裡生成子彈:
-
# 生成普通子弹
-
bullet1 = []
-
bullet1_index = 0
-
BULLET1_NUM = 4
-
for i in range(BULLET1_NUM):
-
bullet1.append(bullet.Bullet1(me.rect.midtop))
接下來設置每10幀發射一顆子彈:
-
# 发射子弹
-
if not(delay % 10):
-
bullet1[bullet1_index].reset(me.rect.midtop)
-
bullet1_index = (bullet1_index + 1) % BULLET1_NUM
接下來檢測射出去的子彈是否擊中敵機,擊中的話,敵機和子彈的active 會設置為False:
-
# 检测子弹是否击中敌机
-
for b in bullet1:
-
if b.active:
-
b.move()
-
screen.blit(b.image, b.rect)
-
enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
-
if enemy_hit:
-
b.active = False
-
for e in enemy_hit:
-
e.active = False
到目前為止,這樣我們基本上就戰無不勝了。無論是中型敵機還是大型敵機,我們直接一槍就把它秒殺了,這就顯得敵機太弱了吧。
因此,我們給中型敵機和大型敵機添加一個energy 的屬性,顯示還有多少生命值。
然後,我們就來修改main 模塊,每當中大型敵機被子彈擊中的時候,我們先將其enery 屬性的值減1,減到為0時,才讓敵機墜機。
-
# 检测子弹是否击中敌机
-
for b in bullet1:
-
if b.active:
-
b.move()
-
screen.blit(b.image, b.rect)
-
enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
-
if enemy_hit:
-
b.active = False
-
for e in enemy_hit:
-
if e in mid_enemies or e in big_enemies:
-
e.energy -= 1
-
if e.energy == 0:
-
e.active = False
-
else: #是小型敌机
-
e.active = False
我們還可以為中大型敵機增加血槽的顯示功能,這樣子可以更直觀的讓玩家知道敵機還剩多少生命值,
所以我們在繪製中大型敵機這裡就需要進行修改了:
-
#绘制大型敌机
-
for each in big_enemies:
-
if each.active: #检测是否还活着
-
each.move()
-
if switch_image:
-
screen.blit(each.image1, each.rect)
-
else:
-
screen.blit(each.image2, each.rect)
-
-
# 绘制血槽
-
pygame.draw.line(screen, BLACK, \
-
(each.rect.left, each.rect.top - 5), \
-
(each.rect.right, each.rect.top - 5), \
-
2)
-
# 当生命大于20%显示绿色,否则显示红色
-
energy_remain = each.energy / enemy.BigEnemy.energy
-
if energy_remain > 0.2:
-
energy_color = GREEN
-
else:
-
energy_color = RED
-
pygame.draw.line(screen, energy_color, \
-
(each.rect.left, each.rect.top - 5), \
-
(each.rect.left + each.rect.width * energy_remain, \
-
each.rect.top - 5),
-
2)
-
-
#即将出现在界面中,播放音效
-
if each.rect.bottom == -50:
-
enemy3_fly_sound.play(-1) #循环播放
-
else:
-
#坠机
-
if not(delay % 3):
-
if e3_destroy_index == 0:
-
enemy3_down_sound.play()
-
screen.blit(each.destroy_images[e3_destroy_index], each.rect)
-
e3_destroy_index = (e3_destroy_index + 1) % 6
-
if e3_destroy_index == 0:
-
enemy3_fly_sound.stop() #循环音效停止播放
-
each.reset()
-
-
#绘制中型敌机
-
for each in mid_enemies:
-
if each.active: #检测是否还活着
-
each.move()
-
screen.blit(each.image, each.rect)
-
-
# 绘制血槽
-
pygame.draw.line(screen, BLACK, \
-
(each.rect.left, each.rect.top - 5), \
-
(each.rect.right, each.rect.top - 5), \
-
2)
-
# 当生命大于20%显示绿色,否则显示红色
-
energy_remain = each.energy / enemy.MidEnemy.energy
-
if energy_remain > 0.2:
-
energy_color = GREEN
-
else:
-
energy_color = RED
-
pygame.draw.line(screen, energy_color, \
-
(each.rect.left, each.rect.top - 5), \
-
(each.rect.left + each.rect.width * energy_remain, \
-
each.rect.top - 5), 2)
-
else:
-
#坠机
-
if not(delay % 3):
-
if e2_destroy_index == 0:
-
enemy2_down_sound.play() #音效
-
screen.blit(each.destroy_images[e2_destroy_index], each.rect)
-
e2_destroy_index = (e2_destroy_index + 1) % 4
-
if e2_destroy_index == 0:
-
each.reset()
就目前而言,我們是成功了。
當中型敵機和大型敵機被子彈擊中時,但不至於墜機時,這時候應該是要有特效的。
我們現在enemy 模塊中增加特效的圖片,並且增加一個用於檢測是否被擊中的hit 屬性。
然後我們在子彈擊中中型或大型飛機時,將hit 屬性的值改為True
然後再繪製中型或大型飛機時,就需要根據hit 作調整。
-
#绘制大型敌机
-
for each in big_enemies:
-
if each.active: #检测是否还活着
-
each.move()
-
if each.hit:
-
#绘制被击中的特效
-
screen.blit(each.image_hit, each.rect)
-
each.hit = False
-
else:
-
if switch_image:
-
screen.blit(each.image1, each.rect)
-
else:
-
screen.blit(each.image2, each.rect)
-
-
-
#(省略部分代码不显示)
-
-
#绘制中型敌机
-
for each in mid_enemies:
-
if each.active: #检测是否还活着
-
each.move()
-
if each.hit:
-
#绘制被击中的特效
-
screen.blit(each.image_hit, each.rect)
-
each.hit = False
-
else:
-
screen.blit(each.image, each.rect)
-
#bullet.py
-
import pygame
-
-
class Bullet1(pygame.sprite.Sprite):#普通子弹,一次一发
-
def __init__(self, position):
-
pygame.sprite.Sprite.__init__(self)
-
-
self.image = pygame.image.load("images/bullet1.png").convert_alpha()
-
self.rect = self.image.get_rect()
-
self.rect.left, self.rect.top = position #把飞机机头位置给子弹位置
-
self.speed = 12
-
self.active = True
-
self.mask = pygame.mask.from_surface(self.image) #非透明部分
-
-
def move(self):
-
self.rect.top -= self.speed
-
-
if self.rect.top < 0: #射出屏幕外
-
self.active = False
-
-
def reset(self, position):
-
self.rect.left, self.rect.top = position
-
self.active = True
-
# 生成普通子弹
-
bullet1 = []
-
bullet1_index = 0
-
BULLET1_NUM = 4
-
for i in range(BULLET1_NUM):
-
bullet1.append(bullet.Bullet1(me.rect.midtop))
-
# 发射子弹
-
if not(delay % 10):
-
bullet1[bullet1_index].reset(me.rect.midtop)
-
bullet1_index = (bullet1_index + 1) % BULLET1_NUM
-
# 检测子弹是否击中敌机
-
for b in bullet1:
-
if b.active:
-
b.move()
-
screen.blit(b.image, b.rect)
-
enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
-
if enemy_hit:
-
b.active = False
-
for e in enemy_hit:
-
e.active = False
-
# 检测子弹是否击中敌机
-
for b in bullet1:
-
if b.active:
-
b.move()
-
screen.blit(b.image, b.rect)
-
enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
-
if enemy_hit:
-
b.active = False
-
for e in enemy_hit:
-
if e in mid_enemies or e in big_enemies:
-
e.energy -= 1
-
if e.energy == 0:
-
e.active = False
-
else: #是小型敌机
-
e.active = False
-
#绘制大型敌机
-
for each in big_enemies:
-
if each.active: #检测是否还活着
-
each.move()
-
if switch_image:
-
screen.blit(each.image1, each.rect)
-
else:
-
screen.blit(each.image2, each.rect)
-
-
# 绘制血槽
-
pygame.draw.line(screen, BLACK, \
-
(each.rect.left, each.rect.top - 5), \
-
(each.rect.right, each.rect.top - 5), \
-
2)
-
# 当生命大于20%显示绿色,否则显示红色
-
energy_remain = each.energy / enemy.BigEnemy.energy
-
if energy_remain > 0.2:
-
energy_color = GREEN
-
else:
-
energy_color = RED
-
pygame.draw.line(screen, energy_color, \
-
(each.rect.left, each.rect.top - 5), \
-
(each.rect.left + each.rect.width * energy_remain, \
-
each.rect.top - 5),
-
2)
-
-
#即将出现在界面中,播放音效
-
if each.rect.bottom == -50:
-
enemy3_fly_sound.play(-1) #循环播放
-
else:
-
#坠机
-
if not(delay % 3):
-
if e3_destroy_index == 0:
-
enemy3_down_sound.play()
-
screen.blit(each.destroy_images[e3_destroy_index], each.rect)
-
e3_destroy_index = (e3_destroy_index + 1) % 6
-
if e3_destroy_index == 0:
-
enemy3_fly_sound.stop() #循环音效停止播放
-
each.reset()
-
-
#绘制中型敌机
-
for each in mid_enemies:
-
if each.active: #检测是否还活着
-
each.move()
-
screen.blit(each.image, each.rect)
-
-
# 绘制血槽
-
pygame.draw.line(screen, BLACK, \
-
(each.rect.left, each.rect.top - 5), \
-
(each.rect.right, each.rect.top - 5), \
-
2)
-
# 当生命大于20%显示绿色,否则显示红色
-
energy_remain = each.energy / enemy.MidEnemy.energy
-
if energy_remain > 0.2:
-
energy_color = GREEN
-
else:
-
energy_color = RED
-
pygame.draw.line(screen, energy_color, \
-
(each.rect.left, each.rect.top - 5), \
-
(each.rect.left + each.rect.width * energy_remain, \
-
each.rect.top - 5), 2)
-
else:
-
#坠机
-
if not(delay % 3):
-
if e2_destroy_index == 0:
-
enemy2_down_sound.play() #音效
-
screen.blit(each.destroy_images[e2_destroy_index], each.rect)
-
e2_destroy_index = (e2_destroy_index + 1) % 4
-
if e2_destroy_index == 0:
-
each.reset()
-
#绘制大型敌机
-
for each in big_enemies:
-
if each.active: #检测是否还活着
-
each.move()
-
if each.hit:
-
#绘制被击中的特效
-
screen.blit(each.image_hit, each.rect)
-
each.hit = False
-
else:
-
if switch_image:
-
screen.blit(each.image1, each.rect)
-
else:
-
screen.blit(each.image2, each.rect)
-
-
-
#(省略部分代码不显示)
-
-
#绘制中型敌机
-
for each in mid_enemies:
-
if each.active: #检测是否还活着
-
each.move()
-
if each.hit:
-
#绘制被击中的特效
-
screen.blit(each.image_hit, each.rect)
-
each.hit = False
-
else:
-
screen.blit(each.image, each.rect)
0 留言:
發佈留言