当前位置:网站首页>Space game Lesson 12: shield
Space game Lesson 12: shield
2022-07-28 20:51:00 【acktomas】
Space game number 12 course : shield
This is us. “Shmup” Project No 9 part . If you haven't read through the previous section , Please from The first 1 part Start . In this lesson , We will add a shield for players and a bar for displaying shield level .
video
You can watch the video of this course here :
Add shield
Now? , Our player was hit and destroyed by a meteor . It's not very interesting , So we want to add one to the player shield attribute , It is 0 - 100 The number of .
class Player(pygame.sprite.Sprite):
def __init__(self):
self.speedx = 0
self.shield = 100
Now? , Whenever a player is hit by a meteor , We can subtract a little from the shield . When the shield reaches 0 when , Players are destroyed . To make things more interesting , We can use meteors radius Attribute makes large meteors cause more damage than small meteors .
In the next video , We will add some shields for players , So we won't die so easily .
Hurt players
at present , Our enemy and player collision code is very simple :
# check to see if a mob hit the player
hits = pygame.sprite.spritecollide(player, mobs, False, pygame.sprite.collide_circle)
if hits:
running = False
We need to make some changes :
# 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
if player.shield <= 0:
running = False
We will spritecollide The parameters of the function False Change to True, Because we want the meteor to be deleted when it hits . If we don't , Then meteors will continue to exist , When it moves , There will be another collision in the next frame , And so on . Besides , We may hit multiple meteors at the same time ,hits There can be multiple projects . We go through a cycle hits, And deduct some shields for each hit according to its radius . Last , If the player's shield reaches 0, The game will be over .
One thing you may have noticed is , Because we are removing any enemies that hit the player , therefore , We are reducing the total number of enemies in the game . We hope it stays the same , So whenever we remove an enemy , We all need to create a new enemy . This is how we generate primitive enemies , As shown below :
for i in range(8):
m = Mob()
all_sprites.add(m)
mobs.add(m)
but , We need to create a new enemy , This is duplicate code , It's a bad thing . contrary , We will mob Create code to move into a function , We can use it when we need it :
def newmob():
m = Mob()
all_sprites.add(m)
mobs.add(m)
Now? , We can start the game , When we hit the enemy , And when we need to replace the enemy that hit the player , You can use this function :
for i in range(8):
newmob()
# 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()
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
newmob()
if player.shield <= 0:
running = False
Shield ruler
We have a shield value , It's working , But unless the player can see this value , Otherwise it is not very useful . We need to create a display , But it's not just about displaying numbers , We will make a bar chart , Show the full of shields / empty :
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)
This function works in the same way as we previously defined draw_text Function similar to . It will draw a length of BAR_LENGTH、 High for BAR_HEIGHT Bar of , be located (x, y) The column and press pct Value padding . We will draw two rectangles : The first rectangle will be a white outline , The second rectangle is filled with green . We add a call to this function in the drawing part of the game loop :
draw_text(screen, str(score), 18, WIDTH / 2, 10)
draw_shield_bar(screen, 5, 5, player.shield)
Now we can see how many shields we have left when it descends :
The complete code of this part
# KidsCanCode - Game Development with Pygame video series
# Shmup game - part 9
# Video link: https://www.youtube.com/watch?v=vvgWfNLgK9c
# Player shield
# 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
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
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):
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()
# 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())
# 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
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.shoot()
# 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()
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
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()
The first 10 part : The explosion
边栏推荐
- How to use redis to realize things and locks?
- 阿里云 MSE 支持 Go 语言流量防护
- Classes and objects (medium)
- What is data center? What value does the data center bring_ Light spot technology
- Unity performance optimization scheme arrangement
- “当你不再是程序员,很多事会脱离掌控”—— 对话全球最大独立开源公司SUSE CTO...
- Seventeen year operation and maintenance veterans, ten thousand words long, speak through the code of excellent maintenance and low cost~
- #yyds干货盘点# 面试必刷TOP101:链表中的节点每k个一组翻转
- 如何平衡SQL中的安全与性能?
- 云原生编程挑战赛火热开赛,51 万奖金等你来挑战!
猜你喜欢

Network shell

十七年运维老兵万字长文讲透优维低代码~

Unity uses shader to quickly make a circular mask
![[server data recovery] HP StorageWorks series storage RAID5 two disk failure offline data recovery case](/img/7c/d5643d27c2ca7a7aed4eb02fd81042.jpg)
[server data recovery] HP StorageWorks series storage RAID5 two disk failure offline data recovery case

How to make the design of governance structure more flexible when the homogenization token is combined with NFT?

Learn about the native application management platform of rainbow cloud

Clock distribution of jesd204 IP core (ultrascale Series)

Use of DDR3 (axi4) in Xilinx vivado (5) board test

JS chart scatter example

想画一张版权属于你的图吗?AI作画,你也可以
随机推荐
第六七八次作业
[C语言刷题篇]链表运用讲解
“当你不再是程序员,很多事会脱离掌控”—— 对话全球最大独立开源公司SUSE CTO...
Talking about canvas and three rendering modes in unity
How to make the design of governance structure more flexible when the homogenization token is combined with NFT?
云原生编程挑战赛火热开赛,51 万奖金等你来挑战!
The engineering practice of super large model was polished, and Baidu AI Cloud released the cloud native AI 2.0 solution
Use order by to sort
#yyds干货盘点# 面试必刷TOP101:链表中的节点每k个一组翻转
Use of DDR3 (axi4) in Xilinx vivado (3) module packaging
View the thread stack according to the lwtid of opengauss/mogdb.
Introduction to redis I: redis practical reading notes
Explain rigid body and collider components in unity
js网页黑白背景开关js特效
js可拖拽alert弹窗插件
【1331. 数组序号转换】
[pytorch] LSTM neural network
Redis入门一:Redis实战读书笔记
Pl515 SOT23-5 single / Dual Port USB charging protocol port controller Parkson electronic agent
SQL审核工具自荐Owls