I had planned from the beginning to add game pad support to ZGF. However, 8 months of pixel art, level building, and programming went by before I got around to it. So this past week I decided to integrate the game pad and start coding the inputs so you could fly and shoot using a controller. The first thing that happened was ...I broke my game.
Then I slowly molded the inputs into a shape roughly resembling something like inputs that you would expect from an actual playable video game. I'll go into a little bit of detail here:
First, some background INFO.
ZGF's default inputs use a keyboard and mouse. WASD controls the ships thrusters while the vessel and it's weapons platforms always orient toward the mouse. The mouse is displaying a custom reticle sprite. You move by firing the forward thrusters with W and you fly toward the reticle. Release W and you continue to drift on that vector as you would expect in a zero g, friction-less environment. You change course by placing the reticle where you want to go and use the appropriate thruster(s) to propel the ship into a new vector.
You aim weapons by placing the reticle on a target and shoot by clicking the left mouse button to fire the primary weapons. Clicking the right mouse button fires the secondary weapon which, by default, is a guided missile. I say "guided" because the missile object also orients toward the mouse reticle so you can lead the missile and change its path allowing you to shoot around space debris or adjust aim mid flight.
ZGF is top down shooter so you would expect it to behave like a twin stick shooter. But that's not actually the case. W,A,S,D controls forward, left, aft, and right thrusters respectively. When the front of the ship is oriented toward the top of the screen this feels natural and intuitive. When the ship is oriented toward the bottom on the screen the inputs are reversed from the action you see on the screen. Early on this was intentional, I was thinking about the WASD keys as being tied to the position of thrusters on the player's ship not as vectors the player intends to move.
I've stuck with this design decision thus far though it seems counter intuitive to the feedback I have received. But that's practically a subject for it's own blog post.
Now Back to Game Pad Inputs
Using an old Xbox 360 controller and a wireless adapter my first task was to figure out how to make the ship rotate and orient toward the direction of the right joy stick axis. This was not as easy you would think. At first I tried a script that would move the mouse cursor on the screen so I was essentially trying to replicate the mouse controls with the joy stick. Ultimately this failed because I could not get the movement of the reticle to feel fluid and precise. So I switched gears did some research and after reading a wonderful blog post from the YoYoGames Tech Blog. I wrote a script that captures the horizontal and vertical axis information from the joystick in a variable and then create a point direction that the ship and it's weapons platforms orient toward. This worked but with mixed results. the rotation is jerky, it is not fluid, and target acquisition was garbage. (This wrecked bullet orientation. You literally could not shoot in the direction of what you were shooting at, but I fixed it.)
I eventually created a hybrid solution. I created a reticle object that I tied to the position of the player's ship using lenghtdir() to place the reticle 300 pixels in front of the ship. However, when the right joy stick is engaged the H and V axis are captured and create a new point direction for the reticle relative to the ship. The reticle basically rotates in a circle around the craft with a radius of three hundred pixels. The ship's smooth rotation script kicks in and the vessel rotates smoothly toward the direction of the reticle. Target acquisition was immediately improved, the rotation of the vessel is smooth, but the reticle movement is still a little jerky. Overall I'm very pleased with the solution but I'll continue to work on it to get it feeling smooth and effortless
My second task was mapping face buttons and triggers to weapons and abilities. This was not difficult and was executed very well.
Next, I modified my existing menus so that they could be navigated and selected with game pad inputs. This was not difficult and was executed very well.
Finally I had to address the propulsion of the ship using the left joy stick. Like the right stick I first captured horizontal and vertical axis information in a variable and used that info in Game Maker's physics_apply_local_force(); function to propel the ship. After some tinkering and inverting the Y axis in code I was able to propel the craft using the right joystick.
However, all was not well. The joy stick controls behaved like the WASD controls. Pressing up on the joystick applied force to the rear of the vessel propelling it forward. This is all well and good when the vessel is oriented toward the top of the screen. But like the WASD controls the action on the screen is inverted when the vessel faces the bottom. The confusion caused by this inversion felt way worse than it did using a keyboard and mouse. It was so bad I had to disconnect the controller and play through a few missions with keyboard and mouse to remind myself that my game is not a broken hunk of junk.
I resolved this issue by switching the method in which I apply force to the ship. I ditched the physics_apply_local_force(); function and used the physics_apply_force(); function instead. The difference here is that the "local" version of this function applies force to the same relative point and direction of the object regardless of the object's orientation in the world space. The physics_apply_force(); will apply force to the object in the direction indicated by the H axis and V axis of the joy stick. The game pad input is now tied to the direction the player wishes to travel instead of the positions of imaginary thrusters.
I have transformed my zero gravity space combat game into a twin stick shooter.
Now, If I can figure out how to draw the appropriate thruster sprites based on vector and orientation so that when thrusters animate they match the ship movement logically. Then I will be satisfied with the game pad setup.
Development Tasks Completed
- You can now fly and shoot fairly well with a game pad.
Upcoming Development Tasks
- Create an Options menu to toggle game pad on and off
- Remake pause menu to support game pad navigation
- Continue improving game feel while using a game pad.
Until next time...