class ini bertujuan untuk menggenerate pohon secara random.
1.
2.
Code:
/*
* 2D procedural tree (proceduralTree beta)
* Part of Cornicle Game Development Kit
*
* Copyright (c) 2009 Kornelius Heru C.M, All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package cornicleProceduralTree
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* ...
* @author cornicle
*/
public class proceduralTree extends Sprite
{
private var bark:BitmapData;
private var leaf:BitmapData;
private var result:MovieClip;
private var maxLeaf:Number;
public function proceduralTree(bark:BitmapData, leaf:BitmapData, outline:Boolean, firstLength:Number, maxBranch:Number, minBranch:Number, maxLeaf:Number) {
//setting up textures
this.bark = bark;
this.leaf = leaf;
//our render target
result = new MovieClip();
//generate new tree
this.maxLeaf = maxLeaf;
generateNewTree(firstLength, maxBranch, minBranch);
//getting the bounding box
var rect:Rectangle = result.getRect(result);
//create new bitmap where we draw our movieclip. drawing a complex movieclip eats more memory than a bitmap;
var treeBitmap:BitmapData = new BitmapData(rect.width, rect.height, true, 0x00000000);
//some simple texture translation
var mat:Matrix = new Matrix();
mat.translate( -rect.x, -rect.y);
//use outline?
if(outline){
var glow:GlowFilter = new GlowFilter(0x000000, 100, 1, 1, 5, 1);
var filters:Array = new Array();
filters.push(glow);
result.filters = filters;
}
//draw our tree to bitmap
treeBitmap.draw(result, mat);
var bmp:Bitmap = new Bitmap(treeBitmap);
bmp.y = -rect.height;
bmp.x = -rect.width/2;
this.addChild(bmp);
//finaly clear our movieClip. we don't need it anymore.
result.graphics.clear();
}
public function generateNewTree(firstLength:Number, maxBranch:Number, minBranch:Number):MovieClip {
result.graphics.clear();
generateTree(firstLength, maxBranch, minBranch, 0, 0, null, null);
return result;
}
public function generateTree(firstLength:Number, maxBranch:Number, minBranch:Number, x:Number, y:Number, pt1:Point, pt2:Point):void {
var rotation:Number = -Math.PI/2 + Math.random() * Math.PI + Math.PI;
var length:Number = Math.max(Math.random() * firstLength, firstLength/2);
var hThickness:Number = length / 10;
var branch:Number = Math.max(Math.round(Math.random() * maxBranch), minBranch);
//brach's geometry
// p3------p2
// | /|
// | / |
// | / |
// | / |
// | / |
// |/ |
// p0------p1
var p0:Point;
if (pt1 == null) {
p0 = new Point( hThickness, 0);
}else {
p0 = pt1;
}
var p1:Point;
if (pt2 == null) {
p1 = new Point(-hThickness , 0);
}else {
p1 = pt2;
}
var p2:Point;
var p3:Point;
if (branch > 0) {
p2 = new Point(hThickness / 2, length);
p3 = new Point( -hThickness / 2, length);
}else {
p2 = new Point(0 , length);
p3 = new Point(0 , length);
}
//setup final transformation
var mat:Matrix = new Matrix();
mat.rotate(rotation);
mat.translate(x, y);
//update real position
p2 = mat.transformPoint(p2);
p3 = mat.transformPoint(p3);
//setup texture matrix
var textureMatrix:Matrix = new Matrix();
textureMatrix.translate(bark.width / 2, 0);
textureMatrix.scale(hThickness / bark.width, length / 2 / bark.height);
textureMatrix.rotate(rotation);
//draw branch
//result.graphics.lineStyle(1, 0x000000);
result.graphics.beginBitmapFill(bark, textureMatrix);
result.graphics.moveTo(p0.x, p0.y);
result.graphics.lineTo(p1.x, p1.y);
result.graphics.lineTo(p2.x, p2.y);
result.graphics.lineTo(p3.x, p3.y);
result.graphics.endFill();
//not for the root
if((pt1 != null)&&(pt2 != null)){
//draw leafs
var numLeaves:Number = Math.round(Math.random() * maxLeaf);
var leafS:Point = new Point((p1.x + p0.x) / 2, (p1.y + p0.y) / 2);
var leafF:Point = new Point((p3.x + p2.x) / 2, (p3.y + p2.y) / 2);
var dx:Number = leafF.x - leafS.x;
var dy:Number = leafF.y - leafS.y;
// create leafs
for (var j:Number = 0 ; j < numLeaves ; j++) {
//leaf position
var newPos:Point = new Point(leafS.x + Math.random() * dx , leafS.y + Math.random() * dy);
var leafSize:Number = Math.max( 25 * Math.random(), length / 4);
//leaf's geometry
// l0----------l1
// | /|
// | / |
// | / |
// | / |
// | / |
// |/ |
// l3----------l2
//drawing points
var l0:Point = new Point(-leafSize, -leafSize);
var l1:Point = new Point( leafSize, -leafSize);
var l2:Point = new Point( leafSize, leafSize);
var l3:Point = new Point(-leafSize, leafSize);
var lMat:Matrix = new Matrix();
lMat.translate(newPos.x, newPos.y);
// transforming points
l0 = lMat.transformPoint(l0);
l1 = lMat.transformPoint(l1);
l2 = lMat.transformPoint(l2);
l3 = lMat.transformPoint(l3);
//texture matrix
var lTMat:Matrix = new Matrix();
var scale:Number = leafSize / leaf.width * 2;
lTMat.translate((newPos.x - leafSize) / scale, (newPos.y - leafSize) / scale);
lTMat.scale(scale , scale);
//drawing
result.graphics.beginBitmapFill(leaf, lTMat);
result.graphics.moveTo(l0.x, l0.y);
result.graphics.lineTo(l1.x, l1.y);
result.graphics.lineTo(l2.x, l2.y);
result.graphics.lineTo(l3.x, l3.y);
result.graphics.endFill();
}
}
//proceed to next branches
for (var i:Number = 0; i < branch ; i++) {
var n1:Point;
var n2:Point;
if (p3.x < p2.x) {
n1 = p2;
n2 = p3;
}else {
n1 = p3;
n2 = p2
}
var nextPosition:Point = new Point((p3.x + p2.x) / 2, (p3.y + p2.y) / 2);
generateTree(length, branch - 1, minBranch - 1, nextPosition.x, nextPosition.y, n1, n2);
}
}
}
}
importkan kemudian panggil constructornya. yang dibutuhkan adalah 2 gambar sebagai texture yang terdiri dari, satu texture daun 64 x 64 pixel, dan satu texture batang 64 x 64. resolusi yang lain belum saya coba.
parameter 7 : 3, maximal daun per batang.
contoh class main-nya. jangan lupa untuk import proceduralTree.as -nya
Code:
package
{
import cornicleProceduralTree.proceduralTree;
import flash.display.Bitmap;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.system.System;
/**
* ...
* @author cornicle
*/
public class Main extends Sprite
{
[Embed(source = 'texture/bark1.jpg')]
public static var Bark1:Class;
[Embed(source = 'texture/daun.png')]
public static var Daun1:Class;
public var text:TextField;
public var daun1:Bitmap;
public var bark1:Bitmap;
public var pt:proceduralTree
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var mc:MovieClip = new MovieClip();
mc.graphics.beginFill(0xccccff, 100);
mc.graphics.moveTo(0, 0);
mc.graphics.lineTo(800, 0);
mc.graphics.lineTo(800, 600);
mc.graphics.lineTo(0, 600);
addChild(mc);
text = new TextField();
this.addChild(text);
text.textColor = 0x000000;
text.width = 400;
text.text = "2D procedural tree Beta.\ncreating 30 random generated trees";
bark1 = new Bark1();
daun1 = new Daun1();
update(null);
addEventListener(MouseEvent.CLICK, update);
}
public function update(e:Event):void {
if (pt) {
removeChild(pt)
}
pt = new proceduralTree(bark1.bitmapData, daun1.bitmapData, false, 200, 8, 4, 3);
addChild(pt);
pt.x = 400;
pt.y = 600;
text.text = "2D procedural tree Beta.\nclick any where to generate new tree\neating "+ Math.round(System.totalMemory/(1024*1024)) + " MB";
}
}
}