diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 771fac2..4ab8fd7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,6 +24,8 @@ download_file_if_it_doesnt_exist(parson.h https://raw.githubusercontent.com/kgab download_file_if_it_doesnt_exist(http.h https://raw.githubusercontent.com/mattiasgustavsson/libs/master/http.h) download_file_if_it_doesnt_exist(log.h https://raw.githubusercontent.com/xtreme8000/log.c/master/src/log.h) download_file_if_it_doesnt_exist(log.c https://raw.githubusercontent.com/xtreme8000/log.c/master/src/log.c) +download_file_if_it_doesnt_exist(hashtable.c https://raw.githubusercontent.com/goldsborough/hashtable/master/hashtable.c) +download_file_if_it_doesnt_exist(hashtable.h https://raw.githubusercontent.com/goldsborough/hashtable/master/hashtable.h) download_file_if_it_doesnt_exist(../deps/libdeflate.h https://raw.githubusercontent.com/ebiggers/libdeflate/master/libdeflate.h) download_file_if_it_doesnt_exist(../bsresources.zip http://aos.party/bsresources.zip) @@ -58,6 +60,8 @@ list(APPEND CLIENT_SOURCES window.c) list(APPEND CLIENT_SOURCES utils.c) list(APPEND CLIENT_SOURCES ping.c) list(APPEND CLIENT_SOURCES log.c) +list(APPEND CLIENT_SOURCES minheap.c) +list(APPEND CLIENT_SOURCES hashtable.c) list(APPEND CLIENT_SOURCES ${BetterSpades_SOURCE_DIR}/resources/icon.rc) add_executable(client ${CLIENT_SOURCES}) @@ -100,15 +104,15 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${BetterSpades_SOURCE_DIR}/cmake/Modu set(OpenGL_GL_PREFERENCE LEGACY) if(ENABLE_GLFW) find_package(glfw3 REQUIRED) - target_link_libraries(client glfw3::glfw3) + target_link_libraries(client glfw3::glfw3 -static) endif() if(ENABLE_SDL) find_package(SDL REQUIRED) - target_link_libraries(client ${SDL_LIBRARY}) + target_link_libraries(client ${SDL_LIBRARY} -static) endif() if(ENABLE_SOUND) find_package(OpenAL REQUIRED) - target_link_libraries(client ${OPENAL_LIBRARY}) + target_link_libraries(client ${OPENAL_LIBRARY} -static) endif() find_package(enet REQUIRED) find_package(deflate REQUIRED) @@ -116,13 +120,13 @@ find_package(Threads REQUIRED) if(NOT ENABLE_OPENGLES) find_package(OpenGL REQUIRED) find_package(GLEW REQUIRED) - target_link_libraries(client GLEW::GLEW) + target_link_libraries(client GLEW::GLEW -static) else() find_package(OpenGL REQUIRED COMPONENTS EGL) - target_link_libraries(client OpenGL::EGL) + target_link_libraries(client OpenGL::EGL -static) endif() -target_link_libraries(client ${CMAKE_THREAD_LIBS_INIT} ${OPENGL_LIBRARIES} enet::enet deflate::deflate m) +target_link_libraries(client ${CMAKE_THREAD_LIBS_INIT} ${OPENGL_LIBRARIES} enet::enet deflate::deflate m -static) include_directories(client ${OPENAL_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR} ${OPENGL_EGL_INCLUDE_DIRS}) add_custom_command( diff --git a/src/camera.c b/src/camera.c index 92141fb..dacabc8 100644 --- a/src/camera.c +++ b/src/camera.c @@ -57,7 +57,24 @@ void camera_overflow_adjust() { } } -void camera_apply(float dt) { +void camera_apply() { + switch(camera_mode) { + case CAMERAMODE_FPS: + cameracontroller_fps_render(); + break; + case CAMERAMODE_BODYVIEW: + cameracontroller_bodyview_render(); + break; + case CAMERAMODE_SPECTATOR: + cameracontroller_spectator_render(); + break; + case CAMERAMODE_SELECTION: + cameracontroller_selection_render(); + break; + } +} + +void camera_update(float dt) { switch(camera_mode) { case CAMERAMODE_FPS: cameracontroller_fps(dt); diff --git a/src/camera.h b/src/camera.h index dcab346..445a2c5 100644 --- a/src/camera.h +++ b/src/camera.h @@ -58,4 +58,5 @@ int camera_CubeInFrustum(float x, float y, float z, float size, float size_y); int* camera_terrain_pick(unsigned char mode); int* camera_terrain_pickEx(unsigned char mode, float x, float y, float z, float ray_x, float ray_y, float ray_z); void camera_overflow_adjust(void); -void camera_apply(float dt); +void camera_apply(void); +void camera_update(float dt); diff --git a/src/cameracontroller.c b/src/cameracontroller.c index ea15bb2..c48412d 100644 --- a/src/cameracontroller.c +++ b/src/cameracontroller.c @@ -23,6 +23,7 @@ int cameracontroller_bodyview_mode = 0; int cameracontroller_bodyview_player = 0; float cameracontroller_bodyview_zoom = 0.0F; +float last_cy; void cameracontroller_fps(float dt) { players[local_player_id].connected = 1; players[local_player_id].alive = 1; @@ -54,6 +55,8 @@ void cameracontroller_fps(float dt) { } #endif + last_cy = players[local_player_id].physics.eye.y-players[local_player_id].physics.velocity.y*0.4F; + if(chat_input_mode==CHAT_NO_INPUT) { players[local_player_id].input.keys.up = window_key_down(WINDOW_KEY_UP); players[local_player_id].input.keys.down = window_key_down(WINDOW_KEY_DOWN); @@ -62,18 +65,24 @@ void cameracontroller_fps(float dt) { if(players[local_player_id].input.keys.crouch && !window_key_down(WINDOW_KEY_CROUCH) && player_uncrouch(&players[local_player_id])) { players[local_player_id].input.keys.crouch = 0; } - if(window_key_down(WINDOW_KEY_CROUCH)) { - players[local_player_id].input.keys.crouch = 1; - } - //players[local_player_id].input.keys.crouch = window_key_down(WINDOW_KEY_CROUCH); - players[local_player_id].input.keys.sprint = window_key_down(WINDOW_KEY_SPRINT); - players[local_player_id].input.keys.jump = window_key_down(WINDOW_KEY_SPACE); - players[local_player_id].input.keys.sneak = window_key_down(WINDOW_KEY_SNEAK); - if(window_key_down(WINDOW_KEY_SPACE) && !players[local_player_id].physics.airborne) { - players[local_player_id].physics.jump = 1; - } - } + if(window_key_down(WINDOW_KEY_CROUCH)) { + //following if-statement disables smooth crouching on local player + if(!players[local_player_id].input.keys.crouch && !players[local_player_id].physics.airborne) { + players[local_player_id].pos.y -= 0.9F; + players[local_player_id].physics.eye.y -= 0.9F; + last_cy -= 0.9F; + } + players[local_player_id].input.keys.crouch = 1; + } + players[local_player_id].input.keys.sprint = window_key_down(WINDOW_KEY_SPRINT); + players[local_player_id].input.keys.jump = window_key_down(WINDOW_KEY_SPACE); + players[local_player_id].input.keys.sneak = window_key_down(WINDOW_KEY_SNEAK); + + if(window_key_down(WINDOW_KEY_SPACE) && !players[local_player_id].physics.airborne) { + players[local_player_id].physics.jump = 1; + } + } camera_x = players[local_player_id].physics.eye.x; camera_y = players[local_player_id].physics.eye.y+player_height(&players[local_player_id]); @@ -114,8 +123,10 @@ void cameracontroller_fps(float dt) { camera_vx = players[local_player_id].physics.velocity.x; camera_vy = players[local_player_id].physics.velocity.y; camera_vz = players[local_player_id].physics.velocity.z; +} - matrix_lookAt(camera_x,camera_y,camera_z,camera_x+sin(camera_rot_x)*sin(camera_rot_y),camera_y+cos(camera_rot_y),camera_z+cos(camera_rot_x)*sin(camera_rot_y),0.0F,1.0F,0.0F); +void cameracontroller_fps_render() { + matrix_lookAt(camera_x,camera_y,camera_z,camera_x+sin(camera_rot_x)*sin(camera_rot_y),camera_y+cos(camera_rot_y),camera_z+cos(camera_rot_x)*sin(camera_rot_y),0.0F,1.0F,0.0F); } void cameracontroller_spectator(float dt) { @@ -206,21 +217,27 @@ void cameracontroller_spectator(float dt) { camera_vx = p->physics.velocity.x; camera_vy = p->physics.velocity.y; camera_vz = p->physics.velocity.z; + } else { + camera_x += camera_movement_x; + camera_y += camera_movement_y; + camera_z += camera_movement_z; + camera_vx = camera_movement_x; + camera_vy = camera_movement_y; + camera_vz = camera_movement_z; + } +} - float l = sqrt(distance3D(p->orientation_smooth.x,p->orientation_smooth.y,p->orientation_smooth.z,0,0,0)); +void cameracontroller_spectator_render() { + if(cameracontroller_bodyview_mode && players[cameracontroller_bodyview_player].alive) { + struct Player* p = &players[cameracontroller_bodyview_player]; + float l = len3D(p->orientation_smooth.x,p->orientation_smooth.y,p->orientation_smooth.z); float ox = p->orientation_smooth.x/l; float oy = p->orientation_smooth.y/l; float oz = p->orientation_smooth.z/l; matrix_lookAt(camera_x,camera_y,camera_z,camera_x+ox,camera_y+oy,camera_z+oz,0.0F,1.0F,0.0F); } else { - camera_x += camera_movement_x; - camera_y += camera_movement_y; - camera_z += camera_movement_z; - camera_vx = camera_movement_x; - camera_vy = camera_movement_y; - camera_vz = camera_movement_z; - matrix_lookAt(camera_x,camera_y,camera_z,camera_x+sin(camera_rot_x)*sin(camera_rot_y),camera_y+cos(camera_rot_y),camera_z+cos(camera_rot_x)*sin(camera_rot_y),0.0F,1.0F,0.0F); + matrix_lookAt(camera_x,camera_y,camera_z,camera_x+sin(camera_rot_x)*sin(camera_rot_y),camera_y+cos(camera_rot_y),camera_z+cos(camera_rot_x)*sin(camera_rot_y),0.0F,1.0F,0.0F); } } @@ -281,7 +298,12 @@ void cameracontroller_bodyview(float dt) { camera_vx = p->physics.velocity.x; camera_vy = p->physics.velocity.y; camera_vz = p->physics.velocity.z; + } +} +void cameracontroller_bodyview_render() { + if(cameracontroller_bodyview_mode && players[cameracontroller_bodyview_player].alive) { + struct Player* p = &players[cameracontroller_bodyview_player]; float l = sqrt(distance3D(p->orientation_smooth.x,p->orientation_smooth.y,p->orientation_smooth.z,0,0,0)); float ox = p->orientation_smooth.x/l; float oy = p->orientation_smooth.y/l; @@ -309,3 +331,8 @@ void cameracontroller_selection(float dt) { matrix_rotate(90.0F,1.0F,0.0F,0.0F); matrix_translate(-camera_x,-camera_y,-camera_z); } + +void cameracontroller_selection_render() { + matrix_rotate(90.0F,1.0F,0.0F,0.0F); + matrix_translate(-camera_x,-camera_y,-camera_z); +} diff --git a/src/cameracontroller.h b/src/cameracontroller.h index fae8384..1732671 100644 --- a/src/cameracontroller.h +++ b/src/cameracontroller.h @@ -25,3 +25,8 @@ void cameracontroller_fps(float dt); void cameracontroller_spectator(float dt); void cameracontroller_bodyview(float dt); void cameracontroller_selection(float dt); + +void cameracontroller_fps_render(void); +void cameracontroller_spectator_render(void); +void cameracontroller_bodyview_render(void); +void cameracontroller_selection_render(void); diff --git a/src/chunk.c b/src/chunk.c index 32b6655..8df1b6a 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -63,6 +63,7 @@ void chunk_init() { chunk_workers[k].vertex_data = NULL; chunk_workers[k].color_data = NULL; pthread_mutex_init(&chunk_workers[k].state_lock,NULL); + pthread_cond_init(&chunk_workers[k].can_work,NULL); pthread_create(&chunk_workers[k].thread,NULL,chunk_generate,&chunk_workers[k]); } } @@ -137,42 +138,34 @@ void* chunk_generate(void* data) { struct chunk_worker* worker = (struct chunk_worker*)data; while(1) { - int state = -1; pthread_mutex_lock(&worker->state_lock); - state = worker->state; + while(worker->state!=CHUNK_WORKERSTATE_BUSY) + pthread_cond_wait(&worker->can_work,&worker->state_lock); pthread_mutex_unlock(&worker->state_lock); - if(state==CHUNK_WORKERSTATE_BUSY) { - pthread_mutex_lock(&chunk_minimap_lock); - for(int x=worker->chunk_x;xchunk_x+CHUNK_SIZE;x++) { - for(int z=worker->chunk_y;zchunk_y+CHUNK_SIZE;z++) { - if((x%64)>0 && (z%64)>0) { - pthread_rwlock_rdlock(&chunk_map_locks[x+z*map_size_x]); - for(int y=map_size_y-1;y>=0;y--) { - if(map_colors[x+(y*map_size_z+z)*map_size_x]!=0xFFFFFFFF) { - map_minimap[(x+z*map_size_x)*4+0] = red(map_colors[x+(y*map_size_z+z)*map_size_x]); - map_minimap[(x+z*map_size_x)*4+1] = green(map_colors[x+(y*map_size_z+z)*map_size_x]); - map_minimap[(x+z*map_size_x)*4+2] = blue(map_colors[x+(y*map_size_z+z)*map_size_x]); - break; - } - } - pthread_rwlock_unlock(&chunk_map_locks[x+z*map_size_x]); - } + pthread_mutex_lock(&chunk_minimap_lock); + for(int x=worker->chunk_x;xchunk_x+CHUNK_SIZE;x++) { + for(int z=worker->chunk_y;zchunk_y+CHUNK_SIZE;z++) { + if((x%64)>0 && (z%64)>0) { + pthread_rwlock_rdlock(&chunk_map_locks[x+z*map_size_x]); + uint32_t color = map_colors[x+(map_heights[x+z*map_size_x]*map_size_z+z)*map_size_x]; + map_minimap[(x+z*map_size_x)*4+0] = red(color); + map_minimap[(x+z*map_size_x)*4+1] = green(color); + map_minimap[(x+z*map_size_x)*4+2] = blue(color); + pthread_rwlock_unlock(&chunk_map_locks[x+z*map_size_x]); } } - pthread_mutex_unlock(&chunk_minimap_lock); - - if(settings.greedy_meshing) - chunk_generate_greedy(worker); - else - chunk_generate_naive(worker); - - pthread_mutex_lock(&worker->state_lock); - worker->state = CHUNK_WORKERSTATE_FINISHED; - pthread_mutex_unlock(&worker->state_lock); } + pthread_mutex_unlock(&chunk_minimap_lock); - usleep(10); + if(settings.greedy_meshing) + chunk_generate_greedy(worker); + else + chunk_generate_naive(worker); + + pthread_mutex_lock(&worker->state_lock); + worker->state = CHUNK_WORKERSTATE_FINISHED; + pthread_mutex_unlock(&worker->state_lock); } return NULL; } @@ -1054,7 +1047,7 @@ void chunk_update_all() { glBindTexture(GL_TEXTURE_2D,0); } if(chunk_workers[j].state==CHUNK_WORKERSTATE_IDLE && chunk_geometry_changed_lenght>0) { - float closest_dist = 1e10; + float closest_dist = FLT_MAX; int closest_index = 0; for(int k=0;k. + BetterSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + BetterSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with BetterSpades. If not, see . */ #include "common.h" @@ -22,139 +22,145 @@ struct Grenade grenades[GRENADES_MAX]; struct Grenade* grenade_add() { - for(int k=0;k=map_size_x) - x -= map_size_x; - if(y>=map_size_z) - y -= map_size_z; - - int sz; - - if (z < 0) - return 0; - sz = (int)z; - if(sz == 63) - sz=62; - else if (sz >= map_size_y-1) - return 1; - else if (sz < 0) - return 0; - return !map_isair((int)x,63-sz,(int)y); + if(x<0) + x += map_size_x; + if(y<0) + y += map_size_z; + if(x>=map_size_x) + x -= map_size_x; + if(y>=map_size_z) + y -= map_size_z; + + int sz; + + if (z < 0) + return 0; + sz = (int)z; + if(sz == 63) + sz=62; + else if (sz >= map_size_y-1) + return 1; + else if (sz < 0) + return 0; + return !map_isair((int)x,63-sz,(int)y); } int grenade_move(struct Grenade* g, float dt) { - float tmp; - tmp = g->pos.z; - g->pos.z = 63.0F-g->pos.y; - g->pos.y = tmp; - tmp = g->velocity.z; - g->velocity.z = -g->velocity.y; - g->velocity.y = tmp; - - struct Position fpos = g->pos; //old position - - //do velocity & gravity (friction is negligible) - float f = dt*32.0F; - g->velocity.z += dt; - g->pos.x += g->velocity.x*f; - g->pos.y += g->velocity.y*f; - g->pos.z += g->velocity.z*f; - //do rotation - //FIX ME: Loses orientation after 45 degree bounce off wall - // if(g->v.x > 0.1f || g->v.x < -0.1f || g->v.y > 0.1f || g->v.y < -0.1f) - // { - // f *= -0.5; - // } - //make it bounce (accurate) - int ret = 0; - - int lpx = floor(g->pos.x); - int lpy = floor(g->pos.y); - int lpz = floor(g->pos.z); - - if(grenade_clipworld(lpx,lpy,lpz)) { //hit a wall - - ret = 1; - if(fabs(g->velocity.x) > 0.1F || - fabs(g->velocity.y) > 0.1F || - fabs(g->velocity.z) > 0.1F) - ret = 2; // play sound - - int lp2x = floor(fpos.x); - int lp2y = floor(fpos.y); - int lp2z = floor(fpos.z); - if (lpz != lp2z && ((lpx == lp2x && lpy == lp2y) || !grenade_clipworld(lpx,lpy,lp2z))) - g->velocity.z *= -1; - else if(lpx != lp2x && ((lpy == lp2y && lpz == lp2z) || !grenade_clipworld(lp2x,lpy,lpz))) - g->velocity.x *= -1; - else if(lpy != lp2y && ((lpx == lp2x && lpz == lp2z) || !grenade_clipworld(lpx,lp2y,lpz))) - g->velocity.y *= -1; - g->pos = fpos; //set back to old position - g->velocity.x *= 0.36F; - g->velocity.y *= 0.36F; - g->velocity.z *= 0.36F; - } - - tmp = g->pos.y; - g->pos.y = 63.0F-g->pos.z; - g->pos.z = tmp; - tmp = g->velocity.y; - g->velocity.y = -g->velocity.z; - g->velocity.z = tmp; - - return ret; + float tmp; + tmp = g->pos.z; + g->pos.z = 63.0F-g->pos.y; + g->pos.y = tmp; + tmp = g->velocity.z; + g->velocity.z = -g->velocity.y; + g->velocity.y = tmp; + + struct Position fpos = g->pos; //old position + + //do velocity & gravity (friction is negligible) + float f = dt*32.0F; + g->velocity.z += dt; + g->pos.x += g->velocity.x*f; + g->pos.y += g->velocity.y*f; + g->pos.z += g->velocity.z*f; + //do rotation + //FIX ME: Loses orientation after 45 degree bounce off wall + // if(g->v.x > 0.1f || g->v.x < -0.1f || g->v.y > 0.1f || g->v.y < -0.1f) + // { + // f *= -0.5; + // } + //make it bounce (accurate) + int ret = 0; + + int lpx = floor(g->pos.x); + int lpy = floor(g->pos.y); + int lpz = floor(g->pos.z); + + if(grenade_clipworld(lpx,lpy,lpz)) { //hit a wall + + ret = 1; + if(fabs(g->velocity.x) > 0.1F || + fabs(g->velocity.y) > 0.1F || + fabs(g->velocity.z) > 0.1F) + ret = 2; // play sound + + int lp2x = floor(fpos.x); + int lp2y = floor(fpos.y); + int lp2z = floor(fpos.z); + if (lpz != lp2z && ((lpx == lp2x && lpy == lp2y) || !grenade_clipworld(lpx,lpy,lp2z))) + g->velocity.z *= -1; + else if(lpx != lp2x && ((lpy == lp2y && lpz == lp2z) || !grenade_clipworld(lp2x,lpy,lpz))) + g->velocity.x *= -1; + else if(lpy != lp2y && ((lpx == lp2x && lpz == lp2z) || !grenade_clipworld(lpx,lp2y,lpz))) + g->velocity.y *= -1; + g->pos = fpos; //set back to old position + g->velocity.x *= 0.36F; + g->velocity.y *= 0.36F; + g->velocity.z *= 0.36F; + } + + tmp = g->pos.y; + g->pos.y = 63.0F-g->pos.z; + g->pos.z = tmp; + tmp = g->velocity.y; + g->velocity.y = -g->velocity.z; + g->velocity.z = tmp; + + return ret; } int grenade_inwater(struct Grenade* g) { - return g->pos.y<1.0F; + return g->pos.y<1.0F; +} + +void grenade_render() { + for(int k=0;k0.05F || fabs(grenades[k].velocity.y)>0.05F || fabs(grenades[k].velocity.z)>0.05F) + matrix_rotate(-window_time()*720.0F,-grenades[k].velocity.z,0.0F,grenades[k].velocity.x); + matrix_upload(); + kv6_render(&model_grenade,TEAM_1); + matrix_pop(); + } + } } void grenade_update(float dt) { - for(int k=0;kgrenades[k].fuse_length) { - sound_createEx(NULL,SOUND_WORLD, - grenade_inwater(&grenades[k])?&sound_explode_water:&sound_explode, - grenades[k].pos.x,grenades[k].pos.y,grenades[k].pos.z, - grenades[k].velocity.x,grenades[k].velocity.y,grenades[k].velocity.z - ); - particle_create(grenade_inwater(&grenades[k])?map_get(grenades[k].pos.x,0,grenades[k].pos.z):0x505050, - grenades[k].pos.x,grenades[k].pos.y+1.5F,grenades[k].pos.z, - 20.0F,1.5F,64,0.1F,0.5F - ); - grenades[k].active = 0; - } else { - if(grenade_move(&grenades[k],dt)==2) { - sound_createEx(NULL,SOUND_WORLD, - &sound_grenade_bounce, - grenades[k].pos.x,grenades[k].pos.y,grenades[k].pos.z, - grenades[k].velocity.x,grenades[k].velocity.y,grenades[k].velocity.z - ); - } - //TODO: position grenade on ground properly - matrix_push(); - matrix_translate(grenades[k].pos.x,grenades[k].pos.y+(model_grenade.zpiv+model_grenade.zsiz*2)*model_grenade.scale,grenades[k].pos.z); - if(fabs(grenades[k].velocity.x)>0.05F || fabs(grenades[k].velocity.y)>0.05F || fabs(grenades[k].velocity.z)>0.05F) { - matrix_rotate(-window_time()*720.0F,-grenades[k].velocity.z,0.0F,grenades[k].velocity.x); - } - matrix_upload(); - kv6_render(&model_grenade,TEAM_1); - matrix_pop(); - } - } - } + for(int k=0;kgrenades[k].fuse_length) { + sound_createEx(NULL,SOUND_WORLD, + grenade_inwater(&grenades[k])?&sound_explode_water:&sound_explode, + grenades[k].pos.x,grenades[k].pos.y,grenades[k].pos.z, + grenades[k].velocity.x,grenades[k].velocity.y,grenades[k].velocity.z + ); + particle_create(grenade_inwater(&grenades[k])?map_get(grenades[k].pos.x,0,grenades[k].pos.z):0x505050, + grenades[k].pos.x,grenades[k].pos.y+1.5F,grenades[k].pos.z, + 20.0F,1.5F,64,0.1F,0.5F + ); + grenades[k].active = 0; + } else { + if(grenade_move(&grenades[k],dt)==2) { + sound_createEx(NULL,SOUND_WORLD, + &sound_grenade_bounce, + grenades[k].pos.x,grenades[k].pos.y,grenades[k].pos.z, + grenades[k].velocity.x,grenades[k].velocity.y,grenades[k].velocity.z + ); + } + } + } + } } diff --git a/src/grenade.h b/src/grenade.h index e2a2bc0..210ce23 100644 --- a/src/grenade.h +++ b/src/grenade.h @@ -31,4 +31,5 @@ struct Grenade { struct Grenade* grenade_add(void); void grenade_update(float dt); +void grenade_render(void); int grenade_inwater(struct Grenade* g); diff --git a/src/main.c b/src/main.c index a78c98e..ba3fd10 100644 --- a/src/main.c +++ b/src/main.c @@ -100,7 +100,7 @@ void drawScene() { matrix_upload(); particle_render(); tracer_render(); - + grenade_render(); map_damaged_voxels_render(); matrix_upload(); @@ -172,8 +172,7 @@ void drawScene() { } } -float last_cy; -void display(float dt) { +void display() { if(network_map_transfer) { glClearColor(0.0F,0.0F,0.0F,1.0F); } else { @@ -188,18 +187,6 @@ void display(float dt) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - player_move(&players[local_player_id],dt,local_player_id); - last_cy = players[local_player_id].physics.eye.y-players[local_player_id].physics.velocity.y*0.4F; - - //following if-statement disables smooth crouching on local player - if(camera_mode==CAMERAMODE_FPS && chat_input_mode==CHAT_NO_INPUT) { - if(!players[local_player_id].input.keys.crouch && window_key_down(WINDOW_KEY_CROUCH) && !players[local_player_id].physics.airborne) { - players[local_player_id].pos.y -= 0.9F; - players[local_player_id].physics.eye.y -= 0.9F; - last_cy -= 0.9F; - } - } - if(settings.opengl14) { matrix_select(matrix_projection); matrix_identity(); @@ -208,7 +195,7 @@ void display(float dt) { matrix_select(matrix_view); matrix_identity(); - camera_apply(dt); + camera_apply(); matrix_select(matrix_model); matrix_identity(); @@ -224,7 +211,7 @@ void display(float dt) { matrix_load(matrix_view); matrix_vector(map_sun); matrix_pop(); - float map_sun_len = sqrt(map_sun[0]*map_sun[0]+map_sun[1]*map_sun[1]+map_sun[2]*map_sun[2]); + float map_sun_len = len3D(map_sun[0],map_sun[1],map_sun[2]); map_sun[0] /= map_sun_len; map_sun[1] /= map_sun_len; map_sun[2] /= map_sun_len; @@ -237,16 +224,12 @@ void display(float dt) { glx_enable_sphericalfog(); drawScene(); - grenade_update(dt); - tracer_update(dt); - int render_fpv = (camera_mode==CAMERAMODE_FPS) || ((camera_mode==CAMERAMODE_BODYVIEW || camera_mode==CAMERAMODE_SPECTATOR) && cameracontroller_bodyview_mode); int is_local = (camera_mode==CAMERAMODE_FPS) || (cameracontroller_bodyview_player==local_player_id); int local_id = (camera_mode==CAMERAMODE_FPS)?local_player_id:cameracontroller_bodyview_player; - if(players[local_player_id].items_show && window_time()-players[local_player_id].items_show_start>=0.5F) { + if(players[local_player_id].items_show && window_time()-players[local_player_id].items_show_start>=0.5F) players[local_player_id].items_show = 0; - } if(camera_mode==CAMERAMODE_FPS) { weapon_update(); @@ -320,9 +303,8 @@ void display(float dt) { int tmp = cubes[amount-1].y; cubes[amount-1].y = 63-cubes[amount-1].z; cubes[amount-1].z = tmp; - if(amount<=(is_local?local_player_blocks:50)) { + if(amount<=(is_local?local_player_blocks:50)) glColor3f(1.0F,1.0F,1.0F); - } short vertices[72] = { cubes[amount-1].x,cubes[amount-1].y,cubes[amount-1].z, @@ -364,9 +346,8 @@ void display(float dt) { if(window_time()-players[local_player_id].item_disabled<0.3F) { players[local_player_id].item_showup = window_time(); - if(players[local_player_id].input.buttons.lmb) { + if(players[local_player_id].input.buttons.lmb) players[local_player_id].input.buttons.lmb_start = window_time(); - } players[local_player_id].input.buttons.rmb = 0; } else { if(hud_active->render_localplayer) { @@ -399,15 +380,14 @@ void display(float dt) { matrix_upload_p(); matrix_upload(); - player_update(dt); + player_render_all(); matrix_upload(); - map_collapsing_render(dt); + map_collapsing_render(); matrix_upload(); - if(!map_isair(camera_x,camera_y,camera_z)) { + if(!map_isair(camera_x,camera_y,camera_z)) glClear(GL_COLOR_BUFFER_BIT); - } glx_disable_sphericalfog(); if(settings.smooth_fog) @@ -435,9 +415,8 @@ void display(float dt) { if(hud_active->render_2D) hud_active->render_2D(scalex,scalef); - if(settings.multisamples>0) { + if(settings.multisamples>0) glEnable(GL_MULTISAMPLE); - } } void init() { @@ -459,6 +438,9 @@ void init() { CHECK_ALLOCATION_ERROR(map_colors) memset(map_colors,(unsigned int)0xFFFFFFFF,map_size_x*map_size_y*map_size_z); + map_heights = malloc(map_size_x*map_size_z*sizeof(uint8_t)); + CHECK_ALLOCATION_ERROR(map_heights) + map_minimap = malloc(map_size_x*map_size_z*sizeof(unsigned char)*4); CHECK_ALLOCATION_ERROR(map_minimap) //set minimap borders (white on 64x64 chunks, black map border) @@ -540,9 +522,8 @@ void keys(struct window_instance* window, int key, int scancode, int action, int glReadPixels(0,0,settings.window_width,settings.window_height,GL_RGBA,GL_UNSIGNED_BYTE,pic_data); for(int y=0;y=PHYSICS_STEP_TIME) { + physics_time_fixed -= PHYSICS_STEP_TIME; + player_update(PHYSICS_STEP_TIME,1); //just physics tick + grenade_update(PHYSICS_STEP_TIME); + } + + //these run at min. ~60fps but as fast as possible + while(physics_time_fast>0) { + double step = min(dt,PHYSICS_STEP_TIME); + physics_time_fast -= step; + player_update(step,0); //smooth orientation update + camera_update(step); + tracer_update(step); + particle_update(step); + map_collapsing_update(step); + } + + display(); - particle_update(dt); sound_update(); network_update(); - window_update(); if(settings.vsync>1 && (window_time()-last_frame_start)<(1.0F/settings.vsync)) { diff --git a/src/map.c b/src/map.c index 4ad719d..2a1b934 100644 --- a/src/map.c +++ b/src/map.c @@ -20,6 +20,7 @@ #include "common.h" unsigned int* map_colors; +uint8_t* map_heights; int map_size_x = 512; int map_size_y = 64; int map_size_z = 512; @@ -171,190 +172,116 @@ void map_damaged_voxels_render() { } struct voxel { - int x,y,z; - char processed; + short x,y,z; }; -static char stack_contains(struct voxel* stack2, int len, int x, int y, int z) { - for(int k=0;k=1 && !map_isair(x,y-1,z) && !ht_contains(&closedlist,&key)) { + if(y<=2) { //reached layer at water level = finished! + minheap_destroy(&openlist); + ht_destroy(&closedlist); return; } - stack[stack_depth].processed = 0; - stack[stack_depth].x = x; - stack[stack_depth].y = y-1; - stack[stack_depth++].z = z; - if(stack_depth==stack_size) { - stack_size += 4096; - stack = realloc(stack,stack_size*sizeof(struct voxel)); - CHECK_ALLOCATION_ERROR(stack) - } - } - if(map_get(x,y+1,z)!=0xFFFFFFFF && !stack_contains(stack,stack_depth,x,y+1,z)) { - stack[stack_depth].processed = 0; - stack[stack_depth].x = x; - stack[stack_depth].y = y+1; - stack[stack_depth++].z = z; - if(stack_depth==stack_size) { - stack_size += 4096; - stack = realloc(stack,stack_size*sizeof(struct voxel)); - CHECK_ALLOCATION_ERROR(stack) - } - } - if(map_get(x+1,y,z)!=0xFFFFFFFF && !stack_contains(stack,stack_depth,x+1,y,z)) { - stack[stack_depth].processed = 0; - stack[stack_depth].x = x+1; - stack[stack_depth].y = y; - stack[stack_depth++].z = z; - if(stack_depth==stack_size) { - stack_size += 4096; - stack = realloc(stack,stack_size*sizeof(struct voxel)); - CHECK_ALLOCATION_ERROR(stack) - } - } - if(map_get(x-1,y,z)!=0xFFFFFFFF && !stack_contains(stack,stack_depth,x-1,y,z)) { - stack[stack_depth].processed = 0; - stack[stack_depth].x = x-1; - stack[stack_depth].y = y; - stack[stack_depth++].z = z; - if(stack_depth==stack_size) { - stack_size += 4096; - stack = realloc(stack,stack_size*sizeof(struct voxel)); - CHECK_ALLOCATION_ERROR(stack) - } - } - if(map_get(x,y,z+1)!=0xFFFFFFFF && !stack_contains(stack,stack_depth,x,y,z+1)) { - stack[stack_depth].processed = 0; - stack[stack_depth].x = x; - stack[stack_depth].y = y; - stack[stack_depth++].z = z+1; - if(stack_depth==stack_size) { - stack_size += 4096; - stack = realloc(stack,stack_size*sizeof(struct voxel)); - CHECK_ALLOCATION_ERROR(stack) - } - } - if(map_get(x,y,z-1)!=0xFFFFFFFF && !stack_contains(stack,stack_depth,x,y,z-1)) { - stack[stack_depth].processed = 0; - stack[stack_depth].x = x; - stack[stack_depth].y = y; - stack[stack_depth++].z = z-1; - if(stack_depth==stack_size) { - stack_size += 4096; - stack = realloc(stack,stack_size*sizeof(struct voxel)); - CHECK_ALLOCATION_ERROR(stack) - } + minheap_put(&openlist,&(struct minheap_block){.pos=key}); } + key = pos_key(x,y+1,z); + if(y=1 && !map_isair(x-1,y,z) && !ht_contains(&closedlist,&key)) + minheap_put(&openlist,&(struct minheap_block){.pos=key}); + + key = pos_key(x,y,z+1); + if(z=1 && !map_isair(x,y,z-1) && !ht_contains(&closedlist,&key)) + minheap_put(&openlist,&(struct minheap_block){.pos=key}); } - for(int k=0;k<32;k++) { - if(!map_collapsing_structures[k].used) { - float px = 0.0F,py = 0.0F,pz = 0.0F; - map_collapsing_structures[k].voxels_color = malloc(stack_depth*sizeof(unsigned int)); - CHECK_ALLOCATION_ERROR(map_collapsing_structures[k].voxels_color) - for(int i=0;ikey); + map_set(pos_keyx(key),pos_keyy(key),pos_keyz(key),0xFFFFFFFF); + px += pos_keyx(key); + py += pos_keyy(key); + pz += pos_keyz(key); - sound_create(NULL,SOUND_WORLD,&sound_debris,px,py,pz); + node = node->next; + } + } + px = (px/(float)closedlist.size)+0.5F; + py = (py/(float)closedlist.size)+0.5F; + pz = (pz/(float)closedlist.size)+0.5F; + sound_create(NULL,SOUND_WORLD,&sound_debris,px,py,pz); + + for(int k=0;k<32;k++) { + if(!map_collapsing_structures[k].used) { map_collapsing_structures[k].used = 1; - map_collapsing_structures[k].voxels = stack; - stack = NULL; + map_collapsing_structures[k].voxels = closedlist; map_collapsing_structures[k].v = (struct Velocity) {0,0,0}; map_collapsing_structures[k].o = (struct Orientation) {0,0,0}; map_collapsing_structures[k].p = (struct Position) {px,py,pz}; map_collapsing_structures[k].p2 = (struct Position) {px,py,pz}; map_collapsing_structures[k].rotation = rand()&3; - map_collapsing_structures[k].voxel_count = stack_depth; + map_collapsing_structures[k].voxel_count = closedlist.size; map_collapsing_structures[k].has_displaylist = 0; return; } } + + //there was no free slot! + ht_destroy(&closedlist); } int map_collapsing_cmp(const void* a, const void *b) { @@ -368,34 +295,15 @@ int map_collapsing_cmp(const void* a, const void *b) { -distance3D(A->p.x,A->p.y,A->p.z,camera_x,camera_y,camera_z); } -void map_collapsing_render(float dt) { +void map_collapsing_render() { qsort(map_collapsing_structures,32,sizeof(struct map_collapsing),map_collapsing_cmp); glEnable(GL_BLEND); for(int k=0;k<32;k++) { if(map_collapsing_structures[k].used) { - map_collapsing_structures[k].v.y -= dt; - char hit_floor = 0; - if(map_get(map_collapsing_structures[k].p.x+map_collapsing_structures[k].v.x*dt*32.0F, - map_collapsing_structures[k].p.y+map_collapsing_structures[k].v.y*dt*32.0F, - map_collapsing_structures[k].p.z+map_collapsing_structures[k].v.z*dt*32.0F)==0xFFFFFFFF) { - map_collapsing_structures[k].p.x += map_collapsing_structures[k].v.x*dt*32.0F; - map_collapsing_structures[k].p.y += map_collapsing_structures[k].v.y*dt*32.0F; - map_collapsing_structures[k].p.z += map_collapsing_structures[k].v.z*dt*32.0F; - } else { - map_collapsing_structures[k].v.x *= 0.7F; - map_collapsing_structures[k].v.y *= -0.7F; - map_collapsing_structures[k].v.z *= 0.7F; - map_collapsing_structures[k].rotation++; - map_collapsing_structures[k].rotation &= 3; - sound_create(NULL,SOUND_WORLD,&sound_bounce,map_collapsing_structures[k].p.x,map_collapsing_structures[k].p.y,map_collapsing_structures[k].p.z); - hit_floor = 1; - } matrix_push(); matrix_identity(); matrix_translate(map_collapsing_structures[k].p.x,map_collapsing_structures[k].p.y,map_collapsing_structures[k].p.z); - map_collapsing_structures[k].o.x += ((map_collapsing_structures[k].rotation&1)?1.0F:-1.0F)*dt*75.0F; - map_collapsing_structures[k].o.y += ((map_collapsing_structures[k].rotation&2)?1.0F:-1.0F)*dt*75.0F; matrix_rotate(map_collapsing_structures[k].o.x,1.0F,0.0F,0.0F); matrix_rotate(map_collapsing_structures[k].o.y,0.0F,1.0F,0.0F); matrix_upload(); @@ -418,139 +326,153 @@ void map_collapsing_render(float dt) { int vertex_index = 0; int color_index = 0; - for(int i=0;ikey); + uint32_t color = *(uint32_t*)(node->value); + + int x2 = pos_keyx(key); + int y2 = pos_keyy(key); + int z2 = pos_keyz(key); + + float x = x2-map_collapsing_structures[k].p2.x; + float y = y2-map_collapsing_structures[k].p2.y; + float z = z2-map_collapsing_structures[k].p2.z; + + key = pos_key(x2,y2-1,z2); + if(!ht_contains(&map_collapsing_structures[k].voxels,&key)) { + #ifdef OPENGL_ES + for(int l=0;l<6;l++) { + #else + for(int l=0;l<4;l++) { + #endif + push_char4(colors,&color_index, + red(color)*0.5F, + green(color)*0.5F, + blue(color)*0.5F,0xCC); + } + push_float3(vertices,&vertex_index,x,y,z); + push_float3(vertices,&vertex_index,x+1,y,z); + push_float3(vertices,&vertex_index,x+1,y,z+1); + #ifdef OPENGL_ES + push_float3(vertices,&vertex_index,x,y,z); + push_float3(vertices,&vertex_index,x+1,y,z+1); + #endif + push_float3(vertices,&vertex_index,x,y,z+1); } - push_float3(vertices,&vertex_index,x,y,z); - push_float3(vertices,&vertex_index,x+1,y,z); - push_float3(vertices,&vertex_index,x+1,y,z+1); - #ifdef OPENGL_ES - push_float3(vertices,&vertex_index,x,y,z); - push_float3(vertices,&vertex_index,x+1,y,z+1); - #endif - push_float3(vertices,&vertex_index,x,y,z+1); - } - if(!stack_contains(map_collapsing_structures[k].voxels,map_collapsing_structures[k].voxel_count,x2,y2+1,z2)) { - #ifdef OPENGL_ES - for(int l=0;l<6;l++) { - #else - for(int l=0;l<4;l++) { - #endif - push_char4(colors,&color_index, - red(map_collapsing_structures[k].voxels_color[i]), - green(map_collapsing_structures[k].voxels_color[i]), - blue(map_collapsing_structures[k].voxels_color[i]),0xCC); + key = pos_key(x2,y2+1,z2); + if(!ht_contains(&map_collapsing_structures[k].voxels,&key)) { + #ifdef OPENGL_ES + for(int l=0;l<6;l++) { + #else + for(int l=0;l<4;l++) { + #endif + push_char4(colors,&color_index, + red(color), + green(color), + blue(color),0xCC); + } + push_float3(vertices,&vertex_index,x,y+1,z); + push_float3(vertices,&vertex_index,x,y+1,z+1); + push_float3(vertices,&vertex_index,x+1,y+1,z+1); + #ifdef OPENGL_ES + push_float3(vertices,&vertex_index,x,y+1,z); + push_float3(vertices,&vertex_index,x+1,y+1,z+1); + #endif + push_float3(vertices,&vertex_index,x+1,y+1,z); } - push_float3(vertices,&vertex_index,x,y+1,z); - push_float3(vertices,&vertex_index,x,y+1,z+1); - push_float3(vertices,&vertex_index,x+1,y+1,z+1); - #ifdef OPENGL_ES - push_float3(vertices,&vertex_index,x,y+1,z); - push_float3(vertices,&vertex_index,x+1,y+1,z+1); - #endif - push_float3(vertices,&vertex_index,x+1,y+1,z); - } - if(!stack_contains(map_collapsing_structures[k].voxels,map_collapsing_structures[k].voxel_count,x2,y2,z2-1)) { - #ifdef OPENGL_ES - for(int l=0;l<6;l++) { - #else - for(int l=0;l<4;l++) { - #endif - push_char4(colors,&color_index, - red(map_collapsing_structures[k].voxels_color[i])*0.7F, - green(map_collapsing_structures[k].voxels_color[i])*0.7F, - blue(map_collapsing_structures[k].voxels_color[i])*0.7F,0xCC); + key = pos_key(x2,y2,z2-1); + if(!ht_contains(&map_collapsing_structures[k].voxels,&key)) { + #ifdef OPENGL_ES + for(int l=0;l<6;l++) { + #else + for(int l=0;l<4;l++) { + #endif + push_char4(colors,&color_index, + red(color)*0.7F, + green(color)*0.7F, + blue(color)*0.7F,0xCC); + } + push_float3(vertices,&vertex_index,x,y,z); + push_float3(vertices,&vertex_index,x,y+1,z); + push_float3(vertices,&vertex_index,x+1,y+1,z); + #ifdef OPENGL_ES + push_float3(vertices,&vertex_index,x,y,z); + push_float3(vertices,&vertex_index,x+1,y+1,z); + #endif + push_float3(vertices,&vertex_index,x+1,y,z); } - push_float3(vertices,&vertex_index,x,y,z); - push_float3(vertices,&vertex_index,x,y+1,z); - push_float3(vertices,&vertex_index,x+1,y+1,z); - #ifdef OPENGL_ES - push_float3(vertices,&vertex_index,x,y,z); - push_float3(vertices,&vertex_index,x+1,y+1,z); - #endif - push_float3(vertices,&vertex_index,x+1,y,z); - } - if(!stack_contains(map_collapsing_structures[k].voxels,map_collapsing_structures[k].voxel_count,x2,y2,z2+1)) { - #ifdef OPENGL_ES - for(int l=0;l<6;l++) { - #else - for(int l=0;l<4;l++) { - #endif - push_char4(colors,&color_index, - red(map_collapsing_structures[k].voxels_color[i])*0.6F, - green(map_collapsing_structures[k].voxels_color[i])*0.6F, - blue(map_collapsing_structures[k].voxels_color[i])*0.6F,0xCC); + key = pos_key(x2,y2,z2+1); + if(!ht_contains(&map_collapsing_structures[k].voxels,&key)) { + #ifdef OPENGL_ES + for(int l=0;l<6;l++) { + #else + for(int l=0;l<4;l++) { + #endif + push_char4(colors,&color_index, + red(color)*0.6F, + green(color)*0.6F, + blue(color)*0.6F,0xCC); + } + push_float3(vertices,&vertex_index,x,y,z+1); + push_float3(vertices,&vertex_index,x+1,y,z+1); + push_float3(vertices,&vertex_index,x+1,y+1,z+1); + #ifdef OPENGL_ES + push_float3(vertices,&vertex_index,x,y,z+1); + push_float3(vertices,&vertex_index,x+1,y+1,z+1); + #endif + push_float3(vertices,&vertex_index,x,y+1,z+1); } - push_float3(vertices,&vertex_index,x,y,z+1); - push_float3(vertices,&vertex_index,x+1,y,z+1); - push_float3(vertices,&vertex_index,x+1,y+1,z+1); - #ifdef OPENGL_ES - push_float3(vertices,&vertex_index,x,y,z+1); - push_float3(vertices,&vertex_index,x+1,y+1,z+1); - #endif - push_float3(vertices,&vertex_index,x,y+1,z+1); - } - if(!stack_contains(map_collapsing_structures[k].voxels,map_collapsing_structures[k].voxel_count,x2-1,y2,z2)) { - #ifdef OPENGL_ES - for(int l=0;l<6;l++) { - #else - for(int l=0;l<4;l++) { - #endif - push_char4(colors,&color_index, - red(map_collapsing_structures[k].voxels_color[i])*0.9F, - green(map_collapsing_structures[k].voxels_color[i])*0.9F, - blue(map_collapsing_structures[k].voxels_color[i])*0.9F,0xCC); + key = pos_key(x2-1,y2,z2); + if(!ht_contains(&map_collapsing_structures[k].voxels,&key)) { + #ifdef OPENGL_ES + for(int l=0;l<6;l++) { + #else + for(int l=0;l<4;l++) { + #endif + push_char4(colors,&color_index, + red(color)*0.9F, + green(color)*0.9F, + blue(color)*0.9F,0xCC); + } + push_float3(vertices,&vertex_index,x,y,z); + push_float3(vertices,&vertex_index,x,y,z+1); + push_float3(vertices,&vertex_index,x,y+1,z+1); + #ifdef OPENGL_ES + push_float3(vertices,&vertex_index,x,y,z); + push_float3(vertices,&vertex_index,x,y+1,z+1); + #endif + push_float3(vertices,&vertex_index,x,y+1,z); } - push_float3(vertices,&vertex_index,x,y,z); - push_float3(vertices,&vertex_index,x,y,z+1); - push_float3(vertices,&vertex_index,x,y+1,z+1); - #ifdef OPENGL_ES - push_float3(vertices,&vertex_index,x,y,z); - push_float3(vertices,&vertex_index,x,y+1,z+1); - #endif - push_float3(vertices,&vertex_index,x,y+1,z); - } - if(!stack_contains(map_collapsing_structures[k].voxels,map_collapsing_structures[k].voxel_count,x2+1,y2,z2)) { - #ifdef OPENGL_ES - for(int l=0;l<6;l++) { - #else - for(int l=0;l<4;l++) { - #endif - push_char4(colors,&color_index, - red(map_collapsing_structures[k].voxels_color[i])*0.8F, - green(map_collapsing_structures[k].voxels_color[i])*0.8F, - blue(map_collapsing_structures[k].voxels_color[i])*0.8F,0xCC); + key = pos_key(x2+1,y2,z2); + if(!ht_contains(&map_collapsing_structures[k].voxels,&key)) { + #ifdef OPENGL_ES + for(int l=0;l<6;l++) { + #else + for(int l=0;l<4;l++) { + #endif + push_char4(colors,&color_index, + red(color)*0.8F, + green(color)*0.8F, + blue(color)*0.8F,0xCC); + } + push_float3(vertices,&vertex_index,x+1,y,z); + push_float3(vertices,&vertex_index,x+1,y+1,z); + push_float3(vertices,&vertex_index,x+1,y+1,z+1); + #ifdef OPENGL_ES + push_float3(vertices,&vertex_index,x+1,y,z); + push_float3(vertices,&vertex_index,x+1,y+1,z+1); + #endif + push_float3(vertices,&vertex_index,x+1,y,z+1); } - push_float3(vertices,&vertex_index,x+1,y,z); - push_float3(vertices,&vertex_index,x+1,y+1,z); - push_float3(vertices,&vertex_index,x+1,y+1,z+1); - #ifdef OPENGL_ES - push_float3(vertices,&vertex_index,x+1,y,z); - push_float3(vertices,&vertex_index,x+1,y+1,z+1); - #endif - push_float3(vertices,&vertex_index,x+1,y,z+1); + + node = node->next; } } glx_displaylist_update(&map_collapsing_structures[k].displaylist,vertex_index/3,GLX_DISPLAYLIST_ENHANCED,colors,vertices,NULL); @@ -562,40 +484,103 @@ void map_collapsing_render(float dt) { glColorMask(1,1,1,1); glx_displaylist_draw(&map_collapsing_structures[k].displaylist,GLX_DISPLAYLIST_ENHANCED); - if(absf(map_collapsing_structures[k].v.y)<0.1F && hit_floor) { - for(int i=0;ikey); + + float v[4] = {pos_keyx(key)+map_collapsing_structures[k].v.x*dt*32.0F-map_collapsing_structures[k].p2.x+0.5F, + pos_keyy(key)+map_collapsing_structures[k].v.y*dt*32.0F-map_collapsing_structures[k].p2.y+0.5F, + pos_keyz(key)+map_collapsing_structures[k].v.z*dt*32.0F-map_collapsing_structures[k].p2.z+0.5F, 1.0F}; matrix_vector(v); - particle_create(map_collapsing_structures[k].voxels_color[i],v[0],v[1],v[2],2.5F,1.0F,2,0.25F,0.4F); + if(!map_isair(v[0],v[1],v[2])) { + collision = 1; + break; + } + + node = node->next; } - free(map_collapsing_structures[k].voxels); - free(map_collapsing_structures[k].voxels_color); + } + + if(!collision) { + map_collapsing_structures[k].p.x += map_collapsing_structures[k].v.x*dt*32.0F; + map_collapsing_structures[k].p.y += map_collapsing_structures[k].v.y*dt*32.0F; + map_collapsing_structures[k].p.z += map_collapsing_structures[k].v.z*dt*32.0F; + } else { + map_collapsing_structures[k].v.x *= 0.85F; + map_collapsing_structures[k].v.y *= -0.85F; + map_collapsing_structures[k].v.z *= 0.85F; + map_collapsing_structures[k].rotation++; + map_collapsing_structures[k].rotation &= 3; + sound_create(NULL,SOUND_WORLD,&sound_bounce,map_collapsing_structures[k].p.x,map_collapsing_structures[k].p.y,map_collapsing_structures[k].p.z); - glx_displaylist_destroy(&map_collapsing_structures[k].displaylist); - map_collapsing_structures[k].used = 0; + if(absf(map_collapsing_structures[k].v.y)<0.1F) { + for(int chain=0;chainkey); + uint32_t color = *(uint32_t*)(node->value); + + float v[4] = {pos_keyx(key)-map_collapsing_structures[k].p2.x+0.5F, + pos_keyy(key)-map_collapsing_structures[k].p2.y+0.5F, + pos_keyz(key)-map_collapsing_structures[k].p2.z+0.5F, + 1.0F}; + matrix_vector(v); + particle_create(color,v[0],v[1],v[2],2.5F,1.0F,2,0.25F,0.4F); + + node = node->next; + } + } + + matrix_pop(); + + ht_destroy(&map_collapsing_structures[k].voxels); + glx_displaylist_destroy(&map_collapsing_structures[k].displaylist); + + map_collapsing_structures[k].used = 0; + continue; + } } matrix_pop(); + + map_collapsing_structures[k].o.x += ((map_collapsing_structures[k].rotation&1)?1.0F:-1.0F)*dt*75.0F; + map_collapsing_structures[k].o.y += ((map_collapsing_structures[k].rotation&2)?1.0F:-1.0F)*dt*75.0F; } } - glDisable(GL_BLEND); } void map_update_physics(int x, int y, int z) { - if(map_get(x+1,y,z)!=0xFFFFFFFF) + if(!map_isair(x+1,y,z)) map_update_physics_sub(x+1,y,z); - if(map_get(x-1,y,z)!=0xFFFFFFFF) + if(!map_isair(x-1,y,z)) map_update_physics_sub(x-1,y,z); - if(map_get(x,y,z+1)!=0xFFFFFFFF) + if(!map_isair(x,y,z+1)) map_update_physics_sub(x,y,z+1); - if(map_get(x,y,z-1)!=0xFFFFFFFF) + if(!map_isair(x,y,z-1)) map_update_physics_sub(x,y,z-1); - if(map_get(x,y-1,z)!=0xFFFFFFFF) + if(!map_isair(x,y-1,z)) map_update_physics_sub(x,y-1,z); - if(map_get(x,y+1,z)!=0xFFFFFFFF) + if(!map_isair(x,y+1,z)) map_update_physics_sub(x,y+1,z); } @@ -605,7 +590,7 @@ float map_sunblock(int x, int y, int z) { int i = 127; while(dec && y<64) { - if((map_get(x,++y,--z)&0xFFFFFFFF)!=0xFFFFFFFF) + if(!map_isair(x,++y,--z)) i -= dec; dec -= 2; } @@ -626,6 +611,15 @@ unsigned int map_get(int x, int y, int z) { return ret; } +int map_height(int x, int z) { + if(x<0 || z<0 || x>=map_size_x || z>=map_size_z) + return 0; + pthread_rwlock_rdlock(&chunk_map_locks[x+z*map_size_x]); + int ret = map_heights[x+z*map_size_x]; + pthread_rwlock_unlock(&chunk_map_locks[x+z*map_size_x]); + return ret; +} + unsigned int map_get_unblocked(int x, int y, int z) { if(x<0 || y<0 || z<0 || x>=map_size_x || y>=map_size_y || z>=map_size_z) return 0xFFFFFFFF; @@ -637,14 +631,22 @@ void map_set(int x, int y, int z, unsigned int color) { if(x<0 || y<0 || z<0 || x>=map_size_x || y>=map_size_y || z>=map_size_z) return; - /*int err = pthread_rwlock_trywrlock(&chunk_map_lock); - if(err!=0) { - log_debug("pthread: %i",err); - return; - }*/ - pthread_rwlock_wrlock(&chunk_map_locks[x+z*map_size_x]); + int offset = x+z*map_size_x; + pthread_rwlock_wrlock(&chunk_map_locks[offset]); map_colors[x+(y*map_size_z+z)*map_size_x] = color; - pthread_rwlock_unlock(&chunk_map_locks[x+z*map_size_x]); + if(color!=0xFFFFFFFF) { + map_heights[offset] = max(map_heights[offset],y); + } else { + if(map_heights[offset]==y) { + for(int k=y-1;k>=0;k--) { + if(map_get_unblocked(x,k,z)!=0xFFFFFFFF || k==0) { + map_heights[offset] = k; + break; + } + } + } + } + pthread_rwlock_unlock(&chunk_map_locks[offset]); chunk_block_update(x,y,z); @@ -816,6 +818,7 @@ void map_vxl_load(unsigned char* v, unsigned int* map) { map_vxl_setgeom(x,y,z,map_dirt_color(x,map_size_y-1-z,y),map); } z = 0; + map_heights[x+y*map_size_x] = map_size_y-1-v[1]; while(1) { unsigned int *color; int i; diff --git a/src/map.h b/src/map.h index cb1ed5d..465f157 100644 --- a/src/map.h +++ b/src/map.h @@ -18,6 +18,7 @@ */ extern unsigned int* map_colors; +extern uint8_t* map_heights; extern int map_size_x; extern int map_size_y; extern int map_size_z; @@ -46,6 +47,7 @@ float map_sunblock(int x, int y, int z); int map_isair(int x, int y, int z); unsigned int map_get(int x, int y, int z); unsigned int map_get_unblocked(int x, int y, int z); +int map_height(int x, int z); void map_set(int x, int y, int z, unsigned int color); int map_cube_line(int x1, int y1, int z1, int x2, int y2, int z2, struct Point* cube_array); void map_vxl_setgeom(int x, int y, int z, unsigned int t, unsigned int* map); @@ -53,4 +55,5 @@ void map_vxl_setcolor(int x, int y, int z, unsigned int t, unsigned int* map); int map_dirt_color(int x, int y, int z); int map_placedblock_color(int color); void map_vxl_load(unsigned char* v, unsigned int* map); -void map_collapsing_render(float dt); +void map_collapsing_render(void); +void map_collapsing_update(float dt); diff --git a/src/minheap.c b/src/minheap.c new file mode 100644 index 0000000..a5fbbce --- /dev/null +++ b/src/minheap.c @@ -0,0 +1,155 @@ +/* + Copyright (c) 2017-2019 ByteBit + + This file is part of BetterSpades. + + BetterSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + BetterSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with BetterSpades. If not, see . +*/ + +#include +#include +#include +#include +#include + +#include "hashtable.h" +#include "minheap.h" + +static void nodes_swap(struct minheap* h, int a, int b) { + struct minheap_block tmp; + tmp = h->nodes[a]; + h->nodes[a] = h->nodes[b]; + h->nodes[b] = tmp; + + ht_insert(&h->contains,&h->nodes[a].pos,&a); + ht_insert(&h->contains,&h->nodes[b].pos,&b); +} + +void minheap_create(struct minheap* h) { + h->index = 0; + h->length = 256; + h->nodes = malloc(sizeof(struct minheap_block)*h->length); + ht_setup(&h->contains,sizeof(uint32_t),sizeof(uint32_t),256); +} + +void minheap_clear(struct minheap* h) { + ht_clear(&h->contains); + free(h->nodes); + h->index = 0; + h->length = 256; + h->nodes = malloc(sizeof(struct minheap_block)*h->length); +} + +void minheap_destroy(struct minheap* h) { + free(h->nodes); + ht_destroy(&h->contains); +} + +int minheap_isempty(struct minheap* h) { + return h->index<=0; +} + +struct minheap_block* minheap_get(struct minheap* h, short x, short y, short z) { + if(x<0 || y<0 || z<0) + return NULL; + + uint32_t key = pos_key(x,y,z); + uint32_t* res = ht_lookup(&h->contains,&key); + return res?(h->nodes+*res):NULL; +} + +struct minheap_block minheap_extract(struct minheap* h) { + struct minheap_block min = h->nodes[0]; + + ht_erase(&h->contains,&min.pos); + + h->nodes[0] = h->nodes[--h->index]; + + //now heapify at root node + int k = 0; + while(1) { + int smallest = k; + if(k*2+1index && pos_keyy(h->nodes[k*2+1].pos)nodes[smallest].pos)) //does left child exist and is less than parent? + smallest = k*2+1; + if(k*2+2index && pos_keyy(h->nodes[k*2+2].pos)nodes[smallest].pos)) //does right child exist and is less than parent? + smallest = k*2+2; + if(smallest==k) //parent is smallest, finished! + break; + nodes_swap(h,k,smallest); + k = smallest; + } + + return min; +} + +static void minheap_increase(struct minheap* h, struct minheap_block* b, int value) { + b->pos = pos_key(pos_keyx(b->pos),value,pos_keyy(b->pos)); + + int k = b-h->nodes; + while(1) { + int smallest = k; + if(k*2+1index && pos_keyy(h->nodes[k*2+1].pos)nodes[smallest].pos)) //does left child exist and is less than parent? + smallest = k*2+1; + if(k*2+2index && pos_keyy(h->nodes[k*2+2].pos)nodes[smallest].pos)) //does right child exist and is less than parent? + smallest = k*2+2; + if(smallest==k) //parent is smallest, finished! + break; + nodes_swap(h,k,smallest); + k = smallest; + } +} + +static void minheap_decrease(struct minheap* h, struct minheap_block* b, int value) { + b->pos = pos_key(pos_keyx(b->pos),value,pos_keyy(b->pos)); + + int k = b-h->nodes; + while(k>0) { + if(pos_keyy(h->nodes[k].pos)nodes[(k-1)/2].pos)) { //is child less than parent? + nodes_swap(h,k,(k-1)/2); + k = (k-1)/2; //continue at parent + } else { + break; + } + } +} + +void minheap_set(struct minheap* h, struct minheap_block* b, int value) { + if(value>pos_keyy(b->pos)) + minheap_increase(h,b,value); + else + minheap_decrease(h,b,value); +} + +struct minheap_block* minheap_put(struct minheap* h, struct minheap_block* b) { + if(h->index>=h->length) { //grow buffer + h->length *= 2; + h->nodes = realloc(h->nodes,sizeof(struct minheap_block)*h->length); + } + + h->nodes[h->index++] = *b; //place new node at end of heap + + int k = h->index-1; + while(k>0) { + if(pos_keyy(h->nodes[k].pos)nodes[(k-1)/2].pos)) { //is child less than parent? + nodes_swap(h,k,(k-1)/2); + k = (k-1)/2; //continue at parent + } else { + break; + } + } + + ht_insert(&h->contains,&b->pos,&k); + + return h->nodes+k; +} diff --git a/src/minheap.h b/src/minheap.h new file mode 100644 index 0000000..2cf6930 --- /dev/null +++ b/src/minheap.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2017-2019 ByteBit + + This file is part of BetterSpades. + + BetterSpades is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + BetterSpades is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with BetterSpades. If not, see . +*/ + +#ifndef MINHEAP_H +#define MINHEAP_H + +#include "hashtable.h" + +#define pos_key(x,y,z) (((z)<<20) | ((x)<<8) | (y)) +#define pos_keyx(key) (((key)>>8)&0xFFF) +#define pos_keyy(key) ((key)&0xFF) +#define pos_keyz(key) (((key)>>20)&0xFFF) + +struct path_vec { + short x,y,z; +}; + +struct minheap_block { + uint32_t pos; +}; + +struct minheap { + int index; + int length; + HashTable contains; + struct minheap_block* nodes; +}; + +void minheap_create(struct minheap* h); +void minheap_clear(struct minheap* h); +void minheap_destroy(struct minheap* h); +int minheap_isempty(struct minheap* h); +struct minheap_block* minheap_get(struct minheap* h, short x, short y, short z); +struct minheap_block minheap_extract(struct minheap* h); +void minheap_set(struct minheap* h, struct minheap_block* b, int value); +struct minheap_block* minheap_put(struct minheap* h, struct minheap_block* b); + +#endif diff --git a/src/player.c b/src/player.c index 08baf54..3f3721f 100644 --- a/src/player.c +++ b/src/player.c @@ -231,7 +231,24 @@ float player_section_height(int section) { } } -void player_update(float dt) { +void player_update(float dt, int locked) { + for(int k=0;kweapon_delay(players[k].weapon) && players[k].ammo>0) { diff --git a/src/player.h b/src/player.h index 2151648..66686f1 100644 --- a/src/player.h +++ b/src/player.h @@ -140,7 +140,8 @@ void player_init(void); float player_height(struct Player* p); float player_height2(struct Player* p); void player_reposition(struct Player* p); -void player_update(float dt); +void player_update(float dt, int locked); +void player_render_all(void); int player_render(struct Player* p, int id, Ray* ray, char render); void player_reset(struct Player* p); int player_move(struct Player* p, float fsynctics, int id);