我在尝试理解如何检测"时遇到严重问题。如果有什么东西在假想的视线中#34;玩家我创造了一个简单的墙。想法是在玩家瞄准墙壁并同时点击鼠标点击按钮时打印一些东西。
这是我的代码:
import sys
import pygame
import math
pygame.init()
screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))
running = True
class Actor:
def __init__(self, x, y, w, h):
self.x = x
self.y = y
self.w = w
self.h = h
class Wall:
def __init__(self):
Actor.__init__(self, 300, 100, 128, 32)
self.surface = pygame.Surface((self.w, self.h))
self.surface.fill((0, 0, 0))
def draw(self):
screen.blit(self.surface, (self.x, self.y))
class Player(Actor):
def __init__(self):
Actor.__init__(self, 0, 0, 64, 64)
self.surface = pygame.transform.scale(pygame.image.load("GFX/player.png"), (self.w, self.h))
self.rotated_surface = self.surface.copy()
self.rect = self.surface.get_rect()
self.directions = [False, False, False, False]
self.speed = 0.1
self.running = False
def rotate(self):
mouse_x = pygame.mouse.get_pos()[0]
mouse_y = pygame.mouse.get_pos()[1]
angle = math.atan2(mouse_y - (self.y + (self.w / 2)), mouse_x - (self.x + (self.w / 2)))
angle = angle * (180 / math.pi)
rot_image = pygame.transform.rotozoom(self.surface, -angle + 270, 1)
rot_rect = self.rect.copy()
rot_rect.center = rot_image.get_rect().center
self.rotated_surface = rot_image
def move(self):
if self.directions[0]:
self.y -= self.speed
if self.directions[1]:
self.y += self.speed
if self.directions[2]:
self.x -= self.speed
if self.directions[3]:
self.x += self.speed
if self.running:
self.speed = 0.2
else:
self.speed = 0.1
def draw(self):
screen.blit(self.rotated_surface, (self.x, self.y))
pygame.draw.aaline(screen, (0, 255, 0), (player.x + (player.w / 2), player.y), pygame.mouse.get_pos())
def fire(self, actor):
bullet_x_pos = self.x + (self.w / 2)
bullet_y_pos = self.y
# ...
player = Player()
wall = Wall()
def redraw():
screen.fill((75, 0, 0))
player.draw()
player.move()
wall.draw()
pygame.display.flip()
while (running):
for e in pygame.event.get():
if e.type == pygame.QUIT:
sys.exit()
elif e.type == pygame.KEYDOWN:
if e.key == pygame.K_ESCAPE:
sys.exit()
if e.key == pygame.K_w:
player.directions[0] = True
if e.key == pygame.K_s:
player.directions[1] = True
if e.key == pygame.K_a:
player.directions[2] = True
if e.key == pygame.K_d:
player.directions[3] = True
if e.key == pygame.K_LSHIFT:
player.running = True
elif e.type == pygame.KEYUP:
if e.key == pygame.K_w:
player.directions[0] = False
if e.key == pygame.K_s:
player.directions[1] = False
if e.key == pygame.K_a:
player.directions[2] = False
if e.key == pygame.K_d:
player.directions[3] = False
if e.key == pygame.K_LSHIFT:
player.running = False
elif e.type == pygame.MOUSEMOTION:
player.rotate()
elif e.type == pygame.MOUSEBUTTONDOWN:
print("Yep")
redraw()
这是图像:
网上关于它的资料不足,特别是对于Python / Pygame(我猜摄影师在图书馆中并不常见)。我不知道如何根据atan2返回的角度返回一个布尔值,告诉我玩家瞄准的是对象。
答案 0 :(得分:1)
Python的atan2有点神奇,人们不必为了获得完整的360度角而使用“x”和“y”方向的符号。 Ant Python的数学模型甚至有一个函数可以将弧度结果转换回度数(然后,只将负数加360到0:360范围而不是-180:180)。
考虑到这一点,只需要小心地确定位置 - 您可以通过检查所有矩形角方向并选择最多来检查矩形的“视线”相对于给定位置的最小和最大角度极端值。 也就是说,由于发现了循环值,有很多极端情况 - 我想我已经覆盖了所有这些。
class Actor(object):
def __init__(self, x, y, w, h):
self.x = x
self.y = y
self.w = w
self.h = h
def __len__(self):
return 4
def __getitem__(self, item):
return {0: self.x, 1: self.y, 2: self.w, 3: self.h}[item]
def get_direction_range(rect, position):
min_d = 181
max_d = -181
# Due to the cases where the target rect crosses the 180, -180 line, always keep the bottom corners last:
for corner in (('top', 'left'), ('top', 'right'), ('bottom', 'left'), ('bottom', 'right')):
tx, ty = getattr(rect, corner[1]), getattr(rect, corner[0])
print(tx, ty)
# Calculate vector from given position to target corner
vx = tx - position[0]
vy = -(ty - position[1])
direction = math.degrees(math.atan2(vy, vx))
if direction < min_d and (not (direction < 0 and min_d > 0 and min_d > 90) or min_d == 181) :
min_d = direction
if direction > max_d or (direction < 0 and max_d > 0 and max_d > 90):
print(direction, "max")
max_d = direction
min_d += 0 if min_d > 0 else 360
max_d += 0 if max_d > 0 else 360
return min_d, max_d
def check_target(direction, position, rect):
if not isinstance(rect, pygame.Rect):
rect = pygame.Rect(rect)
if position in rect:
return True
min_d, max_d = get_direction_range(rect, position)
if max_d < min_d:
max_d, min_d = min_d, max_d
if abs(max_d - min_d) > 180:
return max_d <= direction <= 360 or 0 <= direction <= min_d
return min_d <= direction <= max_d
def dl(scr, pos, direction):
xx = math.cos(math.radians(direction)) * 200
yy = -math.sin(math.radians(direction)) * 200
pygame.draw.line(scr, (0,255,0), pos, (pos[0] + xx, pos[1] + yy))
pygame.display.flip()
你可以让那个“Actor”类派生自pygame.Rect(如果你不能使用Rect本身) - 我在它上面添加了方法,所以它至少可以转换为Rect,这样我们就可以轻松地选择角落坐标。
无论如何,请注意,如果您使用的是Python 2.x(我相信,由于在Python3下安装pygame很困难),所有类应该继承自object
。< / p>
我以前在活动会话中调试的dl
函数 - 它对你也很有用。