diff --git a/src/as/com/threerings/stage/client/CharacterIsoSprite.as b/src/as/com/threerings/stage/client/CharacterIsoSprite.as index dc3ac350..ef966e20 100644 --- a/src/as/com/threerings/stage/client/CharacterIsoSprite.as +++ b/src/as/com/threerings/stage/client/CharacterIsoSprite.as @@ -22,7 +22,11 @@ package com.threerings.stage.client { import flash.display.DisplayObject; import flash.display.Sprite; +import com.threerings.cast.CharacterSprite; +import com.threerings.util.DirectionCodes; import com.threerings.media.Tickable; +import com.threerings.media.util.Path; +import com.threerings.media.util.Pathable; import com.threerings.miso.util.MisoSceneMetrics; import com.threerings.miso.util.MisoUtil; import com.threerings.stage.data.StageLocation; @@ -31,35 +35,43 @@ import as3isolib.display.IsoSprite; import as3isolib.graphics.SolidColorFill; public class CharacterIsoSprite extends IsoSprite + implements Pathable { public function CharacterIsoSprite (bodyOid :int, metrics :MisoSceneMetrics, - disp :DisplayObject) + charSprite :CharacterSprite) { _metrics = metrics; _bodyOid = bodyOid; setSize(1, 1, 2); + usePreciseValues = true; + // We wrap the sprite so we can shift it where we need it. Components like to line up // to the middle of a tile and as3isolib likes to line up to the back of a tile. var wrapper :Sprite = new Sprite(); wrapper.y = _metrics.tilehhei; - wrapper.addChild(disp); + wrapper.addChild(charSprite); - _character = disp; + _character = charSprite; sprites = [wrapper]; } public function tick (tickStamp :int) :void { - if (_character is Tickable) { - Tickable(_character).tick(tickStamp); + if (_path != null) { + if (_pathStamp == 0) { + _pathStamp = tickStamp + _path.init(this, _pathStamp); + } + _path.tick(this, tickStamp); } + _character.tick(tickStamp); } public function isMoving () :Boolean { - return false; //TODO Path + return _path != null; } public function getBodyOid () :int @@ -69,25 +81,97 @@ public class CharacterIsoSprite extends IsoSprite public function placeAtLoc (loc :StageLocation) :void { - moveTo(MisoUtil.fullToTile(loc.x), MisoUtil.fullToTile(loc.y), 0); - // TODO Components - handle orientation + setLocation(MisoUtil.fullToTile(loc.x), MisoUtil.fullToTile(loc.y)); + setOrientation(loc.orient); + } + + public function getX () :Number + { + return x; + } + + public function getY () :Number + { + return y; + } + + public function setLocation (x :Number, y :Number) :void + { + moveTo(x, y, 0); render(); } - public function move (path :Object /*TODO Path */) :void + public function setOrientation (orient :int) :void { - // TODO Path + _character.setOrientation(toIsoOrient(orient)); + render(); + } + + public function toIsoOrient (orient :int) :int + { + if (orient == DirectionCodes.NONE) { + return orient; + } else { + return (orient + 2) % 8; + } + } + + public function fromIsoOrient (orient :int) :int + { + if (orient == DirectionCodes.NONE) { + return orient; + } else { + return (orient + 6) % 8; + } + } + + public function getOrientation () :int + { + return fromIsoOrient(_character.getOrientation()); + } + + public function pathBeginning () :void + { + _character.pathBeginning(); + } + + public function pathCompleted (timestamp :int) :void + { + _character.pathCompleted(timestamp); + _path = null; + } + + public function move (path :Path) :void + { + // if there's a previous path, let it know that it's going away + cancelMove(); + + // save off this path + _path = path; + + // we'll initialize it on our next tick thanks to a zero path stamp + _pathStamp = 0; } public function cancelMove () :void { - // TODO Path + if (_path != null) { + var oldpath :Path = _path; + _path = null; + oldpath.wasRemoved(this); + } } protected var _bodyOid :int; protected var _metrics :MisoSceneMetrics; - protected var _character :DisplayObject; + protected var _character :CharacterSprite; + + /** Path we're currently following, if any. */ + protected var _path :Path; + + /** The time we started moving on our path. */ + protected var _pathStamp :int; } } \ No newline at end of file diff --git a/src/as/com/threerings/stage/client/CrowdStageScenePanel.as b/src/as/com/threerings/stage/client/CrowdStageScenePanel.as index 47bed9ce..70e01a90 100644 --- a/src/as/com/threerings/stage/client/CrowdStageScenePanel.as +++ b/src/as/com/threerings/stage/client/CrowdStageScenePanel.as @@ -27,11 +27,14 @@ import flash.geom.Rectangle; import flash.events.Event; import flash.events.MouseEvent; +import com.threerings.cast.CharacterSprite; import com.threerings.crowd.client.OccupantObserver; import com.threerings.crowd.data.OccupantInfo; import com.threerings.crowd.data.PlaceObject; import com.threerings.media.Tickable; +import com.threerings.media.util.LineSegmentPath; +import com.threerings.media.util.Path; import com.threerings.util.Controller; import com.threerings.util.Integer; import com.threerings.util.Iterator; @@ -77,8 +80,6 @@ public class CrowdStageScenePanel extends StageScenePanel _isoView.size.y*_isoView.size.y))); recomputeProximate(); - _vbounds = new Rectangle(0, 0, _isoView.size.x, _isoView.size.y); - addEventListener(Event.ADDED_TO_STAGE, addedToStage); addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage); } @@ -318,7 +319,7 @@ public class CrowdStageScenePanel extends StageScenePanel if (!isProximateToLoc(nloc)) { if (sprite != null) { // if they are visible, walk them to their new location - if (_vbounds.intersects(sprite.screenBounds)) { + if (_vbounds.intersects(sprite.getBounds(_isoView))) { moveSpriteToLoc(sprite, nloc.loc); } // now queue them up for removal on arrival as appropriate @@ -402,8 +403,9 @@ public class CrowdStageScenePanel extends StageScenePanel // if the source and destination are both offscreen, warp the // sprite to where they are going - var endsOff :Boolean = !_vbounds.contains(nx, ny); - if (!_vbounds.intersects(sprite.screenBounds) && endsOff) { + var sc :Point = _isoView.isoToLocal(new Pt(nx, ny, 0)); + var endsOff :Boolean = !_vbounds.contains(sc.x, sc.y); + if (!_vbounds.intersects(sprite.getBounds(_isoView)) && endsOff) { sprite.cancelMove(); sprite.placeAtLoc(loc); return true; @@ -417,6 +419,7 @@ public class CrowdStageScenePanel extends StageScenePanel (sprite == _selfSprite)) { log.info("Warp-a-saurus! " + StringUtil.toString(_vbounds) + " -> " + StringUtil.toCoordsString(loc.x, loc.y)); + sprite.cancelMove(); sprite.placeAtLoc(loc); @@ -427,11 +430,12 @@ public class CrowdStageScenePanel extends StageScenePanel // if we made it this far, we can actually try to compute a path // for this sprite; if the end of the path is off-screen, allow "partial" paths - var path :Object = null;//TODO Path TilePath = TilePath(getPath(yocs, nx, ny, endsOff)); + var path :LineSegmentPath = LineSegmentPath(getPath(sprite, nx, ny, endsOff)); if (path == null) { - /*TODO Path log.info("Unable to compute path from " + + log.info("Unable to compute path from " + StringUtil.toCoordsString(cx, cy) + " to " + - StringUtil.toCoordsString(loc.x, loc.y) + "; warping.");*/ + StringUtil.toCoordsString(nx, ny) + "; warping."); + sprite.cancelMove(); sprite.placeAtLoc(loc); return true; @@ -534,9 +538,6 @@ public class CrowdStageScenePanel extends StageScenePanel displayFeedback("m.cant_get_there"); } - // TODO Path - remove this - changeLocation(loc); - return; } @@ -586,12 +587,13 @@ public class CrowdStageScenePanel extends StageScenePanel protected function checkWalkToLoc (loc :StageLocation) :int { // obtain the screen coordinates of the location - var sc :Point = _isoView.isoToLocal(new Pt(loc.x, loc.y, 0)); + var lx :int = MisoUtil.fullToTile(loc.x); + var ly :int = MisoUtil.fullToTile(loc.y); + var us :CharacterIsoSprite = getSprite(myOid()); if (us != null) { - //TODO Path var path :TilePath = TilePath(getPath(us, loc.x, loc.y, false)); - //TODO Path return (path == null) ? -1 : path.getFinalOrientation(); - return -1; + var path :LineSegmentPath = LineSegmentPath(getPath(us, lx, ly, false)); + return (path == null) ? -1 : path.getFinalOrientation(); } else { return -1; } @@ -602,7 +604,7 @@ public class CrowdStageScenePanel extends StageScenePanel return new CharacterIsoSprite(info.getBodyOid(), _metrics, createCharacter(info)); } - protected function createCharacter (info :OccupantInfo) :DisplayObject + protected function createCharacter (info :OccupantInfo) :CharacterSprite { throw new Error("abstract"); } @@ -735,12 +737,10 @@ public class CrowdStageScenePanel extends StageScenePanel protected var _scObj :StageSceneObject; - protected var _vbounds :Rectangle; - /** Our sprite path velocity. */ // if we had more frames, maybe we could only update their // location when their frame changed. Alas, we do not. - protected static const SPRITE_PATH_VELOCITY :Number = 0.1; + protected static const SPRITE_PATH_VELOCITY :Number = 0.0025; } }