python - pygame 中的碰撞帮助以及当您使用角度和速度移动时如何阻止它撞到墙壁
问题描述
我很可能没有正确初始化矩形,所以玩家经常“跳墙”,这不是故意的。我很可能没有正确初始化矩形,所以玩家经常“跳墙”,这不是故意的。我很可能没有正确初始化矩形,所以玩家经常“跳墙”,这不是故意的。
这是主要的:
import pygame
import wall
import Player
import math
pygame.init()
pygame.display.set_caption("Tanki")
pygame.display.set_icon(pygame.image.load("mainIcon.png"))
running = True
screen = pygame.display.set_mode((300, 500))
WALLS = pygame.sprite.Group()
fence = \
[wall.Wall(0, 0, 300, 10, pygame.Color(255, 255, 255), screen),
wall.Wall(290, 0, 10, 500, pygame.Color(255, 255, 255), screen),
wall.Wall(0, 0, 10, 500, pygame.Color(255, 255, 255), screen),
wall.Wall(0, 490, 300, 10, pygame.Color(255, 255, 255), screen),
# boundry
wall.Wall(10 + 60, 235, 50, 10, pygame.Color(255, 255, 255), screen),
wall.Wall(10 + 60 + 50 + 60, 235, 50, 10, pygame.Color(255, 255, 255), screen),
# middle blocks
wall.Wall(100, ((245 + 500 - 60) / 2) - 5, 100, 10, pygame.Color(255, 255, 255), screen),
wall.Wall(100, ((235 + 60) / 2) - 5, 100, 10, pygame.Color(255, 255, 255), screen),
wall.Wall(10 + 66.666, 440, 66.666 + 80, 10, pygame.Color(255, 255, 255), screen),
wall.Wall(10 + 66.666, 430, 10, 10, pygame.Color(255, 255, 255), screen),
wall.Wall(10 + 66.666 * 2 + 80 - 11, 430, 10, 10, pygame.Color(255, 255, 255), screen),
# everythin around the goal
wall.Wall(10 + 66.666 + 10, 430, 66.666 + 80 - 11 - 9, 10, pygame.Color(0, 0, 200), screen),
# the bottom goal MAKE A CLASS FOR THIS
wall.Wall(10 + 66.666, 50, 66.666 + 80, 10, pygame.Color(255, 255, 255), screen),
wall.Wall(10 + 66.666, 60, 10, 10, pygame.Color(255, 255, 255), screen),
wall.Wall(10 + 66.666 * 2 + 80 - 11, 60, 10, 10, pygame.Color(255, 255, 255), screen),
# everythin around the goal
wall.Wall(10 + 66.666 + 10, 60, 66.666 + 80 - 11 - 9, 10, pygame.Color(200, 0, 0), screen)
# the top goal
]
tmp = Player.Player(pygame.Color(0, 255, 0), 20, 20, 140, 455, 0.05, 180, 0)
pro = Player.Player(pygame.Color(0, 255, 0), 20, 20, 140, 455, 0.05, 180, tmp)
for eachwall in fence:
WALLS.add(eachwall)
count = 1
while running:
count += 1
print(pro.getAngle() % 360)
if (count % 10 == 0):
tmp.updatetmp(pro)
screen.fill(pygame.Color(0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
pro.setAngle(pro.getAngle() - 10)
if event.key == pygame.K_RIGHT:
pro.setAngle(pro.getAngle() + 10)
if event.key == pygame.K_UP:
pro.setVel(0.05)
if event.key == pygame.K_DOWN:
pro.setVel(-0.05)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
pro.setVel(0)
b = True
for block in WALLS:
if (pygame.sprite.collide_rect(pro, block)):
b = False
print("A")
a = pro.update(WALLS, screen,b)
for awall in WALLS:
awall.draw()
pygame.display.update()
这是播放器
import pygame
import math
class Player(pygame.sprite.Sprite):
direction = 'right'
def __init__(self, color, width, height, x, y, velocity, angle, past):
# Pygame constructor
pygame.sprite.Sprite.__init__(self)
self.past = past
# Init. variables
self.angle = angle
self.velocity = velocity
self.color = color
self.width = width
self.height = height
self.x = x
self.y = y
# Create sprite
self.image = pygame.Surface([width, height])
self.image.fill(self.color)
self.rect = self.image.get_rect(topleft = (self.x, self.y))
#############################
def setColor(self, color):
self.color = color
def setX(self, X):
self.x = X
def setY(self, Y):
self.y = Y
def setVel(self, vel):
self.velocity = vel
def setAngle(self, ANGLE):
self.angle = ANGLE
##############################
def getColor(self):
return self.color
def getX(self):
return self.x
def getY(self):
return self.y
def getVel(self):
return self.velocity
def getAngle(self):
return self.angle
#################################
def draw(self, screen):
# Draw player on the screen
pygame.draw.rect(screen, self.color, [self.x, self.y, self.width, self.height], 0)
def deg_to_rad(self):
return int(self.angle * math.pi) / 180
def rad_to_offset(self, offset): # insert better func name.
radians = self.deg_to_rad()
x = math.cos(radians) * offset
y = math.sin(radians) * offset
return [x, y]
def move(self, walls, go):
if go:
forward = self.rad_to_offset(self.velocity)
self.x += forward[0]
self.y += forward[1]
else:
print("collided")
def update(self, walls, screen, go):
if(self.angle>=360):
self.angle = self.angle%360
hit = self.move(walls, go)
self.draw(screen)
return hit
def updatetmp(self, Player):
self.angle = Player.getAngle()
self.velocity = Player.getVel()
self.color = Player.getColor()
self.x = Player.getX()
self.y = Player.getY()
这是墙类
import pygame
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, color, screen):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.height = height
self.width = width
self.color = color
self.screen = screen
self.image = pygame.Surface((width, height))
self.image.fill(color)
self.rect = self.image.get_rect(topleft = (self.x, self.y))
def get_rectangle(self):
return pygame.Rect(self.x, self.y, self.width, self.height)
def draw(self):
pygame.draw.rect(self.screen, self.color, (self.x, self.y, self.width, self.height), 0)
解决方案
类似pygame.sprite.collide_rect()
或pygame.sprite.spritecollide()
使用对象.rect
属性的操作Sprite
来执行碰撞测试。
对象播放器由浮点属性.x
和定位.y
。您必须将此位置同步到.rect
更新中的(整体)属性,以使碰撞测试工作:
class Player(pygame.sprite.Sprite):
# [...]
def update(self, walls, screen, go):
if(self.angle>=360):
self.angle = self.angle%360
hit = self.move(walls, go)
self.rect.topleft = (round(self.x), round(self.y)) # <-----
self.draw(screen)
return hit
此外,没有必要迭代 all WALLS
:
for block in WALLS: if pygame.sprite.collide_rect(pro, block): b = False print("A")
使用pygame.sprite.spritecollide()
而不是`pygame.sprite.collide_rect()`
if pygame.sprite.spritecollide(pro, WALLS, False):
b = False
print("A")
请注意,没有必要在和中实现draw()
方法。您可以使用. 这个方便的方法使用包含的 Sprite 对象的和属性来绘制它们。Player
Wall
draw()
Group
.rect
.image
删除 和的draw
方法。将玩家和墙添加到组并在组上调用:Player
Wall
draw()
fence = \
[wall.Wall(0, 0, 300, 10, pygame.Color(255, 255, 255), screen),
# [...]
]
tmp = Player.Player(pygame.Color(0, 255, 0), 20, 20, 140, 455, 0.05, 180, 0)
pro = Player.Player(pygame.Color(0, 255, 0), 20, 20, 140, 455, 0.05, 180, tmp)
WALLS = pygame.sprite.Group(fence)
players = pygame.sprite.Group([tmp, pro])
count = 1
while running:
count += 1
# [...]
WALLS.draw(screen)
players.draw(screen)
pygame.display.update()
推荐阅读
- c++ - 为什么使用多重继承时我的 Hippomock 期望失败
- python - AttributeError:模块“tensorflow”没有属性“assign”
- tensorflow - LSTM 层输出大小与 KERAS 中的隐藏状态大小
- php - foreach 中未定义的属性,除非 print_r'd
- php - .htaccess FilesMatch 以阻止 php 执行名称包含大写字母的 php 文件
- cassandra - 增加 roles_validity_in_ms 和 permissions_validity_in_ms 的影响
- ios - 在 Xcode 11 中通过 Fastlane 构建 SPM 包不起作用
- c# - OpenXML 将行追加到 Word 中的现有表
- node.js - 我无法通过公共 IP 访问我的 Docker Node.js 容器
- azure - 我们可以在一个 yaml 文件中有多个触发器来执行不同的作业吗?