I'm making a galaxian-like shooter, and my enemy objects have a destination Vector which they travel towards, using this bit of code:
position.X -= (Motion.X / Magnitude) * Speed;
position.Y -= (Motion.Y / Magnitude) * Speed;
Motion is worked out by:
this.Motion = InitialPosition - Destination;
This makes them travel in a straight line towards the destination.
However, I want to make them a bit more interesting, and travel on a sin or cos wave, a bit like Galaxian did.
How can I do this?
You might be better off defining a bezier curve for the movement function than simple functions like a sine wave. Galaxian certainly had more complex movements than that.
Here is a link to a primer on the maths of Bezier curves. It's quite a long document, but does a good job of covering the maths involved, with plenty of examples.
Hope that helps inspire you.
One way to do this would be to create an acceleration factor for the horizontal motion and add that factor to the horizontal speed every tick. So if your horizontal speed for a given enemy was 2 to begin, and your acceleration was -.01, then after 200 ticks the enemy would be going straight down, and after another 200 ticks it would be moving at a horizontal speed of -2. This will give a nice curve.
By determining the speed and acceleration randomly for each enemy (within certain limits determined by experimentation) you can create a nice looking variety of attack profiles without too much effort. This would give a very Galaxian-like motion.
You can do the same thing with the vertical as well, though, of course, the acceleration limits would be very different...for the horizontal acceleration you would probably want to determine a range that was equal in magnitude on either side of 0 (say -.02 to +.02), while for the vertical acceleration, you probably always want the ship to end up going down off the bottom of the screen, so you probably want that acceleration to always end up positive (or negative depending on how you're doing screen coordinates.)
You would do this by utilizing waypoint navigation, in line with your current motion code. You would calculate the waypoints by graphing the sine wave. You would do this by using something to the effect of Destination.Y = Math.Sin(Destination.X)
- it's a little difficult to say for sure without seeing your code at large.
Creating an oscillator and moving the enemy (even without momentum) perpendicularly to its direction by an offset equals to the sine or cosine of the oscillator would be enough.
The following example, while working, is clearly just a guideline. I hope it can help you.
var dest = new PointF(200, 100);
var pos = new PointF(30, 140);
var oscAngle = 0d;
var dirAngle = Math.Atan2(dest.Y - pos.Y, dest.X - pos.X);
//Constants for your simulation
const int movSpeed = 2;
const int amp = 2;
const double frequency = Math.PI / 5;
//Inappropriate loop condition, change it to proper
while (true)
{
oscAngle += frequency;
//Scalar offset, you can use Cos as well
var oscDelta = Math.Sin(oscAngle);
//Linear movement
var stepVector = new SizeF((float)(Math.Cos(dirAngle) * movSpeed), (float)(Math.Sin(dirAngle) * movSpeed));
//Oscillating movement, making it transversal by adding 90° to the direction angle
var oscNormalAngle = dirAngle + Math.PI / 2;
//Vector for the oscillation
var oscVector = new SizeF((float)(Math.Cos(oscNormalAngle) * oscDelta) * amp, (float)(Math.Sin(oscNormalAngle) * oscDelta) * amp);
pos += stepVector + oscVector;
//Operate below
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With