Creating a parallax on a tiling background - apache-flex

I am using the blitting technique that Jeff from 8bitrocket.com uses for creating tiles. I am trying to paint 2 layers of bitmapdata onto a bitmap. One the first layer is the background ( 1 image). and the second layer is the tiles. In that class below. the updateMap is the method that gets called in the loop to repaint the image.
package com.eapi
{
/**
* ...
* #author Anthony Gordon
*/
import com.objects.XmlManager;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.*;
import flash.display.BitmapData;
import flash.display.Bitmap
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.display.DisplayObject;
public class EngineApi extends MovieClip
{
public var images:Array;
public var world:Array;
//w stands for world, how big it is in columns and rows
private var wCols:Number = 50;
private var wRows:Number = 16;
public var wWidth:Number;
public var wHeight:Number;
//v stands for view, which means your field of view
public var vRows:Number;
public var vCols:Number;
public var vWidth:Number = 540;
public var vHeight:Number = 360;
//how big your indivual tile is
public var tileW:Number = 80;
public var tileH:Number = 80;
public var offsX:Number = 0;
public var offsY:Number = 0;
public var xEnd:Number = 0;
public var yEnd:Number = 0;
public var tilex:int;
public var tiley:int;
public var scrollx:Number = 0;
public var scrolly:Number = 0;
private var screen:Bitmap;
private var canvas:BitmapData;
private var buffer:BitmapData;
public var mapHolder:Array;
private var scrollLoop:Boolean;
private var minLoop:Number;
private var maxLoop:Number;
public var currentMap:Number = 0;
private var queue:Array;
public var currentCol:Number = 0;
public var currentRow:Number = 0;
public var enviroment:Array;
public var currentTileSheet:Number = 0;
private var layer1:Sprite;
private var layer2:Sprite;
private var layer3:Sprite;
private var layer4:Sprite;
private var layer5:Sprite;
public var background:BitmapData
protected var stageObject:Array;
protected var gameObjects:Array;
public function EngineApi(w:Number = 540,h:Number = 360, tw:Number = 50, th:Number = 50)
{
stageObject = new Array();
gameObjects = new Array();
//Add Layers
layer1 = new Sprite();
layer2 = new Sprite();
layer3 = new Sprite();
layer4 = new Sprite();
layer5 = new Sprite();
//end
images = new Array();
vWidth = w;
vHeight = h;
tileW = tw;
tileH = th;
queue = new Array();
mapHolder = new Array();
vCols = Math.floor(vWidth/tileW);
vRows = Math.floor(vHeight/tileH);
wWidth = wCols * tileW;
wHeight = wRows * tileH;
canvas = new BitmapData(vWidth,vHeight,true,0x000000);
buffer = new BitmapData(vWidth + 2 * tileW, vHeight + 2 * tileH ,false,0x000000);
screen = new Bitmap(canvas);
addChild(screen);
addChild(layer1);
addChild(layer2);
addChild(layer3);
addChild(layer4);
addChild(layer5);
}
public function addGameChild(object:IGameObject, layer:Number):void
{
switch(layer)
{
case 1:
layer1.addChild(DisplayObject(object));
break;
case 2:
layer2.addChild(DisplayObject(object));
break;
case 3:
layer3.addChild(DisplayObject(object));
break;
case 4:
layer4.addChild(DisplayObject(object));
break;
case 5:
layer5.addChild(DisplayObject(object));
break;
default:
}
if (object.IsDisplay == true)
gameObjects.push(object);
stageObject.push(object);
}
public function UpDateMap():void
{
offsX += scrollx;
offsY += scrolly;
tilex = int(offsX/tileW);
tiley = int(offsY/tileH);
xEnd = tilex + vWidth;
yEnd = tiley + vHeight;
var tileNum:int;
var tilePoint:Point = new Point(0,0);
var tileRect:Rectangle = new Rectangle(0, 0, tileW, tileH);
var rowCtr:int=0;
var colCtr:int=0;
for (rowCtr=0; rowCtr <= vRows; rowCtr++) {
for (colCtr = 0; colCtr <= vCols; colCtr++) {
currentCol = colCtr+tilex;
currentRow = rowCtr+tiley;
tileNum = mapHolder[currentMap][rowCtr+tiley][colCtr+tilex];
tilePoint.x = colCtr * tileW;
tilePoint.y = rowCtr * tileH;
tileRect.x = int((tileNum % 100))* tileW;
tileRect.y = int((tileNum / 100))* tileH;
buffer.copyPixels(images[currentTileSheet],tileRect,tilePoint);
}
}//End Loop
var bgRect:Rectangle = new Rectangle(0, 0, 544, 510);
var bgPoint:Point = new Point(0, 0);
var bufferRect:Rectangle = new Rectangle(0,0,vWidth,vHeight);
var bufferPoint:Point = new Point();
bufferRect.x = offsX % tileW;
bufferRect.y = offsY % tileH;
canvas.copyPixels(background,bgRect,bgPoint);
canvas.copyPixels(buffer,bufferRect,bufferPoint);
}//End UpdateMap
public function StartRender():void
{
addEventListener(Event.ENTER_FRAME, loop);
}
protected function loop(e:Event):void
{
UpDateMap();
UpdateObjects();
}
protected function UpdateObjects():void
{
for (var i:Number = 0; i < stageObject.length; i++)
{
stageObject[i].UpdateObject();
}
for (var g:Number = 0; g < stageObject.length; g++)
{
if (stageObject[g].Garbage && stageObject[g].IsDisplay)
{
removeChild(DisplayObject(stageObject[g]));
stageObject[g] = null;
}
else if (stageObject[g].Garbage == true && stageObject[g].IsDisplay == false)
{
stageObject[g] = null;
}
}
}
public function StopRender():void
{
removeEventListener(Event.ENTER_FRAME, loop);
}
}
}
It's not the complete code, but if I remove canvas.copyPixels(background,bgRect,bgPoint); or canvas.copyPixels(buffer,bufferRect,bufferPoint); I can see either or. If I paint them both then I can only see the one that painted last. My tile image is 128 x 32. 0 - 3. array 3 is transparent image. I used that hoping that I could see through the image and see the background. I was wrong.
At first it was an all black background, but then I changed the transparent constructor to true on the buffer variable. Now it shows a white background (like the stage), but still no background image.

I'm not sure I completely understand the example, but it looks like the issue is that you're using copyPixels--this should replace the old pixels in the canvas bmp with new values.
Try using draw for the foreground instead:
canvas.copyPixels(background, bgRect, bgPoint);
canvas.draw(buffer, transform, null, null, clipRect);
Also, I'm not sure why you're drawing the background image to a different rect than the foreground? There may be something there.

I took a seperate movieclip and used it as a parallax behind the blitting tiles.

Related

unity 2d auto shadow caster 2d at wall-closed tilemap

https://www.youtube.com/watch?v=0F8boyFinOk&t=12s
While making a roguelike game with Unity2d, I applied an automatic shadow generator to a randomly generated tilemap from the video above. But it doesn't work for tilemaps that are closed due to using the CompositeCollider2d's Path. How do I solve it?
Generated Shadow Shape(outer)
Generated Shadow Shape(inner)
Solved with this code:
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using System.Collections.Generic;
[RequireComponent(typeof(CompositeCollider2D))]
public class AutoShadowClosedTilemap : MonoBehaviour
{
[Space]
[SerializeField]
private bool selfShadows = true;
private CompositeCollider2D tilemapCollider;
private List<Vector2> unionVertices = new();
static readonly FieldInfo meshField = typeof(ShadowCaster2D).GetField("m_Mesh", BindingFlags.NonPublic | BindingFlags.Instance);
static readonly FieldInfo shapePathField = typeof(ShadowCaster2D).GetField("m_ShapePath", BindingFlags.NonPublic | BindingFlags.Instance);
static readonly MethodInfo generateShadowMeshMethod = typeof(ShadowCaster2D)
.Assembly
.GetType("UnityEngine.Rendering.Universal.ShadowUtility")
.GetMethod("GenerateShadowMesh", BindingFlags.Public | BindingFlags.Static);
[ContextMenu("Generate")]
public void Generate()
{
tilemapCollider = GetComponent<CompositeCollider2D>();
if(tilemapCollider.pathCount != 2) {
print("Shadow must be used in one closed tiles. Please erase the other tiles to other Tilemap.");
return;
}
unionVertices.Clear();
DestroyAllChildren();
Vector2[] pathVertices = new Vector2[tilemapCollider.GetPathPointCount(0)];
tilemapCollider.GetPath(0, unionVertices);
tilemapCollider.GetPath(1, pathVertices);
var index = 0;
var endPath = unionVertices[unionVertices.Count - 1];
var length = Vector2.Distance(pathVertices[0], endPath);
for(var i = 1; i < pathVertices.Length; i++) {
var path = pathVertices[i];
var curLen = Vector2.Distance(endPath, path);
if(curLen < length) {
length = curLen;
index = i;
}
}
for(var i = 0; i < pathVertices.Length; i++) {
var path = pathVertices[(i + index) % pathVertices.Length];
unionVertices.Add(path);
}
for(var i = 0; i < unionVertices.Count; i++) {
var cur = unionVertices[i];
var next = unionVertices[(i + 1) % unionVertices.Count];
Debug.DrawLine(cur, cur + (next - cur) * 0.5f, Color.red);
}
var shadowCaster = new GameObject("ShadowCaster");
shadowCaster.transform.parent = gameObject.transform;
shadowCaster.transform.position = Vector3.zero;
ShadowCaster2D shadowCasterComponent = shadowCaster.AddComponent<ShadowCaster2D>();
shadowCasterComponent.selfShadows = this.selfShadows;
var testPath = new Vector3[unionVertices.Count];
var j = 0;
foreach (var path in unionVertices)
{
testPath[j++] = path;
}
shapePathField.SetValue(shadowCasterComponent, testPath);
meshField.SetValue(shadowCasterComponent, new Mesh());
generateShadowMeshMethod.Invoke(shadowCasterComponent, new object[] { meshField.GetValue(shadowCasterComponent), shapePathField.GetValue(shadowCasterComponent) });
Debug.Log("Shadow Generated");
}
public void DestroyAllChildren()
{
var tempList = transform.Cast<Transform>().ToList();
foreach (var child in tempList)
{
DestroyImmediate(child.gameObject);
}
}
}

How can I take a screen shot of entire Screen on regular intervals using Adobe flex and action script

How can I take screen shot of Entire on Screen regular intervals (random between 2 to 5 minutes) without click event using Adobe flex and action script. Currently I am doing it with the Mouse_Up Event and then calling the timer and then saving each image with different name
package
{
import flash.desktop.NativeProcess;
import flash.desktop.NativeProcessStartupInfo;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageDisplayState;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
import flash.events.NativeProcessExitEvent;
import flash.events.TimerEvent;
import flash.filesystem.File;
import flash.system.Capabilities;
import flash.utils.Timer;
public class Grabber extends Sprite
{
private var stageCover:Sprite;
private var captureRect:Sprite;
private var sx:Number;
private var sy:Number;
private var np:NativeProcess;
private var npi:NativeProcessStartupInfo;
public function Grabber()
{
super();
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stageCover = new Sprite();
stageCover.graphics.beginFill(0xFFFFFF, 0.01);
stageCover.graphics.drawRect(0, 0, Capabilities.screenResolutionX, Capabilities.screenResolutionY);
addChild(stageCover);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
captureRect = new Sprite();
captureRect.graphics.lineStyle(2, 0xFFFFFF);
addChild(captureRect);
np = new NativeProcess();
npi = new NativeProcessStartupInfo();
}
private function onTimerComplete( event:TimerEvent):void
{
captureRect.graphics.clear();
var args:Vector.<String> = new Vector.<String>();
args.push("-l");
sx =0;
args.push(sx.toString());
args.push("-t");
sy = 0 ;
args.push(sy.toString());
args.push("-r");
var a:Number = Capabilities.screenResolutionX;
args.push(a.toString());
args.push("-b");
var b:Number= Capabilities.screenResolutionY;
args.push(b.toString());
args.push("-out");
args.push(File.desktopDirectory.nativePath + "/grab.jpeg");
npi.arguments = args;
npi.executable = File.applicationDirectory.resolvePath("GrabberCommand.exe");
np.start(npi);
}
private function onMouseUp(event:MouseEvent):void
{
var timer:Timer=new Timer( 10*1000*Math.random(),1 );
timer.addEventListener( TimerEvent.TIMER, onTimerComplete );
timer.start();
}
}
}
XML Properties are
SystemChrome none
Transparent true
SupportedProfiles extendedDesktop
I actually did something like this before.
You will need a Timer that calls the following function at intervals (whatever intervals you like):
private function captureScreenshots(event:MouseEvent):void
{
var imgEnc:IImageEncoder;
var screenshotArray:Array = new Array();
if(myView.encodingCombo.selectedItem == "PNG")
{
imgEnc = pngEnc; //private const pngEnc:PNGEncoder = new PNGEncoder();
}
else
{
imgEnc = jpgEnc; //private const jpgEnc:JPEGEncoder = new JPEGEncoder();
}
var windowsArray:Array = NativeApplication.nativeApplication.openedWindows;
for each(var window:NativeWindow in windowsArray)
{
if(window && window.stage is IBitmapDrawable)
{
var imageSnapshot:ImageSnapshot = ImageSnapshot.captureImage(window.stage as IBitmapDrawable, 0, imgEnc);
screenshotArray.push(imageSnapshot);
}
}
windowsArray = null;
}
You can then use a FileStream to write them to a directory, but that would be a different question.

Need soution for equalizer in flex?

I have developed a small application for testing 5 band equalizer in flex. I found the code in this link Flex Equalizer
The equalizer works fine.But i am not able to seek the desired position while playing the mp3 file.Following is my code....How to solve this problem?
import __AS3__.vec.Vector;
import mx.events.FlexEvent;
import spark.components.VSlider;
public static const BUFFER_SIZE:int = 8192;
public static const SAMPLE_RATE:int = 44100;
private var _Position:Number=0;
private var timer:Timer = new Timer(1000);
private const _soundURI:String = "testfile.mp3";
private var _out_snd:Sound = new Sound();
private const _eqL:EQ = new EQ();
private const _eqR:EQ = new EQ();
private var _loop_snd:Sound = new Sound();
// For storing dynamically created VSliders
private const _sliders_vect:Vector.<VSlider> = new Vector.<VSlider>();
private var _channel:SoundChannel = new SoundChannel();
private var _samples:ByteArray;
protected function view1_initializeHandler(event:FlexEvent):void
{
// TODO Auto-generated method stub
timer.addEventListener(TimerEvent.TIMER,timerFunction);
pgHolder.addEventListener(MouseEvent.CLICK,seekf);
setupEQ();
loadSound();
}
private function timerFunction(event:TimerEvent):void
{
_Position = _channel.position;
pgHolder.value=_Position;
}
private function seekf(event:MouseEvent):void
{
_channel.stop();
_Position = (pgHolder.contentMouseX/pgHolder.width)*_loop_snd.length;
startPlay();
}
private function loadSound():void
{
_Position=0;
_loop_snd.addEventListener(Event.COMPLETE, loadSoundComplete);
_loop_snd.addEventListener(IOErrorEvent.IO_ERROR, loadSoundError);
_out_snd.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound);
_loop_snd.load(new URLRequest(_soundURI));
}
private function loadSoundComplete(event:Event):void
{
pgHolder.minimum=0;
pgHolder.maximum=_loop_snd.length;
timer.start();
startPlay();
}
private function startPlay():void
{
_channel=_out_snd.play(_Position);
}
private function loadSoundError(event:Event):void
{
trace("loadError");
}
// Create Sliders for changing EQ gain
private function setupEQ():void
{
var slider:VSlider;
for (var i:int = 0; i < _eqL.gains.length; i++) {
slider = new VSlider();
slider.x = (i * 35);
slider.y = 20;
slider.value = .9;
slider.maximum = 1;
slider.snapInterval=0.1;
slider.minimum = 0;
slider.addEventListener("change", changeEQHandler);
addElement(slider);
_sliders_vect[i] = slider;
}
var event:Event = new Event("change");
changeEQHandler(event);
}
private function processSound(event:SampleDataEvent):void
{
//trace("loading");
if(_Position>=_loop_snd.length)
{
_channel.stop();
}
_samples = new ByteArray();
var len:Number = _loop_snd.extract(_samples,BUFFER_SIZE);
var i:int=0;
var l:Number;
var r:Number;
if ( len < BUFFER_SIZE ) { // If end of MP3, start over
len += _loop_snd.extract(_samples,BUFFER_SIZE-len,0);
}
_samples.position = 0;
trace("len" + len + "//" + _channel.position + "//" +_samples.length);
while (i < BUFFER_SIZE) {
event.data.writeFloat(_eqL.compute(_samples.readFloat()));
event.data.writeFloat(_eqR.compute(_samples.readFloat()));
i++;
}
}
// Update EQ gains when sliders are changed
private function changeEQHandler(event:Event):void
{
var i:int = 0;
for(i = 0; i < _eqL.gains.length; i++){
_eqL.gains[i] = _sliders_vect[i].value * 2;
}
for(i = 0; i < _eqR.gains.length; i++){
_eqR.gains[i] = _sliders_vect[i].value * 2;
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:HSlider width="100%" height="100%" id="pgHolder">
</s:HSlider>
When you handle the slider change, I see you calculate the new _Position, but _Position is not bindable and its never used set set the player position.
This is just pseudo-code, but shouldn't you do something like:
private function seekf(event:MouseEvent):void
{
_channel.stop();
_channel.position = (pgHolder.contentMouseX/pgHolder.width)*_loop_snd.length;
_channel.start();
}
Just looking at your code, when you set _Position = _channel.position, you are simply getting a value, not a reference. My guess is that you need to set _channel.position

How should I set up my touch controls in starling?

I am developing a game in starling that has two controls. One will be the users left thumb touching anywhere on the left side of the screen, which drags the character up and down the y axis. The other control that I am having trouble implementing is a single button in the bottom right of the screen that will make the character fire a bullet.
My question is how do I set this up without having the character jump down to the bottom of the screen whenever the button is pressed.
Will I need to mess with multi-touch in order to get this running?
A more specific question I have is how do I define a rectangle for a sprite in starling? Since starling has no drawing API, I can't just do this...
touchLayer.graphics.beginFill(0x000000, 0);
touchLayer.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
touchLayer.graphics.endFill();
Currently my character drag is working, but the touch registers everywhere on the screen (im not sure how to make it just the left side of the screen...)
Any advise would be appreciated, thank you.
Here is the complete code for my InGame class as requested.
package screens
{
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.getTimer;
import objects.Enemy;
import objects.GameBackground;
import objects.Laser;
import objects.Scarlet;
import objects.SnowBall;
import starling.display.Button;
import starling.display.Sprite;
import starling.events.Event;
import starling.events.Touch;
import starling.events.TouchEvent;
import starling.utils.RectangleUtil;
import starling.utils.deg2rad;
public class InGame extends Sprite
{
private var startBtn:Button;
private var fireBtn:Button;
private var bg:GameBackground;
private var scarlet:Scarlet;
private var enemies:Array;
private var lasers:Array;
private var scarletLocation:Point;
private var lasersLayer:Sprite;
private var enemiesLayer:Sprite;
private var touchLayer:Sprite;
private var enemySpawnDelay:Number;
private var enemySpawnCounter:Number;
private var difficulty:Number;
private var difficultyRate:Number;
private var timePrevious:Number;
private var timeCurrent:Number;
private var elapsed:Number;
private var gameState:String;
private var playerSpeed:Number;
private const MIN_SPEED:Number = 650;
//private var scoreDistance:int;
private var gameArea:Rectangle;
private var touchArea:Rectangle;
private var shape:starling.display.Sprite = new starling.display.Sprite();
private var target:Point = new Point(100, 100);
private var touch:Touch;
private var touchX:Number;
private var touchY:Number;
public function InGame()
{
super();
this.addEventListener(starling.events.Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(event:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
drawGame();
}
private function drawGame():void
{
bg = new GameBackground();
this.addChild(bg);
scarlet = new Scarlet;
scarlet.x = stage.stageWidth/2;
scarlet.y = stage.stageHeight/2;
this.addChild(scarlet);
startBtn = new Button(Assets.getTexture("PlayBtn"));
startBtn.x = stage.stageWidth * 0.5 - startBtn.width * 0.5;
startBtn.y = stage.stageHeight * 0.5 - startBtn.height * 0.5 + 35;
this.addChild(startBtn);
fireBtn = new Button(Assets.getTexture("FireBtn"));
fireBtn.x = 675;
fireBtn.y = 435;
this.addChild(fireBtn);
//defines area scarlet can fly in
gameArea = new Rectangle(0, 15, stage.stageWidth, stage.stageHeight - 150);
}
public function disposeTemporarily():void
{
this.visible = false;
}
public function initialize():void
{
this.visible = true;
this.addEventListener(Event.ENTER_FRAME, checkElapsed);
scarlet.x = -stage.stageWidth;
scarlet.y = stage.stageHeight * 0.5;
gameState = "idle";
playerSpeed = 0;
difficultyRate = 0.3;
difficulty = 1;
enemySpawnDelay = enemySpawnCounter = 100;
enemies = new Array();
lasers = new Array();
scarletLocation = new Point(200, 400);
addEventListener(Event.ENTER_FRAME, update);
lasersLayer = new Sprite();
enemiesLayer = new Sprite();
touchLayer = new Sprite();
addChild(lasersLayer);
addChild(enemiesLayer);
addChild(touchLayer);
addEventListener(Event.ADDED_TO_STAGE, setupTouchLayer);
touchLayer.addEventListener(Event.TRIGGERED, shootLaser);
//scoreDistance = 0;
startBtn.addEventListener(Event.TRIGGERED, onStartBtnClick);
this.addEventListener(TouchEvent.TOUCH, onTouch);
}
private function onStartBtnClick(event:Event):void
{
startBtn.visible = false;
startBtn.removeEventListener(Event.TRIGGERED, onStartBtnClick);
launchScarlet();
}
private function launchScarlet():void
{
this.addEventListener(TouchEvent.TOUCH, onTouch);
this.addEventListener(Event.ENTER_FRAME, onGameTick);
}
private function onTouch(event:TouchEvent):void
{
touch = event.getTouch(stage);
touchX = touch.globalX;
touchY = touch.globalY;
target.x = event.touches[0].globalX;
target.y = event.touches[0].globalY;
}
private function onGameTick(event:Event):void
{
switch(gameState)
{
case"idle":
//Take off
if (scarlet.x < stage.stageWidth * 0.5 * 0.5)
{
scarlet.x += ((stage.stageWidth * 0.5 * 0.5 + 10) - scarlet.x) * 0.5;
scarlet.y = stage.stageHeight * 0.5;
playerSpeed += (MIN_SPEED - playerSpeed) * 0.05;
}
else
{
gameState = "flying";
}
break;
case"flying":
playerSpeed -= (playerSpeed - MIN_SPEED) * 0.01;
scarlet.y -= (scarlet.y - touchY) * 0.1;
if (-(scarlet.y - touchY) < 150 && -(scarlet.y - touchY) > -150)
{
scarlet.rotation = deg2rad(-(scarlet.y - touchY) * 0.075);
}
if (scarlet.y > gameArea.bottom - scarlet.height * 0.5)
{
scarlet.y = gameArea.bottom - scarlet.height * 0.5;
scarlet.rotation = deg2rad(0);
}
if (scarlet.y < gameArea.top + scarlet.height * 0.5)
{
scarlet.y = gameArea.top + scarlet.height * 0.5;
scarlet.rotation = deg2rad(0);
}
//scoreDistance += (playerSpeed * elapsed) * 0.1;
//trace(scoreDistance);
break;
case"over":
break;
}
}
//addapted from "Shoot"
private function setupTouchLayer(event:Event):void
{
touchLayer.graphics.beginFill(0x000000, 0);
touchLayer.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
touchLayer.graphics.endFill();
touchArea = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
}
private function shootLaser(event:TouchEvent):void
{
makeLaser(scarletLocation);
}
private function makeLaser(scarletLocation:Point):void
{
var newLaser:Laser = new Laser();
newLaser.x = scarletLocation.x;
newLaser.y = scarletLocation.y;
newLaser.xVel = 5;
newLaser.yVel = 5;
newLaser.addEventListener(Laser.PURGE_EVENT, purgeLaserHandler);
lasersLayer.addChild(newLaser);
lasers.push(newLaser);
}
private function purgeLaserHandler(event:Event):void
{
var targetLaser:Laser = Laser(event.target);
purgeLaser(targetLaser);
}
private function purgeLaser(targetLaser:Laser):void
{
targetLaser.removeEventListener(Laser.PURGE_EVENT, purgeLaserHandler);
try
{
var i:int;
for (i = 0; i < lasers.length; i++)
{
if (lasers[i].name == targetLaser.name)
{
lasers.splice(i, 1);
lasersLayer.removeChild(targetLaser);
i = lasers.length;
}
}
}
catch(e:Error)
{
trace("Failed to delete laser!", e);
}
}
private function makeEnemies():void
{
enemySpawnCounter++;
if (enemySpawnCounter > enemySpawnDelay)
{
enemySpawnCounter = 0;
enemySpawnDelay -= difficultyRate;
difficulty += difficultyRate;
makeEnemy();
}
}
private function makeEnemy():void
{
var i:int;
for (i = 0; i < Math.floor(difficulty); i++)
{
var newEnemy:Enemy = new SnowBall();
newEnemy.x = 925;
newEnemy.y = Math.random() * 375 + 50;
//trace(newEnemy.x); trace(newEnemy.y);
newEnemy.xVel = (-Math.random() * difficulty) - 5;
newEnemy.sinMeter = Math.random() * 10;
newEnemy.bobValue = Math.random() * difficulty;
newEnemy.addEventListener(Enemy.PURGE_EVENT, purgeEnemyHandler);
enemiesLayer.addChild(newEnemy);
enemies.push(newEnemy);
}
}
private function purgeEnemyHandler(event:Event):void
{
var targetEnemy:Enemy = Enemy(event.target);
purgeEnemy(targetEnemy);
}
private function purgeEnemy(targetEnemy:Enemy):void
{
targetEnemy.removeEventListener(Enemy.PURGE_EVENT, purgeLaserHandler);
try
{
var i:int;
for (i = 0; i < enemies.length; i++)
{
if (enemies[i].name == targetEnemy.name)
{
enemies.splice(i, 1);
enemiesLayer.removeChild(targetEnemy);
i = enemies.length;
}
}
}
catch(e:Error)
{
trace("Failed to delete enemy!", e);
}
}
private function newHitTest(laser:Laser):void
{
for each (var enemy:Enemy in enemies)
{
if (enemy.status != "Dead" && enemy.hitTest(new Point(laser.x, laser.y)))
{
enemy.destroy();
purgeLaser(laser);
}
}
}
private function checkElapsed(event:Event):void
{
timePrevious = timeCurrent;
timeCurrent = getTimer();
elapsed = (timeCurrent - timePrevious) * 0.001;
}
private function update():void
{
//trace(enemies.length, lasers.length);
for each (var enemy:Enemy in enemies)
{
enemy.update();
}
for each (var laser:Laser in lasers)
{
laser.update();
newHitTest(laser);
}
makeEnemies();
}
//addapted from "Shoot"
}
}
Oh wow, well a very simple way to solve this problem is to simply enable multi-touch.
Starling.multitouchEnabled = true;
However this still leaves the problem of my character jumping to the bottom of the screen when I press the button in the bottom right IF I am not touching the screen already to control the character... not really a big deal but it would look better if this didn't happen.

What's wrong with my animation function?

It animates but it put's the piece of the sprite sheet where it is on the sprite sheet and not where the x and y tell it to. It's very short, so please take a look? Thank you in advance.
package cyanprime{
import flash.display.*;
import flash.geom.Rectangle;
public class Player{
[Embed(source="brownplane.png")]
public var image:Class;
public var bitmapdata:BitmapData = getBitmap(new image());
public var bitmap:Bitmap = new Bitmap(bitmapdata);
public var speed:int = 5;
public var x:int = 50;
public var y:int = 50;
public var frame:int = 0;
public function getBitmap(img:DisplayObject):BitmapData{
var drawRect:Rectangle = new Rectangle((img.width/3) * frame, 0, img.width/3, img.height);
var bitmap:BitmapData = new BitmapData(img.width, img.height);
bitmap.draw(img,null,null,null,drawRect);
return bitmap;
}
public function animate():void{
bitmap.bitmapData = getBitmap(new image());
frame++;
if(frame > 2)
frame = 0;
bitmap.x = x;
bitmap.y = y;
}
}
}
Looks like you need to add a matrix transform to draw() to translate the position of the rectangle being drawn. Something like this:
var trans:Matrix = new Matrix();
trans.tx = drawRect.x;
bitmap.draw(img,trans,null,null,drawRect);
If that doesn't work, try -drawRect.x, I can't exactly remember how that transform is applied.

Resources