Touch scroll on Air for Android in Adobe Flash - actionscript-3

I'm trying to make a touch-based scrolling MovieClip with many buttons. I want that button to move according to the movieclip's mouseDown or mouseUp events. I hope someone can help me with this problem.
var maxY:Number = 725;
var minY:Number = 350;
var _startY:Number;
var _startMouseY:Number;
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler(event:MouseEvent):void {
_startY = davies.y;
_startY = toa.y;
_startMouseY = mouseY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler, false, 0, true);
}
function stage_mouseMoveHandler(event:MouseEvent):void {
var offsetY:Number = mouseY - _startMouseY;
background_scroll_product.y = Math.max(Math.min(maxY, _startY + offsetY), minY);
davies.y = Math.max(Math.min(maxY, _startY + offsetY), minY);
toa.y = Math.max(Math.min(maxY, _startY + offsetY), minY);
}
function stage_mouseUpHandler(event:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler);
stage.removeEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);
}
Before and after scroll :

Solution
1: Try replacing Math.max(Math.min(maxY, _startY + offsetY), minY); with the following:
clamp(mouseY - _startY + offsetY, minY, maxY);
function clamp(original:Number, low:Number, high:Number):Number {
return (original > high) ? high : (original < low) ? low : original;
}
2: Move all of your content into a single container. It's easier to move a one object, rather than moving many objects.
Many Objects:
0:MainTimeline
0:background_scroll_product //.y += offsetY;
1:davies //.y += offsetY;
2:toa //.y += offsetY;
...
One Object:
0:MainTimeline
0:container //.y += offsetY;
0:background_scroll_product
1:davies
2:toa
...
Demonstration
Below is code that you can drop into a new project and it will compile with a working scrolling container. Please be mindful that others will likely need a Minimal, Complete, and Verifiable example like this when you ask questions.
var background_scroll_product, davies, toa;
demoSetup();
/* ^^^ Omit this if you already have these objects defined ^^^ */
// Create a container for our content.
var container:Sprite = new Sprite();
addChild(container);
// Put the content inside the container.
container.addChild(background_scroll_product);
container.addChild(davies);
container.addChild(toa);
// setup the min based on the size of the contents.
var loc:Object = {
"max":50,
"min":stage.stageHeight - container.height
};
addEventListener("mouseDown", mouseHandler);
function mouseHandler(e:Event):void {
switch (e.type) {
case "mouseDown":
loc.start = mouseY;
loc.container = container.y;
addEventListener("mouseUp", mouseHandler);
addEventListener("mouseMove", mouseHandler);
break;
case "mouseUp":
removeEventListener("mouseUp", mouseHandler)
removeEventListener("mouseMove", mouseHandler);
break;
case "mouseMove":
// Scroll the container.
container.y = clamp(mouseY - loc.start + loc.container, loc.min, loc.max);
break;
}
}
function clamp(original:Number, low:Number, high:Number):Number {
return (original > high) ? high : (original < low) ? low : original;
}
function demoSetup():void {
// This sets up a facsimile of the project, to create a Minimal, and Verifiable example.
var bg:Sprite = new Sprite();
bg.graphics.beginFill(0xA1A1A1);
bg.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
bg.graphics.endFill();
addChild(bg);
background_scroll_product = new Shape();
background_scroll_product.graphics.beginFill(0xf0e3e5);
background_scroll_product.graphics.drawRect(0, 0, 250, 750);
background_scroll_product.graphics.endFill();
davies = new Shape();
davies.graphics.beginFill(0x243066);
davies.graphics.drawRect(0, 0, 200, 400);
davies.graphics.endFill();
davies.x = davies.y = 25;
toa = new Shape();
toa.graphics.beginFill(0xdc3734);
toa.graphics.drawRect(0, 0, 200, 200);
toa.graphics.endFill();
toa.x = 25;
toa.y = 525;
}
Response to FLA
I highly recommend you do not work with scenes, specifically because they create dirty states that are not imminently decipherable. In fact, as you appear to be working towards a mobile app, you should definitely consider using a full-fledge UI framework such as FeathersUI. Regardless...
Lingering Container
The Timeline tries to treat each frame as a unique state for the program. You can visually build a UI this way, but it is clunky. Furthermore, as you've discovered, when you mix WYSIWYG with functional programming, there are things that the Flash UI was never aware of and never "cleans up". You manually added addChild(container), and so you're also expected to manually removeChild(container). You could place that inside your listener function for the back button.
Container hovering over Titlebar
Consider your Main Menu heiarchy:
0: instance15 (Shape)
1: button_back (SimpleButton)
2: instance16 (StaticText)
3: container (Sprite)
As you can see, layers 0 through 2 are your top menu objects. Moving container behind the menu is as simple as calling addChildAt(), and setting the second argument to the 0 index.
addChildAt(container, 0);
Last Images are clipped
The reason for this is that your content is not positioned at y:0. If you want to fix that, either move the content to start at y:0, or add the offset of your first graphic to the min value...
"min":this.loaderInfo.height - container.height - davies.y

Related

AS3 multiple (movieclip buttons) to animate one movieclip

I am developing a desktop application. I am using ActionScript 3 via Adobe Animate CC. I designed the application, animated the GUI, and started coding. The main functions were successfully coded well, but I have added some additional features which are out of the scope of the application's original goals. All of this just to link the application to a website and some other information, which made me totally crazy because I've spent too much time with very simple if statement LOGIC!
Anyway, I created a menu with three MovieClip buttons. These menu button clicks affect one MovieClip that has a white background that moves with each click. I need there to be one background to show the beautiful effect of easeIn and easeOut animation tweens when clicking each button.
About clicked
Gallery clicked
Contact clicked
To make it easy to understand, I recreated the code with a very simple ball and 3 buttons. If you click first button, the ball moves to the right above the 2nd button. Then the first button should be unclickable, unless another button is clicked. If the second button is clicked, then the ball would move to the right above the third button. Then the second button should be unclickable also, unless another button is clicked. The same thing goes for the third button.
Now, if the first button is clicked again, the animation of the white background should not start from the default position when starting up the application!
It should animated back from its current position to the default position... and so on...
I replaced the white background with a ball for simplicity
This is very easy but I lost it with the eventListeners, eventHandlers, and if statements! :/
I also made this table which studies the cases:
I know my coding technique is not smart enough, but that is because I HATE using classes, packages, project folders... etc..
Even if the code runs too long & repeats, It would be better for me for simplicity, as programming is not my day-job!
Please, any help and quick response would be highly appreciated!
Code:
import flash.ui.Mouse;
import flash.events.MouseEvent;
one.addEventListener(MouseEvent.CLICK, moveToSecondPos);
two.addEventListener(MouseEvent.CLICK, moveToThirdPos);
//three.addEventListener(MouseEvent.CLICK, moveToFirstPos);
var buttonState:Boolean;
one.buttonState = 0;
two.buttonState = 0;
//three.buttonState = 0;
function moveToSecondPos(event:MouseEvent){
if(one.buttonState == 0){
theBall.gotoAndPlay("go1");
one.buttonState = 1;
}
else if(two.buttonState == 1){
theBall.gotoAndPlay("backToOne");
// two.buttonState = 0;
// one.buttonState = 1;
}
else{
//disable About Button
one.removeEventListener(MouseEvent.CLICK, moveToSecondPos);
}
}
function moveToThirdPos(event:MouseEvent){
if((two.buttonState == 0)&&(one.buttonState == 0)){
theBall.gotoAndPlay("goProducts");
two.buttonState = 1;
}
else if(one.buttonState == 1){
theBall.gotoAndPlay("go2");
// two.buttonState = 1;
// one.buttonState = 1;
}
else{
two.removeEventListener(MouseEvent.CLICK, moveToThirdPos);
}
}
//function moveToFirstPos(event:MouseEvent){
// if(three.buttonState == 0){
// theBall.gotoAndPlay("go3");
// three.buttonState = 1;
// }
// else{
// three.removeEventListener(MouseEvent.CLICK, moveToFirstPos);
// }
//}
First, you mentioned you wanted to have the
white background should not start from the default position when starting up the application
For that, you'll need a ShareObject or comparable method of saving and loading data.
Secondly, It appears you may be trying to do some of this with Scenes and Timeline' frames. I highly encourage you not to pursue that.
Below is a solution to the problems you mentioned. Notice that without your project, I had to recreate the scene. You can copy & paste the solution into a new scene and it will compile.
To prevent buttons from being clicked, you can remove the event listener by calling myButton.removeEventListener("click"). Alternatively, you can simply stop the object from responding to mouse events by setting its mouseEnabled property to false.
To animate the box smoothly, you can use the built-in Tween class. Alternatively, I'd direct you Greensock's TweenLite.
Because you appeared to want a series of labels to appear depending on the button clicked, I created an array which stores data specific to each button (btns:Array). By using an organized structure, it's easier to write re-useable code which doesn't depend on explicit functions. Note that there's only one btnListener() function which works for all of your buttons.
Solution
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import fl.motion.Color;
import fl.transitions.*;
import fl.transitions.easing.*;
// the list of buttons we want, along with the descriptions for each
var btns:Object = [
{
"label":"About",
"desc":"Learn more about us",
"btn":null
},
{
"label":"Gallery",
"desc":"See our photos",
"btn":null
},
{
"label":"Contact",
"desc":"Write, call, or message",
"btn":null
}
];
var nav:Sprite; // our navigation bar of buttons
var whiteBox:Sprite; // the "ball" with the content text
// where we save the coordinates of the whiteBox between loads
var settings:Object = SharedObject.getLocal("foo");
init();
function init():void {
// Create our navigation of three buttons
// our container for buttons
nav = new Sprite();
// reference to the last button
var last:Sprite = null;
// loop through the list of buttons
for each (var entry:Object in btns) {
// For each button, create a new button
var btn:Sprite = createButton(entry.label);
entry.btn = btn;
nav.addChild(btn);
// If there was a previous button, place this beside it.
if (last != null) {
btn.x = last.x + last.width + 1;
}
last = btn;
}
// Place the nav onscreen
addChild(nav);
nav.x = stage.stageWidth/2 - nav.width/2;
nav.y = stage.stageHeight - nav.height*2;
// Create the whitebox
whiteBox = new Sprite();
whiteBox.graphics.beginFill(0xFAFAFA);
whiteBox.graphics.drawRect(0, 0, 150, 50);
whiteBox.graphics.endFill();
var txt:TextField = new TextField();
txt.name = "txt";
txt.width = 150;
whiteBox.addChild(txt);
nav.addChild(whiteBox);
// Load the settings from the last run of the program.
if (settings.data.hasOwnProperty("x")) {
whiteBox.x = settings.data.x;
whiteBox.y = settings.data.y;
}
}
function createButton(label:String):Sprite {
// Creates a simple button
// Create the label
var txt:TextField = new TextField();
txt.text = label;
// Create the background
var btn:Sprite = new Sprite();
btn.graphics.beginFill(0xA1A1A1);
btn.graphics.drawRect(0, 0, txt.width + 60, txt.height + 30);
btn.graphics.endFill();
btn.addChild(txt);
btn.name = label;
txt.x = 30;
txt.y = 15;
// Hookup events
btn.addEventListener("mouseOver", btnListener);
btn.addEventListener("mouseOut", btnListener);
btn.addEventListener("click", btnListener);
return btn;
}
function btnListener(e:Event):void {
var btn:Sprite = e.currentTarget as Sprite;
var c:Color = new Color();
var entry:Object;
// Find our button in the list.
for each (entry in btns) {
if (entry.label == btn.name) {
break;
}
}
switch (e.type) {
case "mouseOver":
if (btn.mouseEnabled) {
c.setTint(0x0096ff, 0.5);
btn.transform.colorTransform = c;
}
break;
case "mouseOut":
if (btn.mouseEnabled) {
c.setTint(0x00, 0);
btn.transform.colorTransform = c;
}
break;
case "click":
// Set the text, and position of our whitebox
whiteBox.getChildAt(0)["text"] = entry.desc;
whiteBox.y = -whiteBox.height;
var tween:Tween = new Tween(whiteBox, "x", Regular.easeOut, whiteBox.x, btn.x, 0.35, true);
tween.addEventListener("motionFinish", saveState);
for each (var v:Object in btns) {
if (v.btn == btn) {
// make our button unclickable
btn.mouseEnabled = false;
c.setTint(0xFFFFFF, 0.5);
btn.transform.colorTransform = c;
} else {
// Make the other buttons clickable;
v.btn.mouseEnabled = true;
c.setTint(0x00, 0);
v.btn.transform.colorTransform = c;
}
}
break;
}
}
function saveState(e:Event):void {
settings.data.x = whiteBox.x;
settings.data.y = whiteBox.y;
settings.flush();
}

Adding object within another

I have my main stage as 550x400. The header area is a stats bar. So I have an element underneath it which I named gameStage which is 550x350.
I am creating circles on a 1 second interval and then trying to randomly place them within my gameStage. It does not appear to be working. It seems like they're being added to a 550x350 element, but it starts at the top of my main stage -- not within my gameStage.
Also if I simply do addChild(circle) it creates an even 25 radius circle. As soon as I do gameStage.addChild(circle), the circle gets skewed slightly.
What am I doing wrong?
private function createCircle():void {
var stageSafeX:Number = Math.random()*gameStage.width;
var stageSafeY:Number = Math.random()*gameStage.height;
var circle:Sprite = new Sprite();
circle.graphics.clear();
circle.graphics.beginFill(Math.random()*0xFFFFFF, 1);
circle.graphics.drawCircle(0, 0, circleRadius);
circle.graphics.endFill();
circle.x = stageSafeX;
circle.y = stageSafeY;
circle.name = String(circleCount);
gameStage.addChild(circle);
}
Okay I'm using Flash Develop, so you'll have to forgive me as this program doesn't have FLA files, only classes and it uses a Main class to start the program (more reminiscent of Java if you've ever programmed in that). But the code I'll show you is more or less the same of how you want to do it.
First I would recommend you make a randomNumber function, I used it in making this code so if you want to use it here's the one I use (I put this in the Main class, you can put this wherever you want):
public static function randomNumber(minValue:Number, maxValue:Number):uint {
return Math.floor(Math.random() * (1 + maxValue - minValue)) + minValue;
}
This is inclusive, meaning if you put randomNumber(1, 10) it will give you a number between 1 to 10, including 1 and 10. It's more or less common sense, but I figured I might as well mention it just to clarify.
Now on to the addCircle function:
public static function addCircle(gameStage:Sprite, circleRadius:uint):void {
//Initializing the new circle instance
var newCircle:Sprite = new Sprite();
//Basically the same code you had (you don't need to set the alpha value to 1, it's default value is 1 regardless)
newCircle.graphics.beginFill(Math.random() * 0xFFFFFF);
newCircle.graphics.drawCircle(0, 0, circleRadius);
newCircle.graphics.endFill();
//Since the circle's origin is the center, you want its outer edges to be bound to the gameStage's edges
var safeStageX:Number = Main.randomNumber(newCircle.width / 2, gameStage.width - newCircle.width / 2);
var safeStageY:Number = Main.randomNumber(newCircle.height / 2, gameStage.height - newCircle.height / 2);
//Adding the circle to the gameStage's display field
gameStage.addChild(newCircle);
//Only set the circle's x and y AFTER you add it to the gameStage's display list, otherwise it might not set properly
newCircle.x = safeStageX;
newCircle.y = safeStageY;
}
Now following up I will give the code I made for the creation of the gameStage. You probably already have something for it, but I'll provide mine just in case you want to use it instead:
//Initializing the gameStage instance
var gameStage:Sprite = new Sprite();
//Adding the gameStage to the Stage's display field
this.stage.addChild(gameStage);
//Setting the gameStage's width and height (using "gameStage.width = 550" and "gameStage.height = 350" WILL NOT WORK)
//Use the color of your main game's background so you don't see this fill (unless you want to)
//Either do this or add a background picture, you need to do one or the other in order to set the gameStage's dimensions
gameStage.graphics.beginFill(0x000000);
gameStage.graphics.drawRect(0, 0, 550, 350);
gameStage.graphics.endFill();
//This puts the gameStage on the bottom of the screen (since it's 50 pixels shorter in the y direction)
gameStage.y = 50;
Lastly I will give you the actual for loop to create your circles (this function is present in the same class/FLA that your gameStage is on, because the addCircle function needs to take in that gameStage instance:
//Now let's populate your gameStage
for (var i:uint = 0; i < [number of circles you want]; i++) {
Main.addCircle(gameStage, [radius of the circle]);
}
And you're done! I'll also include the entire Main class, just so you can see how all the functions work together.
package {
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite {
public function Main() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var gameStage:Sprite = new Sprite();
this.stage.addChild(gameStage);
gameStage.graphics.beginFill(0x000000);
gameStage.graphics.drawRect(0, 0, 550, 350);
gameStage.graphics.endFill();
gameStage.y = 50;
for (var i:uint = 0; i < 150; i++) {
Main.addCircle(gameStage, Main.randomNumber(15, 25));
}
}
public static function addCircle(gameStage:Sprite, circleRadius:uint):void {
var newCircle:Sprite = new Sprite();
newCircle.graphics.beginFill(Math.random() * 0xFFFFFF);
newCircle.graphics.drawCircle(0, 0, circleRadius);
newCircle.graphics.endFill();
var safeStageX:Number = Main.randomNumber(newCircle.width / 2, gameStage.width - newCircle.width / 2);
var safeStageY:Number = Main.randomNumber(newCircle.height / 2, gameStage.height - newCircle.height / 2);
gameStage.addChild(newCircle);
newCircle.x = safeStageX;
newCircle.y = safeStageY;
}
public static function randomNumber(minValue:Number, maxValue:Number):uint {
return Math.floor(Math.random() * (1 + maxValue - minValue)) + minValue;
}
}
}

AS3 return dropped object to initial location

I am using codes from http://hub.tutsplus.com/tutorials/create-a-drag-and-drop-puzzle-in-actionscript-30--active-2920 to make a drag and drop decoration game. I am trying to make it so that when the dropped object is dragged out of target location (which is an outline of the shape in my case), it goes back to initial location... basically reversing the drag and drop. I've been messing around with really random codes and so far this line is the closest to what I want but I don't think the code is right and also it doesnt return to initial location, it just goes to the side of the stage.
so, I added the else if line to stopDragObject which got the object to be removed from target location, but it randomly goes to the side of the stage, and not initial location:
private function stopDragObject(evt:MouseEvent):void {
if (evt.target.hitTestObject(getChildByName(evt.target.name + "Target"))) {
evt.target.x = getChildByName(evt.target.name + "Target").x;
evt.target.y = getChildByName(evt.target.name + "Target").y;
} else if (evt.target.x = null) {
evt.target.x = xPos;
evt.target.y = yPos;
}
evt.target.stopDrag();
}
Solved
after reading the lesson from below, I ended up with this and it works perfectly! (not exactly the way like the lesson but at least it works...)
private function stopDragObject(evt:MouseEvent):void {
if (evt.target.hitTestObject(getChildByName(evt.target.name + "Target"))) {
evt.target.x = getChildByName(evt.target.name + "Target").x;
evt.target.y = getChildByName(evt.target.name + "Target").y;
} else {
evt.target.x = getChildByName(evt.target.name + "Int").x;
evt.target.y = getChildByName(evt.target.name + "Int").y;
}
evt.target.stopDrag();
}
I added a initial object so the object could only be either at target or initial :)
I will try to teach neither provide code.
Lets draw two rectangles:
var s1:Sprite = new Sprite()
var s2:Sprite = new Sprite()
with (s1)
{
graphics.beginFill(0xfcaaaa, .7)
graphics.drawRect(0, 0, 400, 400)
graphics.endFill()
}
with (s2)
{
graphics.beginFill(0x00aaaa, .7)
graphics.drawRect(0, 0, 30, 30)
graphics.endFill()
}
addChild(s1)
addChild(s2)
Is't that simple? You see that s1 is much bigger than s2 (dimentions: 400, 400 vs 30, 30 ) Now place s2 to the center of our big s1:
s2.x = 200;
s2.y = 200;
We will use s1 for the boundaries of s2 movings.
This code is a simplest solution for dragging our s2 rectangle (Sprite):
s2.addEventListener(MouseEvent.MOUSE_DOWN, onDown)
s2.addEventListener(MouseEvent.MOUSE_UP, onUp)
function onDown(e:MouseEvent):void
{
(e.currentTarget as Sprite).startDrag();
}
function onUp(e:MouseEvent):void
{
(e.currentTarget as Sprite).stopDrag();
}
Now, the basic solution for returning our Sprite to the starting position: hitTestObject will return true, if Sprite s2 is still located in the area of Sprite s1. More helpful functions here. Lets check it. Change onUp function this way:
function onUp(e:MouseEvent):void
{
var s:Sprite = (e.currentTarget as Sprite);
s.stopDrag();
if (!s.hitTestObject(s1))
{
s.x = 200;
s.y = 200;
}
}
You see that now s2 gets returned to the starting position if it gets dragged out from the area of s1.
Now the main part:
What to do, if you can't predict the starting position of the object? Now, when we know how to deal with already known coordinates, this is the challange. I assume that there are several implementations of this functionality exist. One of the best way is to set additional parameters e.g. startingX and startingY for the dragging object when starting drag. E.g. in our example when onDown function gets called. I guess you dealing with Sprites or MovieClips and don't have the ability to do this.
Lets go another way and use Dictionary object. Dictionary is some kind of traditional Hash Map with the ability to use objects as keys.
Hash map is kind of storage, where you can put any value mapped by a key, provided by you. In actionscript 3 we have Object as a limited implementation of Hash Map. Why use it? In two words because it's simple and fast. But with Object we can't use other Objects as keys, only strings ints numbers etc..
var sites:Object = new Object();
sites['stackoverflow'] = "http://stackoverflow.com/"
trace(sites.stackoverflow) // outputs-> http://stackoverflow.com/
With Dictionary we can use Objects as keys.
Lets create it:
var startCoordinates:Dictionary = new Dictionary();
To save coordinates, we need x and y property.
FYI: new Object() is equivalent of {}
var capitals:Object = new Object();
capitals['Italy'] = 'Rome';
is equivalent of
var capitals:Object = {Italy: 'Rome'};
To save current position we will use this code:
var s:Sprite = (e.currentTarget as Sprite);
startCoordinates[s] = { x: s.x, y: s.y };
And the whole code in our example will look like this:
var s1:Sprite = new Sprite()
var s2:Sprite = new Sprite()
addChild(s1)
addChild(s2)
with (s1)
{
graphics.beginFill(0xfcaaaa, .7)
graphics.drawRect(0, 0, 400, 400)
graphics.endFill()
}
with (s2)
{
graphics.beginFill(0x00aaaa, .7)
graphics.drawRect(0, 0, 30, 30)
graphics.endFill()
}
s2.x = 200;
s2.y = 200;
s2.addEventListener(MouseEvent.MOUSE_DOWN, onDown)
s2.addEventListener(MouseEvent.MOUSE_UP, onUp)
var startCoordinates:Dictionary = new Dictionary()
function onDown(e:MouseEvent):void
{
var s:Sprite = (e.currentTarget as Sprite);
startCoordinates[s] = { x: s.x, y: s.y };
s.startDrag();
}
function onUp(e:MouseEvent):void
{
var s:Sprite = (e.currentTarget as Sprite);
s.stopDrag();
if (!s.hitTestObject(s1))
{
s.x = startCoordinates[s].x;
s.y = startCoordinates[s].y;
}
delete startCoordinates[s];
}

over drawn the circle when input angle in actionscript?

var theTextField:TextField = new TextField();
var theText:TextField = new TextField();
theTextField.type = TextFieldType.INPUT;
theTextField.border = true;
theTextField.x = 50;
theTextField.y = 10;
theTextField.height = 20;
theTextField.multiline = true;
theTextField.wordWrap = true;
theText.border = false;
theText.x = 10;
theText.y = 10;
theText.text = "Angle";
addChild(theText);
addChild(theTextField);
submit.addEventListener(MouseEvent.CLICK, click_handler);
function click_handler(event:MouseEvent):void
{
var txt:String = theTextField.text;
ang = Number(txt);
if (ang<0)
{
angle = - ang;
}
else
{
angle = 360 - ang;
}
var circleSlider:CircleSlider=new CircleSlider(120,angle); //draw Circle According to the angle i think here is problem becoz every time clicked it creates new circle and draw over the old circle.
circleSlider.x = stage.stageWidth / 2;
circleSlider.y = stage.stageHeight / 2;
circleSlider.addEventListener(CircleSliderEvent.CHANGE, circleSliderEventHandler);
addChild(circleSlider);
}
Can someone help me.
var circleSlider:CircleSlider=new CircleSlider(120,angle);//draw Circle According to the angle i think here is problem becoz every time clicked it creates new circle and draw over the old circle.
this code is the problem. CircleSlider is a separate class.I tried like this
circleSlider.CircleSlider(120,angle);
but it gives an error "" Call to a possibly undefined method CircleSlider through a reference with static type CircleSlider.""
when i run the program and input value as 90.
then i enter another value as 180 then it becomes
how can i overcome this error
Every time your click handler is executed you're creating a new instance of your circle class and adding it to the stage without removing the old instance. I think the best way to resolve it would be to move the logic you have in the constructor of your CircleSlider class into a separate public method, say draw and call that in the click handler.
Your code would look something like this:
// Set up the circle once
var circleSlider = new CircleSlider();
circleSlider.x = stage.stageWidth / 2;
circleSlider.y = stage.stageHeight / 2;
circleSlider.addEventListener(CircleSliderEvent.CHANGE, circleSliderEventHandler);
// and add it to the stage once
addChild(circleSlider);
function click_handler(event:MouseEvent):void
{
var txt:String = theTextField.text;
ang = Number(txt);
if (ang<0)
{
angle = - ang;
}
else
{
angle = 360 - ang;
}
// Now simply redraw in the same circle instance
circleSlider.draw(120,angle); //draw Circle According to the angle i think here is problem becoz every time clicked it creates new circle and draw over the old circle.
}
Assuming you're using the drawing API to draw the graphic, you could draw the circle (which seems to be constant) in the constructor (once) and the line illustrating the angle in the draw method (repeatedly). You'll need to clear the old line each time like this:
// Assumes you're drawing in the graphics property of the class
this.graphics.clear();

AS3 : Scaling Sprite with Matrix on slider change?

I have a sprite that holds a bitmap data.
I want to give the user the ability to resize the image with a slider.
I am using the code beneath, as you can see the problem is that the scaling is additive so very quickly the image is gone totally.
I understand that i have to scale it in non additive way, just can not figure out how?
I tried to pass :
var m:Matrix = userImageCopy.transform.matrix;
when userImageCopy holds the original image. that helped for the scaling but then, each time the scaling started the userImage jumped to the position of the userImageCopy.
Any help?
function onSliderChange(evt:Event):void
{
trace( evt.target.value);
//this will create a point object at the center of the display object
var ptRotationPoint:Point = new Point(userImage.x + userImage.width / 2,userImage.y + userImage.height / 2);
//call the function and pass in the object to be rotated, the amount to scale X and Y (sx, sy), and the point object we created
scaleFromCenter(userImage, evt.target.value, evt.target.value, ptRotationPoint);
}
private function scaleFromCenter(ob:*, sx:Number, sy:Number, ptScalePoint:Point)
{
var m:Matrix = userImage.transform.matrix;
m.tx -= ptScalePoint.x;
m.ty -= ptScalePoint.y;
m.scale(sx, sy);
m.tx += ptScalePoint.x;
m.ty += ptScalePoint.y;
ob.transform.matrix = m;
}
Rather than combining your center values with the current tx and ty, just set them directly with the Matrix.translate method:
private function scaleFromCenter(ob:*, sx:Number, sy:Number, ptScalePoint:Point)
{
var m:Matrix = new Matrix();
m.translate(-ptScalePoint.x,-ptScalePoint.y);
m.scale(sx, sy);
m.translate(ptScalePoint.x,ptScalePoint.y);
ob.transform.matrix = m;
}