Skip to content

Commit

Permalink
add more gfx related methods to Renderer and refactor gfx example
Browse files Browse the repository at this point in the history
  • Loading branch information
RomainFranceschini committed Jun 7, 2018
1 parent 352eb2d commit c91de36
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 35 deletions.
98 changes: 77 additions & 21 deletions samples/gfx.cr
Original file line number Diff line number Diff line change
@@ -1,47 +1,103 @@
require "../src/sdl"
require "../src/gfx"

WHITE = SDL::Color[255, 255, 255, 255]
BLACK = SDL::Color[0, 0, 0, 255]
RED = SDL::Color[255, 0, 0, 255]
GREEN = SDL::Color[0, 255, 0, 255]
BLUE = SDL::Color[0, 0, 255, 255]
YELLOW = SDL::Color[255, 255, 0, 255]

SDL.init(SDL::Init::VIDEO)
at_exit { SDL.quit }

window = SDL::Window.new("SDL tutorial", 640, 480)
window = SDL::Window.new("SDL gfx", 640, 480)
renderer = SDL::Renderer.new(window)

width, height = window.size
cx = width / 2
cy = height / 2
angle = 0

loop do
case event = SDL::Event.wait
when SDL::Event::Quit
break
end

# clear screen in white
renderer.draw_color = SDL::Color[255, 255, 255, 255]
# clear screen in black
renderer.draw_color = BLUE
renderer.clear

# centered red rectangle
renderer.draw_color = SDL::Color[255, 0, 0, 255]
renderer.fill_rect(width / 4, height / 4, width / 2, height / 2)
# draw a rounded rect
screen_rect = SDL::Rect.new(0, 0, width, height)
renderer.draw_color = BLACK
renderer.fill_rounded_rect screen_rect, 30
renderer.draw_color = WHITE
renderer.draw_rounded_rect screen_rect, 30

# draw white centered cross
renderer.draw_color = WHITE
renderer.draw_line(0, cy, width, cy)
renderer.draw_line(cx, 0, cx, height)

# draw a green centered ellipse and some meridians with anti aliasing
renderer.draw_color = GREEN
renderer.draw_ellipse(cx, cy, width / 6, height / 6, anti_aliased: true)
renderer.draw_circle(cx, cy, height / 6, anti_aliased: true)
renderer.draw_ellipse(cx, cy, width / 12, height / 6, anti_aliased: true)
renderer.draw_ellipse(cx, cy, width / 26, height / 6, anti_aliased: true)

# outlined green rectangle
renderer.draw_color = SDL::Color[0, 255, 0, 255]
renderer.draw_rect(width / 6, height / 6, width * 2 / 3, height * 2 / 3)
# draw two triangles within a square on the bottom right side of the screen
rect = SDL::Rect[cx + width/4 - 51, cy + height/4 - 51, 102, 102]
triangle1 = SDL::Triangle[rect.x + 1, rect.y + 1, rect.x + 100, rect.y + 1, rect.x + 1, rect.y + 100]
triangle2 = SDL::Triangle[rect.x + 1, rect.y + 100, rect.x + 100, rect.y + 100, rect.x + 100, rect.y + 1]
renderer.draw_color = RED
renderer.draw_rect(rect)
renderer.draw_color = YELLOW
renderer.fill_triangle(triangle1)
renderer.draw_color = BLUE
renderer.fill_triangle(triangle2)

# blue horizontal line
renderer.draw_color = SDL::Color[0, 0, 255, 255]
renderer.draw_line(0, height / 2, width, height / 2)
# draw a red ball on the top left side of the screen
renderer.draw_color = RED
renderer.fill_circle SDL::Circle.new(width/4, cy - height/4, 50)
renderer.draw_color = WHITE
renderer.fill_ellipse SDL::Ellipse.new(width/4 + 25, cy - height/4 - 25, 8, 7)

# vertical line of yellow dots
renderer.draw_color = SDL::Color[255, 255, 0, 255]
0.step(by: 4, to: height) do |i|
renderer.draw_point(width / 2, i)
# draw triangles within a circle on the top right side of the screen
circle = SDL::Circle.new(cx + width/4, cy - height/4, 50)
renderer.draw_color = RED
renderer.draw_circle circle, anti_aliased: true
renderer.draw_color = YELLOW
renderer.draw_point(circle.x, circle.y)

30.step(by: 30, to: 360) do |a|
a = a + angle
x1 = circle.x + circle.radius * Math.cos(a * Math::PI / 180.0)
y1 = circle.y + circle.radius * Math.sin(a * Math::PI / 180.0)
x2 = circle.x + circle.radius * Math.cos((a - 30) * Math::PI / 180.0)
y2 = circle.y + circle.radius * Math.sin((a - 30) * Math::PI / 180.0)
renderer.draw_triangle SDL::Triangle.new(x1, y1, x2, y2, circle.x, circle.y), anti_aliased: true
end

renderer.draw_color = SDL::Color[255, 255, 255, 255]
renderer.draw_ellipse(width / 2, height / 2, width / 6, height / 6, anti_aliased: true)
renderer.draw_circle(width / 2, height / 2, height / 6, anti_aliased: true)
renderer.draw_ellipse(width / 2, height / 2, width / 12, height / 6, anti_aliased: true)
renderer.draw_ellipse(width / 2, height / 2, width / 26, height / 6, anti_aliased: true)
# draw random lines on the bottom left side of the screen with antialiasing on and off
renderer.draw_color = GREEN
12.times do |i|
x1 = rand(50..cx - 100)
y1 = rand(cy + 50..height - 50)
x2 = rand(50..cx - 100)
y2 = rand(cy + 50..height - 50)

if i % 2 == 0
renderer.draw_color = GREEN
renderer.draw_line(x1, y1, x2, y2, anti_aliased: true)
else
renderer.draw_color = RED
renderer.draw_line(x1, y1, x2, y2, anti_aliased: false)
end
end

angle = angle + 1 % 360
renderer.present
end
156 changes: 142 additions & 14 deletions src/gfx.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ require "./lib_gfx"
require "./sdl"

module SDL
class GFXError < Exception
end

struct Circle
property x : Int16
property y : Int16
Expand Down Expand Up @@ -36,53 +39,178 @@ module SDL
end
end

struct Triangle
property x1 : Int16
property y1 : Int16
property x2 : Int16
property y2 : Int16
property x3 : Int16
property y3 : Int16

macro [](x1, y1, x2, y2, x3, y3)
SDL::Triangle.new({{x1}}, {{y2}}, {{x2}}, {{y2}}, {{x3}}, {{y3}})
end

def initialize(x1, y1, x2, y2, x3, y3)
@x1 = x1.to_i16
@y1 = y1.to_i16
@x2 = x2.to_i16
@y2 = y2.to_i16
@x3 = x3.to_i16
@y3 = y3.to_i16
end

def initialize(p1, p2, p3)
@x1 = p1.x.to_i16
@y1 = p1.y.to_i16
@x2 = p2.x.to_i16
@y2 = p2.y.to_i16
@x3 = p3.x.to_i16
@y3 = p3.y.to_i16
end
end

class Renderer
# Draw a single `Circle`.
def draw_circle(x, y, radius, anti_aliased = false)
c = self.draw_color
c = draw_color
ret = if anti_aliased
LibGFX.aa_circle_rgba(self, x.to_i16, y.to_i16, radius.to_i16, c.r, c.g, c.b, c.a)
.tap { self.draw_color = c }
else
LibGFX.circle_rgba(self, x.to_i16, y.to_i16, radius.to_i16, c.r, c.g, c.b, c.a)
end
raise Exception.new("GFX_circleRGBA") unless ret == 0
# reset original drawing color as antialiasing modifies alpha
self.draw_color = c if anti_aliased
raise GFXError.new("SDL_gfx_(aa)circleRGBA") unless ret == 0
end

# Draw a single `Circle`.
def draw_circle(circle, anti_aliased = false)
self.draw_circle(circle.x, circle.y, circle.radius, anti_aliased)
draw_circle(circle.x, circle.y, circle.radius, anti_aliased)
end

# Fill a `Circle` with the current `#draw_color`.
def fill_circle(x, y, radius)
c = self.draw_color
c = draw_color
ret = LibGFX.filled_circle_rgba(self, x.to_i16, y.to_i16, radius.to_i16, c.r, c.g, c.b, c.a)
raise Exception.new("GFX_filledCircleRGBA") unless ret == 0
raise GFXError.new("SDL_gfx_filledCircleRGBA") unless ret == 0
end

# Fill a `Circle` with the current `#draw_color`.
def fill_circle(circle)
self.filled_circle(circle.x, circle.y, circle.radius)
fill_circle(circle.x, circle.y, circle.radius)
end

# Draw a single `Ellipse`.
def draw_ellipse(x, y, rx, ry, anti_aliased = false)
c = self.draw_color
c = draw_color
ret = if anti_aliased
LibGFX.aa_ellipse_rgba(self, x.to_i16, y.to_i16, rx.to_i16, ry.to_i16, c.r, c.g, c.b, c.a)
.tap { self.draw_color = c }
else
LibGFX.ellipse_rgba(self, x.to_i16, y.to_i16, rx.to_i16, ry.to_i16, c.r, c.g, c.b, c.a)
end
raise Exception.new("GFX_ellipseRGBA") unless ret == 0
# reset original drawing color as antialiasing modifies alpha
self.draw_color = c if anti_aliased
raise GFXError.new("SDL_gfx_(aa)ellipseRGBA") unless ret == 0
end

# Draw a single `Ellipse`.
def draw_ellipse(ellipse, *, anti_aliased = false)
self.draw_ellipse(ellipse.x, ellipse.y, ellipse.rx, ellipse.ry, anti_aliased)
def draw_ellipse(ellipse, anti_aliased = false)
draw_ellipse(ellipse.x, ellipse.y, ellipse.rx, ellipse.ry, anti_aliased)
end

# Fill an `Ellipse` with the current `#draw_color`.
def fill_ellipse(x, y, rx, ry)
c = draw_color
ret = LibGFX.filled_ellipse_rgba(self, x.to_i16, y.to_i16, rx.to_i16, ry.to_i16, c.r, c.g, c.b, c.a)
raise GFXError.new("SDL_gfx_filledEllipseRGBA") unless ret == 0
end

# Fill an `Ellipse` with the current `#draw_color`.
def fill_ellipse(ellipse)
fill_ellipse(ellipse.x, ellipse.y, ellipse.rx, ellipse.ry)
end

# Draw a single `Triangle`.
def draw_triangle(x1, y1, x2, y2, x3, y3, anti_aliased = false)
c = draw_color
ret = if anti_aliased
LibGFX.aa_trigon_rgba(self, x1, y1, x2, y2, x3, y3, c.r, c.g, c.b, c.a)
.tap { self.draw_color = c }
else
LibGFX.trigon_rgba(self, x1, y1, x2, y2, x3, y3, c.r, c.g, c.b, c.a)
end
raise GFXError.new("SDL_gfx_(aa)trigonRGBA") unless ret == 0
end

# Draw a single `Triangle`.
def draw_triangle(triangle, anti_aliased = false)
draw_triangle(triangle.x1, triangle.y1, triangle.x2, triangle.y2, triangle.x3, triangle.y3, anti_aliased)
end

# Draw a single `Triangle`.
def draw_triangle(a, b, c, anti_aliased = false)
draw_triangle(a.x, a.y, b.x, b.y, c.x, c.y, anti_aliased)
end

# Fill a `Triangle` with the current `#draw_color`.
def fill_triangle(x1, y1, x2, y2, x3, y3)
c = draw_color
ret = LibGFX.filled_trigon_rgba(self, x1, y1, x2, y2, x3, y3, c.r, c.g, c.b, c.a)
raise GFXError.new("SDL_gfx_filledTrigonRGBA") unless ret == 0
end

# Fill a `Triangle` with the current `#draw_color`.
def fill_triangle(triangle)
fill_triangle(triangle.x1, triangle.y1, triangle.x2, triangle.y2, triangle.x3, triangle.y3)
end

# Fill a `Triangle` with the current `#draw_color`.
def fill_triangle(a, b, c)
fill_triangle(a.x, a.y, b.x, b.y, c.x, c.y)
end

# Draw a single line between two `Point`.
def draw_line(a, b, anti_aliased : Bool)
if anti_aliased
draw_line(a.x, a.y, b.x, b.y, true)
else
draw_line(a, b)
end
end

# Draw a single line between two `Point`.
def draw_line(x1, y1, x2, y2, anti_aliased : Bool)
if anti_aliased
c = draw_color
ret = LibGFX.aa_line_rgba(self, x1, y1, x2, y2, c.r, c.g, c.b, c.a)
self.draw_color = c
raise GFXError.new("SDL_gfx_aalineRGBA") unless ret == 0
else
draw_line(x1, y1, x2, y2)
end
end

# Draw a single rounded `Rect`.
def draw_rounded_rect(rect, radius)
draw_rounded_rect(rect.x, rect.y, rect.w, rect.h, radius)
end

# Draw a single rounded `Rect`.
def draw_rounded_rect(x, y, w, h, radius)
c = draw_color
ret = LibGFX.rounded_rectangle_rgba(self, x, y, w, h, radius, c.r, c.g, c.b, c.a)
raise GFXError.new("SDL_gfx_roundedRectangleRGBA") unless ret == 0
end

# Fill a rounded `Rect` with the current `draw_color` and `draw_blend_mode`.
def fill_rounded_rect(rect, radius)
fill_rounded_rect(rect.x, rect.y, rect.w, rect.h, radius)
end

# Fill a rounded `Rect` with the current `draw_color` and `draw_blend_mode`.
def fill_rounded_rect(x, y, w, h, radius)
c = draw_color
ret = LibGFX.rounded_box_rgba(self, x, y, w, h, radius, c.r, c.g, c.b, c.a)
raise GFXError.new("SDL_gfx_roundedBoxRGBA") unless ret == 0
end
end
end

0 comments on commit c91de36

Please sign in to comment.