mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-03 13:11:33 +00:00
use arc4random to seed non-csprng, fleshes out random subsystem
This commit is contained in:
@ -13,7 +13,9 @@ add_executable(Voxelotl MACOSX_BUNDLE
|
|||||||
Color.swift
|
Color.swift
|
||||||
|
|
||||||
Random/RandomProvider.swift
|
Random/RandomProvider.swift
|
||||||
|
Random/RandomRange.swift
|
||||||
Random/Arc4Random.swift
|
Random/Arc4Random.swift
|
||||||
|
Random/DarwinRandom.swift
|
||||||
|
|
||||||
NSImageLoader.swift
|
NSImageLoader.swift
|
||||||
Renderer.swift
|
Renderer.swift
|
||||||
|
@ -25,18 +25,21 @@ class Game: GameDelegate {
|
|||||||
var player = Player()
|
var player = Player()
|
||||||
var projection: matrix_float4x4 = .identity
|
var projection: matrix_float4x4 = .identity
|
||||||
var chunk = Chunk(position: .zero)
|
var chunk = Chunk(position: .zero)
|
||||||
var random = Arc4Random.instance
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
player.position = SIMD3(0.5, Float(Chunk.chunkSize) + 0.5, 0.5)
|
self.player.position = SIMD3(0.5, Float(Chunk.chunkSize) + 0.5, 0.5)
|
||||||
player.rotation = .init(.pi, 0)
|
self.player.rotation = .init(.pi, 0)
|
||||||
|
self.generateWorld()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func generateWorld() {
|
||||||
|
var random = DarwinRandom(seed: Arc4Random.instance.next(in: DarwinRandom.max))
|
||||||
let colors: [Color<UInt8>] = [
|
let colors: [Color<UInt8>] = [
|
||||||
.white,
|
.white,
|
||||||
.red, .blue, .green,
|
.red, .blue, .green,
|
||||||
.magenta, .yellow, .cyan
|
.magenta, .yellow, .cyan
|
||||||
]
|
]
|
||||||
chunk.fill(allBy: {
|
self.chunk.fill(allBy: {
|
||||||
if (random.next() & 0x1) == 0x1 {
|
if (random.next() & 0x1) == 0x1 {
|
||||||
.solid(colors[random.next(in: 0..<colors.count)])
|
.solid(colors[random.next(in: 0..<colors.count)])
|
||||||
} else {
|
} else {
|
||||||
@ -59,19 +62,25 @@ class Game: GameDelegate {
|
|||||||
if let pad = GameController.current?.state {
|
if let pad = GameController.current?.state {
|
||||||
// Delete block underneath player
|
// Delete block underneath player
|
||||||
if pad.pressed(.south) {
|
if pad.pressed(.south) {
|
||||||
chunk.setBlock(at: SIMD3(player.position + .down * 0.2), type: .air)
|
self.chunk.setBlock(at: SIMD3(player.position + .down * 0.2), type: .air)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player reset
|
// Player reset
|
||||||
if pad.pressed(.back) {
|
if pad.pressed(.back) {
|
||||||
player.position = .init(repeating: 0.5) + .init(0, Float(Chunk.chunkSize), 0)
|
self.player.position = .init(repeating: 0.5) + .init(0, Float(Chunk.chunkSize), 0)
|
||||||
player.velocity = .zero
|
self.player.velocity = .zero
|
||||||
player.rotation = .init(.pi, 0)
|
self.player.rotation = .init(.pi, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regenerate
|
||||||
|
if pad.pressed(.start) {
|
||||||
|
self.generateWorld()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player.update(deltaTime: deltaTime, chunk: chunk)
|
self.player.update(deltaTime: deltaTime, chunk: chunk)
|
||||||
camera.position = player.eyePosition
|
self.camera.position = player.eyePosition
|
||||||
camera.rotation = player.eyeRotation
|
self.camera.rotation = player.eyeRotation
|
||||||
}
|
}
|
||||||
|
|
||||||
func draw(_ renderer: Renderer, _ time: GameTime) {
|
func draw(_ renderer: Renderer, _ time: GameTime) {
|
||||||
|
@ -17,8 +17,12 @@ public class Arc4Random: RandomProvider {
|
|||||||
arc4random()
|
arc4random()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func next(in bound: Range<Int>) -> Int {
|
public func next(in bound: Int) -> Int {
|
||||||
assert(bound.upperBound <= Self.max)
|
assert(bound <= Self.max)
|
||||||
return bound.lowerBound + Int(arc4random_uniform(UInt32(bound.upperBound)))
|
return Int(arc4random_uniform(UInt32(bound)))
|
||||||
|
}
|
||||||
|
|
||||||
|
public func next(in range: Range<Int>) -> Int {
|
||||||
|
return range.lowerBound + next(in: range.upperBound - range.lowerBound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
Sources/Voxelotl/Random/DarwinRandom.swift
Normal file
33
Sources/Voxelotl/Random/DarwinRandom.swift
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
public struct DarwinRandom: RandomProvider {
|
||||||
|
public typealias Output = Int
|
||||||
|
|
||||||
|
public static var min: Int { 0x00000000 }
|
||||||
|
public static var max: Int { 0x7FFFFFFF }
|
||||||
|
|
||||||
|
private var state: Int
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self.state = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(seed: Int) {
|
||||||
|
self.state = seed
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating public func seed(with seed: Int) {
|
||||||
|
self.state = seed
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating public func next() -> Int {
|
||||||
|
if self.state == 0 {
|
||||||
|
self.state = 123459876
|
||||||
|
}
|
||||||
|
let hi = self.state / 127773
|
||||||
|
let lo = self.state - hi * 127773
|
||||||
|
self.state = 16807 * lo - 2836 * hi
|
||||||
|
if self.state < 0 {
|
||||||
|
self.state += Self.max
|
||||||
|
}
|
||||||
|
return self.state % (Self.max + 1)
|
||||||
|
}
|
||||||
|
}
|
20
Sources/Voxelotl/Random/RandomRange.swift
Normal file
20
Sources/Voxelotl/Random/RandomRange.swift
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
public extension RandomProvider where Output: BinaryInteger {
|
||||||
|
mutating func next(in range: Range<Int>) -> Int {
|
||||||
|
range.lowerBound + self.next(in: range.upperBound - range.lowerBound)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func next(in range: ClosedRange<Int>) -> Int {
|
||||||
|
range.lowerBound + self.next(in: range.upperBound - range.lowerBound + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func next(in bound: Int) -> Int {
|
||||||
|
assert(Self.min == 0)
|
||||||
|
assert(Self.max >= bound)
|
||||||
|
let threshold = Int(Self.max % Output(bound))
|
||||||
|
var result: Int
|
||||||
|
repeat {
|
||||||
|
result = Int(truncatingIfNeeded: self.next())
|
||||||
|
} while result < threshold
|
||||||
|
return result % bound
|
||||||
|
}
|
||||||
|
}
|
@ -358,7 +358,7 @@ public class Renderer {
|
|||||||
let instancesBytes = numInstances * MemoryLayout<VertexShaderInstance>.stride
|
let instancesBytes = numInstances * MemoryLayout<VertexShaderInstance>.stride
|
||||||
|
|
||||||
// (Re)create instance buffer if needed
|
// (Re)create instance buffer if needed
|
||||||
if self._instances[self.currentFrame] == nil || numInstances > self._instances[self.currentFrame]!.length {
|
if self._instances[self.currentFrame] == nil || instancesBytes > self._instances[self.currentFrame]!.length {
|
||||||
guard let instanceBuffer = self.device.makeBuffer(
|
guard let instanceBuffer = self.device.makeBuffer(
|
||||||
length: instancesBytes,
|
length: instancesBytes,
|
||||||
options: .storageModeManaged)
|
options: .storageModeManaged)
|
||||||
|
Reference in New Issue
Block a user