Skip to content

Instantly share code, notes, and snippets.

@polaco1782
Last active December 12, 2019 20:55
Show Gist options
  • Save polaco1782/1787306c491746fc207d75c9baa8cf4c to your computer and use it in GitHub Desktop.
Save polaco1782/1787306c491746fc207d75c9baa8cf4c to your computer and use it in GitHub Desktop.
<?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