Andy here. I’m the game design/programming end of Golden Ruby. We recently got a bug report from Erick Beard about an issue in Worm Run where the player could be killed by running really fast into a wall with lava on the other side. We fixed it in the most recent update and he was wondering exactly what we did to rectify the issue. So welcome to the first and possibly only issue of GOLDEN RUBY PROGRAMMER MAIL BAG.
(image captured by Eric Beard)
Eric got going good and fast in the temple area, hit that wall up there and was burned to a crisp. Not good.
Why It Happened
The issue lies with how Worm Run deals with collisions. I wrote the physics system myself, but it’s not at all unusual in how it handles things. So let’s brace ourselves for some Programmer Art and dive in.
In this image, the stick figure is Zeke, the plain rectangle is a wall, and the rectangle with the lines is lava. There is a reason we brought in Nick to do the art for this game.
Every frame, the player moves according to their velocity (1). After they move, the game checks to see if they are somewhere they shouldn’t be (such as inside a wall). In (2) up there, you can see that the player is in the wall. When this happens, the game pushes them back out until they are no longer touching the wall (3). This all happens before the player sees anything, so to them it will appear that Zeke hit the wall and stayed there, as physics would dictate.
This check is done by using several nodes that surround the player’s body (which can be seen in this screencap of Worm Run with some of my debug tools on). Worm Run uses 6 of these nodes, four to check walls and such, and an extra two to see when the player is adjacent to a wall. In the game, players can slide and hang onto walls, so it is important to know if they are “touching.” This can be tricky, because the way the game handles collisions is to push the player away from the wall until the four main nodes are no longer in the wall. So on a technical level, Zeke is never touching a wall, just incredibly close. That’s why the extra two nodes are needed. They’re just a bit further away, so when the four main nodes are pushed away from a wall, the extra node on that side will still be touching, and the game knows that the player is up against the wall.
So that’s how the collisions work, but why does the bug happen?
Well previously, checking for deadly things like lava and spikes occurred several times during this process. Usually it was fine because it is very difficult for the player to travel more than 1 block’s distance in a single frame, so if they hit lava they died. No problem (at least for the player; Zeke might have a problem with it). But if something happened like in panel 2 in the illustration, the game would register that one of their nodes was in lava, killing them before moving them back against the wall. Not good.
An obvious solution is to just not check those nodes for contact with deadly things until after the player has been moved, but this leads to its own issues. Remember that after the player has been moved back, they are not technically touching anything, even the floor. As far as the game is concerned, they are hovering a little less than a pixel above the ground.
When the check was made after moving the player, it always found that the player was NOT touching lava, even if they appeared to be standing right on top of it. Technically, the node was not in the lava block; it had just been moved out of it.
Having the player able to stand on lava wasn’t really working for us. While there are many potential solutions, I wound up modifying the function that checks to see if the player’s nodes are touching lava or spikes. I already had two nodes that still could be in lava on the left and right, so the current version uses those two to check if the player is touching lava after the game has moved them away from any solid blocks they may be touching. For the top and bottom, I could have included additional nodes, but that seemed like overkill when they were really only needed for a single check. Instead, when the game checks for lava, it adds or subtracts one pixel from their location so that the new position will be in lava that is directly above or below the player. And then it will kill them.
So that’s it! The newest version of the game includes these changes and a few others that folks have pointed out to us since we released. Thanks to people like Eric Bears and others who have written to us with issues and questions they have!
Maybe we’ll see you again with another edition of GOLDEN RUBY PROGRAMMER MAIL BAG.
I have to imagine that if you’ve been playing Worm Run in the last few weeks, you’ve encountered and been annoyed by our new Twitter feature for posting your score. The idea was that after a really good run you could brag about your score (and of course, help spread the word about our game) if you want to. Unfortunately, due to some bad code and insufficient testing, the twitter button easily gets activated anytime you tap continue after a mission.
This was not our intent at all, and I’m embarrassed that it took us this long to catch it. Games that constantly push you to tell your friends are annoying and do a great job of sucking all the fun out of the room. If you want to share your score, great! We want you to! But we did not intend to badger our players every time they complete a mission, and we’re sorry about that. I personally resent it when games do that, and we’re here to make great games, not trick you into opening up Twitter.
We are sending a new version to Apple right now and it should be live in a week or so.
So how did it happen?
Well, when we were putting the Twitter button in, we didn’t want to clutter up the end screen too much, so we placed it in the largely unused bottom right corner. Of course, we forgot that corner was unused because it is exactly where the continue button is after completing a mission or earning an unlock. Worse still, the code I wrote didn’t stop checking for button presses after the continue button was hit, meaning that it would register the tap the hit the continue button, go to the end screen, and immediately register it again on the twitter button.
So what happened here was bad code and not enough testing. It was not an attempt to bully our players into posting constantly about our game, but I imagine it was pretty annoying for those players, and we’re sorry about that.
What better way to apologize than with a present?
Apple has recently changed their policy on using UDIDs in games, which was how we checked if people were on the list to unlock the special Kickstarter costume, Ultra Zeke. Instead of creating a new system, we’d like to open it up to the public. So if you got hit by some overzealous Twitter action while playing, here’s the code to unlock the new duds: Just go to the credits screen of the game and double tap anywhere. You should hear a coin sound and Ultra Zeke will be waiting for you in the shop, already purchased and ready to go for a run.