float get_tile_height(const float x, const float y) { float z; int pos_x, pos_y, i, j, tmp, count; if (!get_tile_valid(x, y)) { return 0.0f; } pos_x = x; pos_y = y; tmp = height_map[pos_y * tile_map_size_x * 6 + pos_x]; if (tmp != 0) { return tmp * 0.2f - 2.2f; } tmp = 0; count = 0; for (j = pos_y - 1; j <= (pos_y + 1); ++j) { for (i = pos_x - 1; i <= (pos_x + 1); ++i) { if (get_tile_walkable(i, j)) { tmp += height_map[j * tile_map_size_x * 6 + i]; count++; } } } z = tmp; if (count > 1) { z /= count; } return z * 0.2f - 2.2f; }
void update_camera() { const float c_delta = 0.1f; static int last_update = 0; int time_diff = cur_time - last_update; static float old_camera_x = 0; static float old_camera_y = 0; static float old_camera_z = 0; float adjust; actor *me = get_our_actor(); old_rx=rx; old_rz=rz; new_zoom_level=old_zoom_level=zoom_level; //printf("kludge: %f, hold: %f, rx: %f, rz %f, zoom: %f\n",camera_kludge, hold_camera,rx,rz,zoom_level); if (fol_cam && !fol_cam_behind) rz = hold_camera; if (me) camera_kludge = -me->z_rot; /* This is a BIG hack to not polluate the code but if this feature * is accepted and the flag is removed, all the code that * follows will have to be changed in order to get rid of * camera_rotation_duration and camera_tilt_duration. */ camera_rotation_duration = camera_rotation_speed != 0.0 ? time_diff : 0.0; camera_tilt_duration = camera_tilt_speed != 0.0 ? time_diff : 0.0; if(camera_rotation_duration > 0){ if (time_diff <= camera_rotation_duration) rz+=camera_rotation_speed*time_diff; else rz+=camera_rotation_speed*camera_rotation_duration; camera_rotation_duration-=time_diff; adjust_view++; } if(camera_x_duration > 0){ if(camera_x_speed>1E-4 || camera_x_speed<-1E-4){ if (time_diff <= camera_x_duration) camera_x-=camera_x_speed*time_diff; else camera_x-=camera_x_speed*camera_x_duration; if(fabs(camera_x-old_camera_x) >= c_delta){ adjust_view++; } } camera_x_duration-=time_diff; } if(camera_y_duration > 0){ if(camera_y_speed>1E-4 || camera_y_speed<-1E-4){ if (time_diff <= camera_y_duration) camera_y-=camera_y_speed*time_diff; else camera_y-=camera_y_speed*camera_y_duration; if(fabs(camera_y-old_camera_y) >= c_delta){ adjust_view++; } } camera_y_duration-=time_diff; } if(camera_z_duration > 0){ if(camera_z_speed>1E-4 || camera_z_speed<-1E-4){ if (time_diff <= camera_z_duration) camera_z-=camera_z_speed*time_diff; else camera_z-=camera_z_speed*camera_z_duration; if(fabs(camera_z-old_camera_z) >= c_delta){ adjust_view++; } } camera_z_duration-=time_diff; } if(camera_tilt_duration > 0) { if (time_diff <= camera_tilt_duration) rx+=camera_tilt_speed*time_diff; else rx+=camera_tilt_speed*camera_tilt_duration; camera_tilt_duration-=time_diff; adjust_view++; } if(camera_zoom_duration > 0) { if (time_diff <= camera_zoom_duration) new_zoom_level += camera_zoom_speed*(camera_zoom_dir==1?0.003f:-0.003f)*time_diff; else new_zoom_level += camera_zoom_speed*(camera_zoom_dir==1?0.003f:-0.003f)*camera_zoom_duration; camera_zoom_duration-=time_diff; adjust_view++; } else camera_zoom_speed = 1; if (camera_rotation_speed > 0.0) { camera_rotation_speed -= time_diff * camera_rotation_deceleration; if (camera_rotation_speed < 0.0) camera_rotation_speed = 0.0; } else if (camera_rotation_speed < 0.0) { camera_rotation_speed += time_diff * camera_rotation_deceleration; if (camera_rotation_speed > 0.0) camera_rotation_speed = 0.0; } if (camera_tilt_speed > 0.0) { camera_tilt_speed -= time_diff * camera_tilt_deceleration; if (camera_tilt_speed < 0.0) camera_tilt_speed = 0.0; } else if (camera_tilt_speed < 0.0) { camera_tilt_speed += time_diff * camera_tilt_deceleration; if (camera_tilt_speed > 0.0) camera_tilt_speed = 0.0; } clamp_camera(); if (ext_cam && !first_person && me && rx <= -min_tilt_angle && rx >= -max_tilt_angle) { float rot_x[9], rot_z[9], rot[9], dir[3]; float vect[3] = {0.0, 0.0, new_zoom_level*camera_distance}; int tx, ty; float tz; // we compute the camera position MAT3_ROT_X(rot_x, -rx*M_PI/180.0); MAT3_ROT_Z(rot_z, -rz*M_PI/180.0); MAT3_MULT(rot, rot_z, rot_x); MAT3_VECT3_MULT(dir, rot, vect); // we take the tile where the camera is tx = (int)((dir[0] - camera_x)*2); ty = (int)((dir[1] - camera_y)*2); if (get_tile_walkable(tx, ty)) { tz = get_tile_height(tx, ty); } else { // if the tile is outside the map, we take the height at the actor position tz = get_tile_height(me->x_tile_pos, me->y_tile_pos); } // here we use a shift of 0.2 to avoid to be too close to the ground if (tz + 0.2 > dir[2] - camera_z) { if (ext_cam_auto_zoom) // new behaviour { // if the camera is under the ground, we change the zoom level if (fabsf(dir[2]) > 1E-4) new_zoom_level *= (tz + camera_z + 0.2) / dir[2]; else new_zoom_level = 0.0; if (new_zoom_level < 1.0) { new_zoom_level = 1.0; camera_tilt_duration = camera_zoom_duration = 0; camera_tilt_speed = 0.0; if (fabsf(tz + camera_z + 0.2f) < fabsf(vect[2]) - 0.01) rx = -90.0 + 180.0 * asinf((tz + camera_z + 0.2) / vect[2]) / M_PI; } else if (new_zoom_level > old_zoom_level) { new_zoom_level = old_zoom_level; camera_tilt_duration = camera_zoom_duration = 0; camera_tilt_speed = 0.0; } } else // old freecam behaviour { new_zoom_level = old_zoom_level; camera_tilt_duration = camera_zoom_duration = 0; camera_tilt_speed = 0.0; if (fabsf(tz + camera_z + 0.2f) < fabsf(vect[2]) - 0.01) rx = -90.0 + 180.0 * asinf((tz + camera_z + 0.2) / vect[2]) / M_PI; } } } if(adjust_view){ set_all_intersect_update_needed(main_bbox_tree); old_camera_x= camera_x; old_camera_y= camera_y; old_camera_z= camera_z; } hold_camera = rz; if (fol_cam) { static int fol_cam_stop = 0; if ((SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2)) || camera_rotation_speed != 0) fol_cam_stop = 1; else if (me && me->moving && fol_cam_stop) fol_cam_stop = 0; if (last_kludge != camera_kludge && !fol_cam_stop) { set_all_intersect_update_needed(main_bbox_tree); adjust = (camera_kludge-last_kludge); //without this the camera will zip the wrong way when camera_kludge //flips from 180 <-> -180 if (adjust >= 180) adjust -= 360.0; else if (adjust <= -180) adjust += 360.0; if (fabs(adjust) < fol_strn) { last_kludge=camera_kludge; } else { last_kludge += fol_strn*( adjust*(fol_quad*fol_strn + fol_lin)+ fol_con*(adjust>0?1:-1))/ (fol_quad+fol_lin+fol_con+.000001f);//cheap no/0 } } if (fol_cam_behind) { if (!fol_cam_stop) rz = -last_kludge; else last_kludge = -rz; } else rz -= last_kludge; } //Make Character Turn with Camera if (have_mouse && !on_the_move (get_our_actor ())) { adjust = rz; //without this the character will turn the wrong way when camera_kludge //and character are in certain positions if (adjust >= 180) adjust -= 360.0; else if (adjust <= -180) adjust += 360.0; adjust+=camera_kludge; if (adjust >= 180) adjust -= 360.0; else if (adjust <= -180) adjust += 360.0; if (adjust > 35){ Uint8 str[2]; str[0] = TURN_LEFT; my_tcp_send (my_socket, str, 1); } else if (adjust < -35){ Uint8 str[2]; str[0] = TURN_RIGHT; my_tcp_send (my_socket, str, 1); } } adjust_view = 0; last_update = cur_time; }