PDA

View Full Version : Orbit Diver (Movement pattern for boss)



C-Dawg
01-07-2007, 11:18 PM
Here's a slightly more complicated movement pattern. In practice, the enemy seems to jump around in a quasi-random way. What it's really doing is following an ideal (x,y) in orbit around the player, dodging away from player attacks, and swiping in for an attack periodically.

Shout goes out to Jman who debugged this one. I changed his resulting script a little bit, based on the following observation:

You need to guard against your custom boss movement scripts going off the edge of the screen. If they go off to far, the FFC will dissapear. It turns out to be easier to keep things on the screen if you only modify velocity, not actual position. Where I can't do that here, I've tried to guard against going off the screen anyway.

NOTE: This code is not written with this_ffc, but with this->. So wherever you stick it, it will currently affect the first ffc.



// ========================================
// orbit_diver - This FFC script makes the FFC behave as an
// orbit diver. At rest, the FFC will orbit the player at a certain
// distance. If the player attacks, the FFC distance of the
// orbit will double for a short period of time, then it will
// immediately counterattck. At regular
// intervals, the FFC will dive towards the player and then return
// to it's circular path.
//
// D0 - Speed of the orbit diver's normal behavior. Must be
// between 0 and about 6.28 for proper behavior.
// D1 - Speed of the orbit diver's attack
// D2 - Radius of the orbit diver's normal behavior
// D3 - Delay between orbit diver's diving attack. Make it longer
// than 30, because that's how long the attack will last.
// D4 - The time the orbit diver spends in a larger orbit after an attack
// =======================================

ffc script orbit_diver{

void run(int orbit_speed, int diving_speed, int radius, int delay, int dodge_time) {

int state = 0; // 0 = At rest, not dodging
// 1 = Dodging away from player attack
// 2 = Diving towards player

int i = 0; // Used to keep track of the
int orbit_x; // orbit of the ffc.
int orbit_y;
int orig_radius = radius;

int delay_counter = delay; // Countdown to attack

int dodge_counter = dodge_time; // Countdown to dodging

int dive_counter = 30; // Duration of attack

bool ontrack = true;

// We need to scale

while(true) {

// First, calculate the idea orbit of this ffc and put it into orbit_x, orbit_y

orbit_x = ((Sin(i)*radius) + Link->X+8)-(this->EffectWidth/2);
orbit_y = ((Cos(i)*radius) + Link->Y+8)-(this->EffectWidth/2);

// Next, increase the value of i for the next loop.

i = i + orbit_speed;

// ============= State 0 Behavior ==============

if (state == 0) {

// The FFC should get close to the ideal orbit (kept track of
// by orbit_x, orbit_y) if it is not already.

if(!ontrack)
{
if ( ((this->X - orbit_x) > diving_speed) || ((this->X - orbit_x) < -diving_speed) ||
((this->Y - orbit_y) > diving_speed) || ((this->Y - orbit_y) < -diving_speed) )
{

if (this->X >= orbit_x)
{
this->Vx = -diving_speed;
}
else
{
this->Vx = diving_speed;
}

if (this->Y >= orbit_y)
{
this->Vy = -diving_speed;
}
else
{
this->Vy = diving_speed;
}
}
else
{
ontrack=true;
}
}

// If the FFC is already close to the ideal orbit, just follow it around.

else{

if(orbit_x > 248) { this->X = 248; }
else{
if(orbit_x < 0) { this->X = 0; }
else {this->X = orbit_x;}
}

if(orbit_y > 168) { this->Y = 168; }
else{
if(orbit_y < 0) { this->Y = 0; }
else {this->Y = orbit_y;}
}
}

// Countdown to diving attack

if (delay_counter <= 0){

state = 2;
dive_counter = 30;
delay_counter = delay;
}
else{
delay_counter--;
}

// Detect whether the player is attacking or using an item
if ( (Link->InputB) || (Link->InputA)){

state = 1;
}

} // end of state 0

// ============= State 1 Behavior ==============
if ( state == 1 ) {

// Increase the radius incrementally until it reaches double the radius;
if(radius >= orig_radius*2) { radius = orig_radius*2; }
else { radius += 1; }

// The FFC should get close to the ideal orbit (kept track of
// by orbit_x2, orbit_y2) if it is not already.

if(!ontrack)
{
if ( ((this->X - orbit_x) > orbit_speed) || ((this->X - orbit_x) < -orbit_speed) ||
((this->Y - orbit_y) > orbit_speed) || ((this->Y - orbit_y) < -orbit_speed) ){

if (this->X >= orbit_x) { this->X -= diving_speed; }
else { this->X += diving_speed; }

if (this->Y >= orbit_y) { this->Y -= diving_speed; }
else { this->Y += diving_speed; }
}
else
{
ontrack=true;
}
}

// If the FFC is already close to the ideal orbit, just follow it around.
else{

this->X = orbit_x;
this->Y = orbit_y;
}

// Countdown to diving attack
if (delay_counter <= 0){

state = 2;
dive_counter = 30;
delay_counter = delay;
}
else{
delay_counter--;
}

// Countdown to counterattack
if (dodge_counter <= 0){
state = 2;
dive_counter = 30;
dodge_counter = dodge_time;
}
else{
dodge_counter--;
}
} // end of state 1

// ============= State 2 Behavior ==============
if (state == 2) {

if (this->X <= Link->X){
this->Vx = this->Vx + (diving_speed/10);
if ( this->Vx > diving_speed ) { this->Vx = diving_speed; }
}
else{
this->Vx = this->Vx - (diving_speed/10);
if ( this->Vx < -diving_speed ) { this->Vx = -diving_speed; }
}

if (this->Y <= Link->Y){
this->Vy = this->Vy + (diving_speed/10);
if ( this->Vy > diving_speed ) { this->Vy = diving_speed; }
}
else{
this->Vy = this->Vy - (diving_speed/10);
if ( this->Vy < -diving_speed ) { this->Vy = -diving_speed; }
}

// Duration of attack
if (dive_counter <= 0){
state = 0;
this->Vx = 0;
this->Vy = 0;
ontrack = false;
delay_counter = delay;
dodge_counter = dodge_time;
radius = orig_radius;
}
else{
dive_counter--;
}

} //end of state 2

// Edgeguard function

if(this->X > 248) { this->Vx = -1; }
if(this->X < 0) { this->Vx = 1; }

if(this->Y > 168) { this->Vy = -1; }
if(this->Y < 0) { this->Vy = 1; }


Waitframe();
} // end of while loop
} // end of void run
} // end of ffc script

Gleeok
12-02-2007, 09:54 AM
First reply...that's hard to believe. Anyway, I would like to register a bug. While playing Zodiac, the orbit diver will zip off screen if the player "lures it" to the edge. Also messing with the speed variables causes it to instantly fly off screen, while lowering them a tad, messes up the orbit or general movement....I could of erred somehow though... Sweet script otherwise.