当前位置:网站首页>太空射击第13课: 爆炸效果
太空射击第13课: 爆炸效果
2022-07-28 18:25:00 【acktomas】
太空射击第13课: 爆炸效果
这是我们“Shmup”项目的第10部分。如果您尚未通读前面的部分,请从第 1 部分开始。在本课中,我们将在玩家射击流星时进行一些动画爆炸。
视频
您可以在此处观看本课程的视频:
自动开火
首先,让我们对玩家的射击方式进行一些小的改变。现在,我们必须为每次射击按空格键。这导致玩家快速敲击键盘空格键。相反,只要按住空格键,我们就可以让飞船自动射击。
为此,我们将向玩家添加两个新属性:
self.shoot_delay = 250
self.last_shot = pygame.time.get_ticks()
shoot_delay将测量飞船在发射另一颗子弹之前应该等待多长时间(以毫秒为单位)。last_shot跟踪最后一颗子弹的发射时间,以便确定经过足够的时间再次开火。
现在,我们将在玩家更新中将 fire 键添加到键盘检查中:
def update(self):
self.speedx = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -8
if keystate[pygame.K_RIGHT]:
self.speedx = 8
if keystate[pygame.K_SPACE]:
self.shoot()
我们将把所有的射击逻辑放在一个新的方法中:
def shoot(self):
now = pygame.time.get_ticks()
if now - self.last_shot > self.shoot_delay:
self.last_shot = now
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
现在,当空格键被按住时,游戏将检查自创建最后一颗子弹以来已经过去了多少时间。如果已经过shoot_delay毫秒,则发射另一颗子弹并更新last_shot。最后,我们可以从游戏循环中删除以下行:
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shoot()
动画爆炸
对于我们的下一个补充,我们希望通过使流星爆炸而不仅仅是消失,使流星的破坏更具视觉吸引力。为了实现这一点,我们需要一组用于爆炸图形的动画帧,并且我们需要在被摧毁的流星的位置创建一个精灵,该精灵将在动画帧序列中循环。以下是我们将要使用的动画序列:

单击此处下载这些图像的压缩包。
首先,我们需要将这些图形加载到游戏中,并将它们存储在列表中。与玩家精灵一样,我们将需要调整图像大小,当我们这样做时,我们将创建两个不同大小的爆炸:一个大爆炸,当流星被摧毁时;和一个小的,当流星击中玩家的盾牌时。因此,我们将有一个字典explosion_anim ,其中包含两个列表lg和sm .由于这些文件的名称相同,数字从00-08,我们可以使用循环将它们全部加载,调整大小并将它们附加到列表中:
explosion_anim = {
}
explosion_anim['lg'] = []
explosion_anim['sm'] = []
for i in range(9):
filename = 'regularExplosion0{}.png'.format(i)
img = pygame.image.load(path.join(img_dir, filename)).convert()
img.set_colorkey(BLACK)
img_lg = pygame.transform.scale(img, (75, 75))
explosion_anim['lg'].append(img_lg)
img_sm = pygame.transform.scale(img, (32, 32))
explosion_anim['sm'].append(img_sm)
爆炸精灵
接下来,我们将定义一个新的精灵,当它出现在屏幕上时,它将是实际的爆炸。此精灵的图像将在我们的动画帧列表中从一个图像快速更改为下一个图像。当它到达最后一帧时,该精灵将被删除。当我们生成精灵时,我们会告诉它在哪里生成(流星的位置),以及使用哪个大小。类似于我们执行上面的自动射击功能,我们也有一个frame_rate属性,它将使我们能够控制动画运行的速度 - 如果我们每次更新( 1 60 \frac{1}{60} 601秒)更改图像,那么整个爆炸只会持续大约 1 10 \frac{1}{10} 101秒。下面是Explosion精灵的代码:
class Explosion(pygame.sprite.Sprite):
def __init__(self, center, size):
pygame.sprite.Sprite.__init__(self)
self.size = size
self.image = explosion_anim[self.size][0]
self.rect = self.image.get_rect()
self.rect.center = center
self.frame = 0
self.last_update = pygame.time.get_ticks()
self.frame_rate = 50
def update(self):
now = pygame.time.get_ticks()
if now - self.last_update > self.frame_rate:
self.last_update = now
self.frame += 1
if self.frame == len(explosion_anim[self.size]):
self.kill()
else:
center = self.rect.center
self.image = explosion_anim[self.size][self.frame]
self.rect = self.image.get_rect()
self.rect.center = center
现在,每当敌人被摧毁时,我们需要生成其中一个:
# check to see if a bullet hit a mob
hits = pygame.sprite.groupcollide(mobs, bullets, True, True)
for hit in hits:
score += 50 - hit.radius
random.choice(expl_sounds).play()
expl = Explosion(hit.rect.center, 'lg')
all_sprites.add(expl)
newmob()
当玩家被击中时:
# check to see if a mob hit the player
hits = pygame.sprite.spritecollide(player, mobs, True, pygame.sprite.collide_circle)
for hit in hits:
player.shield -= hit.radius * 2
expl = Explosion(hit.rect.center, 'sm')
all_sprites.add(expl)
newmob()
if player.shield <= 0:
running = False
现在我们可以看到最终结果:
在下一部分中,我们将通过为玩家添加生命来使游戏持续更长时间。
此部分的完整代码
# KidsCanCode - Game Development with Pygame video series
# Shmup game - part 10
# Video link: https://www.youtube.com/watch?v=AdG_ITCFHDI
# Explosions
# Frozen Jam by tgfcoder <https://twitter.com/tgfcoder> licensed under CC-BY-3
# Art from Kenney.nl
import pygame
import random
from os import path
img_dir = path.join(path.dirname(__file__), 'img')
snd_dir = path.join(path.dirname(__file__), 'snd')
WIDTH = 480
HEIGHT = 600
FPS = 60
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
# initialize pygame and create window
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Shmup!")
clock = pygame.time.Clock()
font_name = pygame.font.match_font('arial')
def draw_text(surf, text, size, x, y):
font = pygame.font.Font(font_name, size)
text_surface = font.render(text, True, WHITE)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
def newmob():
m = Mob()
all_sprites.add(m)
mobs.add(m)
def draw_shield_bar(surf, x, y, pct):
if pct < 0:
pct = 0
BAR_LENGTH = 100
BAR_HEIGHT = 10
fill = (pct / 100) * BAR_LENGTH
outline_rect = pygame.Rect(x, y, BAR_LENGTH, BAR_HEIGHT)
fill_rect = pygame.Rect(x, y, fill, BAR_HEIGHT)
pygame.draw.rect(surf, GREEN, fill_rect)
pygame.draw.rect(surf, WHITE, outline_rect, 2)
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.transform.scale(player_img, (50, 38))
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = 20
# pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT - 10
self.speedx = 0
self.shield = 100
self.shoot_delay = 250
self.last_shot = pygame.time.get_ticks()
def update(self):
self.speedx = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -8
if keystate[pygame.K_RIGHT]:
self.speedx = 8
if keystate[pygame.K_SPACE]:
self.shoot()
self.rect.x += self.speedx
if self.rect.right > WIDTH:
self.rect.right = WIDTH
if self.rect.left < 0:
self.rect.left = 0
def shoot(self):
now = pygame.time.get_ticks()
if now - self.last_shot > self.shoot_delay:
self.last_shot = now
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
shoot_sound.play()
class Mob(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image_orig = random.choice(meteor_images)
self.image_orig.set_colorkey(BLACK)
self.image = self.image_orig.copy()
self.rect = self.image.get_rect()
self.radius = int(self.rect.width * .85 / 2)
# pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.bottom = random.randrange(-80, -20)
self.speedy = random.randrange(1, 8)
self.speedx = random.randrange(-3, 3)
self.rot = 0
self.rot_speed = random.randrange(-8, 8)
self.last_update = pygame.time.get_ticks()
def rotate(self):
now = pygame.time.get_ticks()
if now - self.last_update > 50:
self.last_update = now
self.rot = (self.rot + self.rot_speed) % 360
new_image = pygame.transform.rotate(self.image_orig, self.rot)
old_center = self.rect.center
self.image = new_image
self.rect = self.image.get_rect()
self.rect.center = old_center
def update(self):
self.rotate()
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.left < -100 or self.rect.right > WIDTH + 100:
self.rect.x = random.randrange(WIDTH - self.rect.width)
self.rect.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = bullet_img
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.bottom = y
self.rect.centerx = x
self.speedy = -10
def update(self):
self.rect.y += self.speedy
# kill if it moves off the top of the screen
if self.rect.bottom < 0:
self.kill()
class Explosion(pygame.sprite.Sprite):
def __init__(self, center, size):
pygame.sprite.Sprite.__init__(self)
self.size = size
self.image = explosion_anim[self.size][0]
self.rect = self.image.get_rect()
self.rect.center = center
self.frame = 0
self.last_update = pygame.time.get_ticks()
self.frame_rate = 50
def update(self):
now = pygame.time.get_ticks()
if now - self.last_update > self.frame_rate:
self.last_update = now
self.frame += 1
if self.frame == len(explosion_anim[self.size]):
self.kill()
else:
center = self.rect.center
self.image = explosion_anim[self.size][self.frame]
self.rect = self.image.get_rect()
self.rect.center = center
# Load all game graphics
background = pygame.image.load(path.join(img_dir, "starfield.png")).convert()
background_rect = background.get_rect()
player_img = pygame.image.load(path.join(img_dir, "playerShip1_orange.png")).convert()
bullet_img = pygame.image.load(path.join(img_dir, "laserRed16.png")).convert()
meteor_images = []
meteor_list = ['meteorBrown_big1.png', 'meteorBrown_med1.png', 'meteorBrown_med1.png',
'meteorBrown_med3.png', 'meteorBrown_small1.png', 'meteorBrown_small2.png',
'meteorBrown_tiny1.png']
for img in meteor_list:
meteor_images.append(pygame.image.load(path.join(img_dir, img)).convert())
explosion_anim = {}
explosion_anim['lg'] = []
explosion_anim['sm'] = []
for i in range(9):
filename = 'regularExplosion0{}.png'.format(i)
img = pygame.image.load(path.join(img_dir, filename)).convert()
img.set_colorkey(BLACK)
img_lg = pygame.transform.scale(img, (75, 75))
explosion_anim['lg'].append(img_lg)
img_sm = pygame.transform.scale(img, (32, 32))
explosion_anim['sm'].append(img_sm)
# Load all game sounds
shoot_sound = pygame.mixer.Sound(path.join(snd_dir, 'pew.wav'))
expl_sounds = []
for snd in ['expl3.wav', 'expl6.wav']:
expl_sounds.append(pygame.mixer.Sound(path.join(snd_dir, snd)))
pygame.mixer.music.load(path.join(snd_dir, 'tgfcoder-FrozenJam-SeamlessLoop.ogg'))
pygame.mixer.music.set_volume(0.4)
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
bullets = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(8):
newmob()
score = 0
pygame.mixer.music.play(loops=-1)
# Game loop
running = True
while running:
# keep loop running at the right speed
clock.tick(FPS)
# Process input (events)
for event in pygame.event.get():
# check for closing window
if event.type == pygame.QUIT:
running = False
# Update
all_sprites.update()
# check to see if a bullet hit a mob
hits = pygame.sprite.groupcollide(mobs, bullets, True, True)
for hit in hits:
score += 50 - hit.radius
random.choice(expl_sounds).play()
expl = Explosion(hit.rect.center, 'lg')
all_sprites.add(expl)
newmob()
# check to see if a mob hit the player
hits = pygame.sprite.spritecollide(player, mobs, True, pygame.sprite.collide_circle)
for hit in hits:
player.shield -= hit.radius * 2
expl = Explosion(hit.rect.center, 'sm')
all_sprites.add(expl)
newmob()
if player.shield <= 0:
running = False
# Draw / render
screen.fill(BLACK)
screen.blit(background, background_rect)
all_sprites.draw(screen)
draw_text(screen, str(score), 18, WIDTH / 2, 10)
draw_shield_bar(screen, 5, 5, player.shield)
# *after* drawing everything, flip the display
pygame.display.flip()
pygame.quit()
第11部分:玩家生活
边栏推荐
- Data mining (data preprocessing) -- Notes
- 【pytorch】LSTM神经网络
- Method number problem for solving sum of numbers (knapsack problem)
- Raspberry pie creation self start service
- C语言数据 3(2)
- 【CodeForces】Educational Codeforces Round 132 (Rated for Div. 2)
- 8. Compilation errors of C language and Chinese explanation
- 83. (cesium home) how the cesium example works
- LeetCode_位运算_中等_260.只出现一次的数字 III
- Solve flask integration_ Error reporting in restplus
猜你喜欢

Speech controlled robot based on ROS (I): realization of basic functions
![[pytorch] LSTM neural network](/img/c8/c1f92e7d4da7f07b85abe481f025bc.png)
[pytorch] LSTM neural network

【pytorch】LSTM神经网络

Configure Windows Server + install MySQL database on the server + Remote Access database

Zfoo adds routes similar to mydog

Use of DDR3 (axi4) in Xilinx vivado (2) read write design

Other IPS cannot connect to the local redis problem solving and redis installation

CNN convolution neural network learning process (weight update)
![[C language] guessing numbers game](/img/ac/81a82404618487861b67e35f18d13f.png)
[C language] guessing numbers game

LVS deployment Dr cluster
随机推荐
Common instructions of vim software
Raspberry pie uses the command line to configure WiFi connections
Storage of C language data in memory (1)
C language data 3 (1)
Product manager interview | innovation and background of the fifth generation verification code
Nocturnal simulator settings agent cannot be saved
83.(cesium之家)cesium示例如何运行
一文让你搞懂什么是TypeScript
[task02: SQL basic query and sorting]
Wildcard ssl/tls certificate
User, user group related operations
Linxu 【基本指令】
How to automatically store email attachments in SharePoint
Solve flask integration_ Error reporting in restplus
WFST decoding process
LVS deployment Dr cluster
Torch. NN. Linear() function
Teach you how to draw a map with ArcGIS [thermal map]
Does any elder brother know how to solve the huge flinksql log
Use of DDR3 (axi4) in Xilinx vivado (2) read write design