How could i make an array of removed tiles? - actionscript-3

So i have a procedural generated game that loads in chunks, i need a way for my code to remember if i cut down a tree or broke a rock so it doesnt replace it when leaving and entering a new area. I got it almost working except instead of putting them back in the correct place, it moves them to fill in the blanks. (if that makes since)
this is the slimmed down function of what adds the removed tiles to my array of removed tiles
public function removeAndAddTile(tileRemoved:Function, tileAdded:Function, i:int)
{
world.removedTiles.push(world.tilesInWorld[i]);
}
This is what loads after the tiles get placed when entering an area. In other words, whats suppose to be replacing the tiles that have already been destroyed
protected function usedTiles()
{
for (var i:int = world.tilesInWorld.length - 1; i >= 0; --i)
{
for (var c:int = world.removedTiles.length - 1; c >= 0; --c)
{
if (world.tilesInWorld[i].x == world.removedTiles[c].x && world.tilesInWorld[i].y == world.removedTiles[c].y)
{
var ti:String = world.tilesInWorld[i].onTile;
var tx:int = world.removedTiles[c].x;
var ty:int = world.removedTiles[c].y;
world.worldTiles.removeChild(world.tilesInWorld[i]);
switch (ti)
{
case "grass" :
world.tilePool.returnSprite(world.tilesInWorld[i]);
break;
case "stone" :
world.rockPool.returnSprite(world.tilesInWorld[i]);
break;
}
world.tilesInWorld.splice(i, 1);
clicked = true;
switch (ti)
{
case "grass" :
world.tile = world.tilePool.getSprite();
break;
case "stone" :
world.tile = world.stonePool.getSprite();
break;
}
world.tile.width = world.TILE_SIZE;
world.tile.height = world.TILE_SIZE;
world.tile.x = tx;
world.tile.y = ty;
world.tilesInWorld.push(world.tile);
world.worldTiles.addChildAt(world.tile, i);
}
}
}
}
My question simply is, how can i get my tiles to remember when they have been destroyed and to delete and replace those tiles when entering an area?
http://www.fastswf.com/PJyyXsc

You could use two layers. One bottom layer for the map surface, and another detail layer contains trees, rocks. When your role moves and new area tiles appear, try to get the new area tiles data and add the trees, rocks to the new tile positions.
//the key may be tileX_tileY, the value will be the object type
//if a rock or a tree been broke,delete detailDic[tileX_tileY]
var detailDic:Dictionary;
When your role moves and enter a new area
var newTiles:Array;//the new appeared tiles
for each (var tile:Tile in newTiles)
{
var key:String = tile.tileX + "_" + tile.tileY;
var objectType:String = detailDic[key];
if (check ojectType is valid)
{
add the wanted tree, rock to target position.
}
}
//here you should remove the trees and rocks that disappear from your map's ViewPort

Related

How to hitTest same Objects in one Array?

I want to create a stacking Game. Where when you tap the screen for instance a block falls down and a new one appears where the other one originally was. Now when the User taps the screen again the same block falls down and if aligned correctly stacks on top of the first one so one and so one. Keep stacking until you miss.
I thought creating an array and pushing each new object to that array would be able to hitTest between each new one etc and have them stack on each other. I realized I don't quite understand how to go about doing this. New instances are created so I got that down. Here is my code so far:
private function engineLogic(e:Event):void
{
stackingHandler();
}
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
var currentCat:mcCats = aCatArray[i];
//HIT TEST CATS
}
trace("NUMBER OF CATS: " + aCatArray.length);
}
private function onTap(e:MouseEvent):void
{
//Move Down
TweenLite.to(cats, 1.0, {y:(stage.stageHeight / 2) + 290, onComplete: addCats});
}
private function addCats():void
{
//Create Instance
cats = new mcCats();
//Add Objects
addChild(cats);
//Push to Array
aCatArray.push(cats);
}
I would appreciate any help from you guys. Maybe if you can push me in the right direction. Thank you in advance!
It looks like the cats variable holds the object that is currently falling?
In that case you'd do something like this:
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
if(cats.hitTestObject(aCatArray[i])) {
// collision detected!
// kill the Tween
// set the y position of the `cats` object
// so it appears on top of the object it collided with (`aCatArray[i]`)
// (it may have moved slightly past the object before doing this check)
}
}
}
So you're looping through the array and hit testing cats against every object in the array one at a time.
It might make more sense to use a basic gravity simulation, or just linearly increasing the y value instead of using a Tween, but you didn't ask about that.
You might also want to set a flag for whether or not an object is currently falling and use that to determine whether or not to run the stackingHandler. Otherwise, you'll just be continually hit testing all the objects when nothing is moving.
This is how I was able to fix it. Creating a double for loop. Checking if they are equal to each other continue and check for hitTest:
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
var currentCat:mcCats = aCatArray[i];
for (var j:int = 0; j < aCatArray.length; j++)
{
var newCat:mcCats = aCatArray[j];
if (currentCat == newCat) continue;
//Hit Test between Objects
if (newCat.hitTestObject(currentCat.mcHit) && newCat.bFlag == false)
{
//Stop Moving
newCat.stopMoving();
trace("HIT");
if (highScore == 0)
{
addCats();
trace("ADD CATS 1");
}else
{
TweenLite.delayedCall(0.6, addCats);
trace("ADD CATS 2");
}
//Add Points
highScore ++;
trace(highScore + " Score");
//Set Flag boolean
newCat.bFlag = true
}
}
}
}

Nested movieclips; changing background frame

Where have all my children gone?
Hope this is a relatively simple answer to a less-than-intelligent question that's a consequence of how I learn things when not doing them for work. In this case I started a game about 3 years ago in AS3 as I was familiar with js at least and had also worked with shockwave back in the day. Anyway, when learning something offline like this I tend to learn just what I need to know to do what I need to do next, and can sometimes get pretty far into one area while missing something obvious and simple because I just haven't crossed that case yet.
We have a playing field and playing pieces. Those playing pieces (sailing ships) you see below are complex objects with dozens of properties and several children including graphics and text fields that change depending on the state of the ship. It's WEGO where each side plots moves, those moves are then executed one ship at a time alternatively between the two sides, then we have gun combat, etc. All that is there and works fine, a few thousand lines of code.
My current problem is that when a player clicks on a ship to select it, I unhide a yellow border to indicate which ship is selected and draw the complex ship detail screen you see top left, but for a long time I've wanted to change the background color of the playing piece as well.
After a long layoff I started working on this again and decided to start there. So I made new counters, added them as keyframes to the already existing symbol/class that contains all of the country default backgrounds, and modified the code. It works fine in that the background is changed to the correct highlighted version, and then goes back to default when deselected.
In the image the currently-selected ship is in the center, USS Constitution, its detail/info screen is also displayed. You can see the problem, all the children are gone on the playing piece. And they don't come back when you go back to the original default background.
At first I thought it was a z order problem but it isn't, I walked the selected ship playing piece background in the z index until they disappeared behind the ocean background, there was just open ocean where the ship playing piece used to be.
My best guess is that maybe the children have to be instanced on each frame of the parent's timeline each time you change the parent's frame but if so I'm not finding reference to or explanation of that. That and that seems really unwieldy way of doing things, I was completely caught off guard by the idea of the children caring what frame its parent is on unless there was coded logic telling it to.
Somehow even though I have thousands of lines of complex dialogs and screens displaying multiple dynamic children I have never changed the base background in any of those cases.
Also tried to google this, but had little luck. I couldn't even figure out a relatively simple question to ask.
I'll be happy to paste code but I don't seem to have a code problem but an understanding problem.
Example-selected ship with highlighted background graphic is in the center
For those who feel the code is important, this is the end of the 1500 line ship-creation function where most of the children get added:
textShipSailSpeed.name = "textShipSailSpeed";
textShipSailSpeed.width = 20;
textShipSailSpeed.height = 13;
textShipSailSpeed.x = 33;
textShipSailSpeed.y = 14;
textShipSailSpeed.embedFonts = true;
textShipSailSpeed.textColor = 0xFFFFFF;
textShipSailSpeed.rotation -= 90;
//full sails set
if ("full" == finalShip.sailState) {
textShipSailSpeed.text = finalShip.fullSailSpeed;
}
//battle sails set, which are reduced sails to improve visibility and reduce sail damage in combat
else {
textShipSailSpeed.text = finalShip.battleSailSpeed;
}
// textShipBattleSailSpeed and textShipFullSailSpeed no longer used on counters, but still used in Info screens
var textShipBattleSailSpeed: TextField = new TextField();
textShipBattleSailSpeed.name = "textShipBattleSailSpeed";
textShipBattleSailSpeed.text = finalShip.battleSailSpeed;
textShipBattleSailSpeed.visible = false;
var textShipFullSailSpeed: TextField = new TextField();
textShipFullSailSpeed.name = "textShipFullSailSpeed";
textShipFullSailSpeed.text = finalShip.fullSailSpeed;
textShipFullSailSpeed.visible = false;
//create sailState (battle/full) indicator
var sailStateIndicator: WSIM_Counters_SailtState_Indicator = new WSIM_Counters_SailtState_Indicator();
//set indicator to correct sailState background graphic
sailStateIndicator.gotoAndStop("battle");
if ("full" == finalShip.sailState) {
sailStateIndicator.gotoAndStop("full");
}
finalShip.addChild(sailStateIndicator);
//add ship and attach text fields
gridBG1.addChild(finalShip);
finalShip.addChild(textShipName);
finalShip.addChild(textShipSailSpeed);
finalShip.addChild(textShipTurnAllowance);
finalShip.addChild(textShipBattleSailSpeed);
finalShip.addChild(textShipFullSailSpeed);
finalShip.parent.setChildIndex(finalShip, 1);
//logging
if (log_shipCreation) {
trace(finalShip.name + " added added as child of background in createShip()");
}
//create background sprite "ship is selected" border
var border: Sprite = new Sprite();
border.name = "shipBorder";
border.graphics.beginFill(0xFFCC00, 1);
border.graphics.drawRect(-1, -1, 52, 132)
border.graphics.endFill();
border.visible = false;
//create background sprite combat border
var borderCombat: Sprite = new Sprite();
borderCombat.name = "borderCombat";
borderCombat.graphics.beginFill(0xFF0000, 1);
borderCombat.graphics.drawRect(-1, -1, 52, 132)
borderCombat.graphics.endFill();
borderCombat.visible = false;
//add the borders as children of ship
finalShip.addChild(border);
finalShip.addChild(borderCombat);
//move the borders in z-order to behind ship counter, so they show looking like a border
border.parent.setChildIndex(border, border.parent.getChildIndex(border) - 5);
borderCombat.parent.setChildIndex(borderCombat, borderCombat.parent.getChildIndex(borderCombat) - 6);
//PUSH TO MASTER SHIP ARRAYS
//finalShip is Side 1, add to master list of ship objects for Side 1
if (sideList[0] == finalShip.country) { ....
And this is part of the even larger selectShip function, here is where I clear the selected state on all ships on map and then set the current ship's background to currShip.country+"_sel" which is the correct frame label for the "selected" background images.
//clear combat selected state on all ships
for (var i: int = 0; i < shipListSide1.length; i++) {
//hide selection border sprite and set select property false
shipListSide1[i].combatSelected = false;
var borderChildCombat = shipListSide1[i].getChildByName("borderCombat");
borderChildCombat.visible = false;
//show default counter background, build label name
shipListSide1[i].gotoAndStop(shipListSide1[i].country+"_def");
}
for (var i: int = 0; i < shipListSide2.length; i++) {
//hide selection border sprite and set select property false
shipListSide2[i].combatSelected = false;
var borderChildCombat2 = shipListSide2[i].getChildByName("borderCombat");
borderChildCombat2.visible = false;
//show default counter background, build label name
shipListSide2[i].gotoAndStop(shipListSide2[i].country+"_def");
}
//check to see if this is selecting a target in gun combat
if ((false == currShip.side1 && enableCombatSelectSide2) || (currShip.side1 && enableCombatSelectSide1)) {
combatSelectShip(currShip);
}
//we're allowed to select this ship
if ((enableSelectSide1 && currShip.side1) || (enableSelectSide2 && false == currShip.side1)) {
//event is from a ship object
if (currShip is Ship_1) {
//remove previous ship info screen
if (currShipInfo.parent) {
currShipInfo.parent.removeChild(currShipInfo);
}
//clear selected state on all ships
for (var i: int = 0; i < shipListSide1.length; i++) {
//hide selection border sprite and set select property false
shipListSide1[i].selected = false;
var borderChild = shipListSide1[i].getChildByName("shipBorder");
borderChild.visible = false;
//default graphic already set in clearing combatselect status above
}
for (var i: int = 0; i < shipListSide2.length; i++) {
//hide selection border sprite and set select property false
shipListSide2[i].selected = false;
var borderChild2 = shipListSide2[i].getChildByName("shipBorder");
borderChild2.visible = false;
//default graphic already set in clearing combatselect status above
}
//Change graphic of selected ship to selected, highlighted color
currShip.gotoAndStop(currShip.country+"_sel");
//set selected state on clicked ship, unhide border
currShip.selected = true;
borderChild = currShip.getChildByName("shipBorder");
borderChild.visible = true;
Ok based on feedback about it being a z-order issue, the below is what I tried to move the missing children back above the playing piece background. If you notice it also has to be a z order issue as the "selected" border, which is a child of the playing piece like the missing ones, that happens to purposely be behind the playing piece graphic, displays correctly when the ship is in the selected state. See the original screenshot, the playing piece in the center that's selected and is missing its children also has a yellow border.
Anyway, below is what I tried. It works in that there are no errors but I really couldn't find these children in the debugger to confirm what happened, and so far I at least appear to have moved them up in the z order to the max before I get an out of range error, and the problem still exists - no ship graphic, ship name, movement allowance, etc.
//Change playing piece background of the selected ship to selected, highlighted color frame
currShip.gotoAndStop(currShip.country+"_sel");
//trying to move the children of the playing piece back above the playing piece graphic
var shipChildrenArray:Array = new Array("textShipName","textShipTurnAllowance","textShipSailSpeed","sailStateIndicator");
for each(var childItem:String in shipChildrenArray) {
currShip.setChildIndex(currShip.getChildByName(childItem), 3);
}
Your parent movieclip should have layers. The child movieclip that you want to always be visible needs to extend across all frames of the parent.
Note that I did not see what you say I should be able to see on your graphic. Since I don't know what you think it should look like, I wasn't able to spot the difference between what it does look like and that.
You may find you get better feedback if you post a screen capture of the timeline and post any code that's involved.
I try to build a simple replica of your hierarchy here:
package {
import flash.display.MovieClip;
import flash.events.*;
public class gameTestDoc extends MovieClip {
var pieceArray:Array = new Array();
public function gameTestDoc() {
stage.addEventListener(MouseEvent.CLICK, selectPiece);
for (var i:int = 0; i < 4; i++){ // creates 4 instances of a class with 6 frames, each having a different colored rectangle.
var gamePiece:MovieClip = new backGround();
addChild(gamePiece);
gamePiece.x = 50 * i + 200; // space out the game pieces.
gamePiece.y = stage.stageHeight/2; // center game pieces.
pieceArray.push(gamePiece);// add piece to array.
for (var j:int = 0; j < 5; j++){
var components:MovieClip = new MovieClip();
components.graphics.lineStyle();
components.graphics.beginFill(0x00ffcc * j * 200000); //gives different color to each component.
components.graphics.drawRect(0,0,5, 10);
components.graphics.endFill();
gamePiece.addChild(components);
components.y = j * 5;
}
gamePiece.gotoAndStop(Math.ceil(Math.random()*10)); // give each piece a random frame to go to.
}
}
function selectPiece(e:MouseEvent):void{ // sends game piece frame to random frame.
for (var i:int = 0; i < pieceArray.length; i++){
e.target.gotoAndStop(Math.ceil(Math.random()*10));
}
}
}
}
and I have an mc in the GUI library with the linkage name of "backGround". When I click on the pieces, the backgrounds change color, and everything else stays on top. Here is a picture:
and after I click the 2nd piece:
can you see from my simple code what you might be doing differently?
edit: 6-10-16
//move the borders in z-order to behind ship counter, so they show looking like a border
border.parent.setChildIndex(border, border.parent.getChildIndex(border) - 5);
borderCombat.parent.setChildIndex(borderCombat, borderCombat.parent.getChildIndex(borderCombat) - 6);
wouldn't this be less confusing/prone to strange behavior?:
//move the borders in z-order to behind ship counter, so they show looking like a border
border.parent.setChildIndex(border, 0);
borderCombat.parent.setChildIndex(borderCombat, 0);
Would this not give the same result?
At first I thought it was a z order problem but it isn't,
Actually this is probably exactly your problem.
I walked the selected ship playing piece background in the z index until they disappeared behind the ocean
Really? How? Moving the z-order of display objects in a container can't change the z-order of the container. But if you are moving the ship itself (the container of all your other symbols), then yes, the open ocean will appear. But just shifting things around within the ship won't do that. How to shift things around in the ship container? Go here.
Example
If your game piece (pieceMc) is a child of the ocean background (oceanMc) and the the flag background (flagMc) is a child of the piece then
oceanMc.gamePieceMc.setChildIndex(flagMc,0);
should put the flag to the bottom
Edit 6/11/16
One quick and dirty way to change z-order at runtime is to re add the child; it will be put on top of the stack. You could do
piece[i].addChild(ship);
piece[i].addChild(guns);
piece[i].addChild(nameField);
the result will be that the ship will come to the top, then the guns will be put back on top of that, then the nameField on top of that. If the flag background is also a child of "piece" it will below, like you want.
One quick and dirty way to change z-order at runtime is to re add the child; it will be put on top of the stack. You could do piece[1].addChild(ship); piece[1].addChild(guns); piece[1].addChild(nameField); the result will be that the ship will come to the top, then the guns will be put back on top of that, then the nameField on top of that. If the flag background is also a child of "piece" it will below, like you want. – Neal Davis yesterday
Ok, this is the closest to the correct answer I'm going with. As you can see in the update to my original question, I tried to fix the z order problem by either moving the children up or the background down, but had no luck even though the code executes fine.
So I changed my solution to this:
//Change playing piece background of the selected ship to selected, highlighted color frame
currShip.gotoAndStop(currShip.country+"_sel");
//move the children of the playing piece back above the playing piece graphic. When parent changes frame as above it goes to the top of the z order for some stupid reason
var shipChildrenArray:Array = new Array("textShipName","textShipTurnAllowance","textShipSailSpeed","sailStateIndicator", "currShipGraphic");
for each(var childItem:String in shipChildrenArray) {
//currShip.setChildIndex(currShip.getChildByName(childItem), 5);
var childObject = currShip.getChildByName(childItem);
currShip.removeChild(childObject);
currShip.addChild(childObject);
}
It seems very hacky to me, I'd rather correctly manipulate the z order but unless someone has other ideas on how to do that, we'll have to go with this solution. Re-adding the children does indeed move them back to the top of the current z order array.
So:
1) If you have nested movieclips and you change the frame of the parent, it will go to the top of the z order array for reasons I can't begin to fathom. I don't see a way to prevent it either.
2) If you know how to manipulate the z order of the child movieclips better than I do, that would probably be the best solution.
3) A sledgehammer solution is removing and adding all the children back.
...and it won't let me post a screenshot of it working properly because I "need at least 10 reputation points to post more than two links." Makes no sense as this attachment is the SECOND link, not third or more. Oh well.
Responding to Neal's post.
Looking at the code, only difference that I see is that you're adding the pieces as children of the stage, while mine are one nested level down by being children of the ocean graphic.
Since you're interested and spending time with it, I'll post the entire ship creation function below. It gets called iteratively and loops through the side1 master array of ships and then side2, back to back. That's one reason I'm so confused by the two sides' z orders being consistently different, maybe alphabetical is being applied- only z order manipulation I do in the creation is pushing the border children (one normal select one combat) behind the playing piece.
BTW, please also look for another question from me involving a different issue I am having where a dialog is refusing to disappear on removeChild even though the associated code hasn't been touched in a couple years.
This is ship creation. This is a simulation, not a game, so it's reasonably complex with large numbers of properties set. One somewhat unusual thing I do you will see is cast my Ship_1 classes to a generic object to set all the custom properties and then back to Ship_1 once that's done. I always thought that was a little risky but have seen zero problems (unless this issue is tied to that somehow)
//create ship objects, set properties, add to core arrays
function createShip(currShip) {
// create Ship_1 obj and cast it temporarily as parent class (which is dynamic) to set custom properties
var finalShip: Ship_1 = new Ship_1();
var temp_Ship: Object = finalShip as Object;
//set basic stats
temp_Ship.selected = currShip.selected;
temp_Ship.combatSelected = currShip.combatSelected;
temp_Ship.name = currShip.name;
//rigging & rigging damage
temp_Ship.rigging = currShip.rigging;
temp_Ship.riggingSlots = currShip.riggingSlots;
temp_Ship.rigging_1 = currShip.rigging_1;
temp_Ship.rigging_2 = currShip.rigging_2;
temp_Ship.rigging_3 = currShip.rigging_3;
temp_Ship.rigging_4 = currShip.rigging_4;
temp_Ship.riggingDamage = currShip.riggingDamage;
temp_Ship.riggingDamage_1 = currShip.riggingDamage_1;
temp_Ship.riggingDamage_2 = currShip.riggingDamage_2;
temp_Ship.riggingDamage_3 = currShip.riggingDamage_3;
temp_Ship.riggingDamage_4 = currShip.riggingDamage_4;
//hull & hull damage
temp_Ship.hull = currShip.hull;
temp_Ship.hull_1 = currShip.hull_1;
temp_Ship.hull_2 = currShip.hull_2;
temp_Ship.hull_3 = currShip.hull_3;
temp_Ship.hullDamage = currShip.hullDamage;
temp_Ship.hullDamage_1 = currShip.hullDamage_1;
temp_Ship.hullDamage_2 = currShip.hullDamage_2;
temp_Ship.hullDamage_3 = currShip.hullDamage_3;
//guns & guns damage
temp_Ship.guns = currShip.guns;
temp_Ship.gunsDamage = currShip.gunsDamage;
temp_Ship.guns_1 = currShip.guns_1;
temp_Ship.guns_2 = currShip.guns_2;
temp_Ship.guns_3 = currShip.guns_3;
temp_Ship.guns_4 = currShip.guns_4;
temp_Ship.gunsDamageLeftBow = currShip.gunsDamageLeftBow;
temp_Ship.gunsDamageLeftBowInitial = currShip.gunsDamageLeftBowInitial;
temp_Ship.gunsDamageRightBow = currShip.gunsDamageRightBow;
temp_Ship.gunsDamageRightBowInitial = currShip.gunsDamageRightBowInitial;
temp_Ship.gunsDamageLeftStern = currShip.gunsDamageLeftStern;
temp_Ship.gunsDamageLeftSternInitial = currShip.gunsDamageLeftSternInitial;
temp_Ship.gunsDamageRightStern = currShip.gunsDamageRightStern;
temp_Ship.gunsDamageRightSternInitial = currShip.gunsDamageRightSternInitial;
//carronades & carronades damage
temp_Ship.carronades = currShip.carronades;
temp_Ship.carronades_1 = currShip.carronades_1;
temp_Ship.carronades_2 = currShip.carronades_2;
temp_Ship.carronades_3 = currShip.carronades_3;
temp_Ship.carronades_4 = currShip.carronades_4;
temp_Ship.carronadesDamageLeftBow = currShip.carronadesDamageLeftBow;
temp_Ship.carronadesDamageLeftBowInitial = currShip.carronadesDamageLeftBowInitial;
temp_Ship.carronadesDamageRightBow = currShip.carronadesDamageRightBow;
temp_Ship.carronadesDamageRightBowInitial = currShip.carronadesDamageRightBowInitial;
temp_Ship.carronadesDamageLeftStern = currShip.carronadesDamageLeftStern;
temp_Ship.carronadesDamageLeftSternInitial = currShip.carronadesDamageLeftSternInitial;
temp_Ship.carronadesDamageRightStern = currShip.carronadesDamageRightStern;
temp_Ship.carronadesDamageRightSternInitial = currShip.carronadesDamageRightSternInitial;
//crew and crew damage
temp_Ship.crewQuality = currShip.crewQuality;
temp_Ship.crewDamage = currShip.crewDamage;
temp_Ship.crew_1 = currShip.crew_1;
temp_Ship.crew_1_damage = currShip.crew_1_damage;
temp_Ship.crew_1_lost = currShip.crew_1_lost;
temp_Ship.crew_1_lostInitial = currShip.crew_1_lostInitial;
temp_Ship.crew_2 = currShip.crew_2;
temp_Ship.crew_2_damage = currShip.crew_2_damage;
temp_Ship.crew_2_lost = currShip.crew_2_lost;
temp_Ship.crew_2_lostInitial = currShip.crew_2_lostInitial;
temp_Ship.crew_3 = currShip.crew_3;
temp_Ship.crew_3_damage = currShip.crew_3_damage;
temp_Ship.crew_3_lost = currShip.crew_3_lost;
temp_Ship.crew_3_lostInitial = currShip.crew_3_lostInitial;
//initial positions, used in plotted movement
temp_Ship.initialColumn = currShip.initialColumn;
temp_Ship.initialRow = currShip.initialRow;
temp_Ship.initialColumn2 = currShip.initialColumn2;
temp_Ship.initialRow2 = currShip.initialRow2;
temp_Ship.initialDirection = currShip.initialDirection;
//movement properties
temp_Ship.fullSailSpeed = currShip.fullSailSpeed;
temp_Ship.fullSailSpeedArray = currShip.fullSailSpeedArray;
temp_Ship.maxFullSailSpeed = currShip.maxFullSailSpeed;
temp_Ship.initialFullSailSpeed = currShip.initialFullSailSpeed;
temp_Ship.battleSailSpeed = currShip.battleSailSpeed;
temp_Ship.battleSailSpeedArray = currShip.battleSailSpeedArray;
temp_Ship.maxBattleSailSpeed = currShip.maxBattleSailSpeed;
temp_Ship.initialBattleSailSpeed = currShip.initialBattleSailSpeed;
//point of sailing (close reach, broad reach, etc.)
temp_Ship.shipOrientation = currShip.shipOrientation;
temp_Ship.movementAllowanceUsed = currShip.movementAllowanceUsed;
temp_Ship.moveLog = currShip.moveLog;
//turn properties
temp_Ship.turnAllowanceBase = currShip.turnAllowanceBase;
temp_Ship.turnAllowance = currShip.turnAllowance;
//used in movement
temp_Ship.turnAllowed = currShip.turnAllowed;
temp_Ship.moveAllowed = currShip.moveAllowed;
//special conditions (anchored, grappled, etc.) can block movement/turning
temp_Ship.canMove = currShip.canMove;
temp_Ship.fouled = currShip.fouled;
temp_Ship.anchored = currShip.anchored;
temp_Ship.grappled = currShip.grappled;
temp_Ship.onFire = currShip.onFire;
//dismasted
temp_Ship.dismasted = currShip.dismasted;
temp_Ship.initialDismasted = currShip.initialDismasted;
temp_Ship.dismastedPreviousValue = currShip.dismastedPreviousValue;
//weapons status
temp_Ship.loadedLeft = currShip.loadedLeft;
temp_Ship.loadedRight = currShip.loadedRight;
temp_Ship.shotType = currShip.shotType;
//position
temp_Ship.column = currShip.column;
temp_Ship.row = currShip.row;
//stern hex
temp_Ship.column2 = currShip.column2;
temp_Ship.row2 = currShip.row2;
temp_Ship.direction = currShip.direction;
//country
temp_Ship.country = currShip.country;
//class and rating
temp_Ship.shipClassName = currShip.shipClassName;
temp_Ship.shipClassNumber = currShip.shipClassNumber;
temp_Ship.shipRate = currShip.shipRate;
temp_Ship.originalGuns = currShip.originalGuns;
//HACK need to find a better solution
temp_Ship.combatBorderFixed = currShip.combatBorderFixed;
//value will be frame label of the ship portrait we will use for this ship
//these will be used by the info screens
temp_Ship.portraitLabel = "";
// <--- begin select ship portrait for Info screens ---->
//number of options per country + number of guns combo
var portraitRandLimit:int = 1;
//actual class that contains all of the ship portrait bitmaps
var shipPortraitSource:Ship_Portrait = new Ship_Portrait;
//pull list of all frame labels in shipPortraitSource
var labelList:Array = shipPortraitSource.currentLabels;
//iterate through list of frame labels to see if we have one that matches this ship's name
for each (var frameObject:FrameLabel in labelList) {
//we have a name match in our list of ship portraits, use specific bitmap for that individual ship
if (frameObject.name == currShip.name) {
temp_Ship.portraitLabel = currShip.name;
//LOGGING
if (log_shipPortraitSelection) {
trace("==================================================");
trace("framObject.name: "+frameObject.name+" matched currShip.name: "+currShip.name);
trace("temp_Ship.portraitLabel set to: "+temp_Ship.portraitLabel);
trace("==================================================");
trace("");
}
}
}
//we didn't find a name match, select a ship portrait from available options that match the ship country + number of guns it really carried
//Trying to have 3-4 accurate options in each gun number + country combo
if ("" == temp_Ship.portraitLabel) {
//configure the number of options for each country + number of guns combo
switch(currShip.country) {
case "US":
switch(currShip.originalGuns) {
case 44:
portraitRandLimit = 4;
break;
case 38:
portraitRandLimit = 4;
break;
case 36:
break;
case 32:
portraitRandLimit = 2;
break;
case 28:
portraitRandLimit = 2;
break;
case 16:
break;
case 12:
portraitRandLimit = 2;
break;
}
break;
case "GB":
switch(currShip.originalGuns) {
case 38:
portraitRandLimit = 4;
break;
case 36:
break;
case 32:
portraitRandLimit = 2;
break;
case 28:
portraitRandLimit = 3;
break;
}
break;
case "FR":
case "ES":
case "NL":
break;
}
//now that we know how many options we have for this gun number + country combo, select one randomly
var portraitNumber:int = Math.ceil(Math.random() * portraitRandLimit);
//build the label name for us in the info screens, E.G., "GB_38_3", being the third portrait for 38 gun British ships
temp_Ship.portraitLabel = currShip.country+"_"+currShip.originalGuns+"_"+portraitNumber;
//LOGGING
if (log_shipPortraitSelection) {
trace("==================================================");
trace("There was no name match selecting a portrait, so building label name");
trace("currShip.name: "+currShip.name);
trace("portraitRandLimit: "+portraitRandLimit);
trace("portraitNumber: "+portraitNumber);
trace("temp_Ship.portraitLabel set to: "+temp_Ship.portraitLabel);
trace("==================================================");
trace("");
}
}
// <--- end select ship portrait for Info screens ---->
//used for movement rules, ship can only turn once per hex. 1 = straight, 2 = turn
temp_Ship.lastMove = currShip.lastMove;
//is ship fulll or battle sail
temp_Ship.sailState = currShip.sailState;
//designates which sdie ship is on
temp_Ship.side1 = currShip.side1;
temp_Ship.starboardHitZone = currShip.starboardHitZone;
temp_Ship.portHitZone = currShip.portHitZone;
temp_Ship.initialBroadside = currShip.initialBroadside;
//ship going down
temp_Ship.isSinking = currShip.isSinking;
temp_Ship.isExploding = currShip.isExploding;
//ship surrender
temp_Ship.isSurrendered = currShip.isSurrendered;
temp_Ship.strikeColors = currShip.strikeColors;
temp_Ship.strikeFirePower = currShip.strikeFirePower;
temp_Ship.strikeMobility = currShip.strikeMobility;
//recast back to ship type. This seems risky but it works
finalShip = temp_Ship as Ship_1;
//calc initial positions based on column/row properties and a hex-based grid
finalShip.x = (62 * (finalShip.column - 1)) + 17;
//y setting is annoying
finalShip.y = 5 + ((finalShip.row - 1) * 70) + ((finalShip.row - 1) * 1) - 71;
//odd columns must compensate for half hexes
if (1 == finalShip.column % 2) {
finalShip.y += 35;
}
//rotate based on ship direction and correct for top left registration point
switch (finalShip.direction) {
case 1:
//do nothing
break;
case 2:
finalShip.rotation = 60;
finalShip.x += 99;
finalShip.y += 27;
break;
case 3:
finalShip.rotation = 120;
finalShip.x += 124;
finalShip.y += 129;
break;
case 4:
finalShip.rotation = -180;
finalShip.x += 50;
finalShip.y += 202;
break;
case 5:
finalShip.rotation = -120;
finalShip.x -= 51;
finalShip.y += 172;
break;
case 6:
finalShip.rotation = -60;
finalShip.x -= 76;
finalShip.y += 72;
break;
}
//create ship graphics object. Numerous ship graphics representing all countries and all rates (1st-7th). There are multiple options in some country/rate cases
var currShipGraphic:WSIM_Ship_Graphics = new WSIM_Ship_Graphics();
//select correct background and ship graphics. Counter backgrounds are selected by ship country and ship rate sets the correct ship image to place on that background
switch (finalShip.country) {
//United States
case "US":
//set US background
finalShip.gotoAndStop("US_def");
//Select correct ship overlay based on ship rating (1st-7th)
switch (finalShip.shipRate) {
//US had no ships of the line. Well there was America but she saw no action and was given to the French
//everything gets frigate for now
case 5:
case 6:
case 7:
currShipGraphic.gotoAndStop("US_5_1");
break;
}
break;
//Great Britain
case "GB":
//set GB background
finalShip.gotoAndStop("GB_def");
switch (finalShip.shipRate) {
case 1:
currShipGraphic.gotoAndStop("GB_1_1");
break;
case 2:
currShipGraphic.gotoAndStop("GB_2_1");
break;
case 3:
currShipGraphic.gotoAndStop("GB_3_1");
break;
case 4:
currShipGraphic.gotoAndStop("GB_4_1");
break;
//everything gets frigate for now
case 5:
case 6:
case 7:
currShipGraphic.gotoAndStop("GB_5_1");
break;
}
break;
//France
case "FR":
//set FR background
finalShip.gotoAndStop("FR_def");
switch (finalShip.shipRate) {
case 1:
currShipGraphic.gotoAndStop("FR_1_1");
break;
case 2:
case 3:
//we have multiple options for French 3rd rate SoL
var FR_shipGraphicRandom:int = Math.ceil(Math.random() * 2);
switch (FR_shipGraphicRandom) {
case 1:
currShipGraphic.gotoAndStop("FR_3_1");
break;
case 2:
currShipGraphic.gotoAndStop("FR_3_2");
break;
}
break;
case 4:
currShipGraphic.gotoAndStop("FR_4_1");
break;
//everything gets frigate
case 5:
case 6:
case 7:
currShipGraphic.gotoAndStop("FR_5_1");
break;
}
break;
//Spain
case "ES":
//set ES background
finalShip.gotoAndStop("ES_def");
switch (finalShip.shipRate) {
case 1:
currShipGraphic.gotoAndStop("ES_1_1");
break;
case 2:
case 3:
case 4:
currShipGraphic.gotoAndStop("ES_3_1");
break;
//everything gets frigate
case 5:
case 6:
case 7:
currShipGraphic.gotoAndStop("ES_5_1");
break;
}
break;
//Netherlands
case "NL":
//set NL background
finalShip.gotoAndStop("NL_def");
switch (finalShip.shipRate) {
case 1:
case 2:
case 3:
case 4:
currShipGraphic.gotoAndStop("NL_3_1");
break;
//everything gets frigate
case 5:
case 6:
case 7:
currShipGraphic.gotoAndStop("NL_5_1");
break;
}
break;
}
currShipGraphic.x = 0;
currShipGraphic.y = 0;
currShipGraphic.name = "currShipGraphic";
//add correct ship graphic to the counter background
finalShip.addChild(currShipGraphic);
//font and format for counter text fields
var arialFont = new Arial();
var lucidaFont = new Lucida_Cal();
var textShipNameFormat: TextFormat = new TextFormat();
textShipNameFormat.size = 11;
textShipNameFormat.font = lucidaFont.fontName;
//ship name text field
var textShipName: TextField = new TextField();
textShipName.defaultTextFormat = textShipNameFormat;
textShipName.name = "textShipName";
textShipName.width = 80;
textShipName.height = 13;
textShipName.x = 34;
textShipName.y = 105;
textShipName.embedFonts = true;
textShipName.textColor = 0xFFFFFF;
textShipName.rotation -= 90;
textShipName.sharpness = 200;
textShipName.htmlText = "<p align='center'>" + finalShip.name + "</p>";
//font format for movement and turn allowance
var textShipNumbersFormat: TextFormat = new TextFormat();
textShipNumbersFormat.size = 12;
textShipNumbersFormat.font = arialFont.fontName;
//ship turn allowance
var textShipTurnAllowance: TextField = new TextField();
textShipTurnAllowance.defaultTextFormat = textShipNumbersFormat;
textShipTurnAllowance.name = "textShipTurnAllowance";
textShipTurnAllowance.width = 20;
textShipTurnAllowance.height = 13;
textShipTurnAllowance.x = 33;
textShipTurnAllowance.y = 127;
textShipTurnAllowance.embedFonts = true;
textShipTurnAllowance.textColor = 0xFFFFFF;
textShipTurnAllowance.rotation -= 90;
textShipTurnAllowance.text = finalShip.turnAllowance;
//ship movement allowance AS DISPLAYED ON THE COUNTER - display either battle sails speed or full sails speed depending on ship state
var textShipSailSpeed: TextField = new TextField();
textShipSailSpeed.defaultTextFormat = textShipNumbersFormat;
textShipSailSpeed.name = "textShipSailSpeed";
textShipSailSpeed.width = 20;
textShipSailSpeed.height = 13;
textShipSailSpeed.x = 33;
textShipSailSpeed.y = 14;
textShipSailSpeed.embedFonts = true;
textShipSailSpeed.textColor = 0xFFFFFF;
textShipSailSpeed.rotation -= 90;
//full sails set
if ("full" == finalShip.sailState) {
textShipSailSpeed.text = finalShip.fullSailSpeed;
}
//battle sails set, which are reduced sails to improve visibility and reduce sail damage in combat
else {
textShipSailSpeed.text = finalShip.battleSailSpeed;
}
// textShipBattleSailSpeed and textShipFullSailSpeed no longer used on counters, but still used in Info screens
var textShipBattleSailSpeed: TextField = new TextField();
textShipBattleSailSpeed.name = "textShipBattleSailSpeed";
textShipBattleSailSpeed.text = finalShip.battleSailSpeed;
textShipBattleSailSpeed.visible = false;
var textShipFullSailSpeed: TextField = new TextField();
textShipFullSailSpeed.name = "textShipFullSailSpeed";
textShipFullSailSpeed.text = finalShip.fullSailSpeed;
textShipFullSailSpeed.visible = false;
//create sailState (battle/full) indicator
var sailStateIndicator: WSIM_Counters_SailtState_Indicator = new WSIM_Counters_SailtState_Indicator();
//set indicator to correct sailState background graphic
sailStateIndicator.gotoAndStop("battle");
if ("full" == finalShip.sailState) {
sailStateIndicator.gotoAndStop("full");
}
sailStateIndicator.name = "sailStateIndicator";
finalShip.addChild(sailStateIndicator);
//add ship and attach text fields
gridBG1.addChild(finalShip);
finalShip.addChild(textShipName);
finalShip.addChild(textShipSailSpeed);
finalShip.addChild(textShipTurnAllowance);
finalShip.addChild(textShipBattleSailSpeed);
finalShip.addChild(textShipFullSailSpeed);
finalShip.parent.setChildIndex(finalShip, 1);
//logging
if (log_shipCreation) {
trace(finalShip.name + " added added as child of background in createShip()");
}
//create background sprite "ship is selected" border
var border: Sprite = new Sprite();
border.name = "shipBorder";
border.graphics.beginFill(0xFFCC00, 1);
border.graphics.drawRect(-1, -1, 52, 132)
border.graphics.endFill();
border.visible = false;
//create background sprite combat border
var borderCombat: Sprite = new Sprite();
borderCombat.name = "borderCombat";
//Great Britain ships are bright red, need to make combat border white
if ("GB" == finalShip.country) {
borderCombat.graphics.beginFill(0xFFFFFF, 1);
}
else {
borderCombat.graphics.beginFill(0xFF0000, 1);
}
borderCombat.graphics.drawRect(-1, -1, 52, 132)
borderCombat.graphics.endFill();
borderCombat.visible = false;
//add the borders as children of ship
finalShip.addChild(border);
finalShip.addChild(borderCombat);
//move the borders in z-order to behind ship counter, so they show looking like a border
border.parent.setChildIndex(border, border.parent.getChildIndex(border) - 5);
borderCombat.parent.setChildIndex(borderCombat, borderCombat.parent.getChildIndex(borderCombat) - 6);
//PUSH TO MASTER SHIP ARRAYS
//finalShip is Side 1, add to master list of ship objects for Side 1
if (sideList[0] == finalShip.country) {
shipListSide1.push(finalShip);
//logging
if (log_shipCreation) {
trace(finalShip.name + " added to Shiplist1 in createShip()");
}
}
//Side 2, add to master list of ship objects for Side 2
else {
shipListSide2.push(finalShip);
//logging
if (log_shipCreation) {
trace(finalShip.name + " added to Shiplist2 in createShip()");
}
}
//disable events on all children
finalShip.mouseChildren = false;
//ship selection event handler
finalShip.addEventListener(MouseEvent.CLICK, selectShip);
}

how do I call a function if the image clicked is equal to its matching word? Actionscript3

When my random word appears the user has to memorise it and click the correct corresponding image to it. I'm trying to write the code that runs if the user selects the right image. I have paired my words and images in my array. I'm just unsure as how to go about calling this function.
This is what I've attempted so far, but this isn't working. I'm new to actionscript3 so excuse the lack of knowledge as I am trying to teach myself.
All help greatly appreciated!!
This is one way you can do this:
See code comments
basket.visible = false;
//------ Home Button ------\\
backhome1btn.addEventListener(MouseEvent.CLICK, goback1Click);
function goback1Click(event:MouseEvent):void{
gotoAndStop("homepage");
}
//-------------------
var score:int = 0;
var items:Array = new Array(); //store all food items in array
var wordsToShow:Array = new Array(); //store all words to show in array - this is the array that will keep track of which has been asked (or rather not asked yet)
//to reduce redundant code, call this with each food item (below)
function initFoodItem(item:MovieClip, word:String):void {
item.word = word; //forget the array, just store the word on the image as a dynamic property
item.addEventListener(MouseEvent.CLICK, foodClicked);
items.push(item); //add to array
wordsToShow.push(item); //add to array
item.visible = false;
}
initFoodItem(oc, "Orange Juice");
initFoodItem(sand, "Sandwich");
//...repeat for all other food items
//now randmize the words to show array:
wordsToShow.sort(function(a,b):int {
return(Math.random() > .5) ? 1 : -1;
});
var curAnswer:MovieClip; //a var to store the current correct answer
//this does the next question per se
function displayWord():void {
if(wordsToShow.length < 1){
//they've all been asked
gotoAndPlay("gameoverpage");
return;
}
curAnswer = wordsToShow.pop(); //assigns the last item in the array to the cur asnwer, and pop also removes that item from the array (so it won't get asked again)
randomword.text = curAnswer.word; //assign the text to the word value of this item
randomword.visible = true;
remember.visible = true;
}
remember.addEventListener(MouseEvent.CLICK, readyClick);
//when you click your ready button
function readyClick(e:MouseEvent):void {
//we have an array of all items, let's loop through it and change them all to be visible
for (var i:int = 0; i < items.length; i++) {
//items[i].alpha = 1; //alpha values are 0 - 1 in AS3
items[i].visible = true; //use visible instead of alpha if just toggling visibility, it's more efficient
}
randomword.visible = false;
remember.visible = false;
bask.visible = true;
notepape.visible = false;
//! another reason to use visible instead of alpha = 0, is alpha = 0 items will still be clickable! visible = false items cannot be clicked.
}
function foodClicked(e:MouseEvent):void {
if (e.currentTarget == curAnswer) {
//if the current target (the item clicked) is the same item as what we stored in curAnswer, you answered correctly, so do this:
score += 10; //or however much you get for answering correctly
gotoAndStop("listpage"); //not sure what this does?
displayWord();
}else {
//wrong
gotoAndStop("gameoverpage");
}
}

Delete the bitmap directly behind newly placed bitmap - AS3

Tile-based map maker. I want to click the canvas, it places a tile, change tile, click the canvas and it replace the bitmap that I clicked on. .alpha shows clearly that all I am doing is stacking tiles... which will become a problem when I make a 2d array from it. I imagine that there's a way to make layers that they could sit on, but I haven't been able to find anything about it. Here's the code -
public function DrawATile(e:Event, tileToDraw:Object)
{
if (mouseXind <= 19 && mouseYind <= 14) //Only within the canvas!!
{
var newTile:Bitmap = new Bitmap(tileToDraw.Graphic);
newTile.x = mouseXind*32;
newTile.y = mouseYind*32;
newTile.alpha = .4;
addChild(newTile);
setChildIndex(newTile, this.numChildren-1); //Put this graphic behind the grid.
}
}
I want to delete the tile below the new tile that I place. I place a tile... I place a diferent tile over the old tile, I want the old tile to delete... not just stack tiles.
Sounds like you just need to keep track of the previous tile, then remove it accordingly:
private var curTile:Bitmap; //let's keep a reference to the current tile
public function DrawATile(e:Event, tileToDraw:Object)
{
if (mouseXind <= 19 && mouseYind <= 14) //Only within the canvas!!
{
//if there is a current tile, remove it from the display list
if(curTile){
removeChild(curTile);
}
//create your new one as usual
var newTile:Bitmap = new Bitmap(tileToDraw.Graphic);
newTile.x = mouseXind*32;
newTile.y = mouseYind*32;
newTile.alpha = .4;
addChild(newTile);
setChildIndex(newTile, this.numChildren-1); //Put this graphic behind the grid.
curTile = newTile; //make the current tile the one just created
}
}
EDIT
Based off you comment, this seems more like the solution you're looking for.
Sounds like you just want the tile to go away when clicked.
private var curTile:Bitmap; //let's keep a reference to the current tile
public function DrawATile(e:Event, tileToDraw:Object)
{
if (mouseXind <= 19 && mouseYind <= 14) //Only within the canvas!!
{
var newTile:Bitmap = new Bitmap(tileToDraw.Graphic);
newTile.x = mouseXind*32;
newTile.y = mouseYind*32;
newTile.alpha = .4;
addChild(newTile);
setChildIndex(newTile, this.numChildren-1); //Put this graphic behind the grid.
//add a click listener to delete this tile when clicked
newTile.addEventListener(MouseEvent.CLICK, deleteTile, false, 0 true); //make sure the event listener has a weak listener
}
}
private function deleteTile(e:Event):void {
var tile:Bitmap = e.currentTarget as Bitmap;
if(tile.parent) tile.parent.removeChild(tile);
}
I pushed it all into an array, with placeholder strings for every unoccupied cell. Then I check if the index at my current mouse position is a DisplayObject and remove it if it is, replacing it with the new tile.
public function DrawATile(e:Event, tileToDraw:Object)
{
if (mouseXind <= 19 && mouseYind <= 14) //Only within the canvas!!
{
if(aarray[mouseYind][mouseXind] is DisplayObject)
{
removeChild(aarray[mouseYind][mouseXind]);
}
var newTile:Sprite = new Sprite();
var bmp:Bitmap = new Bitmap(tileToDraw.Graphic);
newTile.addChild(bmp);
newTile.x = mouseXind*32;
newTile.y = mouseYind*32;
addChild(newTile);
aarray[mouseYind][mouseXind] = newTile;
}
}

Flex mobile - increase list scrolling performance

Imagine a tablet app that displays two content areas side by side. They completely fill the display, so are 100% in height and 50% in width.
Lets assume we add a list to one container. Naturally this list will consume half the space of the whole display.
Now to my problem, is it possible that high framerate scrolling is kind of impossible with lists of this size? I've got the most basic AS3 ItemRenderer and still can't get anything higher than 30fps during scrolling. Now the odd part, if I add stuff the other container, lets say another list or other components, the list scrolling performance drops to the low 20s.
So nowhere near the 40+ fps you see Adobe advertising in their MAX shows.
I'm testing on a iPad2 and 3 and even with static values, scrolling isn't really good. Now if I enable streaming values so that the ItemRenderer's set data method is called, the framerate drops another 2 to 3 frames.
My (almost) complete renderer looks like this, but even if I strip it to just display a single textfield, disable the stuff going on in the set data and also set only the size of the single textfield in the layoutContents, performance is as described, about 30 if the list is displayed alone, low 20s if other stuff is displayed as well.
//FCStyleableTextField is just a StyleableTextField with an additional ID
private var _textFields:Vector.<FCStyleableTextField>;
private var _oldValues:Dictionary;
private var _sym:Symbol;
public function GridRenderer() {
super();
_textFields = new Vector.<FCStyleableTextField>();
_oldValues = new Dictionary();
}
override protected function createChildren():void {
var _symLabel:FCStyleableTextField = new FCStyleableTextField();
_symLabel.editable = false;
_symLabel.selectable = false;
_symLabel.multiline = false;
_symLabel.id="sym";
_symLabel.setStyle("fontSize", fontSize);
_symLabel.textColor = 0xc0c0c0;
_textFields.push(_symLabel);
addChild(_symLabel);
var fidLen:int = fids.length;
for (var i:int = 0; i<fidLen; i++) {
var _fid_lbl:FCStyleableTextField = new FCStyleableTextField();
_fid_lbl.selectable = false;
_fid_lbl.editable = false;
_fid_lbl.multiline = false;
_fid_lbl.id = String(fids[i]);
_fid_lbl.textColor = 0xc0c0c0;
_fid_lbl.setStyle("textAlign", "right");
_fid_lbl.setStyle("fontSize", fontSize);
_fid_lbl.text = " ";
_textFields.push(_fid_lbl);
addChild(_fid_lbl);
if(i>visibleColumns) {
_fid_lbl.includeInLayout = false;
_fid_lbl.visible = false;
}
}
}
override public function set data(value:Object):void {
if(!value) return;
if(data) {
// check if the value's symbolName is different than the current
// data's symbolName, if so, the itemRenderer has been
// recycled, thus we need to reset the old fid values
if((value as Symbol).symbolName != (data as Symbol).symbolName)
_oldValues = new Dictionary();
}
super.data = value;
_sym = data as Symbol;
try {
var textLen:int = _textFields.length;
for (var i:int = 0; i<textLen;i++) {
var lbl:FCStyleableTextField = _textFields[i];
if(lbl.id == "sym") {
lbl.text = _sym.symbolName;
lbl.truncateToFit();
} else {
if(lbl.id == _sym.fidList.fidMap[lbl.id].fidId && lbl.text != _sym.fidList.fidMap[lbl.id].fieldValue) {
var time:int = new Date().time;
var timerName:String = _sym.symbolName+","+lbl.id+","+grid;
globalTimer.addTimer(timerName, time, "reset", lbl, null, null);
var _oldVal:* = _oldValues[lbl.id];
var _newVal:* = _sym.fidList.fidMap[lbl.id].fieldValue;
// basic color formatting
if(Number(_newVal) > Number(_oldVal))
lbl.textColor = 0x40c040;
else if(Number(_newVal) < Number(_oldVal))
lbl.textColor = 0xf05050;
// add + to change and changePercent fids if value is positive
if(lbl.id == "56") {
if(_newVal >0)
lbl.text = "+" + _newVal;
else
lbl.text = String(_newVal);
} else if(lbl.id == "11") {
if(_newVal >0)
lbl.text = "+" + _newVal;
else
lbl.text = String(_newVal);
} else
lbl.text = String(_newVal);
if(!_sym.fidList.fidMap[lbl.id].fieldValue)
lbl.text =" ";
_oldValues[lbl.id] = _newVal;
}
}
lbl.truncateToFit();
}
} catch (e:Error) { /* nothing to do here -> try/catch required due to async symbolassembly */ }
}
override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void {
var viewWidth:Number = unscaledWidth - paddingLeft - paddingRight;
var viewHeight:Number = unscaledHeight - paddingTop - paddingBottom;
var _previousLabel:FCStyleableTextField;
var textLen:int = _textFields.length;
for(var i:int =0; i<textLen;i++) {
var lbl:FCStyleableTextField = _textFields[i];
graphics.beginFill(0x808080, .3);
lbl.height = viewHeight;
lbl.y = paddingTop;
if(lbl.id=="sym") {
lbl.width = 95;
} else if (lbl.id == "35000") {
lbl.width = 24;
} else {
lbl.width = optimalColWidth;
}
_previousLabel ? lbl.x = (_previousLabel.x + _previousLabel.width): lbl.x = paddingLeft;
graphics.drawRect(lbl.x+lbl.width, 1, 1, unscaledHeight-1);
lbl.commitStyles();
_previousLabel = lbl;
graphics.endFill();
}
}
Still, I'm pretty sure that it is not the item renderer that causes the slowdown, cause as I said, it costs 2, maybe 3 frames compared to a renderer that displays just a single textfield.
I rather think that Flex somehow can't handle the amount of vectors being displayed at once, is something like that possible? And is there any way to boost performance?
I already disabled live streaming values as soon as the user scrolls the list, so that flex basically just has to scroll bitmaps (since LabelItemRenderer automatically enables cacheasbitmap), but that gained maybe 4 frames.
What are your guys tricks to make scrolling a little smoother?
Figured out that using setElementSize() and setElementPosition() instead of using width/height and x/y makes quite a difference. Gained 3fps in initial scrolling performance and 8fps once every item has been rendered.
So I'm pretty close to 30fps now, still not close to what you can do with a native app, but I figure that's as good as it gets with Flex and such a massive renderer.
Also disabled live updates so that the renderer doesn't need to be cached as a bitmap again when updates come in.