ActionScript 3.0 Exponent Calculator - actionscript-3

If a user enters a base = 3 and an exponent = 4, your program should be able to use a loop to calculate powers as follows: i know I have to use power=Math.pow(baseIn, exponentIn) but other then that im very lost.. learning this my self since im the only person taking the class
Example:
31 = 3
32 = 9
33 = 27
34 = 81
![enter image description here][1]
tip: power=Math.pow(baseIn, exponentIn);
http://i.stack.imgur.com/EUkdx.png

To use a loop to calculate you would do this.
function powerCalc(base:Number, power:Number):Number
{
var result:Number = 1;
for (var i:int = 0; i < power; i++)
{
result = result * base;
}
return result;
}
Then you can call:
var power = powerCalc(3,4);

Related

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

Improve function speed that uses remainder:

Please have a look at this piece of code:
public static function getCharLocationById(id:int):Point {
var lx:int = id % 16;
var ly:int = id / 16;
return new Point(lx, ly);
}
It works perfectly but is very slow. Does anyone know of a way to make it much faster?
Thanks in advance!
If you create the objects beforehand for all possibilities, all you have to do is look them up in an array (with the id as index).
private static const _locationLookUpTable:Array = []; //or Vector, if you like
// fill the array somewhere, maybe like this
for (var i:uint = 0; i <= maximumId; ++i) _locationLookUpTable.push(i % 16, i / 16);
public static function getCharLocationById(id:int):Point {
return _locationLookUpTable[id];
}
If the number of ids is not limited or very large you can employ an object pool.
This requires a little more code as you should return the objects to the pool if they are not used any more.
Ignore the variable creations, only takes time to create, assign and then again read them to submit them to the Point constructor.
public static function getCharLocationById(id:int):Point
{
return new Point(id % 16, id / 16);
}
Also, considering that your input is an integer, you can use bitshifts for the division by 16 like this:
id = id >> 1; // div. by 2 = id/2
id = id >> 1; // div. by 2 = id/2/2 = id/4
id = id >> 1; // div. by 2 = id/2/2/2 = id/8
id = id >> 1; // div. by 2 = id/2/2/2/2 = id/16
Shortening that we get
id = id >> 4; // (1+1+1+1 = 4)
Keep in mind that the result will also be an integer, so 11 >> 1 will return 5 and not 5.5.

Action Script 3. How to add multiple children of 1 instance?

I'm creating flash game. I need to make player lives - heart images. If player have 5 lives should be added 5 hearts <3 <3 <3 <3 <3. I have image with instance name heart. How to add them correctly?
I've tried this:
var lives:Number = 4;
var currentHP = lives;
var heart:Heart = new Heart();
var hpArr:Array = new Array();
function hp() {
for (var i=0; i<lives; i++) {
heart = new Heart();
hpArr[i] = heart;
hpArr.push(heart);
heart.x += heart.width+20;
addChild(heart);
}
trace("Array length" + hpArr.length);
}
This correctly return 5 trace("Array length" + hpArr.length);, so that means hearts successfully added to array. Problem is that only 1 heart is added. What can be problem?
Change your for loop like this:
for (var i=0; i<lives; i++) {
heart = new Heart();
hpArr.push(heart);
heart.x = ( heart.width + 20 ) * i; // here is the trick!
addChild(heart);
}

Converting alpha percent to RGBA hex in AS3?

Say I have the following setup in my AS code:
var color:String = "#0000FF"; //blue
var alpha:Number = 42; //42% or 42/100
How would I combine those into a #RRGGBBAA hex color? I've been Googling around and trying to figure out hexadecimal conversion and notation without luck.
There are two ways you could do this.
One is a bit hacky using int's toString() method and passing 16 as the radix/base:
var rgb:int = (int)("#0000FF".replace("#","0x"));//convert the string to a int (note you can type hex ints starting with 0x (e.g. 0x0000FF)
var a:int = 42;
var rgba:int = int("0x"+rgb.toString(16) + a.toString(16));
or the less hacky and probably faster computationally method using bitwise operators:
var rgb:uint = (uint)("#0000FF".replace("#","0x"));
//extract components using bit shifting (>>) and masking (0xFF)
var r:uint = rgb >> 16 & 0xFF;
var g:uint = rgb >> 8 & 0xFF;
var b:uint = rgb >> 0 & 0xFF;//same as rgb >> 0xFF, just added >> 0 to make the shift obvious
var a:uint = 42;
var rgba:uint = r << 24 | g << 16 | b << 8 | a;
var argb:uint = a << 24 | r << 16 | g << 8 | b;
//test
trace(rgba.toString(16));
trace(argb.toString(16));
Note that using toString(16) in the trace above is to make it useful to us humans,
you'd use the actual uint value when working with hex color values.
Also note that you might want to use ARGB in as3 sometimes, for example when working with BitmapData:
addChild(new BitmapData(100,100,true,0x2a0000ff));//add a 42% transparent blue box (100x100 px)
UPDATE
The above bitshift code snippet actually explains rgb extraction in detail which helps understand things better, but you already have rgb, so it's a matter of adding the alpha component. Also you mentioned 42% which is not the same as on a 0 to 255 scale. Therefore bellow lies your answer:
var rgb:uint = (uint)("#0000FF".replace("#","0x"));
var a:uint = (uint)((42 * .01) * 255);//map 42 from 0<>100 to 0<>255 ( *.01 is the same as / 100 but faster
var rgba:uint = rgb << 8 | a;
var argb:uint = a << 24 | rgb;
Regarding speed, if I run the two different conversion methods a million times here are execution times:
using strings (var rgba:int = int("0x"+rgb.toString(16) + a.toString(16));) takes 851 ms
using bitwise ops (var rgba:uint = rgb << 8| a;) takes 3 ms
As you can the bitwise version is much faster and for your case even less verbose than the string version. Also, now that you understand bitwise operators probably it's easier to read/understand.
In conclusion:
var color:String = "#0000FF"; //blue
var alpha:Number = 42; //42% or 42/100
var rgb:uint = (uint)(color.replace("#","0x"));
var a:uint = (uint)((alpha * .01) * 255);
var rgba:uint = rgb << 8 | a;
trace("hex: #",rgba.toString(16),"test",0x0000ff6b.toString(16));
Also, it's funny you mentioned Google, because you can use the search to convert to hex.
Update:
There seems to be a bit of confusion so I've split the 3 steps into functions:
converting a hex string to an int
converting a alpha percentage (0-100) to a 0-255 int
concatenating the above
Which would be:
function getHex(hexStr:String):uint{
return (uint)(hexStr.replace("#","0x"));
}
function getHexAlpha(alpha:uint):uint{
return (uint)((alpha * .01) * 255);
}
function rgbaConcat(rgb:uint,a:uint):uint{
return rgb << 8 | a;
}
trace("test",rgbaConcat(getHex("#FF9900"),getHexAlpha(50)).toString(16));
or all in one go:
function rgbaConcat(hexStr:String,alpha:uint):uint{
var rgb:uint = (uint)(hexStr.replace("#","0x"));
var a:uint = (uint)((alpha * .01) * 255);
return (rgb << 8 | a);
}
trace("test",rgbaConcat("#123456",100).toString(16));
I'm not sure if sprintf or something similar is available in action script, but you would use something like:
var alpha_2:int = Math.round(255*alpha/100);
var rgba:String = sprintf("%s%2x", color, alpha_2);
By the way, be sure to check whether it is supposed to be #RRGGBBAA or #AARRGGBB
So apparently sprintf is not available, you can use some substitute as mentioned in Is there something like printf in Action Script 3?
If you do not like to use a printf like function you can use:
function hex_char(value:int) {
if (value < 0)
return "X";
if (value < 10)
return String.fromCharCode("0".charCodeAt(0)+value);
if (value < 16)
return String.fromCharCode("A".charCodeAt(0)+value-10);
return "X";
}
var alpha_2:int = Math.round(255*alpha/100);
var rgba:String = color + hex_char(alpha_2/16) + hex_char(alpha_2%16);
alternatively you coulde use the following definition for hex_char which (I assume) will give you an exception/error for any value under 0 or over 15 instead of "X"
function hex_char(value:int) {
return "0123456789ABCDEF".charAt(value);
}

Trouble creating a spectrogram

I know it was asked a thousand times before, but I still can't find a solution.
Searching SO, I indeed found the algorithm for it, but lacking the mathematical knowledge required to truly understand it, I am helplessly lost!
To start with the beginning, my goal is to compute an entire spectrogram and save it to an image in order to use it for a visualizer.
I tried using Sound.computeSpectrum, but this requires to play the sound and wait for it to end, I want to compute the spectrogram in a way shorter time than that will require to listen all the song. And I have 2 hours long mp3s.
What I am doing now is to read the bytes from a Sound object, the separate into two Vectors(.); Then using a timer, at each 100 ms I call a function (step1) where I have the implementation of the algorithm, as follows:
for each vector (each for a channel) I apply the hann function to the elements;
for each vector I nullify the imaginary part (I have a secondary vector for that)
for each vector I apply FFT
for each vector I find the magnitude for the first N / 2 elements
for each vector I convert squared magnitude to dB scale
end.
But I get only negative values, and only 30 percent of the results might be useful (in the way that the rest are identical)
I will post the code for only one channel to get rid off the "for each vector" part.
private var N:Number = 512;
private function step1() : void
{
var xReLeft:Vector.<Number> = new Vector.<Number>(N);
var xImLeft:Vector.<Number> = new Vector.<Number>(N);
var leftA:Vector.<Number> = new Vector.<Number>(N);
// getting sample range
leftA = this.channels.left.slice(step * N, step * (N) + (N));
if (leftA.length < N)
{
stepper.removeEventListener(TimerEvent.TIMER, getFreq100ms);
return;
}
else if (leftA.length == 0)
{
stepper.removeEventListener(TimerEvent.TIMER, getFreq100ms);
return;
}
var i:int;
// hann window function init
m_win = new Vector.<Number>(N);
for ( var i:int = 0; i < N; i++ )
m_win[i] = (4.0 / N) * 0.5 * (1 - Math.cos(2 * Math.PI * i / N));
// applying hann window function
for ( i = 0; i < N; i++ )
{
xReLeft[i] = m_win[i]*leftA[i];
//xReRight[i] = m_win[i]*rightA[i];
}
// nullify the imaginary part
for ( i = 0; i < N; i++ )
{
xImLeft[i] = 0.0;
//xImRight[i] = 0.0;
}
var magnitutel:Vector.<Number> = new Vector.<Number>(N);
fftl.run( xReLeft, xImLeft );
current = xReLeft;
currf = xImLeft;
for ( i = 0; i < N / 2; i++ )
{
var re:Number = xReLeft[i];
var im:Number = xImLeft[i];
magnitutel[i] = Math.sqrt(re * re + im * im);
}
const SCALE:Number = 20 / Math.LN10;
var l:uint = this.total.length;
for ( i = 0; i < N / 2; i++ )
{
magnitutel[i] = SCALE * Math.log( magnitutel[i] + Number.MIN_VALUE );
}
var bufferl:Vector.<Number> = new Vector.<Number>();
for (i = 0; i < N / 2 ; i++)
{
bufferl[i] = magnitutel[i];
}
var complete:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
complete[0] = bufferl;
this.total[step] = complete;
this.step++;
}
This function is executed in the event dispatched by the timer (stepper).
Obviously I do something wrong, as I said I have only negative values and further more values range between 1 and 7000 (at least).
I want to thank you in advance for any help.
With respect,
Paul
Negative dB values are OK. Just add a constant (representing your volume control) until the number of points you want to color become positive. The remaining values that stay negative are usually just displayed or colored as black in a spectrogram. No matter how negative (as they might just be the FFT's numerical noise, which can be a huge negative dB number or even NaN or -Inf for log(0)).