I am re-learning ActionScript, and I am trying to learn from
digitaldogbyte.com 'Dynamically attached library objects in ActionScript 3.0'. This example, in digialdogbyte, sets the position of each MovieClip across the X position. At high number of numberOfClips, the Objects run right and of the Stage, and out-of-view.
I am trying to adapt the following script to:
wrap the flow of objects to a new line when the edge of the Stage is reached
every other block is coloured red with text colour set to white
The ActionScript:
var numberOfClips:Number = 150;
var xStart:Number = 0;
var yStart:Number = 0;
var xVal:Number = xStart;
var xOffset:Number = 2;
for (var i:Number=0; i<numberOfClips; i++)
{
var mc:myClip = new myClip();
mc.name = "myClip"+(i+1);
this.addChild (mc);
mc.y = yStart;
mc.x = xVal;
xVal = mc.x + mc.width + this.xOffset;
mc.label_txt.text = (i).toString();
}
I'd be grateful if anyone could suggest ways to adapt this script as such.
Add something simple like:
var numberOfClips:Number = 150;
var grid:Rectangle = new Rectangle(0, 0, 20, 20);
for(var i:Number = 0; i < numberOfClips; i++)
{
var mc:myClip = new myClip();
addChild(mc);
mc.x = grid.x;
mc.y = grid.y;
grid.x += grid.width;
// If the new x position is outside of the stage, reset it and
// increase the y position.
if(grid.x + grid.width > stage.stageWidth)
{
grid.x = 0;
grid.y += grid.height;
}
}
You can adjust the width and height of the grid on line 2.
Related
im making a code where I have an input field and a button on my screen. In the code below btnLeggTil (its norwegian) adds the number you wrote in the input field. It determines the height of the bars. My code is supposed to let the user add bars of whatever the height he/she prefers. As you can see I have put alot of my code inside a loop. The problem with the code is that the bars it makes, overlap eachother. I need to have a space between each bar, but don't know how. Thanks in advance! You can test out the code yourself and see (just remember to make a button and input field with names btnLeggTil and txtInn.
("høyde" means height) ("bredde" means width) ("verdier" means values) sorry its all norwegian
var verdier:Array = new Array();
btnLeggTil.addEventListener(MouseEvent.CLICK, leggtil);
function leggtil (evt:MouseEvent)
{
verdier.push(txtInn.text);
var totHøyde:int = 200; //total height on diagram
var totBredde:int = 450; //total width on diagram
var antall:int = verdier.length;
var xv:int = 50;
var yb:int = 350;
var bredde:int = (totBredde/antall) * 0.8;
var mellom:int = (totBredde/antall) * 0.2;
var maksHøyde:int = maksVerdi(verdier);
function maksVerdi(arr:Array):Number //finds the biggest value in the array
{
//copies to not destroy the order in the original
var arrKopi:Array = arr.slice();
arrKopi.sort(Array.NUMERIC|Array.DESCENDING);
return arrKopi[0];
}
for(var i:int = 0; i < verdier.length; i++)
{
graphics.lineStyle(2, 0x000000);
graphics.beginFill(0x00ff00);
graphics.drawRect(xv + (bredde+mellom)*i, yb, bredde, -verdier[i] * (totHøyde/maksHøyde));
graphics.endFill();
var txtTall = new TextField();
txtTall.x = xv + (bredde+mellom)*i + 5;
txtTall.y = yb - verdier[i] - 10;
txtTall.type = "dynamic";
txtTall.text = verdier[i];
addChild(txtTall);
}
}
You need to modify your for loop a bit,
graphics.clear();
graphics.lineStyle(2, 0x000000);
graphics.beginFill(0x00ff00);
for(var i:int = 0; i < verdier.length; i++)
{
graphics.drawRect(xv + (bredde+mellom)*i, yb, bredde, -verdier[i] * (totHøyde/maksHøyde));
var txtTall = new TextField();
txtTall.x = xv + (bredde+mellom)*i + 5;
txtTall.y = yb - verdier[i] - 10;
txtTall.type = "dynamic";
txtTall.text = verdier[i];
addChild(txtTall);
}
graphics.endFill();
So I am trying to create random, falling snow in a Flash application. Using the following code I have my snow appearing at a random point on the screen.
var mc:snowFalling = new snowFalling();
addChild(mc);
var result:Number = Math.random() * 100;
var randomX:Number = Math.random() * stage.stageWidth;
mc.x = randomX;
snowFalling is the linkage name.
I am unsure how to have the snow both appear multiple times and respawn. Could someone give me a rundown of the code I will need to do this.
First, you need to create as many snowflakes on the screen as you'd like to have. Then, you need to move each snow flake every frame tick. Something like the following is ONE way you could do it. (there are many ways to accomplish this).
var flakes:Vector.<snowFalling> = new Vector.<snowFalling>(); //an array to store all your snow flakes
var mc:snowFalling;
var mc2:snowFalling;
var columns:int = 5;
var rows:int = 7;
var columnWidth:Number = stage.stageWidth / columns;
var rowHeight:Number = stage.stageHeight / rows;
//make 5 columns
for (var i:int = 0; i < columns; i++) {
mc = new snowFalling();
mc.x = (columnWidth * i);// + (Math.random() * (columnWidth * .25)); //to randomize the x position within the column size
addChild(mc);
flakes.push(mc);
//make 7 rows in each column
for (var j:int = 0; j < rows; j++) {
mc2 = new snowFalling();
mc2.x = mc.x;
mc2.y = (rowHeight * j);// + (Math.random() * (rowHeight * .25)); //to randomize the y within the row size
addChild(mc2);
flakes.push(mc2);
}
}
//run the enterFrame function below every frame tick of the application
this.addEventListener(Event.ENTER_FRAME, enterFrame);
function enterFrame(e:Event):void {
//loop through each snowflake in the flakes array
for (var i:int = 0; i < flakes.length; i++) {
flakes[i].y += 2; //move it down 2 pixels
//check to see if it's off screen, if so, move back to the top of the screen (less it's height so it's just off screen at the top)
if (flakes[i].y > stage.stageHeight) flakes[i].y = -flakes[i].height;
}
}
Or, if you wanted a traditional spawn type method, this:
//create a container to hold all the snowflakes
var snowContainer:Sprite = new Sprite();
addChild(snowContainer);
//this function creates a snowflake and puts it at the top of the screen in a random x spot
function spawnFlake(e:Event = null):void {
var mc:snowFalling;
snowContainer.addChild(mc);
mc.x = Math.random() * (stage.stageWidth - mc.width);
mc.y = -mc.height; //just off screen at the top
}
//create a timer that will call the spanFlake function every second
var timer:Timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, spawnFlake);
timer.start();
this.addEventListener(Event.ENTER_FRAME, enterFrame);
//every frame, iterate through all the children of snowContainer and move the flakes down 2 pixels
function enterFrame(e:Event):void {
var flake:snowFalling;
var i:int = snowContainer.numChildren;
//we need to iterate backwards because we are potentially removing items (which would throw our i value out of whack if iterating forwards)
while(i--){
flake = snowContainer.getChildAt(i) as snowFalling;
flake.y += 2;
//if out of bounds, remove the flake
if (flake.y > stage.stageHeight) {
snowContainer.removeChild(flake);
}
}
}
I have altered an image carousel I downloaded, to rotate to the next picture (left or right) when I click one of the two buttons I added. The original carousel was built to rotate according to mouse movement/position.
For some reason, whenever I click the 'right' or 'left' button, which each rotate the carousel in their respecive directions, the event listener/handler is one 'behind'. It does whatever it should've done the previous time I clicked a button. To put it more clearly, the first button click it does nothing. The second button click it responds to what I clicked the last time.
Example:
I click the left button, nothing happens.
Then I click the right button, the carousel rotates to the left (because I clicked the left button before this click)
Then I click the left button, the carousel rotates to the right (idem).
See the code below. It seems fairly simple; no complex structure or whatever.
You can ignore most vars and positioning (like focalLength,vanishingPointX,radius, etc), I suppose. I'm guessing this bug is either related to the importing/processing of the XML, the for() loops, or the structure the .as file has.
package {
//here are all the imports
public class Imagereel extends Sprite {
var imgurl:URLRequest = new URLRequest()
var loadedimgs:uint = 0;
var images_num = 0;
var imageHolders:Array = new Array();
var imageHolder:MovieClip;
var btnLeft:BtnLeft = new BtnLeft;
var btnRight:BtnRight = new BtnRight;
//Set the focal length
var focalLength:Number = 2000;
//Set the vanishing point
var vanishingPointX:Number = stage.stageWidth / 2;
var vanishingPointY:Number = stage.stageHeight / 2;
//The 3D floor for the images
var floor:Number = 40;
//Radius of the circle
var radius:Number = 350;
//We use 70x70 sized images (change this if different for your images)
const IMAGE_WIDTH:uint = 393;
const IMAGE_HEIGHT:uint = 249;
var xmlLoader:URLLoader = new URLLoader();
var xmlData:XML = new XML();
public function Imagereel() {
//here's the positioning of the buttons
//here are the button addChilds
xmlLoader.load(new URLRequest("carousel.xml"));
xmlLoader.addEventListener(Event.COMPLETE, LoadXML);
btnLeft.addEventListener(MouseEvent.CLICK, prevImg);
btnRight.addEventListener(MouseEvent.CLICK, nextImg);
}
function LoadXML(e:Event):void {
xmlData = new XML(e.target.data);
Parseimage(xmlData);
}
function Parseimage(imageinput:XML):void {
var imageurl:XMLList = imageinput.image.iurl;
images_num = imageurl.length();
for (var i:int = 0; i < images_num; i++) {
var urlElement:XML = imageurl[i];
imageHolder = new MovieClip();
var imageLoader = new Loader();
imageHolder.addChild(imageLoader);
imageHolder.mouseChildren = false;
imageLoader.x = - (IMAGE_WIDTH);
imageLoader.y = - (IMAGE_HEIGHT);
imageHolders.push(imageHolder);
imgurl.url = imageurl[i];
imageLoader.load(imgurl);
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
}
}
function imageLoaded(e:Event) {
//Update the number of loaded images
loadedimgs++;
//Check to see if this is the last image loaded
if (loadedimgs == images_num) {
//Set up the carousel
initializeCarousel();
}
}
function initializeCarousel() {
//Calculate the angle difference between the images (in radians)
var angleDifference:Number = Math.PI * (360 / images_num) / 180;
//Loop through the images
for (var i:uint = 0; i < imageHolders.length; i++) {
//Assign the imageHolder to a local variable
var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
//Get the angle for the image (we space the images evenly)
var startingAngle:Number = angleDifference * i -0.30;
//Position the imageHolder
imageHolder.xpos3D = radius * Math.cos(startingAngle);
imageHolder.zpos3D = radius * Math.sin(startingAngle);
imageHolder.ypos3D = floor;
//Set a "currentAngle" attribute for the imageHolder
imageHolder.currentAngle = startingAngle;
var scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);
//Position the imageHolder to the stage (from 3D to 2D coordinates)
imageHolder.x = vanishingPointX + imageHolder.xpos3D * scaleRatio;
imageHolder.y = vanishingPointY + imageHolder.ypos3D * scaleRatio;
//Add the imageHolder to the stage
addChild(imageHolder);
}
sortZ();
}
function prevImg(e:MouseEvent) {
//Loop through the images
for (var i:uint = 0; i < imageHolders.length; i++) {
var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
//Set a new 3D position for the imageHolder
imageHolder.xpos3D = radius * Math.cos(imageHolder.currentAngle);
imageHolder.zpos3D = radius * Math.sin(imageHolder.currentAngle);
var scaleRatio;
//Calculate a scale ratio
scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);
//Update the imageHolder's coordinates
imageHolder.x = vanishingPointX+imageHolder.xpos3D * scaleRatio;
imageHolder.y = vanishingPointY+imageHolder.ypos3D * scaleRatio;
//spinning the carousel
imageHolder.currentAngle += 0.6285;
}
//Call the function that sorts the images so they overlap each others correctly
sortZ();
}
function nextImg(e:MouseEvent) {
//Loop through the images
for (var i:uint = 0; i < imageHolders.length; i++) {
var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
//Set a new 3D position for the imageHolder
imageHolder.xpos3D = radius * Math.cos(imageHolder.currentAngle);
imageHolder.zpos3D = radius * Math.sin(imageHolder.currentAngle);
var scaleRatio;
//Update the imageHolder's coordinates
imageHolder.x = vanishingPointX+imageHolder.xpos3D * scaleRatio;
imageHolder.y = vanishingPointY+imageHolder.ypos3D * scaleRatio;
//spinning the carousel
imageHolder.currentAngle -= 0.6285;
}
sortZ();
}
//This function sorts the images so they overlap each others correctly
function sortZ():void {
imageHolders.sortOn("zpos3D", Array.NUMERIC | Array.DESCENDING);
//Set new child indexes for the images
for (var i:uint = 0; i < imageHolders.length; i++) {
setChildIndex(imageHolders[i], i);
}
}
}
}
So what this code does:
carousel.xml is imported
The xml is processed so that the image paths there are converted to displayed images
A carousel is made out of the images
The sortZ() function makes sure that the images are aligned in 3D perspective properly; just like z-index in CSS would do.
When clicking btnLeft or btnRight, the carousel rotates to the left or right (this is done by updating the value of imageHolder.currentAngle).
When I put trace's inside the prevImg() and nextImg() functions, I do see the trace that
belongs to the right function, and not the previously clicked one. So it seems that Flash does call the right event.
So how do I get rid of this bug?
Help and tips are greatly appreciated!
Move imageHolder.currentAngle assignment (the line where you change it) BEFORE the code that alters imageHolder's 3D position.
for (var i:uint = 0; i < imageHolders.length; i++) {
var imageHolder:MovieClip = (MovieClip)(imageHolders[i]);
//Set a new 3D position for the imageHolder
imageHolder.currentAngle += 0.6285; // <== HERE
imageHolder.xpos3D = radius * Math.cos(imageHolder.currentAngle);
imageHolder.zpos3D = radius * Math.sin(imageHolder.currentAngle);
var scaleRatio;
//Calculate a scale ratio
scaleRatio = focalLength/(focalLength + imageHolder.zpos3D);
//Update the imageHolder's coordinates
imageHolder.x = vanishingPointX+imageHolder.xpos3D * scaleRatio;
imageHolder.y = vanishingPointY+imageHolder.ypos3D * scaleRatio;
//spinning the carousel
}
The same for the other function.
Having a bit of a problem with some code I've written. Basically what it does is take 3 values that constantly change and graphs them over time in the form of a cumulative line graph. It almost works except I get this weird line drawn across the entire stage and further and I can't figure out what the issue is. The full code is below, you can run it by pasting it into flash.
import flash.display.Shape;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.utils.Timer;
var y1:Array = new Array();
var y2:Array = new Array();
var y3:Array = new Array();
var avg:Array = new Array();
var y1Shape:Shape = new Shape();
var y2Shape:Shape = new Shape();
var y3Shape:Shape = new Shape();
var avgShape:Shape = new Shape();
var container:Sprite = new Sprite();
var scale:uint = 1;
var redrawGraph:int = setInterval(reDraw,500);
var y1Int:int = 0;
var y2Int:int = 0;
var y3Int:int = 0;
container.addChild(y1Shape);
container.addChild(y2Shape);
container.addChild(y3Shape);
container.addChild(avgShape);
this.addChild(container);
function reDraw():void
{
y1Shape.graphics.clear();
y2Shape.graphics.clear();
y3Shape.graphics.clear();
avgShape.graphics.clear();
y1Shape.graphics.lineStyle(1, 0x0066FF, 1);
y1Shape.graphics.beginFill(0x0066FF, 0.5);
y2Shape.graphics.lineStyle(1, 0x009900, 1);
y2Shape.graphics.beginFill(0x009900, 0.5);
y3Shape.graphics.lineStyle(1, 0x990000, 1);
y3Shape.graphics.beginFill(0x990000, 0.5);
avgShape.graphics.lineStyle(1, 0x000000, 1);
y1Int = rand();
y2Int = rand();
y3Int = rand();
trace(y1Int, y2Int, y3Int);
y1.unshift(y1Int);
y2.unshift(y2Int);
y3.unshift(y3Int);
popOut(y1);
popOut(y2);
popOut(y3);
var i:uint,sum:uint,aLength:uint,len:uint = y1.length,max:int = 0,height_:int = 400;
scale = 10;
for (i=0; i<len; i++)
{
max = Math.max(y1[i] + y2[i] + y3[i],max);
}
for (i=0; i<len; i++)
{
sum += y1[i] + y2[i] + y3[i];
}
avg.unshift(Math.round(sum/len));
/*--------------------------------MATCHED GRAPH------------------------------------------*/
var y1_commands:Vector.<int> = new Vector.<int>();
var y1_coord:Vector.<Number>= new Vector.<Number>();
var y1_coord_rev:Vector.<Number> = new Vector.<Number>();
y1_commands.push(1);
y1_coord.push(400,height_);
for (i=0; i<len; i++)
{
y1_commands.push(2);
y1_coord.push((400-i*scale),height_-(Math.round((y1[i]/max)*height_)));
y1_coord_rev.unshift((400-i*scale),height_-(Math.round((y1[i]/max)*height_)));
}
for (i=len; i>0; i--)
{
y1_commands.push(2);
y1_coord.push(400 - i*scale,height_);
}
y1_commands.push(2);
y1_coord.push(400,height_);
/*--------------------------------MATCHED GRAPH------------------------------------------*/
/*----------------------------------BUSY GRAPH-------------------------------------------*/
var y2_commands:Vector.<int> = new Vector.<int>();
var y2_coord:Vector.<Number>= new Vector.<Number>();
var y2_coord_rev:Vector.<Number> = new Vector.<Number>();
y2_commands.push(1);
y2_coord.push(400,height_-(Math.round((y1[i]/max)*height_)));
for (i=0; i<len; i++)
{
y2_commands.push(2);
y2_coord.push((400-i*scale),height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
y2_coord_rev.unshift((400-i*scale),height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
}
for (i=len; i>0; i--)
{
y2_commands.push(2);
y2_coord.push(400 - i*scale, height_-(Math.round((y1[i]/max)*height_)));
}
y2_commands.push(2);
y2_coord.push(400,height_-(Math.round((y1[i]/max)*height_)));
/*----------------------------------BUSY GRAPH-------------------------------------------*/
/*----------------------------------VAC GRAPH-------------------------------------------*/
var y3_commands:Vector.<int> = new Vector.<int>();
var y3_coord:Vector.<Number>= new Vector.<Number>();
var y3_coord_rev:Vector.<Number> = new Vector.<Number>();
y3_commands.push(1);
y3_coord.push(400,height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
for (i=0; i<len; i++)
{
y3_commands.push(2);
y3_coord.push((400-i*scale),height_-(Math.round(((y1[i]+y2[i]+y3[i])/max)*height_)));
y3_coord_rev.unshift((400-i*scale),height_-(Math.round(((y1[i]+y2[i]+y3[i])/max)*height_)));
}
for (i=len; i>0; i--)
{
y3_commands.push(2);
y3_coord.push(400 - i*scale, height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
}
y2_commands.push(2);
y2_coord.push(400,height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
/*----------------------------------BUSY GRAPH-------------------------------------------*/
//y3Shape.graphics.drawPath(y3_commands, y3_coord);
y2Shape.graphics.drawPath(y2_commands, y2_coord);
y1Shape.graphics.drawPath(y1_commands, y1_coord);
}
function popOut(a:Array):void
{
if (a.length >=Math.ceil(400/scale))
{
a.pop();
}
}
function rand():int
{
return Math.floor(Math.random() * (1 + 5 - 0) + 0);
}
y3Shape is commented out until the problem with y2Shape is fixed (having both drawn just makes the problem harder to figure out).
Any ideas what could be up?
Thanks
If you insert trace your vectors near .drawPath, you'll see something like that:
trace(y2_commands); // 1,2,2,2,2
trace(y2_coord); // 400,171,400,57,390,NaN,400,171,400,57
So, NaN (Not a Number) means, that you have error in coordinates calculating.
ps. y1[i] in first calculating of BUSY GRAPH is undefined
You seem to be using beginFill(), when you draw a path that's not looped, Flash requires your path to get looped in order to fill it with something. So, it loops it implicitly by adding a line to your starting point and filling it. In order to receive a non-overlapping path, add two points to your path that will be right below 0 point in X axis, one right under the last point on your graph, and one right under the FIRST point on the graph.
Actually, you already have them installed, but for some reason you place not 2 points, but a whole lot of em, and height position of that line is plainly wrong. Your code states:
for (i=len; i>0; i--)
{
y2_commands.push(2);
y2_coord.push(400 - i*scale, height_-(Math.round((y1[i]/max)*height_)));
}
You should have:
for (i=len; i>0; i--)
{
y2_commands.push(2);
y2_coord.push(400 - i*scale, height_);
}
Or even better:
y2_commands.push(2);
y2_commands.push(2);
y2_coord.push(400 - len*scale, height_);
y2_coord.push(400, height_);
I'm trying to make a dynamic image gallery from and xml. From my tutorials, right now i've got it so it will constantly add the next thumbnail below the other, which is fine, but I'm trying to figure out how to make it that once it reaches a certain y coordinate, it will move the x coordinate over and stack them again. So that rather one long list of thumbs, it will be a side by side stack. For some reason, I can't get it in my head how something like this would work. My goal is to have a side by side stack that I will end up putting in a movie clip that will be masked to show only 2 stacks at a time. Then when clicking a button will slide it over. I was planning to use the "movieclip.length" to calculate how far over to move it, but i haven't gotten that far yet. This is what I got:
var gallery_xml:XML;
var xmlReq:URLRequest = new URLRequest("xml/content.xml");
var xmlLoader:URLLoader = new URLLoader();
var imageLoader:Loader;
function xmlLoaded(event:Event):void
{
gallery_xml = new XML(xmlLoader.data);
info_txt.text = gallery_xml.screenshots.image[0].attribute("thumb");
for(var i:int = 0; i < gallery_xml.screenshots.image.length(); i++)
{
imageLoader = new Loader();
imageLoader.load(new URLRequest(gallery_xml.screenshots.image[i].attribute("thumb")));
imageLoader.x = 0;
imageLoader.y = i * 70 + 25;
imageLoader.name = gallery_xml.screenshots.image[i].attribute("src");
addChild(imageLoader);
imageLoader.addEventListener(MouseEvent.CLICK, showPicture);
}
}
xmlLoader.load(xmlReq);
xmlLoader.addEventListener(Event.COMPLETE, xmlLoaded);
function showPicture(event:MouseEvent):void
{
imageLoader = new Loader();
imageLoader.load(new URLRequest(event.target.name));
imageLoader.x = 200;
imageLoader.y = 25;
addChild(imageLoader);
}
I can't seem to wrap my head around what I can do to move things over dynamically without having to write a custom if for each set of positions.. I get the feeling I've totally forgotten how to do algebra.
I'd suggest one of the following two solutions (untested):
var next_x:Number = 0.0;
var next_y:Number = 25.0;
for (var i:int = 0; i < gallery_xml.screenshots.image.length(); ++i)
{
// ...
imageLoader.y = next_y;
imageLoader.x = next_x;
next_y += 70;
if (next_y > THRESHOLD)
{
next_x += X_OFFSET;
next_y = 25.0;
}
}
That is, just keep track of where your next image will be placed and adjust that coordinate accordingly when you exceed thresholds. If you want to use your i variable, you'll have to calculate what row and column the image will be placed at:
for (var i:int = 0; i < gallery_xml.screenshots.image.length(); ++i)
{
// ...
var row:int = i % MAX_ITEMS_PER_COLUMN;
var column:int = i / MAX_ITEMS_PER_COLUMN;
imageLoader.y = 25 + row * 70;
imageLoader.x = column * COLUMN_WIDTH;
}