mirror of
https://github.com/SleepingInsomniac/pixelfaucet
synced 2025-01-31 19:57:53 +01:00
Clarify the line drawing algorithm
This commit is contained in:
parent
db5a1747fa
commit
60f1e39ae9
2 changed files with 54 additions and 44 deletions
|
@ -12,14 +12,13 @@ class Triangle < PF::Sprite
|
||||||
include PF::VectorSprite
|
include PF::VectorSprite
|
||||||
|
|
||||||
def update(dt)
|
def update(dt)
|
||||||
# @rotation += 0.5 * dt
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def draw(engine)
|
def draw(engine)
|
||||||
frame = project_points(@frame)
|
frame = project_points(@frame)
|
||||||
engine.fill_triangle(frame[0], frame[1], frame[2], PF::Pixel.new(255, 255, 0))
|
engine.fill_triangle(frame[0], frame[1], frame[2], PF::Pixel.new(255, 255, 0))
|
||||||
# engine.draw_shape(frame, PF::Pixel.new(0, 0, 255))
|
engine.draw_shape(frame, PF::Pixel.new(0, 255, 255))
|
||||||
# engine.draw_line(@position, frame[0], PF::Pixel.new(255, 255, 0))
|
engine.draw_line(@position, frame[0], PF::Pixel.new(0, 255, 0))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -57,10 +56,8 @@ class TriangleThing < PF::Game
|
||||||
|
|
||||||
def draw
|
def draw
|
||||||
clear(0, 0, 200)
|
clear(0, 0, 200)
|
||||||
# fill_rect(25, 25, 10, 15)
|
|
||||||
# draw_rect(15, 15, 30, 30)
|
|
||||||
@tri.draw(self)
|
@tri.draw(self)
|
||||||
# draw_circle((@width / 2).to_i32, (@height / 2).to_i32, 45)
|
draw_circle((@width / 2).to_i32, (@height / 2).to_i32, (@width / 3).to_i32)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
89
src/game.cr
89
src/game.cr
|
@ -67,29 +67,35 @@ module PF
|
||||||
|
|
||||||
# Draw a line using Bresenham’s Algorithm
|
# Draw a line using Bresenham’s Algorithm
|
||||||
def draw_line(x1 : Int, y1 : Int, x2 : Int, y2 : Int, pixel : Pixel = Pixel.new, surface = @screen)
|
def draw_line(x1 : Int, y1 : Int, x2 : Int, y2 : Int, pixel : Pixel = Pixel.new, surface = @screen)
|
||||||
dx = (x2 - x1).abs
|
# The sloap for each axis
|
||||||
dy = -(y2 - y1).abs
|
slope = Point.new((x2 - x1).abs, -(y2 - y1).abs)
|
||||||
|
|
||||||
sx = x1 < x2 ? 1 : -1
|
# The step direction in both axis
|
||||||
sy = y1 < y2 ? 1 : -1
|
step = Point.new(x1 < x2 ? 1 : -1, y1 < y2 ? 1 : -1)
|
||||||
|
|
||||||
d = dx + dy
|
# The final decision accumulation
|
||||||
x, y = x1, y1
|
# Initialized to the height of x and y
|
||||||
|
decision = slope.x + slope.y
|
||||||
|
|
||||||
|
point = Point.new(x1, y1)
|
||||||
|
|
||||||
loop do
|
loop do
|
||||||
draw_point(x, y, pixel, surface)
|
draw_point(point.x, point.y, pixel, surface)
|
||||||
break if x == x2 && y == y2
|
# Break if we've reached the ending point
|
||||||
|
break if point.x == x2 && point.y == y2
|
||||||
|
|
||||||
d2 = d + d
|
# Square the decision to avoid floating point calculations
|
||||||
|
decision_squared = decision + decision
|
||||||
|
|
||||||
if d2 >= dy
|
# if decision_squared is greater than
|
||||||
d += dy
|
if decision_squared >= slope.y
|
||||||
x += sx
|
decision += slope.y
|
||||||
|
point.x += step.x
|
||||||
end
|
end
|
||||||
|
|
||||||
if d2 <= dx
|
if decision_squared <= slope.x
|
||||||
d += dx
|
decision += slope.x
|
||||||
y += sy
|
point.y += step.y
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -176,17 +182,17 @@ module PF
|
||||||
# find the lower left and right points
|
# find the lower left and right points
|
||||||
p_left, p_right = p2.x < p3.x ? [p2, p3] : [p3, p2]
|
p_left, p_right = p2.x < p3.x ? [p2, p3] : [p3, p2]
|
||||||
|
|
||||||
edge_left = get_tri_edge(p_top.x, p_top.y, p_left.x, p_left.y)
|
edge_left = pixel_edge(p_top.x, p_top.y, p_left.x, p_left.y)
|
||||||
edge_right = get_tri_edge(p_top.x, p_top.y, p_right.x, p_right.y)
|
edge_right = pixel_edge(p_top.x, p_top.y, p_right.x, p_right.y)
|
||||||
|
|
||||||
if edge_left.size < edge_right.size
|
if edge_left.size < edge_right.size
|
||||||
rest = get_tri_edge(p_left.x, p_left.y, p_right.x, p_right.y)
|
rest = pixel_edge(p_left.x, p_left.y, p_right.x, p_right.y)
|
||||||
rest.shift
|
rest.shift
|
||||||
edge_left.concat(rest)
|
edge_left.concat(rest)
|
||||||
end
|
end
|
||||||
|
|
||||||
if edge_left.size > edge_right.size
|
if edge_left.size > edge_right.size
|
||||||
rest = get_tri_edge(p_right.x, p_right.y, p_left.x, p_left.y)
|
rest = pixel_edge(p_right.x, p_right.y, p_left.x, p_left.y)
|
||||||
rest.shift
|
rest.shift
|
||||||
edge_right.concat(rest)
|
edge_right.concat(rest)
|
||||||
end
|
end
|
||||||
|
@ -195,39 +201,46 @@ module PF
|
||||||
pl = edge_left[i]
|
pl = edge_left[i]
|
||||||
pr = edge_right[i]
|
pr = edge_right[i]
|
||||||
|
|
||||||
(pl.x + 1).upto(pr.x - 1) do |x|
|
(pl.x).upto(pr.x) do |x|
|
||||||
draw_point(x, pl.y, pixel, surface)
|
draw_point(x, pl.y, pixel, surface)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private def get_tri_edge(x1 : Int, y1 : Int, x2 : Int, y2 : Int)
|
private def pixel_edge(x1 : Int, y1 : Int, x2 : Int, y2 : Int)
|
||||||
line = [] of Point(Int32)
|
line = [] of Point(Int32)
|
||||||
dx = (x2 - x1).abs
|
|
||||||
dy = -(y2 - y1).abs
|
|
||||||
|
|
||||||
sx = x1 < x2 ? 1 : -1
|
# The sloap for each axis
|
||||||
sy = y1 < y2 ? 1 : -1
|
slope = Point.new((x2 - x1).abs, -(y2 - y1).abs)
|
||||||
|
|
||||||
d = dx + dy
|
# The step direction in both axis
|
||||||
x, y = x1, y1
|
step = Point.new(x1 < x2 ? 1 : -1, y1 < y2 ? 1 : -1)
|
||||||
xp = x
|
|
||||||
|
|
||||||
line << Point.new(x, y)
|
# The final decision accumulation
|
||||||
|
# Initialized to the height of x and y
|
||||||
|
decision = slope.x + slope.y
|
||||||
|
|
||||||
|
pixel = Point.new(x1, y1)
|
||||||
|
|
||||||
|
line << pixel
|
||||||
|
|
||||||
loop do
|
loop do
|
||||||
break if x == x2 && y == y2
|
# Break if we've reached the ending point
|
||||||
d2 = d + d
|
break if pixel.x == x2 && pixel.y == y2
|
||||||
|
|
||||||
if d2 >= dy
|
# Square the decision to avoid floating point calculations
|
||||||
d += dy
|
decision_squared = decision + decision
|
||||||
x += sx
|
|
||||||
|
# if decision_squared is greater than
|
||||||
|
if decision_squared >= slope.y
|
||||||
|
decision += slope.y
|
||||||
|
pixel.x += step.x
|
||||||
end
|
end
|
||||||
|
|
||||||
if d2 <= dx
|
if decision_squared <= slope.x
|
||||||
d += dx
|
decision += slope.x
|
||||||
line << Point.new(x, y)
|
line << pixel
|
||||||
y += sy
|
pixel.y += step.y
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue