Log in
Please log in or register.
Pages: [1]
  Print  
Author Topic: slopes?  (Read 3304 times)
tamagokun
Newbie
*
Posts: 2


View Profile
« on: Thu, Jun 11, 2009 »

Is there any intention to support sloped blocks in future releases? That's definitely a hard implementation that would totally top-off such a great framework.
Logged
Adam Atomic
Administrator
Hero Member
*****
Posts: 724


hostest w/ the mostest


View Profile WWW
« Reply #1 on: Thu, Jun 11, 2009 »

flixel will not officially support sloped surfaces anytime soon, however I'm hoping to be able to kind of collect unofficial modifications or additions to the framework in some kind of official way here on the forums, so that stuff that I personally feel falls outside the scope of flixel itself can still be available to the community
Logged

lechuckgl
Jr. Member
**
Posts: 77


View Profile
« Reply #2 on: Fri, Jun 12, 2009 »

Well, 45° slopes are very easy to implement, but you'll need a tileBlock with just 1 tile to make it work.
Logged
tamagokun
Newbie
*
Posts: 2


View Profile
« Reply #3 on: Sat, Jun 13, 2009 »

i've implemented slope walking on previous game projects, and it worked fairly well. Basically, any tile that was sloped, the angle of the slope had to go from one corner of the bounds of the image to the other corner, and then the engine could calculate where the player should be based on the width/height of the tile.

I might have to try that same approach again
Logged
failrate
Jr. Member
**
Posts: 52



View Profile WWW
« Reply #4 on: Sat, Jun 13, 2009 »

You can currently do slopes in an expensive manner with base flixel by having a series of small boxes ( I think the threshold may be one or two pixels ).

A more sophisticated stair-step approach would be to determine a threshold ( say, 4 pixels ), and if your sprite hitWall() but doesn't collidePoint with a block 4 pixels above your sprite's feet, then you can move the sprite on top of the block.
Something like :
Code:
override function hitWall():Boolean
{
if ( velocity.x > 0 )
{
   if (!collidePoint(x+width+velocity.x, y+height-4))
  {
     y -= 4;
  }
}
else if ( velocity.x < 0 )
{
   if (!collidePoint(x+velocity.x, y+height-4))
  {
     y -= 4;
  }
}

return true;
}

Now, I'm sure there's errors in that code, but I hope it conveys the idea.

@lechuckgl: If you've implemented slopes in a tile-based system before, please share some pseudocode on how you'd implement it in flixel.
Logged
lechuckgl
Jr. Member
**
Posts: 77


View Profile
« Reply #5 on: Fri, Jun 19, 2009 »

Well, it's not hard. tamagokun explained the concept.

You just have to know that you are colliding with a sloped tile and the slope's direction. Then, you add to the player's vertical position how far from the edge of tile he is ( if the tile slope goes up you add, if it goes down you substract ).



The math would be something like:

player.y = tile.y + player.height +  ( tile.x + tile.width - player.x )slope going up

player.y = tile.y + player.height +  ( tile.x - player.x )slope going down

Keep in mid that player.x should be player.CENTERX , in other words : player.x + player.width/2  ( asuming player.x is located on the top left corner of the player's sprite ). Asuming that, you should also heck if the player's CENTERX is located over the sloped tile before adjusting player.y value.

I'll try to figure out if there is any "elegant" solution for this problem using blocks instead of tiles.
Logged
failrate
Jr. Member
**
Posts: 52



View Profile WWW
« Reply #6 on: Fri, Jun 19, 2009 »

Well, assuming a special kind of "slope block", you can first test against the rectangular volume, since that's cheaper.  If that passes, then you can do the additional calculation for the slope.

I see two problems with your approach, though.

- It looks like you're clamping the player sprite to the sloped surface if it's within the tile boundary, but that's not always valid.  A player sprite could enter the tile/block boundary without actually hitting the sloped surface.
- You don't account for angles greater or less than 45 degrees.  If you keep the slopes in the range of 1 ~179 degrees, then you could use the slope formula ( y = mx + b ) to determine the floor height at any x position on the slope tile/block.
Logged
darthlupi
Full Member
***
Posts: 209


All Smiles


View Profile WWW
« Reply #7 on: Fri, Jul 17, 2009 »

Hello,

   I finished my proof of concept for incorporating sloped FLOORS within Flixel.  The way it works is pretty simplistic ( read single purpose ):

http://darthlupi.com/projects/Wonder_Palm/slope_test/

1. This is the class that was built off of FlxBlock.  It creates the slope based on the upper left coordinate you specify, the upper right coordinates you specify, the Height of slope's block, and finally the image you wish to use as your "skin" for the slope.

Code:
package com.adamatomic.flixel
{
import com.adamatomic.flixel.data.FlxCore;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.display.Sprite;
import flash.events.*;

//@desc Wonky proof of concept for slopes in the framework...
public class FlxSlopeBlock extends FlxCore
{

public function FlxSlopeBlock(X1:int,Y1:int,X2:int,Y2:int,tHeight:uint,TileGraphic:Class)
{
super();
x = X1;
y = Y1;
//Get the width
//width = 100;
if (X1 > X2)
{
width = X1 - X2;
X1 = width;
X2 = 0;
}
else
{
width = X2 - X1;
X1 = 0;
X2 = width;
}
//Get the height

if (Y1 > Y2)
{
y = Y2; //Make sure the block is drawn on the right side y since that is the high point
height = Math.abs(Y1 - Y2) + tHeight;
Y1 = Math.abs(Y1 - Y2);
Y2 = 0;
}
else
{

height = Math.abs(Y2 - Y1) + tHeight;
Y2 = Math.abs(Y1 - Y2);
Y1 = 0;

}

if(TileGraphic == null)
return;
_p = new Point()
_pixels = FlxG.addBitmap(TileGraphic);
_rect = new BitmapData(width, height, true, 0x0);
_rect.draw(draw_poly(X1, Y1, X2, Y2, X2, Y2 + tHeight, X1, Y1 + tHeight, _pixels));
}

//@desc Draws this block
override public function render():void
{
super.render();
getScreenXY(_p);
_p.x = x;
_p.y = y;
FlxG.buffer.copyPixels(_rect, new Rectangle(0,0,width,height), _p, null, null, true);
}

////////////////////
//Draw the polygon
////////////////////
private function draw_poly(pX1:int, pY1:int, pX2:int, pY2:int, pX3:int, pY3:int, pX4:int, pY4:int,image:BitmapData ):Sprite
{
var the_square:Sprite = new Sprite();
//this.addChild(the_square);
//the_square.graphics.beginFill(0x0000FF);
the_square.graphics.beginBitmapFill(image );
the_square.graphics.moveTo(pX1,pY1);//Start of new line
the_square.graphics.lineTo(pX2,pY2);//End of new line
the_square.graphics.lineTo(pX3,pY3);//End of new line
the_square.graphics.lineTo(pX4,pY4);//End of new line
the_square.graphics.endFill();
return the_square;
}

////////////////////
//Collisions
////////////////////
public function prefectCollideSlope(Spr:FlxSprite):void
{
//This function checks pixel perfect against the Sprite and the Block
//I've opted to check by a point vs the entire sprite - should be a little quicker
//The collisions work, but they need a LOT of work on the after effect on the sprite.
var xcheck:Number = Spr.width * 0.5;
var ycheck:Number = Spr.height;
var xadder:Number = 0;
var yadder:Number = -0.1;
var col:Boolean = false;
//Moving up away from collision
if (
_rect.hitTest(new Point(x,y),1,new Point(Spr.x + xcheck, Spr.y + ycheck)
))
{
Spr.y -= Spr.velocity.y * FlxG.elapsed;
Spr.velocity.y = 0;
col = true;
while( _rect.hitTest(new Point(x,y),1,new Point(Spr.x + xcheck, Spr.y + ycheck)))
{
Spr.y += yadder;
Spr.x += xadder;
}
}
//Moving down toward collision
if ( col == false && Spr.velocity.y > 0) //Don't do this if collisions have been handled
{
//Decrease the ii_increment to have the object check in smaller steps - small = slower
var ii_increment:Number = 0.2;
//How far down the slope to check - bigger = slower
var ii_how_far:Number = 2;
for (var ii:Number = 0; ii < ii_how_far; ii += ii_increment)
{
if (_rect.hitTest(new Point(x,y),1,new Point(Spr.x + xcheck, Spr.y + ycheck + ii)
))
{
Spr.y += ii - ii_increment; //Ok, collision now go back one increment and hope for the best
Spr.velocity.y = 0;
ii = 9999;
}
}
}
} //End of collision function
static public function collideSlopeArray(Blocks:FlxArray,Sprite:FlxSprite):void
{
if((Sprite == null) || !Sprite.exists || Sprite.dead) return;
for(var i:uint = 0; i < Blocks.length; i++)
Blocks[i].prefectCollideSlope(Sprite);
}

}
}


Next you are going to want to create some sloped blocks to play with in your the flixel state o' your preference:

1. Put this jive in your constructor:

Code:
#As normal create a flixel array to store your class's reference in or what ever the right term is
private var _blocks:FlxArray;
#Add your blocks
_blocks.add(this.add(new FlxSlopeBlock(0, 0, 240, 80, 32, ImgTech2) ) );
_blocks.add(this.add(new FlxSlopeBlock(20, 100, 220, 32, 32, ImgTech2) ) );
_blocks.add(this.add(new FlxSlopeBlock(220, 32, 320, 90, 32, ImgTech2) ) );

2. Slap this in the update function of the constructor for collisions:

Code:
FlxSlopeBlock.collideSlopeArray(_blocks, _player);

DISCLAIMER:  The collision is really wonky and pretty cpu intensive if you have a lot of slopes.  Also there is no collideSlopeArrays built in yet.  That, however would be pretty easy to wip together.  

Also, there is no support for ceilings.  Floors only right now, and you may have to tweak the settings in the prefectCollideSlope function.  Yes it's miss spelled, and yes I will lose sleep over it.  Functions will need to be built or existing needs to be tweaked to allow for bullets etc.

For now I am done playing with this and works for what I will need when I need it, so feel free to add subtract or multiple to this thing.  Just don't divide.
« Last Edit: Fri, Jul 17, 2009 by darthlupi » Logged

To take care of that not so fresh feeling: #flixel on irc.freenode.net.

Use your favorite IRC client or  http://webchat.freenode.net/
PlayOrDie
Full Member
***
Posts: 151


Game Over


View Profile
« Reply #8 on: Wed, Nov 18, 2009 »

Nice, this is exactly what I was looking for.  Thanks, Darthlupi Smiley
Logged

Make it work reliably and fast.
Donald Lebeau - Gauntlet
caspervanest
Newbie
*
Posts: 15


View Profile
« Reply #9 on: Thu, Nov 19, 2009 »

Thanks for sharing this darthlupi!

Your code didn't run at first, but after moving around some stuff it works perfectly. I guess maybe it's not compatible with v1.25 or something. But anyway, it works, yay!
Logged
darthlupi
Full Member
***
Posts: 209


All Smiles


View Profile WWW
« Reply #10 on: Fri, Nov 20, 2009 »

Glad it helped some!  Again, it needs some serious loving before it can be called anything close to optimized.  It sure would be fun if a smart person made it run nicely!
Logged

To take care of that not so fresh feeling: #flixel on irc.freenode.net.

Use your favorite IRC client or  http://webchat.freenode.net/
risko
Newbie
*
Posts: 3


View Profile
« Reply #11 on: Tue, Dec 22, 2009 »

Thank you for sharing your code darthlupi! It works after few touches without problems also in 1.47 and it ist not that cpu demanding as i thought. I tested it with 200 platforms on my map (not many of them really painted on the 320x240 part of my level in any frame) without really noticing it. I have experienced some problems on the boarders of such tiles and normal tiles, but i will see what will happen if i will use just this kind of tiles. Maybe it will be applicable at least for some smaller levels.
Thanks a lot!
Logged
Pages: [1]
  Print  
 
Jump to: