Brush Pattern
2d brush pattern for 2d games
♥0 |
Line 229 |
Modified 2014-05-06 04:25:59 |
MIT License
archived:2017-03-20 11:45:21
| (replaced)
Related images
ActionScript3 source code
/**
* Copyright NewKrok ( http://wonderfl.net/user/NewKrok )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/kRcG
*/
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLRequest;
import flash.system.LoaderContext;
public class test extends Sprite {
private const TEXTURE_URL:String = "http://assets.wonderfl.net/images/related_images/1/13/13f7/13f73c8fb2b8cd3e291c6c63c44c42ffa722ebe2m";
private const TEST_MAP:String = "49<164<72<152&72<152<100<155&100<155<163<141&163<141<202<117&202<117<252<74&252<74<293<51&293<51<347<50&347<50<385<79&385<79<419<114&419<114<431<161&431<161<428<224&428<224<400<288&400<288<340<308&340<308<281<291&281<291<258<222&258<222<204<214&204<214<162<255&162<255<99<328&99<328<66<298&66<298<35<245&35<245<90<200&90<200<49<164";
public function test () :void {
loadImage ( TEXTURE_URL, loaded );
}
private function loadImage ( $url:String, $onComplete:Function ) :void {
var imageLoader:Loader = new Loader ();
imageLoader.contentLoaderInfo.addEventListener ( Event.COMPLETE, $onComplete );
var image:URLRequest = new URLRequest ( $url );
imageLoader.load ( image, new LoaderContext ( true ) );
}
private function loaded ( event:Event ) :void {
var texture:BitmapData = new BitmapData ( event.currentTarget.content.width, event.currentTarget.content.height, true, 0x60 );
texture.draw ( event.currentTarget.content );
addChild ( new BrushPattern ( TEST_MAP, texture ) );
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.TriangleCulling;
import flash.geom.Point;
import flash.events.Event;
import flash.events.MouseEvent;
class BrushPattern extends Sprite {
private var linePoints: Array = new Array();
private var linePointsInput: Array = new Array();
private var holder: Sprite = new Sprite();
private var holderS: Sprite = new Sprite();
private var g: Graphics;
private var _fillBack: Sprite = new Sprite;
private var vertices: Vector.<Number>;
private var indices: Vector.<int> ;
private var uvtData: Vector.<Number>;
private var terrainTexture: BitmapData;
private var lastLength: Number = 0;
private var segLength: Number = 0;
private var _view: Bitmap;
public function BrushPattern ( $map:String, $texture:BitmapData ) {
terrainTexture = $texture;
$map = renderPreProcess ( $map, 72, 72 );
g = holderS.graphics;
_fillBack.graphics.lineStyle ( 1, 0, 1 );
holder.addChild ( _fillBack );
holder.addChild ( holderS );
var mapPieces:Array = $map.split ( "|" );
for ( var j:uint = 0; j < mapPieces.length; j++ ) {
var tmp:Array = mapPieces[j].split ( "&" );
for ( var i:uint = 0; i < tmp.length; i++ ) {
var tmp2:Array = tmp[i].split ( "<" );
if ( i == 0 )
_fillBack.graphics.moveTo ( tmp2[0], tmp2[1] );
if ( j == 0 && i == 0 )
_fillBack.graphics.moveTo ( tmp2[0], tmp2[1] );
else if ( tmp2.length > 1 )
_fillBack.graphics.lineTo ( tmp2[0], tmp2[1] );
if ( i == 0 ) {
var lp:LinePoint = new LinePoint ( tmp2[0], tmp2[1] );
linePointsInput.push ( lp );
} else if ( tmp2.length > 1 ) {
lp = new LinePoint ( tmp2[0], tmp2[1], linePointsInput[linePointsInput.length - 1] );
linePointsInput.push ( lp );
calculate ();
render ();
}
}
}
addChild ( _view = new Bitmap ( new BitmapData ( 450, 450, true, 0x60 ) ) );
_view.smoothing = true;
_view.bitmapData.draw ( holder, null, null, null, null, true );
clear ();
}
private function renderPreProcess ( $map:String, $textureSize:Number = 72, $textureMaxWidth:Number = 100 ) :String {
var blockSize:Number = $textureSize;
var convertedMap:String = "";
var mapPieces:Array = $map.split ( "|" );
for ( var j:uint = 0; j < mapPieces.length; j++ ) {
blockSize = $textureSize;
var tmp:Array = mapPieces[j].split ( "&" );
for ( var i:uint = 0; i < tmp.length - 1; i++ ) {
var tmp2:Array = tmp[i].split ( "<" );
tmp2[0] = Number ( tmp2[0] );
tmp2[1] = Number ( tmp2[1] );
tmp2[2] = Number ( tmp2[2] );
tmp2[3] = Number ( tmp2[3] );
var lineLength:Number = Math.sqrt ( Math.pow ( tmp2[2] - tmp2[0], 2 ) + Math.pow ( tmp2[3] - tmp2[1], 2 ) );
if ( lineLength < $textureMaxWidth )
convertedMap += tmp2[0] + "<" + tmp2[1] + "<" + tmp2[2] + "<" + tmp2[3] + "&";
else {
var angle:Number = Math.atan2 ( tmp2[3] - tmp2[1], tmp2[2] - tmp2[0] );
var pieces:uint = Math.ceil ( lineLength / $textureSize );
blockSize = lineLength / pieces;
var newX:Number = tmp2[0];
var newY:Number = tmp2[1];
for ( var k:uint = 1; k < pieces + 1; k++ ) {
var newX2:Number = tmp2[0] + blockSize * k * Math.cos ( angle );
var newY2:Number = tmp2[1] + blockSize * k * Math.sin ( angle );
convertedMap += newX + "<" + newY + "<" + newX2 + "<" + newY2 + "&";
newX = newX2;
newY = newY2;
}
}
}
convertedMap += "|"
}
return convertedMap;
}
private function calculate () :void {
segLength = 1;
lastLength = 0;
linePoints = [];
linePoints.push ( linePointsInput[0] );
vertices = new Vector.<Number>;
indices = new Vector.<int>;
uvtData = new Vector.<Number>;
for ( var i:int = 1; i < linePointsInput.length; i++ ) {
var lp : LinePoint = linePointsInput[i];
if ( lp.currentLength > lastLength + segLength ) {
lastLength = lp.currentLength;
linePoints.push ( lp );
}
}
var count:uint = 0;
var uvStep:Number = .5;
var currentUV:Number = 0
for ( i = 0; i < linePoints.length; i += 2 ) {
lp = linePoints[i];
vertices.push ( lp.xL, lp.yL, lp.xR, lp.yR );
if ( i == linePoints.length - 1 )
lp = linePoints[i];
else
lp = linePoints[i + 1];
vertices.push ( lp.xL, lp.yL, lp.xR, lp.yR );
indices.push ( count, count + 1, count + 2, count + 1, count + 2, count + 3 );
indices.push ( count + 2, count + 3, count + 4, count + 3, count + 4, count + 5 );
uvtData.push ( currentUV, 0, currentUV, 1, currentUV + uvStep, 0, currentUV + uvStep, 1 );
count += 4;
currentUV += uvStep;
currentUV += uvStep;
}
}
private function render () :void {
g.clear ();
g.beginBitmapFill ( terrainTexture, null, true, true )
g.drawTriangles ( vertices, indices, uvtData );
}
private function clear () :void {
g.clear ();
LinePoint.fullLength = 0;
linePointsInput = [];
linePoints = [];
}
}
import flash.geom.Point;
class LinePoint extends Point {
public static var fullLength: Number = 0;
public var currentLength: Number
public var l: Number;
public var xL: Number;
public var yL: Number;
public var xR: Number;
public var yR: Number;
public var angle: Number = 0;
public var angleT: Number = 0;
public var lw: Number = 15;
public var prevPoint: LinePoint;
public function LinePoint ( xPos:Number, yPos:Number, prevPoint:LinePoint = null ) {
super ( xPos, yPos );
this.prevPoint = prevPoint;
if ( prevPoint ) {
l = Point.distance ( this, prevPoint );
fullLength += l;
currentLength = fullLength;
angleT = Math.atan2 ( this.y - prevPoint.y, this.x - prevPoint.x );
angle = angleT;
var pR:Point = Point.polar ( lw, angle + Math.PI / 2 );
xR = pR.x + x;
yR = pR.y + y;
var pL:Point = Point.polar ( lw, angle - Math.PI / 2 );
xL = pL.x + x;
yL = pL.y + y;
if ( prevPoint.prevPoint )
prevPoint.setAngel ( this );
} else {
xR = x;
yR = y;
xL = x;
yL = y;
}
}
private function setAngel ( nextPoint:LinePoint ) :void {
angle = Math.atan2 ( nextPoint.y - prevPoint.y, nextPoint.x - prevPoint.x );
var ll:Number= l + prevPoint.l + nextPoint.l
var pR:Point = Point.polar ( lw, angle + Math.PI / 2 );
xR = pR.x + x;
yR = pR.y + y;
var pL:Point = Point.polar ( lw, angle - Math.PI / 2 );
xL = pL.x + x;
yL = pL.y + y;
}
private function intersect ( p1:Point, p2:Point, p3:Point, p4:Point ) :Boolean {
var nx:Number, ny:Number, dn:Number;
var x4_x3:Number = p4.x - p3.x;
var pre2:Number = p4.y - p3.y;
var pre3:Number = p2.x - p1.x;
var pre4:Number = p2.y - p1.y;
var pre5:Number = p1.y - p3.y;
var pre6:Number = p1.x - p3.x;
nx = x4_x3 * pre5 - pre2 * pre6;
ny = pre3 * pre5 - pre4 * pre6;
dn = pre2 * pre3 - x4_x3 * pre4;
nx /= dn;
ny /= dn;
if ( nx >= 0 && nx <= 1 && ny >= 0 && ny <= 1 )
return true;
return false;
}
}