public FlxTilemap() : base() { auto = OFF; widthInTiles = 0; heightInTiles = 0; totalTiles = 0; tileGraphic = null; _rects = null; _tiles = null; _tileObjectsForDrawing = new List<FlxTile>(); _tileObjects = null; _tileWidth = 0; _tileHeight = 0; immovable = true; _block = new FlxObject(); _block.width = _block.height = 0; _block.immovable = true; _startingIndex = 0; collideIndex = 1; allowCollisions = ANY; ID = 3; }
/** * Clean up memory. */ public void destroy() { Object = null; if(next != null) next.destroy(); next = null; }
public FlxCamera(float X, float Y, float Width, float Height, float Zoom = 1.0f) : base() { x = X; y = Y; width = Width; height = Height; defaultZoom = 1.0f; rotating = 0.0f; scroll = new FlxPoint(); _point = new FlxPoint(); target = null; deadzone = null; bounds = null; zooming = Zoom; _fxShakeIntensity = 0; _fxShakeDuration = 0; _fxShakeComplete = null; _fxShakeOffset = new FlxPoint(); _fxShakeDirection = 0; }
/// <summary> /// The main collision resolution function /// </summary> /// <param name="Object1"></param> /// <param name="Object2"></param> /// <returns></returns> public static bool separate(FlxObject Object1, FlxObject Object2) { bool separatedX = separateX(Object1,Object2); bool separatedY = separateY(Object1,Object2); return separatedX || separatedY; }
/// <summary> /// Returns true if the two FlxObjects overlap. Optional Callback function of return type bool with two FlxObject parameters will be called if true. /// </summary> /// <param name="ObjectOrGroup1"></param> /// <param name="ObjectOrGroup2"></param> /// <param name="NotifyCallback"></param> /// <param name="ProcessCallback"></param> /// <returns></returns> public static Boolean overlap(FlxObject ObjectOrGroup1 = null, FlxObject ObjectOrGroup2 = null, Func<FlxObject, FlxObject, Boolean> NotifyCallback = null, Func<FlxObject, FlxObject, Boolean> ProcessCallback = null) { if(ObjectOrGroup1 == null) ObjectOrGroup1 = FlxG.state; if(ObjectOrGroup2 == ObjectOrGroup1) ObjectOrGroup2 = null; FlxQuadTree.divisions = FlxG.worldDivisions; FlxQuadTree quadTree = new FlxQuadTree(FlxG.worldBounds.x,FlxG.worldBounds.y,FlxG.worldBounds.width,FlxG.worldBounds.height); quadTree.load(ObjectOrGroup1,ObjectOrGroup2,NotifyCallback,ProcessCallback); Boolean result = quadTree.execute(); quadTree.destroy(); return result; }
/// <summary> /// Returns true if the two FlxObjects collide. Optional callback function of return type bool with two FlxObject parameters will be called if true. /// </summary> /// <param name="ObjectOrGroup1"></param> /// <param name="ObjectOrGroup2"></param> /// <param name="NotifyCallback"></param> /// <returns></returns> public static Boolean collide(FlxObject ObjectOrGroup1 = null, FlxObject ObjectOrGroup2 = null, Func<FlxObject, FlxObject, Boolean> NotifyCallback = null) { return overlap(ObjectOrGroup1,ObjectOrGroup2,NotifyCallback,FlxObject.separate); }
/// <summary> /// Make the camera follow an object with a specified follow-style /// </summary> /// <param name="Target"></param> /// <param name="Style"></param> public void follow(FlxObject Target, uint Style=STYLE_LOCKON) { target = Target; float helper, w, h; switch (Style) { case STYLE_PLATFORMER: w = width / 8; h = height / 3; deadzone = new FlxRect((width - w) / 2, (height - h) / 2 - h * 0.25f, w, h); break; case STYLE_TOPDOWN: helper = FlxU.max(width, height) / 3; deadzone = new FlxRect((width - helper) / 3, (height - helper) / 3, helper, helper); break; case STYLE_TOPDOWN_TIGHT: helper = FlxU.max(width, height) / 12; deadzone = new FlxRect((width - helper) / 2, (height - helper) / 2, helper, helper); break; case STYLE_LOCKON: break; case STYLE_LOOSE: deadzone = new FlxRect(0, 0, width, height); break; default: deadzone = null; break; } }
/** * Creates a new link, and sets <code>object</code> and <code>next</code> to <code>null</code>. */ public FlxList() { Object = null; next = null; }
protected void createSound() { destroy(); x = 0; y = 0; playCount = 0; _sound = null; _position = 0; _volume = 1.0f; _volumeAdjust = 1.0f; _looped = false; _target = null; _source = null; _radius = 0; _pan = false; _fadeOutTimer = 0; _fadeOutTotal = 0; _pauseOnFadeOut = false; _fadeInTimer = 0; _fadeInTotal = 0; exists = true; active = true; visible = false; name = null; artist = null; amplitude = 0; amplitudeLeft = 0; amplitudeRight = 0; autoDestroy = false; _followTarget = false; proximitized = false; }
/** * Call this function if you want this sound's volume to change * based on distance from a particular FlxCore object. * * @param X The X position of the sound. * @param Y The Y position of the sound. * @param Object The object you want to track. * @param Radius The maximum distance this sound can travel. * @param Pan Whether the sound should pan in addition to the volume changes (default: true). * * @return This FlxSound instance (nice for chaining stuff together, if you're into that). */ public FlxSound proximity(FlxObject Source, FlxObject Target, float Radius) { x = Source.x; y = Source.y; _target = Target; _source = Source; _radius = Radius; _followTarget = true; proximitized = true; return this; }
/** * Clean up memory. */ public override void destroy() { kill(); //_transform = null; _sound = null; //_channel = null; _target = null; name = null; artist = null; base.destroy(); }
/** * Change the emitter's midpoint to match the midpoint of a <code>FlxObject</code>. * * @param Object The <code>FlxObject</code> that you want to sync up with. */ public void at(FlxObject Object) { Object.getMidpoint(_point); x = _point.x - (Convert.ToInt32(width)>>1); y = _point.y - (Convert.ToInt32(height)>>1); }
/** * Creates a new <code>FlxEmitter</code> object at a specific position. * Does NOT automatically generate or attach particles! * * @param X The X position of the emitter. * @param Y The Y position of the emitter. * @param Size Optional, specifies a maximum capacity for this emitter. */ public FlxEmitter(float X=0, float Y=0, uint Size=0, FlxObject Target=null) : base(Size) { //super(Size); x = X; y = Y; width = 0; height = 0; minParticleSpeed = new FlxPoint(-100,-100); maxParticleSpeed = new FlxPoint(100,100); minRotation = -360; maxRotation = 360; gravity = 0; particleClass = null; particleDrag = new FlxPoint(); frequency = 0.1f; lifespan = 3; bounce = 0; _quantity = 0; _counter = 0; _explode = true; on = false; _point = new FlxPoint(); target = Target; }
/// <summary> /// X-axis component of the object separation process /// </summary> /// <param name="Object1"></param> /// <param name="Object2"></param> /// <returns></returns> public static bool separateX(FlxObject Object1, FlxObject Object2) { //can't separate two immovable objects bool obj1immovable = Object1.immovable; bool obj2immovable = Object2.immovable; if(obj1immovable && obj2immovable) return false; //If one of the objects is a tilemap, just pass it off. if (Object1 is FlxTilemap) return (Object1 as FlxTilemap).overlapsWithCallback(Object2, separateX); if (Object2 is FlxTilemap) return (Object2 as FlxTilemap).overlapsWithCallback(Object1, separateX, true); //First, get the two object deltas float overlap = 0; float obj1delta = Object1.x - Object1.last.x; float obj2delta = Object2.x - Object2.last.x; if(obj1delta != obj2delta) { //Check if the X hulls actually overlap float obj1deltaAbs = (obj1delta > 0) ? obj1delta : -obj1delta; float obj2deltaAbs = (obj2delta > 0) ? obj2delta : -obj2delta; FlxRect obj1rect = new FlxRect(Object1.x-((obj1delta > 0)?obj1delta:0),Object1.last.y,Object1.width+((obj1delta > 0)?obj1delta:-obj1delta),Object1.height); FlxRect obj2rect = new FlxRect(Object2.x-((obj2delta > 0)?obj2delta:0),Object2.last.y,Object2.width+((obj2delta > 0)?obj2delta:-obj2delta),Object2.height); if((obj1rect.x + obj1rect.width > obj2rect.x) && (obj1rect.x < obj2rect.x + obj2rect.width) && (obj1rect.y + obj1rect.height > obj2rect.y) && (obj1rect.y < obj2rect.y + obj2rect.height)) { float maxOverlap = obj1deltaAbs + obj2deltaAbs + OVERLAP_BIAS; //If they did overlap (and can), figure out by how much and flip the corresponding flags if(obj1delta > obj2delta) { overlap = Object1.x + Object1.width - Object2.x; if((overlap > maxOverlap) || !Convert.ToBoolean(Object1.allowCollisions & RIGHT) || !Convert.ToBoolean(Object2.allowCollisions & LEFT)) overlap = 0; else { Object1.touching |= RIGHT; Object2.touching |= LEFT; } } else if(obj1delta < obj2delta) { overlap = Object1.x - Object2.width - Object2.x; if((-overlap > maxOverlap) || !Convert.ToBoolean(Object1.allowCollisions & LEFT) || !Convert.ToBoolean(Object2.allowCollisions & RIGHT)) overlap = 0; else { Object1.touching |= LEFT; Object2.touching |= RIGHT; } } } } //Then adjust their positions and velocities accordingly (if there was any overlap) if(overlap != 0) { float obj1v = Object1.velocity.x; float obj2v = Object2.velocity.x; if(!obj1immovable && !obj2immovable) { overlap *= 0.5f; Object1.x = Object1.x - overlap; Object2.x += overlap; float obj1velocity = (float)Math.Sqrt((obj2v * obj2v * Object2.mass) / Object1.mass) * ((obj2v > 0) ? 1f : -1f); float obj2velocity = (float)Math.Sqrt((obj1v * obj1v * Object1.mass) / Object2.mass) * ((obj1v > 0) ? 1f : -1f); float average = (obj1velocity + obj2velocity) * 0.5f; obj1velocity -= average; obj2velocity -= average; Object1.velocity.x = average + obj1velocity * Object1.elasticity; Object2.velocity.x = average + obj2velocity * Object2.elasticity; } else if(!obj1immovable) { Object1.x = Object1.x - overlap; Object1.velocity.x = obj2v - obj1v*Object1.elasticity; } else if(!obj2immovable) { Object2.x += overlap; Object2.velocity.x = obj1v - obj2v*Object2.elasticity; } return true; } else return false; }
// overlapsWithCallBack public Boolean overlapsWithCallback(FlxObject Object, Func<FlxObject, FlxObject, Boolean> Callback=null, Boolean FlipCallbackParams=false, FlxPoint Position=null) { Boolean results = false; float X = x; float Y = y; if (Position != null) { X = Position.x; Y = Position.x; } //Figure out what tiles we need to check against int selectionX = (int)FlxU.floor((Object.x - X) / _tileWidth); int selectionY = (int)FlxU.floor((Object.y - Y) / _tileHeight); uint selectionWidth = (uint)(selectionX + (FlxU.ceil((int)Object.width / _tileWidth)) + 2); uint selectionHeight = (uint)(selectionY + (FlxU.ceil((int)Object.height / _tileHeight)) + 2); //Then bound these coordinates by the map edges if (selectionX < 0) selectionX = 0; if (selectionY < 0) selectionY = 0; if (selectionWidth > widthInTiles) selectionWidth = (uint)widthInTiles; if (selectionHeight > heightInTiles) selectionHeight = (uint)heightInTiles; //Then loop through this selection of tiles and call FlxObject.separate() accordingly uint rowStart = (uint)selectionY * (uint)widthInTiles; uint row = (uint)selectionY; uint column; FlxTile tile; Boolean overlapFound; float deltaX = X - last.x; float deltaY = Y - last.y; while (row < selectionHeight) { column = (uint)selectionX; while (column < selectionWidth) { overlapFound = false; tile = _tileObjects[(int)_data[(int)(rowStart+column)]] as FlxTile; if ( Convert.ToBoolean(tile.allowCollisions) ) { tile.x = X + (int)column * _tileWidth; tile.y = Y + (int)row * _tileHeight; tile.last.x = tile.x - deltaX; tile.last.y = tile.y - deltaY; if (Callback != null) { if (FlipCallbackParams) overlapFound = Callback(Object, tile); else overlapFound = Callback(tile, Object); } else { overlapFound = (Object.x + Object.width > tile.x) && (Object.x < tile.x + tile.width) && (Object.y + Object.height > tile.y) && (Object.y < tile.y + tile.height); } if (overlapFound) { if ((tile.callback != null)) { tile.mapIndex = (uint)rowStart + column; tile.callback(tile, Object); } results = true; } } else if ((tile.callback != null)) { tile.mapIndex = (uint)rowStart + (uint)column; tile.callback(tile, Object); } column++; } rowStart += (uint)widthInTiles; row++; } return results; }
/// <summary> /// Y-axis component of the object separation process /// </summary> /// <param name="Object1"></param> /// <param name="Object2"></param> /// <returns></returns> public static bool separateY(FlxObject Object1, FlxObject Object2) { //can't separate two immovable objects bool obj1immovable = Object1.immovable; bool obj2immovable = Object2.immovable; if(obj1immovable && obj2immovable) return false; ////If one of the objects is a tilemap, just pass it off. if (Object1 is FlxTilemap) return (Object1 as FlxTilemap).overlapsWithCallback(Object2, separateY); if (Object2 is FlxTilemap) return (Object2 as FlxTilemap).overlapsWithCallback(Object1, separateY, true); //First, get the two object deltas float overlap = 0; float obj1delta = Object1.y - Object1.last.y; float obj2delta = Object2.y - Object2.last.y; if(obj1delta != obj2delta) { //Check if the Y hulls actually overlap float obj1deltaAbs = (obj1delta > 0) ? obj1delta : -obj1delta; float obj2deltaAbs = (obj2delta > 0) ? obj2delta : -obj2delta; FlxRect obj1rect = new FlxRect(Object1.x,Object1.y-((obj1delta > 0)?obj1delta:0),Object1.width,Object1.height+obj1deltaAbs); FlxRect obj2rect = new FlxRect(Object2.x,Object2.y-((obj2delta > 0)?obj2delta:0),Object2.width,Object2.height+obj2deltaAbs); if((obj1rect.x + obj1rect.width > obj2rect.x) && (obj1rect.x < obj2rect.x + obj2rect.width) && (obj1rect.y + obj1rect.height > obj2rect.y) && (obj1rect.y < obj2rect.y + obj2rect.height)) { float maxOverlap = obj1deltaAbs + obj2deltaAbs + OVERLAP_BIAS; //If they did overlap (and can), figure out by how much and flip the corresponding flags if(obj1delta > obj2delta) { overlap = Object1.y + Object1.height - Object2.y; if((overlap > maxOverlap) || !Convert.ToBoolean(Object1.allowCollisions & DOWN) || !Convert.ToBoolean(Object2.allowCollisions & UP)) overlap = 0; else { Object1.touching |= DOWN; Object2.touching |= UP; } } else if(obj1delta < obj2delta) { overlap = Object1.y - Object2.height - Object2.y; if((-overlap > maxOverlap) || !Convert.ToBoolean(Object1.allowCollisions & UP) || !Convert.ToBoolean(Object2.allowCollisions & DOWN)) overlap = 0; else { Object1.touching |= UP; Object2.touching |= DOWN; } } } } //Then adjust their positions and velocities accordingly (if there was any overlap) if(overlap != 0) { float obj1v = Object1.velocity.y; float obj2v = Object2.velocity.y; if(!obj1immovable && !obj2immovable) { overlap *= 0.5f; Object1.y = Object1.y - overlap; Object2.y += overlap; float obj1velocity = (float)Math.Sqrt((obj2v * obj2v * Object2.mass) / Object1.mass) * ((obj2v > 0) ? 1f : -1f); float obj2velocity = (float)Math.Sqrt((obj1v * obj1v * Object1.mass) / Object2.mass) * ((obj1v > 0) ? 1f : -1f); float average = (obj1velocity + obj2velocity) * 0.5f; obj1velocity -= average; obj2velocity -= average; Object1.velocity.y = average + obj1velocity * Object1.elasticity; Object2.velocity.y = average + obj2velocity * Object2.elasticity; } else if(!obj1immovable) { Object1.y = Object1.y - overlap; Object1.velocity.y = obj2v - obj1v*Object1.elasticity; //This is special case code that handles cases like horizontal moving platforms you can ride if(Object2.active && Object2.moves && (obj1delta > obj2delta)) Object1.x += Object2.x - Object2.last.x; } else if(!obj2immovable) { Object2.y += overlap; Object2.velocity.y = obj1v - obj2v*Object2.elasticity; //This is special case code that handles cases like horizontal moving platforms you can ride if(Object1.active && Object1.moves && (obj1delta < obj2delta)) Object2.x += Object1.x - Object1.last.x; } return true; } else return false; }
// overlapsWithCallBack public Boolean overlapsWithCallback(FlxObject Object, Func <FlxObject, FlxObject, Boolean> Callback = null, Boolean FlipCallbackParams = false, FlxPoint Position = null) { Boolean results = false; float X = base.X; float Y = base.Y; if (Position != null) { X = Position.X; Y = Position.X; } //Figure out what tiles we need to check against int selectionX = (int)FlxU.floor((Object.X - X) / _tileWidth); int selectionY = (int)FlxU.floor((Object.Y - Y) / _tileHeight); uint selectionWidth = (uint)(selectionX + (FlxU.ceil((int)Object.Width / _tileWidth)) + 2); uint selectionHeight = (uint)(selectionY + (FlxU.ceil((int)Object.Height / _tileHeight)) + 2); //Then bound these coordinates by the map edges if (selectionX < 0) { selectionX = 0; } if (selectionY < 0) { selectionY = 0; } if (selectionWidth > widthInTiles) { selectionWidth = (uint)widthInTiles; } if (selectionHeight > heightInTiles) { selectionHeight = (uint)heightInTiles; } //Then loop through this selection of tiles and call FlxObject.separate() accordingly uint rowStart = (uint)selectionY * (uint)widthInTiles; uint row = (uint)selectionY; uint column; FlxTile tile; Boolean overlapFound; float deltaX = X - Last.X; float deltaY = Y - Last.Y; while (row < selectionHeight) { column = (uint)selectionX; while (column < selectionWidth) { overlapFound = false; tile = _tileObjects[(int)_data[(int)(rowStart + column)]] as FlxTile; if (Convert.ToBoolean(tile.AllowCollisions)) { tile.X = X + (int)column * _tileWidth; tile.Y = Y + (int)row * _tileHeight; tile.Last.X = tile.X - deltaX; tile.Last.Y = tile.Y - deltaY; if (Callback != null) { if (FlipCallbackParams) { overlapFound = Callback(Object, tile); } else { overlapFound = Callback(tile, Object); } } else { overlapFound = (Object.X + Object.Width > tile.X) && (Object.X < tile.X + tile.Width) && (Object.Y + Object.Height > tile.Y) && (Object.Y < tile.Y + tile.Height); } if (overlapFound) { if ((tile.callback != null)) { tile.mapIndex = (uint)rowStart + column; tile.callback(tile, Object); } results = true; } } else if ((tile.callback != null)) { tile.mapIndex = (uint)rowStart + (uint)column; tile.callback(tile, Object); } column++; } rowStart += (uint)widthInTiles; row++; } return(results); }