с использованием pygame (только с python)
Расшифровка: я изучаю трассировку лучей, и я хотел сделать зеркала (без силы света, 0% прозрачное зеркало), classi c, направляющий источники света желтые, отражающие оранжевые, а отражающие отражающие - красные, а иногда, когда источник света попадает в зеркало, он создает отражение (basi c), а затем появляется другое отражение (всегда красное, (это может помочь)), проходящее через него. зеркало с тем же углом, что и источник света (непосредственно через него (но оно становится красным (отражение при отражении)))
есть код моей стены / зеркала
class Boundary:
def __init__(self, screen: pg.display, start: tuple, end: tuple,state: str):
self.start = pg.Vector2(start)
self.end = pg.Vector2(end)
self.image = None
self.state=state
self.color=(255,255,255)
self.tagged_rays="" # None
if self.state=="mirror":
self.color = (0,255,255)
self.tagged_rays=[]
def update(self, screen: pg.display):
if self.state=="mirror":
## writes the len of the tagged rays list var
screen.blit(pg.font.SysFont("helvetica", 10).render("{}".format(len(self.tagged_rays)), 10, (0,255,0)), (int(self.start.x+10), int(self.start.y)))
self.tagged_rays=[]
#print(len(self.tagged_rays))
## draw the wall / the mirror
self.image = pg.draw.line(screen, (self.color), self.start, self.end, 2)
экран ошибки
![](https://i.stack.imgur.com/to8Jq.png)
есть код моего луча
class Ray:
def __init__(self, p: Particle, heading: float = 0):
self.start = p.pos
self.heading = heading
self.end: pg.math.Vector2 = pg.math.Vector2()
self.image = None
#self.color = (randint(215,225),randint(175,200),0)
self.color =(255,255,0)
self.isrefleted=False
self.reflect_angle=0
def update(self, screen: pg.display, p: Particle, boundaries: list, rays:list, reflections:list):
self.isrefleted=False
self.start = p.pos
self.end.from_polar((sys.maxsize, self.heading))
closest = float("inf")
new_end = pg.Vector2()
x3 = self.start.x
x4 = self.end.x
y3 = self.start.y
y4 = self.end.y
for b in boundaries:
if b.state == "mirror" and self in b.tagged_rays:
continue
x1 = b.start.x
x2 = b.end.x
y1 = b.start.y
y2 = b.end.y
den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
if den == 0:
return
t_num = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)
t = t_num / den
u_num = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3))
u = u_num / den
if u >= 0 and 0 <= t <= 1:
x = x1 + t * (x2 - x1)
y = y1 + t * (y2 - y1)
dist = self.start.distance_to((x, y))
if dist < closest:
closest = dist
new_end.xy = x, y
if b.state=="mirror":
#print("REFLET")
#print(self.start.x-new_end.x,",",b.start.x-b.start.y)
radius1, self.reflect_angle1 = (self.start - self.end).as_polar()
radius2, self.reflect_angle2 = (b.start - b.end).as_polar()
#radius2, self.reflect_angle3 = (self.reflect_angle1 - self.reflect_angle2).as_polar()
if self.start.x < self.end.x:
#print(self.reflect_angle2,"pos")
self.reflect_angle2-=90
elif self.start.x > self.end.x:
#print(self.reflect_angle2,"neg")
self.reflect_angle2+=90
else:
pass
#print()
## 90* from the miror ( to understand the mechanics )
_90_reflet= False
if _90_reflet:
reflect2= Reflect(new_end, self.reflect_angle2,(0,255,0))
b.tagged_rays.append(reflect2)
reflections.append(reflect2)
reflect= Reflect(new_end, -self.reflect_angle1,(255,100,0))
b.tagged_rays.append(reflect)
reflections.append(reflect)
self.isrefleted=True
if closest == float("inf"):
self.end = self.start
self.image = None
else:
self.end = new_end
self.image = pg.draw.line(screen, self.color, (self.start.x,self.start.y), (self.end), 1)
anglepos=pg.math.Vector2()
anglepos.x = int(self.end.x)
anglepos.y= int(self.end.y)
w, h = pg.display.get_surface().get_size()
xoffset=10
yoffset=-3
if anglepos.x+len(str(self.heading)) >w:
anglepos.x -=50
if anglepos.y+10 >h:
anglepos.y -=20
if 0> anglepos.y:
anglepos.y=+10
screen.blit(pg.font.SysFont("helvetica", 11).render("{}".format(self.heading), 10, (0,255,255)), (int(anglepos.x+xoffset), int(anglepos.y+yoffset)))
#pg.draw.circle(screen,(255,0,0), (int(self.end.x),int(self.end.y)),5)
и там код моего отраженного луча
from particle import Particle
import pygame as pg
from random import randint
import math,sys
class Reflect:
def __init__(self, r_End, heading: float = 0,color: tuple=(255,0,0)):
self.start= r_End
self.heading=heading
self.end: pg.math.Vector2 = pg.math.Vector2()
self.color =color
self.isrefleted=False
def update(self, screen: pg.display, p: Particle, boundaries: list,rays:list,reflections:list):
self.isrefleted=False
self.end.from_polar((sys.maxsize, self.heading))
closest = float("inf")
new_end = pg.Vector2()
x3 = self.start.x+3
x4 = self.end.x
y3 = self.start.y
y4 = self.end.y
for b in boundaries:
if b.state == "mirror" and self in b.tagged_rays:
continue
x1 = b.start.x
x2 = b.end.x
y1 = b.start.y
y2 = b.end.y
den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
if den == 0:
return
t_num = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)
t = t_num / den
u_num = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3))
u = u_num / den
if u >= 0 and 0 <= t <= 1:
x = x1 + t * (x2 - x1)
y = y1 + t * (y2 - y1)
dist = self.start.distance_to((x, y))
if dist < closest:
closest = dist
new_end.xy = x, y
if b.state=="mirror" and 1:
#print("REFLET")
#print(self.start.x-new_end.x,",",b.start.x-b.start.y)
radius1, self.reflect_angle1 = (self.start - self.end).as_polar()
radius2, self.reflect_angle2 = (b.start - b.end).as_polar()
#radius2, self.reflect_angle3 = (self.reflect_angle1 - self.reflect_angle2).as_polar()
if self.start.x < self.end.x:
#print(self.reflect_angle2,"pos")
self.reflect_angle2-=90
elif self.start.x > self.end.x:
#print(self.reflect_angle2,"neg")
self.reflect_angle2+=90
else:
pass
#print()
## 90* from the miror ( to understand the mechanics )
_90_reflet= False
if _90_reflet:
reflect2= Reflect(new_end, self.reflect_angle2,(0,255,0))
b.tagged_rays.append(reflect2)
reflections.append(reflect2)
if not -1<abs(self.heading) <1:
if not 179<abs(self.heading) <181:
#print(self.heading)
reflect=None
reflect= Reflect(new_end, -self.reflect_angle1,(255,0,0))
b.tagged_rays.append(reflect)
reflections.append(reflect)
self.isrefleted=True
if closest == float("inf"):
self.end = self.start
self.image = None
else:
self.end = new_end
#print(self.end)
self.image = pg.draw.line(screen, self.color, self.start, self.end,2)
anglepos=pg.math.Vector2()
anglepos.x = int(self.end.x)
anglepos.y= int(self.end.y)
w, h = pg.display.get_surface().get_size()
xoffset=10
yoffset=-3
if anglepos.x+len(str(self.heading)) >w:
anglepos.x -=50
if anglepos.y+10 >h:
anglepos.y -=20
if 0> anglepos.y:
anglepos.y=+10
screen.blit(pg.font.SysFont("helvetica", 11).render("{}".format(self.heading), 10, (0,255,255)), (int(anglepos.x+xoffset), int(anglepos.y+yoffset)))
#pg.draw.circle(screen,(255,0,0), (int(self.end.x),int(self.end.y)),5)
Правка, есть код частицы
import pygame as pg
from random import randint
class Particle:
def __init__(self):
info = pg.display.Info()
self.image = None
pg.math.Vector2()
self.pos = pg.Vector2(randint(0, info.current_w), randint(0, info.current_h))
self.heading = 0
self.vel = pg.math.Vector2((0, 0))
def update(self, screen: pg.display,mouseX=int(),mouseY=int()):
#self.move_random()
self.move_on_mouse(mouseX,mouseY)
self.image = pg.draw.circle(screen, pg.Color('white'), (int(self.pos[0]), int(self.pos[1])), 4, 2) #basic (random)
def move_random(self):
info = pg.display.Info()
self.pos += self.vel
if self.pos.x < 0:
self.pos.x = 0
self.vel.x += 5
elif self.pos.x > info.current_w:
self.pos.x = info.current_w - 1
self.vel.x -= 5
if self.pos.y < 0:
self.pos.y = 0
self.vel.y += 5
elif self.pos.y > info.current_h:
self.pos.y = info.current_h - 1
self.vel.y -= 5
self.vel.x += randint(-5, 5)
self.vel.y += randint(-5, 5)
def move_on_mouse(self,mouseX=int(),mouseY=int()):
self.pos = pg.Vector2(mouseX, mouseY)