patternpythonMinor
Drawing a dashed line with pygame
Viewed 0 times
linewithdrawingpygamedashed
Problem
def draw_dashed_line(surf, color, start_pos, end_pos, width=1, dash_length=10):
x1, y1 = start_pos
x2, y2 = end_pos
dl = dash_length
if (x1 == x2):
ycoords = [y for y in range(y1, y2, dl if y1 < y2 else -dl)]
xcoords = [x1] * len(ycoords)
elif (y1 == y2):
xcoords = [x for x in range(x1, x2, dl if x1 < x2 else -dl)]
ycoords = [y1] * len(xcoords)
else:
a = abs(x2 - x1)
b = abs(y2 - y1)
c = round(math.sqrt(a**2 + b**2))
dx = dl * a / c
dy = dl * b / c
xcoords = [x for x in numpy.arange(x1, x2, dx if x1 < x2 else -dx)]
ycoords = [y for y in numpy.arange(y1, y2, dy if y1 < y2 else -dy)]
next_coords = list(zip(xcoords[1::2], ycoords[1::2]))
last_coords = list(zip(xcoords[0::2], ycoords[0::2]))
for (x1, y1), (x2, y2) in zip(next_coords, last_coords):
start = (round(x1), round(y1))
end = (round(x2), round(y2))
pygame.draw.line(surf, color, start, end, width)This function takes two coordinates and draws a colored dashed line from the first to the second coordinate. Line
a = abs(x2 - x1) to line dy = dl * b / c calculates the amount x and y change for dl (dash_length).Because dx and dy are floats, I had to use numpy.arange (built-in range() doesn't allow floating-point).
Here's an example:
draw_dashed_line(screen, RED, (0, 0), (800, 600), dash_length=5)Documentation for pygame.draw.line:
http://www.pygame.org/docs/ref/draw.html#pygame.draw.line
Solution
Instead of storing all the values you're trying to draw, it might be more efficient to just get the slope of the drawn line, and compute dashes at draw time.
Considering that there's a lot of mirrored code here, consider using a point class to handle both the x and the y values at the same time!
Considering that there's a lot of mirrored code here, consider using a point class to handle both the x and the y values at the same time!
class Point:
# constructed using a normal tupple
def __init__(self, point_t = (0,0)):
self.x = float(point_t[0])
self.y = float(point_t[1])
# define all useful operators
def __add__(self, other):
return Point((self.x + other.x, self.y + other.y))
def __sub__(self, other):
return Point((self.x - other.x, self.y - other.y))
def __mul__(self, scalar):
return Point((self.x*scalar, self.y*scalar))
def __div__(self, scalar):
return Point((self.x/scalar, self.y/scalar))
def __len__(self):
return int(math.sqrt(self.x**2 + self.y**2))
# get back values in original tuple format
def get(self):
return (self.x, self.y)
def draw_dashed_line(surf, color, start_pos, end_pos, width=1, dash_length=10):
origin = Point(start_pos)
target = Point(end_pos)
displacement = target - origin
length = len(displacement)
slope = displacement/length
for index in range(0, length/dash_length, 2):
start = origin + (slope * index * dash_length)
end = origin + (slope * (index + 1) * dash_length)
pygame.draw.line(surf, color, start.get(), end.get(), width)Code Snippets
class Point:
# constructed using a normal tupple
def __init__(self, point_t = (0,0)):
self.x = float(point_t[0])
self.y = float(point_t[1])
# define all useful operators
def __add__(self, other):
return Point((self.x + other.x, self.y + other.y))
def __sub__(self, other):
return Point((self.x - other.x, self.y - other.y))
def __mul__(self, scalar):
return Point((self.x*scalar, self.y*scalar))
def __div__(self, scalar):
return Point((self.x/scalar, self.y/scalar))
def __len__(self):
return int(math.sqrt(self.x**2 + self.y**2))
# get back values in original tuple format
def get(self):
return (self.x, self.y)
def draw_dashed_line(surf, color, start_pos, end_pos, width=1, dash_length=10):
origin = Point(start_pos)
target = Point(end_pos)
displacement = target - origin
length = len(displacement)
slope = displacement/length
for index in range(0, length/dash_length, 2):
start = origin + (slope * index * dash_length)
end = origin + (slope * (index + 1) * dash_length)
pygame.draw.line(surf, color, start.get(), end.get(), width)Context
StackExchange Code Review Q#70143, answer score: 8
Revisions (0)
No revisions yet.