I recently started programming in as3, and lately, I've started to learn object oriented programming. My problem is to access functions within a class. I guess that the "main" code is not very suitable for doing so, but I'm pretty much just asking for advice for every part of the code.
Main Code:
import flash.utils.Timer;
import flash.events.TimerEvent;
stage.addEventListener(MouseEvent.CLICK, makeCircle);
function makeCircle(event:MouseEvent):void
{
var s = new Circle();
addChild(s);
s.x = mouseX;
s.y = mouseY;
}
Class code (connected to a MovieClip circle with a MovieClip fill inside):
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.filters.BlurFilter;
import flash.geom.ColorTransform;
public class Circle extends MovieClip
{
private var t:Timer = new Timer(30,1000);
var time:Number = 0;
var size:Number;
var bf = new BlurFilter();
var ct:ColorTransform = new ColorTransform();
public function Circle()
{
// constructor code
t.addEventListener(TimerEvent.TIMER, updateCircle);
t.start();
ct.color = 0xffffff * Math.random();
fill.transform.colorTransform = ct;
fill.blendMode = "hardlight";
}
public function updateCircle(event:TimerEvent):void
{
time = t.currentCount / 10;
size = Math.pow(Math.E, - time) * Math.sin(5 * time) * (Math.log(time));
width = (size * 20 + 100 - time * 5) * 2;
height = (size * 20 + 100 - time * 5) * 2;
bf.blurX = time;
bf.blurY = time;
filters = [bf];
alpha = 1 - time / 20;
}
}
}
What I want to do is to remove the child of s (main code) when the t.currentCount (class code) is a set value (when the alpha value is 0).
Thanks in advance.
whay you want to do is do create either an even inside the Circle class that triggers when your timer completes (alpha == 0). The custom event would have to be caught in your main class.
To put a custom event listener in your main class write:
s.addEventListener("RemoveChild", removeChild)
add the handler function
function removeChild(e:Event)
{
removeChild(s);
}
in your circle class you can add the event when you want to trigger it:
this.dispatchEvent(new Event("RemoveChild");
Alternatively you control the Alpha value from your main class by placing the loop there and call removeChild(s); directly.
An easy way to get your custom events working is by using the AS3Signals framework.
Hope that helps
Related
import flash.display.MovieClip;
import flash.events.Event;
public class rainfall extends MovieClip {
public function rainfall() {
// rainfall
var i:int;
for (i = 0; i< 50; i++)
{
//variables
var mc:MovieClip = new MovieClip ();
//theStage, and alpha properties
mc.x = Math.random() * stage.stageWidth ;
mc.y = Math.random() * 400 * 4 ;
mc.alpha = Math.random()* 2;
mc.graphics.beginFill(0x0000FF);
mc.graphics.drawCircle(0,0,20);
//trace
trace(i);
addChild(mc);
mc.addEventListener(Event.ENTER_FRAME, moveDown) ;
}
function moveDown(e:Event):void
{ //fall speed
e.target.y += 1 ;
}
}
having a lot of trouble trying to figure out how to get the circles to repeat down the screen in a continueous loop, I'm fairly new to actionscript 3 but any tips on what im doing wrong or what I need to get it to loop threw
Try something like this:
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.DisplayObject;
import flash.events.Event;
package{
public class Rainfall extends Sprite {//class names should be title case
private var numDrops = 50;//this make it easier to configure
private var dropRadius = 20;
private var maxY;
public function Rainfall() {
addEventListener(Event.ADDED_TO_STAGE,init);//make sure the stage property will not be null
}
private function init(event:Event):void{
maxY = stage.stageHeight;//getters can be slow, store the height so it can be reused for each drop reset
var i:int;
for (i = 0; i < numDrops; i++){
var mc:Shape = new Shape();//if no interactivity is needed, Shape is the simplest/lightest class to use for drawing
mc.x = Math.random() * stage.stageWidth ;
mc.y = Math.random() * 400 * 4 ;
mc.alpha = 0.1 + Math.random() * 0.9;//alpha values are from 0 to 1.
mc.graphics.beginFill(0x0000FF);
mc.graphics.drawCircle(0,0,dropRadius);
addChild(mc);
}
addEventListener(Event.ENTER_FRAME, moveDown) ;
}
private function moveDown(e:Event):void
{ //fall speed
for(var i:int = 0 ; i < numDrops; i++){
var drop:DisplayObject = getChildAt(i);
drop.y += 1 ;
if(drop.y > maxY) drop.y = -dropRadius;//if the drop exits the screen downards, place it back at the top (above the visible area)
}
}
}
}
It's not tested code, so you might run into syntax errors, but the ideas are commented:
You need to use a conditional for your problem: if the drop's vertical position is greater than the stage's height, then the drop's vertical position should reset back to the top of the stage(`if(drop.y > maxY) drop.y = -dropRadius;a)
Although not necessary if you're just getting started, here are a few tips on efficiency/speed when working in flash:
MovieClip is a dynamic class (you can add properties to instances on the fly) but also has a cost. Since you only need to render/draw elements and no events or children are needed, this makes your circles perfect candidates for using the Shape class. Also, your main class can be a Sprite since you're not using a timeline
Getters and setters can be a bit slow in actionscript. It's a healthy habbit to cache/store values that don't change much over time for reuse as local variables for faster access.
Not as much a performance issue:a common pitfall is not having the stage initialized on a display object, resulting in an annoying and for beginners puzzling null object reference errors. If you use the stage property on a DisplayObject(Shape/Sprite/MovieClip), it's best to make sure it's been added to the stage (and the stage property isn't null) using the ADDED_TO_STAGE event
Good luck!
In the code below, I have created 4 sprites (picn) inside a sprite (noteholder). How can I get the absolute values of the picn instances that I create? I know about the localToGlobal function, but I can't figure out how to use that in this case. At this point, I think I need the container because I need to be able to move the sprites after creation. Any help is greatly appreciated. Thanks!
package
{
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import Main;
public class Notes extends Sprite
{
private var speed:int = 14;
[Embed(source="../lib/Dodgethis.jpg")]
private var picn:Class;
private var noteholder:Sprite = new Sprite();
public function appear() {
trace ("appear ran")
var arr1:Array = new Array;
var numnotes:Number = 4;
Main.StageRef.addChild(noteholder);
trace (noteholder.x, noteholder.y);
for (var i = 0; i < numnotes; i++)
{
//trace (i);
var nbm:Bitmap = new picn;
noteholder.addChild(nbm);
nbm.y = i * 50;
arr1.push(nbm);
You need to hold a reference to the display objects you dynamically create — you don't need a "name" which is just an abstraction of instance variables when creating visual assets in the Flash IDE.
I've updated your code to demonstrate the concept:
package
{
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.Stage; // added this
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle; // added this (see below)
import Main;
public class Notes extends Sprite
{
private var speed:int = 14;
[Embed(source="../lib/Dodgethis.jpg")]
private var NoteBMP:Class;
private var display:Sprite = new Sprite();
private var notes:Array = []; // make notes an instance variable, so it's accessible throughout the class
// I renamed appear to 'build' because I'm a pedantic moron
public function build():void
{
trace ("build ran");
var noteCount:int = 4;
Main.StageRef.addChild(display);
for (var i:int = 0; i < noteCount; i++)
{
var nbm:Bitmap = new NoteBMP;
display.addChild(nbm);
nbm.y = i * 50;
notes.push(nbm); // by adding the display objects to an array you can reference them later
then at some later point in the Notes class you can reference your bitmaps by looping through the notes array
// initialize variables outside the loop
var localPos:Point
var globalPos:Point;
var bounds:Rectangle;
var n:DisplayObject;
var stage:Stage = Main.StageRef;
for (var i:int = 0; i < notes.length; i++)
{
trace( 'note' + i );
n = notes[i] as DisplayObject; // cast during assignment since array items have ambiguous type
// getBounds() returns a Rectangle representing the bounding box of the display object
bounds = n.getBounds(stage);
trace(
'getBounds:',
bounds.top, bounds.left, bounds.bottom, bounds.right
);
// localToGlobal() returns a Point which is just the position
localPos = new Point( n.x, n.y );
globalPos = display.localToGlobal(localPos)
trace(
'localToGlobal:',
globalPos.x, globalPos.y
);
}
A few points:
I refactored some names to make the intention more clear
I wonder why your Notes class extends Sprite, since it adds display (what you called "noteholder") to the stage. Assuming that's correct just make Notes a generic object i.e. doesn't seem to need to extend another class.
You can use getBounds about getBounds
// call this after added to stage
if (stage) {
var r:Rectangle = nbm.getBounds(stage);// r's x and y is the global pos
}
And I think localToGlobal should work in your case. Move the sprites don't have effect on localToGlobal
I have a confetti generator that I am tyring to add to a single movie clip within my flash file. The clip is masked and I want to have some graphics and text appear above the confetti (which will be above a background layer as well).
I purchased a decent script and have modified it to work with some original confetti artwork but I can't figure out how to use this class (or change it for use) in just the one movie clip. Pasting the class below. I've been stressing about this for a couple of hours now, any help would be greatly appreciated.
package com.pixeljunkyard
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import caurina.transitions.*;
import fl.motion.Color;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
public class Main extends Sprite
{
//Create Heart Instance
private var hearts:Heart;
//Amount of hearts
private var totalHearts:Number = 30;
//Falling Speed
private var speed:Number = 1.5;
//Constructor
public function Main()
{
//Align top left for screen aspect ratio
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
//Loop through the amount of heart to be created
for (var i = 0; i < totalHearts; i++)
{
//Create new heart
var heart = new Heart();
//Set Random value
var randScale:Number = randRange(50, 100);
var randRotation:Number = randRange( -180, 180);
var randRotationY:Number = randRange( -360, 360);
//Random position and scale
heart.x = randRange(0, stage.stageWidth);
heart.y = randRange( -stage.stageHeight, stage.stageHeight);
heart.scaleX = randScale/100;
heart.scaleY = randScale/100;
//Name each heart with the number of creation
heart.name = "heart" + i;
var Low : int = 1;
var High : int = 8;
var myRandomNumber:int = Math.floor(Math.random()*(1+High-Low))+Low;
heart.gotoAndStop(myRandomNumber);
//Add eventlisteners for interactions
heart.addEventListener(MouseEvent.ROLL_OVER, hit_heart);
heart.addEventListener(Event.ENTER_FRAME, change_shade);
//Initial Animation
Tweener.addTween(heart, {time:randRange(1,5)/speed, rotation:randRotation,rotationY:randRotationY,y:stage.stageHeight+(heart.height/2)+20, transition:"linear", onComplete:rebirth,onCompleteParams:[heart]} );
//Add to Stage
addChildAt(heart, i);
}
}
//Change shade to give lighting effect
private function change_shade(e:Event):void
{
//New color instance
var c:Color = new Color();
//Set properties
c.brightness = e.target.rotation / 300;
//Apply color to heart
e.target.transform.colorTransform = c;
}
//Random Function
private function randRange(min:Number, max:Number):Number
{
var randomNum:Number = Math.floor(Math.random() * (max - min + 1)) + min;
return randomNum;
}
//Interactive animation
private function hit_heart(e:Event):void
{
Tweener.addTween(e.target, { time:randRange(1,3), rotationY:e.target.rotationY+180 } );
}
//Reset heart to top of the screen once fallen
private function rebirth($heart:Heart):void
{
$heart.x = randRange(0, stage.stageWidth);
$heart.y = -$heart.height;
Tweener.addTween($heart, {time:randRange(1,5)/speed, rotation:randRange(-180,180),y:stage.stageHeight+($heart.height/2)+20, transition:"linear", onComplete:rebirth,onCompleteParams:[$heart]} );
}
}
}
Now I understand your problem.
First of all, I suggest to never write code on the timeline, except simple stuff like stop() or gotoAndPlay("loop").
The easiest way to achieve what you want is to do the following:
Make a blank MovieClip in Flash IDE Ctrl + F8
Give it a linkage like this:
Then click the edit button (marked with a red rectangle)
Open in Flash Professional if asked
Save the file in your .FLA directory and copy the contents of your Main.as file into this file
Remove the package name ("com.pixeljunkyard")
Change the public class Main extends Sprite to public class ConfettiContainer extends MovieClip and import flash.display.MovieClip
Now you have a class ConfettiContainer which does the same stuff that you Main.as file did. Don't forget to copy anything that this Main.as class uses from stage to your ConfettiContainer MovieClip.
You can now create and use it like this:
var confetti:ConfettiContainer = new ConfettiContainer();
addChild(confetti);
P.S. If you can't see Export for Actionscript option when creating a Symbol in Flash, click Advanced.
I need to develop a cube that contain 10 little cubes and manipulate everyone like an object..Somebody have any idea or some tutorial for do this on PaperVision3d and Flash CS4..Thanks Folks!!
I think what you actually want is Papervision3d as I know of nothing called "PaperViewer". If that is the case, please update your question.
This should give you an idea of how to start. It creates 10 cubes and stores them in an array. You can access them using boxes[index] to alter their scale, postion and rotation.
package
{
import flash.display.Sprite;
import flash.events.Event;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.view.BasicView;
public class Boxes3d extends Sprite
{
private static const NUM_BOXES:int = 10;
private var world:BasicView;
private var boxes:Array;
public function Boxes3d()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStage);
}
private function addedToStage(event:Event):void
{
// create the world and add it to the stage
world = new BasicView();
addChild(world);
// create a set of boxes
boxes = [];
var box:Cube;
var materials:MaterialsList;
for(var boxIndex:int = 0; boxIndex < NUM_BOXES; boxIndex++)
{
// create a material to cover the cube
materials = new MaterialsList({
all: new ColorMaterial(Math.random()*0xFFFFFF) });
// make a cube
box = new Cube(materials, 100, 100, 100);
// spread it out in space
box.x = Math.random()*500 - 250;
box.y = Math.random()*500 - 250;
box.z = Math.random()*500 - 250;
// add it to the scene
world.scene.addChild(box);
}
// get the world to render each frame
world.startRendering();
addEventListener(Event.ENTER_FRAME, positionCamera);
}
private function positionCamera(event:Event):void
{
var camera:Camera3D = world.cameraAsCamera3D;
camera.x = -(stage.width/2 - mouseX) * 2;
camera.y = (stage.height/2 - mouseY) * 2;
}
}
}
I'm trying to make a simple animation with Flash CS4 and Action Script 3.0 to make a number of Symbols fly by from right to left constantly. What I want is that once a symbol has reached the end of the screen it is destroyed and another one is placed at the start position.
I intend to give each symbol a random speed and create a random symbol each time one is 'destroyed'. Any clues where I can start?
As you seem new to flash as a platform I would think writing classes shouldn't be your first port of call when learning ActionScript. Definitely just play about on the timeline for now and learn the basics. As very simple solution to this, I would suggest creating a MovieClip in the library with a class name like 'MyBall'... then paste this onto the first frame of the main timeline et voila.
// Create some variables to store data
var numberOfBalls : int = 20;
var myBalls : Array = [];
var xVelocities : Array = [];
var maxXVelocitySpeed : Number = 5;
var minXVelocitySpeed : Number = 2;
// Add your orginal balls to the stage
for (var i : int = 0; i < numberOfBalls; i++)
{
var myBall : MyBall = new MyBall();
myBall.x = -(Math.random() * stage.stageWidth);
myBall.y = Math.random() * stage.stageHeight;
var xVelocity : Number = minXVelocitySpeed + (Math.random() * (maxXVelocitySpeed - minXVelocitySpeed));
myBalls.push(myBall);
xVelocities.push(xVelocity);
addChild(myBall);
}
// Add a listener for enter frame events
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
//Run this code on every frame to move the balls and reposition them if they are off the stage
function enterFrameHandler(event : Event) : void
{
for each( var myBall : MyBall in myBalls)
{
var ballIndex : int = myBalls.indexOf(myBall);
myBall.x += xVelocity[ballIndex];
if (myBall.x > stage.stageWidth)
{
myBall.x = -(Math.random() * stage.stageWidth);
myBall.y = Math.random() * stage.stageHeight;
}
}
}
First, turn your symbols into MovieClips. Then create a base class MySymbol.as for your symbols, something like:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.Point;
public class MySymbol extends MovieClip
{
public var speed:Number; // Pixels moved per frame
public function MySymbol(speed:Number, startPosition:Point)
{
this.speed = speed;
this.addEventListener(Event.ENTER_FRAME, update);
this.x = startPosition.x;
this.y = startPosition.y;
}
private function update():void
{
this.x -= this.speed;
if (this.x < 0 - this.width) { // We're at the left edge
this.removeEventListener(Event.ENTER_FRAME, update);
this.dispatchEvent(new Event(Event.COMPLETE));
}
}
}
}
Then make sure your movie clips are exported for AS3 (the "linkage" option on the item in the library). Make the class name for each item unique (e.g. MySymbol1, MySymbol2), and set the base class to MySymbol.
Your document class might look something like this:
package {
import flash.display.MovieClip;
import flash.events.Event;
import MySymbol; // Not strictly needed
public class DocumentClass extends flash.display.MovieClip
{
private static var SYMBOLS:Array = new Array(MySymbol1, MySymbol2);
public function DocumentClass()
{
// Create five symbols:
for (var i:int = 0; i < 5; i++) {
makeSymbol();
}
}
private function makeSymbol():void
{
// Pick a random symbol from the array:
var symType:Class = SYMBOLS[Math.random() * SYMBOLS.length];
// Construct the new symbol:
var loc:Point = new Point(stage.stageWidth, Math.random() * stage.stageHeight);
var sym:MySymbol = new symType(1 + Math.random() * 30, loc);
// Listen for the object hitting the left edge:
sym.addEventListener(Event.COMPLETE, remakeObject);
this.addChild(sym);
}
private function remakeObject(e:Event):void
{
e.target.removeEventListener(Event.COMPLETE, remakeObject);
this.removeChild(e.target);
// Replace the dead symbol:
makeSymbol();
}
}
}
It is a lot more efficient if instead of destroying and re-creating an object that flies off-stage you re-use the existing one and move it back to the right. But this is an optimization you can implement later, if things become slow.
Note that all the code above is UNTESTED and I have not coded AS3 in a while, so there's likely at least a few bugs in it. Hopefully it will serve as a good enough starting point.
Define a Circle (symbol) class that extends Sprite/Shape and has a velocity variable
Draw a circle (or whatever) with a random color
Math.floor(Math.random() * 0xffffff)
Assign a random value to velocity
minVelocity + Math.floor(Math.random() * velocityRange)
Create a start() method inside the Circle class that registers an enter frame handler
Increment this.y inside the enter frame handler, and dispatch a 'recycleMe' event if y is more than the max value.
Create N instances of Circle, addChild them, and call their start() methods.
listen to 'recycleMe' events on each of them, and reset the value of y from the handler.
Here's a few prompts to get you started.
MovieClips have an x and y property. If you were to add to these numbers over time you would see the MovieClip move along the x and/or y axis of the stage. Look into doing this using the Event.ENTER_FRAME which will allow you to change the values every time the screen is going to update.
Your stage will have a given width (a stageWidth property). You probably want to monitor when your MovieClip's x property is greater than the width of your stage. If it is remove (removeChild) it and add a new one (addChild) and place it back at the start x/y position.