mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-02 13:00:53 +00:00
initial voxel implementation
This commit is contained in:
parent
9b455652ff
commit
799c7a2a55
@ -3,6 +3,8 @@ add_executable(Voxelotl MACOSX_BUNDLE
|
||||
|
||||
test.png
|
||||
|
||||
Chunk.swift
|
||||
|
||||
shadertypes.h
|
||||
shader.metal
|
||||
|
||||
|
57
Sources/Voxelotl/Chunk.swift
Normal file
57
Sources/Voxelotl/Chunk.swift
Normal file
@ -0,0 +1,57 @@
|
||||
public struct Chunk {
|
||||
public static let chunkSize: Int = 16
|
||||
|
||||
public let position: SIMD3<Int>
|
||||
private var blocks: [Block]
|
||||
|
||||
init(position: SIMD3<Int>, blocks: [Block]) {
|
||||
self.position = position
|
||||
self.blocks = blocks
|
||||
}
|
||||
|
||||
init(position: SIMD3<Int>) {
|
||||
self.position = position
|
||||
self.blocks = Array(
|
||||
repeating: BlockType.air,
|
||||
count: Chunk.chunkSize * Chunk.chunkSize * Chunk.chunkSize
|
||||
).map { type in Block(type) }
|
||||
}
|
||||
|
||||
func getBlockInternally(at position: SIMD3<Int>) -> Block {
|
||||
blocks[position.x + position.y * Chunk.chunkSize + position.z * Chunk.chunkSize * Chunk.chunkSize]
|
||||
}
|
||||
|
||||
mutating func setBlockInternally(at position: SIMD3<Int>, type: BlockType) {
|
||||
blocks[position.x + position.y * Chunk.chunkSize + position.z * Chunk.chunkSize * Chunk.chunkSize].type = type
|
||||
}
|
||||
|
||||
mutating func fill(allBy calculation: () -> BlockType) {
|
||||
blocks.indices.forEach { i in
|
||||
blocks[i].type = calculation()
|
||||
}
|
||||
}
|
||||
|
||||
func forEach(block perform: (SIMD3<Int>, Block) -> Void) {
|
||||
for x in 0..<Chunk.chunkSize {
|
||||
for y in 0..<Chunk.chunkSize {
|
||||
for z in 0..<Chunk.chunkSize {
|
||||
perform(SIMD3(x, y, z), blocks[x + y * Chunk.chunkSize + z * Chunk.chunkSize * Chunk.chunkSize])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum BlockType: Equatable {
|
||||
case air
|
||||
case solid(Color<Float16>)
|
||||
}
|
||||
|
||||
public struct Block {
|
||||
public var type: BlockType
|
||||
|
||||
|
||||
public init(_ type: BlockType) {
|
||||
self.type = type
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import simd
|
||||
import Foundation
|
||||
|
||||
struct Box {
|
||||
var geometry: AABB
|
||||
@ -24,26 +25,54 @@ struct Instance {
|
||||
}
|
||||
}
|
||||
|
||||
let boxes: [Box] = [
|
||||
Box(geometry: .fromUnitCube(
|
||||
position: .init( 0, -1, 0) * 2,
|
||||
scale: .init(10, 0.1, 10) * 2)),
|
||||
Box(geometry: .fromUnitCube(
|
||||
position: .init(-2.5, 0, -3) * 2,
|
||||
scale: .init(repeating: 2)),
|
||||
color: .init(rgb888: 0xFF80BF).linear),
|
||||
Box(geometry: .fromUnitCube(
|
||||
position: .init(-2.5, -0.5, -5) * 2,
|
||||
scale: .init(repeating: 2)),
|
||||
color: .init(rgb888: 0xBFFFFF).linear)
|
||||
]
|
||||
|
||||
class Game: GameDelegate {
|
||||
private var fpsCalculator = FPSCalculator()
|
||||
var camera = Camera(fov: 60, size: .one, range: 0.06...50)
|
||||
var camera = Camera(fov: 60, size: .one, range: 0.06...900)
|
||||
var player = Player()
|
||||
var projection: matrix_float4x4 = .identity
|
||||
|
||||
var boxes: [Box] = []
|
||||
|
||||
init() {
|
||||
var chunk = Chunk(position: .zero)
|
||||
let options: [BlockType] = [
|
||||
.air,
|
||||
.solid(.blue),
|
||||
.air,
|
||||
.solid(.red),
|
||||
.air,
|
||||
.solid(.green),
|
||||
.air,
|
||||
.solid(.white),
|
||||
.air,
|
||||
.solid(.cyan),
|
||||
.air,
|
||||
.solid(.yellow),
|
||||
.air,
|
||||
.solid(.magenta),
|
||||
.air,
|
||||
]
|
||||
chunk
|
||||
.fill(allBy: { options[Int(arc4random_uniform(UInt32(options.count)))] })
|
||||
chunk.forEach { position, block in
|
||||
if block.type == .air {
|
||||
return
|
||||
}
|
||||
|
||||
if case let .solid(color) = block.type {
|
||||
boxes
|
||||
.append(
|
||||
Box(
|
||||
geometry:
|
||||
.fromUnitCube(position: SIMD3<Float>(position) + 0.5, scale: .init(repeating: 0.5)),
|
||||
color: color
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
player.position = SIMD3(0.5, Float(Chunk.chunkSize) + 0.5, 0.5)
|
||||
}
|
||||
|
||||
func fixedUpdate(_ time: GameTime) {
|
||||
|
||||
}
|
||||
@ -74,7 +103,7 @@ class Game: GameDelegate {
|
||||
}
|
||||
instances.append(
|
||||
Instance(
|
||||
position: .init(0, sin(totalTime * 1.5 * cubeSpeedMul) * 0.5, -2) * 2,
|
||||
position: .init(0, sin(totalTime * 1.5 * cubeSpeedMul) * 0.5, 0) * 2,
|
||||
scale: .init(repeating: 0.5),
|
||||
rotation: .init(angle: totalTime * 3.0 * cubeSpeedMul, axis: .init(0, 1, 0)),
|
||||
color: .init(r: 0.5, g: 0.5, b: 1).linear))
|
||||
|
@ -20,7 +20,9 @@ struct Player {
|
||||
|
||||
private var _onGround: Bool = false
|
||||
|
||||
public var position: SIMD3<Float> { self._position + .init(0, Self.eyeLevel, 0) }
|
||||
public var position: SIMD3<Float> {
|
||||
get { self._position + .init(0, Self.eyeLevel, 0) } set { self._position = newValue }
|
||||
}
|
||||
public var rotation: SIMD2<Float> { self._rotation }
|
||||
|
||||
mutating func update(deltaTime: Float, boxes: [Box]) {
|
||||
@ -36,22 +38,27 @@ struct Player {
|
||||
}
|
||||
self._rotation.y = self._rotation.y.clamp(-.pi * 0.5, .pi * 0.5)
|
||||
|
||||
if self._onGround {
|
||||
// Movement on ground
|
||||
let movement = pad.leftStick.cardinalDeadzone(min: 0.1, max: 1)
|
||||
let rotc = cos(self._rotation.x), rots = sin(self._rotation.x)
|
||||
self._velocity.x = (movement.x * rotc - movement.y * rots) * Self.accelerationCoeff
|
||||
self._velocity.z = (movement.y * rotc + movement.x * rots) * Self.accelerationCoeff
|
||||
// Movement (slower in air than on ground)
|
||||
let movement = pad.leftStick.cardinalDeadzone(min: 0.1, max: 1)
|
||||
let rotc = cos(self._rotation.x), rots = sin(self._rotation.x)
|
||||
let movementScale: Float = self._onGround ? 1.0 : 0.4
|
||||
self._velocity.x = (
|
||||
movement.x * rotc - movement.y * rots
|
||||
) * Self.accelerationCoeff * movementScale
|
||||
self._velocity.z = (
|
||||
movement.y * rotc + movement.x * rots
|
||||
) * Self.accelerationCoeff * movementScale
|
||||
|
||||
if self._onGround {
|
||||
// Jumping
|
||||
if pad.pressed(.east) {
|
||||
self._velocity.y = Self.jumpVelocity
|
||||
self._onGround = false
|
||||
}
|
||||
}
|
||||
|
||||
// Flying
|
||||
self._velocity.y += pad.rightTrigger * 36 * deltaTime
|
||||
|
||||
// Flying and unflying
|
||||
self._velocity.y += (pad.rightTrigger - pad.leftTrigger) * 36 * deltaTime
|
||||
|
||||
// Reset
|
||||
if pad.pressed(.back) {
|
||||
@ -112,5 +119,17 @@ struct Player {
|
||||
self._velocity.x = 0
|
||||
self._velocity.z = 0
|
||||
}
|
||||
|
||||
if self._velocity.x > 10 {
|
||||
self._velocity.x = 10
|
||||
}
|
||||
|
||||
if self._velocity.y > 10 {
|
||||
self._velocity.y = 10
|
||||
}
|
||||
|
||||
if abs(self._velocity.y) > 40 {
|
||||
self._velocity.y = Float(signOf: self._velocity.y, magnitudeOf: 40.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user