In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

flash on 2010-11-15

キャラクターの自然な移動等
Get Adobe Flash player
by TmskSt 15 Nov 2010
/**
 * Copyright TmskSt ( http://wonderfl.net/user/TmskSt )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/8T8p
 */

package {
    
    [SWF(width="465", height="465")]
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    
    /** 
     * キャラクターの自然な移動等
     */
    public class Main extends Sprite {
        
        private var map:Map;
        private var sp:Shape;
        private var loader:Loader;
        
        public function Main() {
            this.addEventListener(Event.ADDED, init);
        }
        
        private function init(e:Event):void {
            this.removeEventListener(Event.ADDED, init);
            this.loadCompleted(null);
            
            //loader = new Loader();
            //loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loadCompleted);
            //loader.load(new URLRequest("image.png"));
        }
        
        private function loadCompleted(e:Event):void {
            
            var tmp:Sprite = new Sprite();
            tmp.graphics.beginFill(0x0);
            tmp.graphics.drawCircle(100, 100, 50);
            tmp.graphics.drawCircle(320, 220, 25);
            tmp.graphics.drawRect(250, 300, 200, 50);
            tmp.graphics.drawRect(120, 200, 50, 200);
            tmp.graphics.endFill();
            
            var bmd:BitmapData = new BitmapData(465, 465/*loader.width, loader.height*/);
            bmd.draw(tmp/*loader*/);
            var bitmap:Bitmap = new Bitmap(bmd);
            this.addChild(bitmap);
            
            sp = new Shape();
            this.addChild(sp);
            
            map = new Map(bitmap, 465, 465, 1);
            stage.addEventListener(MouseEvent.CLICK, check);
        }
        
        private function check(e:MouseEvent = null):void {
            
            var pp:Point = new Point(450, 50);
            var v:Vector.<Position> = map.findPath(pp.x, pp.y, mouseX, mouseY);
            
            sp.graphics.clear();
            sp.graphics.moveTo(pp.x, pp.y);
            
            for each(var p:Position in v) {
                sp.graphics.lineStyle(5, 0xFFFFFF * Math.random());
                sp.graphics.lineTo(p.x, p.y);
            }
        }
    }
    
}



import flash.display.Bitmap;
import flash.geom.Point;
class Map {
    
    /** */
    private var _obstacle:Bitmap;
    public function get obstacle():Bitmap { return _obstacle; }
    public function set obstacle(value:Bitmap):void {
        _obstacle = value;
    }
    
    /** */
    private var _width:Number;
    public function get width():Number { return _width; }
    public function set width(value:Number):void {
        _width = value;
    }
    
    /** */
    private var _height:Number;
    public function get height():Number { return _height; }
    public function set height(value:Number):void {
        _height = value;
    }
    
    /** */
    private var _sfSize:Number;
    public function get sfSize():Number { return _sfSize; }
    public function set sfSize(value:Number):void {
        _sfSize = value;
    }
    
    /** */
    private var _hSize:Number;
    public function get hSize():Number { return _hSize; }
    public function set hSize(value:Number):void {
        _hSize = value;
    }
    
    /** */
    private var _vSize:Number;
    public function get vSize():Number { return _vSize; }
    public function set vSize(value:Number):void {
        _vSize = value;
    }
    
    private const DIRECTIONS:Vector.<Direction> = Vector.<Direction>([
        new Direction(0, "__north_west",    -1,  -1    ),
        new Direction(1, "__west",          -1,   0    ),
        new Direction(2, "__south_west",    -1,   1    ),
        new Direction(3, "__south",          0,   1    ),
        new Direction(4, "__south_east",     1,   1    ),
        new Direction(5, "__east",           1,   0    ),
        new Direction(6, "__north_east",     1,  -1    ),
        new Direction(7, "__north",          0,  -1    )
    ]);
    
    
    /**
     *
     * @param    obstacleMC
     * @param    width
     * @param    height
     * @param    sfSize
     */
    public function Map($obstacle:Bitmap, $width:Number, $height:Number, $sfSize:Number) {
        this.obstacle = $obstacle;
        this.width = $width;
        this.height = $height;
        this.sfSize = $sfSize;
        this.hSize = Math.floor(width / sfSize);
        this.vSize = Math.floor(height / sfSize);
    }
    
    /**
     *
     * @param    nowX
     * @param    nowY
     * @param    distX
     * @param    distY
     * @return
     */
    public function findPath(nowX:Number, nowY:Number, distX:Number, distY:Number):Vector.<Position> {
        
        var result:Vector.<Position> = new Vector.<Position>();
        if ((distX < 0 || distX >= this.hSize || distY < 0 || distY >= this.vSize) || (distX == nowX && distY == nowY)) return result;
        
        result.push(new Position(nowX, nowY));
        var dist:Position = findStraightPath(nowX, nowY, distX, distY);
        if (dist.x != nowX || dist.y != nowY) { result.push(dist); }
        
        nowX = dist.x;
        nowY = dist.y;
        
        var prev:Link = new Link(-1, 0x7FFF), counter:int = 0;
        while (dist.x != distX || dist.y != distY) {
            var next:Direction = this.next(nowX, nowY, distX, distY, prev.distance);
            if (next == null) { break; }
            
            nowX += next.offsetX;
            nowY += next.offsetY;
            if (prev.dir == next.dir) { result.pop(); }
            
            result.push(new Position(nowX, nowY, next.dir));
            
            if (prev.dir != next.dir) {
                prev = next;
                dist = this.findStraightPath(nowX, nowY, distX, distY);
                if (Math.abs(dist.x - nowX) > 1 || Math.abs(dist.y - nowY) > 1) {
                    result.push(dist);
                    nowX = dist.x;
                    nowY = dist.y;
                    prev = new Link(dist.dir, 0x7FFF);
                }
            }
            
            if (++counter > 100) { break; }
        }
        
        return result;
    }
    
    /**
     *
     * @param    nowX
     * @param    nowY
     * @param    distX
     * @param    distY
     * @return
     */
    private function findStraightPath(nowX:Number, nowY:Number, distX:Number, distY:Number):Position {
        var atan:int = Math.round(4 * (1 + Math.atan2(distX - nowX, distY - nowY) / Math.PI) - 1);
        if(atan >= 8){ atan -= 8; }
        else if (atan <  0) { atan += 8; }
        
        var bp:Bresenham = new Bresenham(nowX, nowY, distX, distY);

        var px:Number = nowX, py:Number = nowY, pd:Number = 0, noobs:Boolean = true;
        for (var i:int = 0; i < bp.dist1; i++) {
            var lastpx:Number = px, lastpy:Number = py;
            pd += bp.dist2;
            if (pd >= bp.dist1) {
                pd -= bp.dist1;
                px += bp.addX2;
                py += bp.addY2;
            }
            px += bp.addX1;
            py += bp.addY1;
            
            if (this.isObstacle(px, py)) {
                distX = lastpx;
                distY = lastpy;
                break;
            }
        }
        
        return new Position(distX, distY, atan);
    }
    
    /**
     *
     * @param    xx
     * @param    yy
     * @return
     */
    private function isObstacle(xx:Number, yy:Number):Boolean {
        var pt:Point = this.obstacle.localToGlobal(new Point(xx, yy));
        return (this.obstacle.bitmapData.getPixel(pt.x, pt.y) == 0x0);
    }
    
    /**
     *
     * @param    x1
     * @param    y1
     * @param    x2
     * @param    y2
     * @param    ox
     * @param    oy
     * @return
     */
    private function distance(x1:Number, y1:Number, x2:Number, y2:Number, ox:Number, oy:Number):Number {
        return Math.pow(x2 - x1 - ox, 2) + Math.pow(y2 - y1 - oy, 2);
    }
    
    /**
     *
     * @param    nowX
     * @param    nowY
     * @param    distX
     * @param    distY
     * @param    oldDist
     * @return
     */
    private function next(nowX:Number, nowY:Number, distX:Number, distY:Number, oldDist:Number):Direction {
        var result:Direction;
        
        var minDist:Number = this.distance(nowX, nowY, distX, distY, 0, 0);
        if (minDist <= 2 && this.isObstacle(distX, distY)) { return null; }
        
        for (var i:int = 0; i < 8; i++) {
            var dir:Direction = DIRECTIONS[i];
            if (this.isObstacle(nowX + dir.offsetX, nowY + dir.offsetY)) { continue; }
            
            var dist:Number = this.distance(nowX, nowY, distX, distY, dir.offsetX, dir.offsetY);
            if (dist > minDist) { continue; }
            
            minDist = dist;
            result = dir;
            result.distance = minDist;
        }
        
        if (oldDist <= minDist) { return null; }
        return result;
    }
}

class Bresenham {
    
    /**
     *
     * @param    x1
     * @param    y1
     * @param    x2
     * @param    y2
     */
    public function Bresenham(x1:Number, y1:Number, x2:Number, y2:Number) {
        var addX:Number = 1;
        var dstX:Number = x2 - x1;
        if (dstX < 0) { dstX *= -1; addX = -1; }
        
        var addY:Number = 1;
        var dstY:Number = y2 - y1;
        if (dstY < 0) { dstY *= -1; addY = -1; }
        
        _dist1 = dstX;    _dist2 = dstY;
        _addX1 = addX;    _addX2 = 0;
        _addY1 = 0;        _addY2 = addY;
        
        if (dstX < dstY) {
            _dist1 = dstY; _dist2 = dstX;
            _addX1 = 0;    _addX2 = addX;
            _addY1 = addY; _addY2 = 0;
        }
    }
    
    private var _dist1:Number;
    public function get dist1():Number { return _dist1; }
    
    private var _dist2:Number;
    public function get dist2():Number { return _dist2; }
    
    private var _addX1:Number;
    public function get addX1():Number { return _addX1; }
    
    private var _addX2:Number;
    public function get addX2():Number { return _addX2; }
    
    private var _addY1:Number;
    public function get addY1():Number { return _addY1; }
    
    private var _addY2:Number;
    public function get addY2():Number { return _addY2; }
}

class Position {
    
    /**
     *
     * @param    $x
     * @param    $y
     * @param    $dir
     */
    public function Position($x:Number, $y:Number, $dir:Number = -1) {
        this.x = $x;
        this.y = $y;
        this.dir = $dir;
    }
    
    private var _x:Number;
    public function get x():Number { return _x; }
    public function set x(value:Number):void {
        _x = value;
    }
    
    private var _y:Number;
    public function get y():Number { return _y; }
    
    public function set y(value:Number):void {
        _y = value;
    }
    
    private var _dir:Number;
    public function get dir():Number { return _dir; }
    
    public function set dir(value:Number):void {
        _dir = value;
    }
}

class Link {
    
    /**
     *
     * @param    $dir
     * @param    $distance
     */
    public function Link($dir:int, $distance:uint) {
        this.dir = $dir;
        this.distance = $distance;
    }
    
    private var _dir:int;
    public function get dir():int { return _dir; }
    public function set dir(value:int):void {
        _dir = value;
    }
    
    private var _distance:uint;
    public function get distance():uint { return _distance; }
    public function set distance(value:uint):void {
        _distance = value;
    }
}

class Direction extends Link {
    
    /**
     *
     * @param    $dir
     * @param    $prop
     * @param    $offsetX
     * @param    $offsetY
     */
    public function Direction($dir:int, $prop:String, $offsetX:int, $offsetY:int) {
        super($dir, 0);
        _prop = $prop;
        _offsetX = $offsetX;
        _offsetY = $offsetY;
    }
    
    private var _prop:String;
    public function get prop():String { return _prop; }
    
    private var _offsetX:int;
    public function get offsetX():int { return _offsetX; }
    
    private var _offsetY:int;
    public function get offsetY():int { return _offsetY; }
}