One of the many reasons I decided to include a fishing mini-game, aside from it being required by law in any RPG-like adventure game, was to challenge myself on a few new scripting issues.
Both the casting off and the reeling in require the player to press A when a pointer moves over a specific area of a bar. I felt this was an interesting input to look into, as most of my games require very little real-time reflex input where timing is crucial. So far I’ve “gotten away” with smudging a lot of input issues, adding calculations and checks in between inputs, because I wasn’t making games that require nano-second input lag requirements.
The challenge was to tie a graphical bar with a hotzone, to the position of an animated arrow, tied to user input. First things first, I have to create a graphical bar with a dynamic (ie. random) hot zone the player has to land on. The bar itself is a simple but criminally disorganised material into which I feed a few variables.
Ok, look, wait… don’t judge me! Mostly I keep my BluePrints organised and readable, but sometimes you make something for single use and you just slap it together. It works, you don’t need to revisit it (fingers crossed) and life’s too short to make all your connections align neatly. If I ever need to fix this material because of issues, then I’ll spend some time making it super clean and readable. For now..it’s fine, okay?
So I set the length of the hotzone as a variable. This is because that makes it easier to tweak and play around with in the design and play testing phase. In the end I landed on the hotzone being 15% of the length of the bar, so 0.15 in the BluePrint above. Now I randomly set the start point of the hotzone some where between 0, the start of the bar, and (1 minus 0.15) the end of the bar, minus the length of the hotzone, as we don’t want it to run over the 100% length of the bar.
With these two variables (hotzone length and start of the hotzone) I create a dynamic material where I set a green zone, the length of 15% of the bar width, and draw a white line in the middle of it. The rest of the material is transparent.
Next I simply animate the arrows over the bar, from 0 to 1 seconds. This animation I play ping-pong style; ie. it plays from 0 to 1, then plays backward from 1 to 0 and the loops indefinitely.
What is very important at this stage is to make sure there is no ease in or out on the animation keyframes! I need to pick out at where the animation is when the player hits the A button and I do this by looking at the time. If the arrow starts moving slowly at first before coming to speed the position of it, visually, won’t correspond to its position on the time line.
Above you can see this in action. At 0.15 seconds into the animation i have moved the arrows 15% along the bar in the top screen capture. But in the bottom capture you can see at 0.15 seconds the arrows aren’t 15% along the bar yet because they slowly accelerate initially (and decelerate toward the end). This would not be good for what I need.
When the player presses A I pause the animation.
At this stage I check where the cursor is according to what time along the timeline the animation is. E.g. if the player stopped the cursor animation at 0.6 seconds, and the hotspot safezone runs from 0.6 to 0.75 (60% to 75% of the full width) the arrow will just be inside the hotzone, which counts as a successful cast!
On top of this I also check if they are within a margin of the center of the hotzone. That white like in the middle of the green zone is 0.075 away from the start of the hotzone. So I created a small margin either way and if the player stops the arrows at that point it will count as a “perfect” cast.
I repeat this system once the player hooks a fish, but repeat it a few times. With every successful stop the fish gets reeled closer to the left, while all the while swimming away to the right. If you miss the hotzone you lose time. Do this often enough and the fish will get away. Do it often enough in quick succession and you catch the fish.
As you can see it’s a fairly simple system that compares the animation phase, between 0 and 1, to a randomly generated hotspot between 0 and 1. It is not as limiting as you’d think. Using the playback speed option in BluePrints I can make the arrow animation move at whatever speed I see fit, without messing up my “ingenious” 0-1 seconds > 0-1 float comparison.
Currently the fishing mini-game is only required to be played a little. An object from it is required to access an area on the map otherwise inaccessible, and the puzzles therein are required to get enough XP to clear the puzzles towards the end of the story mode. Of course, you can play the mini-game for fun and earn a trophy by catching one of every fish. And even if you’re that way inclined you can “ace” the fishing mini-game by catching all fish at “perfect” level (meaning casting off perfectly and starting the reel in perfectly), although there are no extra in-game rewards for doing so.
In the end I’m pretty happy with how it all works out, especially considering the short, intense scheduling I allowed myself to achieve this in. I didn’t want this to become too big a task that would distract from developing the main game. As it stands it was a great little palette cleanser and allowed me to learn a few new techniques in UE4.