#include #include #include #include "ghost.h" float pi = glm::pi(); int counter = 0; float direction_persist_factor = 0.02; Ghost::Ghost(float xmin, float xmax, float zmin, float zmax) { ghost_id = counter; counter++; this->xmin = xmin; this->xmax = xmax; this->zmin = zmin; this->zmax = zmax; pos.x = rand_float(xmin, xmax); pos.y = 2.5; pos.z = rand_float(zmin, zmax); y_offset = rand_float(0.0, pi); yawr = rand_float(0.0, pi*2.0f); first_frame = false; direction_persist = 0.0f; } void Ghost::apply_movement(float curr_time, float timed) { // vertical movement pos.y = 2.5 + sin(curr_time + y_offset); moved.x = -sin(yawr) + cos(yawr); moved.z = cos(yawr) + sin(yawr); pos += moved * timed; bool reset_yaw = false; if (pos.x < xmin) { reset_yaw = true; pos.x = xmin; } else if (pos.x > xmax) { reset_yaw = true; pos.x = xmax; } if (pos.z < zmin) { reset_yaw = true; pos.z = zmin; } else if (pos.z > zmax) { reset_yaw = true; pos.z = zmax; } // TODO make this face origin if (reset_yaw) { yawr = rand_float(0.0, pi * 2.0); } else { yawr += rand_float(-0.05, 0.05); } } glm::mat4 Ghost::get_model(glm::vec3 &camera_pos) { // initialize to identity matrix glm::mat4 ghost_model = glm::mat4(1.0f); // apply location ghost_model = glm::translate(ghost_model, pos); // apply direction // the cross product helps us determine which direction it's going relative to player glm::vec3 ghost_to_player = pos - camera_pos; glm::vec3 crossed = glm::cross(ghost_to_player, moved); //float dist2 = ghost_to_player.x * ghost_to_player.x + ghost_to_player.z * ghost_to_player.z; float theta = atan2f(ghost_to_player.x, ghost_to_player.z); if (crossed.y < 0.0) { direction_persist = (1.0 - direction_persist_factor) * direction_persist - direction_persist_factor; } else { direction_persist = (1.0 - direction_persist_factor) * direction_persist + direction_persist_factor; } if (direction_persist < 0.0) { theta += pi; } ghost_model = glm::rotate(ghost_model, theta, glm::vec3(0.0f, 1.0f, 0.0f)); /* if (dist2 > 256) { yawr = theta; } if (ghost_id == 0) { printf("(%f, %f, %f)\n", pos.x, pos.y, pos.z); printf("%f %f %f %f\n", xmin, xmax, zmin, zmax); } */ return ghost_model; } float rand_float(float rmin, float rmax) { float rdiff = rmax - rmin; float res = (float)rand()/(float)RAND_MAX; return res * rdiff + rmin; } glm::vec3 Ghost::get_pos() const { return pos; } void Ghost::reverse_direction_from_position(glm::vec3 target_pos) { // Calculate direction from target_pos to ghost position glm::vec3 direction = pos - target_pos; // Set yawr to point directly away from target_pos yawr = atan2(direction.x, direction.z); } void Ghost::regenerate_position() { pos.x = rand_float(xmin, xmax); pos.z = rand_float(zmin, zmax); }