To clarify, the button is NOT a user interface element. It is an in-game object.
Here's a picture of the issue : It shows my main problem; I pressed the button that's circled, but it activated the one on the right.
I'm making a game where you have to complete 10 "chambers" of varying difficulty.
I have currently finished the first level and while finishing up I found an annoying bug I cant seem to fix.
If I have two buttons on a map, it seems that no matter which button I press, it will always do whatever the last one put on the map is going to do.
Also, if one button is activated, the other can't be activated.
I'm using the flashpunk engine/library/whatever and AS3.
The button class:
package Sprites
{
import net.flashpunk.Entity;
import net.flashpunk.graphics.Tilemap;
import net.flashpunk.masks.Grid;
import net.flashpunk.*;
/**
* ...
* #author Brad
*/
public class Button extends Entity
{
public var _tiles:Tilemap
private var _grid:Grid
private var xa:Number
private var ya:Number
private var conTiles:Array
public function Button(xN:Number, yN:Number, tiles:Array)
{
xa = xN
ya = yN
conTiles = []
_tiles = new Tilemap(Assets.Switch, 640, 480, 32, 32)
graphic = _tiles;
layer = 1
conTiles = tiles
_tiles.setTile(xN, yN, 0)
_grid = new Grid(640, 480, 32, 32, 0, 0)
mask = _grid
_grid.setTile(xN, yN, true)
name = "Button"
type = "button"
}
public function Activate():void
{
var Activated:Boolean = false
if (!Activated)
{
for (var i:Number = 0; i < conTiles.length; i++)
{
trace("Hi!")
FP.world["map"]["_tiles"].setTile(conTiles[i].x, conTiles[i].y, 3)
FP.world["map"]["_grid"].setTile(conTiles[i].x, conTiles[i].y, false)
}
_tiles.setTile(xa, ya, 1)
Activated = true
}
else
trace("Activated already!")
}
}
}
How I put the buttons into the world:
public class World1 extends World
{
public var startPos:Object = {"x": 45, "y": 135}
public var player:Player = new Player(startPos["x"], startPos["y"])
public var button:Button = new Button(5, 6, [new Point(10, 10), new Point(10, 11)])
public var button2:Button = new Button(7, 6, [new Point(10, 10), new Point(10, 11)])
public var map:Map1 = new Map1()
public var finish:Finish = new Finish(14,2,"map1")
public function World1()
{
add(map)
add(finish)
add(button)
add(button2)
add(player)
player.layer = 0
for (var i2:Number = 0; i2 < 9; i2++)
add(new Wall3D(i2+1, 1))
for (var i3:Number = 0; i3 < 11; i3++)
add(new Wall3D(i3, 13))
trace("Hi!")
}
}
Related
I'm embedding an image, creating a grid, and trying to cast each embedded image as a DisplayObject so I can use MouseEvents on each image in the grid, however, I can't get a mouseEvent to work. Any help is greatly appreciated. I think I'm missing something simple perhaps.
public class ImageGrid extends Sprite
{
private var gridItems:Array;
private var grid:Sprite;
private var sprite:Sprite
private var reveals:uint = 0;
private var exceededNumReveals:SimpleText;
[Embed(source="../Assets/images/tile-grad5-108.png")]
public var imgCls:Class;
public function ImageGrid(tileSize:Number, numTiles:Number, rows:Number)
{
gridItems = new Array();
grid = new Sprite();
addChild(grid);
for (var i:int = 0; i < numTiles; i++) {
gridItems[i] = new imgCls() as DisplayObject;
trace(gridItems[i] is DisplayObject) //true
gridItems[i].rotation = 180
gridItems[i].x = (i % rows) * (tileSize)
gridItems[i].y = int(i / rows) * (tileSize)
gridItems[i].addEventListener(MouseEvent.CLICK, gridItemClick, false, 0, false);
grid.addChild(gridItems[i]);
}
}
private function gridItemClick (event:MouseEvent):void {
trace(event.currentTarget);
reveals ++
if (reveals < AssetManager.numReveals) {
TweenLite.to(event.currentTarget, 0.5, {y:900,rotation:Math.random() * 360, ease:Sine.easeOut});
} else {
exceededNumReveals = new SimpleText ('You have exceeded your number of reveals', false, false, null, true, true, false, null, null, 20, 'right');
exceededNumReveals.y = this.y + 300;
exceededNumReveals.x = this.x + 30;
addChild(exceededNumReveals)
}
}
}
}
Here is how I fixed it:
public function ImageGrid(tileSize:Number, numTiles:Number, rows:Number)
{
gridItems = new Array();
grid = new Sprite();
addChild(grid);
for (var i:int = 0; i < numTiles; i++) {
var imageHolder:Sprite = new Sprite()
gridItems[i] = new imgCls() as DisplayObject;
gridItems[i].rotation = 180
gridItems[i].x = (i % rows) * (tileSize)
gridItems[i].y = int(i / rows) * (tileSize)
imageHolder.addChild(gridItems[i]);
imageHolder.addEventListener(MouseEvent.CLICK, gridItemClick, false, 0, false);
grid.addChild(imageHolder);
}
}
Wrap them in an interactive object (MovieClip, Sprite, etc.) to add a Mouse Click Event to them. Bitmaps are not interactive objects.
bitmaps are not interactive objects, you will have to add the listener to the parent
The main goal of my code is to create a 3x3 grid and when you click a cell from that grid you cant click it again even if you close the fla and load it again.
Something like a shop where the 1st row is level1 of the upgrade and the columns are the other levels.
There are also 2-3 other things that it does -> every cell of the grid has 4 mouseStates.
Also at the 1st load of the FLA you create the 3x3 grid and you can click only on the elements in the 1st row.(you cant get Speed 2 if you didnt have Speed1 before that.)
So you can click the 2nd element of a column only if the 1st element of the same column has been clicked before.
The same goes for the 3rd element of the column -> it can be clicked only if the 2nd was clicked before.
But im having trouble with the logic after loading the fla for the 2nd time.
To be more specific :
It is changing the mouseOver/out states on the elements that were clicked before(which is good (cause i want to see that)), but it is leting me click only the 1st row.And since Im loading the clickedBefore buttons and removing the mouseEvent.CLICK from them, I cant click some of them if i haven`t clicked them at the 1st load of the fla.
I have 2 classes: Main
import flash.events.Event;
import flash.events.MouseEvent;
import flash.utils.getDefinitionByName;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.Graphics;
import flash.display.Bitmap;
import flash.display.SimpleButton;
import flash.net.SharedObject;
public class Main extends Sprite
{
private var elementRow:int = 0;
private var elementCol:int = 0;
private var myClassImage_Arr:Array = new Array();//this contains the different mouseState Images in Class data.
private var myBitmapNames_Arr:Array = ["speed1_", "speed2_", "speed3_",
"time1_", "time2_", "time3_",
"turbo1_", "turbo2_", "turbo3_",];
//------------------------------------------
private var index:int = 0;
private var col:int = 3;
private var row:int = 3;
//------------------------------------------
private var savedData:SharedObject = SharedObject.getLocal("ZZZ_newWAY_nextButton+imageChange_7");
private var buttonThatHaveBeenClicked_Arr:Array = [];
private var myButtons_Arr:Array = [];
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
for (var i:int = 0; i < col; i++)
{
var lastRowElement:BitmapButton = null;
for (var j:int = 0; j < row; j++)
{
for (var k:int = 0; k < 4; k++)//4states of mouse
{
var cls:Class = Class(getDefinitionByName(myBitmapNames_Arr[index] + k));
myClassImage_Arr.push(cls);
}
var myImage_mc = new BitmapButton(myClassImage_Arr[0 + (index * 4)],
myClassImage_Arr[1 + (index * 4)],
myClassImage_Arr[2 + (index * 4)],
myClassImage_Arr[3 + (index * 4)], i, j);
myImage_mc.x = 100 + i * (myImage_mc.width + 10);
myImage_mc.y = 100 + j * (myImage_mc.height + 10);
myImage_mc.name = "myImage_mc" + index;
this.addChild(myImage_mc);
myButtons_Arr.push(myImage_mc)
myImage_mc.mouseEnabled = false;
myImage_mc.mouseChildren = false;
myImage_mc.buttonMode = false;
myImage_mc.addEventListener("send_SOS", onCustomClick);
if ( lastRowElement == null )
{
myImage_mc.mouseEnabled = true;
myImage_mc.mouseChildren = true;
myImage_mc.buttonMode = true;
}
else
{
lastRowElement.next_1 = myImage_mc;
}
lastRowElement = myImage_mc;
index++;
}
}
if(savedData.data.myArray == undefined) trace(" 1st time loading this game\n")
else if(savedData.data.myArray != undefined)
{
trace(" Game was played before\n")
buttonThatHaveBeenClicked_Arr = savedData.data.myArray;
var savedData_length:int = savedData.data.myArray.length;
trace("Buttons that have been clicked before: " + buttonThatHaveBeenClicked_Arr + "\n");
for (var m:int = 0; m < myButtons_Arr.length; m++)
{
var myButtons_ArrName:String = myButtons_Arr[m].name
for (var p:int = 0; p < savedData_length; p++)
{
if(myButtons_ArrName == savedData.data.myArray[p])
{
myButtons_Arr[m].alpha = 0.9
myButtons_Arr[m].buttonMode = false;
myButtons_Arr[m].removeEventListener("send_SOS", onCustomClick);
myButtons_Arr[m].myInsideBtn.upState = myButtons_Arr[m].image3
myButtons_Arr[m].myInsideBtn.overState = myButtons_Arr[m].image4
}
}
}
}
}
private function onCustomClick(ev:Event):void
{
trace(ev.target.name);
if (ev.target is BitmapButton)
{
var btn:BitmapButton = ev.currentTarget as BitmapButton;
if (btn.next_1 != null)
{
btn.next_1.mouseEnabled = true;
btn.next_1.mouseChildren = true;
btn.next_1.buttonMode = true;
}
btn.mouseChildren = false;
btn.buttonMode = false;
btn.removeEventListener("send_SOS", onCustomClick);
buttonThatHaveBeenClicked_Arr.push( btn.name );
savedData.data.myArray = buttonThatHaveBeenClicked_Arr;
savedData.flush();
savedData.close();
}
}
}
}
and BitmapButton
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.events.Event;
public class BitmapButton extends Sprite
{
public var next_1:BitmapButton = null;
//-----------------------------------
public var myInsideBtn:SimpleButton = new SimpleButton();
private var image1:Bitmap;
private var image2:Bitmap;
public var image3:Bitmap;
public var image4:Bitmap;
public var imageIsInRow:int;
public var imageIsInCol:int;
public function BitmapButton(active_OutState:Class, active_OverState:Class, notActive_OutState:Class, notActive_OverState:Class,col:int,row:int)
{
image1 = new Bitmap (new active_OutState() );
image2 = new Bitmap (new active_OverState() );
image3 = new Bitmap (new notActive_OutState() );
image4 = new Bitmap (new notActive_OverState() );
imageIsInRow = row;
imageIsInCol = col;
myInsideBtn.upState = image1;
myInsideBtn.overState = image2;
myInsideBtn.downState = myInsideBtn.upState;
myInsideBtn.hitTestState = myInsideBtn.overState;
addChild( myInsideBtn );
myInsideBtn.addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(ev:MouseEvent):void
{
myInsideBtn.upState = image3;
myInsideBtn.overState = image4;
var myNewEvent:Event = new Event("send_SOS");
this.dispatchEvent(myNewEvent);
trace("CLICK from inside the button");
}
}
}
ill also upload it to this link Grid_with_sharedObject with a zip.
and upload also Grod_before_Using_sharedObject if someone decides that he would help but the code is to messed up
If I'm reading your code correctly, I'd honestly say your problem is sequential. For whatever reason, the setting of the active and inactive rows is occurring BEFORE the data is actually being interpreted into the button states. As a result, the computer sees all buttons as off when it decides whether to make other rows clickable, and THEN updates the state of the buttons.
The easiest way to fix this, I think, would be to split the Main() function into a few sub functions, such as updateButtons() for the function that changes whether a row/button is clickable, and loadData() for the function the loads from the SharedObject. In Main(), put the calls to those functions. This will make Main() easier to work with, and you can call a function multiple times if necessary.
To solve your particular issue, you'd need to get the data for the buttons using the SharedObject FIRST (which obviously is working), and THEN update whether the other buttons are clickable.
A "soft-skills" tip for programming: when you run into a problem, grab a piece of paper, a pencil, and read through your code the way your computer would. Be the computer. Write down variables and their values when they change. Mark when functions are called. You'll spot a lot of errors this way.
In Drug.as I have a button, the listener is in Main and I'm trying to find out
which instance I have clicked so I can pick out the price of the drug and make a purchase.
MAIN.AS
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
/**
* ...
* #author MindGem
*/
public class Main extends Sprite
{
private var drug:Drug;
private var cash:Cash;
private var drugNames:Array = ["Ganja", "Khat", "Extacy", "Amphetamine", "Dopamine", "Heroin", "Cocaine"];
private var drugPrices:Array = [5, 10, 15, 20, 30, 50, 75];
private var randomDrugPrice:uint;
private var drugCollection:Vector.<Drug>;
public function Main():void
{
drugCollection = new Vector.<Drug>;
for (var i:int = 0; i < drugNames.length; i++)
{
randomDrugPrice = Math.random() * (i*5) + drugPrices[i];
drug = new Drug();
addChild(drug);
drugCollection.push(drug);
drug.setName(drugNames[i]);
drug.setPrice(randomDrugPrice);
drug.x = 0;
drug.y = (i * 24);
drug.buy.addEventListener(MouseEvent.CLICK, BuyDrug);
}
cash = new Cash();
addChild(cash);
cash.x = 100;
cash.y = 200;
}
public function BuyDrug(e:MouseEvent):void
{
//How can I find out the price or id of the clicked instance?
THIS is where I need to find out which instance I've clicked.
Now, I tried Drug/e.currentTarget).getPrice(), I've tried pushing in the instances
inside a vector and picking out that one, nothing works for me.
I can put the listener on the class itself instead of a button but that makes the whole
class clickable and I have textfields in there I don't want effected by this.
What Can I do?
}
}
}
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
DRUG.AS
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
/**
* ...
* #author MindGem
*/
public class Drug extends Sprite
{
private var drugNameContainer:MovieClip;
private var drugNameText:TextField;
private var drugPriceContainer:MovieClip;
private var drugPriceText:TextField;
private var textDesigner:TextFormat;
private var buyDrugText:TextField;
public var buy:MovieClip;
private var buyLabel:TextField;
private var price:uint = 12;
private var drugName:String = "Cocaine";
public function Drug()
{
buyLabel = new TextField();
drugNameContainer = new MovieClip();
drugPriceContainer = new MovieClip();
buy = new MovieClip();
buyDrugText = new TextField();
textDesigner = new TextFormat();
drugNameText = new TextField();
drugPriceText = new TextField();
textDesigner.align = "right";
textDesigner.font = "_sans";
textDesigner.size = 13;
drugNameContainer.graphics.beginFill(0xeeeeee);
drugNameContainer.graphics.lineStyle(1, 0xbbbbbb);
drugNameContainer.graphics.drawRoundRect(50, 50, 120, 20, 6, 6);
drugPriceContainer.graphics.beginFill(0xeeeeee);
drugPriceContainer.graphics.lineStyle(1, 0xbbbbbb);
drugPriceContainer.graphics.drawRoundRect(175, 50, 50, 20, 6, 6);
buy.graphics.beginFill(0x60ce0f);
buy.graphics.lineStyle(2, 0x000000);
buy.graphics.drawRoundRect(275, 50, 50, 21, 6, 6);
buy.buttonMode = true;
drugPriceText.x = 120;
drugPriceText.y = 51;
drugNameText.x = 66;
drugNameText.y = 50;
buyDrugText.type = TextFieldType.INPUT;
buyDrugText.text = "1";
buyDrugText.x = 230;
buyDrugText.y = 50;
buyDrugText.background = true;
buyDrugText.backgroundColor = 0xcccccc;
buyDrugText.border = true;
buyDrugText.borderColor = 0x000000;
buyDrugText.width = 40;
buyDrugText.height = 20;
buyDrugText.maxChars = 3;
buyDrugText.restrict = "0-9";
buyDrugText.setTextFormat(textDesigner);
buyLabel.text = "BUY";
buyLabel.x = 217;
buyLabel.y = 51;
buyLabel.mouseEnabled = false;
buyLabel.setTextFormat(textDesigner);
addChild(drugNameContainer);
addChild(drugPriceContainer);
addChild(drugNameText);
addChild(buy);
addChild(buyDrugText);
addChild(drugPriceText);
addChild(buyLabel);
}
public function setName(p_drugName:String):void
{
drugName = p_drugName;
drugNameText.text = drugName;
drugNameText.mouseEnabled = false;
drugNameText.setTextFormat(textDesigner);
}
public function setPrice(p_price:uint):void
{
price = p_price;
drugPriceText.text = "$" + price;
drugPriceText.mouseEnabled = false;
drugPriceText.setTextFormat(textDesigner);
}
public function getPrice():uint
{
return uint(buyDrugText.text)*price;
}
}
}
Help?
You add the buy MovieClip directly to Drug, so you can just assume:
public function BuyDrug(e:MouseEvent):void
{
var drugClicked:Drug = e.target.parent as Drug;
// more stuff here
}
(You'd have to have the listener added directly to "buy", of course)
drug = new Drug();
drug.name = "drug"+i;
Now u can recognize which item has been clicked.
I have the following problem when I try to use TweenLite with a Bitmap:
I get strange error messages when applying TweenLite to a Bitmap (tempScore.bitmap). GetBounds works. The bitmap has transparency. Does anyone have an idea why it doesn't work? Any help appreciated. Thanks.:)
When using a getBounds-Method I get this:
tempScore.bitmap.getBounds(this)(x=2.35, y=-0.45, w=25, h=18)
This is the error message:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.greensock.plugins::TransformAroundPointPlugin/onInitTween()
at com.greensock.plugins::TransformAroundCenterPlugin/onInitTween()
at com.greensock::TweenLite/init()
at com.greensock::TweenLite/renderTime()
at com.greensock.core::SimpleTimeline/renderTime()
at com.greensock::TweenLite$/updateAll()
My imported and activated libraries look like this:
import com.greensock.*;
import com.greensock.TweenLite;
import com.greensock.plugins.TweenPlugin;
import com.greensock.plugins.TransformAroundCenterPlugin;
import com.greensock.plugins.TransformAroundPointPlugin;
import com.greensock.easing.*;
import com.greensock.plugins.AutoAlphaPlugin;
import com.greensock.plugins.ColorTransformPlugin;
import com.greensock.plugins.ColorMatrixFilterPlugin;
TweenPlugin.activate([TransformAroundCenterPlugin, TransformAroundPointPlugin, ColorTransformPlugin,
ColorMatrixFilterPlugin]);
This is the part where I try to use TweenLite on my tempScore:
var scoreTextLength:int = scoreManager.scores.length - 1;
for (var counter:int = scoreTextLength; counter >= 0; counter--)
{
tempScore = scoreManager.scores[counter];
tempScore.startDelay = true;
TweenLite.to(tempScore.bitmap, 2, {transformAroundCenter: {scale:2}});
trace("tempScore.bitmap.getBounds(this)" + tempScore.bitmap.getBounds(this));
if (tempScore.update())
{
disposeScore(counter);
}
}
So far as I can see the getBounds-values are ok. My game is based on a gameframework. There's a renderer inside of it.
Call me an idiot if I'm wrong but is it possible that the renderer of the framework and tweenlite are getting in each other's way??
TweenLite has problems with other similar objects like tempAsteroid. A lot of objects are drawn onto a canvas with copyPixels (blitting-method).
tempScore is a Score-object. The Score object is based on a BasicBlitArrayObject. Otherwise this object extends an EventDispatcher. I hope this little info helps.
This is the scoreManager which manages the look and properties of tempScore:
package com.cosmicward.src.classes
{
import flash.display.*;
import flash.text.*;
import flash.geom.*;
import com.framework_mod.src.BlitArrayAsset;
public class ScoreManager
{
public var scoreBitmapData:BitmapData;
public var scoreBitmap:Bitmap;
public var scoreAnimationFrames:Array = [];
public var scores:Array;
public var tempScore:Score;
private var textfield:TextField = new TextField();
private var textFormat:TextFormat = new TextFormat();
private var $textWidth:int;
private var $textHeight:int;
private var rec:Rectangle;
public var scoreCount:int;
public var scoreCountTwo:int;
public var scoreCountThree:int;
private var drawingCanvas:Shape = new Shape();
private var point0:Point = new Point(0, 0);
public function ScoreManager()
{
}
public function createScoreLook(textWidth:int, textHeight:int, text:String, textFormat:TextFormat):void {
var tempBlitArrayAsset:BlitArrayAsset = new BlitArrayAsset();
scoreBitmapData = new BitmapData(textWidth, textHeight, true, 0x00000000);
var font:ArialBold = new ArialBold();
textFormat.font = "ArialBold";
textFormat.font = font.fontName;
Font.registerFont(ArialBold);
textfield.embedFonts = true;
textfield.blendMode = BlendMode.LAYER;
//textfield.autoSize = TextFieldAutoSize.LEFT;
textfield.defaultTextFormat = textFormat;
textfield.setTextFormat(textFormat);
textfield.selectable = false;
textfield.text = text;
trace("drawingCanvas.height =" + drawingCanvas.height);
trace("drawingCanvas.width =" + drawingCanvas.width);
scoreBitmapData.draw(textfield);/
$textWidth = textWidth;
$textHeight = textHeight;
//*** end look
}
public function createScores(xPos:Number, yPos:Number, stopAnimation:int = 5,
scoreDelay:int = 10, scoreLife:int = 40):void {
var tempScore:Score = new Score(5, 1315, 5, 995);
tempScore.bitmapData = scoreBitmapData;
scoreBitmap = new Bitmap(tempScore.bitmapData);
tempScore.bitmap = scoreBitmap;
tempScore.x = xPos;
tempScore.y = yPos;
tempScore.life = scoreLife;
tempScore.lifeCount = 0;
tempScore.widthObject = $textWidth;
tempScore.heightObject = $textHeight;
tempScore._delay = scoreDelay;
tempScore.delayCount = 0;
tempScore.nextX = tempScore.x;
tempScore.nextY = tempScore.y;
scores.push(tempScore);
}
}
}
Here is some code of the BasicBlitArrayObject (tempScore rests upon that (i.e. Score-object):
package com.framework_mod.src
{
import flash.display.BitmapData;
import flash.geom.Point;
import flash.events.EventDispatcher;
import flash.geom.Rectangle;
import flash.display.Bitmap;
public class BasicBlitArrayObject extends EventDispatcher{
public var x:Number = 0;
public var y:Number = 0;
public var nextX:Number = 0;
public var nextY:Number = 0;
public var dx:Number = 0;
public var dy:Number = 0;
public var frame:int = 0;
public var bitmapData:BitmapData;
public var bitmap:Bitmap;
public var animationList:Array = [];
public var testList:Array = [];
public var point:Point = new Point(0, 0);
public var speed:Number = 0;
public var xMax:int = 0;
public var yMax:int = 0;
public var xMin:int = 0;
public var yMin:int = 0;
public var aniType:int = 1;
public var health:int = 0;
public var _size:int = 0;
public var score:int = 0;
public var _damage:int = 0;
public var count:int = 0;
public var bitmapSize:int = 0;
public var life:int = 0;
public var lifeCount:int = 0;
public var startCount:Boolean;
public var _delay:int = 0;
public var delayCount:int = 0;
public var startDelay:Boolean;
public var _stop:int;
public var stopAni:Boolean;
public var stopAniCount:int = 0;
public var _type:int = 0;
public var shield:int = 0;
public var healthPoints:int = 0;
public var widthObject:int;
public var heightObject:int;
public var boost:Number;
public var boostLfe:int;
public var weaponLfe:int;
public var _projXAdjust:Number;
public var _projYAdjust:Number;
public var number:int;
public var _offset:int;
public var marked:Boolean;
public var objMove:Boolean;
public var removeObj:Boolean;
public var finished:Boolean;
public function BasicBlitArrayObject(xMin:int, xMax:int, yMin:int, yMax:int)
{
this.xMin = xMin;
this.xMax = xMax;
this.yMin = yMin;
this.yMax = yMax;
//trace("basicblittarrayobject");
}
public function updateFrame(inc:int, aniType:int = 1):void
{
frame += inc;
switch (aniType) {
case 1:
if (frame > animationList.length - 1){
frame = 0;
}
bitmapData = animationList[frame];
break;
case 2:
if (frame > animationList.length - 1){
frame = 0;
}
bitmapData = animationList[1][frame];
break;
}
}
public function render(canvasBitmapData:BitmapData):void {
x = nextX;
y = nextY;
point.x = x;
point.y = y;
canvasBitmapData.copyPixels(bitmapData, bitmapData.rect, point);
}
public function dispose():void {
bitmapData.dispose();
bitmapData = null;
bitmap = null;
animationList = null;
point = null;
}
}
}
I think the problem is simple, but the resolution is not. The objects you are trying to transform are blitted. So they are not added to the stage. So the object's stage property is null.
I suspect that the TransformAroundPoint plugin is trying to use the object's stage property, and that is throwing a null object error your are seeing.
To see a simple example of this, make a very simple file.
Create two bitmaps, add one to the stage, and don't add the other.
Apply the tween to the stage instance, it will work.
Then apply the tween to the off-stage instance, and you should get the same error you get in the game.
What you will need to do instead is handle the transform yourself. Instead of using TweenLite to rotate around a point, do it yourself.
Fortunately Stack Overflow already has a great thread on that topic!
Rotate around a point that is not (0,0)
I've looped through the vertices and mapped a plane to each one. I'm having problems orientating the planes correctly. I can get it working with a sphere but when i make any alterations to the the primitive - positions are correct but they don't face/tilt the right way.
EDIT: Note - the alternation to the sphere was done before the sphere was created. I have updated the Sphere class to create an elongated sphere.
The code I'm using to place the planes are as follows:
pivotDO3D = new DisplayObject3D();
scene.addChild(pivotDO3D);
var bigSphere:Sphere = new Sphere(null, 500, 20, 20);
for each (var v:Vertex3D in bigSphere.geometry.vertices)
{
var __seatmaterial:ColorMaterial = new ColorMaterial(0x000000);
__seatmaterial.doubleSided = true;
var p:Plane = new Plane(__seatmaterial, 20, 20, 2, 2);
pivotDO3D.addChild(p);
p.position = v.toNumber3D();
p.lookAt(bigSphere);
}
The following demo shows how to minimize the problem. I changed the multiplication factor of 0.6 to 2.0 as well as the sphere size in order to exaggerate the effect so you can see it easily. Make sure to change 0.6 to 2.0 in your Sphere.as as well.
The key is in varying the z location of the target point with the z location of the point on the sphere.
To compare, run it as-is to see the "fixed" version, and change the lookAt target from pivotDO3D2 to bigSphere to see the old version.
package
{
import flash.display.Sprite;
import flash.events.Event;
import org.papervision3d.cameras.*;
import org.papervision3d.core.geom.renderables.*;
import org.papervision3d.materials.*;
import org.papervision3d.objects.*;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.render.*;
import org.papervision3d.scenes.*;
import org.papervision3d.view.*;
[SWF(width='400', height='400', backgroundColor='0x000000', frameRate='30')]
public class PlaneOrientationDemo extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
private var renderer:BasicRenderEngine;
private var viewport:Viewport3D;
private var pivotDO3D:DisplayObject3D;
public function PlaneOrientationDemo()
{
viewport = new Viewport3D(0, 0, true, true);
addChild( viewport );
renderer = new BasicRenderEngine();
scene = new Scene3D( );
camera = new Camera3D();
camera.z = -700;
camera.zoom = 50;
pivotDO3D = new DisplayObject3D();
scene.addChild(pivotDO3D);
var pivotDO3D2:DisplayObject3D = new DisplayObject3D();
var bigSphere:Sphere = new Sphere(null, 150, 20, 20);
for each (var v:Vertex3D in bigSphere.geometry.vertices)
{
var __seatmaterial:ColorMaterial = new ColorMaterial(0x00FF00);
__seatmaterial.doubleSided = true;
var p:Plane = new Plane(__seatmaterial, 20, 20, 2, 2);
pivotDO3D.addChild(p);
p.position = v.toNumber3D();
// This number should match the fx multiplication factor in Sphere.as.
var xFactor:Number = 2.0;
pivotDO3D2.z = v.z / (Math.PI / xFactor);
p.lookAt(pivotDO3D2);
}
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event: Event): void
{
pivotDO3D.rotationX += 1;
pivotDO3D.rotationY += 1;
renderer.renderScene(scene, camera, viewport);
}
}
}