void DoorRenderer::toggleState(const BLOCK_WDATA block, int local_x, int local_y, int local_z, Chunk &c, const uint8_t open_state) { BLOCK_SIDE side = static_cast<BLOCK_SIDE>(getBLOCKDATA(block) & BLOCK_SIDE_BITS); uint8_t new_data = door_side_map[side] | open_state | (getBLOCKDATA(block) & DOOR_TOP); c.setLocalBlock(local_x, local_y, local_z, getBLOCKWDATA(getBLOCK(block), new_data)); //Change the other door part as well if(getBLOCKDATA(block) & DOOR_TOP) //If top c.setGlobalBlockRelative(local_x, local_y - 1, local_z, getBLOCKWDATA(getBLOCK(block), new_data ^ DOOR_TOP)); else c.setGlobalBlockRelative(local_x, local_y + 1, local_z, getBLOCKWDATA(getBLOCK(block), new_data ^ DOOR_TOP)); }
void DoorRenderer::addedBlock(const BLOCK_WDATA block, int local_x, int local_y, int local_z, Chunk &c) { if(getBLOCKDATA(block) & DOOR_TOP) { if(getBLOCK(c.getGlobalBlockRelative(local_x, local_y - 1, local_z)) != BLOCK_AIR) c.setLocalBlock(local_x, local_y, local_z, BLOCK_AIR); else c.setGlobalBlockRelative(local_x, local_y - 1, local_z, getBLOCKWDATA(getBLOCK(block), getBLOCKDATA(block) ^ DOOR_TOP)); } else { if(getBLOCK(c.getGlobalBlockRelative(local_x, local_y + 1, local_z)) != BLOCK_AIR) c.setLocalBlock(local_x, local_y, local_z, BLOCK_AIR); else c.setGlobalBlockRelative(local_x, local_y + 1, local_z, getBLOCKWDATA(getBLOCK(block), getBLOCKDATA(block) ^ DOOR_TOP)); } }
void WorldTask::logic() { GLFix dx = 0, dz = 0; if(keyPressed(KEY_NSPIRE_8)) //Forward { GLFix dx1, dz1; getForward(&dx1, &dz1); dx += dx1; dz += dz1; } else if(keyPressed(KEY_NSPIRE_2)) //Backward { GLFix dx1, dz1; getForward(&dx1, &dz1); dx -= dx1; dz -= dz1; } if(keyPressed(KEY_NSPIRE_4)) //Left { GLFix dx1, dz1; getRight(&dx1, &dz1); dx -= dx1; dz -= dz1; } else if(keyPressed(KEY_NSPIRE_6)) //Right { GLFix dx1, dz1; getRight(&dx1, &dz1); dx += dx1; dz += dz1; } if(!world.intersect(aabb)) { AABB aabb_moved = aabb; aabb_moved.low_x += dx; aabb_moved.high_x += dx; if(!world.intersect(aabb_moved)) { x += dx; aabb = aabb_moved; } aabb_moved = aabb; aabb_moved.low_z += dz; aabb_moved.high_z += dz; if(!world.intersect(aabb_moved)) { z += dz; aabb = aabb_moved; } aabb_moved = aabb; aabb_moved.low_y += vy; aabb_moved.high_y += vy; can_jump = world.intersect(aabb_moved); if(!can_jump) { y += vy; aabb = aabb_moved; } else if(vy > GLFix(0)) { can_jump = false; vy = 0; } else vy = 0; vy -= 5; in_water = getBLOCK(world.getBlock((x / BLOCK_SIZE).floor(), ((y + eye_pos) / BLOCK_SIZE).floor(), (z / BLOCK_SIZE).floor())) == BLOCK_WATER; if(in_water) can_jump = true; } if(keyPressed(KEY_NSPIRE_5) && can_jump) //Jump { vy = 50; can_jump = false; } if(has_touchpad) { touchpad_report_t touchpad; touchpad_scan(&touchpad); if(touchpad.pressed) { switch(touchpad.arrow) { case TPAD_ARROW_DOWN: xr += speed()/3; break; case TPAD_ARROW_UP: xr -= speed()/3; break; case TPAD_ARROW_LEFT: yr -= speed()/3; break; case TPAD_ARROW_RIGHT: yr += speed()/3; break; case TPAD_ARROW_RIGHTDOWN: xr += speed()/3; yr += speed()/3; break; case TPAD_ARROW_UPRIGHT: xr -= speed()/3; yr += speed()/3; break; case TPAD_ARROW_DOWNLEFT: xr += speed()/3; yr -= speed()/3; break; case TPAD_ARROW_LEFTUP: xr -= speed()/3; yr -= speed()/3; break; } } else if(tp_had_contact && touchpad.contact) { yr += (touchpad.x - tp_last_x) / 50; xr -= (touchpad.y - tp_last_y) / 50; } tp_had_contact = touchpad.contact; tp_last_x = touchpad.x; tp_last_y = touchpad.y; } else { if(keyPressed(KEY_NSPIRE_UP)) xr -= speed()/3; else if(keyPressed(KEY_NSPIRE_DOWN)) xr += speed()/3; if(keyPressed(KEY_NSPIRE_LEFT)) yr -= speed()/3; else if(keyPressed(KEY_NSPIRE_RIGHT)) yr += speed()/3; } //Normalisation required for rotation with nglRotate yr.normaliseAngle(); xr.normaliseAngle(); //xr and yr are normalised, so we can't test for negative values if(xr > GLFix(180)) if(xr <= GLFix(270)) xr = 269; if(xr < GLFix(180)) if(xr >= GLFix(90)) xr = 89; //Do test only on every second frame, it's expensive if(do_test) { GLFix dx = fast_sin(yr)*fast_cos(xr), dy = -fast_sin(xr), dz = fast_cos(yr)*fast_cos(xr); GLFix dist; if(!world.intersectsRay(x, y + eye_pos, z, dx, dy, dz, selection_pos, selection_side, dist, in_water)) selection_side = AABB::NONE; else selection_pos_abs = {x + dx * dist, y + eye_pos + dy * dist, z + dz * dist}; } world.setPosition(x, y, z); do_test = !do_test; if(key_held_down) key_held_down = keyPressed(KEY_NSPIRE_ESC) || keyPressed(KEY_NSPIRE_7) || keyPressed(KEY_NSPIRE_9) || keyPressed(KEY_NSPIRE_1) || keyPressed(KEY_NSPIRE_3) || keyPressed(KEY_NSPIRE_PERIOD) || keyPressed(KEY_NSPIRE_MINUS) || keyPressed(KEY_NSPIRE_PLUS) || keyPressed(KEY_NSPIRE_MENU); else if(keyPressed(KEY_NSPIRE_ESC)) //Save & Exit { save(); Task::running = false; return; } else if(keyPressed(KEY_NSPIRE_7)) //Put block down { if(selection_side != AABB::NONE) { if(!world.blockAction(selection_pos.x, selection_pos.y, selection_pos.z)) { VECTOR3 pos = selection_pos; switch(selection_side) { case AABB::BACK: ++pos.z; break; case AABB::FRONT: --pos.z; break; case AABB::LEFT: --pos.x; break; case AABB::RIGHT: ++pos.x; break; case AABB::BOTTOM: --pos.y; break; case AABB::TOP: ++pos.y; break; default: puts("This can't normally happen #1"); break; } if(!world.intersect(aabb)) { //Only set the block if there's air const BLOCK_WDATA current_block = world.getBlock(pos.x, pos.y, pos.z); if(current_block == BLOCK_AIR || (in_water && getBLOCK(current_block) == BLOCK_WATER)) { if(!global_block_renderer.isOriented(current_inventory.currentSlot())) world.changeBlock(pos.x, pos.y, pos.z, current_inventory.currentSlot()); else { AABB::SIDE side = selection_side; //If the block is not fully oriented and has been placed on top or bottom of another block, determine the orientation by yr if(!global_block_renderer.isFullyOriented(current_inventory.currentSlot()) && (side == AABB::TOP || side == AABB::BOTTOM)) side = yr < GLFix(45) ? AABB::FRONT : yr < GLFix(135) ? AABB::LEFT : yr < GLFix(225) ? AABB::BACK : yr < GLFix(315) ? AABB::RIGHT : AABB::FRONT; world.changeBlock(pos.x, pos.y, pos.z, getBLOCKWDATA(current_inventory.currentSlot(), side)); //AABB::SIDE is compatible to BLOCK_SIDE } //If the player is stuck now, it's because of the block change, so remove it again if(world.intersect(aabb)) world.changeBlock(pos.x, pos.y, pos.z, BLOCK_AIR); } } } } key_held_down = true; } else if(keyPressed(KEY_NSPIRE_9)) //Remove block { if(selection_side != AABB::NONE && world.getBlock(selection_pos.x, selection_pos.y, selection_pos.z) != BLOCK_BEDROCK) world.changeBlock(selection_pos.x, selection_pos.y, selection_pos.z, BLOCK_AIR); key_held_down = true; } else if(keyPressed(KEY_NSPIRE_1)) //Switch inventory slot { current_inventory.previousSlot(); key_held_down = true; } else if(keyPressed(KEY_NSPIRE_3)) { current_inventory.nextSlot(); key_held_down = true; } else if(keyPressed(KEY_NSPIRE_PERIOD)) //Open list of blocks (or take screenshot with Ctrl + .) { if(keyPressed(KEY_NSPIRE_CTRL)) { //Find a filename that doesn't exist char buf[45]; unsigned int i; for(i = 0; i <= 999; ++i) { sprintf(buf, "/documents/ndless/screenshot_%d.ppm.tns", i); struct stat stat_buf; if(stat(buf, &stat_buf) != 0) break; } if(i > 999 || !saveTextureToFile(*screen, buf)) setMessage("Screenshot failed!"); else { sprintf(message, "Screenshot taken (%d)!", i); message_timeout = 20; } } else block_list_task.makeCurrent(); key_held_down = true; } else if(keyPressed(KEY_NSPIRE_MINUS)) //Decrease max view distance { int fov = world.fieldOfView() - 1; world.setFieldOfView(fov < 1 ? 1 : fov); key_held_down = true; } else if(keyPressed(KEY_NSPIRE_PLUS)) //Increase max view distance { world.setFieldOfView(world.fieldOfView() + 1); key_held_down = true; } else if(keyPressed(KEY_NSPIRE_MENU)) { menu_task.makeCurrent(); key_held_down = true; } }