플래시 게임 Budapest defenders

Programming/Etc 2007. 8. 26. 19:15
게임 장르를 잘모르지만 이런 장르를 전략시물레이션 게임이라고 하지 않나 싶다. 간단한 스토리지만 플래시 전략 보드게임으로서는 매력적이다.













http://alt.tnt.tv/tntoriginals/thecompany/budapestdefenders/index.htm

사용자 삽입 이미지





    

설정

트랙백

댓글

[AS3] Head First - OOAD AS3로 변환 두번째

Programming/ActionScript 3.0 2007. 8. 26. 12:11
이전에 포스팅한 기타 검색 프로그램의 두 번째로 객체지향 원리를 살린 cohesive버전을 AS3로 변환하였다. 변환 과정에서 Java에서 제공하고 있는 HashMap의 경우는 AS3로 기본적인 기능만을 하는 HashMap class를 만들었다.

메인 document class에서 inventory. addInstrument() 메소드를 실행할 때, 마지막 파라미터 값으로 new InstrumentSpec(HashMap)을 전달하게 되는데, 이때 HashMap 클래스의 경우 Array을 이용하여 데이터를 테이블 형태로 저장하고 있기 때문에 put과 remove과정에서 하나의 Array를 참조하므로 마지막 데이터만을 저장하게 되어 검색이 제대로 되지 않는다.

이는 addInstrument 메소드를 실행하는 시점에서 참조 형태로 HashMap 데이터 Array를 전달하기 때문에 발생하는 문제다. 이를 해결하기 위해 HashMap에 있는 Array를 복제(clone)할 필요가 생겼다. 그래서 HashMap 클래스 내에 clone() 메소드를 만들어 사용되고 있는 Array를 byteArray로 변환하여 복제하였다.

이 프로그램을 변환하면서 다시 한번 느끼는 건 단순해 보이지만 단순하지 않은, 간결하고 함축적인, 사용자가 사용하기 편리한 것과 개발자의 정신분열 증상은 항상 반비례한다는 것이다. 
Java의 버전업을 통해 지원하고 있는 클래스들을 분석하는 것은 충분히 가치가 있는 일이다. 이미 입증된 알고리즘으로 제작되었기 때문에 AS3로 변환하면 충분히 사용성에서 좀더 나을 방법을 찾을 수 있을 듯싶다.

사용자 삽입 이미지

// FindInstrumentTester.as
package{
import flash.display.Sprite;
public class FindInstrumentTester extends Sprite{

public function FindInstrumentTester():void{
var inventory:Inventory = new Inventory();
initializeInventory(inventory);

var properties:HashMap = new HashMap();
properties.put("builder", Builder.GIBSON);
properties.put("backWood", Wood.MAPLE);
var whatBryanLikes:InstrumentSpec = new InstrumentSpec(properties);

var matchingInstruments:Array = inventory.search(whatBryanLikes);
if(matchingInstruments.length != 0){
trace("Bryan, you might like these instruments:");
var ilen:int = matchingInstruments.length;
for(var i:int=0;i<ilen;i++){
var instrument:Instrument = matchingInstruments[i];
var spec:InstrumentSpec = instrument.getSpec();

trace("We have a " + spec.getProperty("instrumentType") +
" with the following properties:");

var hashMap:HashMap = spec.getProperties();
var jlen:int = hashMap.length;
for(var j:int=0;j<jlen;j++){
var propertyName:String =
String(hashMap.getHashTable()[j].key);
trace(" " + propertyName + ": "
+spec.getProperty(propertyName));
}
trace(" You can have this " +
spec.getProperty("instrumentType") +
" for $" + instrument.getPrice() + "\n---");
}
}else{
trace("Sorry, Bryan, we have nothing for you.");
}
}
private function initializeInventory(inventory:Inventory):void {
var properties:HashMap = new HashMap();
properties.put("instrumentType", InstrumentType.GUITAR);
properties.put("builder", Builder.COLLINGS);
properties.put("model", "CJ");
properties.put("type", Type.ACOUSTIC);
properties.put("numStrings", 6);
properties.put("topWood", Wood.INDIAN_ROSEWOOD);
properties.put("backWood", Wood.SITKA);
inventory.addInstrument("11277", 3999.95,
new InstrumentSpec(properties.clone()));

properties.put("builder", Builder.MARTIN);
properties.put("model", "D-18");
properties.put("topWood", Wood.MAHOGANY);
properties.put("backWood", Wood.ADIRONDACK);
inventory.addInstrument("122784", 5495.95,
new InstrumentSpec(properties.clone()));

properties.put("builder", Builder.FENDER);
properties.put("model", "Stratocastor");
properties.put("type", Type.ELECTRIC);
properties.put("topWood", Wood.ALDER);
properties.put("backWood", Wood.ALDER);
inventory.addInstrument("V95693", 1499.95,
new InstrumentSpec(properties.clone()));
inventory.addInstrument("V9512", 1549.95,
new InstrumentSpec(properties.clone()));

properties.put("builder", Builder.GIBSON);
properties.put("model", "Les Paul");
properties.put("topWood", Wood.MAPLE);
properties.put("backWood", Wood.MAPLE);
inventory.addInstrument("70108276", 2295.95,
new InstrumentSpec(properties.clone()));

properties.put("model", "SG '61 Reissue");
properties.put("topWood", Wood.MAHOGANY);
properties.put("backWood", Wood.MAHOGANY);
inventory.addInstrument("82765501", 1890.95,
new InstrumentSpec(properties.clone()));

properties.put("instrumentType", InstrumentType.MANDOLIN);
properties.put("type", Type.ACOUSTIC);
properties.put("model", "F-5G");
properties.put("backWood", Wood.MAPLE);
properties.put("topWood", Wood.MAPLE);
properties.remove("numStrings");
inventory.addInstrument("9019920", 5495.99,
new InstrumentSpec(properties.clone()));

properties.put("instrumentType", InstrumentType.BANJO);
properties.put("model", "RB-3 Wreath");
properties.remove("topWood");
properties.put("numStrings", 5);
inventory.addInstrument("8900231", 2945.95,
new InstrumentSpec(properties.clone()));
}
}
}
//  Inventory.as
package{
        public class Inventory{
                private var inventory:Array;
                public function Inventory():void{
                        inventory = new Array();
                }
                public function addInstrument(serialNumber:String,
                price:Number,
                spec:InstrumentSpec):void{
                        var instrument:Instrument = new Instrument(serialNumber,
                        price,
                        spec);
                        inventory.push(instrument);
                }
                public function get(serialNumber:String):Instrument{
                        var len:int = inventory.length;
                        for(var i:int=0;i<len;i++){
                                if(inventory[i].getSerialNumber() == serialNumber){
                                        return inventory[i];
                                }
                        }
                        return null;
                }
                public function search(searchSpec:InstrumentSpec):Array{
                        var matchingInstruments = new Array();
                        var len:int = inventory.length;
                        for(var i:int=0;i<len;i++){
                                if(inventory[i].getSpec().matches(searchSpec)){
                                        matchingInstruments.push(inventory[i]);
                                }
                        }
                        return matchingInstruments;
                }
        }

}
// Instrument.as
package{
        public class Instrument{
                private var serialNumber:String;
                private var price:Number;
                private var spec:InstrumentSpec;
                public function Instrument(serialNumber:String,
                price:Number,
                spec:InstrumentSpec) {
                        this.serialNumber = serialNumber;
                        this.price = price;
                        this.spec = spec;
                }
                public function getSerialNumber():String {
                        return serialNumber;
                }
                public function getPrice():Number{
                        return price;
                }
                public function setPrice(newPrice:Number):void{
                        price = newPrice;
                }
                public function getSpec():InstrumentSpec{
                        return spec;
                }
        }
}
// InstrumentSpec.as
package{
        public class InstrumentSpec{
                private var properties:HashMap;
                public function InstrumentSpec(properties:HashMap=null):void{
                        if (properties == null) {
                                this.properties = new HashMap();
                        } else {
                                this.properties = new HashMap(properties);
                        }
                }
                public function getProperty(propertyName:String):*{
                        return properties.getValue(propertyName);
                }
                public function getProperties():HashMap{
                        return properties;
                }
                public function matches(otherSpec:InstrumentSpec):Boolean{
                        var otherHashMap:HashMap = otherSpec.getProperties();
                        var len:int = otherHashMap.length;

                        var hashTable:Array = otherHashMap.getHashTable();

                        for (var i:int=0; i<len; i++ ) {
                                var propertyName:String = String(hashTable[i].key);

                                if (String(properties.getValue(propertyName)) !=
                                String(otherHashMap.getValue(propertyName))) {
                                        return false;
                                }
                        }
                        return true;
                }
        }
}
// HashMap.as
package{
        import flash.utils.ByteArray;
        public class HashMap{
                private var hashTable:Array;
                public function HashMap(hm:HashMap=null):void{
                        if (hm == null) {
                                hashTable = new Array();
                        } else {
                                hashTable = hm.getHashTable();
                        }
                }
                public function put(k:*, v:*):*{
                        var len:int = length;
                        for(var i:int=0;i<len;i++){
                                if(hashTable[i].key == k){
                                        hashTable[i].key = k;
                                        hashTable[i].value = v;
                                        return v;
                                }
                        }
                        hashTable.push({key:k, value:v});
                        return v;
                }
                public function remove(k:*):Boolean{
                        var len:int = length;
                        for(var i:int=0;i<len;i++){
                                if(hashTable[i].key == k){
                                        hashTable.splice(i,1);
                                        return true;
                                }
                        }
                        return false;
                }
                public function getValue(k:*):*{
                        var len:int = length;
                        for(var i:int=0;i<len;i++){
                                if(hashTable[i].key == k){
                                        return hashTable[i].value;
                                }
                        }
                        return null;
                }
                // this function for test
                public function allTrace():void{
                        var len:int = length;
                        for(var i:int=0;i<len;i++){
                                trace(String(hashTable[i].key)+" : "+String(hashTable[i].value));
                        }
                }
                public function getHashTable():Array{
                        return hashTable;
                }
                public function setHashTable(hashTable:Array):void{
                        this.hashTable = hashTable;
                }
                public function get length():int{
                        return hashTable.length;
                }
                public function clone():HashMap{
                        var hm:HashMap = new HashMap();
                        var hashTableBA:ByteArray = new ByteArray();
                        hashTableBA.writeObject(hashTable);
                        hashTableBA.position = 0;
                        var ary:Array = hashTableBA.readObject() as Array;
                        hm.setHashTable(ary);
                        return hm;
                }
        }
}
// Builder.as
package{
        public class Builder{
                public static const FENDER = "Fender";
                public static const MARTIN = "Martin";
                public static const GIBSON = "Gibson";
                public static const COLLINGS = "Collings";
                public static const OLSON = "Olson";
                public static const RYAN = "Ryan";
                public static const PRS = "PRS";
        }
}

// InstrumentType.as

package{
        public class InstrumentType{
                public static const GUITAR = "Guitar";
                public static const BANJO = "Banjo";
                public static const DOBRO = "Dobro";
                public static const FIDDLE = "Fiddle";
                public static const BASS = "Bass";
                public static const MANDOLIN = "Mandolin";
        }
}

// Type.as

package{
        public class Type{
                public static const ACOUSTIC = "acoustic";
                public static const ELECTRIC = "Belectric";
        }
}

// Wood.as

package{
        public class Wood{
                public static const INDIAN_ROSEWOOD = "Indian Rosewood";
                public static const BRAZILIAN_ROSEWOOD = "Brazilian Rosewood";
                public static const MAHOGANY = "Mahogany";
                public static const MAPLE = "Maple";
                public static const COCOBOLO = "Cocobolo";
                public static const CEDAR = "Cedar";
                public static const ADIRONDACK = "Adirondack";
                public static const ALDER = "Alder";
                public static const SITKA = "Sitka";
        }
}



 

    

설정

트랙백

댓글

[FlashCS3] AIR for FlashCS3 업데이트

Programming/ActionScript 3.0 2007. 8. 25. 23:44
AIR이 공식적으로 FlashCS3에 서포트 되었다. 예전 포스트 grant skinner의 Flash CS3용 Adobe AIR extension 에서 개인이 만든 AIR extension 소개한 적이 있는데 adobe에서 공식적으로 AIR을 FlashCS3에서 생성할 수 있도록 지원하는 update 파일을 배포했다. 버전은 현재 AIR 1.0이다.  업데이트 파일은 아래 링크에서 다운로드 할 수 있다.

http://labs.adobe.com/wiki/index.php/AIR:Flash_CS3_Professional_Update

air파일 정보 세팅과 air파일 생성은 Commands 메뉴에 추가된 AIR-Application and Package Settings 와 AIR-Pacakge AIR File 명령을 통해서 세팅 및 생성할 수 있다.





사용자 삽입 이미지






    

설정

트랙백

댓글

[AS3] Head First - OOAD AS3로 변환

Programming/ActionScript 3.0 2007. 8. 24. 18:43
Head First 시리즈 중에 설계를 위한 객체지향 방법론에 관한 내용을 담고 있는 『Head First Object-Oriented Analysis&Design』 이라는 책이 있다. 책에서 사용한 언어는 Java언어인데 내용 중 기타 판매점의 기타검색 프로그램을 AS3로 수정하였다. 비교적 간단한 구조를 가지고 있지만 막상 하나의 문제를 해결하기 위해 필요한 기능을 구현하고 재사용성이 용이한 구조로 설계하려고 하면 어려움이 많이 발생하는 것 같다. AS3로 변환 과정에서 Java의 enum(열거형 타입 Builder, Type, Wood)는 각 클래스의 static const속성으로 변환하였다.

이 구조는 책의 2장까지 나와 있는 내용 중에서 final 버전이다. 책에서는 이 프로그램을 객체지향의 원리

(변하는 것을 캡슐화하라,
구현에 의존하기 보다는 인터페이스에 의존하도록 코딩하라,
각 클래스는 변경 요인이 오직 하나이어야 한다.)


에 입각해서 다시 5장에서 리펙토링하게 되는데 그 버전은 다음에 바꿔볼 생각이다. 어떤 문제를 풀 때 역행으로 분석해 보는 것도 상당히 도움이 된다.



사용자 삽입 이미지

// FindGuitarTester .as
package{
import flash.display.Sprite;
public class FindGuitarTester extends Sprite{
private var inventory:Inventory;
private var whatErinLikes:GuitarSpec;
private var matchingGuitars:Array;
public function FindGuitarTester():void{
inventory = new Inventory();
initialize();
}
private function initialize():void{
initializeInventory(inventory);
whatErinLikes = new GuitarSpec(Builder.FENDER, "Stratocastor", Type.ELECTRIC, 6, Wood.ALDER, Wood.ALDER);
matchingGuitars = inventory.search(whatErinLikes);
if (matchingGuitars != null) {
trace("Erin, you might like these guitars:");
var len:int = matchingGuitars.length;
for (var i:int=0;i<len;i++) {
var guitar:Guitar = matchingGuitars[i];
var spec:GuitarSpec = guitar.getSpec();
trace(" We have a " +
spec.getBuilder() + " " + spec.getModel() + " " +
spec.getType() + " guitar:\n " +
spec.getBackWood() + " back and sides,\n " +
spec.getTopWood() + " top.\n You can have it for only $" +
guitar.getPrice() + "!\n ----");
}
} else {
trace("Sorry, Erin, we have nothing for you.");
}
}
private function initializeInventory(inventory:Inventory):void {
inventory.addGuitar("11277", 3999.95, new GuitarSpec(Builder.COLLINGS, "CJ", Type.ACOUSTIC, 6, Wood.INDIAN_ROSEWOOD, Wood.SITKA));
inventory.addGuitar("V95693", 1499.95, new GuitarSpec(Builder.FENDER, "Stratocastor", Type.ELECTRIC, 6, Wood.ALDER, Wood.ALDER));
inventory.addGuitar("V9512", 1549.95, new GuitarSpec(Builder.FENDER, "Stratocastor", Type.ELECTRIC, 6, Wood.ALDER, Wood.ALDER));
inventory.addGuitar("122784", 5495.95, new GuitarSpec(Builder.MARTIN, "D-18", Type.ACOUSTIC, 6, Wood.MAHOGANY, Wood.ADIRONDACK));
inventory.addGuitar("76531", 6295.95, new GuitarSpec(Builder.MARTIN, "OM-28", Type.ACOUSTIC, 6, Wood.BRAZILIAN_ROSEWOOD, Wood.ADIRONDACK));
inventory.addGuitar("70108276", 2295.95, new GuitarSpec(Builder.GIBSON, "Les Paul", Type.ELECTRIC, 6, Wood.MAHOGANY, Wood.MAHOGANY));
inventory.addGuitar("82765501", 1890.95, new GuitarSpec(Builder.GIBSON, "SG '61 Reissue", Type.ELECTRIC, 6, Wood.MAHOGANY, Wood.MAHOGANY));
inventory.addGuitar("77023", 6275.95, new GuitarSpec(Builder.MARTIN, "D-28", Type.ACOUSTIC, 6, Wood.BRAZILIAN_ROSEWOOD, Wood.ADIRONDACK));
inventory.addGuitar("1092", 12995.95, new GuitarSpec(Builder.OLSON, "SJ", Type.ACOUSTIC, 12, Wood.INDIAN_ROSEWOOD, Wood.CEDAR));
inventory.addGuitar("566-62", 8999.95, new GuitarSpec(Builder.RYAN, "Cathedral", Type.ACOUSTIC, 12, Wood.COCOBOLO, Wood.CEDAR));
inventory.addGuitar("6 29584", 2100.95, new GuitarSpec(Builder.PRS, "Dave Navarro Signature", Type.ELECTRIC, 6, Wood.MAHOGANY, Wood.MAPLE));
}
}
}

// Inventory.as

package{
        public class Inventory{
                private var guitars:Array;
                public function Inventory():void{
                        guitars = new Array();
                }
                public function addGuitar(serialNumber:String, price:Number, spec:GuitarSpec):void{
                        var guitar:Guitar = new Guitar(serialNumber, price, spec);
                        guitars.push(guitar);
                }
                public function getGuitar(serialNumber:String):Guitar{
                        var len:int = guitars.length;
                        for(var i:int=0;i<len;i++){
                                if(guitars[i].getSerialNumber() == serialNumber){
                                        return guitars[i];
                                }
                        }
                        return null;
                }
                public function search(searchSpec:GuitarSpec):Array{
                        var matchingGuitars = new Array();
                        var len:int = guitars.length;
                        for(var i:int=0;i<len;i++){
                                if(guitars[i].getSpec().matches(searchSpec)){
                                        matchingGuitars.push(guitars[i]);
                                }
                        }
                        return matchingGuitars;
                }
        }

}


// GuitarSpec.as

package {
        public class GuitarSpec {
                private var builder:String;
                private var model:String;
                private var type:String;
                private var numStrings:int;
                private var backWood:String;
                private var topWood:String;

                public function GuitarSpec(builder:String, model:String, type:String, numStrings:int, backWood:String, topWood:String) {
                        this.builder = builder;
                        this.model = model;
                        this.type = type;
                        this.numStrings = numStrings;
                        this.backWood = backWood;
                        this.topWood = topWood;
                }

                public function getBuilder():String {
                        return builder;
                }

                public function getModel():String {
                        return model;
                }

                public function getType():String {
                        return type;
                }

                public function getNumStrings():int {
                        return numStrings;
                }

                public function getBackWood():String {
                        return backWood;
                }

                public function getTopWood():String {
                        return topWood;
                }

                public function matches(otherSpec:GuitarSpec):Boolean {
                        if (builder != otherSpec.getBuilder()) {
                                return false;
                        }
                        if ((model != null) && (model !="") && (model.toLowerCase() != (otherSpec.getModel().toLowerCase()))) {
                                return false;
                        }
                        if (type != otherSpec.getType()) {
                                return false;
                        }
                        if (numStrings != otherSpec.getNumStrings()) {
                                return false;
                        }
                        if (backWood != otherSpec.getBackWood()) {
                                return false;
                        }
                        if (topWood != otherSpec.getTopWood()) {
                                return false;
                        }
                        return true;
                }
        }
}

// Guitar.as
package{
        public class Guitar{
                private var serialNumber:String;
                private var price:Number;
                private var spec:GuitarSpec;
                public function Guitar(serialNumber:String, price:Number, spec:GuitarSpec):void{
                        this.serialNumber = serialNumber;
                        this.price = price;
                        this.spec = spec;
                }
                public function getSerialNumber():String{
                        return serialNumber;
                }
                public function getPrice():Number{
                        return price;
                }
                public function setPrice(newPrice:Number):void{
                        price = newPrice;
                }
                public function getSpec():GuitarSpec{
                        return spec;
                }
        }
}

// Builder.as
package{
        public class Builder{
                public static const FENDER = "Fender";
                public static const MARTIN = "Martin";
                public static const GIBSON = "Gibson";
                public static const COLLINGS = "Collings";
                public static const OLSON = "Olson";
                public static const RYAN = "Ryan";
                public static const PRS = "PRS";
        }
}
// Wood.as
package{
        public class Wood{
                public static const INDIAN_ROSEWOOD = "Indian Rosewood";
                public static const BRAZILIAN_ROSEWOOD = "Brazilian Rosewood";
                public static const MAHOGANY = "Mahogany";
                public static const MAPLE = "Maple";
                public static const COCOBOLO = "Cocobolo";
                public static const CEDAR = "Cedar";
                public static const ADIRONDACK = "Adirondack";
                public static const ALDER = "Alder";
                public static const SITKA = "Sitka";
        }
}
// Type.as
package{
        public class Type{
                public static const ACOUSTIC = "acoustic";
                public static const ELECTRIC = "Belectric";
        }
}
    

설정

트랙백

댓글

[FlashCS3] AlignAssist Extension

Programming/ActionScript 3.0 2007. 8. 23. 09:17
AlignAssist Extension은 스테이지에 있는 복수의 심볼을 원형으로 배치해 주는 Extension이다. 일본 사람이 만든 것으로 익스텐션을 설치하면 익스텐션 설명이 일본어로 되어 있는데 내용은 다음과 같다.

 ■AlignAssist에 대해
 선택한 심볼을 지정한 수치 간격으로 정렬합니다.
 본확장 기능은 Macromedia Flash MX 2004에서 사용할 수 있습니다.  다만 환상 정렬 기능에 대해서는 Flash CS3에서만 되니 주의해 주십시오.

 ■사용 방법
 도구모음의[Window]의[Other Panels]의 [AlignAssist]를 선택하세요.




왼쪽과 같이 불특정 좌표로 배치되어 있는 심볼들을 선택하고 익스텐션을 실행하면 오른쪽과 같이 정렬이 가능하다.
 



    

설정

트랙백

댓글