Last active
December 12, 2019 20:55
-
-
Save polaco1782/1787306c491746fc207d75c9baa8cf4c 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
<?php | |
define('TICKS_PER_SEC', 60); | |
define('SECTOR_SIZE', 16); | |
define('WALKING_SPEED', 5); | |
define('FLYING_SPEED', 15); | |
define('TERMINAL_VELOCITY', 50); | |
define('PLAYER_HEIGHT', 2); | |
define('GRAVITY', 20.0); | |
define('MAX_JUMP_HEIGHT', 1.0); | |
// About the height of a block. | |
// To derive the formula for calculating jump speed, first solve | |
// v_t = v_0 + a * t | |
// for the time at which you achieve maximum height, where a is the acceleration | |
// due to gravity and v_t = 0. This gives: | |
// t = - v_0 / a | |
// Use t and the desired MAX_JUMP_HEIGHT to solve for v_0 (jump speed) in | |
// s = s_0 + v_0 * t + (a * t^2) / 2 | |
define('JUMP_SPEED', sqrt(2 * GRAVITY * MAX_JUMP_HEIGHT)); | |
define('FACES', [ [ 0, 1, 0], | |
[ 0,-1, 0], | |
[-1, 0, 0], | |
[ 1, 0, 0], | |
[ 0, 0, 1], | |
[ 0, 0,-1] | |
]); | |
function cube_vertices($x, $y, $z, $n) | |
{ | |
return [ [$x-$n,$y+$n,$z-$n], [$x-$n,$y+$n,$z+$n], [$x+$n,$y+$n,$z+$n], [$x+$n,$y+$n,$z-$n], # top | |
[$x-$n,$y-$n,$z-$n], [$x+$n,$y-$n,$z-$n], [$x+$n,$y-$n,$z+$n], [$x-$n,$y-$n,$z+$n], # bottom | |
[$x-$n,$y-$n,$z-$n], [$x-$n,$y-$n,$z+$n], [$x-$n,$y+$n,$z+$n], [$x-$n,$y+$n,$z-$n], # left | |
[$x+$n,$y-$n,$z+$n], [$x+$n,$y-$n,$z-$n], [$x+$n,$y+$n,$z-$n], [$x+$n,$y+$n,$z+$n], # right | |
[$x-$n,$y-$n,$z+$n], [$x+$n,$y-$n,$z+$n], [$x+$n,$y+$n,$z+$n], [$x-$n,$y+$n,$z+$n], # front | |
[$x+$n,$y-$n,$z-$n], [$x-$n,$y-$n,$z-$n], [$x-$n,$y+$n,$z-$n], [$x+$n,$y+$n,$z-$n] # back | |
]; | |
} | |
// Return the bounding vertices of the texture square. | |
function tex_coord($x, $y, $n=4) | |
{ | |
$m = 1.0 / $n; | |
$dx = $x * $m; | |
$dy = $y * $m; | |
return [ $dx, $dy, $dx + $m, $dy, $dx + $m, $dy + $m, $dx, $dy + $m ]; | |
} | |
// Return a list of the texture squares for the top, bottom and side. | |
function tex_coords(array $top, array $bottom, array $side) | |
{ | |
[$tx, $ty] = $top; | |
[$bx, $by] = $bottom; | |
[$sx, $sy] = $side; | |
return array_merge(tex_coord($tx, $ty), tex_coord($bx, $by), tex_coord($sx, $sy)); | |
} | |
// Accepts `position` of arbitrary precision and returns the block containing that position. | |
function normalize(array $position) | |
{ | |
[$x, $y, $z] = $position; | |
return [ | |
int(round($x)), | |
int(round($y)), | |
int(round($z)) | |
]; | |
} | |
function sectorize(array $position) | |
{ | |
[$x, $y, $z] = normalize($position); | |
return [ floor($x/SECTOR_SIZE), 0, floor($z/SECTOR_SIZE) ]; | |
} | |
function hashpos(array $position) | |
{ | |
// this is an ugly crude hack. PHP for() iteration is EXTREMELY slow | |
// in recursive calls. Indexing as integer will greatly speed it up. | |
return crc32("$position[0]$position[1]$position[2]"); | |
} | |
define('GRASS', tex_coords([1, 0], [0, 1], [0, 0])); | |
define('SAND', tex_coords([1, 1], [1, 1], [1, 1])); | |
define('BRICK', tex_coords([2, 0], [2, 0], [2, 0])); | |
define('STONE', tex_coords([2, 1], [2, 1], [2, 1])); | |
class World | |
{ | |
private $world = []; | |
private $visible = []; | |
private $window; | |
// Initialize the world by placing all the blocks. | |
public function __construct() | |
{ | |
$n = 80; // 1/2 width and height of world | |
$s = 1; // step size | |
$y = 0; // initial y height | |
foreach(range(-$n, $n, $s) as $x) | |
{ | |
foreach(range(-$n, $n, $s) as $z) | |
{ | |
// create a layer stone and grass everywhere | |
$this->addblock([$x, $y - 2, $z], GRASS, false); | |
$this->addblock([$x, $y - 3, $z], STONE, false); | |
if(in_array($x, [-$n, $n]) || in_array($z, [-$n, $n])) | |
{ | |
// create outer walls | |
foreach(range(-2, 3) as $dy) | |
$this->addblock([$x, $y + $dy, $z], STONE, false); | |
} | |
} | |
} | |
} | |
public function init_video() | |
{ | |
SDL_Init(SDL_INIT_EVERYTHING); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); | |
$this->window = SDL_CreateWindow("CRAPS", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); | |
SDL_GL_CreateContext($this->window); | |
} | |
public function dump() | |
{ | |
print_r($this->world); | |
printf("Total world blocks: %d\n", sizeof($this->world)); | |
} | |
// returns a block from the position | |
public function getblock(array $position) | |
{ | |
$crc = hashpos($position); | |
if(isset($this->world[$crc])) | |
return $this->world[$crc]; | |
return false; | |
} | |
// deletes a block from the array | |
public function delblock(array $position) | |
{ | |
$crc = hashpos($position); | |
if(isset($this->world[$crc])) | |
unset($this->world[$crc]); | |
} | |
public function addblock(array $position, array $texture, bool $immediate=true) | |
{ | |
$crc = hashpos($position); | |
// add vertex block to the array | |
$this->world[$crc] = [$position, $texture, $crc]; | |
} | |
// Returns False is given `position` is surrounded on all 6 sides by blocks, True otherwise. | |
public function exposed(array $position) | |
{ | |
[$x, $y, $z] = $position; | |
foreach(FACES as [$dx,$dy,$dz]) | |
{ | |
$crc = hashpos([$x + $dx, $y + $dy, $z + $dz]); | |
if(!isset($this->world[$crc])) | |
return true; | |
} | |
return false; | |
} | |
private function render_block(array $position, array $texture) | |
{ | |
[$x, $y, $z] = $position; | |
// generate cube vertices | |
$vertex = cube_vertices($x, $y, $z, 0.5); | |
var_dump($vertex); | |
} | |
public function show_block(array $position, bool $immediate=true) | |
{ | |
[$pos, $tex, $crc] = $this->getblock($position); | |
// add block to visible list | |
$this->visible[$crc] = [$pos, $tex]; | |
//if(immediate) | |
$this->render_block($pos, $tex); | |
} | |
/* | |
def show_block(self, position, immediate=True): | |
""" Show the block at the given `position`. This method assumes the | |
block has already been added with add_block() | |
Parameters | |
---------- | |
position : tuple of len 3 | |
The (x, y, z) position of the block to show. | |
immediate : bool | |
Whether or not to show the block immediately. | |
""" | |
texture = self.world[position] | |
self.shown[position] = texture | |
if immediate: | |
self._show_block(position, texture) | |
else: | |
self._enqueue(self._show_block, position, texture) | |
def _show_block(self, position, texture): | |
""" Private implementation of the `show_block()` method. | |
Parameters | |
---------- | |
position : tuple of len 3 | |
The (x, y, z) position of the block to show. | |
texture : list of len 3 | |
The coordinates of the texture squares. Use `tex_coords()` to | |
generate. | |
""" | |
x, y, z = position | |
vertex_data = cube_vertices(x, y, z, 0.5) | |
texture_data = list(texture) | |
# create vertex list | |
# FIXME Maybe `add_indexed()` should be used instead | |
self._shown[position] = self.batch.add(24, GL_QUADS, self.group, | |
('v3f/static', vertex_data), | |
('t2f/static', texture_data))*/ | |
} | |
$x = new World(); | |
//$x->dump(); | |
//var_dump($x->show_block([-60,-2,59])); | |
$x->init_video(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment