Control timeline with pinchzoom in Actionscript 3.0 - actionscript-3

I'm using Actionscript 3.0 in Flash. Is there a way to control the timeline with pinching (so instead of zooming out/in you are moving the timeline back/forth)? I'm working on an story app where the player is in control of the story.

You could do something like the following:
import flash.events.TransformGestureEvent;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stop();
//listen on whatever object you want to be able zoom on
stage.addEventListener(TransformGestureEvent.GESTURE_ZOOM , zoomGestureHandler);
function zoomGestureHandler(e:TransformGestureEvent):void{
//get the zoom amount (since the last event fired)
//we average the two dimensions (x/y). 1 would mean no change, .5 would be half the size as before, 2 would twice the size etc.
var scaleAmount:Number = (e.scaleX + e.scaleY) * 0.5;
//set the value (how many frames) to skip ahead/back
//we want the value to be at least 1, so we use Math.max - which returns whichever value is hight
//we need a whole number, so we use Math.round to round the value of scaleAmount
//I'm multiplying scaleAmount by 1.25 to make the output potentially go a bit higher, tweak that until you get a good feel.
var val:int = Math.max(1, Math.round(scaleAmount * 1.25));
//determine if the zoom is actually backwards (smaller than before)
if(scaleAmount < 1){
val *= -1; //times the value by -1 to make it a negative number
}
//now assign val to the actual target frame
val = this.currentFrame + val;
//check if the target frame is out of range (less than 0 or more than the total)
if(val < 1) val = this.totalFrames + val; //if less than one, add (the negative number) to the totalFrames value to loop backwards
if(val > this.totalFrames) val = val - this.totalFrames; //if more than total, loop back to the start by the difference
//OR
if(val < 1) val = 0; //hard stop at the first frame (don't loop)
if(val > this.totalFrames) val = this.totalFrames; //hard stop at the last frame (don't loop)
//now move the playhead to the desired frame
gotoAndStop(val);
}

Related

actionscript 3 - random object selection

So I want a unit to be able to randomly target a player unit or a players allies.
I have all ally ships stored in an array and the player is on the stage separately.
Here is the code for the bullet creation, with the irrelevant stuff removed.
private function createBullet(): void {
var rand = allies[Math.floor(Math.random()*allies.length)];
_endX = rand.x
_endY = rand.y
}
With the code above I can make them target random ally ships, but I also want it to include the player ship (_player) when randomly selecting a target, but I cant add the player to the ally array so Im not really sure what to do.
When you multiply a random number by length of array, add plus one to length.
If generated index is equal to the allies length, this means that "rand" is _player.
var randomIndex:int = Math.floor(Math.random() * (allies.length + 1));
var rand:*;
if (randomIndex == allies.length - 1)
rand = _player;
else
rand = allies[randomIndex];
...

ActionScript 3 stage width

Im doing my first flash AS game, so need a little help.
I have only 1 thing on the stage, its ball (layer instance) which has anchor point in the middle. I'm trying to make this ball bounce off walls (i mean screen).
This instance name is called 'kugla1'
Heres my code (its second frame):
if(kugla1.x<=kugla1.width/2 || kugla1.x>=stage.stageWidth-kugla1.width/2)
speedX=-speedX;
if(kugla1.y<=kugla1.height/2 || kugla1.height>=stage.stageHeight-kugla1.height/2)
speedY=-speedY;
kugla1.x+=speedX;
kugla1.y+=speedY;
First frame is:
var speedX:int=5;
var speedY:int=5;
kugla1.x=100;
kugla1.y=100;
And third frame is only:
gotoAndPlay(2);
what am I doing wrong?
Thanks!
Your problem, is likely this line:
if(kugla1.y<=kugla1.height/2 || kugla1.height>=stage.stageHeight-kugla1.height/2)
In the second part (after the ||) you are comparing the height of kugla1 instead of the y position.
Another issue you could run into, is your ball could potentially meet the same condition for longer than one frame, so it would be best to separate your speed from the current direction of movement.
See code comments:
On your first frame, you'll need two additional variables:
var speedX:int=5;
var speedY:int=5;
var curSpeedX:Number = speedX;
var curSpeedY:Number = speedY;
on your second frame:
if(kugla1.x <= kugla1.width/2){
curSpeedX = speedX; //we need the positive value to make it go right
}
if(kugla1.x >= stage.stageWidth - kugla1.width/2){
curSpeedX = -speedX; //we need the negative value to make it go left
}
if(kugla1.y <= kugla1.height/2){
curSpeedY = speedY; //we need the positive value to make it go down
}
if(kugla1.y >= stage.stageHeight - kugla1.height/2){
curSpeedY = -speedY; //we need the negative value to make it go up
}
kugla1.x+= curSpeedX;
kugla1.y+= curSpeedY;

AS3 Psuedo 3D Z-Indexing

I am attempting to make a really basic Pseudo 3D game in AS3. When I press certain keys my character moves up and down but what I want to happen is when the characters y position is above an objects y position then the character should appear behind the object.
Here is my code for an objects class at the moment:
package {
import flash.display.MovieClip;
import flash.utils.getTimer
import flash.events.Event;
public class bushMC extends MovieClip {
private var lastFrame:int = new int(0);
private var dt:Number = new Number();
private var main:Main;
public function bushMC(){
main = this.parent as Main;
stage.addEventListener(Event.ENTER_FRAME, update);
trace(main.getChildIndex(this));
}
private function update(e:Event):void{
dt = (getTimer() - lastFrame)/30;
lastFrame = getTimer();
if(main.char.y + 200 < this.y + 55 && main.getChildIndex(main.char) > main.getChildIndex(this)){
main.setChildIndex(this, main.getChildIndex(main.char)+1);
}
else if(main.getChildIndex(main.char) < main.getChildIndex(this)){
main.setChildIndex(this, main.getChildIndex(main.char));
}
}
}
}
I have tried editing loads of the values(+1, -1, equal to) for each calculation but I can't seem to find the right ones. One I tried almost works but instead when the char is supposed to be behind the object it simply flickers in-front and then behind continuously.
Thanks in advance, Kyle.
I just tried a little quick mock script based off your code. I got it working how I assume you are attempting to get it to work:
import flash.events.Event;
import flash.display.MovieClip;
var char:MovieClip = new MovieClip();
var bush:MovieClip = new MovieClip();
char.graphics.beginFill(0xFF0000);
char.graphics.drawCircle(0, 0, 30);
bush.graphics.beginFill(0x00FF00);
bush.graphics.drawEllipse(0, 0, 40, 80);
this.addChild(char);
this.addChild(bush);
bush.x = 100+(Math.random()*350);
bush.y = 100+(Math.random()*200);
this.addEventListener(Event.ENTER_FRAME, updateYPos);
function updateYPos(e:Event):void {
char.x = mouseX;
char.y = mouseY;
if(char.y < bush.y + 30 && this.getChildIndex(char) >= this.getChildIndex(bush)){
this.setChildIndex(bush, this.getChildIndex(char));
}
else if(char.y > bush.y + 30 && this.getChildIndex(char) < this.getChildIndex(bush)){
this.setChildIndex(bush, this.getChildIndex(char));
}
}
I hope this sample is enough to help you. All it needed was an extra condition on the else if and it works. :)
You should have a sorted list of bushes somewhere, which is then added via addChild() in the right order - uppermost bush has lowermost Z-position (child index 0 or the least of bushes, there could be other objects). Then, as your player moves, you track its position relative to list of bushes, so you don't run the full list check for z-ordering of player, but only check "nearest" bushes for possible change, then you set child index of player to found value. Note that if you're setting child index of player to bush's index, if you are moving player forwards (greater indexes), set to -1, as the bush will actually be one position lower because of player occupying a position in the display list, and if you are setting child index to lower values, set to equal. There is a more elegant version of this, using the fact that your bushes are continuous within display list, with only interruption being player, although it will run out of steam once more moving objects will appear.
And yes, you run update on the player or any other moving objects, not on the bush.
function updateZPos(e:Event):void {
// process coordinates change
var p:DisplayObjectContainer=this.parent;
// a bit faster to use function local var to get parent
var ci:int=p.getChildIndex(this); // changeable, get current index
var prev:DisplayObject=null;
if(ci>0) prev=p.getChildAt(ci-1);
var next:DisplayObject=null;
if(ci<p.numChildren-1) next=p.getChildAt(ci+1);
while(prev) {
if (this.y<prev.y) {
ci--;
p.setChildIndex(this,ci);
if (ci>0) prev=p.getChildAt(ci-1); else prev=null;
} else break;
while(next) {
if (this.y>next.y) {
ci++;
p.setChildIndex(this,ci);
if(ci<p.numChildren-1) next=p.getChildAt(ci+1); else next=null;
} else break;
}
}
This function was written with implication of display list of p being pre-sorted, and will maintain sorted state of it after moving of this, and is suitable for any moving object, not just the player. For this to work without messing up your other objects, separate everything moving into one container which will then get referenced as base for sorting display list. Otherwise your player might eventually get above all as the last element to check will be say score textfield with Y of 0. Also you will need to maintain coherent position of register point all over your set of moving objects' classes, so that say the base of a bush will be at Y=0 instead of being at Y=30, as implied in your code. The legs of a player should then also be at Y=0.

AS 3 simple ease

How can I move an object and be able to physically see it when it is moving? Not just disappear and appear on a different location like it would be using the following code.
buttonL2_btn.addEventListener(MouseEvent.CLICK, left);
function left(event:Event):void{
box_mc.x =241.5;
}
This is going to move myObject to any location specified, but again I want to be able to see it when moving.
In your example you are just setting it's X position when some button is pressed, when you need to change X into an EnterFrame event, like this:
this.addEventListener(Event.ENTER_FRAME, move);
function move(event:Event):void{
box_mc.x -= 5
}
Your box_mc should move left 5 pixels accordingly with your framerate.
You can use a easing library to that easily. I strongly recommend TweenMax.
Okay I am getting a bit sick of people constantly suggesting some tweening engine. Sure they rock, but it won't help the OP to understand what he is doing.
Kircho to move an object with a really easy tween I suggest the following code in an onEnterFrame event for your object to move:
addEventListener(Event.ENTER_FRAME, onEnterFrame);
var xGoal:Number = 100; //:: The target X destination for your object
var yGoal:Number = 100; //:: The target Y destination for your object
var smothness:Number = 10; //:: Smoothness factor for movement. The lower the value the faster the movement.
function onEnterFrame(e:Event):void
{
box_mc.x += (xGoal - box_mc.x) / smothness;
box_mc.y += (yGoal - box_mc.y) / smothness;
}
Will move/ease your box object to the desired location with a set smoothness.
You can install any of the 437 available tweening engines
or you can add a few lines of code
set up a variable that holds the destination value
var dest:Number = 241.5; // this is what gets updated on mouse click
on enterframe event for box:
function onBoxEnterFrame(e:MouseEvent):void{
if (dest != box_mc.x){
var easeNum:Number = 0.4 // between 0 and 1, the higher the number, the slower the transition
box_mc.x = box_mc.x * easeNum + dest * (1-easeNum);
}
}
you can add a few more lines to snap the position when it is close (less than 0.1 difference) or use a more linear change where you adjust incrementally like box_mc.x += 5; until it matches the dest number

How to display the highest value from a random created list of numbers in AS3

I m building kind of a game in Flash (AS3) where sound input (microphone) trigger a equalizer (the micLevel.height controls the height of a mask (showing the equalizer). The activityLevel of the microphone gives me a number ( 0 - 100 ) wich is displayed in textfield prosent. The contestant shout in the microphone and try to reach 100 ( I use the mc.gain to make it hard to reach 100 ). So far so good! I m pretty new to AS3 so I feel kind of lost.
I need to display the highest number they manage to reach and I want to have a time limit on this. The highest sound level in lets say 5 seconds.
Here is the code so far:
var mic:Microphone = Microphone.getMicrophone();
Security.showSettings("privacy");
mic.setLoopBack(true);
if(mic != null)
{
mic.setUseEchoSuppression(true);
stage.addEventListener(Event.ENTER_FRAME, showLevel);
}
function showLevel(e:Event)
{
micLevel.height = mic.activityLevel * 6;
//mic.gain = 1;
//trace(mic.activityLevel);
prosent.text = "Activity: " + String(mic.activityLevel) + "%";
}
I just need some code that grab the highest number from the text field "prosent" (with a time limit) and display it in a new text field.
Im sorry if I m unclear, but if anyone could help me out I would be very happy!
Br Harald
Just create a variable that will be updated whenever the micLevel.height value is higher than it, e.g.
var highest:Number = 0;
function showLevel(e:Event):void
{
if(micLevel.height > highest)
{
// The mic level was higher than the previous highest level.
highest = micLevel.height;
// Change your other text field to show the value of 'highest'.
// ..
}
prosent.text = "Activity: " + String(mic.activityLevel) + "%";
}
Start a Timer to reset your highestLevel var. This will show you then the highest level every 5 seconds. You could add a timer start-stop button too if you wanted to keep one highest always showing.
Then in your showLevel function, use Math.max() to get the highest number (between current activity and recent highest)
var highestLevel:Number = 0;
var timer:Timer = new Timer(5000); // fires every 5 seconds
function initLevels(e:TimerEvent){
timer.stop(); // you could stop your timer here automatically and then use a button to start again
highestLevel = 0; // when timer fires restart your highestLevels var
}
function showLevel(e:Event) {
highestLevel = Math.max(mic.activityLevel * 6, highestLevel);
prosent.text = "Activity: " + String(highestLevel) + "%";
}
timer.start();
timer.addEventListener(TimerEvent.TIMER, initLevels);
addEventListener(Event.ENTER_FRAME, showLevel);