Programing Medusa head type movement

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Kitty_Space_Program
Posts: 27
Joined: Mon Sep 21, 2020 7:42 am

Programing Medusa head type movement

By this I mean, things that move up and down in a sin wave. I doubt the 6502 could calculate sin(x) easily, i would think they used a lookup table of sin values, but then how would they offset the verticle height (like the line they are going up and down around) and change the amplitude of the wave. And how would they have it loop? Maybe a cmp and beq? Any ideas?

lidnariq
Posts: 9774
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Programing Medusa head type movement

Does this thread help any?

rainwarrior
Posts: 7877
Joined: Sun Jan 22, 2012 12:03 pm
Contact:

Re: Programing Medusa head type movement

You can get a very nice sine-like curve by using an acceleration that flips periodically, and storing the resulting velocity:
1. Have an acceleration that flips from +12 to -12 every 100 frames.
2. Every frame that acceleration adds to a velocity.
3. Every frame that velocity adds to the position.
To explain what that does to the position of the enemy:
1. The acceleration over time graph looks like a square wave.
2. The velocity over time goes up and down in straight diagonal lines. It makes a triangle wave. (The integral of a square wave is a triangle wave.)
3. Finally the position over time graph (i.e. where you see the enemy move) is a nice round curve going up and down.
A quick diagram to show that visually:
Using 16-bit variables will help, here. For the final position onscreen, you probably want to take the high 8 bits of the position.

Finally, in order to make it go back and forth, we need to start with the right velocity. 12 x 100 frames = 1200 total change in velocity before it flips. This means it should swing from -600 to positive 600. (Half the total range.)

If you want to start at the top or bottom of the wave, the velocity is 0, and you are at the start of an acceleration cycle: 100 frames to go before flipping.

If you want to start in the middle of the wave, the velocity is 600 or -600, but the acceleration is half-way through its cycle: 50 frames to go before flipping.

The result of this is not quite a sine wave but it does make a nice curve that looks a lot like a sine. The number of frames chosen between acceleration flips is the length of time the enemy takes to go from top to bottom.

The height of the wave I think should be the velocity times the square of half the number of frames? In this case 12 x 50 x 50 = 30,000 (~117 pixels if you take the high 8 bits). Alternatively you can just try a few different acceleration values until it looks good.

Oziphantom
Posts: 928
Joined: Tue Feb 07, 2017 2:03 am

Re: Programing Medusa head type movement

typically you make a LUT such as

Code: Select all

``.char \$00,\$01,\$02,\$03,\$3,\$03,\$02,\$01,\$00,\$-1,\$-2,\$-3,\$-3,\$-3,\$-2,\$-1``
or some other POW2 length then you

y += TABLE[index]
index = index + 1 and 15

if you want to scale it you either make a pre scalled tabled which is better as you will get better resolution. or you ASL + ADC it before adding

Code: Select all

``````lda Table,x
asl a
adc Table,x ; x3
sta Y
``````

rainwarrior
Posts: 7877
Joined: Sun Jan 22, 2012 12:03 pm
Contact:

Re: Programing Medusa head type movement

Something I forgot to add about the method I mentioned:

The acceleration flip happens at the same time the position crosses the zero line. An alternate way to program this is have acceleration be negative or positive depending whether you're below or above a target centre line.

If you do it that way, you could move the enemy up and down smoothly just by changing its target and letting it fly there, but it needs two additional things:

1. If it's going to move, put a cap on the velocity (i.e. check if it's over 600, or under -600 and set it back to the maximum if it goes to far), so that the height of the wave doesn't increase.

2. When it moves, if it is close to the new target line and its velocity is low, the height and period of the wave gets smaller. You can compensate for this by checking if the velocity is below the maximum when crossing the target line, and boosting it if it isn't.

Kitty_Space_Program
Posts: 27
Joined: Mon Sep 21, 2020 7:42 am

Re: Programing Medusa head type movement

rainwarrior wrote:
Sun Oct 11, 2020 10:04 pm
You can get a very nice sine-like curve by using an acceleration that flips periodically, and storing the resulting velocity:
1. Have an acceleration that flips from +12 to -12 every 100 frames.
2. Every frame that acceleration adds to a velocity.
3. Every frame that velocity adds to the position.
thats really helpful, thank you.

Kitty_Space_Program
Posts: 27
Joined: Mon Sep 21, 2020 7:42 am

Re: Programing Medusa head type movement

rainwarrior wrote:
Mon Oct 12, 2020 1:04 pm
An alternate way to program this is have acceleration be negative or positive depending whether you're below or above a target centre line.
Is it possible to use adc or something similar to where if the number is signed negative it will subtract and if not it will add or would you have to add bpl/bmi

Oziphantom
Posts: 928
Joined: Tue Feb 07, 2017 2:03 am

Re: Programing Medusa head type movement

2's compliment means you can add signed numbers

so

Code: Select all

`````` \$34 +
\$FF
----
133

which we have 8 bits so
\$33``````
127 = + 127
1 = + 1
2 = + 2
FF = -1
FE = -2
80 = -128

tokumaru
Posts: 11891
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Programing Medusa head type movement

Assuming you're using 8-bit coordinates, you can add a signed delta (-128 to 127) to an unsigned coordinate (0 to 255) and the result will be correct. If you're using 16-bit coordinates (usually the case when levels scroll), then the deltas have to be 16 bits as well.

rainwarrior
Posts: 7877
Joined: Sun Jan 22, 2012 12:03 pm
Contact:

Re: Programing Medusa head type movement

Just in case it's unclear: adding (or subtracting) two numbers is the same assembly code whether or not they are signed. The only thing that is different is how you choose to use the result.

If you need to convert an 8-bit signed number to a 16-bit one, you duplicate its leftmost bit into the new high byte. Here BPL and BMI are useful because they branch on that bit, where you can select 0 for the high byte if BPL or -1 = \$FF if BMI. (This is called "sign extension".) If the numbers are already both 16-bit there's no need to sign extend.

If you need to compare two signed numbers, or check for an overflow condition, there is the "V" (oVerflow) flag, which is affected by ADC or SBC. This flag doesn't mean anything if the numbers were unsigned, but if they're signed it becomes useful. (I usually refer to this article: Beyond 8-bit Unsigned Comparisons.)

Kitty_Space_Program
Posts: 27
Joined: Mon Sep 21, 2020 7:42 am

Re: Programing Medusa head type movement

Oziphantom wrote:
Wed Oct 14, 2020 11:32 pm
2's compliment means you can add signed numbers
I realized that right after I made the post. For some reason it wouldn't let me edit it. XP