La Rana
Lead Programmer
About La Rana
La Rana is a single person adventure game where the player controls Soos, a frog temple servant, who is trying to purify a cursed temple.
Long ago the Temple of Rana brought rain and prosperity to the world. Now it stands neglected, its source of power stolen away. You awaken as the temple’s last guardian, a small frog spirit. The lost power of Rana lies before you at the temple’s base. Using the last drops of Rana’s power, you must explore the vast ruins while discovering its secret chambers and marveling at its faded glory. Recover the Temple of Rana’s lost power and restore rain to the world.
We worked on La Rana from June to December of 2018. Because of our condensed development schedule, we decided to focus on making a tight, highly focused game with only a few polished mechanics. We played to our strengths whenever possible. With so many visually focused designers we chose to emphasize the magical, whimsical quality of the game, using visual effects to bring those qualities to life.
My Role
On La Rana, I served as the lead programmer. As a lead, I worked closely with 2 other programmers and 4 other leads to plan each sprint, coordinate with other disciplines, and be an advocate for my team in stakeholder meetings. Additionally, as the technical lead, I was responsible for project structure, builds, and ports.
Specs
Role: | Lead Programmer |
Team size: | 14 |
Engine | Unreal Engine 4 |
Tools: | Blueprint, C++ |
Development Time: | 5 months
(3 hours/day) |
Download
Content
Lead Responsibilities
- Sprint Planning
- Deliverable Negotiation
- Cross-Discipline communication
- Documentation
- Conflict Resolution
Programmer Responsibilities
Project Builds
As the technical lead on the project, it was my job to make regular builds, especially towards the end of the project, and ensure that they were stable. This included monitoring game performance, approving any risky project pushes, and tracking bugs. Early in the project, I worked with other tech leads at the Guildhall to create scripts that would run each night on a designated build PC. As the project progressed, I worked with my producer to coordinate QA testing on both the nightly build and on midday builds created on my own computer. As we began making release candidates for shipping, I was responsible for ensuring that any development tools were turned off in the build, and creating both a standalone executable and a Steam build.
Along with our steam build, I also worked on ports of the game to the PlayStation 4 and Universal Windows Platform. In the end, we didn't have an avenue to publish to the PlayStation store or the Microsoft store, so we didn't dive into console-specific optimization. But the process of making builds for both PS4 and UWP was very valuable and I'm excited to take that knowledge forward to any future console ports.
Back To Top
User Interface
With my previous experience as a UI programmer in Unreal for Interstellar Racing League, I was happy to do the implementation of all UI in La Rana. I took the lessons I learned in IRL, and made much more coherent and polished systems for the menu and in-game HUD in La Rana.
Menus
For La Rana, I wanted a menu system that could change with the game, and that my teammates could quickly understand if they needed to step in and do some menu work in my stead. From the start, I outlined a system that made greater use of UMG's inheritance system - each menu shared a parent class, which I used in conjunction with a central MenuManager to control universal things like tracking widget states and the behavior of the back button.
This system made it easier to update functionality across all menus quickly - updating the hover texture on the central button widget would update all buttons in every menu seamlessly. Additionally, it was easy to work in parallel in this system. I could easily be editing the functionality of the main menu while our sound designer was tweaking functionality in the audio menu, with no merge conflicts.
HUD
Though La Rana's HUD is minimal, I wanted to make sure that the elements it did have were as organized as possible. To do this, I split up the HUD into component widgets, each with its own functionality, which were all owned by a single HUD widget. Using this method, I could move and update each indivual component of the HUD, without interfering with any other components. This allowed for parallel work when other developers needed access to HUD elements - for instance, I could work on the frog collectible widget while another developer was updating functionality in the water widget.
This also made it easy to add developer options to the UI. For most of the project, we worked with a frame-rate counter always visible on the HUD. It was easy to toggle this counter on/off with hotkeys when we started taking promotional screenshots, and when we got to release, we just had to delete the self-contained FPSwidget from the HUD widget, with no worrying about references.
Loading
We knew that we didn't want to break up player experience with any sort of level select or extended loading during gameplay. This meant that the entire game would be in one persistent level, with parts of that level loading in and out around the player as they progressed. This would also mean a much longer load time when the player started the game.
To avoid a long, static break going into the game, I implemented an animated loading screen to play while all of the initial loading was being handled. Immediately after entering the (empty) game level from the main menu, the loading screen is placed over the viewport and begins animating. Then, the rest of the game is loaded in asynchronously, so the animation runs as smoothly as possible. Once all of the necessary streaming levels are loaded, the loading screen is removed from the viewport, and the player is given control.
Conveyance VFX
During development, we established as a team that we wanted a ruleset for all interactable elements in the game, to give the player some intuition. We wanted to link elements that could be squirted with the water pools, so we decided to give all interactable elements the same firefly particle effect, and use a filling/draining effect similar to the water UI on a blue orb, which would be found on all puzzle elements. I have an interest in VFX, and enjoy working with Unreal Engine's material editor, so I was thrilled to have the opportunity to implement some of the visual effects our artists worked on in the game.
Chess Block Directions
For the chess block, we wanted fireflies to only appear on the sides the player could squirt to actually move the block. To do this, the chessblock raycasts in each direction, looking for rails/obstacles, and updates the directions it can move in. This triggers the particle effect on the opposite side of the block to activate accordingly. When a chess block moves, it sends out another 4 rays to update the directions it can move.
Water Bubble
For the water bubble effect, I created a variation of the water material used in the HUD, where the fill mask drives emissive and color rather than opacity. I then made a blueprint component, which manages the interpolation of the "water_level" parameter on this material when the puzzle element is activated and deactivated to create the filling/emptying effect. It was easy to attach this component to every relevant blueprint actor, and tweak any values for the speed of the interpolation according to the geometry of the puzzle element.
River Heart
In the finale sequence, the player must purify the poisoned River Heart by purifying 5 small orbs. To convey this, we needed to have the central orb become more blue with each small orb. The material takes a grayscale mask with a watery shape, and displays purple if the mask's value is greater than the current purfication level, and blue if the pixel's value is less than the current purification level. Each small orb activated raises the purification level of the River Heart, creating the effect of the River Heart filling up along the water channels defined in the material mask.
Back To Top
Retrospective: What I Learned
Developing La Rana was an incredible experience, and having the opportunity to be a lead on the project was eye opening. I'm very proud of what I did well on the project, and I'm very thankful for the lessons I learned in an environment where it was safe to fail. Here are a few of my major takeaways from the project.
Same Team
It's hard to imagine working on a game where everything goes exactly as planned, 100% of the time. When things go wrong, it's important to remember that above anything else, you're on the same team. Even in disagreements, you both want to make the best game you can, and THAT drive should be the thing fueling any arguments about the game.
On La Rana, I tried to keep this in mind when I had disagreements about the game, and when my teammates did. I found that it was helpful to support my producer as a mediator when conflicts started heating up. It's better to help everybody arrive at an ~okay~ decision that we all agree on rather than to have two opposing factions trying to build two different games in one executable. And when you have to disappoint somebody, it's important to make sure they understand your reasoning in an objective, considerate way.
Advocate for your teammates, but know when you have to say "no."
When I was chosen to be a lead, I knew it would be important to advocate for my programming team when talking to the other leads. In past projects, a common complaint was that developers would have suggestions or concerns, their leads would take those concerns into a meeting, and they would never hear about it again. To combat this, I tried to be a voice for my team above anything else, and always get their perspective on big decisions.
However, I learned that it's important not to take this too far. Sometimes, hard decisions have to be made, and you have to disappoint your team with a hard "no." I learned that it was important to acknowledge my teammates' perspectives and to let them know that I understood why they disagreed. There's nothing worse than feeling like your concerns are being ignored, so I did my best to make sure my teammates understood that this was never the case, and to keep any disappointing decisions from spilling over into personal conflicts.
Be positive! For real!
I always try to facilitate a positive work environment, so I wanted to make sure I was a positive influence on the team as much as I could. Even when things went wrong or teammates fell short of their goals, I tried to stay level-headed and optimistic, without softening my expectations for them. Criticisms are always vital to a team's growth, but finding ways to communicate criticisms in a way that's helpful instead of hurtful goes miles in keeping the team together. When I had to have hard conversations with teammates, I always tried to keep in mind that the point of the conversation was to have a positive effect on the team, so that I could prevent the conversation from turning personal or feeling like a blame-session.
Back To Top