Skip to content

Commit

Permalink
Merge pull request #227 from konstructs/fix-falling-outside-of-chunk
Browse files Browse the repository at this point in the history
Don't move player if chunk is not loaded
  • Loading branch information
petterarvidsson committed Nov 18, 2016
2 parents 8c4a18e + a22cac1 commit 5c6bb21
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 91 deletions.
7 changes: 4 additions & 3 deletions lib/include/world.h
Expand Up @@ -15,9 +15,10 @@ namespace konstructs {
int size() const;
void delete_unused_chunks(const Vector3i player_chunk, const int radi);
void insert(const ChunkData data);
const BlockData get_block(const Vector3i &block_pos) const;
const ChunkData chunk_at(const Vector3i &block_pos) const;
const optional<ChunkData> chunk_opt(const Vector3i &chunk_pos) const;
const optional<BlockData> get_block(const Vector3i &block_pos) const;
const optional<ChunkData> chunk_by_block(const Vector3f &block_pos) const;
const optional<ChunkData> chunk_by_block(const Vector3i &block_pos) const;
const optional<ChunkData> chunk(const Vector3i &chunk_pos) const;
const std::vector<ChunkData> atAndAround(const Vector3i &pos) const;
std::unordered_map<Vector3i, ChunkData, matrix_hash<Vector3i>>::const_iterator find(const Vector3i &pos) const;
std::unordered_map<Vector3i, ChunkData, matrix_hash<Vector3i>>::const_iterator end() const;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/chunk_factory.cpp
Expand Up @@ -117,7 +117,7 @@ namespace konstructs {

const ChunkData get_chunk(const Vector3i &position,
const World &world) {
auto chunk = world.chunk_opt(position);
auto chunk = world.chunk(position);

if(chunk) {
return chunk.value();
Expand Down
157 changes: 83 additions & 74 deletions lib/src/player.cpp
Expand Up @@ -11,6 +11,10 @@ namespace konstructs {
static float CAMERA_OFFSET = 0.5f;
static Vector3f CAMERA_OFFSET_VECTOR = Vector3f(0, CAMERA_OFFSET, 0);

static bool block_is_obstacle(const optional<BlockData> &block, const BlockTypeInfo &blocks) {
return block && blocks.is_obstacle[(*block).type];
}

Player::Player(const int id, const Vector3f position, const float rx,
const float ry):
id(id), position(position), mrx(rx), mry(ry), flying(false), dy(0) {}
Expand Down Expand Up @@ -54,7 +58,7 @@ namespace konstructs {
/* We may place on our feet under certain circumstances */
if(f(1) == block(1)) {
/* Allow placing on our feet if the block above our head is not an obstacle*/
return !blocks.is_obstacle[world.get_block(Vector3i(f(0), f(1) + 2, f(2))).type];
return !block_is_obstacle(world.get_block(Vector3i(f(0), f(1) + 2, f(2))), blocks);
} else {
/* We are never allowed to place on our head */
return false;
Expand All @@ -67,81 +71,86 @@ namespace konstructs {
const World &world, const BlockTypeInfo &blocks,
const float near_distance, const bool jump,
const bool sneaking) {
float vx = 0, vy = 0, vz = 0;
if (!sz && !sx) { // Not mowing in X or Z
vx = 0;
vz = 0;
} else { // Moving in X or Z
optional<ChunkData> chunk_opt = world.chunk_by_block(position);

if(chunk_opt) { // Only update position if the chunk we are in is loaded
float vx = 0, vy = 0, vz = 0;
if (!sz && !sx) { // Not mowing in X or Z
vx = 0;
vz = 0;
} else { // Moving in X or Z

float strafe = atan2f(sz, sx);

if (flying) {
float m = cosf(mrx);
float y = sinf(mrx);
if (sx) {
if (!sz) {
y = 0;
float strafe = atan2f(sz, sx);

if (flying) {
float m = cosf(mrx);
float y = sinf(mrx);
if (sx) {
if (!sz) {
y = 0;
}
m = 1;
}
m = 1;
}
if (sz < 0) {
y = -y;
if (sz < 0) {
y = -y;
}
vx = cosf(mry + strafe) * m;
vy = y;
vz = sinf(mry + strafe) * m;
} else {
vx = cosf(mry + strafe);
vy = 0;
vz = sinf(mry + strafe);
}
vx = cosf(mry + strafe) * m;
vy = y;
vz = sinf(mry + strafe) * m;
} else {
vx = cosf(mry + strafe);
vy = 0;
vz = sinf(mry + strafe);
}
}

if(jump) {
if(flying) {
// Jump in flight moves upward at constant speed
vy = 1;
} else if(dy == 0) {
// Jump when walking changes the acceleration upwards to 8
dy = 8;
} else {
// Get middle of block
Vector3i iPos((int)(position[0] + 0.5f), (int)(position[1]), (int)(position[2] + 0.5f));
ChunkData chunk = world.chunk_at(iPos);
if(blocks.state[chunk.get(iPos).type] == STATE_LIQUID) {
dy = 5.5;
if(jump) {
if(flying) {
// Jump in flight moves upward at constant speed
vy = 1;
} else if(dy == 0) {
// Jump when walking changes the acceleration upwards to 8
dy = 8;
} else {
// Get middle of block
Vector3i iPos((int)(position[0] + 0.5f), (int)(position[1]), (int)(position[2] + 0.5f));
auto chunk = world.chunk_by_block(iPos);

if(chunk && blocks.state[chunk->get(iPos).type] == STATE_LIQUID) {
dy = 5.5;
}
}
}
}

float speed = flying ? 20 : 5;
int estimate =
roundf(sqrtf(powf(vx * speed, 2) +
powf(vy * speed + std::abs(dy) * 2, 2) +
powf(vz * speed, 2)) * dt * 8);
int step = std::max(8, estimate);
float ut = dt / step;
vx = vx * ut * speed;
vy = vy * ut * speed;
vz = vz * ut * speed;
for (int i = 0; i < step; i++) {
if (flying) {
// When flying upwards acceleration is constant i.e. not falling
dy = 0;
} else {
// Calculate "gravity" by decreasing upwards acceleration
dy -= ut * 25;
dy = std::max(dy, -250.0f);
float speed = flying ? 20 : 5;
int estimate =
roundf(sqrtf(powf(vx * speed, 2) +
powf(vy * speed + std::abs(dy) * 2, 2) +
powf(vz * speed, 2)) * dt * 8);
int step = std::max(8, estimate);
float ut = dt / step;
vx = vx * ut * speed;
vy = vy * ut * speed;
vz = vz * ut * speed;
for (int i = 0; i < step; i++) {
if (flying) {
// When flying upwards acceleration is constant i.e. not falling
dy = 0;
} else {
// Calculate "gravity" by decreasing upwards acceleration
dy -= ut * 25;
dy = std::max(dy, -250.0f);
}
position += Vector3f(vx, vy + dy * ut, vz);
if (collide(world, blocks, near_distance, sneaking)) {
dy = 0;
}
}
position += Vector3f(vx, vy + dy * ut, vz);
if (collide(world, blocks, near_distance, sneaking)) {
dy = 0;
if (position[1] < 0) {
position[1] = 2;
}
}
if (position[1] < 0) {
position[1] = 2;
}
return position;
}

Expand Down Expand Up @@ -219,44 +228,44 @@ namespace konstructs {

try {

if (blocks.is_obstacle[world.get_block(feet()).type]) {
if (block_is_obstacle(world.get_block(feet()), blocks)) {
position[1] += 1.0f;
return 1;
}

if(sneaking) {
if (px < -pad && !blocks.is_obstacle[world.get_block(Vector3i(nx - 1, ny - 2, nz)).type]) {
if (px < -pad && !block_is_obstacle(world.get_block(Vector3i(nx - 1, ny - 2, nz)), blocks)) {
position[0] = nx - pad;
}
if (px > pad && !blocks.is_obstacle[world.get_block(Vector3i(nx + 1, ny - 2, nz)).type]) {
if (px > pad && !block_is_obstacle(world.get_block(Vector3i(nx + 1, ny - 2, nz)), blocks)) {
position[0] = nx + pad;
}
if (pz < -pad && !blocks.is_obstacle[world.get_block(Vector3i(nx, ny - 2, nz - 1)).type]) {
if (pz < -pad && !block_is_obstacle(world.get_block(Vector3i(nx, ny - 2, nz - 1)), blocks)) {
position[2] = nz - pad;
}
if (pz > pad && !blocks.is_obstacle[world.get_block(Vector3i(nx, ny - 2, nz + 1)).type]) {
if (pz > pad && !block_is_obstacle(world.get_block(Vector3i(nx, ny - 2, nz + 1)), blocks)) {
position[2] = nz + pad;
}
}
for (int dy = 0; dy < height; dy++) {
if (px < -pad && blocks.is_obstacle[world.get_block(Vector3i(nx - 1, ny - dy, nz)).type]) {
if (px < -pad && block_is_obstacle(world.get_block(Vector3i(nx - 1, ny - dy, nz)), blocks)) {
position[0] = nx - pad;
}
if (px > pad && blocks.is_obstacle[world.get_block(Vector3i(nx + 1, ny - dy, nz)).type]) {
if (px > pad && block_is_obstacle(world.get_block(Vector3i(nx + 1, ny - dy, nz)), blocks)) {
position[0] = nx + pad;
}
if (py < -pad && blocks.is_obstacle[world.get_block(Vector3i(nx, ny - dy - 1, nz)).type]) {
if (py < -pad && block_is_obstacle(world.get_block(Vector3i(nx, ny - dy - 1, nz)), blocks)) {
position[1] = ny - pad;
result = 1;
}
if (py > (pad - CAMERA_OFFSET) && blocks.is_obstacle[world.get_block(Vector3i(nx, ny - dy + 1, nz)).type]) {
if (py > (pad - CAMERA_OFFSET) && block_is_obstacle(world.get_block(Vector3i(nx, ny - dy + 1, nz)), blocks)) {
position[1] = ny + pad - CAMERA_OFFSET;
result = 1;
}
if (pz < -pad && blocks.is_obstacle[world.get_block(Vector3i(nx, ny - dy, nz - 1)).type]) {
if (pz < -pad && block_is_obstacle(world.get_block(Vector3i(nx, ny - dy, nz - 1)), blocks)) {
position[2] = nz - pad;
}
if (pz > pad && blocks.is_obstacle[world.get_block(Vector3i(nx, ny - dy, nz + 1)).type]) {
if (pz > pad && block_is_obstacle(world.get_block(Vector3i(nx, ny - dy, nz + 1)), blocks)) {
position[2] = nz + pad;
}
}
Expand Down
22 changes: 13 additions & 9 deletions lib/src/world.cpp
Expand Up @@ -25,20 +25,24 @@ namespace konstructs {
chunks.insert({pos, data});
}

const BlockData World::get_block(const Vector3i &block_pos) const {
return chunk_at(block_pos).get(block_pos);
const optional<BlockData> World::get_block(const Vector3i &block_pos) const {
auto chunk = chunk_by_block(block_pos);
if(chunk) {
return (*chunk).get(block_pos);
} else {
return nullopt;
}
}

const ChunkData World::chunk_at(const Vector3i &block_pos) const {
try {
return chunks.at(chunked_vec_int(block_pos));
} catch(std::out_of_range e) {
return VACUUM_CHUNK;
}
const optional<ChunkData> World::chunk_by_block(const Vector3f &block_pos) const {
return chunk(chunked_vec(block_pos));
}

const optional<ChunkData> World::chunk_by_block(const Vector3i &block_pos) const {
return chunk(chunked_vec_int(block_pos));
}

const optional<ChunkData> World::chunk_opt(const Vector3i &chunk_pos) const {
const optional<ChunkData> World::chunk(const Vector3i &chunk_pos) const {
try {
return chunks.at(chunk_pos);
} catch(std::out_of_range e) {
Expand Down
12 changes: 8 additions & 4 deletions src/main.cpp
Expand Up @@ -336,10 +336,14 @@ class Konstructs: public nanogui::Screen {
block.direction = direction;
block.rotation = rotation;
}
ChunkData updated_chunk =
world.chunk_at(l.first.position).set(l.first.position, block);
world.insert(updated_chunk);
model_factory.create_models({updated_chunk.position}, world);
auto chunk_opt =
world.chunk_by_block(l.first.position);
if(chunk_opt) {
ChunkData updated_chunk =
chunk_opt->set(l.first.position, block);
world.insert(updated_chunk);
model_factory.create_models({updated_chunk.position}, world);
}
}
click_delay = MOUSE_CLICK_DELAY_IN_FRAMES;
client.click_at(1, l.first.position, translate_button(GLFW_MOUSE_BUTTON_2), hud.get_selection(),
Expand Down

0 comments on commit 5c6bb21

Please sign in to comment.