mirror of
https://github.com/SleepingInsomniac/pixelfaucet
synced 2025-01-31 19:57:53 +01:00
Refactor drawing methods onto Sprite class
This commit is contained in:
parent
5f7880c171
commit
c0d6d0ba90
20 changed files with 258 additions and 225 deletions
Binary file not shown.
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 5.1 KiB |
|
@ -96,7 +96,7 @@ class ThreeDee < PF::Game
|
|||
def draw
|
||||
clear(25, 50, 25)
|
||||
tris = @projector.project(@model.tris)
|
||||
@text.draw(@screen, "Triangles: #{tris.size}")
|
||||
@text.draw_to(screen, "Triangles: #{tris.size}")
|
||||
|
||||
tris.each do |tri|
|
||||
# Rasterize all triangles
|
||||
|
|
|
@ -11,6 +11,7 @@ module PF
|
|||
def initialize(*args, **kwargs)
|
||||
super
|
||||
@bricks = Sprite.new("./assets/bricks.png")
|
||||
@bricks.convert(@screen)
|
||||
end
|
||||
|
||||
def update(dt, event)
|
||||
|
|
|
@ -4,6 +4,20 @@ require "../src/entity"
|
|||
require "../src/entity/circle_collision"
|
||||
|
||||
module PF
|
||||
class Sprite
|
||||
# Redefine draw_point to wrap the coordinates
|
||||
def draw_point(x : Int32, y : Int32, color : UInt32)
|
||||
x = x % width
|
||||
y = y % height
|
||||
|
||||
x = width + x if x < 0
|
||||
y = height + y if y < 0
|
||||
|
||||
# super(x, y, color) # Undefined method super for Object??
|
||||
pixel_pointer(x, y).value = color
|
||||
end
|
||||
end
|
||||
|
||||
class Ball < Entity
|
||||
include CircleCollision
|
||||
|
||||
|
@ -32,17 +46,6 @@ module PF
|
|||
end
|
||||
end
|
||||
|
||||
# override to wrap the coordinates
|
||||
def draw_point(x : Int32, y : Int32, pixel : PF::Pixel, surface = @screen)
|
||||
x = x % @width
|
||||
y = y % @height
|
||||
|
||||
x = @width + x if x < 0
|
||||
y = @height + y if y < 0
|
||||
|
||||
super(x, y, pixel, surface)
|
||||
end
|
||||
|
||||
def update(dt, event)
|
||||
@balls.each do |b|
|
||||
b.update(dt)
|
||||
|
@ -65,9 +68,9 @@ module PF
|
|||
|
||||
def draw
|
||||
clear(10, 10, 30)
|
||||
# @balls.each { |b| draw_circle(b.position.to_i32, b.radius.to_i32) }
|
||||
@balls.each do |ball|
|
||||
fill_shape(Shape.translate(ball.frame, translation: ball.position).map(&.to_i32))
|
||||
# draw_circle(ball.position.to_i32, ball.radius.to_i32, Pixel.green)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -60,7 +60,6 @@ end
|
|||
|
||||
class Snow < PF::Game
|
||||
@wind : Wind
|
||||
@pixels : Slice(UInt32)
|
||||
@last_flake : Float64 = 0.0
|
||||
@flakes : Array(Flake) = [] of Flake
|
||||
|
||||
|
@ -68,7 +67,6 @@ class Snow < PF::Game
|
|||
super
|
||||
|
||||
@wind = Wind.new(@width, @height)
|
||||
@pixels = Slice.new(@screen.pixels.as(Pointer(UInt32)), @width * @height)
|
||||
clear(0, 0, 15)
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ class Snow < PF::Game
|
|||
def initialize(*args, **kwargs)
|
||||
super
|
||||
|
||||
@pixels = Slice.new(@screen.pixels.as(Pointer(UInt32)), @width * @height)
|
||||
@pixels = @screen.pixels
|
||||
clear(0, 0, 25)
|
||||
end
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ module PF
|
|||
|
||||
def draw
|
||||
clear(255, 255, 255)
|
||||
@bricks.draw(@screen, width // 2 - @bricks.width // 2, height // 2 - @bricks.height // 2)
|
||||
@bricks.draw_to(@screen, width // 2 - @bricks.width // 2, height // 2 - @bricks.height // 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -46,7 +46,7 @@ class TextGame < PF::Game
|
|||
|
||||
def draw
|
||||
clear(0, 0, 50)
|
||||
@text.draw(@screen, @msg, @x.to_i, @y.to_i)
|
||||
@text.draw_to(@screen, @msg, @x.to_i, @y.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
206
src/game.cr
206
src/game.cr
|
@ -1,7 +1,6 @@
|
|||
require "./lib_sdl"
|
||||
require "./pixel"
|
||||
require "./controller"
|
||||
require "./game/*"
|
||||
require "./sprite"
|
||||
|
||||
module PF
|
||||
abstract class Game
|
||||
|
@ -14,7 +13,10 @@ module PF
|
|||
property scale : Int32
|
||||
property title : String
|
||||
property running = true
|
||||
property screen : SDL::Surface
|
||||
property screen : Sprite
|
||||
|
||||
delegate :draw_point, :draw_line, :draw_circle, :draw_triangle, :draw_rect, :draw_shape,
|
||||
:fill_triangle, :fill_rect, :fill_shape, to: @screen
|
||||
|
||||
@fps_lasttime : Float64 = Time.monotonic.total_milliseconds # the last recorded time.
|
||||
@fps_current : UInt32 = 0 # the current FPS.
|
||||
|
@ -28,10 +30,13 @@ module PF
|
|||
@window = SDL::Window.new(@title, @width * @scale, @height * @scale, flags: window_flags)
|
||||
@renderer = SDL::Renderer.new(@window, flags: flags)
|
||||
@renderer.scale = {@scale, @scale}
|
||||
@screen = SDL::Surface.new(LibSDL.create_rgb_surface(
|
||||
|
||||
surface = SDL::Surface.new(LibSDL.create_rgb_surface(
|
||||
flags: 0, width: @width, height: @height, depth: 32,
|
||||
r_mask: 0xFF000000, g_mask: 0x00FF0000, b_mask: 0x0000FF00, a_mask: 0x000000FF
|
||||
))
|
||||
|
||||
@screen = Sprite.new(surface)
|
||||
end
|
||||
|
||||
abstract def update(dt : Float64, event : SDL::Event)
|
||||
|
@ -61,177 +66,22 @@ module PF
|
|||
@screen.fill(r, g, b)
|
||||
end
|
||||
|
||||
def pixel_pointer(x : Int32, y : Int32, surface = @screen)
|
||||
target = surface.pixels + (y * surface.pitch) + (x * 4)
|
||||
target.as(Pointer(UInt32))
|
||||
end
|
||||
|
||||
# =================
|
||||
# Drawing functions
|
||||
# =================
|
||||
|
||||
# Unsafely draw a single point
|
||||
def unsafe_draw_point(x : Int32, y : Int32, color : UInt32, surface = @screen)
|
||||
pixel_pointer(x, y, surface).value = color
|
||||
end
|
||||
|
||||
# Draw a single point
|
||||
def draw_point(x : Int32, y : Int32, pixel : Pixel = Pixel.new, surface = @screen)
|
||||
if x >= 0 && x < @width && y >= 0 && y < @height
|
||||
pixel_pointer(x, y, surface).value = pixel.format(surface.format)
|
||||
end
|
||||
end
|
||||
|
||||
# ditto
|
||||
def draw_point(point : Vector(Int, 2), pixel : Pixel = Pixel.new, surface = @screen)
|
||||
draw_point(point.x, point.y, pixel, surface)
|
||||
end
|
||||
|
||||
# ditto
|
||||
def draw_point(point : Vector(Float, 2), pixel : Pixel = Pixel.new, surface = @screen)
|
||||
draw_point(point.to_i32, pixel, surface)
|
||||
end
|
||||
|
||||
# =================
|
||||
|
||||
# Draw a line using Bresenham’s Algorithm
|
||||
def draw_line(x1 : Int, y1 : Int, x2 : Int, y2 : Int, pixel : Pixel = Pixel.new, surface = @screen)
|
||||
# The slope for each axis
|
||||
slope = Vector[(x2 - x1).abs, -(y2 - y1).abs]
|
||||
|
||||
# The step direction in both axis
|
||||
step = Vector[x1 < x2 ? 1 : -1, y1 < y2 ? 1 : -1]
|
||||
|
||||
# The final decision accumulation
|
||||
# Initialized to the height of x and y
|
||||
decision = slope.x + slope.y
|
||||
|
||||
point = Vector[x1, y1]
|
||||
|
||||
def run!
|
||||
loop do
|
||||
draw_point(point.x, point.y, pixel, surface)
|
||||
# Break if we've reached the ending point
|
||||
break if point.x == x2 && point.y == y2
|
||||
|
||||
# Square the decision to avoid floating point calculations
|
||||
decision_squared = decision + decision
|
||||
|
||||
# if decision_squared is greater than
|
||||
if decision_squared >= slope.y
|
||||
decision += slope.y
|
||||
point.x += step.x
|
||||
case event = SDL::Event.poll
|
||||
when SDL::Event::Quit
|
||||
break
|
||||
end
|
||||
|
||||
if decision_squared <= slope.x
|
||||
decision += slope.x
|
||||
point.y += step.y
|
||||
end
|
||||
engine_update(event)
|
||||
engine_draw
|
||||
|
||||
break unless @running
|
||||
end
|
||||
ensure
|
||||
SDL.quit
|
||||
end
|
||||
|
||||
# ditto
|
||||
def draw_line(p1 : Vector(Int, 2), p2 : Vector(Int, 2), pixel : Pixel = Pixel.new, surface = @screen)
|
||||
draw_line(p1.x, p1.y, p2.x, p2.y, pixel, surface)
|
||||
end
|
||||
|
||||
# ditto
|
||||
def draw_line(p1 : Vector(Float, 2), p2 : Vector(Float, 2), pixel : Pixel = Pixel.new, surface = @screen)
|
||||
draw_line(p1.to_i32, p2.to_i32, pixel, surface)
|
||||
end
|
||||
|
||||
# =================
|
||||
|
||||
# Draw the outline of a square rect
|
||||
def draw_rect(x1 : Int, y1 : Int, x2 : Int, y2 : Int, pixel : Pixel = Pixel.new, surface = @screen)
|
||||
# draw from top left to bottom right
|
||||
y1, y2 = y2, y1 if y1 > y2
|
||||
x1, x2 = x2, x1 if x1 > x2
|
||||
|
||||
x1.upto(x2) do |x|
|
||||
draw_point(x, y1, pixel, surface)
|
||||
draw_point(x, y2, pixel, surface)
|
||||
end
|
||||
|
||||
y1.upto(y2) do |y|
|
||||
draw_point(x1, y, pixel, surface)
|
||||
draw_point(x2, y, pixel, surface)
|
||||
end
|
||||
end
|
||||
|
||||
def draw_rect(p1 : PF::Vector(Int, 2), p2 : PF::Vector(Int, 2), pixel : Pixel = Pixel.new, surface = @screen)
|
||||
draw_rect(p1.x, p1.y, p2.x, p2.y, pixel, surface)
|
||||
end
|
||||
|
||||
# =================
|
||||
|
||||
# Draw lines enclosing a shape
|
||||
def draw_shape(frame : Enumerable(Point), pixel : Pixel = Pixel.new, surface = @screen)
|
||||
0.upto(frame.size - 1) do |n|
|
||||
draw_line(frame[n], frame[(n + 1) % frame.size], pixel, surface)
|
||||
end
|
||||
end
|
||||
|
||||
# =================
|
||||
|
||||
# Draw a circle using Bresenham’s Algorithm
|
||||
def draw_circle(cx : Int, cy : Int, r : Int, pixel : Pixel = Pixel.new, surface = @screen)
|
||||
x, y = 0, r
|
||||
d = 3 - 2 * r
|
||||
|
||||
loop do
|
||||
draw_point(cx + x, cy + y, pixel)
|
||||
draw_point(cx - x, cy + y, pixel)
|
||||
draw_point(cx + x, cy - y, pixel)
|
||||
draw_point(cx - x, cy - y, pixel)
|
||||
draw_point(cx + y, cy + x, pixel)
|
||||
draw_point(cx - y, cy + x, pixel)
|
||||
draw_point(cx + y, cy - x, pixel)
|
||||
draw_point(cx - y, cy - x, pixel)
|
||||
|
||||
break if x > y
|
||||
|
||||
x += 1
|
||||
|
||||
if d > 0
|
||||
y -= 1
|
||||
d = d + 4 * (x - y) + 10
|
||||
else
|
||||
d = d + 4 * x + 6
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def draw_circle(c : Vector(Int, 2), r : Int, pixel : Pixel = Pixel.new, surface = @screen)
|
||||
draw_circle(c.x, c.y, r, pixel, surface)
|
||||
end
|
||||
|
||||
# =================
|
||||
|
||||
def draw_triangle(p1 : Vector, p2 : Vector, p3 : Vector, pixel : Pixel = Pixel.new, surface = @screen)
|
||||
draw_line(p1, p2, pixel, surface)
|
||||
draw_line(p2, p3, pixel, surface)
|
||||
draw_line(p3, p1, pixel, surface)
|
||||
end
|
||||
|
||||
# =================
|
||||
|
||||
# Fill a rect
|
||||
def fill_rect(x1 : Int, y1 : Int, x2 : Int, y2 : Int, pixel : Pixel = Pixel.new, surface = @screen)
|
||||
# draw from top left to bottom right
|
||||
y1, y2 = y2, y1 if y1 > y2
|
||||
x1, x2 = x2, x1 if x1 > x2
|
||||
|
||||
y1.upto(y2) do |y|
|
||||
x1.upto(x2) do |x|
|
||||
draw_point(x, y, pixel, surface)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# =====================
|
||||
# END drawing functions
|
||||
# =====================
|
||||
|
||||
private def engine_update(event)
|
||||
et = elapsed_time
|
||||
calculate_fps(et)
|
||||
|
@ -255,24 +105,8 @@ module PF
|
|||
draw
|
||||
end
|
||||
|
||||
@renderer.copy(@screen)
|
||||
@renderer.copy(@screen.surface)
|
||||
@renderer.present
|
||||
end
|
||||
|
||||
def run!
|
||||
loop do
|
||||
case event = SDL::Event.poll
|
||||
when SDL::Event::Quit
|
||||
break
|
||||
end
|
||||
|
||||
engine_update(event)
|
||||
engine_draw
|
||||
|
||||
break unless @running
|
||||
end
|
||||
ensure
|
||||
SDL.quit
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@ module PF
|
|||
end
|
||||
end
|
||||
|
||||
def draw(surface : SDL::Surface, text : String, x : Int32 = 0, y : Int32 = 0)
|
||||
def draw_to(surface : SDL::Surface, text : String, x : Int32 = 0, y : Int32 = 0)
|
||||
ix = 0
|
||||
iy = 0
|
||||
text.each_char do |char|
|
||||
|
@ -47,5 +47,9 @@ module PF
|
|||
ix += 1
|
||||
end
|
||||
end
|
||||
|
||||
def draw_to(sprite : Sprite, text : String, x : Int32 = 0, y : Int32 = 0)
|
||||
draw_to(sprite.surface, text, x, y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
require "sdl/image"
|
||||
require "./vector"
|
||||
require "./sprite/*"
|
||||
|
||||
module PF
|
||||
class Sprite
|
||||
property surface : SDL::Surface
|
||||
|
||||
delegate :convert, :format, to: @surface
|
||||
delegate :fill, :lock, :format, to: @surface
|
||||
|
||||
def initialize(@surface)
|
||||
end
|
||||
|
@ -26,10 +27,22 @@ module PF
|
|||
Vector[width, height]
|
||||
end
|
||||
|
||||
def draw(surface : SDL::Surface, x : Int32, y : Int32)
|
||||
def convert(other : SDL::Surface)
|
||||
@surface = @surface.convert(other)
|
||||
end
|
||||
|
||||
def convert(other : Sprite)
|
||||
@surface = @surface.convert(other.surface)
|
||||
end
|
||||
|
||||
def draw_to(surface : SDL::Surface, x : Int32, y : Int32)
|
||||
@surface.blit(surface, nil, SDL::Rect.new(x, y, width, height))
|
||||
end
|
||||
|
||||
def draw_to(sprite : Sprite, x : Int32, y : Int32)
|
||||
draw_to(sprite.surface, x, y)
|
||||
end
|
||||
|
||||
# Raw access to the pixels as a Slice
|
||||
def pixels
|
||||
Slice.new(@surface.pixels.as(Pointer(UInt32)), width * height)
|
||||
|
@ -42,10 +55,9 @@ module PF
|
|||
r = uninitialized UInt8
|
||||
g = uninitialized UInt8
|
||||
b = uninitialized UInt8
|
||||
a = uninitialized UInt8
|
||||
|
||||
LibSDL.get_rgba(raw_pixel, format, pointerof(r), pointerof(g), pointerof(b), pointerof(a))
|
||||
Pixel.new(r, g, b, a)
|
||||
LibSDL.get_rgb(raw_pixel, format, pointerof(r), pointerof(g), pointerof(b))
|
||||
Pixel.new(r, g, b)
|
||||
end
|
||||
|
||||
# ditto
|
||||
|
@ -53,6 +65,19 @@ module PF
|
|||
sample(point.x, point.y)
|
||||
end
|
||||
|
||||
# Sample a color with alhpa
|
||||
def sample(x : Int, y : Int, alpha = true)
|
||||
raw_pixel = pixel_pointer(x, y).value
|
||||
|
||||
r = uninitialized UInt8
|
||||
g = uninitialized UInt8
|
||||
b = uninitialized UInt8
|
||||
a = uninitialized UInt8
|
||||
|
||||
LibSDL.get_rgba(raw_pixel, format, pointerof(r), pointerof(g), pointerof(b), pointerof(a))
|
||||
Pixel.new(r, g, b, a)
|
||||
end
|
||||
|
||||
# Get the pointer to a pixel
|
||||
private def pixel_pointer(x : Int32, y : Int32)
|
||||
target = @surface.pixels + (y * @surface.pitch) + (x * 4)
|
||||
|
|
35
src/sprite/draw_circle.cr
Normal file
35
src/sprite/draw_circle.cr
Normal file
|
@ -0,0 +1,35 @@
|
|||
module PF
|
||||
class Sprite
|
||||
# Draw a circle using Bresenham’s Algorithm
|
||||
def draw_circle(cx : Int, cy : Int, r : Int, pixel : Pixel = Pixel.new)
|
||||
x, y = 0, r
|
||||
d = 3 - 2 * r
|
||||
|
||||
loop do
|
||||
draw_point(cx + x, cy + y, pixel)
|
||||
draw_point(cx - x, cy + y, pixel)
|
||||
draw_point(cx + x, cy - y, pixel)
|
||||
draw_point(cx - x, cy - y, pixel)
|
||||
draw_point(cx + y, cy + x, pixel)
|
||||
draw_point(cx - y, cy + x, pixel)
|
||||
draw_point(cx + y, cy - x, pixel)
|
||||
draw_point(cx - y, cy - x, pixel)
|
||||
|
||||
break if x > y
|
||||
|
||||
x += 1
|
||||
|
||||
if d > 0
|
||||
y -= 1
|
||||
d = d + 4 * (x - y) + 10
|
||||
else
|
||||
d = d + 4 * x + 6
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def draw_circle(c : Vector(Int, 2), r : Int, pixel : Pixel = Pixel.new)
|
||||
draw_circle(c.x, c.y, r, pixel)
|
||||
end
|
||||
end
|
||||
end
|
48
src/sprite/draw_line.cr
Normal file
48
src/sprite/draw_line.cr
Normal file
|
@ -0,0 +1,48 @@
|
|||
module PF
|
||||
class Sprite
|
||||
# Draw a line using Bresenham’s Algorithm
|
||||
def draw_line(x1 : Int, y1 : Int, x2 : Int, y2 : Int, pixel : Pixel = Pixel.new)
|
||||
# The slope for each axis
|
||||
slope = Vector[(x2 - x1).abs, -(y2 - y1).abs]
|
||||
|
||||
# The step direction in both axis
|
||||
step = Vector[x1 < x2 ? 1 : -1, y1 < y2 ? 1 : -1]
|
||||
|
||||
# The final decision accumulation
|
||||
# Initialized to the height of x and y
|
||||
decision = slope.x + slope.y
|
||||
|
||||
point = Vector[x1, y1]
|
||||
|
||||
loop do
|
||||
draw_point(point.x, point.y, pixel)
|
||||
# Break if we've reached the ending point
|
||||
break if point.x == x2 && point.y == y2
|
||||
|
||||
# Square the decision to avoid floating point calculations
|
||||
decision_squared = decision + decision
|
||||
|
||||
# if decision_squared is greater than
|
||||
if decision_squared >= slope.y
|
||||
decision += slope.y
|
||||
point.x += step.x
|
||||
end
|
||||
|
||||
if decision_squared <= slope.x
|
||||
decision += slope.x
|
||||
point.y += step.y
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# ditto
|
||||
def draw_line(p1 : Vector(Int, 2), p2 : Vector(Int, 2), pixel : Pixel = Pixel.new)
|
||||
draw_line(p1.x, p1.y, p2.x, p2.y, pixel)
|
||||
end
|
||||
|
||||
# ditto
|
||||
def draw_line(p1 : Vector(Float, 2), p2 : Vector(Float, 2), pixel : Pixel = Pixel.new)
|
||||
draw_line(p1.to_i32, p2.to_i32, pixel)
|
||||
end
|
||||
end
|
||||
end
|
25
src/sprite/draw_point.cr
Normal file
25
src/sprite/draw_point.cr
Normal file
|
@ -0,0 +1,25 @@
|
|||
module PF
|
||||
class Sprite
|
||||
# Draw a single point
|
||||
def draw_point(x : Int32, y : Int32, color : UInt32)
|
||||
if x >= 0 && x < width && y >= 0 && y < height
|
||||
pixel_pointer(x, y).value = color
|
||||
end
|
||||
end
|
||||
|
||||
# ditto
|
||||
def draw_point(x : Int32, y : Int32, pixel : Pixel = Pixel.new)
|
||||
draw_point(x, y, pixel.format(format))
|
||||
end
|
||||
|
||||
# ditto
|
||||
def draw_point(point : Vector(Int, 2), pixel : Pixel = Pixel.new)
|
||||
draw_point(point.x, point.y, pixel)
|
||||
end
|
||||
|
||||
# ditto
|
||||
def draw_point(point : Vector(Float, 2), pixel : Pixel = Pixel.new)
|
||||
draw_point(point.to_i32, pixel)
|
||||
end
|
||||
end
|
||||
end
|
24
src/sprite/draw_rect.cr
Normal file
24
src/sprite/draw_rect.cr
Normal file
|
@ -0,0 +1,24 @@
|
|||
module PF
|
||||
class Sprite
|
||||
# Draw the outline of a square rect
|
||||
def draw_rect(x1 : Int, y1 : Int, x2 : Int, y2 : Int, pixel : Pixel = Pixel.new)
|
||||
# draw from top left to bottom right
|
||||
y1, y2 = y2, y1 if y1 > y2
|
||||
x1, x2 = x2, x1 if x1 > x2
|
||||
|
||||
x1.upto(x2) do |x|
|
||||
draw_point(x, y1, pixel)
|
||||
draw_point(x, y2, pixel)
|
||||
end
|
||||
|
||||
y1.upto(y2) do |y|
|
||||
draw_point(x1, y, pixel)
|
||||
draw_point(x2, y, pixel)
|
||||
end
|
||||
end
|
||||
|
||||
def draw_rect(p1 : PF::Vector(Int, 2), p2 : PF::Vector(Int, 2), pixel : Pixel = Pixel.new)
|
||||
draw_rect(p1.x, p1.y, p2.x, p2.y, pixel)
|
||||
end
|
||||
end
|
||||
end
|
10
src/sprite/draw_shape.cr
Normal file
10
src/sprite/draw_shape.cr
Normal file
|
@ -0,0 +1,10 @@
|
|||
module PF
|
||||
class Sprite
|
||||
# Draw lines enclosing a shape
|
||||
def draw_shape(frame : Enumerable(Point), pixel : Pixel = Pixel.new)
|
||||
0.upto(frame.size - 1) do |n|
|
||||
draw_line(frame[n], frame[(n + 1) % frame.size], pixel)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
10
src/sprite/draw_triangle.cr
Normal file
10
src/sprite/draw_triangle.cr
Normal file
|
@ -0,0 +1,10 @@
|
|||
module PF
|
||||
class Sprite
|
||||
# Draws 3 lines
|
||||
def draw_triangle(p1 : Vector, p2 : Vector, p3 : Vector, pixel : Pixel = Pixel.new)
|
||||
draw_line(p1, p2, pixel)
|
||||
draw_line(p2, p3, pixel)
|
||||
draw_line(p3, p1, pixel)
|
||||
end
|
||||
end
|
||||
end
|
16
src/sprite/fill_rect.cr
Normal file
16
src/sprite/fill_rect.cr
Normal file
|
@ -0,0 +1,16 @@
|
|||
module PF
|
||||
class Sprite
|
||||
# Fill a rect
|
||||
def fill_rect(x1 : Int, y1 : Int, x2 : Int, y2 : Int, pixel : Pixel = Pixel.new)
|
||||
# draw from top left to bottom right
|
||||
y1, y2 = y2, y1 if y1 > y2
|
||||
x1, x2 = x2, x1 if x1 > x2
|
||||
|
||||
y1.upto(y2) do |y|
|
||||
x1.upto(x2) do |x|
|
||||
draw_point(x, y, pixel)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,11 +1,11 @@
|
|||
module PF
|
||||
abstract class Game
|
||||
class Sprite
|
||||
# Fill an abitrary polygon. Expects a clockwise winding of points
|
||||
def fill_shape(points : Enumerable(Vector), color : Pixel = Pixel.new, surface = @screen)
|
||||
def fill_shape(points : Enumerable(Vector), color : Pixel = Pixel.new)
|
||||
return if points.empty?
|
||||
return draw_point(points[0], color, surface) if points.size == 1
|
||||
return draw_line(points[0], points[1], color, surface) if points.size == 2
|
||||
return draw_triangle(points[0], points[1], points[2], color, surface) if points.size == 3
|
||||
return draw_point(points[0], color) if points.size == 1
|
||||
return draw_line(points[0], points[1], color) if points.size == 2
|
||||
return draw_triangle(points[0], points[1], points[2], color) if points.size == 3
|
||||
|
||||
# set initial bounding box
|
||||
top = points[0].y
|
||||
|
@ -50,7 +50,7 @@ module PF
|
|||
# Only draw points within x values of an ascending slope,
|
||||
# descending slope indicates that the point is outside of the shape
|
||||
if intercepts[n][1] || x == intercepts[n][0] # Always draw the border itself
|
||||
draw_point(x, y, color, surface)
|
||||
draw_point(x, y, color)
|
||||
end
|
||||
|
||||
# # While condition for overlapping points
|
||||
|
@ -61,13 +61,13 @@ module PF
|
|||
end
|
||||
end
|
||||
|
||||
def fill_shape(*points : Vector, color : Pixel = Pixel.new, surface = @screen)
|
||||
fill_shape(points, color, surface)
|
||||
def fill_shape(*points : Vector, color : Pixel = Pixel.new)
|
||||
fill_shape(points, color)
|
||||
end
|
||||
|
||||
def draw_shape(*points : Vector, color : Pixel = Pixel.new, surface = @screen)
|
||||
def draw_shape(*points : Vector, color : Pixel = Pixel.new)
|
||||
0.upto(points.size - 1) do |n|
|
||||
draw_line(points[n], points[(n + 1) % points.size], color, surface)
|
||||
draw_line(points[n], points[(n + 1) % points.size], color)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,8 +1,8 @@
|
|||
require "../line"
|
||||
|
||||
module PF
|
||||
abstract class Game
|
||||
def fill_triangle(p1 : Vector, p2 : Vector, p3 : Vector, pixel : Pixel = Pixel.new, surface = @screen)
|
||||
class Sprite
|
||||
def fill_triangle(p1 : Vector, p2 : Vector, p3 : Vector, pixel : Pixel = Pixel.new)
|
||||
# Sort points from top to bottom
|
||||
p1, p2 = p2, p1 if p2.y < p1.y
|
||||
p1, p3 = p3, p1 if p3.y < p1.y
|
||||
|
@ -39,7 +39,7 @@ module PF
|
|||
end
|
||||
|
||||
x_left.upto(x_right) do |x|
|
||||
draw_point(x, y + c, pixel, surface)
|
||||
draw_point(x, y + c, pixel)
|
||||
end
|
||||
|
||||
if y == mid
|
||||
|
@ -54,8 +54,8 @@ module PF
|
|||
end
|
||||
end
|
||||
|
||||
def fill_triangle(points : Enumerable(Vector), pixel : Pixel = Pixel.new, surface = @screen)
|
||||
fill_triangle(points[0], points[1], points[2], pixel, surface)
|
||||
def fill_triangle(points : Enumerable(Vector), pixel : Pixel = Pixel.new)
|
||||
fill_triangle(points[0], points[1], points[2], pixel)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue