如何解决Pygame 中的蒙版碰撞
我正在制作一个无尽的跑步类型游戏,玩家在尝试避开障碍物的同时驾驶宇宙飞船。我在船和障碍物之间使用掩码碰撞检测。玩家还可以激活应该摧毁其路径上的小行星的激光。我正在尝试为此使用相同的碰撞检测方法,但它不起作用。那可能是因为我有一个改变图像的激光动画。我该如何解决这个问题?
######################
#
# Pls help
#
# Written by: Theo
# Date: December 2020 - march 2021
#
# Version 1: an endless runner game where the player
# controls a ship traveling through space,dodging obstacles
import pygame
import math
import time
import random
import RiftObstacles
global ship
global rot_ship
global shipX
global moonMask
pygame.init()
FPS = 100
clock = pygame.time.Clock()
size = pygame.display.Info()
WIDTH = 1000
HEIGHT = 1000
pygame.display.set_caption('Parallax Nebula')
screen = pygame.display.set_mode((WIDTH,HEIGHT))
########## Rift Variables
ship = pygame.image.load("Images/Rift/Ship.PNG")
ship = pygame.transform.scale(ship,(85,125))
rot_ship = ship
shipX = 450
shipY = 700
A1 = pygame.image.load("Images/Rift/Asteroids/1.PNG")
A1 = pygame.transform.scale(A1,(100,100))
A1 = pygame.Surface.convert_alpha(A1)
A2 = pygame.image.load("Images/Rift/Asteroids/2.PNG")
A2 = pygame.transform.scale(A2,100))
A2 = pygame.Surface.convert_alpha(A2)
A3 = pygame.image.load("Images/Rift/Asteroids/3.PNG")
A3 = pygame.transform.scale(A3,100))
A3 = pygame.Surface.convert_alpha(A3)
A4 = pygame.image.load("Images/Rift/Asteroids/4.PNG")
A4 = pygame.transform.scale(A4,100))
A4 = pygame.Surface.convert_alpha(A4)
A5 = pygame.image.load("Images/Rift/Asteroids/5.PNG")
A5 = pygame.transform.scale(A5,100))
A5 = pygame.Surface.convert_alpha(A5)
A6 = pygame.image.load("Images/Rift/Asteroids/6.PNG")
A6 = pygame.transform.scale(A6,100))
A6 = pygame.Surface.convert_alpha(A6)
A7 = pygame.image.load("Images/Rift/Asteroids/7.PNG")
A7 = pygame.transform.scale(A7,100))
A7 = pygame.Surface.convert_alpha(A7)
A8 = pygame.image.load("Images/Rift/Asteroids/8.PNG")
A8 = pygame.transform.scale(A8,100))
A8 = pygame.Surface.convert_alpha(A8)
A9 = pygame.image.load("Images/Rift/Asteroids/9.PNG")
A9 = pygame.transform.scale(A9,100))
A9 = pygame.Surface.convert_alpha(A9)
A10 = pygame.image.load("Images/Rift/Asteroids/10.PNG")
A10 = pygame.transform.scale(A10,100))
A10 = pygame.Surface.convert_alpha(A10)
A11 = pygame.image.load("Images/Rift/Asteroids/11.PNG")
A11 = pygame.transform.scale(A11,100))
A11 = pygame.Surface.convert_alpha(A11)
A12 = pygame.image.load("Images/Rift/Asteroids/12.PNG")
A12 = pygame.transform.scale(A12,(60,100))
A12 = pygame.Surface.convert_alpha(A12)
F1 = pygame.image.load("Images/Rift/Fuel/1.PNG")
F1 = pygame.transform.scale(F1,(150,150))
F2 = pygame.image.load("Images/Rift/Fuel/2.PNG")
F2 = pygame.transform.scale(F2,150))
F3 = pygame.image.load("Images/Rift/Fuel/3.PNG")
F3 = pygame.transform.scale(F3,150))
F4 = pygame.image.load("Images/Rift/Fuel/4.PNG")
F4 = pygame.transform.scale(F4,150))
F5 = pygame.image.load("Images/Rift/Fuel/5.PNG")
F5 = pygame.transform.scale(F5,150))
F6 = pygame.image.load("Images/Rift/Fuel/6.PNG")
F6 = pygame.transform.scale(F6,150))
comet = pygame.image.load("Images/Rift/Comet.PNG")
comet = pygame.transform.scale(comet,(80,250))
moon = pygame.image.load("Images/Rift/Moon - WIP.PNG")
moon = pygame.transform.smoothscale(moon,(1200,1200))
moon = pygame.Surface.convert_alpha(moon)
moonMask = pygame.mask.from_surface(moon)
angle = 0
lasers = []
stretch = []
for i in range(60):
laserImg = pygame.image.load("Images/Rift/Laser/"+str(i+1)+".PNG")
laserImg = pygame.Surface.convert_alpha(laserImg)
stretchTemp = int(15*math.cos(math.pi*i/30))
stretch.append(50 - stretchTemp)
laserImg = pygame.transform.scale(laserImg,(50-stretchTemp,1050))
lasers.append(laserImg)
angle = 0
RiftBG = pygame.image.load("Images/Rift/Background/BG.PNG")
RiftBG = pygame.Surface.convert_alpha(RiftBG)
RiftBG = pygame.transform.smoothscale(RiftBG,(1000,1000))
#Transparent comet warning
def warning(surface,color,rect):
shape_surf = pygame.Surface(pygame.Rect(rect).size,pygame.SRCALPHA)
pygame.draw.rect(shape_surf,shape_surf.get_rect())
surface.blit(shape_surf,rect)
#Moving the ship
def moveShip(shipX,X,angle):
if (X >= 0 and shipX > 100) or (X <= 0 and shipX < 800):
shipX -= X
else:
shipX -= X
angle -= (X*speed)/11
rot_ship = pygame.transform.rotate(ship,angle)
return(shipX,rot_ship,angle)
#Pulling ship towards the middle of the screen
def riftpull(shipX,angle,rot_ship):
if shipX < 440:
if angle > -25:
angle -= 0.1 * speed
else:
angle += 0.1 * speed
shipX,angle = moveShip(shipX,(angle/2.5),angle)
elif shipX > 460:
if angle < 25:
angle += 0.1 * speed
else:
angle -= 0.1 * speed
shipX,angle)
elif 440 < shipX < 460:
if abs(angle) > 1:
angle = angle/1.2
else:
angle = 0
shipX,angle)
return shipX,rot_ship
#Ship Travel through the rift
def rift():
global ship
global rot_ship
global shipX
global speed
global moon
global moonOutline
global moonMask
global distance
speed = 5
angle = 0
laserOn = 2*FPS
laserAnimation = int(FPS/30)
laserFrame = 0
distanceTimer = 0
delay = FPS
laserMode = False
crash = False
key = pygame.key.get_pressed()
wallX = 470
wallY = [-1000,-3000]
rocks = [A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12]
fuel = [F1,F2,F3,F4,F5,F6]
numRock,rockX,rockY,numComet,cometX,cometY,numMoon,moonX,moonY,moonScale,numFuel,fuelX,fuelY = RiftObstacles.path()
rockType = []
rockAngle = []
rockAngle2 = []
rockRot = []
for i in range(numRock):
rockType.append(random.choice(rocks))
rockAngle.append(random.uniform(-0.2,0.2))
rockAngle2.append(rockAngle[i])
fuelType = []
fuelAngle = []
fuelAngle2 = []
fuelRot = []
for i in range(numFuel):
fuelType.append(random.choice(fuel))
fuelAngle.append(random.uniform(-0.2,0.2))
fuelAngle2.append(fuelAngle[i])
warningWidth = []
for i in range(numComet):
warningWidth.append(10)
endRift = False
while endRift == False:
screen.blit(RiftBG,(0,0))
#displaying obstacles
for i in range(numRock):
rockRot.append(pygame.transform.rotate(rockType[i],rockAngle2[i]))
screen.blit(rockRot[i],(rockX[i],rockY[i]))
for i in range(numComet):
screen.blit(comet,(cometX[i],cometY[i]))
if -2000 < cometY[i] < HEIGHT:
warningHEIGHT = HEIGHT - cometY[i]
cometWarning = pygame.Rect(cometX[i]+40 - warningWidth[i]/2,cometY[i]+100,warningWidth[i],warningHEIGHT)
if warningWidth[i] < 78:
warningWidth[i] += 1.5
warning(screen,(250,200,3,127),(cometWarning))
for i in range(numFuel):
fuelRot.append(pygame.transform.rotate(fuelType[i],fuelAngle2[i]))
screen.blit(fuelRot[i],(fuelX[i],fuelY[i]))
if laserMode == True:
laserOn -= 1
if laserOn <= 0:
laserMode = False
rot_laser = pygame.transform.rotate(lasers[laserFrame],angle)
laserAnimation -= 1
if -1 < laserAnimation < 1:
laserAnimation = FPS/30
if laserFrame < 59:
laserFrame += 1
laserRect = rot_laser.get_rect()
if angle == 0:
correction = 50*math.sin((angle*math.pi)/180)
laserRect.midbottom = (shipX + 42 - correction,shipY+100)
elif angle <= 1:
correction = angle*9
laserRect.midbottom = (shipX + 50 - correction,shipY+100)
else:
correction = angle*7
laserRect.midbottom = (shipX + 30 - correction,shipY+100)
screen.blit(rot_laser,laserRect)
if laserMode == False:
laserOn = 180
laserFrame = 0
for i in range(numMoon):
moon = pygame.transform.smoothscale(moon,(int(100*moonScale[i]),int(100*moonScale[i])))
screen.blit(moon,(moonX[i],moonY[i]))
#Ship Movement
screen.blit(rot_ship,(int(shipX),shipY))
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
key = 'left'
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
key = 'right'
#Activating the laser
elif event.key == pygame.K_SPACE:
if laserMode == False:
laserMode = True
else:
key = 'up'
if event.type == pygame.KEYUP:
key = 'up'
if key == 'left':
if angle < 35 and shipX > 50:
angle += 0.2*speed
shipX,angle)
elif key == 'right':
if angle > -35 and shipX < 850:
angle -= 0.2*speed
shipX,angle)
elif key == 'up':
shipX,rot_ship = riftpull(shipX,rot_ship)
#Collision detection
shipRect = pygame.Rect(shipX,shipY,85,125)
shipMask = pygame.mask.from_surface(rot_ship)
if laserMode == True:
rot_laser = pygame.transform.rotate(lasers[laserFrame],angle)
laserRect = rot_laser.get_rect()
laserMask = pygame.mask.from_surface(rot_laser)
remove = []
for i in range(numRock):
rockRect = pygame.Rect(rockX[i],rockY[i],100,100)
if laserMode == True:
if rockRect.colliderect(laserRect):
#print('laser')
#print('o')
rockMask = pygame.mask.from_surface(rockRot[i])
offset_x = laserRect.x - rockRect.x
offset_y = laserRect.y - rockRect.y
laserHit = rockMask.overlap(laserMask,(offset_x,offset_y))
if laserHit:
remove.append(i)
if rockRect.colliderect(shipRect):
rockMask = pygame.mask.from_surface(rockRot[i])
offset_x = shipRect.x - rockRect.x
offset_y = shipRect.y - rockRect.y
crash = rockMask.overlap(shipMask,offset_y))
for i in range(len(remove)):
numRock -= 1
rockX.pop(remove[i])
rockY.pop(remove[i])
rockType.pop(remove[i])
rockAngle.pop(remove[i])
rockAngle2.pop(remove[i])
rockRot.pop(remove[i])
remove = []
for i in range(numComet):
cometRect = pygame.Rect(cometX[i],cometY[i],80,250)
if cometRect.colliderect(shipRect):
cometMask = pygame.mask.from_surface(comet)
offset_x = shipRect.x - cometRect.x
offset_y = shipRect.y - cometRect.y
crash = cometMask.overlap(shipMask,offset_y))
remove = []
for i in range(numMoon):
moonRect = pygame.Rect(moonX[i],moonY[i],int(100*moonScale[i]),int(100*moonScale[i]))
if int(50*moonScale[i]+60)**2 >= ((shipX+40 - moonX[i]-int(50*moonScale[i]))**2 + (shipY+100 - moonY[i]-int(50*moonScale[i]))**2) and not crash:
moonMask = pygame.mask.from_surface(moon)
offset_x = shipRect.x - moonRect.x
offset_y = shipRect.y - moonRect.y
crash = moonMask.overlap(shipMask,offset_y))
remove = []
for i in range(numFuel):
fuelRect = pygame.Rect(fuelX[i],fuelY[i],100)
if fuelRect.colliderect(shipRect):
fuelMask = pygame.mask.from_surface(fuelRot[i])
offset_x = shipRect.x - fuelRect.x
offset_y = shipRect.y - fuelRect.y
fuelHit = fuelMask.overlap(shipMask,offset_y))
if fuelHit:
remove.append(i)
for i in range(len(remove)):
numFuel -= 1
fuelX.pop(remove[i])
fuelY.pop(remove[i])
fuelType.pop(remove[i])
fuelAngle.pop(remove[i])
fuelAngle2.pop(remove[i])
fuelRot.pop(remove[i])
remove = []
#Moves objects down screen
rockRot = []
fuelRot = []
for i in range(numRock):
rockY[i] += speed
rockAngle2[i] += rockAngle[i]
for i in range(numMoon):
moonY[i] += speed
for i in range(numComet):
cometY[i] += speed * 5
if cometY[i] > HEIGHT:
warningWidth[i] = 10
for i in range(numFuel):
fuelY[i] += speed
fuelAngle2[i] += fuelAngle[i]
#Choosing a new path
rockPassed = HEIGHT+1
cometPassed = HEIGHT+1
moonPassed = HEIGHT+1
if len(rockY) != 0:
rockPassed = rockY[-1]
if len(cometY) != 0:
cometPassed = cometY[-1]
if len(moonY) != 0:
moonPassed = moonY[-1]
if rockPassed > HEIGHT and cometPassed > HEIGHT and moonPassed > HEIGHT:
numRock,fuelY = RiftObstacles.path()
rockType = []
rockAngle = []
rockAngle2 = []
rockRot = []
fuelType = []
fuelAngle = []
fuelAngle2 = []
fuelRot = []
for i in range(numRock):
rockType.append(random.choice(rocks))
rockAngle.append(random.uniform(-0.2,0.2))
rockAngle2.append(rockAngle[i])
for i in range(numFuel):
fuelType.append(random.choice(fuel))
fuelAngle.append(random.uniform(-0.2,0.2))
fuelAngle2.append(fuelAngle[i])
warningWidth = []
for i in range(numComet):
warningWidth.append(10)
#Shows that collision between the ship works with obstacles
if crash:
#print('crash')
crash = False
pygame.display.update()
clock.tick(FPS)
distance = 0
active = True
while active:
rift()
pygame.quit()
解决方法
pygame.Surface.get_rect.get_rect()
返回一个具有 Surface 对象大小的矩形,该矩形总是从 (0,0) 开始,因为 Surface 对象没有位置。 表面 blit
位于屏幕上的某个位置。矩形的位置可以通过关键字参数指定。例如,矩形的中心可以用关键字参数 center
指定。这些关键字参数在返回之前应用于 pygame.Rect
的属性(有关关键字参数的完整列表,请参阅 pygame.Rect
)。
确保始终设置 laserRect
的位置。位置设置在这里:
laserRect = rot_laser.get_rect()
if angle == 0:
correction = 50*math.sin((angle*math.pi)/180)
laserRect.midbottom = (shipX + 42 - correction,shipY+100)
但是这里没有设置:
if laserMode == True:
rot_laser = pygame.transform.rotate(lasers[laserFrame],angle)
laserRect = rot_laser.get_rect()
laserMask = pygame.mask.from_surface(rot_laser)
由于laserRect
之前设置正确,以后就不需要get了
if laserMode == True:
rot_laser = pygame.transform.rotate(lasers[laserFrame],angle)
# delete
#laserRect = rot_laser.get_rect()
laserMask = pygame.mask.from_surface(rot_laser)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。