R.R.Karter Editor
forked from alone in a cave (diff: 656)
♥0 |
Line 464 |
Modified 2015-01-16 22:30:19 |
MIT License
archived:2017-03-20 01:58:35
| (replaced)
ActionScript3 source code
/**
* Copyright Cheshir ( http://wonderfl.net/user/Cheshir )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/wbMq
*/
// Если это похоже на FTL, то это потому, что FTL мне нравится.
// If this sounds like FTL, then it's because I like FTL.
package {
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.display.Shape;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Point;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
import flash.text.TextFieldAutoSize;
import flash.text.TextField;
import flash.display.Sprite;
public class FlashTest extends Sprite {
private static var tracetext:TextField = new TextField();
private var load:MyLoader;
private var externalData:Array = ['Rojer.png','spaceTruck1.png','spTrIns1.png','simpleDoor.png','armoredDoor.png']; // думаю здесь я пожалуй укажу .xml а внутри уже контент уровня
private var mapHolder:Sprite; // Здесь я буду собирать новые уровни и сюда буду загружать старые
public function FlashTest() {
// write as3 code here...
drawBack();
tracetext.textColor = 0xf0fff0;
mapHolder = new Sprite();
addChild(mapHolder);
load = new MyLoader(stage); // Создаем мульти загрузчик
load.addEventListener(MyLoader.ALL_LOADED, initApp); // Ожидаем пока загрузится пакет
load.loadAll(externalData); // Загружаем массив данных
// It is not finished ! --- December 23, 2014
tracetext.autoSize = TextFieldAutoSize.LEFT; // Просто текст для дебага
tracetext.y = 330;
stage.addChild(tracetext);
//stage.addEventListener(MouseEvent.MOUSE_DOWN, stDr);
//stage.addEventListener(MouseEvent.MOUSE_UP, spDr);
}
private function stDr(e:MouseEvent):void{mapHolder.startDrag();}
private function spDr(e:MouseEvent):void{mapHolder.stopDrag();}
private function initApp(e:Event):void {
// после загрузки всего контента выполняется эта функция...
var model:Model = new Model();
var controll:Controller = new Controller(model);
// по идее модель и контроллеры можно создавать и раньше, но представление только теперь.
var view:View = new View(model, controll, stage);
stage.addChild(tracetext); // replace after view...
var ship:TileClip = new TileClip(471,509,load.loaded_D['spaceTruck1.png']);
ship.x = -16; ship.y = -11;
ship.nameTile = 'spaceTruck1.png';
var inside:TileClip = new TileClip(328,168,load.loaded_D['spTrIns1.png']);
inside.x = 28; inside.y = 156; //inside.alpha = 0.3;
inside.nameTile = 'spTrIns.png';
var player:TileClip = new TileClip(32,32,load.loaded_D['Rojer.png']);
player.x = 192; player.y = 160;
player.frameDelay = [40,30];
player.nameTile = 'Rojer.png';
// Взаимодействие с запертыми дверями ( вскрыть-интелект, выломать-сила, открыть-ключ/кнопка )
var doorSimple:TileClip = new TileClip(23,6,load.loaded_D['armoredDoor.png']);
var testDoor:Door = new Door(doorSimple);
testDoor.x = 209; testDoor.y = 224;
mapHolder.addChild(ship);
mapHolder.addChild(inside);
mapHolder.addChild(player);
mapHolder.addChild(testDoor);
var levelCr:LevelCreator = new LevelCreator(mapHolder); // Передадим держатель карты, чтобы распарсить его потом и сохранить XML
}
private static var numLog:Number = 0;
public static function log(v:Object):void{
numLog++;
if(numLog%5 == 0){
tracetext.text = '';
}
tracetext.appendText('\n'+v.toString());
}
private var stars:Shape;
private function drawBack():void{
this.graphics.beginFill(0x222233);
this.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
this.graphics.endFill();
stars = new Shape();
stars.filters = [new GlowFilter(Math.random()*0xffffff+0xcccccc)];
for(var i:int = 0; i<300; i++){
stars.graphics.beginFill(0xffffff);
stars.graphics.drawCircle(Math.random()*stage.stageWidth,Math.random()*stage.stageHeight,Math.random()*.8);
}
addChild(stars);
}
}
}
import flash.text.TextField;
import flash.display.SimpleButton;
import flash.display.Shape;
import flash.net.FileReference;
import flash.display.AVM1Movie;
import flash.events.MouseEvent;
import flash.events.ProgressEvent;
import flash.display.LoaderInfo;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.system.SecurityDomain;
import flash.system.LoaderContext;
import flash.utils.Dictionary;
import flash.geom.Matrix;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Stage;
import flash.ui.Keyboard;
import flash.geom.Point;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.display.Sprite;
Class {
class Model extends EventDispatcher {
public function Model() {
// Модель - хранит данные о мире.
}
}
}
Class {
class View extends Sprite {
private var model:Model;
private var controller:Controller;
public function View(aModel:Model, oController:Controller,
target:Stage)
{ // Представление - получает данные из модели и отображает на экране
this.model = aModel;
this.controller = oController;
target.addChild(this);
}
}
}
Class {
class Controller {
private var model:Model;
public function Controller(aModel:Model)
{ // Контроллер меняет данные в модели
this.model = aModel;
}
}
}
Class { // Нужен класс, чтобы возвращал XML-ку с уровнем
class LevelCreator extends Sprite{ // Вообще это скорее Editor
// private var tiles:Array = []; зачем мне массив если потом все равно парстить mapHolder ?
private var tiles:uint = 0;
private var stg:Sprite;
private var dragged:TileDO; // Сейчас перетаскивается
private var needConnect:TileDO;
private var DrawConnectMode:Boolean = false;
public function LevelCreator(st:Sprite):void { // У меня есть объект MapHolder - на который я добавляю все что есть на уровне...
st.addChild(this);
stg = st; // в принципе я могу пропарсить этот объект и собрать XML для сохранения...
var tileCreator:Sprite = new Sprite();
tileCreator.graphics.beginFill(0xaaaaaa,0.6);
tileCreator.graphics.lineStyle(1,0xaaaaaa);
tileCreator.graphics.drawRoundRect(400,340,50,100,4);
this.addChild(tileCreator);
st.addEventListener(MouseEvent.CLICK, newTileFunc);
var xmlTileExportBtn:Sprite = LevelCreator.getButton(390,410,'xml export',0xffaaaa);
this.addChild(xmlTileExportBtn);
var toggleStateBtn:Sprite = LevelCreator.getButton(380,386,'togg connect',0xaaaaff);
this.addChild(toggleStateBtn);
toggleStateBtn.addEventListener(MouseEvent.CLICK, toggleState);
xmlTileExportBtn.addEventListener(MouseEvent.CLICK, saveXML);
}
// Создание простых квадратов с текстом
public static function getButton(nX:Number, nY:Number, text:String='simpleButton', color:uint=0xaaffaa):Sprite{
var upState:Sprite = new Sprite();
upState.graphics.beginFill(color,0.6);
upState.graphics.lineStyle(1,color);
var tf:TextField = new TextField();
tf.text = text;
tf.autoSize = 'left';
tf.mouseEnabled = false;
upState.addChild(tf);
upState.graphics.drawRoundRect(-5,0,tf.width+10,tf.height,5);
upState.graphics.endFill();
upState.buttonMode = true;
upState.x = nX; upState.y = nY;
return upState;
}
private function saveXML(e:MouseEvent):void {
var endXML:XML = new XML(<level>
<graphics></graphics>
<logick></logick>
</level>);
var graphicsI:uint = 0;
var tileI:uint = 0;
var analize:Object;
for(var i:int=0; i<stg.numChildren; i++){ // Все, что будет добавленно на карту - включая объеты логики, сейчас содержится на stg
analize = stg.getChildAt(i);
if(analize is TileClip){
endXML.graphics.clip[graphicsI] = TileClip(analize).nameTile;
endXML.graphics.clip[graphicsI].@x = analize.x;
endXML.graphics.clip[graphicsI].@y = analize.y;
graphicsI++;
} else if(analize is TileDO){
FlashTest.log(stg.getChildAt(i)+' at num '+i);
endXML.logick.tile[tileI] = tileI;
endXML.logick.tile[tileI].@x = analize.x;
endXML.logick.tile[tileI].@y = analize.y;
endXML.logick.tile[tileI].@links = analize.links;
tileI++;
//endXML.logick.tile.@y = stg.getChildAt(i).y;
}
}
var fr:FileReference = new FileReference();
fr.save(endXML, 'newLevel.xml');
FlashTest.log(endXML);
}
private function toggleState(e:MouseEvent):void{
this.DrawConnectMode = !this.DrawConnectMode;
if(!DrawConnectMode)
needConnect = null;
}
// нужно еще как то научится делать связи между элементами...
private function newTileFunc(e:MouseEvent):void{ // Ну по идее здесь мы создаем новый тайл и позволяем перетаскивать его
if(e.currentTarget is TileDO){
stg.removeChild(e.currentTarget as TileDO);
//e.currentTarget = null;
return;
}
var tile:TileDO = new TileDO(Math.floor(mouseX/32)*32,Math.floor(mouseY/32)*32,tiles);
tile.links = [];
// tile.addEventListener(MouseEvent.MOUSE_UP, dropDragged);
stg.addChild(tile);
tiles++;
// dragged = tile;
// tiles.push( tile );
}
/*
private function pickUpDragged(e:MouseEvent):void{ // Повторно перетаскиваем старый тайл
dragged = TileDO(e.currentTarget);
// Если мы рисуем связи, тогда к этому тайлу связь проведена
if(DrawConnectMode){
needConnect.addLink(dragged);
}
}
/*
private function dropDragged(e:MouseEvent):void{
dragged = null; // Отпускаем перетаскиваемый тайл
if(DrawConnectMode)
needConnect = TileDO(e.currentTarget);
e.currentTarget.addEventListener(MouseEvent.MOUSE_DOWN,pickUpDragged); // Разрешаем повтороно перетаскивать
FlashTest.log('total tiles is: '+tiles.length);
}
/*
private function moveDragged(e:Event):void{
if(dragged && !DrawConnectMode){ // если есть что перетаскивать, то перетаскиваем ))
dragged.x = Math.floor(mouseX/32)*32;
dragged.y = Math.floor(mouseY/32)*32;
}
} */
}
}
Class {
class TileDO extends Sprite {
public var id:uint;
public var links:Array = [];
public function TileDO(x:Number,y:Number,id:uint){
this.x = x; this.y = y; this.id = id;
this.graphics.beginFill(0xaaffaa,0.6);
this.graphics.lineStyle(1,0x33aa33);
this.graphics.drawRoundRect(0,0,31,31,2);
}
public function addLink(tile:TileDO):void{
if(tile == this) return; // связь с самим собой это как то неправильно
for(var i:int=0; i<links.length; i++){
if(links[i]==tile.id)
return; // хм... тонкий момент (!) эта функиця выполняется 3! раза
}
links.push(tile.id);
tile.addLink(this);
this.graphics.moveTo(16,16); // а это уже для наглядности
this.graphics.lineStyle(1);
this.graphics.lineTo( tile.x - this.x+16, tile.y - this.y+16 ); //нужно что-то вроде global to local и
}
}
}
Class { // Логический объект который потом будет хранится в модели... (после загрузки Xml и инициализации уровня)
class TileVO extends Point{
public var neighbors:Vector.<TileVO>; // а вот запись соседей будет внешняя // координат тоже
private var myID:uint;
public function TileVO(id:uint){
this.myID = id;
neighbors = new Vector.<TileVO>();
}
public function get id():uint { return myID; } // only read Id
}
}
// help classes
Class { // Так получилось что загружать можно только картинки... я попробовал загрузить xml
class MyLoader extends EventDispatcher { // не вышло (( это надо решить
public static const ALL_LOADED:String = 'allLoaded';
public var placeToLoad:String = 'http://cheshir.zabix.net/footlocker/RojerKarter/';
public var loaded_D:Dictionary = new Dictionary();
// to correct name
private var WonderflFIX:String = 'http://swf.wonderfl.net/[[IM'; // this wonderfl add before my url...
private var adresses:Array = []; // download all that is in this array // Probably worth doing tileset...
private var loaded:int = 0; // count loaded elements
private var loadedContents:Array = []; // animate progress loading...
private var loadSprite:Sprite = new Sprite();
private var setFeedBack:View;
private var lastId:uint = 0;
private var stageLink:Stage;
public function MyLoader(stageToLoad:Stage){
stageLink = stageToLoad;
stageLink.addChild(loadSprite);
}
public function loadAll(newAdresses:Array):void{
this.adresses = newAdresses;
FlashTest.log('start load...');
var nowAdress:String = '';
var context:LoaderContext = new LoaderContext();
context.checkPolicyFile = true;
context.securityDomain = SecurityDomain.currentDomain;
for(var i:int=0; i<adresses.length; i++ ){
FlashTest.log('new adress num '+(i+1));
nowAdress = adresses[i];
var url:URLRequest = new URLRequest(placeToLoad+nowAdress);
var img:Loader = new Loader();
img.contentLoaderInfo.addEventListener(Event.COMPLETE, loadedBit);
img.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressLoad);
loadedContents.push(img.contentLoaderInfo);
img.load(url, context);
}
}
private function progressLoad(e:ProgressEvent):void{
var percent:Number = 0;//(e.currentTarget as LoaderInfo).bytesLoaded / (e.currentTarget as LoaderInfo).bytesTotal * 100;
var lX:Number = 20;
var lY:Number = 20;
loadSprite.graphics.clear(); // clear graphitcs before draw...
for(var i:int=0; i < loadedContents.length; i++){ // draw each loaded progress
percent = (loadedContents[i] as LoaderInfo).bytesLoaded /(loadedContents[i] as LoaderInfo).bytesTotal * 100;
loadSprite.graphics.lineStyle(1,0x75D07B, 0.8);
loadSprite.graphics.drawRect(lX,lY,102,5);
loadSprite.graphics.lineStyle(0);
loadSprite.graphics.beginFill(0x9DD075,0.8);
loadSprite.graphics.drawRect(lX+1,lY+1,percent,3);
lY += 12;
}
}
private function loadedBit(e:Event):void{ //
var bitmap:Bitmap = e.target.content; // i want BitmapData
// i need only original name...
var nameOfLoaded:String = e.target.url.toString().slice(WonderflFIX.length+placeToLoad.length);
FlashTest.log('I have '+nameOfLoaded);
// i want safe loaded to dictionary use original name...
loaded_D[nameOfLoaded] = bitmap.bitmapData;
loaded++;
if(loaded == adresses.length){
dispatchEvent(new Event(MyLoader.ALL_LOADED,true)); // why not?
loadSprite.graphics.clear();
}
}
}
}
Class {
class Door extends Sprite {
public var isOpen:Boolean = false;
public var isLocked:Boolean = false;
public var tilesConect:Array = [];
private var doorClip:TileClip;
public function Door(doorClip:TileClip) {
this.doorClip = doorClip;
doorClip.stop();
doorClip.currentFrame = 0;
doorClip.loop = false;
this.buttonMode = true;
doorClip.x = -doorClip.width/2;
doorClip.y = -doorClip.height/2;
addChild(doorClip);
this.addEventListener(MouseEvent.CLICK, open_close);
this.addEventListener(MouseEvent.MOUSE_OVER, lock_unlock);
}
public function lock_unlock(e:MouseEvent=null):void{
isLocked = !isLocked;
doorClip.currentState++;
if(isLocked && isOpen){
doorClip.inverse = true;
doorClip.play();
isOpen = false; // Если дверь оказалась заперта и открыта одновременно, надо это исправить
removeConnect();
} // Если я запер дверь, то она закрывается
}
public function open_close(e:MouseEvent=null):void{
if(!isLocked){ // Дверь реагирует только если не заперта
doorClip.inverse = isOpen; // Если дверь открыта, значит ее нужно закрыть - инверсировать анимацию
doorClip.play(); // воспроизвести анимацию
isOpen = !isOpen; // записать что дверь закрыта и наоборот
if(isOpen){
setConnect(); // Если дверь открылась тогда нужны связи
} else {
removeConnect(); // Если дверь закрылась тогда связи не нужны
}
}
}
private function setConnect():void { // Когда дверь открывается она должна установить между двумя тайлами
// между которых она находится - связь, чтобы можно было произвести поиск пути сквозь открытые двери
}
private function removeConnect():void { // Когда дверь закрывается она должна убрать связь
}
}
}
Class {
interface AlphaChanger { /*
function alphaFading():void;
function alphaIgnition():void; */
}
}
Class{
class TileClip extends Bitmap implements AlphaChanger
{
public var demoMode:Boolean = false;
public var randomDelay:Boolean = false;
public var inverse:Boolean = false; // Если мне нужно проиграть видео в обратном направлении
public var loop:Boolean = true; // Если анимация должна быть цикличной, по умолчанию ДА
public var nameTile:String = 'simple TileClip';
private var delays:Array = []; // yes... when i change delays -- current delay must change also to delays[0]
private var currentDelay:uint = 0;
private var widthFrame:Number;
private var heightFrame:Number;
private var bitData:BitmapData;
private var currFrame:uint = 0;
private var totalFrame:uint = 0;
private var currState:uint = 0;
private var totalState:uint = 0;
private var matrix:Matrix;
// Create TileClip from bitmap Data
public function TileClip(widthFrame:Number, heightFrame:Number, bitData:BitmapData, scale:Number = 1)
{ // для парсинга может стоит сохранять имя клипа?
this.widthFrame = widthFrame;
this.heightFrame = heightFrame;
this.bitData = bitData; // Safe data to draw
matrix = new Matrix(); // Init Matrix transform
totalFrame = uint(bitData.width / widthFrame); // Calculate frames
totalState = uint(bitData.height / heightFrame); // Calculate states
this.bitmapData = new BitmapData(widthFrame, heightFrame, true, 0); // This is 'wiew window' of my clip
super();
currentFrame = 0;
this.width = widthFrame * scale;
this.height = heightFrame * scale;
if(totalFrame>1){
play();
}
}
public function set frameDelay(val:Array):void
{
delays = val;
currentDelay = delays[0];
}
public function set currentFrame(num:uint):void
{
if (num < totalFrame) // Elementary update as looped video "currentFrame+=1"
{
this.currFrame = num;
} else {
if(loop){
this.currFrame = 0;
} else {
this.stop();
}
if(demoMode){currentState++;}
}
setCurrentFrame();
}
public function get currentFrame():uint
{
return this.currFrame;
}
public function set currentState(num:uint):void
{
if (num < totalState)
{
this.currState = num;
} else {
this.currState = 0;
}
setCurrentFrame();
}
public function get currentState():uint
{
return this.currState;
}
public function play():void
{
this.addEventListener(Event.ENTER_FRAME, update);
}
public function stop():void
{
this.removeEventListener(Event.ENTER_FRAME, update);
}
public function update(e:Event):void
{
//currentFrame++; // Maybe i must add delays to each frame?
/* How can I add delays to frames... Delay can be a good idea becouse my sheep slightly twitch.
I like a meditative thing ... */
if(currentDelay <= 0){
if(inverse){
currentFrame--;
} else {
currentFrame++;
}
currentDelay = (randomDelay) ? uint(delays[currentFrame]*Math.random()) : uint(delays[currentFrame]);
// I like random and it make my animation not so repetitive...
// FlashTest.myConsole.clear();
// FlashTest.myConsole.log('next frame delay '+currentDelay);
} else {
currentDelay--;
}
}
private function setCurrentFrame():void // DRY (don't repeat yourself)
{
matrix.tx = -this.currFrame * widthFrame; // positioning data
matrix.ty = -this.currState * heightFrame;
this.bitmapData.fillRect(this.bitmapData.rect, 0); // clear 'wiew window'
this.bitmapData.draw(bitData, matrix);
}
}
}