|
| 1 | +extension SDL.Test { |
| 2 | + final class MouseGrid: Game { |
| 3 | + enum CodingKeys: CodingKey { |
| 4 | + case options |
| 5 | + case gridSize |
| 6 | + case circleRadius |
| 7 | + } |
| 8 | + |
| 9 | + static let configuration = CommandConfiguration( |
| 10 | + abstract: "Simple program to test grid drawing with mouse events" |
| 11 | + ) |
| 12 | + |
| 13 | + static let name: String = "SDL Test: Mouse Grid" |
| 14 | + |
| 15 | + @OptionGroup |
| 16 | + var options: Options |
| 17 | + |
| 18 | + @Option |
| 19 | + var gridSize: SDL_Size = [64, 40] |
| 20 | + |
| 21 | + @Option |
| 22 | + var circleRadius: Float = 10 |
| 23 | + |
| 24 | + |
| 25 | + private var renderer: (any Renderer)! |
| 26 | + private var mousePos: Point<Float> = .zero |
| 27 | + |
| 28 | + func onReady(window: any Window) throws(SwiftSDL.SDL_Error) { |
| 29 | + try SDL_Init(.gamepad) |
| 30 | + |
| 31 | + let windowSize = try window.size(as: Float.self) |
| 32 | + self.renderer = try window |
| 33 | + .createRenderer() |
| 34 | + .set( |
| 35 | + logicalSize: windowSize, |
| 36 | + presentation: .stretch |
| 37 | + ) |
| 38 | + } |
| 39 | + |
| 40 | + func onUpdate(window: any Window) throws(SwiftSDL.SDL_Error) { |
| 41 | + let logicalSize = try renderer.logicalSize.get() |
| 42 | + let cellSize: Size<Float> = (SDL_Size(logicalSize) / gridSize).to(Float.self) |
| 43 | + |
| 44 | + try renderer |
| 45 | + .clear(color: .gray) |
| 46 | + .pass(to: { renderer in |
| 47 | + for col in 0..<self.gridSize.x { |
| 48 | + for row in 0..<self.gridSize.y { |
| 49 | + let xPos = Float(col) * cellSize.x |
| 50 | + let yPos = Float(row) * cellSize.y |
| 51 | + |
| 52 | + var rect: SDL_FRect = [ |
| 53 | + xPos, yPos, |
| 54 | + cellSize.x, cellSize.y |
| 55 | + ] |
| 56 | + |
| 57 | + let mousePos = SDL_FPoint(self.mousePos) |
| 58 | + let distanceX = abs(xPos - mousePos.x) |
| 59 | + let distanceY = abs(yPos - mousePos.y) |
| 60 | + let distance = (distanceX * distanceX + distanceY * distanceY).squareRoot() |
| 61 | + let circleArea = self.circleRadius * max(cellSize.x, cellSize.y) |
| 62 | + |
| 63 | + if distance <= circleArea { |
| 64 | + if distance <= circleArea / 3 { |
| 65 | + try renderer.fill(rects: rect, color: 72, 72, 72, 0xF0) |
| 66 | + } |
| 67 | + else { |
| 68 | + try renderer.fill(rects: rect, color: 96, 96, 96, 0xF0) |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + if mousePos(SDL_PointInRectFloat, .some(&rect)) { |
| 73 | + try renderer.fill(rects: rect, color: 64, 64, 64, 0xFF) |
| 74 | + } |
| 75 | + |
| 76 | + try renderer |
| 77 | + .lines( |
| 78 | + [xPos, yPos + cellSize.y], |
| 79 | + [xPos, yPos], |
| 80 | + [xPos + cellSize.x, yPos], |
| 81 | + [xPos + cellSize.x, yPos + cellSize.y], |
| 82 | + color: .white |
| 83 | + ) |
| 84 | + } |
| 85 | + } |
| 86 | + }) |
| 87 | + .present() |
| 88 | + } |
| 89 | + |
| 90 | + func onEvent(window: any Window, _ event: SDL_Event) throws(SwiftSDL.SDL_Error) { |
| 91 | + var event = event |
| 92 | + try renderer(SDL_ConvertEventToRenderCoordinates, .some(&event)) |
| 93 | + switch event.eventType { |
| 94 | + case .mouseMotion: |
| 95 | + self.mousePos = event.motion.position(as: Float.self) |
| 96 | + default: break |
| 97 | + } |
| 98 | + } |
| 99 | + |
| 100 | + func onShutdown(window: (any Window)?) throws(SwiftSDL.SDL_Error) { |
| 101 | + self.renderer = nil |
| 102 | + } |
| 103 | + } |
| 104 | +} |
0 commit comments