Best method for circular motion?
Moderator: Moderators
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: Best method for circular motion?
Jesus, is there any place that says the mathematical equation for sine and cosine? We just used our calculators, along with what seems to be the rest of the world, to figure it out.
Edit: Well, I found something, but I'm not sure how well the NES will do... http://math.stackexchange.com/questions ... t-a-number
Edit: Well, I found something, but I'm not sure how well the NES will do... http://math.stackexchange.com/questions ... t-a-number
Re: Best method for circular motion?
Nobody calculates these at run time, everyone uses look-up tables.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: Best method for circular motion?
I can tell...
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Best method for circular motion?
On the NES, few people would calculate a sine at runtime. There are lots of ways to calculate them, though, and lots of reasons why you might do this rather than a lookup. The naive way of calculating one is probably the Taylor Series definition of the sine, i.e. you have an infinite series with increasingly smaller terms, and you just evaluate enough terms to reach the accuracy you want. CORDIC is the name of a commonly used set of trigonometry calculations for CPUs without a hardware multiply, like the 6502.
So, now that you can easily calculate position and velocity in terms of frame, pick a number of frames for your object to travel from the extreme to the centre. For instance, if it takes 5 frames, and acceleration is +3 per frame:
radius = 3 * 5 * (5+1) / 2 = 3 * 5 * 6 / 2 = 45
starting velocity = 3 * 5 = 15
So, in this case, you can place your object on the Y extreme, at (0,45) relative to the target, and give it a starting velocity of (15,0), and it will create a perfect orbit, at least until the target moves. Once the target moves, the circle gets stretched, probably irreversibly without extra corrections.
Here are some ways to do corrections to recover a circle:
1. Clamp your maximum velocity to that calculated starting velocity value, this creates a maximum radius.
2. Encourage motion in one direction only, like a Coriolis effect. Discourage anti-clockwise movement by preventing out-of-phase acceleration, by using 4 quadrant rules for acceleration instead of just 2 axis rules, e.g.:
To calculate the starting velocity, know that X velocity is 0 at the two horizontal extremes, and Y is 0 at the vertical. So, starting from zero, the velocity at frame T is A*T. The position accumulates each frame, though, so it's a series, (A*1)+(A*2)+(A*3)+...(A*T) = A*(1+2+3+...T) which reduces to: A*T*(T+1)/2JoeGtake2 wrote:Yeah, the target point method is essentially what I'm working with. I can get oscillation in either axis just fine, I just can't get a dependable circular motion that way...or even close, no matter how i populate the starting values or starting velocities (LOTS of trial and error, too). I mean, it's a cool organic sort of movement, but certainly not orbiting 'around' the orbit object ... any tips on better control over this?
So, now that you can easily calculate position and velocity in terms of frame, pick a number of frames for your object to travel from the extreme to the centre. For instance, if it takes 5 frames, and acceleration is +3 per frame:
radius = 3 * 5 * (5+1) / 2 = 3 * 5 * 6 / 2 = 45
starting velocity = 3 * 5 = 15
So, in this case, you can place your object on the Y extreme, at (0,45) relative to the target, and give it a starting velocity of (15,0), and it will create a perfect orbit, at least until the target moves. Once the target moves, the circle gets stretched, probably irreversibly without extra corrections.
Here are some ways to do corrections to recover a circle:
1. Clamp your maximum velocity to that calculated starting velocity value, this creates a maximum radius.
2. Encourage motion in one direction only, like a Coriolis effect. Discourage anti-clockwise movement by preventing out-of-phase acceleration, by using 4 quadrant rules for acceleration instead of just 2 axis rules, e.g.:
- top right - always accelerate down, only accelerate left if X velocity is positive
- bottom right - always accelerate left, only accelerate up if Y velocity is positive
- bottom left - always accelerate up, only accelerate right if X velocity is negative
- top left - always accelerate right, only accelerate down if Y velocity is negative
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: Best method for circular motion?
I've just been thinking about the whole sine and cosine thing: About the table, would you have it to where you have it to where there are 2 separate 90 entry tables that are indexed by whatever degree? On the SNES at least, you could have it to where the values in the table are for a radius of 1 (there will be sub pixel precision) and say if you wanted the radius to be 5, you would get the numbers from the sine and cosine table and use the multiplication units to multiply them by 5.
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Best method for circular motion?
A sine and cosine table are the same thing starting at different offsets. You only need one. If instead of degrees you divide the circle into 256, you can just use the implicit modulo 256.
cos[x] = sin[(x+64) & 255]
As for scaling, that's its own problem. You can have different tables at different scales, or you can attempt to scale them in some manner (shifting, multiply, etc.).
cos[x] = sin[(x+64) & 255]
As for scaling, that's its own problem. You can have different tables at different scales, or you can attempt to scale them in some manner (shifting, multiply, etc.).
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: Best method for circular motion?
How would you multiply on a system that doesn't have any multiplication hardware? The only way I could think of is if you had it like this:
(I think this would work on the 6502? It would be slow as all hell though.)
Would there be some sort of way to improve this with bit shifts? I really don't get how you'd do division.
(I think this would work on the 6502? It would be slow as all hell though.)
Code: Select all
start_multiplier:
lda #$00
ldx Multiplier
multiplier_loop:
beq multiplier_done
clc
adc Multiplicand
dex
bra multiplier_loop
multiplier_done:
sta Product
rts
Re: Best method for circular motion?
Multiplication on 6502 uses the peasant algorithm, and division uses long division algorithm in base 2. The source code for Thwaite has examples of both.
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Best method for circular motion?
There are a hundred different ways to implement a multiply or divide.
There's a few here: http://6502.org/source/
The wiki has a few:
http://wiki.nesdev.com/w/index.php/8-bit_Multiply
http://wiki.nesdev.com/w/index.php/Mult ... nt_integer
http://wiki.nesdev.com/w/index.php/Divi ... nt_integer
One requiring large lookup tables:
http://codebase64.org/doku.php?id=base: ... iplication
Omegamatrix wrote a series of routines for dividing by specific integers:
viewtopic.php?f=2&t=11336
There's a few here: http://6502.org/source/
The wiki has a few:
http://wiki.nesdev.com/w/index.php/8-bit_Multiply
http://wiki.nesdev.com/w/index.php/Mult ... nt_integer
http://wiki.nesdev.com/w/index.php/Divi ... nt_integer
One requiring large lookup tables:
http://codebase64.org/doku.php?id=base: ... iplication
Omegamatrix wrote a series of routines for dividing by specific integers:
viewtopic.php?f=2&t=11336