Brute Force Texture Editor
Brute-Force texture editor
@author "Alessandro Ituarte"
This is a test at a map-editor from games, that calculate the correct transitions from one texture to another
To see it working with actual meaningful textures instead of just random bitmap data check it out here:
http://alessandroituarte.com/blag/2009/10/10/62
/**
* Copyright dredlockz ( http://wonderfl.net/user/dredlockz )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zkIR
*/
package {
import de.polygonal.ds.Array2;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import net.hires.debug.Stats;
/**
* Brute-Force texture editor
* @author "Alessandro Ituarte"
* This is a test at a map-editor from games, that calculate the correct transitions from one texture to another
* To see it working with actual meaningful textures instead of just random bitmap data check it out here:
* http://alessandroituarte.com/blag/2009/10/10/62
*/
[SWF(frameRate='30',backgroundColor='0xCCCCCC',width='480',height='480')]
public class BackgroundTest extends Sprite {
private const WIDTH :int = 480;
private const HEIGHT :int = 480;
private const UNIT_SIZE :int = 20;
private const ROWS :int = 24;
private const COLUMNS :int = 24;
//value constants
private const GRASS :int = 0;
private const DIRT :int = 1;
private const TRANS :int = 2;
private const IDLE :int = 3;
//These should be actual images, I'll work on loading them later, since they were originally embeded
public var dirt:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x0000FF));
public var dirt_b:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x333300));
public var dirt_bl:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x444400));
public var dirt_br:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x555500));
public var dirt_t:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x666600));
public var dirt_tl:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x777700));
public var dirt_tr:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x888800));
public var dirt_l:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x999900));
public var dirt_r:Bitmap = new Bitmap(new BitmapData(20,20,false, 0xAAAA00));
public var dirt_cbl:Bitmap = new Bitmap(new BitmapData(20,20,false, 0xBBBB00));
public var dirt_cbr:Bitmap = new Bitmap(new BitmapData(20,20,false, 0xCCCC00));
public var dirt_ctl:Bitmap = new Bitmap(new BitmapData(20,20,false, 0xDDDD00));
public var dirt_ctr:Bitmap= new Bitmap(new BitmapData(20,20,false, 0xEEEE00));
public var dirt_cc2:Bitmap= new Bitmap(new BitmapData(20,20,false, 0xFFFF00));
public var dirt_cc:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x222200));
public var grass1:Bitmap= new Bitmap(new BitmapData(20,20,false, 0x005500));
public var grass2:Bitmap = new Bitmap(new BitmapData(20,20,false, 0x006600));
public var grass3:Bitmap= new Bitmap(new BitmapData(20,20,false, 0x007700));
private var grasses:Vector.<Bitmap> = new Vector.<Bitmap>();
private var grid:Array2;
private var mouseDown:Boolean = false;
private var conflicts:Boolean = false;
private var currentType:int = IDLE;
private var screen:BitmapData;
private var output:Bitmap;
private var midCells:int;
private var corCells:int;
public function BackgroundTest() {
super();
grasses.push(grass1);
grasses.push(grass2);
grasses.push(grass3);
screen = new BitmapData(WIDTH, HEIGHT, false, 0xFF0000);
output = new Bitmap(screen);
stage.addChild(output);
var st:Stats = stage.addChild(new Stats()) as Stats;
initDataArray();
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseIsDown);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseIsUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseIsMoving);
fillScreen();
}
public function tryCell(cellX:int, cellY:int):void{
if (currentType == IDLE || !isType(cellX, cellY)){
setCurrentType(cellX, cellY);
toggleCell(cellX, cellY);
balanceCheck();
paint();
}
}
public function setCurrentType(cellX:int, cellY:int):void {
switch(int(grid.get(cellX, cellY))){
case GRASS:
case TRANS:
currentType = DIRT;
break;
case DIRT:
currentType = GRASS;
break;
}
}
public function isType(cellX:int, cellY:int):Boolean{
var type:int = int(grid.get(cellX, cellY));
return (currentType == DIRT && type == DIRT) || (currentType == GRASS && (type == GRASS || type == TRANS));
}
public function toggleCell(cellX:int, cellY:int):void {
switch(currentType){
case DIRT:
grid.set(cellX, cellY, DIRT);
break;
case GRASS:
toggleGrass(cellX, cellY);
break;
}
}
public function toggleGrass(cellX:int, cellY:int):void {
for (var i:int = -1; i < 2;i++){
for (var j:int = -1; j < 2; j++){
if (cellX+i >=0 && cellX+i < COLUMNS && cellY+j >=0 && cellY+j < ROWS){
grid.set(cellX+i, cellY+j, GRASS);
}
}
}
}
public function checkForTransition(cellX:int, cellY:int):void {
if (cellX >=0 && cellX < COLUMNS && cellY >=0 && cellY < ROWS && int(grid.get(cellX, cellY)) == GRASS){
grid.set(cellX, cellY, TRANS);
}
}
public function transitionSweep(cellX:int, cellY:int):void {
if (int(grid.get(cellX, cellY)) == DIRT){
for (var i:int = -1; i < 2;i++){
for (var j:int = -1; j < 2; j++){
checkForTransition(cellX+i, cellY+j);
}
}
}
}
public function balanceSweep(cellX:int, cellY:int):void {
if (int(grid.get(cellX, cellY)) == TRANS && opposedCheck(cellX, cellY)){
conflicts = true;
grid.set(cellX, cellY, DIRT);
//transitionSweep(cellX, cellY);
}
}
public function balanceCheck():void {
do {
conflicts = false;
//CLEAN SWEEP
for (var i:int = 0; i < COLUMNS;i++){
for (var j:int = 0; j < ROWS;j++){
if (int(grid.get(i, j)) == TRANS){
grid.set(i, j, GRASS);
}
}
}
//TRANSITION SWEEP
for (i = 0; i < COLUMNS;i++){
for (j = 0; j < ROWS;j++){
transitionSweep(i,j);
}
}
//BALANCE SWEEP
for (i = 0; i < COLUMNS;i++){
for (j = 0; j < ROWS;j++){
balanceSweep(i,j);
}
}
}while (conflicts);
}
public function paint():void {
var tempBit:Bitmap;
//trace("-------------------------");
for (var i:int = 0; i < COLUMNS;i++){
for (var j:int = 0; j < ROWS;j++){
switch(int(grid.get(i,j))){
case GRASS:
tempBit = randomGrass();
break;
case DIRT:
tempBit = dirt;
break;
case TRANS:
tempBit = getTransitionBitmap(i,j);
break;
}
screen.copyPixels(tempBit.bitmapData, new Rectangle(0,0, UNIT_SIZE, UNIT_SIZE),new Point(UNIT_SIZE*i, UNIT_SIZE*j));
}
}
}
public function getTransitionBitmap(cellX:int, cellY:int):Bitmap {
//Count middle and corner cells
countCellTypes(cellX, cellY);
if (midCells > 1){
//in corner
return getInCornerBitmap(cellX, cellY);
}else if (midCells == 1){
var bitmap:Bitmap = getInCornerBitmap(cellX, cellY);
if (bitmap != null){
return bitmap;
}else {
return getStraightBitmap(cellX, cellY);
}
}else {
if (corCells > 1){
//double corner
return getDoubleCornerBitmap(cellX, cellY);//
}else if (corCells == 1){
//out corner
return getOutCornerBitmap(cellX, cellY);
}
}
return null;
}
public function getDoubleCornerBitmap(cellX:int, cellY:int):Bitmap {
var dirtA:Boolean = cellX-1 >= 0 && cellY-1 >= 0 && int(grid.get(cellX-1, cellY-1)) == DIRT;
var dirtB:Boolean = cellX+1 < ROWS && cellY+1 < COLUMNS && int(grid.get(cellX-1, cellY-1)) == DIRT;
//var dirtC:Boolean = cellX-1 >= 0 && cellY+1 < COLUMNS && int(grid.get(cellX-1, cellY-1)) == DIRT;
//var dirtD:Boolean = cellX+1 < ROWS && cellY+1 < COLUMNS && int(grid.get(cellX-1, cellY-1)) == DIRT;
if (dirtA && dirtB) {
return dirt_cc;
}else {
return dirt_cc2;
}
}
public function getInCornerBitmap(cellX:int, cellY:int):Bitmap{
var dirtA:Boolean = cellX-1 >= 0 && int(grid.get(cellX-1, cellY)) == DIRT;
var dirtB:Boolean = cellX-1 >= 0 && cellY-1 >= 0 && int(grid.get(cellX-1, cellY-1)) == DIRT;
var dirtC:Boolean = cellY+1 < ROWS && int(grid.get(cellX, cellY+1)) == DIRT;
var dirtD:Boolean = cellY+1 < ROWS && cellX+1 < COLUMNS && int(grid.get(cellX+1, cellY+1)) == DIRT;
if ( isInCorner(dirtA, dirtB, dirtC, dirtD)) {
return dirt_ctr;
}
dirtA = dirtC;
dirtB = cellX-1 >= 0 && cellY+1 < ROWS && int(grid.get(cellX-1, cellY+1)) == DIRT;
dirtC = cellX+1 < COLUMNS && int(grid.get(cellX+1, cellY)) == DIRT;
dirtD = cellY-1 >= 0 && cellX+1 < COLUMNS && int(grid.get(cellX+1, cellY-1)) == DIRT;
if ( isInCorner(dirtA, dirtB, dirtC, dirtD)) {
return dirt_ctl;
}
dirtA = dirtC;
dirtB = cellX+1 < COLUMNS && cellY+1 < ROWS && int(grid.get(cellX+1, cellY+1)) == DIRT;
dirtC = cellY-1 >= 0 && int(grid.get(cellX, cellY-1)) == DIRT;
dirtD = cellY-1 >= 0 && cellX-1 >= 0 && int(grid.get(cellX-1, cellY-1)) == DIRT;
if ( isInCorner(dirtA, dirtB, dirtC, dirtD)) {
return dirt_cbl;
}
dirtA = dirtC;
dirtB = cellX+1 < COLUMNS && cellY-1 >= 0 && int(grid.get(cellX+1, cellY-1)) == DIRT;
dirtC = cellX-1 >= 0 && int(grid.get(cellX-1, cellY)) == DIRT;
dirtD = cellY+1 < ROWS && cellX-1 >= 0 && int(grid.get(cellX-1, cellY+1)) == DIRT;
if ( isInCorner(dirtA, dirtB, dirtC, dirtD)) {
return dirt_cbr;
}
return null;
}
public function isInCorner(dirtA:Boolean, dirtB:Boolean, dirtC:Boolean, dirtD:Boolean):Boolean {
return ( dirtA && (dirtC || dirtD) ) || ( dirtC && (dirtA || dirtB));
}
public function getStraightBitmap(cellX:int, cellY:int):Bitmap{
if (cellX-1 >= 0 && int(grid.get(cellX-1, cellY)) == DIRT){
return dirt_r;
}else if (cellX+1 < COLUMNS && int(grid.get(cellX+1, cellY)) == DIRT){
return dirt_l;
}else if (cellY-1 >= 0 && int(grid.get(cellX, cellY-1)) == DIRT){
return dirt_b;
}else {
return dirt_t;
}
}
public function getOutCornerBitmap(cellX:int, cellY:int):Bitmap{
if (cellX-1 >= 0 && cellY-1 >= 0 && int(grid.get(cellX-1, cellY-1)) == DIRT){
return dirt_br;
}else if (cellX-1 >= 0 && cellY+1 < ROWS && int(grid.get(cellX-1, cellY+1)) == DIRT){
return dirt_tr;
}else if (cellX+1 < COLUMNS && cellY-1 >= 0 && int(grid.get(cellX+1, cellY-1)) == DIRT){
return dirt_bl;
}else {
return dirt_tl;
}
}
public function countCellTypes(cellX:int, cellY:int):void {
midCells = 0;
corCells = 0;
var counter:int = 0;
for (var i:int = -1; i < 2;i++){
for (var j:int = -1; j < 2; j++){
if (cellX+i >= 0 && cellX+i < COLUMNS && cellY+j >= 0 && cellY+j < ROWS && int(grid.get(cellX+i, cellY+j)) == DIRT) {
switch(counter){
case 0:
case 2:
case 6:
case 8://CORNERS
corCells++;
break;
case 1:
case 3:
case 5:
case 7://MIDS
midCells++;
break;
}
}
counter++;
}
}
}
public function opposedCheck(cellX:int, cellY:int):Boolean {
var pass:Boolean = true;
if (cellX-1 >=0 && cellX+1 < COLUMNS){
pass = pass && !(int(grid.get(cellX-1, cellY)) == DIRT && int(grid.get(cellX+1, cellY)) == DIRT);
}
if (cellY-1 >=0 && cellY+1 < ROWS){
pass = pass && !(int(grid.get(cellX, cellY-1)) == DIRT && int(grid.get(cellX, cellY+1)) == DIRT);
}
return !pass;
}
public function mouseIsMoving(event:MouseEvent):void {
if (mouseDown){
tryCell(pixelToCell(this.mouseX), pixelToCell(this.mouseY));
}
}
public function mouseIsUp(event:MouseEvent):void {
trace("Mouse is Up");
mouseDown = false;
currentType = IDLE;
}
public function mouseIsDown(event:MouseEvent):void {
trace("Mouse is Down");
mouseDown = true;
tryCell(pixelToCell(this.mouseX), pixelToCell(this.mouseY));
}
public function pixelToCell(pixel:int):int {
return pixel/UNIT_SIZE;
}
public function cellToPixel(cell:int):int {
return cell*UNIT_SIZE;
}
public function initDataArray():void {
grid = new Array2(ROWS, COLUMNS);
for (var i:int = 0; i < COLUMNS;i++){
for (var j:int = 0; j < ROWS;j++){
grid.set(i,j,GRASS);
}
}
}
public function randomGrass():Bitmap {
return grasses[int(Math.random()*3)];
}
public function fillScreen():void {
trace("Filling screen with grass...");
var randGrass:Bitmap;
for (var i:int = 0; i < COLUMNS;i++){
for (var j:int = 0; j < ROWS;j++){
randGrass = randomGrass();
screen.copyPixels(randGrass.bitmapData, new Rectangle(0,0, UNIT_SIZE, UNIT_SIZE),new Point(UNIT_SIZE*i, UNIT_SIZE*j));
}
}
output.bitmapData = screen;
}
}
}