I hope you're well.
I've a problem that I do not understand. My variables seem to update but they don't (i've explained further in context in the code below).
[I'm trying to create a store where my users can buy bosses for my game].
I really hope you can help me :)
Here is the code. Do not hesitate to ask me for further details (number total of bosses will be around 36).
var bossBuyBtnArray:Array=[campagnesBuy.boss1, campagnesBuy.boss2];
//array with the MovieClips used as button to buy
var pbArray:Array=[campagnesBuy.pb1, campagnesBuy.pb2]; //array with MovieClips that tells if boss is owned or not
var bossVar:Array=[sp[59], sp[60]]; //array with int variables needed to save the state of inventory
for each(var storeBtn: MovieClip in bossBuyBtnArray)
storeBtn.addEventListener(MouseEvent.CLICK, fnBossStoreBtn); //when user click on the store buttons,
function fnBossStoreBtn(e: Event): void {
var listElementBoss: DisplayObject = e.target as DisplayObject; //listeElementBoss = Selected Boss.
var iBoss: int = bossBuyBtnArray.indexOf(listElementBoss); //get the index of the selected boss
if (iBoss < 0) { //check if selected boss is in the array
listElementBoss = e.currentTarget as DisplayObject;
if (listElementBoss) iBoss = bossBuyBtnArray.indexOf(listElementBoss);
}
if (iBoss < 0) return;
if(pbArray[iBoss].currentFrame == 1){ //check if boss not already owned.
if (sp[58]>999){ //check if user has enough gold.
/*The Part that Doesn't Work : */
bossVar[iBoss] = 1; //modify the variable (sp[59] or sp[60])
//normally it would update the variable, let's say sp[59] if boss 1 is selected.
//The interface is modified by fnAlreadyOwned (see below) so I guess something is updated,
//But when I trace(sp[59]), it says 0, and the writeObject() function saves 0. Meaning that
//when I reload the game, the gold is gone, but boss is locked again.
/*The rest works*/
sp[58] = sp[58] -1000; //substract cost of the boss from the total gold.
gameMode.pirateTxt.text = sp[58]; //update gold "inventory"
writeObject(); //save the state of gold and boss ownership
fnAlreadyOwned(null);// updates the interface
}else{
trace("not enough gold"); //if not enough gold
}
}else{
trace("already owned"); //if boss already owned.
}
}
When you do this:
var bossVar:Array=[sp[59], sp[60]]; //array with int variables needed to save the state of inventory
you take the variables from the sp array and put them in bossVar array. int variables are copied in this case.
That means changing either sp[59] or bossVar[0] won't change the other.
example code:
var a:Array = [1, 2];
var b:Array = [a[0], 5];
a[0] = 42;
trace("a[0] =" + a[0]);
trace("b[0] =" + b[0]);
You could circumvent that by storing objects for example.
Related
Okay, so I'm trying to create a mobile flash game (I'm mostly an animator, a storyteller) and I'm having trouble with the input text for the player name. I've often read helpful tips on this site so I signed up to get some help. The code I use to load and save data is saveDataObject, But as far as I know input text has to be used with package code. I tried to convert it to function var, but then these errors occur. I am unsure how to use the Package class code, and everything I've read on it has been confusing. I am pretty much self taught for everything I know about code though tutorials and forums, so if it isn't explained in a way I can understand I wont be able to do it...
Here's the section of code if I wasn't clear(error lines separate):
var playerName:int;
init(); // this line goes directly beneath the variables
function f_1(init):void
{ // call once to set everything up
saveDataObject = SharedObject.getLocal("DataBattle/character/name"); // give the save data a location
-
playerName = txtPlayer;
-
function addName(e:TouchEvent):void
{
var myTextBox1:TextField = new TextField();
var txtPlayer:TextField = new TextField();
var myText:String = "Cyan";
function CaptureUserInput()
{
captureText();
}
function captureText():void
{
myTextBox1.type = TextFieldType.INPUT;
myTextBox1.background = true;
addChild(myTextBox1);
myTextBox1.text = myText;
myTextBox1.addEventListener(TextEvent.TEXT_INPUT, textInputCapture);
}
function textInputCapture(event:TextEvent):void
{
var str:String = myTextBox1.text;
createOutputBox(str);
}
function createOutputBox(str:String):void
{
txtPlayer.background = false;
txtPlayer.x = 200;
addChild(txtPlayer);
txtPlayer.text = str;
}
-
if(saveDataObject.data.characterName = playerName == null)
-
{ // checks if there is save data
trace("No Player data yet."); // if there isn't any data on the computer...
saveDataObject.data.characterName = playerName; // ...set the savedScore to 0
}
else
{
trace("Player data found."); // if we did find data...
loadData1(); // ...load the data
}
function loadData1():void
{
playerName = saveDataObject.data.characterName; // set the current score to the saved score
trace("Data Loaded!");
}
}
}
function saveData(e:TouchEvent):void
{
saveDataObject.data.characterName = playerName; // set the saved score to the current score
trace("Data Saved!");
saveDataObject.flush(); // immediately save to the local drive
trace(saveDataObject.size); // this will show the size of the save file, in bytes
}
Would be nice to have some more details about this error. Like which line is actually throwing this error.
However even without it there are few things that looks weird right away.
var playerName:int;
// And few lines below
playerName = txtPlayer;
// Few more lines below
var txtPlayer:TextField = new TextField();
Looks like you're declaring playerName as int so you want to store numeric values, but then txtPlayer is a TextField. So by playerName = txtPlayer; you're trying to store TextField as Int value, which is not gonna work.
I can also see
if(saveDataObject.data.characterName = playerName == null)
and it's like :O
I'm not even sure how this part is being compiled. You want to do playerName == null check (which would return true/false) and then assign it to saveDataObject.data.characterName ?
I'm a bit new with AS3 (but not really with coding) so please forgive my ignorance. I'm creating a small function that will be called by a Main Function to update the position of 52 Pointers that have the x and y position of multiple point objects (empty movie clips). It will also then update two global arrays with those values (one array for the x and one for the y).
The problem is, as there are 52 of them, and they will probably grow in quantity, I'd like to be able to use a FOR function to do it, but I can't seem to be able to figure it out.
I get this error: Access of undefined property _point.
Here is a piece of the code that dream about:
function happyFunc():void
{
var avpointers:int = 52;
var vpointx:Array = new Array();
var vpointy:Array = new Array();
for (aa=0; aa<vpointers; aa++)
{
vpointx[aa] = _point[aa].x;
vpointy[aa] = _point[aa].y;
}
}
And this is the code that I'm stuck with...
function reallySadFunc():void
{
_point1 = localToGlobal(new Point(point1.x,point1.y));
//...
_point52 = localToGlobal(new Point(point52.x,point1.y));
vpointx[0] = _point1.x;
vpointx[1] = _point2.x;
//...
//oh god there are 104 lines of this why do I have to suffer
}
Thank you!
If I read your question correctly, I think this is what you need:
public static const CLIP_COUNT:int = 52;
// ...
private function happyFunc(parentClip:DisplayObjectContainer):void
{
var vpointx:Vector.<Number> = new Vector.<Number>(CLIP_COUNT, true);
var vpointy:Vector.<Number> = new Vector.<Number>(CLIP_COUNT, true);
var clipPoint:Point = new Point ();
var globalPoint:Point;
for (var i:int = 0; i < CLIP_COUNT; i++)
{
var childClip:DisplayObject = parentClip.getChildByName("point" +
(i + 1).toString());
clipPoint.x = childClip.x;
clipPoint.y = childClip.y;
globalPoint = parentClip.localToGlobal(clipPoint);
vpointx[i] = globalPoint.x;
vpointy[i] = globalPoint.y;
}
// do something with vpointx and vpointy - they're local variables
// and will go out of scope unless you declare them as class members
// or somehow return them from this function.
}
This function works by taking the parent display object (the one that contains the 52 movie clips - this could be the Stage) and iterates through them by getting each movie clip by name. The code assumes that your movie clips are called point1, point2, ..., point52.
To speed up the local-to-global coordinate conversion, two Point objects are created and then reused during the for loop to avoid creating many temporary Point instances.
Instead of using Array, use Vector.<Number> - this class has better performance than Array does.
I've been working on a Flash drag-and-drop scene using AS3. The scene is broken into 4 "zones", and each zone has 5 targets. I've used arrays to allow the mc's to be dropped in their respective zones, without any particular order. All of this works as it should.
The issue I have it that there are 2 "puzzle" pieces (MCs) that are identical to one-another in terms of how they visually display on the screen. I've set up the arrays to allow for both to be dropped in zone 1 or zone 2. However, I'd like to set it up so that if "identical piece 1" gets dropped into zone 1, then "identical piece 2" cannot also be dropped into that same zone.
Any suggestions for how to go about doing this?
How about setting a flag in every zone that tells if a piece has already been attached to it?
If your zones are MovieClips you can simply add variables to them, and set mcTarget.isTaken = true when a piece gets attached to it. If they are simply coordinates, you can use a global array like this
private mZoneTaken:Array = new Array();
for (var i:int=0; i<4; i++)
{
mZoneTaken[i] = new Array();
for (var j:int = 0; j<5; j++)
{
mZoneTaken[i][j] = false;
}
}
Then whenever a piece is dropped on a zone, you can set its flag to true, allowing you to prevent any further piece from getting attached to it.
Personally, I would have an array/Vector (Vectors are much, much faster. Though they can be a royal pain to use) of objects within each individual zone. You keep this updated at all times. If you remove one, you use splice(indexOf(obj),1) to remove it from the array.
For your problem, I would do this:
var p1:Sprite = new Sprite();
var p2:Sprite = new Sprite();
var zoneArray:Array = new Array();//there would be one for each zone, simplified it here
//this code would run whenever an object enters the zone
function zoneEnter(e:Event = null):void{
var currentZone:Sprite; //set this equal to the zone the sprite just entered
var currentObject:Sprite = e.currentTarget as Sprite; //this way we know which object just entered currentZone
if ( currentObject == p1 && zoneArray.indexOf(p2) >= 0 ) {
//prevent it from entering the zone
}
if ( currentObject == p2 && zoneArray.indexOf(p1) >= 0 ) {
//prevent it from entering the zone
}
}
There are obviously some limitations here if you are looking at a lot of objects. But if you know, for sure, there will only be two, I think this would be the way to go. If there will be more, you would need to create some kind of control structure that would allow you to check an object against other objects. I could elaborate and give a sample of what I am talking of here if it's needed. It's a tad bit complex, but not hard to implement.
EDIT 10-17-12: Added in example code of how the more advanced logic would look.
var puzzleMap:Array = new Array();
var piece1:Piece = new Piece(); //this is the puzzle piece we'll be checking
var piece2:Piece = new Piece();
var piece3:Piece = new Piece();
var piece1Objs:Array = [piece2,piece3];
var piece2Objs:Array = [piece1,piece3];
puzzleMap.push({piece:piece1,others:piece1Objs});
puzzleMap.push({piece:piece2,others:puzzle2Objs);
private function stopDragHandler(e:MouseEvent = null):void{
var space:Space = space; //this is the space the object was dropped into (I don't know how you identify them, so this is pseudo code)
var valid:Boolean = true; //we'll check for a bad drop since it's easiest
if (event.target.dropTarget != null && MovieClip(event.target.dropTarget.parent).allowed.indexOf(event.target) > -1){
for ( var i:Number = 0; i < puzzleMap.length; i++ ) {
var current:Object = puzzleMap[i];
if ( current == e.currentTarget ) {
for ( var j:Number = 0; j < current.others.length; j++ ) {
var checkAgainst:Piece = current.others[i] as Piece;
if ( space.currentObjects.indexOf(checkAgainst) < 0 ) {
valid = false;
break;
}
}
}
}
if ( !valid ) {
//prevent the drop here
}
}
}
I've created a score system in my flash Quiz game where the faster you answer a question, the more points you get. At the moment however my tracer shows 'NAN' when I run my game. Can anybody see why this is?
var score:int = 0;
var count:int = 0;
var mTimer:Timer;
mTimer = new Timer(100, 70);
function processScore():void {
var count:int = mTimer.currentCount;
var score:int = score + (700 - (count * 10));
trace("score registered");
}
trace(aUserAnswers[numLoops] + " " + returnedNumber);
if(aUserAnswers[numLoops] == returnedNumber){
processScore();
}
returnedNumber is when a button is clicked, if the number matches that which is in the array, the question is correct.
Thank you
You're redeclaring count and score inside processScore(). That makes them local variables to the function, unrelated to the previous declared variables of the same name. This means that their values are lost when the function finishes and the previous variables are unchanged. I'm guessing that at some point you divide something by one of them and since you'll always be dividing by zero you get NAN.
I came across a unique (to me), and quite puzzling situation.
I have an array of three values.
focal[x,y,z]
these values change based on user input.
however when the change occurs, they are logged into a new array to test for valid changed
A simplified psuedo version of my code:
var temp:Array = focal; //I have even changed this to a const at times but to no avail
//changes to array are made like thus:
focal[1]++;
focal[0]--;
if(valid){
doStuff();
} else {
focal = temp;
}
However, when the focal[1]++; focal[0]--; ect, ect, code takes place. It also changed the temp array.
and since it changes my temp, it never resets me original code back to its previous nature.
I have never seen this behavior and its kinda throwin' me off. Suggestions?
when you are doing like this:
var temp:Array = focal; // Both array variables refer to the same array.
if you want to make a backup or temporary array you need to copy all the componetns from one to another:
var baseArray : Array = [0, 0, 0];
var tempArray : Array = baseArray.slice();
baseArray[0]++;
baseArray[1] += 2;
baseArray[2] += 3;
trace ( baseArray ); // output: 1,2,3
trace ( tempArray ); // output: 0,0,0
I add the deep copy method to the (very good) post by Jevgenij:
import flash.utils.ByteArray;
function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
More informations here: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7ee7.html