mirror of
				https://github.com/GayPizzaSpecifications/voxelotl-engine.git
				synced 2025-11-04 10:59:39 +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
 | 
			
		||||
 | 
			
		||||
  Random/RandomProvider.swift
 | 
			
		||||
  Random/RandomRange.swift
 | 
			
		||||
  Random/Arc4Random.swift
 | 
			
		||||
  Random/DarwinRandom.swift
 | 
			
		||||
 | 
			
		||||
  NSImageLoader.swift
 | 
			
		||||
  Renderer.swift
 | 
			
		||||
 | 
			
		||||
@ -25,18 +25,21 @@ class Game: GameDelegate {
 | 
			
		||||
  var player = Player()
 | 
			
		||||
  var projection: matrix_float4x4 = .identity
 | 
			
		||||
  var chunk = Chunk(position: .zero)
 | 
			
		||||
  var random = Arc4Random.instance
 | 
			
		||||
 | 
			
		||||
  init() {
 | 
			
		||||
    player.position = SIMD3(0.5, Float(Chunk.chunkSize) + 0.5, 0.5)
 | 
			
		||||
    player.rotation = .init(.pi, 0)
 | 
			
		||||
    self.player.position = SIMD3(0.5, Float(Chunk.chunkSize) + 0.5, 0.5)
 | 
			
		||||
    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>] = [
 | 
			
		||||
      .white,
 | 
			
		||||
      .red, .blue, .green,
 | 
			
		||||
      .magenta, .yellow, .cyan
 | 
			
		||||
    ]
 | 
			
		||||
    chunk.fill(allBy: {
 | 
			
		||||
    self.chunk.fill(allBy: {
 | 
			
		||||
      if (random.next() & 0x1) == 0x1 {
 | 
			
		||||
        .solid(colors[random.next(in: 0..<colors.count)])
 | 
			
		||||
      } else {
 | 
			
		||||
@ -59,19 +62,25 @@ class Game: GameDelegate {
 | 
			
		||||
    if let pad = GameController.current?.state {
 | 
			
		||||
      // Delete block underneath player
 | 
			
		||||
      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
 | 
			
		||||
      if pad.pressed(.back) {
 | 
			
		||||
        player.position = .init(repeating: 0.5) + .init(0, Float(Chunk.chunkSize), 0)
 | 
			
		||||
        player.velocity = .zero
 | 
			
		||||
        player.rotation = .init(.pi, 0)
 | 
			
		||||
        self.player.position = .init(repeating: 0.5) + .init(0, Float(Chunk.chunkSize), 0)
 | 
			
		||||
        self.player.velocity = .zero
 | 
			
		||||
        self.player.rotation = .init(.pi, 0)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Regenerate
 | 
			
		||||
      if pad.pressed(.start) {
 | 
			
		||||
        self.generateWorld()
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    player.update(deltaTime: deltaTime, chunk: chunk)
 | 
			
		||||
    camera.position = player.eyePosition
 | 
			
		||||
    camera.rotation = player.eyeRotation
 | 
			
		||||
    self.player.update(deltaTime: deltaTime, chunk: chunk)
 | 
			
		||||
    self.camera.position = player.eyePosition
 | 
			
		||||
    self.camera.rotation = player.eyeRotation
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  func draw(_ renderer: Renderer, _ time: GameTime) {
 | 
			
		||||
 | 
			
		||||
@ -17,8 +17,12 @@ public class Arc4Random: RandomProvider {
 | 
			
		||||
    arc4random()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public func next(in bound: Range<Int>) -> Int {
 | 
			
		||||
    assert(bound.upperBound <= Self.max)
 | 
			
		||||
    return bound.lowerBound + Int(arc4random_uniform(UInt32(bound.upperBound)))
 | 
			
		||||
  public func next(in bound: Int) -> Int {
 | 
			
		||||
    assert(bound <= Self.max)
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    // (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(
 | 
			
		||||
        length: instancesBytes,
 | 
			
		||||
        options: .storageModeManaged)
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user