import CSDL2 import FirebladeECS if SDL_Init(SDL_INIT_VIDEO) != 0 { fatalError("could not init video") } let width: Int32 = 640 let height: Int32 = 480 let hWin = SDL_CreateWindow("Fireblade ECS demo", 100, 100, width, height, SDL_WINDOW_SHOWN.rawValue) if hWin == nil { SDL_Quit() fatalError("could not crate window") } func randNorm() -> Double { return Double(arc4random()) / Double(UInt32.max) } // won't produce pure black func randColor() -> UInt8 { return UInt8(randNorm() * 254) + 1 } let nexus = Nexus() class Position: Component { var x: Int32 = width/2 var y: Int32 = height/2 } class Color: Component { var r: UInt8 = randColor() var g: UInt8 = randColor() var b: UInt8 = randColor() } func createScene() { let numEntities: Int = 10_000 for i in 0.. width { x = -x } if y < 0 || y > height { y = -y } pos!.x = x pos!.y = y } } } class PositionResetSystem { let family = nexus.family(requiresAll: [Position.self], excludesAll: []) func update() { family.iterate(components: Position.self) { (_, pos) in pos!.x = width/2 pos!.y = height/2 } } } class ColorSystem { let family = nexus.family(requiresAll: [Color.self], excludesAll: []) func update() { family.iterate(components: Color.self) { (_, color) in color!.r = randColor() color!.g = randColor() color!.b = randColor() } } } class RenderSystem { let hRenderer: OpaquePointer? let family = nexus.family(requiresAll: [Position.self, Color.self], excludesAll: []) init(hWin: OpaquePointer?) { hRenderer = SDL_CreateRenderer(hWin, -1, SDL_RENDERER_ACCELERATED.rawValue) if hRenderer == nil { SDL_DestroyWindow(hWin) SDL_Quit() fatalError("could not create renderer") } } deinit { SDL_DestroyRenderer(hRenderer) } func render() { SDL_SetRenderDrawColor( hRenderer, 0, 0, 0, 255 ) // black SDL_RenderClear(hRenderer) // clear screen family.iterate(components: Position.self, Color.self) { [unowned self] (_, pos, color) in var rect = SDL_Rect(x: pos!.x, y: pos!.y, w: 2, h: 2) SDL_SetRenderDrawColor(self.hRenderer, color!.r, color!.g, color!.b, 255) SDL_RenderFillRect(self.hRenderer, &rect) } SDL_RenderPresent(hRenderer) } } let positionSystem = PositionSystem() let positionResetSystem = PositionResetSystem() let renderSystem = RenderSystem(hWin: hWin) let colorSystem = ColorSystem() createScene() var event: SDL_Event = SDL_Event() var quit: Bool = false while quit == false { while SDL_PollEvent(&event) == 1 { switch SDL_EventType(rawValue: event.type) { case SDL_QUIT: quit = true break case SDL_KEYDOWN: switch Int(event.key.keysym.sym) { case SDLK_ESCAPE: quit = true break case SDLK_c: colorSystem.update() case SDLK_r: positionResetSystem.update() case SDLK_s: positionSystem.acceleration = 0.0 case SDLK_PLUS: positionSystem.acceleration += 0.1 case SDLK_MINUS: positionSystem.acceleration -= 0.1 case SDLK_SPACE: positionSystem.acceleration = 4.0 default: break } default: break } } positionSystem.update() renderSystem.render() } SDL_DestroyWindow(hWin) SDL_Quit()