06/12/2009, 22:17
|
|
#1
|
|
Member
Join Date: Sep 2008
Location: jogja
Posts: 245
|
procedural fire (beta)
procedural fire
PENGANTAR
pada jaman dahulu kala hingga sekarang orang menggunakan file image untuk membuat animasi api(texture animation). biasanya texture tersebut didapatkan dari software-software animasi dalam bentuk image file(.jpg, .bmp, .png, dsb).
MANFAAT
karena saya terlalu malas untuk melakukan hal diatas. ups... alasan yang jahat, bagai mana kalo kita bisa membuat api tersebut on the fly, dengan image yang lebih sedikit dan kecil ukurannya.
fungsi dari class ini adalah menggenerate array of bitmapData yang menggambarkan pergerakan api. class ini turunan dari Sprite sehingga bisa langsung di-attach kan pada Sprite lain.
LANDASAN TEORI
algoritma :
step 1.
membuat warna api yang berupa grandient dengan tipe radial
step 2.
menggenerate alpha channel untuk croping. alpha channel dihasilkan dari image fireShape dan image Cloud. dengan melakukan blending antar cloud-cloud. dengan detail level tertentu.
step 3
gradient color tadi ditulis ke bitmap data, kemudian di clone ke sejumlah frame buffer(array of bitmapData), pada setiap buffer apply alpha yang telah digenerate. mainkan texture coordinate tiap cloud, generate lagi alpha chanell untuk buffer yang lain.
step 4
tampilkan hasil berdasarkan posisi frame.
IMPLEMENTASI
dibutuhkan 2 texture yang pertama adalah texture fireShape yang mewakili bentuk api, dan yang kedua adalah texture cloud yang merupakan hasil dari ....eemmmm filter->render->cloud. texture cloud harus tile.
Code:
//preparing textures
var rt:Bitmap = new tx();
var fs:Bitmap = new sht();
set resolusi dari api yang akan dibuat
Code:
//set fire's resolution
var reshx:Number = 256;
var reshy:Number = 256;
buat color template yang isinya akan digunakan untuk menggenerate base color dari api yang akan dibuat. silakan lihat dokumentasi tentang gradientfill untuk as3(sama dengan gradientFill di as2)
Code:
//setup colors of the fire
var colors:Array = new Array(0xfffc00, 0xff0000)
var ratios:Array = new Array(0, 256 / 4);
var template:fireColorTemplate = new fireColorTemplate();
template.setColors(colors, ratios);
panggil constructor. masukkan parameter colorTemplate, 2texture texture diatas, resolusi api, detail dan frame. detail terisi 5 cloud yang igunakan akan di-blending 5 kali untuk menghasilkan feature-feature yang lebih detail. detail tinggi menggambarkan api yang besar. dan detail yang rendah menggambarkan api yang kecil. frame diisi 30 artinya saya akan memainkan texture animation untuk FPS 30.
Code:
//create our fire
var rfire:proceduralFire = new proceduralFire(template,
rt.bitmapData,
fs.bitmapData,
reshx,
reshy,
5,
30)
addChild(rfire);
atur posisi api
Code:
// set position
rfire.x = 400;
rfire.y = 300;
selamat mencoba
1. demo
2. fd sample project
__________________
PROMISED LAND
a place, where a game programmer. siting in front of a super computer. beside a million tons of beer
ready to drink.
- my works -
|
|
06/12/2009, 23:16
|
|
#2
|
|
Senior Member
Join Date: Jan 2007
Location: Earth? Place that can ping IRIS maybe...
Posts: 541
|
Hmm... Kalo di dunia 3D cg kayaknya dah umum tuh..
Aku beberapa bulan lalu abis baca paper tentang generate cloud on the fly.
Tekniknya, dengan "sebar" density particles, generate "sprite" dengan kepadatan yang sesuai dengan density n sudut pantang kamera, billboard spritenya, combine, addition, (kalo perlu) atur pencahayaan...
Detilnya tapi lupa
keuntungan dari generate partikel sudah pasti bisa dikasih physics semau designer, tapi dibayar ama processing time
Kalo dari sudut pandang aku, I'd prefer sprite based particle karena lebih artistic ^^
__________________
東方Rule!
current project:[kebanyakan, masuk gudang dulu]
- my portfolio- blag-
|
|
07/12/2009, 20:57
|
|
#3
|
|
Member
Join Date: Sep 2008
Location: jogja
Posts: 245
|
@ewaru
thanks replynya
waduh .. perlu gogling lage neeh. hehe. punya link na gak buat generate cloud on the fly-na.
tentang sprite based particle, kalo sprite yang kita perlukan banyak kan bakan mengurangi FPS. ya kan? kalo di procedural fire saya ada fungsi getBuffer so kita bisa mbikin api satu saja lalu ambil buffernya dan bikin sprite laen pake buffer tsb
btw saya sudah update classnya
Code:
/*
* 2D procedural fire (proceduralFire 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 cornicleProceduralFire
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* ...
* @author cornicle
*/
public class proceduralFire extends Sprite
{
private var drawSurface:BitmapData;
private var cloudTexture:BitmapData;
private var fireShapeTexture:BitmapData;
private var speed:Number;
private var frameCount:Number;
private var framePos:Number;
private var frameBuffer:Array;
private var detail:Number;
private var time:Number
public function proceduralFire(template:fireColorTemplate, cloudTexture:BitmapData, fireShapeTexture:BitmapData, width:Number, height:Number, detail:Number, frames:Number) {
//base attributes
this.detail = Math.min(Math.max(detail, 1), 10);
this.frameCount = frames;
this.cloudTexture = cloudTexture;
this.fireShapeTexture = fireShapeTexture;
this.framePos = 0;
this.time = 0;
//setup fire
setupFire(width, height);
//init fire into frame buffer
initFire(template);
//adding listener
initEvent();
}
private function setupFire(width:Number, height:Number):void {
//primary drawing surface
drawSurface = new BitmapData(width, height, true, 0x00000000);
var bmp:Bitmap = new Bitmap(drawSurface);
addChild(bmp)
bmp.x = -width / 2;
bmp.y = -height / 4 * 3;
//alpha generator via movie clip blending;
frameBuffer = new Array();
}
private function initFire(template:fireColorTemplate):void {
var W:Number = drawSurface.width;
var H:Number = drawSurface.height;
//fixed texture scaling factor
var tsX:Number = W / cloudTexture.width;
var tsY:Number = H / cloudTexture.height;
var colorTexture:BitmapData = new BitmapData(W, H, true, 0x00000000);
var cmc:MovieClip = new MovieClip();
//init alpha buffers
var point1:Point = new Point(0, 0);
var point2:Point = new Point(W, 0);
var point3:Point = new Point(W, H);
var point4:Point = new Point(0, H);
//drawing base color
var colors:Array = template.getColors();
var alphas:Array = template.getAlphas();
var ratios:Array = template.getRatios();
var grMat:Matrix = new Matrix();
grMat.translate(W / 2, H / 4 * 3);
cmc.graphics.beginGradientFill("radial", colors, alphas, ratios, grMat);
cmc.graphics.moveTo(point1.x, point1.y);
cmc.graphics.lineTo(point2.x, point2.y);
cmc.graphics.lineTo(point3.x, point3.y);
cmc.graphics.lineTo(point4.x, point4.y);
cmc.graphics.endFill();
colorTexture.draw(cmc);
cmc.graphics.clear();
//logaritmic division
var devidingFactor:Number = 0;
for (var t:Number = 0 ; t <= detail ; t ++) {
devidingFactor += t;
}
//drawwing alpha buffer
for (var i:Number = 0 ; i < frameCount ; i++) {
var xTrans:Number;
//new bitmap for frame buffer
var bmp:BitmapData = new BitmapData(W, H, true, 0x00000000);
for (var s:Number = 1 ; s < detail + 2 ; s++) {
//texture matrix
var mat:Matrix = new Matrix();
//draw our alpha layer
cmc.graphics.clear();
if (s == detail + 1) {
//using the fire shape
mat.scale(tsX, tsY);
cmc.graphics.beginBitmapFill(fireShapeTexture, mat);
}else {
//using cloud texture
if (isNaN(xTrans)) {
xTrans = W * Math.random();
}
mat.translate(xTrans, -(i / frameCount)*cloudTexture.width);
mat.scale(tsX * 1 / s * 4, tsY * 1 / s * 4);
cmc.graphics.beginBitmapFill(cloudTexture, mat);
}
//draw the square
cmc.graphics.moveTo(point1.x, point1.y);
cmc.graphics.lineTo(point2.x, point2.y);
cmc.graphics.lineTo(point3.x, point3.y);
cmc.graphics.lineTo(point4.x, point4.y);
cmc.graphics.endFill();
//draw to frameBuffer surface
if (s == detail + 1) {
var ct:ColorTransform = new ColorTransform( 1, 1, 1, 1, -52, -52, -52, 0);
//over burn
bmp.draw(cmc, null, ct, "add");
//crop everything with fire shape
bmp.draw(cmc, null, null, "multiply");
}else {
var alpha:Number = s / devidingFactor * 2;
var ct2:ColorTransform = new ColorTransform( alpha, alpha, alpha, alpha);
bmp.draw(cmc, null, ct2, "add");
}
}
//fill our buffer
var bufferContent:BitmapData = colorTexture.clone();
//apply our generated alpha to base color.
bufferContent.copyChannel(bmp, new Rectangle(0, 0, drawSurface.width, drawSurface.height), new Point(0, 0), 1, 8);
frameBuffer.push(bufferContent);
}
}
private function update(e:Event):void {
drawSurface.copyPixels(frameBuffer[framePos], new Rectangle(0, 0, drawSurface.width, drawSurface.height), new Point(0, 0));
if (framePos < frameCount-1) {
framePos++;
}else {
framePos = 0;
}
}
private function initEvent():void {
addEventListener(Event.ENTER_FRAME, update);
}
public function getBuffer():Array {
var result:Array = new Array();
for (var i:Number = 0 ; i < frameBuffer.length ; i++) {
result.push(frameBuffer[i].clone());
}
return result;
}
}
}
color template
Code:
/*
* fireColorTemplate
* 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 cornicleProceduralFire
{
/**
* ...
* @author cornicle
*/
public class fireColorTemplate
{
private var colors:Array;
private var ratios:Array;
private var alphas:Array;
public function fireColorTemplate() {
alphas = new Array();
}
public function setColors(colors:Array, ratios:Array):void {
//number of colors and ratios
if (colors.length != ratios.length) return;
this.colors = copyArray(colors);
this.ratios = copyArray(ratios);
alphas.splice(0, alphas.length);
for (var i:Number = 0 ; i < colors.length ; i++) {
alphas.push(255);
}
}
private function copyArray(target:Array):Array {
var result:Array = new Array();
for (var i:Number = 0 ; i < target.length ; i++) {
result.push(target[i]);
}
return result;
}
public function getColors():Array {
return copyArray(colors);
}
public function getAlphas():Array {
return copyArray(alphas);
}
public function getRatios():Array {
return copyArray(ratios);
}
}
}
mohon saran-sarannya lagi
__________________
PROMISED LAND
a place, where a game programmer. siting in front of a super computer. beside a million tons of beer
ready to drink.
- my works -
|
|
07/12/2009, 21:32
|
|
#4
|
|
GDI Power Users
Join Date: Dec 2007
Location: Pangkalpinang
Posts: 3,279
|
Hmmm... Aku rasa perlin noise di bitmap data hampir mirip ma efek cloud di sotosop, coba di cek 
__________________
tobat ngejunk. tobat nyepam. tobat bikin yang gak bener. tobat kasih komen gak jelas. tobat buang-buang ikon. tobat jadi orang jelek. tobat maen komputer sambil belajar. tobat banget kalo ngomong gak bertanggung jawab. tobat banget untuk kesalahan laennya.
"siapa yang mau ikut2an tobat??"
blog : http://alijaya.wordpress.com/, http://bothaxe.wordpress.com/
|
|
07/12/2009, 22:18
|
|
#5
|
|
Member
Join Date: Sep 2008
Location: jogja
Posts: 245
|
wanderful........
jadi tambah dong perlin noise
__________________
PROMISED LAND
a place, where a game programmer. siting in front of a super computer. beside a million tons of beer
ready to drink.
- my works -
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|