光线会继续投射在错误的“墙壁”上,但前提是灯位于右下角。如果灯泡在左上角,则一切正常。
我尝试了很多事情,但是上次遇到问题时,我写了很多遍检查配方设计师,最后这是配方设计师的问题,所以我什至不愿意尝试
(https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection)
查找最近的墙的功能:
def draw(self):
bestdist = 1000000000000000000
for obs in run.Obs:
x1, y1 = obs.startp
x2, y2 = obs.endp
x3, y3 = run.lamp
x4, y4 = self.maxendpoint
d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
if d != 0:
t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / d
u = ((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / d
if 0 < t < 1 and u > 0:
px = round(x1 + t * (x2 - x1))
py = round(y1 + t * (y2 - y1))
dist = px**2+py**2
if dist < bestdist:
bestdist = dist
self.endpoint= [px, py]
# pygame.draw.circle(run.screen, pygame.Color('green'), (px, py), 3)
if len(self.endpoint) == 2:
pygame.draw.line(run.screen, pygame.Color('white'), run.lamp, self.endpoint)
整个代码:
import pygame
import sys
import math
import random as rd
import numpy as np
class Obs(object):
def __init__(self, startp, endp):
self.startp = startp
self.endp = endp
def drawww(self):
pygame.draw.line(run.screen, pygame.Color('red'), (self.startp), (self.endp))
class rays(object):
def __init__(self, maxendpoint):
self.maxendpoint = maxendpoint
self.endpoint = []
def draw(self):
bestdist = 1000000000000000000
for obs in run.Obs:
x1, y1 = obs.startp
x2, y2 = obs.endp
x3, y3 = run.lamp
x4, y4 = self.maxendpoint
d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
if d != 0:
t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / d
u = ((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / d
if 0 < t < 1 and u > 0:
px = round(x1 + t * (x2 - x1))
py = round(y1 + t * (y2 - y1))
dist = px**2+py**2
if dist < bestdist:
bestdist = dist
self.endpoint= [px, py]
# pygame.draw.circle(run.screen, pygame.Color('green'), (px, py), 3)
if len(self.endpoint) == 2:
pygame.draw.line(run.screen, pygame.Color('white'), run.lamp, self.endpoint)
class Control(object):
def __init__(self):
self.winw = 800
self.winh = 800
self.screen = pygame.display.set_mode((self.winw, self.winh))
self.fps = 60
self.clock = pygame.time.Clock()
self.lamp = [round(self.winw/2), round(self.winh/2)]
self.lampr = 13
self.lines = []
self.r = 5
self.Obs = []
self.angel = 0
self.fov = 360
self.scene = np.ones(self.fov)
self.done = False
self.makeobs()
def event_loop(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_F5:
self.__init__()
elif event.key == pygame.K_LEFT:
if self.angel <= 0:
self.angel = 360
else:
self.angel -= 5
elif event.key == pygame.K_RIGHT:
if self.angel >= 360:
self.angel = 0
else:
self.angel += 5
elif event.key == pygame.K_w:
self.lamp[1] -= 10
elif event.key == pygame.K_a:
self.lamp[0] -= 10
elif event.key == pygame.K_s:
self.lamp[1] += 10
elif event.key == pygame.K_d:
self.lamp[0] += 10
elif event.key == pygame.K_y:
pass
if pygame.mouse.get_pressed() == (1, 0, 0):
if pygame.mouse.get_pos()[0] > 800:
self.lamp = [799, pygame.mouse.get_pos()[1]]
else:
self.lamp[0] = pygame.mouse.get_pos()[0]
self.lamp[1] = pygame.mouse.get_pos()[1]
def draw(self):
self.screen.fill((pygame.Color('black')))
pygame.draw.circle(self.screen, pygame.Color('white'), self.lamp, self.lampr)
for obs in self.Obs:
obs.drawww()
for line in self.lines:
line.draw()
def makeobs(self):
for i in range(2):
self.Obs.append(Obs((rd.randint(0, self.winw), rd.randint(0, self.winh)),
(rd.randint(0, self.winw), rd.randint(0, self.winh))))
# self.Obs.append(Obs((0, 0), (self.winw, 0)))
# self.Obs.append(Obs((0, 0), (0, self.winh)))
# self.Obs.append(Obs((self.winw, 0), (self.winw, self.winh)))
# self.Obs.append(Obs((0, self.winh), (self.winw, self.winh)))
def createlines(self):
self.lines.clear()
for angle in range(self.angel, self.angel+self.fov):
angle = math.radians(angle)
self.lines.append(rays([self.lamp[0] + math.cos(angle), self.lamp[1] + math.sin(angle)]))
def main_loop(self):
while not self.done:
self.event_loop()
self.createlines()
self.draw()
pygame.display.update()
self.clock.tick(self.fps)
pygame.display.set_caption(f"Draw FPS: {self.clock.get_fps()}")
if __name__ == '__main__':
run = Control()
run.main_loop()
pygame.quit()
sys.exit()
预计无论灯泡在哪里,它都可以工作。
答案 0 :(得分:1)
代码
px = round(x1 + t * (x2 - x1)) py = round(y1 + t * (y2 - y1)) dist = px**2+py**2
没有任何意义,因为(py, py)
是一个点,因此dist = px**2+py**2
是从原点(0, 0)
到(py, py)
的平方Euclidean distance。
您必须计算从(x3, x4)
到交点的距离:
vx = u * (x4 - x3)
vy = u * (y4 - y3)
dist = vx**2+vy**2
在计算u
时还有一个问题:
u = ((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / d
u = ((x1 - x3) * (y1 - y2) - (y1 - y3) * (x1 - x2)) / d
方法类rays
:
class rays(object):
def __init__(self, maxendpoint):
self.maxendpoint = maxendpoint
self.endpoint = []
def draw(self):
bestdist = 1000000000000000000
for obs in run.Obs:
x1, y1 = obs.startp
x2, y2 = obs.endp
x3, y3 = run.lamp
x4, y4 = self.maxendpoint
d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
if d != 0:
t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / d
u = ((x1 - x3) * (y1 - y2) - (y1 - y3) * (x1 - x2)) / d
if 0 < t < 1 and u > 0:
vx = u * (x4 - x3)
vy = u * (y4 - y3)
dist = vx**2+vy**2
if dist < bestdist:
px = round(x3 + u * (x4 - x3))
py = round(y3 + u * (y4 - y3))
bestdist = dist
self.endpoint= [px, py]
# pygame.draw.circle(run.screen, pygame.Color('green'), (px, py), 3)
if len(self.endpoint) == 2:
pygame.draw.line(run.screen, pygame.Color('white'), run.lamp, self.endpoint)