diff --git a/Sources/Voxelotl/Renderer/SpriteBatch.swift b/Sources/Voxelotl/Renderer/SpriteBatch.swift index 122af9e..a29c484 100644 --- a/Sources/Voxelotl/Renderer/SpriteBatch.swift +++ b/Sources/Voxelotl/Renderer/SpriteBatch.swift @@ -124,6 +124,20 @@ public struct SpriteBatch { .texcoords(flip), color: color.linear) } + public mutating func draw(_ texture: RendererTexture2D, position: SIMD2, transform: simd_float2x2) { + assert(self._active != .inactive, "call to SpriteBatch.draw without calling begin") + self.drawQuad(texture, .positions(position, transform, Size(texture.size))) + } + + public mutating func draw(_ texture: RendererTexture2D, position: SIMD2, transform: simd_float2x2, + flip: Sprite.Flip = .none, color: Color = .white + ) { + assert(self._active != .inactive, "call to SpriteBatch.draw without calling begin") + self.drawQuad(texture, + .positions(position, transform, Size(texture.size)), + .texcoords(flip), color: color.linear) + } + public mutating func draw(_ texture: RendererTexture2D, source: Rect, position: SIMD2) { assert(self._active != .inactive, "call to SpriteBatch.draw without calling begin") self.drawQuad(texture, .positions(position, source.size), .texcoords(texture.size, source)) @@ -220,7 +234,25 @@ public struct SpriteBatch { flip: Sprite.Flip = .none, color: Color = .white ) { assert(self._active != .inactive, "call to SpriteBatch.draw without calling begin") - self.drawQuad(texture, .positions(transform, source.size), .texcoords(texture.size, source), color: color.linear) + self.drawQuad(texture, + .positions(transform, source.size), + .texcoords(texture.size, source, flip), color: color.linear) + } + + public mutating func draw(_ texture: RendererTexture2D, source: Rect, + position: SIMD2, transform: simd_float2x2 + ) { + assert(self._active != .inactive, "call to SpriteBatch.draw without calling begin") + self.drawQuad(texture, .positions(position, transform, source.size), .texcoords(texture.size, source)) + } + + public mutating func draw(_ texture: RendererTexture2D, source: Rect, + position: SIMD2, transform: simd_float2x2, flip: Sprite.Flip = .none, color: Color = .white + ) { + assert(self._active != .inactive, "call to SpriteBatch.draw without calling begin") + self.drawQuad(texture, + .positions(position, transform, source.size), + .texcoords(texture.size, source, flip), color: color.linear) } public mutating func draw(_ texture: RendererTexture2D, vertices: [VertexType]) { @@ -338,6 +370,14 @@ fileprivate extension SpriteBatch.Quad { v11: (transform * .init(w, h, 1)).xy) } + static func positions(_ position: SIMD2, _ transform: simd_float2x2, _ size: Size) -> Self { + .init( + v00: position + .init( 0, 0) * transform, + v01: position + .init(size.w, 0) * transform, + v10: position + .init( 0, size.h) * transform, + v11: position + .init(size.w, size.h) * transform) + } + static let texcoordsDefault = Self( v00: SIMD2(0, 1), v01: SIMD2(1, 1), v10: SIMD2(0, 0), v11: SIMD2(1, 0)) diff --git a/Sources/Voxelotl/SpriteTestGame.swift b/Sources/Voxelotl/SpriteTestGame.swift index 6465488..e61e0a2 100644 --- a/Sources/Voxelotl/SpriteTestGame.swift +++ b/Sources/Voxelotl/SpriteTestGame.swift @@ -81,12 +81,16 @@ internal class SpriteTestGame: GameDelegate { // Sliding door test let doorAngle = max(sin(player.rotate * 2.6) - 0.75, 0) * .pi + let doorScale = SIMD2(24, 12) + let doorAffine = simd_float2x2( + .init( cos(doorAngle) * doorScale.x, sin(doorAngle) * doorScale.y), + .init(-sin(doorAngle) * doorScale.x, cos(doorAngle) * doorScale.y)) + let doorOrigin = SIMD2(repeating: 1) + let doorPosition = SIMD2(704 + 24, 1152 + 12) - doorOrigin * doorAffine self.spriteBatch.draw(self.texture, source: Rect( origin: .init(4 + cos(player.rotate / 1.2) * 4, 0), size: .init(4 + cos(player.rotate / 1.3) * 4, 16)), - position: .init(704 + 24, 1152 + 12), scale: .init(24, 12), - angle: doorAngle, origin: SIMD2(repeating: 1), - flip: .none, color: .red.mix(.white, 0.3)) + position: doorPosition, transform: doorAffine, color: .red.mix(.white, 0.3)) // Draw mouse cursor var mpos = Mouse.position