Prometi, aqui está. O mestrado começou e percebi que ele vai destruir o que resta de minha alma =D
Em breve faço um post sobre colisão de polígonos convexos.
EDIT: Sugestões para otimização são bem-vindas!
import math
def trans(xa, ya, xb, yb, voxel):
"""
Given a start and end point, returns the list of voxels
that must be checked against collisions, in priority order,
as a list of (voxel_x, voxel_y) tuples.
A brief study about parametric line equations will help!
Implements the method seem at: http://www.cs.yorku.ca/~amana/research/grid.pdf
@param xa: The start x coord
@param ya: The start y coord
@param xb: The end x coord
@param yb: The end y coord
@param voxel: The voxel width and length (i.e. for 16x16 tiles it would be 16)
@author: Paolo victor, paolovictor@gmail.com
"""
# Getting start and end x and y voxels
xa_g, ya_g = xa // voxel, ya // voxel
xb_g, yb_g = xb // voxel, yb // voxel
# Base cases: same y voxel, same x voxel
if xa_g == xb_g or ya_g == yb_g:
# Getting x and y increments
if xa_g < xb_g: x_inc = 1
else: x_inc = -1
if ya_g < yb_g: y_inc = 1
else: y_inc = -1
# If it's in same horizontal voxel, test if it's in the same
# vertical voxel. Return a straight vertical line otherwise
if xa_g == xb_g:
if ya_g == yb_g:
return [(xa_g, ya_g)]
return [(xa_g, i) for i in range(ya_g, yb_g + y_inc, y_inc)]
elif ya == yb: # Similar for being in the same vertical voxel
return [(i, ya_g) for i in range(xa_g, xb_g + x_inc, x_inc)]
# Usual case: different start and end voxels
xbxa = xb - xa
ybya = yb - ya
# Evaluating horizontal increment
x_dir = float((xbxa) // abs(xbxa))
y_dir = float((ybya) // abs(ybya))
# Initializing and starting loop
xp, yp = xa, ya
result = []
r = 0.0
while r <= 1.0: # Goes through the whole vector
# Add current voxel to results
xp_g, yp_g = xp // voxel, yp // voxel
result.append((xp_g, yp_g))
# Evaluate horizontal and vertical increase
delta_rx = ((xp_g + x_dir) * voxel - xp) / xbxa
delta_ry = ((yp_g + y_dir) * voxel - yp) / ybya
# Choose the smaler increment
if delta_rx < delta_ry:
xp += delta_rx * xbxa
yp += delta_rx * ybya
r += delta_rx
else:
xp += delta_ry * xbxa
yp += delta_ry * ybya
r += delta_ry
return result