Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Galaxian-like Enemy movement

Tags:

c#

xna

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?

like image 568
AllFallD0wn Avatar asked Dec 19 '12 16:12

AllFallD0wn


4 Answers

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.

like image 163
SDC Avatar answered Nov 10 '22 07:11

SDC


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.)

like image 5
Beska Avatar answered Nov 10 '22 08:11

Beska


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.

like image 3
tmesser Avatar answered Nov 10 '22 08:11

tmesser


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
}
like image 2
Mir Avatar answered Nov 10 '22 09:11

Mir