Taking on a Zelda Clone: Part 7

Most of my time on the project today was spent working on rehauling a lot of the game’s engine, so there isn’t too much to actually show off. But it’s coming along well!

Projectiles
I quickly put together the enemy projectile stuff yesterday, and one of the things I didn’t like was the way the enemy fireballs targeted the player. I basically let the fireballs live for 100 game ticks and made it so that the fireballs would reach the player’s position in exactly those 100 ticks. I did it this way because the math was easy, but it actually seemed pretty dumb when you were really close to the enemy and they’d shoot a fireball that would move super slow and last forever.

So, to fix that, I employed my old pals from high school, geometry and trigonometry. As a professional translator I’ve never had much use for the maths and the trigs and the calculus stuff, but I loved that stuff back then so it was pretty easy to apply it even after all these years.

Basically, I wanted the fireballs to move one pixel at a time, no matter what, and continue to fly past the player’s spot if the player moves before it arrives. To figure out how much to move the fireball on the x axis and how much to move it on the y axis with each clock tick meant I had to do some angle trickery.

A handy trick in case you’re ever making a game – you can get the angle of something by doing the arctangent (sometimes called inverse tangent) of the length of the opposite side of the triangle divided by the length of the adjacent side of the triangle. Using that, I did some other inverse trig stuff to figure out the answer I needed.

The problem I encountered was what if the player is exactly lined up on the x or y axis? That could result in a divide-by-zero problem, so I wanted a better way to handle it. Plus, I find it hard to believe the Zelda 1 programmers implemented this same thing using trig functions – on the NES that’s some heavy math to do (or at least a lot of ROM space wasted storing trig tables).

So I approached it from a geometry standpoint and did some simple algebra to figure out an equation I can use. It works perfectly, although I have to go in and assign negative or positives to the results manually.

You can see the result of all that math in action here!

See? People say all the time that math is never useful in real life – that’s because math is actually good for making fireballs.

Anyway, my resulting equation involves division and taking the square root of something, both of which are tough to do on the NES and cycle-intensive, so I still don’t believe that’s how they did it in Zelda 1. I *know* there has to be a cleaner, more optimized equation for this, if anyone knows, please share! It’s not often I get to mess with math, I forgot how nice of a puzzle game it can be 🙂

Enemies
While on the subject of projectiles, I was like, what if we made an enemy like a dog or a flower that shoots bees at you? Mainly I said it so I could try to make a different kind of projectile at some point, a sort of homing projectile maybe.

So Poe drew up a sunflower animation and, using the custom actions thing I did for the eye ghost yesterday, I made a new enemy that acts differently from all the rest of the current enemies. So that’s a good sign of how that design is coming along.

While I was at it, I made it so that some enemies will fly back when hit, while some won’t. And then I made it so that if you hit an enemy and it doesn’t die, it’ll flash briefly and make a sound so that you know you did damage it. It’s spiffy.

Engine work
A big thing that’s been bugging me is how to organize all the graphics and sounds and make it so that these assets are easily available to the things that need them. Before, I had to do some crazy parameter passing to get the assets to where they needed to go.

To fix this, I’ve started on a GameContentManager class that’s very basic, but by having an instance of it made at the start, I can then just pass a reference to this object around. This simplifies things a lot AND makes the source code make more sense.

Right now, the only downside is that I basically end up loading everything at the start, and I can’t unload it until the game’s over. I can probably add that feature in, but having to reload stuff on the fly can possibly cause stuttering and other issues. I’ll just have to try it out, but if I were to make a much larger game this basic solution wouldn’t really work.

Download
Currently no downloads as the engine is still being reworked. I’ll probably have other rehauls to do later too, like the tile system and the collision system. I just hope this doesn’t kill the roll I’m on.

Both comments and pings are currently closed.

13 Responses to “Taking on a Zelda Clone: Part 7”

  1. Murasaki says:

    I’ve never actually employed an angular trajectory system in anything I’ve worked on, BUT I always thought that if I did I would simply take the ratio between the difference in X positions of the enemy and the player, and the difference in Y positions, and have the projectile move along each axis in increments proportional to that ratio.

    Does that make sense? In any case, it would require floats and such since scaling the lower figure down to your 1 pixel limit would definitely be a “lossy” compression of the ratio, if you will.

    Now, I’m not certain how different this is from your model, although I don’t see why any square root derivation would be required.

    As for doing this without division…I’d have to think that one over for a bit.

    • Mato says:

      Yeah, that’s what I initially did (at least I think so, it’s late), but it still seemed odd to me. I think you might be right though and I did things the hard way, or maybe all the hard work was because I wanted it to move in increments of 1 pixel at a time from the hypotenuse’s point of view rather than just move in the direction alone. But I’ll recheck stuff in the morning, but I bet your way is exactly how it’s done in the old games.

    • blahmoomoo says:

      Old games almost always used subpixels in their calculations to simulate floating points. For example, if they don’t use subpixels in a platformer, then the main character would have a very choppy acceleration as their velocity jumps from 1 pixel per vsync to 2, and onward.

      Say that 1000 subpixels = 1 pixel. The velocity of an object is calculated as subpixels per vsync (60 times per second) in each direction. You apply the velocity to the object’s position at every vsync. Whenever the subpixel count exceeds 1000, add 1 to the pixel count and subtract 1000 from the subpixel count. The opposite happens when the subpixel count goes below 1000. (naturally, account for cases where the velocity exceeds 1000 in any direction)

      The subpixel count does not have any affect on rendering a single frame; the pixel count determines the position of the sprite. The subpixel count is just there to make the movement smooth.

      As to do the calculations to determine the velocity of those projectiles without complex operations… can’t help you there without looking it up.

  2. phee says:

    Take the vector from the enemy to the player: x, y
    Find the distance: d = sqrt(x squared + y squared)
    Finally, divide x and y by length: x = x / d; y = y / d
    Now you have a “unit vector,” it points in the same direction as it originally did, but is only one pixel of distance;
    You can use that, multiply a velocity in pixels by it or something

    • Mato says:

      Excellent, thanks, that’s what I was aiming for in my poor attempts at mathiness.

      I still wonder if that’s how old games did it, doing several divides AND a square root is pretty costly. But the unit vector thing is definitely the way to go, many thanks!

      • tapi says:

        xna also has Vector2.Normalize() which makes a vector into a unit vector for you.

      • phee says:

        You’ve made me curious twice, now. I shall make it my life’s mission to find and read the code in ANY nes game where an enemy fires a projectile in your direction.

  3. Murasaki says:

    Yeah, blahmoo brings up a good point. It’s also worth mentioning that some languages (perhaps not C#, but I believe C++ which is what I use) feature odd quirks in rounding and float calculations.

    I think for this game thing I was working on a little while ago I encountered some problems with smooth movement and almost on a whim just kind of said “what if I scale everything up by 100 and then just slice off the last two digits each time I need to blit” and the results impressed me.

    So use scales of magnitude and probably not floats unless you feel you can keep them under control. :s

  4. Murasaki says:

    orders. ^_^

  5. Skulryk says:

    I can’t say what would be appropriate for this situation, but as someone who deals with hardware logic, I can tell you that what you usually do when trying to do crazy math is using a linear approximation. Basically, some simpler math that can give you results that are pretty close to what the hard math gives you, usually by summing things up.

    Look up ‘Taylor series’ and ‘linear approximations’ — trig is a big deal there, so I would be willing to bet there’s a good approximation for what you’re doing.

  6. Skulryk says:

    Another thing that’s usually done (which you kind of alluded to) is using lookup tables. Basically, calculate the answer (or a rough approximation of your answer) ahead of time, store it in a table, and use the X and Y inputs (or a simple function of the X/Y inputs) as an index for that lookup table. Depending on how rough your approximation is, you actually don’t need that much space — I figure you could probably get away with only 32 or 64 angles for this problem, since anything finer than that won’t really be noticeable.

Subscribe to RSS Feed Follow me on Twitter!