mirror of
https://github.com/SleepingInsomniac/pixelfaucet
synced 2025-01-31 19:57:53 +01:00
Add transform2d class
This commit is contained in:
parent
f4409b4496
commit
5f7880c171
3 changed files with 160 additions and 0 deletions
BIN
assets/bricks.png
Normal file
BIN
assets/bricks.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
47
examples/affine.cr
Normal file
47
examples/affine.cr
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
require "../src/game"
|
||||||
|
require "../src/sprite"
|
||||||
|
require "../src/transform2d"
|
||||||
|
|
||||||
|
module PF
|
||||||
|
class Affine < Game
|
||||||
|
@bricks : Sprite
|
||||||
|
@transform : Transform2d = Transform2d.new
|
||||||
|
@angle = 0.0
|
||||||
|
|
||||||
|
def initialize(*args, **kwargs)
|
||||||
|
super
|
||||||
|
@bricks = Sprite.new("./assets/bricks.png")
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(dt, event)
|
||||||
|
@angle += 1.0 * dt
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
clear(50, 127, 200)
|
||||||
|
|
||||||
|
@transform
|
||||||
|
.reset
|
||||||
|
.translate(-(@bricks.size // 2))
|
||||||
|
.rotate(@angle)
|
||||||
|
.translate(viewport // 2)
|
||||||
|
|
||||||
|
b1, b2 = @transform.bounding_box(@bricks.size.x, @bricks.size.y).map(&.to_i)
|
||||||
|
|
||||||
|
@transform.invert
|
||||||
|
|
||||||
|
b1.y.upto(b2.y) do |y|
|
||||||
|
b1.x.upto(b2.x) do |x|
|
||||||
|
point = @transform.apply(x, y).to_i
|
||||||
|
if point >= Vector[0, 0] && point < @bricks.size
|
||||||
|
color = @bricks.sample(point.x, point.y)
|
||||||
|
draw_point(x.to_i, y.to_i, color)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
game = PF::Affine.new(300, 200, 2)
|
||||||
|
game.run!
|
113
src/transform2d.cr
Normal file
113
src/transform2d.cr
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
require "./matrix"
|
||||||
|
require "./vector"
|
||||||
|
|
||||||
|
module PF
|
||||||
|
class Transform2d
|
||||||
|
property matrix : Matrix(Float64, 3, 3) = Matrix[
|
||||||
|
1.0, 0.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
]
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(@matrix)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset
|
||||||
|
@matrix = Matrix[
|
||||||
|
1.0, 0.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
]
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def translate(x : Float | Int, y : Float | Int)
|
||||||
|
@matrix = Matrix[
|
||||||
|
1.0, 0.0, x.to_f64,
|
||||||
|
0.0, 1.0, y.to_f64,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
] * @matrix
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def translate(to : Vector)
|
||||||
|
translate(to.x, to.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
def scale(x : Float | Int, y : Float | Int)
|
||||||
|
@matrix = Matrix[
|
||||||
|
x.to_f64, 0.0, 0.0,
|
||||||
|
0.0, y.to_f64, 0.0,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
] * @matrix
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def rotate(angle : Float | Int)
|
||||||
|
cos = Math.cos(angle)
|
||||||
|
sin = Math.sin(angle)
|
||||||
|
@matrix = Matrix[
|
||||||
|
cos, -sin, 0.0,
|
||||||
|
sin, cos, 0.0,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
] * @matrix
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def shear(x : Float | Int, y : Float | Int)
|
||||||
|
@matrix = Matrix[
|
||||||
|
1.0, x.to_f64, 0.0,
|
||||||
|
y.to_f64, 1.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
] * @matrix
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def bounding_box(x : Float | Int, y : Float | Int)
|
||||||
|
top_left = apply(0.0, 0.0)
|
||||||
|
top_right = apply(x.to_f, 0.0)
|
||||||
|
bot_right = apply(x.to_f, y.to_f)
|
||||||
|
bot_left = apply(0.0, y.to_f)
|
||||||
|
|
||||||
|
xs = Float64[top_left.x, top_right.x, bot_right.x, bot_left.x]
|
||||||
|
ys = Float64[top_left.y, top_right.y, bot_right.y, bot_left.y]
|
||||||
|
|
||||||
|
{Vector[xs.min, ys.min], Vector[xs.max, ys.max]}
|
||||||
|
end
|
||||||
|
|
||||||
|
def invert
|
||||||
|
det = @matrix[0, 0] * (@matrix[1, 1] * @matrix[2, 2] - @matrix[1, 2] * @matrix[2, 1]) -
|
||||||
|
@matrix[1, 0] * (@matrix[0, 1] * @matrix[2, 2] - @matrix[2, 1] * @matrix[0, 2]) +
|
||||||
|
@matrix[2, 0] * (@matrix[0, 1] * @matrix[1, 2] - @matrix[1, 1] * @matrix[0, 2])
|
||||||
|
|
||||||
|
idet = 1.0 / det
|
||||||
|
|
||||||
|
@matrix = Matrix[
|
||||||
|
(@matrix[1, 1] * @matrix[2, 2] - @matrix[1, 2] * @matrix[2, 1]) * idet,
|
||||||
|
(@matrix[2, 0] * @matrix[1, 2] - @matrix[1, 0] * @matrix[2, 2]) * idet,
|
||||||
|
(@matrix[1, 0] * @matrix[2, 1] - @matrix[2, 0] * @matrix[1, 1]) * idet,
|
||||||
|
|
||||||
|
(@matrix[2, 1] * @matrix[0, 2] - @matrix[0, 1] * @matrix[2, 2]) * idet,
|
||||||
|
(@matrix[0, 0] * @matrix[2, 2] - @matrix[2, 0] * @matrix[0, 2]) * idet,
|
||||||
|
(@matrix[0, 1] * @matrix[2, 0] - @matrix[0, 0] * @matrix[2, 1]) * idet,
|
||||||
|
|
||||||
|
(@matrix[0, 1] * @matrix[1, 2] - @matrix[0, 2] * @matrix[1, 1]) * idet,
|
||||||
|
(@matrix[0, 2] * @matrix[1, 0] - @matrix[0, 0] * @matrix[1, 2]) * idet,
|
||||||
|
(@matrix[0, 0] * @matrix[1, 1] - @matrix[0, 1] * @matrix[1, 0]) * idet,
|
||||||
|
]
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def apply(x : Float | Int, y : Float | Int)
|
||||||
|
result = Vector[x, y, 1.0] * @matrix
|
||||||
|
Vector[result.x, result.y]
|
||||||
|
end
|
||||||
|
|
||||||
|
def apply(point : Vector)
|
||||||
|
apply(point.x, point.y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Add table
Reference in a new issue