Actionscript 3.0: Error #1006: value is not a function - actionscript-3

I am a beginner at ActionSccript 3.0. I made this code which works fine but when I put an amount over 150 grams, i get an error in the output that says Error #1006: value is not a function Please Help. Mind telling giving me the correct code? Thank you
//import controls
import fl.controls.RadioButtonGroup;
import flash.events.MouseEvent;
import fl.controls.RadioButton;
// This line makes the button, btnCalculate wait for a mouse click
// When the button is clicked, the determineCost function is called
btnCalculate.addEventListener(MouseEvent.CLICK, determineCost);
// These lines make the textinput and the radioButtons wait for a mouse click
// When these components are clicked, the clearLabels function is called
txtinMass.addEventListener(MouseEvent.CLICK, clearLabels);
// This is the determineCost function
// e:MouseEvent is the click event experienced by the button
// void indicates that the function does not return a value
function determineCost(e:MouseEvent):void
{
// declare the variables
var Mass:uint;
var Letter:RadioButtonGroup = new RadioButtonGroup("Letters");
// put the groups together
FirstRadio.group = Letter;
SecondRadio.group = Letter;
// get the mass from the user
Mass = uint(txtinMass.text);
// determine the cost
if (Mass <= 30 && Letter.selection.label == "First Class")
{
lblCost.text = "0.38";
}
else if (Mass <= 30 && Letter.selection.label == "Second Class")
{
lblCost.text = "0.28";
}
else if (Mass > 30 && Mass <= 50 && Letter.selection.label == "First Class")
{
lblCost.text = "0.55";
}
else if (Mass > 30 && Mass <= 50 && Letter.selection.label == "Second Class")
{
lblCost.text = "0.40";
}
else if (Mass > 50 && Mass <= 100 && Letter.selection.label == "First Class")
{
lblCost.text = "0.73";
}
else if (Mass > 50 && Mass <= 100 && Letter.selection.label == "Second Class")
{
lblCost.text = "0.55";
}
else if (Mass >= 150 && Letter.selection.label == "First Class")
{
lblCost = ((0.73 + 0.24 * Math.floor((Mass - 100) / 50)))();
}
else if (Mass >= 150 && Letter.selection.label == "Second Class")
{
lblCost = ((0.55 + 0.19 * Math.floor((Mass - 100) / 50)))();
}
}
// This is the clearLabels function
// e:MouseEvent is the click event experienced by the textInput and the radioButtons
// void indicates that the function does not return a value
function clearLabels(e:MouseEvent):void
{
lblCost.text = "";
txtinMass.text = "";
}
I'm pretty sure the error is in my last 2 else if statement. I'm trying to make the answer of the equations appear when i put a mass over 150 grams.

The problem is in the lines with (); at the ending.
Try to not add the "()" at the end, since you are not running a function.
Try something like this :
lblCost = (( 0.55 + 0.19 * Math.floor((Mass - 100) / 50) ));

Related

How to make if chains

I am making a game for my assignment in AS3.0 and this isn't working.
All the variables and buttons are defined, I get no error but it just dose not function :
frame 2 layer 1
function CheckScene():void
{
P_HP = 5
E_HP = 1
A_D = 1
if(P_HP == 5)
if(E_HP == 2)
if(A_D == 1)
q = 1
if(P_HP == 5)
if(E_HP == 1)
if(A_D == 1)
q = 2
}
frame 2 layer 2
stop();
but.addEventListener(MouseEvent.CLICK, fl_ClickToGoToAndStopAtFrame);
function fl_ClickToGoToAndStopAtFrame(event:MouseEvent):void
{
gotoAndStop(5);
}
frame 3 layer 2
button_2.addEventListener(MouseEvent.CLICK, fl_ClickToGoToAndStopAtFrame_2);
function fl_ClickToGoToAndStopAtFrame_2(event:MouseEvent):void
{
if(q == 1)
gotoAndStop(5)
if(q == 2)
gotoAndStop(4)
}
Basically it goes to frame 4 if it works, or 5 if it doesn't. The if chain isn't working. I have no clue how to do this because this sort of thing works in excel (for checking multiple variables before execution).
See comments for help and explanation:
//use naming conventions : methods start with lower-case.
//fix method signature
private void checkScene()
{
//declare all variables
//use naming conventions : variables start with lower-case.
int p_HP = 5; // ; at the end of every statement
int e_HP = 1;
int a_D = 1;
int q = 0;
if(p_HP == 5) {
if(e_HP == 2) {
if(a_D == 1) {
q = 1;
}
}
}
//you could use an equivalent and shorter format:
//if( p_HP==5 && e_HP==2 && a_D==1) q=1;
if(p_HP == 5) {
if(e_HP == 1) {
if(a_D == 1) {
q = 2;
}
}
}
//you could use an equivalent and shorter format:
// if( p_HP==5 && e_HP==1 && a_D==1) q=2;
//add printout to check the result
System.out.println("q is "+q);
}
For future questions pleas post an MCVE

ActionScript 3 Scoring/Math

I've been attempting to implement a score inside of a game that I'm creating in AS3. So far, I've managed to create a score system that adds/subtracts points based on actions in-game. I've decided that it'd be simpler to have the scoring system just add points instead of subtract them and on reaching a certain number, end the game.
The problem I'm having is that on the one hand, the game is performing checks to see if the pieces are in the right place. If they are, the player wins. On the other, the counter needs to count and reach a certain number (10) before deciding the player loses. At the moment there's some weird behaviour going on where I'm able to drag the pieces around without putting them in their right place and the counter still goes over 10. I've tried a few variations of changing the math so that it totals differently, but the functionality is the same. What would I have to change so that it would behave as first described?
stop();
//Create the score counter
import flash.text.TextField;
var score = 0;
scorecounter.text = score;
function init(): void
{
score = 0;
scorecounter.text = "SCORE:" + score.toString();
}
function updateScore(): void
{
scorecounter.text = ++score;
}
function evaluateScore(): void //this is meant to stop the score going below 0
{
scorecounter.text = --score;
if(score < 0) {
score -= score;
}
}
/*Omitted some functions and var's for object positions and events*/
function stopDragging(e:MouseEvent):void {
e.currentTarget.stopDrag();
switch (e.currentTarget){
case apple:
if (apple.x < appleEndX - offset || apple.x > appleEndX + offset ||
apple.y < appleEndY - offset || apple.y > appleEndY + offset) {
apple.x = appleStartX;
apple.y = appleStartY;
soundOne();
updateScore();
} else {
apple.x = appleEndX;
apple.y = appleEndY;
soundTwo();
updateScore();
checkGame();
}
break;
//Lots of other cases, using the same method
//The end of the game - here, I've been trying to set it to
//check whether the player will win or lose
}
}
function checkGame(): void {
if (apple.x == appleEndX && apple.y == appleEndY && pear.x == pearEndX &&
pear.y == pearEndY && guava.x == guavaEndX && guava.y == guavaEndY &&
pineapple.x == pineappleEndX && pineapple.y == pineappleEndY &&
plum.x == plumEndX && plum.y == plumEndY &&
purple.x == purpleEndX && purple.y == purpleEndY)
{
trace("You win!");
gotoAndStop(149);
soundFive();
} else if (score == 10) {
gotoAndStop(150);
soundSix();
trace("You lose.");
}
}
I think that the logic is a little confusing, but as I understand it from your code, the idea is to move a drag-gable item to the correct x,y position, with a tolerance of "offset"? The aim is to to this with the lowest possible "score" (or number of moves) and if the number of moves (score) is greater than 10 then you lose the game?
Currently the only place that checks to see if you have made 10 moves is "checkGame" and this method is only called if your "apple" is correctly positioned. If it is incorrectly positioned then the number of moves is incremented, but the score is not checked. So when you finally get to "checkGame" but correctly positioning the "apple" the score could already be greater than 10. So your "score == 10" check will fail also.
So what you need is to check the game on every move with something like this:
function stopDragging(e:MouseEvent):void {
...
switch (e.currentTarget){
case apple:
if (apple.x < appleEndX - offset || apple.x > appleEndX + offset ||
apple.y < appleEndY - offset || apple.y > appleEndY + offset) {
apple.x = appleStartX;
apple.y = appleStartY;
soundOne();
} else {
apple.x = appleEndX;
apple.y = appleEndY;
soundTwo();
}
break;
...
}
//Check the game on every turn.
checkGame();
}
function checkGame(){
//Update the score
score++;
if (apple.x == appleEndX && apple.y == appleEndY && pear.x == pearEndX &&
pear.y == pearEndY && guava.x == guavaEndX && guava.y == guavaEndY &&
pineapple.x == pineappleEndX && pineapple.y == pineappleEndY &&
plum.x == plumEndX && plum.y == plumEndY &&
purple.x == purpleEndX && purple.y == purpleEndY)
{
//Do the game win.
}
else if (score>=10)
{
//Else if you have a score greater then or equal to 10 do the game lose.
}
}

Flash AS3 - Timer goes crazy after a few loops

I've been making a "slideshow" where 4 images are animated in random order.
To prevent multiple animations to one image for example 3 times successively, I've write a little logic.
My problem : after a few times all the 4 images are animated (after the query 'array' is cleared the second time I think), the timer goes crazy and trace() random numbers in a high sequence rate without to animate the images, with would look creepy I think.
My code :
var myTimer:Timer = new Timer(2500);
myTimer.addEventListener(TimerEvent.TIMER, animate);
myTimer.start();
var array:Array = new Array();
var lastNum:int;
function animate(e:TimerEvent):void {
var num:int = getRandomNumber( 1, 4 );
trace( num );
if( array.indexOf( num ) < 0 && num != lastNum ) {
myTimer.delay = 2500;
if( num == 1 ) {
sideImg_start_1.play(); // comment this*
} else if( num == 2 ) {
sideImg_start_2.play(); // comment this*
} else if( num == 3 ) {
sideImg_start_3.play(); // comment this*
} else if( num == 4 ) {
sideImg_start_4.play(); // comment this*
}
array.push( num );
if( array.length == 4 ) {
array.splice(0, 4);
trace(" array cleared - " + array.length);
lastNum = num;
}
} else {
myTimer.delay = 100; // I've also tryed so make a higher delay
// like 500 but its the same problem...
}
}
function getRandomNumber( min:int, max:int ):int {
return Math.floor( Math.random() * ( 1 + max - min ) ) + min;
}
stop();
So guys, thanks for all your answers and your help :D
UPDATE:
First I've tried to simply call the 'animate()' function instead of defining a higher speed to the timer to call the next number fast, without to loose time, which would make the random animation look weird.
I've used animate(null); instead of myTimer.delay = 100; before, but then I was getting a STACKOVERFLOW error :P
For example if your lastNum is equal to 4, and you have 1,2 and 3 as new values, than you will end up with an infinite loop,
because you can't insert 4 (because it's equal to the lastNum) and you can't insert 1,2 or 3 because they are already in the array.
What you need to do is:
if (array.length == 4) {
array.splice(0, 4);
lastNum = num;
} else {
lastNum = 0; //<-- HERE
}

AS3: Large number of timers lagging flash

I have a large number of objects (472) that require a timer used to check how long it takes between state changes of a variable. The code below is what I have so far but that many timers running definitely impacts the performance of the application, is there a better optimised way of measuring this?
import flash.utils.Timer;
var active_:Boolean;
var matched:Boolean;
var vacated:Boolean;
var circ:Shape=new Shape();
this.addChild(circ);
circ.x = 0;
circ.y = 0;
var circRad:Number = 5;
var mat= new Matrix();
var busyColors = [0xFFFF00,0xFFCC00];
var idleColors = [0xCCCCCC,0x000000];
var matchedColors = [0x0099FF,0x0066FF];
var vacatedColors = [0xFF0000,0x990000];
var busyAlphas = [1,1];
var idleAlphas = [0.5,0.5];
var ratios = [0,255];
var prev:int = 0;
var time:Timer = new Timer(1000,0);
//time.start();
mat.createGradientBox(2*circRad,2*circRad,0,-circRad,-circRad);
circ.graphics.lineStyle();
if (active_ == false)
{
if (prev != 0)
{
setAverage(prev,false);
prev = 0;
}
circ.graphics.clear();
circ.graphics.beginGradientFill(GradientType.RADIAL,idleColors,idleAlphas,ratios,mat);
circ.graphics.drawCircle(0,0,circRad);
circ.graphics.endFill();
}
else if (active_ == true && matched == true)
{
if (prev != 1)
{
setAverage(prev,true);
prev = 1;
}
circ.graphics.clear();
circ.graphics.beginGradientFill(GradientType.RADIAL,matchedColors,busyAlphas,ratios,mat);
circ.graphics.drawCircle(0,0,circRad);
circ.graphics.endFill();
}
else if (active_ == true && vacated == false && matched == false)
{
if (prev != 2)
{
setAverage(prev,true);
prev = 2;
}
circ.graphics.clear();
circ.graphics.beginGradientFill(GradientType.RADIAL,busyColors,busyAlphas,ratios,mat);
circ.graphics.drawCircle(0,0,circRad);
circ.graphics.endFill();
}
else if (active_ == true && vacated == true)
{
if (prev != 3)
{
setAverage(prev,true);
prev = 3;
}
circ.graphics.clear();
circ.graphics.beginGradientFill(GradientType.RADIAL,vacatedColors,busyAlphas,ratios,mat);
circ.graphics.drawCircle(0,0,circRad);
circ.graphics.endFill();
}
function setAverage(i:int, a:Boolean)
{
time.stop();
switch (i)
{
case 0 :
break;
case 1 :
MovieClip(root).avgMat.push(uint(time.currentCount));
break;
case 2 :
MovieClip(root).avgBusy.push(uint(time.currentCount));
break;
case 3 :
MovieClip(root).avgVac.push(uint(time.currentCount));
break;
}
if(a == true){
//time.reset();
//time.start();
}
}
Commented out the timer starts because of the issue.
You can make public function like "tick()" at yours objects and call it in loop from 1 general timer outside.
Consider doing the following:
in the top, import getTimer
import flash.utils.Timer;
Create a variable containing the starting time (instead of doing timer.start) do this:
var timerStart : int = getTimer();
and instead of doing this: time.currentCount
Simply do this:
(getTimer() - timerStart) / 1000
Good luck.
you could change all the timers with addEventListener of type EVENT FRAME
var counter:Number = 0;
addEventListener(Event.ENTER_FRAME, counting);
function counting (e:Event):void
{
counter++
}
So counter will increment on every frame. Now you have to find fps. Now multiply fps by time that you want timer to run after. So it's should look like this:
var counter:Number = 0;
addEventListener(Event.ENTER_FRAME, counting);
function counting (e:Event):void
{
counter++
if(counter == 60) //60 fps means this line will run after 1 sec.
{
//do something
}
If(counter == 120) //60 fps; 2 sec
{
//do something
}
}
This method is much more accurate and the system will not be so overloaded. This can especcially help you for setting up the stage using addChild, when you need a delay after the animation is started.
You can make more of this 'timers', but that depends on the demands of the game, but i'm sure that it will work faster than hundreths of timers.

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;
}