Last active
September 13, 2016 14:14
-
-
Save mohiji/1f4087395c5ab8aa565595d11e63af0b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
struct Vector3 : Equatable { | |
let x: Float | |
let y: Float | |
let z: Float | |
func magnitude() -> Float { | |
return sqrtf(x * x + y * y + z * z) | |
} | |
func normal() -> Vector3 { | |
let magnitude = self.magnitude() | |
if (magnitude == 0.0) { | |
return Vector3(x: 0.0, y: 0.0, z: 0.0) | |
} else { | |
return self / magnitude | |
} | |
} | |
} | |
func ==(left: Vector3, right: Vector3) -> Bool { | |
return left.x == right.x && left.y == right.y && left.z == right.z | |
} | |
prefix func -(v: Vector3) -> Vector3 { | |
return Vector3(x: -v.x, y: -v.y, z: -v.z) | |
} | |
func +(left: Vector3, right: Vector3) -> Vector3 { | |
return Vector3(x: left.x + right.x, y: left.y + right.y, z: left.z + right.z) | |
} | |
func -(left: Vector3, right: Vector3) -> Vector3 { | |
return Vector3(x: left.x - right.x, y: left.y - right.y, z: left.z - right.z) | |
} | |
func *(left: Vector3, right: Float) -> Vector3 { | |
return Vector3(x: left.x * right, y: left.y * right, z: left.z * right) | |
} | |
func *(left: Vector3, right: Vector3) -> Vector3 { | |
return Vector3(x: left.z * right.z, y: left.y * right.y, z: left.z * right.z) | |
} | |
func *(left: Float, right: Vector3) -> Vector3 { | |
return Vector3(x: left * right.x, y: left * right.y, z: left * right.z) | |
} | |
func /(left: Vector3, right: Float) -> Vector3 { | |
return Vector3(x: left.x / right, y: left.y / right, z: left.z / right) | |
} | |
func distance(left: Vector3, _ right: Vector3) -> Float { | |
return (left - right).magnitude() | |
} | |
struct Block { | |
let location: Vector3 | |
let name: String | |
let durability: Int | |
let textureId: Int | |
let breakable: Bool | |
let visible: Bool | |
let type: Int | |
let id: Int | |
} | |
enum EntityType { | |
case Zombie | |
case Chicken | |
case Exploder | |
case TallCreepyThing | |
} | |
class Entity { | |
let name: String | |
let type: EntityType | |
let speed: Vector3 | |
var location: Vector3 | |
var health: Int | |
init(location: Vector3, type: EntityType) { | |
self.location = location | |
self.type = type | |
switch (type) { | |
case .Zombie: | |
self.name = "Zombie" | |
self.speed = Vector3(x: 0.5, y: 0.0, z: 0.5) | |
self.health = 50 | |
case .Chicken: | |
self.name = "Chicken" | |
self.speed = Vector3(x: 0.75, y: 0.25, z: 0.75) | |
self.health = 25 | |
case .Exploder: | |
self.name = "Exploder" | |
self.speed = Vector3(x: 0.75, y: 0.0, z: 0.75) | |
self.health = 75 | |
case .TallCreepyThing: | |
self.name = "Tall Creepy Thing" | |
self.speed = Vector3(x: 1.0, y: 1.0, z: 1.0) | |
self.health = 500 | |
} | |
} | |
func updatePosition() { | |
self.location = self.location + self.speed | |
} | |
} | |
class Chunk { | |
static let numBlocks = 256 | |
static let numEntities = 1000 | |
let blocks: [Int] | |
let location: Vector3 | |
var entities: [Entity] | |
init(location: Vector3) { | |
self.location = location | |
var mutableBlocks = [Int]() | |
mutableBlocks.reserveCapacity(Chunk.numBlocks) | |
for i in 0 ..< Chunk.numBlocks { | |
mutableBlocks.append(i % 256) | |
} | |
blocks = mutableBlocks | |
entities = [] | |
entities.reserveCapacity(Chunk.numEntities) | |
for i in 0 ..< (Chunk.numEntities / 4) { | |
entities.append(Entity(location: Vector3(x: Float(i), y: Float(i), z: Float(i)), type: EntityType.Chicken)) | |
entities.append(Entity(location: Vector3(x: Float(i + 2), y: Float(i), z: Float(i)), type: EntityType.Zombie)) | |
entities.append(Entity(location: Vector3(x: Float(i + 3), y: Float(i), z: Float(i)), type: EntityType.Exploder)) | |
entities.append(Entity(location: Vector3(x: Float(i + 4), y: Float(i), z: Float(i)), type: EntityType.TallCreepyThing)) | |
} | |
} | |
func processEntities() { | |
for entity in entities { | |
entity.updatePosition() | |
} | |
} | |
} | |
class Game { | |
static let chunkCount = 100 | |
let blocks: [Block] | |
var chunks: [Chunk] | |
var playerLocation = Vector3(x: 0.0, y: 0.0, z: 0.0) | |
var chunkCounter: Int | |
init() { | |
var mBlocks = [Block]() | |
mBlocks.reserveCapacity(Chunk.numBlocks) | |
for i in 0 ..< Chunk.numBlocks { | |
mBlocks.append(Block(location: Vector3(x: Float(i), y: Float(i), z: Float(i)), | |
name: "Block:\(i)", | |
durability: 100, | |
textureId: 1, | |
breakable: true, | |
visible: true, | |
type: 1, | |
id: i)) | |
} | |
self.blocks = mBlocks | |
chunks = [] | |
chunks.reserveCapacity(Game.chunkCount) | |
for i in 0 ..< Game.chunkCount { | |
chunks.append(Chunk(location: Vector3(x: Float(i), y: 0.0, z: 0.0))) | |
} | |
chunkCounter = Game.chunkCount | |
} | |
func updateWorld() { | |
for i in 0 ..< chunks.count { | |
let chunk = chunks[i] | |
let dist = distance(playerLocation, chunk.location) | |
if dist > Float(Game.chunkCount) { | |
// Replace the existing chunk with a new one | |
chunks[i] = Chunk(location: Vector3(x: Float(chunkCounter), y: 0.0, z: 0.0)) | |
chunkCounter = chunkCounter + 1 | |
} else { | |
chunk.processEntities() | |
} | |
} | |
} | |
} | |
print("Creating game!") | |
let loadStart = CFAbsoluteTimeGetCurrent() | |
let game = Game() | |
let loadElapsed = CFAbsoluteTimeGetCurrent() - loadStart | |
print("Load game time: \(loadElapsed * 1000.0)ms") | |
let numFrames = 60 * 60 | |
var minFrameTime = CFAbsoluteTime(1000.0) | |
var maxFrameTime = CFAbsoluteTime(0.0) | |
var frameTimeAccum = CFAbsoluteTime(0.0) | |
for i in 0 ..< numFrames { | |
let frameStart = CFAbsoluteTimeGetCurrent() | |
game.playerLocation = game.playerLocation + Vector3(x: 0.1, y: 0.0, z: 0.0) | |
game.updateWorld() | |
let frameElapsed = CFAbsoluteTimeGetCurrent() - frameStart | |
// print("Frame \(i): \(frameElapsed * 1000.0)ms") | |
if frameElapsed < minFrameTime { | |
minFrameTime = frameElapsed | |
} | |
if frameElapsed > maxFrameTime { | |
maxFrameTime = frameElapsed | |
} | |
frameTimeAccum += frameElapsed | |
} | |
let totalElapsed = CFAbsoluteTimeGetCurrent() - loadStart | |
print("Run finished in \(totalElapsed) seconds") | |
print("Minimum frame time: \(minFrameTime * 1000.0)ms") | |
print("Maximum frame time: \(maxFrameTime * 1000.0)ms") | |
print("Average frame time: \((frameTimeAccum / CFAbsoluteTime(numFrames)) * 1000.0)ms") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment