Quindi sto usando pygame
per creare un semplice sparatutto dall'alto verso il basso, e sto facendo molti calcoli con l'angolo dalla prospettiva dall'alto verso il basso. Usiamo una semplice freccia e una palla come esempio, voglio che la freccia rossa continui a puntare sulla palla blu indipendentemente da dove si muove la pallina blu:
Emièsembratoabbastanzafacile,avevosolobisognodiatan2
:
angle=math.atan2(blue.y-red.y,blue.x-red.x)
Mailproblemaècheatan2
funzionaperunagrigliadicoordinatematematichecomequesta:
Dovealpha=math.atan2(blue.y-red.y,blue.x-red.x)
Malacosaconpygame
(almenosuWindows)èchelagrigliadellecoordinatenonfunzionacomeunagrigliadicoordinatematematiche,inrealtàècapovoltaapartiredall'angoloinaltoasinistradellafinestradigioco:
Quindi,mentresembrachelapallinablusiapiùinaltoequindimatematicamenteblue.y
dovrebbeesseremaggioredired.y
,questoinrealtànonèilcasoacausadellagrigliadicoordinatecapovolta,chemath.atan2()
diPythonnonloso,eilcalcolooriginalechehoavuto:
angle=math.atan2(blue.y-red.y,blue.x-red.x)
Produceeffettivamentelanegazionedell'angolocorretto.
Oral'ovviaprimasoluzionechehotrovatoèstatadicapovolgereilsegno,eabbastanzagiustohafunzionatoconquesto:
angle=-math.atan2(blue.y-red.y,blue.x-red.x)
Maiproblemisonoricominciatiunavoltacheavevobisognodifareulterioricalcolibasatisull'angolocalcolatoinprecedenza,chetecnicamenteèoracapovolto.
Qualicontromisurepossoprendereper"permanentemente" sbarazzarmi di questo problema?
Ecco un esempio reale di dove ho bisogno di questo, ho un'entità "zombi" che non fa altro che seguire l'obiettivo che è stato dato:
class Zombie(Entity):
def __init__(self, *args, target=None, **kwargs):
super().__init__(*args, **kwargs)
self.target = target
def update(self, dt, app):
if self.target:
# Face towards target
dx = self.target.x - self.x
dy = self.target.y - self.y
self.angle = math.atan2(dy, dx)
# Change velocity towards target
speed = self.get_max_speed()
vel_x = math.cos(angle) * speed
vel_y = math.sin(angle) * speed
self.velocity = (vel_x, vel_y)
else:
self.velocity = (0, 0)
# Moves the zombie based on velocity
super().update(dt, app)
Per questo caso specifico sono riuscito a risolverlo memorizzando l'angolo in una variabile separata per un uso successivo, e annullandolo separatamente dopo aver impostato self.angle
:
# Face towards target
dx = self.target.x - self.x
dy = self.target.y - self.y
angle = math.atan2(dy, dx)
self.angle = -angle
# Change velocity towards target
speed = self.get_max_speed()
vel_x = math.cos(angle) * speed
vel_y = math.sin(angle) * speed
self.velocity = (vel_x, vel_y)
Ma questo è solo l'elemosina di altri bug, e sto cercando una soluzione più generica al problema.