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.
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:
#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:
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.