package { import flash.display.*; import flash.events.*; import flash.filters.*; import flash.geom.*; import flash.system.*; import flash.text.*; import flash.ui.Keyboard; import flash.utils.*; [SWF(backgroundColor="0x000000",width="920",height="500",frameRate="40")] public class Main extends Sprite { private var worldWidth:Number = 400; // width of world, in pixels private var worldHeight:Number = 400; // height of world, in pixels private var mapDisplayWidth:Number = 520; // width of displayed game area, in pixels private var mapDisplayHeight:Number = 400; // height of displayed game area, in pixels private var tilesAcross:Number; // width of displayed portion of world, in visible tiles private var tilesDown:Number; // height of displayed portion of world, in visible tiles private var tileWidth:Number = 64; // width of each tile, in pixels private var tileHeight:Number = 64; // height of each tile, in pixels private var displayXOffset:Number = 0; // Amount the visible map has scrolled X, modulo tileWidth private var displayYOffset:Number = 0; // Amount the visible map has scrolled Y, modulo tileHeight private var worldBitmapData:BitmapData; // bitmapData containing world color map private var displayBitmapData:BitmapData; // bitmapData containing shaded world map for display private var worldBitmap:Bitmap; private var world:Sprite; // private var tiles:Array; private var currentMinX:Number = 0; // left pixel of viewable area of world bitmap private var currentMinY:Number = 0; // top pixel of viewable area of world bitmap private var currentMaxX:Number = 0; // right pixel of viewable area of world bitmap private var currentMaxY:Number = 0; // bottom pixel of viewable area of world bitmap private var centerLocationX:Number = 0; // X coordinate of the ship on the world grid private var centerLocationY:Number = 0; // Y coordinate of the ship on the world grid private var mapBitmapData:BitmapData; // "blown up" view of the world private var mapBitmap:Bitmap; private var locator:Shape; private var debugOutput:TextField; private var debugButton:Sprite; private var paletteShape:Shape; private var paletteBitmapData:BitmapData; private var paletteColors:Array; // array of color numbers private var textureTiles:Array; // array of colored and textured tiles for the play map private var ship:Sprite; private var isLeft:Boolean = false; private var isRight:Boolean = false; private var isUp:Boolean = false; private var isDown:Boolean = false; private var angle:Number = 0; // in radians private var turnSpeed:Number = 0; // how sharp a curve can we turn private var friction:Number = .2; // how fast can we slow private var acceleration:Number = .1; // how fast can we speed up private var currentSpeed:Number = 0; // current movement speed private var minSpeed:Number = 0; // minimum speed before stopping private var maxSpeed:Number = 5; // maximum allowable speed private var r2d:Number = 180 / Math.PI private var d2r:Number = Math.PI / 180; private var steps:Number = 120; private var step:Number = Math.PI*2/steps; private var mainTimer:Timer; private var hasChangedCoordinate:Boolean = false; // have I moved to a new world map coordinate? private var encounterChance:Number = .1; private var tileRect:Rectangle = new Rectangle(0,0,tileWidth,tileHeight); private var tilePoint:Point; public function Main() { addEventListener(Event.ENTER_FRAME,init); } private function init(e:Event):void { if(!stage) return; removeEventListener(Event.ENTER_FRAME,init); createButtons(); createDebugger(); initializeVariables(); createMapBitmapData(); createWorldDisplayGrid(); createShip(); stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); mainTimer = new Timer(20); mainTimer.addEventListener(TimerEvent.TIMER,mainLoop); mainTimer.start(); } private function createButtons():void { var resetButton:Sprite = new Sprite(); resetButton.graphics.beginFill(0xcccccc,1); resetButton.graphics.drawRect(0,0,50,20); resetButton.graphics.endFill(); resetButton.buttonMode=true; resetButton.addEventListener(MouseEvent.CLICK,onResetButtonClicked); resetButton.mouseChildren = false; resetButton.x=750; resetButton.y=stage.stageHeight-20; var rt:TextField = new TextField(); rt.width=50; rt.height=20; rt.text="RESET"; resetButton.addChild(rt); addChild(resetButton); } private function onKeyDown(e:KeyboardEvent):void { switch(e.keyCode) { case Keyboard.LEFT: isLeft = true; break; case Keyboard.RIGHT: isRight = true; break; case Keyboard.UP: isUp = true; break; case Keyboard.DOWN: isDown = true; break; default: break; } } private function onKeyUp(e:KeyboardEvent):void { switch(e.keyCode) { case Keyboard.LEFT: isLeft = false; break; case Keyboard.RIGHT: isRight = false; break; case Keyboard.UP: isUp = false; break; case Keyboard.DOWN: isDown = false; break; default: break; } } private function createShip():void { ship = new Sprite(); ship.graphics.lineStyle(0,0x000000,1); ship.graphics.beginFill(0xcccccc,1); ship.graphics.moveTo(-10,-10); ship.graphics.lineTo(20,0); ship.graphics.lineTo(-10,10); ship.graphics.lineTo(-10,-10); ship.graphics.endFill(); addChild(ship); ship.x = Math.floor(mapDisplayWidth/2); ship.y = Math.floor(mapDisplayHeight/2); addChild(ship); } private function initializeVariables():void { displayXOffset = 0; displayYOffset = 0; currentMinX = Math.floor(worldWidth/2); currentMinY = Math.floor(worldHeight/2); currentMaxX = 0; currentMaxY = 0; createColorPalette(); createTileTextures(); } private function createColorPalette():void { paletteColors = []; paletteShape = new Shape(); var m:Matrix = new Matrix(); m.createGradientBox(256,1,0,0,0); paletteShape.graphics.beginGradientFill( GradientType.LINEAR, [0x0000a8,0x0043ff,0x51c9fe,0x4c9329,0x6f9645,0xbfad6f,0xf0d5a0,0xfeecd6], [1,1,1,1,1,1,1,1], [0,30,60,70,100,160,200,255], m ); paletteShape.graphics.drawRect(0,0,256,1); paletteShape.graphics.endFill(); paletteBitmapData = new BitmapData(256,1); paletteBitmapData.draw(paletteShape); } private function createTileTextures():void { textureTiles = []; var randomSeed:Number = Math.round(Math.random()*10000); var baseTextureTile:BitmapData = new BitmapData(tileWidth,tileHeight); baseTextureTile.perlinNoise( tileWidth, // baseX tileHeight, // baseY 5, // numOctaves randomSeed, // randomSeed true, // stitch true, // fractalNoise on or off 7, // channelOptions true // grayScale ); for(var i:Number = 0;i<256;i++) { textureTiles[i] = baseTextureTile.clone(); var ct:ColorTransform = new ColorTransform(.25,.25,.25,1, paletteBitmapData.getPixel32(i,0)>>16 & 0xff, paletteBitmapData.getPixel32(i,0)>>8 & 0xff, paletteBitmapData.getPixel32(i,0) & 0xff, 255 ); paletteColors.push(paletteBitmapData.getPixel32(i,0)); textureTiles[i].colorTransform(tileRect,ct); } } private function createMapBitmapData():void { // create the bitmap which contains the world information var rectangle:Rectangle = new Rectangle(0,0,worldWidth,worldHeight); var point:Point = new Point(0,0); var currentColor:Number; if(worldBitmapData) worldBitmapData.dispose(); if(displayBitmapData) displayBitmapData.dispose(); worldBitmapData = new BitmapData(worldWidth,worldHeight,true,0x00000000); displayBitmapData = new BitmapData(worldWidth,worldHeight,true,0x00000000); var tempBitmapData:BitmapData = new BitmapData(worldWidth,worldHeight,true,0x00000000); var seed:Number = Math.round(Math.random()*1000000000); updateDebugger("Seed : " + seed,true); worldBitmapData.perlinNoise( worldWidth/1.5, // baseX worldHeight/1.5, // baseY 9, // numOctaves seed, // randomSeed false, // stitch false, // fractalNoise on or off 7, // channelOptions true // grayScale ); tempBitmapData.draw(worldBitmapData); displayBitmapData.draw(worldBitmapData); var tempBitmapDatas:Array = []; for(var i:int=0;i<255;i++) { tempBitmapDatas[i] = new BitmapData(worldWidth,worldHeight,true,0x00000000); currentColor = 0xff<<24 | i<<16 | i<<8 | i; tempBitmapDatas[i].threshold( tempBitmapData, rectangle, point, "==", currentColor, paletteBitmapData.getPixel32(i,0), 0xff0000, false ); worldBitmapData.copyPixels(tempBitmapDatas[i],tempBitmapDatas[i].rect,new Point(0,0),null,null,true); tempBitmapDatas[i].applyFilter(tempBitmapDatas[i],rectangle,point,new DropShadowFilter(1,45,0x000000,.1,1,1)); displayBitmapData.copyPixels(tempBitmapDatas[i],tempBitmapDatas[i].rect,new Point(0,0),null,null,true); tempBitmapDatas[i].dispose(); } tempBitmapData.dispose(); worldBitmap = new Bitmap(displayBitmapData); addChildAt(worldBitmap,0); worldBitmap.x = stage.stageWidth-worldBitmap.width; worldBitmap.y = 0; } private function onResetButtonClicked(e:Event):void { createMapBitmapData(); } private function createWorldDisplayGrid():void { // create the map, which holds the grid of tiles mapBitmapData = new BitmapData(mapDisplayWidth,mapDisplayHeight,false,0xffff0000); var c:Number; var r:Rectangle; tilesAcross = (mapDisplayWidth / tileWidth) + 2; tilesDown = (mapDisplayHeight / tileHeight) + 2; currentMaxX = currentMinX + tilesAcross; currentMaxY = currentMinY + tilesDown; locator = new Shape(); locator.graphics.clear(); locator.graphics.lineStyle(0,0x660000,.5) locator.graphics.drawRect(0,0,tilesAcross,tilesDown); addChild(locator); for(var i:Number = 0;i maxSpeed) currentSpeed = maxSpeed; } } else { if(currentSpeed > minSpeed) { currentSpeed -= friction; if(currentSpeed < minSpeed)currentSpeed = minSpeed; } } displayXOffset -= (currentSpeed*Math.cos(angle)); displayYOffset -= (currentSpeed*Math.sin(angle)); hasChangedCoordinate = false; if(displayXOffset < -tileWidth) { displayXOffset += tileWidth; currentMinX++; currentMaxX++; hasChangedCoordinate = true; } else if(displayXOffset > 0) { displayXOffset -= tileWidth; currentMinX--; currentMaxX--; hasChangedCoordinate = true; } if(displayYOffset < -tileHeight) { displayYOffset += tileHeight; currentMinY++; currentMaxY++; hasChangedCoordinate = true; } else if(displayYOffset > 0) { displayYOffset -= tileHeight; currentMinY--; currentMaxY--; hasChangedCoordinate = true; } centerLocationX = Math.round((currentMinX+currentMaxX)/2); centerLocationY = Math.round((currentMinY+currentMaxY)/2); if(hasChangedCoordinate == true) checkForEncounters(); } private function checkForEncounters():void { var ec:Number = paletteColors.indexOf(worldBitmapData.getPixel32(centerLocationX,centerLocationY)); updateDebugger("You are at\nx : " + centerLocationX + "\ny : " + centerLocationY + "\nz : " + ec,true); } private function updateBitmap():void { locator.x = currentMinX+worldBitmap.x; locator.y = currentMinY+worldBitmap.y; var c:Number; var ox:Number; mapBitmapData.lock(); for(var i:Number = currentMinX;i