Blog

Furthering Puzzle Mechanics

This post will sum up my progress in the third and fourth week of this month.  Putting the push and pull blocks on backlog, I began to focus on a new task which involved picking up three batteries.  My approach to this was to start with one battery, which would have a temporary model, and when the player is on or within a small distance of the battery and used the interaction key, the battery would disappear and log “Battery has been picked up.”

Though the interaction code was fairly cut and dry being very similar to the other puzzle mechanics that have been implemented, an error encountered while developing this mechanic which had to do with the battery not disappearing when being interacted with.  Not having seen anything immediately relevant, I took a break from this and when I re-approached my code I instantly discovered a typo so insignificant it bypassed me several times.  From here on out I spent my time cleaning up the code to make it the result more polished and overall increasing the readability of my code.  This alone took an estimate total of 19 hours to complete leading to my final and current task of the month, the revisiting of the blocks.

With currently 23 hours logged into this task trying to figure out problems with the collider, I have a goal in mindset to wrap this up by today and talking to my peers about the issues they have also encountered and managed to solve.

 

 

 

First Encounter with Lua

Hello, my name is Asia Bradley and I am one of the gameplay developers working on Monochromatic.  This post will be dedicated to my first two weeks on the project.  I was invited to this team prior to reaching my final project month, so when I heard that this project would be based in Lua, I took my time and studied up with various sources to learn how to write in it.  I commonly work in C# or C++, so when it came to having to learn a new language I tried to approach it slowly to fully dissolve the information.

Finally, I reached final project month and dedicated my first two days to reviewing the engine for our game that was currently in development by our fellow teammates, known as the “ghoti” engine (pronounced as “fish”).  It took quite a bit of time, especially as a newbie in this language and adapting to an entity-component system.

Following the next few days in that same week, my sole goal was to work on a mechanic to be utilized in a puzzle involving the rotation of mirrors.  Without a mirror model or the rest of the mechanics, it was a little difficult to work on but I used a temporary model and just focused on getting a smooth rotation on the model each time a key bind or button was pushed with a controller.   Despite a lot of difficulty involving quaternions and spending about 15 hours just to touch up on using and understanding them, finally I was able to get my model to rotate.  The issue from then was that the kazmath function kmQuaternionSlerp was not properly slerping during it’s rotation.  Instead of a smooth motion from it’s initial angle to the next 90 degree angle, the model would just do one quick motion.

In the second week, I was tasked with continuing to solve the slerp problem.  I tried many solutions to resolve this issue and finally with the help of another teammate we were able to get the proper smooth rotation.  From here I worked on another task that was to get the player to interact with a mural and in the future it was to trigger a cutscene.  For this, I set a basic cube and just triggered a bool to print if it true when the player was within a distance and looking at the cube and used the interaction key.  After this was completed, I started the work on another puzzle mechanic.  This new puzzle mechanic was to be able to push and pull on a block that you would be able to put into placement to then be able to use a bridge.  This used a good amount of the same code from the interaction with the mural, however I ran into issues with the collision for our engine.  The collision turned out to be a problem engine side as the other gameplay developers also could not get their collision to properly function.  I decided not to waste any further time and moved my focus onto the start of a new task that would be carried into the third week.

The Engine, Player Movement, and Camera

Joining Monochromatic, the first task I had was to become familiar with the engine that we were using. The most difficult part of this was to become used to the way we had to create stuff in the game. Our engine, “ghoti”, uses an entity-component system instead of OOP like I’ve always known. Because of this, I made sure to take my time combing through as much of the engine as I could to get a better grasp on it.

Once getting more familiar with the engine, my next task was to begin reworking the player that Logan had left behind. The first step for that was the movement of the player. The initial thing I needed to change regarding the movement was how the player changed directions. The player would snap to 45 degree angles, which would not be ideal for anyone playing our game with a controller. Once I had the player no longer snapping to angles, I discovered a bug with the quaternion slerp function in our math library, kazmath. Essentially, the way quaternions rotate with kazmath is to use a positive and negative axis for x, y, and z. Each positive and negative axis would go from 0 to 180 degrees, creating the full 360 together. The issue that this has is when a quaternion “crosses” an axis, changing from positive to negative or vice versa. When this occurs, the angle of rotation converts to an angle above 180, instead of being a negative angle. Because of this, the player would immediately do a 360 in the opposite way it was going, which didn’t look right at all.

To solve this problem, I had to create an algorithm that would check the angles each time the model tried to rotate, comparing the current angle to the desired angle and the associated axis of each angle. If the desired direction was on a new axis, I replaced the current rotation with that of one on the desired axis with a negative angle. This fixed the unnecessary 360 the player would do when crossing the axis, since it never does when actually calling the slerp function.

That wraps up my first week on the project. During the second week, my tasks were to rework the combo system that Logan had started, and to work on the camera’s ability to follow the player and orient itself in the way they were moving. The combo system was not much of an issue, and I had that completed and working fairly quickly. The real problem of the week was the camera.

The camera was something I definitely underestimated, looking back on it now. Things had started off well, with me modifying the camera we already had to start following the player. Pretty quickly I had it lerping behind the player and rotating to face the same direction they were. The issue with what I had was when the player would do sharp turns, particularly when they would do a 180 without moving much. Doing a 180 without moving caused the camera to fly straight through the head of the player, cutting into the model and showing the inside of it.

I tried various methods that I could think of to fix this issue, and eventually found one that limited the yaw and pitch on the camera so that the clipping was mostly avoided, but this didn’t change the fact of how the camera moved. The camera still moved in a straight line behind the player, when our ideal movement would be for it to move around the player in a circle.

Physics in the Engine

Working in the engine has been a bit of a trial and error process. There are a lot of things I’m still learning about the engine, and as a result, I was unable to do anything in the engine for a week due to my lack of knowledge. C isn’t difficult though. Once Josh was able to fill me in on the things that I didn’t know, like marking a transform as dirty to make sure it is updated, we were able to get a good bit of work done.

Once basic AABB collision was added, I thought adding gravity would be easy to do. It wasn’t. Gravity completely screwed over basic AABB collision, because the dynamic object would slowly build up speed and phase through the static object. To get gravity finished we had to implement force-based collisions first. That was a bit tricky, but since Josh and I were pair programming for this, we were able to come to a conclusion together.

For today, Josh and I will continue to work on force-based collisions, and next week we will pair program spacial partitioning.

Optimization

Most of my time spent during the last week of month 2 was optimizing and tweaking all of the systems I had created up until then.  I quickly realized the task was going to take longer than expected due to a decent portion of the all the code being structured mainly for testing, and the other portion could have been optimized better.  For instance, the player’s movement and weapon systems were functional, but were optimized before, but had a decent portion of code used only for testing features.  Optimizing these systems was my biggest concern this past week.

I decided to tackle player movement first, and broke the code down into different sections based on the different movement mechanics: normal movement, sprint, jump, and dodge. Basic movement and sprinting were fine, however, dodging and jumping lead to more variables and logic needing to be checked all at once which slowed down the code.  To fix this, I decided to create a new component and system for advanced movement that would contain the information for jumping, dodging, and any other advanced mechanic that would/could be implemented.  In addition, other entities besides the player will need to be able to jump and dodge, and creating a system for all advanced mechanics will eliminate having to write the same code multiple times.  Once, the advanced movement component and system were implemented and functioning the player movement system was faster, not performing useless checks every frame.

Moving on, during the previous weeks I spent a decent amount of time on the player weapon system and was able to optimize little by little, but I was never fully satisfied with it. I decided to fix this problem by closely inspecting my code line by line and taking note of where a lot of duplicate/similar code was, and replace them with functions that could handle each case. Once the finished, the code was much more readable and easier to follow.  With this done, I looked over my logic again to make sure it was correct, then looked over how and when I manipulated my timers.  What I ended up doing, was setting the base time for an attack every time there is an input for an attack, which gave a more accurate time for tracking combos, and after every attack is performed I reset the attack timer to zero.  After making these small changes, the code was optimized much more than before, and made it easier to implement a heavy attack and combo.

– Logan Acree