We’ve decided to change our game idea to a competitive
first person shooter. We wanted our game to have a fast paced, fun and
competitive feel, and by incorporating elements like wall running can add
variation to gameplay similar to Mirror's Edge. Another great aspect was the game's camera
movement, it gives the player a very intense feeling when maneuvering through
obstacles and looks more realistic. These are the elements I want to focus on
the most while my other team member wants to focus on the shooting.
So for this week I started to implement basic
movement, physics and model loading into the engine. We want swift movement
along with a wall running mechanic to have fast gameplay. I started off with a
basic camera class that moves in a FPS fashion by calculating the forward,
right and up vectors and moving the entity along those directions.
I have also created an object class to easily create
new obj entities in the scene in only 3 lines of code.
OBJModel player;
player.Load("Crate.obj", "crateTexture.png");
player.Init(entityMgr, cpoolMgr,
shaderPathVS, shaderPathFS);
For collision, a map class was made to extract the
vertex information of a map obj file to be used with collision checking.
bool Map::Load(core_str::String model, core_str::String texture)
{
this->Model.Load(model, texture);
gfx_med::ObjLoader::vert_cont_type model_verts = Model.Get_Vertices();
for (gfx_med::ObjLoader::vert_cont_type::iterator itr = model_verts.begin(), itrEnd = model_verts.end();
itr != itrEnd; ++itr)
{
math::types::Vector_TI<float, 3> vert =
itr->GetPosition();
mesh.push_back(math_t::Vec3f(vert[0], vert[1], vert[2]));
//also
needs verts to be transformed by the modelmatrix (NEEDS UPDATING)
}
return true;
}
Once that’s
done I’ve implemented mesh collision between each individual triangle of the
mesh and a sliding sphere.
bool camera::Collide(core_conts::Array<math_t::Vec3f> coll_verts, input_hid::keyboard_b_vptr& keyboard)
{
bool result = false;
int verts_size = coll_verts.size();
if (verts_size > 0)
{
for (int i = 0; i < verts_size; i += 3)
{
if (Collision_Tools::GetInstance()->IntersectsTriangle(this->Coll_Sphere, coll_verts[i], coll_verts[i + 1], coll_verts[i + 2]))
{
math_t::Vec3f &vertex1 = coll_verts[i];
math_t::Vec3f &vertex2 = coll_verts[i + 1];
math_t::Vec3f &vertex3 = coll_verts[i + 2];
math_t::Vec3f closestpt = Collision_Tools::GetInstance()->NearestPointOnTriangle(this->Coll_Sphere.center,
vertex1, vertex2, vertex3);
math_t::Vec3f closestpt_subtr_coll_sphere
= (closestpt - this->Coll_Sphere.center);
closestpt_subtr_coll_sphere.Normalize();
math_t::Vec3f PlaneNormal =
closestpt_subtr_coll_sphere;
float penetrationdepth = abs(this->Coll_Sphere.radius -
closestpt.Distance(this->Coll_Sphere.center));
float velocityAlongNormal =
velocity.Dot(PlaneNormal);
float dotangle =
abs(PlaneNormal.Dot(math_t::Vec3f(PlaneNormal[0], 0, PlaneNormal[2])));
if (dotangle < 0.6f)
{
this->on_ground = true;
PlaneNormal[0]
*= 0;
PlaneNormal[2]
*= 0;
}
if ((dotangle > 0.8f
&& dotangle < 1.2f) && !on_ground)
{
wall_normal =
PlaneNormal;
if (mode == 1)
{
previous_direction
= direction;
previous_direction[1]
= -0.08f;
}
if (keyboard->IsKeyDown(input_hid::KeyboardEvent::space) || wall_run_timer
> 0)
{
}
wall_run_timer
= 0.2f;
}
if (velocityAlongNormal >
-penetrationdepth)
{
this->velocity -= PlaneNormal
* (penetrationdepth + velocityAlongNormal);
//this->state.velocityAlongWall =
glm::normalize(this->velocity);
result = true;
}
}
}
}
return result;
}
This algorithm calculates the velocity of the player
against a wall.
For the
rest of the week, I made a prototype testing out the wall running mechanic. In
this example, I made a map where the player needs to wall run across to get to
the other side of the building.
This is
done by simply moving the player against the inverted normal of the wall and
moving the player in the forward velocity along the wall.