当前位置:网站首页>Space shooting lesson 08: improved collision
Space shooting lesson 08: improved collision
2022-07-23 23:51:00 【acktomas】
Space shooting No 08 course : Improved collision
This is us. “Shmup” Project No 5 part . If you haven't read through the previous section , Please from The first 1 part Start . In this lesson , We will discuss how to change Pygame The way to deal with conflicts between elves .
What happened to the collision ?
In the last tutorial , We added graphics , Change the sprite from a normal rectangle to a more beautiful PNG Images . However , This brings up a problem : Sometimes the game will think that there is a collision between the player and the meteor , And it seems that they didn't hit at all . To understand what happened , Let's see a picture :

Pygame The default conflict type in is to use collide_rect() function , This function uses two sprites rect Property to calculate whether they overlap . This is known as AABB Collision , It's very fast and reliable . however , If the sprite image is not rectangular , Then you will encounter rectangle overlap similar to that in the picture . At this time collide_rect() The return value of the function is True, Players will feel frustrated , Because they think they should have successfully avoided the meteor .
If you are in this situation , There are several ways to try :

By using collide_rect_ratio() function , You can use smaller rectangles , Thus reducing the amount of space that can be counted as overlap . According to the shape of the spirit , It works well . Notice how the tip of the wing is outside the rectangle . This means that in some cases the star seems to pass through the wing , It will not count as an impact . This is actually a good situation ! At the speed of things moving in the game , Players will not notice this directly , And I just think they “ get away ” A very close dodge . They don't feel depressed , Instead, I will feel that I have done well .

Another option is to use a circular bounding box . For meteors , This is a very good choice . It is not suitable for this ship , But the same , It's not a bad thing that the wing is outside the collision .
Set the radius of the sprite
According to the above options , We will choose a circle for the collision between meteors and players .Pygame Make it easy - We just need to set a new attribute on each wizard :self.radius.
Let's start with players . How big should the collision ring be ? It may take a little experiment to get the correct value . The following is how to perform this operation in the player wizard :__init()__
self.rect = self.image.get_rect()
self.radius = 25
pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
We draw a red circle at the top of the player image , So that we can see its appearance . Let's do the same thing with meteors :
self.rect = self.image.get_rect()
self.radius = int(self.rect.width / 2)
pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
under these circumstances , We are planning ahead . We may decide to use meteor images of different sizes . By setting the radius to 1⁄2, We can do that , Without having to adjust the code later .
Here is our final result :

You can see , For player elves , Our radius may be too large —— It's actually y The axis is larger than the size of the spacecraft . To get closer to the above example , Let's set up players self.radius = 20.
For meteors , We want to highlight a little bit , So let's scale the circle to the size 85%:
self.radius = int(self.rect.width * .85 / 2)
Change the collision type
Let the game start using these circles for collision testing , We just need to change spritecollide Command to use the circle function instead of AABB function :
# check to see if a mob hit the player
hits = pygame.sprite.spritecollide(player, mobs, False, pygame.sprite.collide_circle)
if hits:
running = False

Once you try , And you are satisfied with the way the collision works , You can delete the red circle . I suggest you just comment out the command , Instead of deleting them , In case you want to use them again in the future .
Conclusion
Determining the right collision style can greatly change the feel of the game . We now have a better meteor collision with players , But please pay attention to , We haven't changed the style of bullets colliding with meteors . Circle is a bad choice for the shape of bullets , So it's best to keep them rectangular .
thereinafter , We will make things lively by learning how to add animation to sprites
The complete code of this part
# KidsCanCode - Game Development with Pygame video series
# Shmup game - part 5
# Video link: https://www.youtube.com/watch?v=_y5U8tB36Vk
# Improved collisions
import pygame
import random
from os import path
img_dir = path.join(path.dirname(__file__), 'img')
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()
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
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)
class Mob(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = meteor_img
self.image.set_colorkey(BLACK)
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.y = random.randrange(-100, -40)
self.speedy = random.randrange(1, 8)
self.speedx = random.randrange(-3, 3)
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.top > HEIGHT + 10 or self.rect.left < -25 or self.rect.right > WIDTH + 20:
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()
meteor_img = pygame.image.load(path.join(img_dir, "meteorBrown_med1.png")).convert()
bullet_img = pygame.image.load(path.join(img_dir, "laserRed16.png")).convert()
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
bullets = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(8):
m = Mob()
all_sprites.add(m)
mobs.add(m)
# 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:
m = Mob()
all_sprites.add(m)
mobs.add(m)
# check to see if a mob hit the player
hits = pygame.sprite.spritecollide(player, mobs, False, pygame.sprite.collide_circle)
if hits:
running = False
# Draw / render
screen.fill(BLACK)
screen.blit(background, background_rect)
all_sprites.draw(screen)
# *after* drawing everything, flip the display
pygame.display.flip()
pygame.quit()
The first 6 part : Sprite animation
边栏推荐
- 数据驱动之Excel读写
- [CTF] Tiange team writeup - the first digital space security attack and defense competition (Preliminary)
- 深度学习之 9 前馈神经网络 基本概念
- 【OpenCV】- cv.threshold()函数的参数type是数字时,代表的含义
- 474-82(8、221、300)
- Beijing University qingniaochangping Campus: how about the current situation of operation and maintenance employment? Are skills required?
- [ssm] joint commissioning of front and rear console protocols ②
- 第五章、实现Web适配器
- Structured Streaming 编程模型(Input Table、Result Table、Output Mode...)
- DGS file upload
猜你喜欢

史上最全的2022年版Android面试题

y75.第四章 Prometheus大厂监控体系及实战 -- prometheus报警设置(六)
![[SSM]前后台协议联调①](/img/47/c1016c5c5e4ffc0d6cc93cf50d52df.png)
[SSM]前后台协议联调①

warmup_ csaw_ two thousand and sixteen

Structured Streaming 编程模型(Input Table、Result Table、Output Mode...)

js把数字转大写

数据驱动之Excel读写

ret2text

Android金九银十的面试你准备的怎么样了?最新Android面试真题汇总助你备战
![[ssm] joint debugging of front and rear protocols ①](/img/47/c1016c5c5e4ffc0d6cc93cf50d52df.png)
[ssm] joint debugging of front and rear protocols ①
随机推荐
PyTorch 中遇到的问题
ciscn_ 2019_ n_ one
权重分析——熵权法
[array] longest continuous subsequence in nc95 array - difficult
Code generation of DGS
How are you preparing for the Android golden nine silver ten interview? The latest Android Interview Questions Summary helps you prepare for the war
Sentinel链路方式流控失效解决
Windows软件:如何安装Mysql5.7并配置环境变量
JS學習筆記-- 數組方法 底層實現方式
PushGateway+Prometheus+Grafana构建Flink实时监控
网络安全课堂作业
Chapter 6: implement a persistence adapter
Longest increasing subsequence variant [deep understanding of the longest increasing sequence]
【攻防世界WEB】难度五星15分进阶题:bug
太空射击 第07课: 添加图形
SQL语句实战学习
Is Zhongyuan securities reliable? Is it legal? Is it safe to open a stock account?
The world's smallest material ranking, Lingzi, Xianzi, quark
在原生终端实现类似 rz、sz 上传下载文件与目录的功能
[three-year interview and five-year simulation] Dugu Jiujian secret script of Algorithm Engineer (first six style summary) V1 version