Simplifying code as3 - actionscript-3

I am still working on a project with pies. Going to the next level. Now I have this code that is repeating all the time and i am trying to make it simple and less code. So this code is repeated for pie 2 till 12. When I trie to use the toString command for the pie_mc i get an error that it 's not working for the MovieClip symbol. How can I solve this?
if(counter == 2) {
pie_mc = pie2_mc;
//pie_mc = "pie" + counter.toString()+"_mc";
pie_mc.visible = true;
for (i=1; i <= counter; i++){
partx_mc = "t"+ counter.toString()+"_p"+i.toString()+"_mc";
pie_mc[partx_mc].alpha = 0.6;
pie_mc[partx_mc].addEventListener(MouseEvent.CLICK, showPiepart);
}
}
if(counter == 3) {
pie_mc = pie3_mc;
//pie_mc = "pie" + counter.toString()+"_mc";
pie_mc.visible = true;
for (i=1; i <= counter; i++){
partx_mc = "t"+ counter.toString()+"_p"+i.toString()+"_mc";
pie_mc[partx_mc].alpha = 0.6;
pie_mc[partx_mc].addEventListener(MouseEvent.CLICK, showPiepart);
}
}
In dutch: 1067: Impliciete afgedwongen omzetting van een waarde van het type String in een niet-gerelateerd type flash.display:MovieClip.
- Implicit transform of a value of type string in a MovieClip.

Related

Different objects with the same function IF Error -Actionscipt

I am trying to create a drag and drop game.
I used an array and it works with drag and drop, but doesn't work with the IF function.
Instead, it shows me this error:
"TypeError: Error #1010: A term is undefined and has no properties.
at
Test_game_fla::MainTimeline/drop()[Test_game_fla.MainTimeline::frame1:38]"
Here is my code:
var s = 0;
score.text = s;
var mixed:Array = new Array;
mixed.push(orange);
mixed.push(cheese);
mixed.push(lobbio);
mixed.push(meat);
mixed.push(fish);
for (var i:uint = 0; i < mixed.length; i++) {
mixed[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
mixed[i].addEventListener(MouseEvent.MOUSE_UP, drop);
function drag(e)
{
e.target.startDrag();
}
function drop(e)
{
e.target.stopDrag();
if( (cheese.y > 50 && cheese.y < 150) && (cheese.x > 480 && cheese.x < 570) )
{
cheese.x = -50;
cheese.y = -50;
s = s + 10;
score.text = s;
}
if( (mixed[i].y > 50 && mixed[i].y < 150) && (mixed[i].x > 480 && mixed[i].x
< 570) )
{
mixed[i].y = -50;
mixed[i].x = -50;
s = s + 10;
score.text = s;
}
}
}
To explain what your actual problem is, it's the use of inline functions.
Inside your for loop, you define some functions (those are referred to as inline functions, and as mentioned in VC.One's answer, this is not a good practice - please follow their other advice as well).
Since those functions are defined inside the for loop block, every iteration you are actually creating a whole new function/object. When you create those functions, the ones called drop are referencing your iterator (i). BUT, those functions are not actually called until you MOUSE_UP. This mouse up trigger will happen long after the for loop has finished. At which point i will have a value of 5. Why 5? (as it only iterates from 0 - 4), because after every iteration i is incremented, so it will end up 1 higher than the last iteration.
Since there is no element at position 5 in your mixed array, you get the error.
To rectify the situation, follow the code example from the other answers (which break those functions out of the for loop)
Instead of referencing i, use the event's currentTarget property (which is a reference to the object that you attached the listener to).
Sprite(e.currentTarget).y
U can fix it like this.
var s = 0;
score.text = s;
var mixed:Array = new Array;
mixed.push(orange);
mixed.push(cheese);
mixed.push(lobbio);
mixed.push(meat);
mixed.push(fish);
for (var i:uint = 0; i < mixed.length; i++) {
mixed[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
mixed[i].addEventListener(MouseEvent.MOUSE_UP, drop);
}
function drag(e)
{
e.currentTarget.startDrag();
}
function drop(e)
{
var mix:Sprite = Sprite(e.currentTarget);
mix.stopDrag();
if( (cheese.y > 50 && cheese.y < 150) && (cheese.x > 480 && cheese.x < 570) )
{
cheese.x = -50;
cheese.y = -50;
s = s + 10;
score.text = s;
}
//Error in mixed[i] ; at last i = mixed.length mixed[i] is null.
//Event has a property "currentTarget" this can get u select target
if( (mix.y > 50 && mix.y < 150) && mix.x > 480 && mix.x < 570) )
{
mix.y = -50;
mix.x = -50;
s = s + 10;
score.text = s;
}
}
Some things to fix :
(1) Give your variables a data type. Saying var s = 0; suggests that s is a numerical variable, right? Well score.text expects a String not Number so you must use casting to convert. Try :
var s : int = 0; //define a numerical variable
score.text = String(s); //cast number into String type (for usage as text)
(2) Don't put your functions inside a For-loop!!! Don't even put functions inside other functions (unless you know what an Anonymous Function is, and you can justify needing it).
(3) You can shorten some code typing by :
Incrementing? Use s += 10 to avoid longer s = s + 10;. Can also be -=, /= etc.
If setting same value to multiple variables just chain like so: cheese.x = cheese.y = -50;
(4) Don't try to access mixed[i] by mixed.length. Since length is 5 at some point the compiler sees an instruction like : mixed[5].addEventListener...
However an array starts at zero for first item so you should understand the fifth item is really at mixed[4].addEventListener....
That other mixed[5].something (same as : mixed[mixed.length].something) does not exist.
PS : I would have thought that setting i < mixed.length would have protected against going over the array size, since if i must be smaller than .length then i == 5 could never happen.
Anyways... This code below is untested (no AS3 compiler here) but try the following :
var s : int = 0;
score.text = String(s);
var mixed:Array = new Array;
mixed.push(orange); mixed.push(cheese);
mixed.push(lobbio); mixed.push(meat); mixed.push(fish);
for (var i:uint = 0; i <= (mixed.length-1); i++)
{
mixed[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
mixed[i].addEventListener(MouseEvent.MOUSE_UP, drop);
} //end "For" loop
function drag(e) : void { e.target.startDrag(); }
function drop(e) : void
{
e.target.stopDrag();
if( (cheese.y > 50 && cheese.y < 150) && (cheese.x > 480 && cheese.x < 570) )
{
cheese.x = cheese.y = -50;
s += 10; //# achieves same thing as... s = s + 10;
score.text = String(s);
}
if( (Sprite(e.currentTarget).y > 50 && Sprite(e.currentTarget).y < 150) && (Sprite(e.currentTarget).x > 480 && Sprite(e.currentTarget).x < 570) )
{
Sprite(e.currentTarget).x = Sprite(e.currentTarget).y = -50;
s += 10;
score.text = String(s);
}
} //end Function "drop"

How to walk a game character using mouse event in Adobe Animate CC AS3?

This question is related to my previous post, “TypeError: Error #1010: A term is undefined and has no properties” in AS3 because as I mentioned there, I'm creating an Android Game for our thesis. Now, I have a spritesheet of a character in the link: sprite character, I'm using this in the game. I'm researching on how to walk a character, I found one at a website, it actually works but unfortunately, it fails because the character didn't actually walk. I have no idea on what code will be place there. Either I will walk a character by clicking mouse or I will create a button then click on it to walk a character. What would be the code can I use for that? Any help will be appreciated.
P.S. In my previous post, I'm creating a code from timeline but now I transfer it to Actionscript file because of some errors.
EDIT:
Here's my code of the character:
forward.addEventListener(MouseEvent.CLICK, ppap);
function ppap(event:MouseEvent):void{
gril.x += mouseX;
gril.y += mouseY;
gril.gotoAndStop('i');
gameloop();
}
function gameloop(): void {
for (var o = 0; o > 5; o++) {
if (linya.hitTestObject(gril)) {
o++;
gotoAndStop(2);
scorer.visible = true;
timer.visible = true;
}
}
}
And the line: gril.gotoAndStop('a'); where the character is standing.
The gril is the instance name of a character. When it reaches to linya, the question will appear. Thanks!
Let's walk through your broken game loop
function gameloop(): void {
for (var o = 0; o > 5; o++) { //sets o to 0, loops as long as o > 5 (which it isn't, since we just set it to 0;
if (linya.hitTestObject(gril)) {
o++; //this also adds 1 to o
gotoAndStop(2);
scorer.visible = true;
timer.visible = true;
}
// if this part ever executed, it would add 1 to o
}
}
Do you see the problem? This for loop will not execute even once since 0 < 5
Instead it should be
function gameloop(): void {
for (var i = 0; i < 5; i++) {
if (linya.hitTestObject(gril)) {
gotoAndStop(2);
scorer.visible = true;
timer.visible = true;
break;
}
}
}
So here we have a functional (but pointless) for loop. It will work, but the first time through the loop it is going to result in the exact same thing as the second and third and fourth and fifth because changing the variable value by 1 isn't actually changing anything at all. You just telling the program to check the collision state 5 times. Well it does this 5 times before anything else can change. It checks it 5 times every game loop. Well I promise you nothing is moving while that for loop is running so why check it 5 times? I suggest stepping back and getting some help from your teacher or something because this seems way off. Sorry.
Right again #NealDavis and thank You for the comment!!!
I wrote my comment too quickly
Ascending loop from 0->4 (5 items):
for (var i:uint = 0; i < 5; i++){
trace("ascending = " + i);
}
Output:
ascending = 0
ascending = 1
ascending = 2
ascending = 3
ascending = 4
Descending loop from 4->0 (5 items):
for (var j:int = 4; j>=0; j--){
// j must be an int in this case, second mistake!
trace("descending = " + j)
};
Output:
descending = 4
descending = 3
descending = 2
descending = 1
descending = 0
My mistake. SRY
This is well explained in Looping reference
And in ActionScript 3 fundamentals: Loops reference
Shame on me!!! ;)
I'm a noob! :D
So I deleted my comment ;)
WOW, I'm so sorry about this mistake!!!
// You may also create Vectors to store the values.
var ascending:Vector.<uint> = new Vector.<uint>;
var descending:Vector.<uint> = new Vector.<uint>;
for (var k:uint = 0; k < 5; k++){
ascending.push(k+1);
}
trace("ascending Vector.<uint> = " + ascending);
// Output : ascending Vector.<uint> = 1,2,3,4,5
for (var l:int = 4; l >= 0; l--){
descending.push(l+1);
}
trace("descending Vector.<uint> = " + descending);
// Output : descending Vector.<uint> = 5,4,3,2,1
Or in an ascending loop :
trace("\nascending Vector.<uint> loop : ")
for(var m:String in ascending){
trace(m + " = " + ascending[m]);
}
Output :
ascending Vector.<uint> loop :
0 = 1
1 = 2
2 = 3
3 = 4
4 = 5
Or in a descending loop :
trace("descending Vector.<uint> loop : ")
for(var n:String in descending){
trace(n + " = " + descending[n]);
}
Output:
descending Vector.<uint> loop :
0 = 5
1 = 4
2 = 3
3 = 2
4 = 1

AS 3 Error Null Object

I've got an error in my game in AS3. When my array lenght is 0 the app should go to the Menu scene. However it always appears a box saying:
TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/removeChild()
at kitkat_game_fla::MainTimeline/moveBall()[kitkat_game_fla.MainTimeline::frame2:105]
I click on dismiss all and when i start the game again the ball is completely fast. What should i do. Is it because my mcBall.x is null and it shouldn´t? I already search and nothing works. Some help please.
Here's my code
stop();
var ballSpeedX:int = 23;//Velocidade em X da bola.
var ballSpeedY:int = 23;//Velocidade em Y da bola.
var mySound:Sound = new myFavSong();
var myArray:Array = new Array(mc1,mc2);
trace (myArray.length);
function iniciarCode():void{
mcPaddle.addEventListener(Event.ENTER_FRAME, movePaddle);
mcBall.addEventListener(Event.ENTER_FRAME, moveBall);
}
function movePaddle(event:Event):void{
var dx:int = mcPaddle.x - mouseX;
mcPaddle.x -= dx / 5;
if(mcPaddle.x <= mcPaddle.width/2){
mcPaddle.x = mcPaddle.width/2;
}else if(mcPaddle.x >= stage.stageWidth-mcPaddle.width/2){
mcPaddle.x = stage.stageWidth-mcPaddle.width/2;
}
}
function moveBall(event:Event):void{
mcBall.x += ballSpeedX;
mcBall.y += ballSpeedY;
if(mcBall.x <= mcBall.width/2){
mcBall.x = mcBall.width/2;
ballSpeedX *= -1;
} else if(mcBall.x >= stage.stageWidth-mcBall.width/2){
mcBall.x = stage.stageWidth-mcBall.width/2;
ballSpeedX *= -1;
}
if(mcBall.y <= mcBall.height/2){
mcBall.y = mcBall.height/2;
ballSpeedY *= -1;
} else if(mcBall.y >= stage.stageHeight-mcBall.height/2){
mcBall.y = stage.stageHeight-mcBall.height/2;
ballSpeedY *= -1;
}
if(mcBall.hitTestObject(mcPaddle)){
calcBallAngle();
}
if(mcBall.hitTestObject(mc_lettering)){
calcBallAngle();
}
if(mcBall.hitTestObject(mc1)){
removeChild(mc1);
myArray.splice(mc1, 1)
trace(myArray.length);
mc1 == null;
}
if(mcBall.hitTestObject(mc2)){
removeChild(mc2);
myArray.splice(mc2, 1);
trace(myArray.length);
mc2 == null;
}
if(myArray.length == 0){
gotoAndPlay(1,"Menu");
}
if(mcBall.hitTestObject(mcPaddle.barra_mc1)){
mcPaddle.removeChild(mcPaddle.barra_mc1);
mcPaddle.barra_mc1 == null;
mySound.play();
}
}
function calcBallAngle():void{
var ballPosition:Number = mcBall.x - mcPaddle.x;
var hitPercent:Number = (ballPosition / (mcPaddle.width - mcBall.width)) - .5;
ballSpeedX = hitPercent * 30;
ballSpeedY *= -1;
}
iniciarCode();
myArray.splice(mc2, 1); is a wrong approach, because the first parameter to splice() is an index, not an object. You should instead query indexOf() for that object, and if it's off the array already, you don't splice and don't call removeChild().
if (mc1) if (mc1.parent) // if mc1 is detached, why checking hit test?
if(mcBall.hitTestObject(mc1)){
removeChild(mc1);
myArray.splice(myArray.indexOf(mc1), 1) // at this point mc1 is still in array
trace(myArray.length);
// mc1 == null; this is wrong, unless you create a new mc1 at the start of the game
// and it should spell one equal sign, not two.
}
if (mc2) if (mc2.parent)
if(mcBall.hitTestObject(mc2)){
removeChild(mc2);
myArray.splice(myArray.indexOf(mc2), 1);
trace(myArray.length);
// mc2 == null;
}
Also such an approach defies the use of an array. Normally you don't query the individual MCs, but instead you iterate through the array and run hitTestObject against every item in the array. Like this:
for (var i:int=myArray.length-1;i>=0;i--) {
if (mcBall.hitTestObject(myArray[i])) {
removeChild(myArray[i]);
myArray.splice(i,1);
// that's all
}
}
if (myArray.length==0) { gotoAndPlay(1,"Menu"); }
Also, please get rid of "scenes", they are deprecated and can cause weird issues. Instead, use one scene and split it into frame sequences via timeline stop() calls.

Is it possible to get the label of the next frame in flash?

Had a look for this but nothing seemed clear at the moment I have a script which will only play if the frame is the currentFrameLabel or rewind.
However in order for it not to go one frame too far I need to be able to stop it on the frame before the change not on the change.
Or am I just going about this the wrong way?
For example:
Frame 10 Label: Up
Frame 12-36 Label: Idle Loop
Frame 37 Label: Hand Up
I need it to only play from frames 12 to 36 but at the moment it plays from frames 12-37.
var reverse:Boolean = false;
var robotlabel:String = 'Up/Down';
what.addEventListener(MouseEvent.MOUSE_OVER, botAction);
what.addEventListener(MouseEvent.MOUSE_OUT, botAction2);
function botAction(evt:MouseEvent):void{
reverse = false;
robotlabel = 'Hand up/Down';
robot.gotoAndPlay('Hand up/Down');
robot.addEventListener(Event.ENTER_FRAME,run);
}
function botAction2(evt:MouseEvent):void{
reverse = true;
robot.prevFrame();
}
function run(e:Event):void{
trace("label:" + robotlabel);
trace("current" + robot.currentFrameLabel);
if(robot.currentFrameLabel != robotlabel && robot.currentFrameLabel != null){
trace("stoooooppppp");
robot.stop();
}
if(reverse == true && currentFrameLabel==robotlabel){
robot.prevFrame();
trace("reversing!");
}else if(reverse == false && (currentFrameLabel==robotlabel || robot.currentFrameLabel == null)){
robot.nextFrame();
}else{
trace("destroy");
reverse = false;
robot.stop();
robot.removeEventListener(Event.ENTER_FRAME,run);
}
}
There is not a "nextFrameLabel" property as such in as3, however you can get an array of all the frame labels and numbers in your target movieclip using the currentLabel property of the MovieClip and work it out from there, since you know the currentFrame at all times.
Quick example from the docs:
import flash.display.FrameLabel;
var labels:Array = mc1.currentLabels;
for (var i:uint = 0; i < labels.length; i++)
{
var label:FrameLabel = labels[i];
trace("frame " + label.frame + ": " + label.name);
}
In case this is useful to anybody else I solved it by looping through each frame and then storing the corresponding label to the frame so it can later be checked against.
for (i = 1; i < robot.totalFrames; i++)
{
for (var n:uint = 0; n < this.robolabels.length; n++)
{
if(this.robolabels[n].frame == i){
newLabel = this.robolabels[n].name
}
}
this.roboframes[i] = newLabel;
}

How to remove/reload movieclip/graphic in Flash CS5 with AS3

I have a setupBoard(); and a setupBlocks(); in my function:
function init(e)
{
setupBoard();
removeEventListener(Event.ENTER_FRAME , init);
setupCat();
setupBlocks();
}
function setupBoard()
{
var columns:Array = new Array();
var i,j:int;
var _place:place;
for (i = 0; i < 11; i++)
{
columns = [];
for (j = 0; j < 11; j++)
{
_place = new place();
_place.thisX=i;
_place.thisY=j;
_place.thisDistance=Math.min(i+1,j+1,11-i,11-j)*11;
_place.y = 56 * i + 3;
_place.x = 5 + 71 * j + 35*(i%2);
_place.buttonMode=true;
_place.addEventListener(MouseEvent.CLICK, setBlock);
columns[j] = _place;
// SÆTTER TAL PÅ BRIKKERNE
_place.thisText.text = _place.thisDistance + " - " + _place.thisX + " : " + _place.thisY;
addChild(_place);
}
rows[i] = columns;
}
}
The "place" is the MovieClip
this function loads when the game launches and when the game is finish/completed..
the setupBoard, setup the board ofc, and the setupBlocks setup some movieclips, which contain some graphic.
Here's my question, how do I remove/reload all the blocks when the game enters that function again?
At the moment they are just placed upon each other, which I don't like at all.
If I understood correctly, what you want to do is remove all the previous blocks (from the last time you ran the setup function) when you run setup a second time.
To do that, you should create a function which loops your rows and columns Arrays, and for each Place object it find, it does the following: removes it from the stage, removes all Event Listeners, and finally sets it to null. Your function could look something like this (and you would call it just before calling setup again):
for (i = 0; i < rows.length; i++)
{
var column:Array = rows[i];
for (j = 0; j < column.length; j++)
{
var place:Place = column[j];
if (contains(place))
{
removeChild(place);
}
place.removeEventListener(MouseEvent.CLICK, setBlock);
place = null;
}
column = [];
}
row = [];
I just wrote that straight into the box, so it's not tested. But basically it does the three things necessary to get those objects removed from the view, and clears up anything that would stop them from being freed from memory by the garbage collector.
Hope that helps.
Debu