Reverse-engineering multi-joint bosses

Discussion in 'Technical Discussion' started by Sonic 65, Aug 25, 2019.

  1. Sonic 65

    Sonic 65

    Tech Member
    1,174
    0
    16
    Manhattan
    Dustin Wyatt's Epic Jailbreak
    You know what I'm talking about: Seven Force, Yokozuna, Beast Kimkoh, and many more. Large bosses pieced together from many distinct sprites, which interface and animate together smoothly. Is there a standard way that games achieved this effect, back in the 16-bit era? I'm working on a retro side-scroller project of my own, and I'm at the point where I need to know how this stuff works.

    I believe the modern way to do something like this is to use a physics engine which supports joints, impose some sort of constraints between each joint so the "parts" fit together in the right ways (maybe changing the constraints for different animation states), and leave the rest up to some sort of hyper-optimized linear-algebra solver. For various technical reasons, I don't have access to that (more accurately, it would be a pain for me to interface with a proper physics engine and I'd like to avoid it if I can). It seems like overkill to import an entire physics engine just for this one function, anyway, if so many games in the 16-bit era were able to achieve these kind of effects with 7.6MhZ processors and without complex physics engines.

    Here are two specific examples. I'd be interested in knowing more about the programming of each:
    • The Orphic Vipers in Super Castlevania IV (I'm sure they're doing something very simple, but the way the joints move looks complicated. The regular Bone Dragon enemy has a similar movement, I think, and that guy was from the NES games, so the calculations can't be TOO taxing)
    • Xi-Tiger and Seven Force in Alien Soldier (16:45 and 34:22 respectively in this video; they're the most complicated bosses, in a game which is basically a non-stop variation on this idea. They both look incredibly smooth, to the point where I doubt that all the animation data was inputted manually)
    There are many more examples I could give, but I figure that if I can program these two guys, in addition to what I can already program, then I've covered everything that I might need. The Orphic Vipers are the most immediately pressing to me, since I'm currently working on a miniboss which demands similar movement.

    (Related question, if anyone knows. I've read in interviews that Konami had a stock set of generic routines that they would use for multi-joint sprite animation, combining the routines in various ways until they got a visual effect that looked cool. The design lead of Contra: Hard Corps said he threw this approach out, and the team custom-programmed every boss individually instead. What did these "generic routines" look like? And what is Hard Corps doing in comparison?)

    Feel free to post other examples you like in this thread, too, even if you can't explain how they work. (For some reason, I associate this effect way more with the Genesis than the SNES, or even the arcades, but feel free to prove me wrong.)
     
  2. MarkeyJester

    MarkeyJester

    My predecessors have nothing on me. Resident Jester
    It depends on how you want these pieces to react with one another.

    I'll create a terminology; we'll say you have a line of pieces, the first piece will be a "master" piece, and the piece that'll follow it or is linked to it, will be called a "slave" piece. So the second piece in the line will be a slave to the first piece, the first piece is the master to the second piece. The third piece is a slave to the second piece, and the second piece is a master to the third piece. This continues down to the last piece, which is only a slave to the second from last piece, but is a master to nothing because it's the last piece in the chain.

    You can use the terms "Adult" and "Child" or some other terminology if you'd like, but you get the idea.

    Now, let's take a simple example, you would probably give every piece a 360 degree angle variable, and this 360 degree will control how to position that piece's slave. In this example, each piece will directly control the exact position of it's slave, so the order of control is from master to slave. This can give a very direct and solid looking approach, though you can get snake like effects by manipulating the 360 variables to each piece at the right time.

    If you want something far more complicated and fluid, including things like gravity and collision with floors/walls, then this can get somewhat complex, but there are rules you can follow to get a near realistic looking chain of pieces. This will involve having the slave follow the master, rather than the master controlling the slave. In other words, if the master moves, the master does not touch the slave, but rather the slave pays attention to the master and where it's going.

    I would use pythagoras theorem to get the distance the master is away from the slave in any 360 direction, and if it's surpassed a certain radius, you get the arctangent between the two, this will give you the angle at which they are distanced from, you then use that angle to force the slave to be away from the master at the maximum radius. This will cause the slave piece to follow the master piece like some sort of chain, if you don't want to allow the pieces to go into each other, you can do the same thing but using the radius is the minimum distance as well as the maximum. Applying gravity with the above will cause realistic looking chains which try to fall towards the floor but swing around because they are pulled towards the master like an orbit, you could even implement a bounce such that once they surpass the radius, they snap to the radius, but the vertical speed is negated to bounce back up.

    If you want the change to swing back and forth before slowly stopping, you would probably implement a "speed angle", where if the angle variable is away from a certain specific angle (we'll pretend 180 degrees for down to simulate gravity), you'll increase the angle speed and add that speed to the angle variable to rotate it around, if it surpasses the angle 180, you then decrease the speed until negative gradually and continue adding the negative speed to the angle (you will need to apply things like friction/wind resistance to slow it down so it eventually reaches 180 and stops). I would also apply some sort of "stiff" mode, when enabled stops the pieces from following the gravity rules, or perhaps follows the "minimum" radius rule I mentioned above. Say you have a character who has an arm of pieces which swing around with realistic physics, and then you wanted to initiate an attack, where the arm unrolls towards the player, you would need the pieces to stiffen up.

    If there are two masters (by that I mean a chain is being held up and controlled from two points instead of one), then this gets a little more complicated as you'll need to apply the master/slave rules above in both directions.

    I would suspect that some of the mechanics in these games may be hard coded to save on CPU time or just programming time in general though. The above is not methods others have used, it's just a method I would (and have) used before in the past. There will be certain more elaborate and CPU cost effective ways which might suit your needs best. It is alas, dependent on what and how you intend to implement your chain of pieces.

    EDIT: Here is one example I made using some of the above ideas if you're interested (this was shared publicly at some point, so I don't think it'll be a problem to share here):

    [​IMG]

    There was more updated on this, including the stiffness put to very good use, and it looked very realistic, unfortunately I don't think I'd be allowed to show that as it was never made public, sorry.
     
    Last edited: Aug 26, 2019
    • Informative Informative x 4
    • List
  3. Ritz

    Ritz

    Subhedgehog Member
    Short answer: Matrix multiplication. Any transformation matrix multiplied by another transformation matrix inherits the transformations of the preceding matrix, creating an implicit parent/child relationship. It's surprisingly simple, you can do it on a graphing calculator- the sample programs in the chapter 4 folder here and the accompanying book material are the best introduction I've seen, if you don't mind compiling OpenGL. Chapters 4-6 of "3D Math Primer for Graphics and Game Development" are my favorite reference for the math.

    (I spent the past three months grinding this stuff because I want to do Alien Soldier bosses too)
     
    • Informative Informative x 2
    • List
  4. Sonic 65

    Sonic 65

    Tech Member
    1,174
    0
    16
    Manhattan
    Dustin Wyatt's Epic Jailbreak
    Thanks for the tips, guys. I've indeed used a parent/child system before (it's how I programmed the snake boss in the video in the OP), but nothing that complex! Good stuff.

    The guys over at SNESdev gave me a tip that the Orphic Vipers were just using multiplied sine waves to position the link pieces. Here's our variation on that idea, it worked like a charm (WIP assets, of course):

    [​IMG]

    So the most immediately pressing issue is solved. Alien-Soldier-bosses are going to be a much more complicated thing, though. I was hoping to never directly deal with matrix multiplication ever again, after getting my Master's! :specialed:

    The guys in that thread also referred me to the Spline library, which has bindings for the graphics library I'm using; I haven't looked very far into it yet. The examples look cool, but many of them also have a weird unnatural Flash-animated quality, so we'll see how it goes; I'm still really hoping I won't have to roll my own for this one in any significant regard. I'll update this thread again once I figure out the more complicated bosses.

    (Another example I'd love to hear more about, by the way: Spinderella from Dynamite Headdy. We have a bizarre psuedo-3D fight coming up, which is structured kind of similarly to this guy. I doubt knowing exactly how he works will be insightful in any practical way for me, but I'm sure it would be cool trivia.)
     
    Last edited: Sep 4, 2019