Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional bindings for SDL2_gfx #22

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ more samples, and the necessary corrections!
## Requirements

- SDL2 is required;
- Optional bindings for `SDL2_Mixer`, `SDL2_Image` and `SDL2_TTF`;
- Optional bindings for `SDL2_Mixer`, `SDL2_Image`, `SDL2_TTF` and `SDL2_gfx`;
- Crystal > 0.22.0 is required for `SDL2_Mixer` to work correctly.
103 changes: 103 additions & 0 deletions samples/gfx.cr
Original file line number Diff line number Diff line change
@@ -0,0 +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 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 black
renderer.draw_color = BLUE
renderer.clear

# 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)

# 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)

# 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)

# 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

# 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
216 changes: 216 additions & 0 deletions src/gfx.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
require "./lib_gfx"
require "./sdl"

module SDL
class GFXError < Exception
end

struct Circle
property x : Int16
property y : Int16
property radius : Int16

macro [](x, y, r)
SDL::Circle.new({{x}}, {{y}}, {{r}})
end

def initialize(x, y, r)
@x = x.to_i16
@y = y.to_i16
@radius = r.to_i16
end
end

struct Ellipse
property x : Int16
property y : Int16
property rx : Int16
property ry : Int16

macro [](x, y, rx, ry)
SDL::Ellipse.new({{x}}, {{y}}, {{rx}}, {{ry}})
end

def initialize(x, y, rx, ry)
@x = x.to_i16
@y = y.to_i16
@rx = rx.to_i16
@ry = ry.to_i16
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 = 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 GFXError.new("SDL_gfx_(aa)circleRGBA") unless ret == 0
end

# Draw a single `Circle`.
def draw_circle(circle, anti_aliased = false)
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 = 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 GFXError.new("SDL_gfx_filledCircleRGBA") unless ret == 0
end

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

# Draw a single `Ellipse`.
def draw_ellipse(x, y, rx, ry, anti_aliased = false)
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 GFXError.new("SDL_gfx_(aa)ellipseRGBA") unless ret == 0
end

# Draw a single `Ellipse`.
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
Loading