PDA

View Full Version : Multiblock Trigger and LinkPusher



C-Dawg
10-30-2006, 12:37 PM
I'm at work, so I can't test this code yet. But I thought I'd post it anyway so the community can take a look and correct any glaring oversight in the algorithim. (Or perhaps someone more talented than I can be inspired.)

Multiblock Triggers:


int distancesq(int x1, int x2, int y1, int y2)
{
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}

// ===============================================
// multiblock_trigger - This FFC will change combo
// depending on whether certain combos on Layer 0
// are unwalkable. As input, this FFC takes eight
// integers which represent four (X,Y) pairs that the
// multiblock checks for walkability. When all are
// unwalkable, the combo of this FFC will increase by
// one and a secret noise will chime. When any are
// walkable, they will revert back to their original
// combo and not make a chime. By default, the original
// combo used by this FFC mimics unwalkability.
//
// USE - You can use the multiblock trigger to require
// Link to push up to four blocks into position. For
// less than four, just set all of the inputs to permanently
// unwalkable combos, like a dungeon wall, or set them
// all to the same location. Because this FFC reverts
// when the tiles are not walkable, it can also be used
// to create "pressure-sensitive" triggers that must be
// held down by a block and will deactive when the block
// moves away.
// ===============================================

ffc script multiblock_trigger{

// CONSTANTS - Change to change this FFC's behavior

int walkable = 1; // Whether or not the starting
// combo for this FFC is walkable
// or not. For instance, a closed
// door should start unwalkable.
// 0 = walkable
// 1 = unwalkable

// VARIABLES - Do not change!

int state = 0; // Current state of the FFC.
// 0 = untriggered
// 1 = triggered

void run (int block1_x, int block1_y, int block2_x, int block2_y,
int block3_x, int block_3y,int block4_x, int block_4y){

while(true){

if(state == 0){


// Check to see if all blocks in position
if (!canMove(block1_x, block1_y) &&
!canMove(block2_x, block2_y) &&
!canMove(block3_x, block3_y) &&
!canMove(block4_x, block4_y)){

this->Data = this->Data + 1;
PlaySound(27);
state = 1;
}

// Simulate unwalkability
if(walkable == 1){

if( (Link->InputUp) && (Link->Y << this->Y + 16) &&
(Link-Y >> this->Y)){Link->Y++;}

if( (Link->InputDown) && (Link->Y >> this->Y - 16) &&
(Link-Y << this->Y)){Link->Y--;}


if( (Link->InputLeft) && (Link->X << this->X + 16) &&
(Link-X >> this->X)){Link->X++;}

if( (Link->InputRight) && (Link->X >> this->X - 16) &&
(Link-X << this->X)){Link->X--;}
}

} // end of state 0

if (state == 1){

// Check to see if a block has moved
if (canMove(block1_x, block1_y) ||
canMove(block2_x, block2_y) ||
canMove(block3_x, block3_y) ||
canMove(block4_x, block4_y)){

this->Data = this->Data - 1;
state = 0;
}

} // end of state 1

} // end of while loop

} // end of void run

} // end of ffc script



Link_Pusher ideally functions like Blocky from Adventures of Lolo.



int distancesq(int x1, int x2, int y1, int y2)
{
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}

// =======================================
// Link_Pusher - The FFC will move towards
// Link, though it will not pass through
// unwalkable combos on layer 0. When it
// reaches Link, it pushes him in whatever
// direction it is moving.
// =======================================

ffc script link_pusher {

int x;
int y;

void run() {

while(true)

{
x = this->X;
y = this->Y;
int dist = distancesq(Link->X, this->X, Link->Y, this->Y);

this->Vx = (Link->X - x)*Abs((Link->X-x))/dist;
this->Vy = (Link->Y - y)*Abs((Link->Y-y))/dist;


// Don't move if it would move into an unwalkable block.

if ( (!canMove(this->X, this->Y + 16)) && (this->Vy >> 0)){
this->Vy = 0;
}

if ( (!canMove(this->X, this->Y - 16)) && (this->Vy << 0)){
this->Vy = 0;
}

if ( (!canMove(this->X + 16, this->Y)) && (this->Vx >> 0)){
this->Vx = 0;
}

if ( (!canMove(this->X - 16, this->Y)) && (this->Vx << 0)){
this->Vx = 0;
}

// Push Link if moving next to him. Check if the FFC is
// within one tile of Link, and is moving towards him. Then
// checks whether Link would be pushed into a solid block.
// If conditions are satisfied, Link is pushed back in the
// direction of the FFC's movement. If Link moves against
// the pusher, he's forced back more heavily.

if ( (this->X >> Link->X) && (this->X << Link->X + 16) &&
(this->Vx << 0)){

if (canMove(Link->X - 16)){

Link->X = Link->X -1;
if (Link->InputRight == true){Link->X = Link->X-1;}

}
}


if ( (this->X << Link->X) && (this->X >> Link->X - 16) &&
(this->Vx >> 0)){

if (canMove(Link->X + 16)){

Link->X = Link->X + 1;
if (Link->InputLeft == true){Link->X = Link->X+1;}

}
}

if ( (this->Y << Link->Y) && (this->Y >> Link->Y - 16) &&
(this->Vy >> 0)){

if (canMove(Link->Y + 16)){

Link->Y = Link->Y + 1;
if (Link->InputUp == true){Link->Y = Link->Y+1;}

}
}

if ( (this->Y >> Link->Y) && (this->Y << Link->Y + 16) &&
(this->Vy << 0)){

if (canMove(Link->Y - 16)){

Link->Y = Link->Y - 1;
if (Link->InputDown == true){Link->Y = Link->Y-1;}

}
}

Waitframe();


} // end of while loop
} // end of void run


// Collision detection function
bool canMove(int x, int y)
{
if(x<0 || x>240 || y<0 || y>160)
return false;

return Screen->ComboS[y+(x>>4)]==0;
}


} // end of ffc script

Saffith
10-30-2006, 01:52 PM
A couple of minor problems in multiblock_trigger...

void run (int block1_x, int block1_y, int block2_x, int block2_y,
int block3_x, int block_3y,int block4_x, int block_4y){block3_y and block4_y are mistyped.


PlaySound(27);You have to write it as Game->PlaySound(27).


if( (Link->InputUp) && (Link->Y << this->Y + 16) &&
(Link-Y >> this->Y)){Link->Y++;}
// etc.I assume you meant to use greater than and less than instead of the bitshift operators?
Also, be sure to change Link-Y to Link->Y.

Also, you forgot to put a Waitframe() in the while loop and to define canMove().


So, no serious mistakes there, as far as compiling, and it almost works. It's a bit quirky; apparently, you have to give the top-left pixel of the tile you want to check for solidity. It doesn't seem to work in the middle. Not what I would expect, really; I think it might be a result of how the bitshift works with non-integral numbers.

But, as for why it only almost works, the real problem is here:

// Simulate unwalkability
if(walkable == 1){

if( (Link->InputUp) && (Link->Y << this->Y + 16) &&
(Link-Y >> this->Y)){Link->Y++;}

if( (Link->InputDown) && (Link->Y >> this->Y - 16) &&
(Link-Y << this->Y)){Link->Y--;}


if( (Link->InputLeft) && (Link->X << this->X + 16) &&
(Link-X >> this->X)){Link->X++;}

if( (Link->InputRight) && (Link->X >> this->X - 16) &&
(Link-X << this->X)){Link->X--;}
}Well, two problems actually. First, you have to check if Link is aligned both horizontally and vertically at once; as it is, it checks if he's anywhere along the lines intersecting at the FFC.
Second, Link doesn't move only one pixel per frame. I forget how it is, exactly; 1-1-2-1-1-2, or something like that. In any case, this only adjusts Link's position by one pixel per frame, so it only slows him down instead of stopping him altogether. You might try saving his position and resetting it afterward, or simply setting the appropriate inputs to false.


As for the link_pusher... I don't know. There are a couple of simple mistakes (most importantly: << and >> instead of < and >, Link->InputRight == true instead of just Link->InputRight, and missing arguments to canMove() ), but I'm not sure why it's acting the way it is. It's pushing Link into walls, moving into walls itself, and simply failing to move at all after a while. Oh, and it has that same problem of checking whether Link is along a vertical or horizontal line instead of right next to it.
I can spend a bit more time on it later, but at the moment, I don't see why exactly it's doing what it is.

C-Dawg
10-30-2006, 03:20 PM
You might try saving his position and resetting it afterward, or simply setting the appropriate inputs to false.


That's a question I have, actually. If I put Link->InputUp = false; in an FFC script, will it totally cancel out the input before Link has a chance to move?

Answer: YES! Glory be that's sweet.