alternative way for positioning objects - actionscript-3

I'm looking for an alternative way to position a bunch of objects.
Here is my code:
private var orderContainer:Sprite;
private var currentOrder:uint = 1;
private var orderArray:Array;
private var scroller:uint;
private var xPos:uint;
private var yPos:uint;
.....
xPos = 55;
yPos = 30;
if (currentOrder == 7){ winkelwagenContent.TestBtn.addEventListener(MouseEvent.CLICK, clickHandler);
scroller++;
xPos = 700*scroller;
yPos = 60;
teller = 1;
currentOrder = 1;
}
orderContainer.x = xPos;
orderContainer.y = yPos;
xPos+=270;
if( teller % 2 == 0){
if(scroller >0){
xPos = (700+(teller*8))*scroller;
}else{
xPos = 55+(teller*8);
}
yPos+=100;
}
teller++;
currentOrder++;
}
private function clickHandler(e:MouseEvent):void{
for each(var order:Object in orderArray){
TweenLite.to(order, .5,{x:order.x-60});
}
}
Basicly what i want is that the objects(ordercontainer) are added to my movieclip in 2 collumns, so 1 left, 1 right, move the y-position down to below the 2 i just added and repeat.
till i get 3 2-collumns under eachother, when it reaches this, the yPosition should get reset to the top and the xPosition should move to the right so i can create a 2-column again next to it, again to 3 2-collumns, reset the yPositon again and repeat till all my objects are added, the amount of objects is variable so the calculation should be flexible.
Its working with the code i have but i have a feeling that i am making it way to complicated again.
You will see that the xPosition adds (teller*8) this is just because my allignment should be slightly diagonal on the yPosition.
There is also a tween attached to a button wich makes all the objects move to the left so the next collumn is visible(this isnt working very well thou, no idea why).
so to summ it up it should go like this:
**(1)** **(2)** **(7)** **(8)**
**(3)** **(4)** **(9)** **(10)**
**(5)** **(6)** **(11)** **(12)**
numbers are for the order the objects are added.

Here's one solution. Suppose you have an array of movieclips called objs.
const colNum:int = 2;
const rowNum:int = 3;
var offset:int = 0;
while (objs.length)
{
for (var j:int=0; j<rowNum; j++)
{
for (var i:int = 0; i<colNum; i++)
{
if (objs.length)
{
var nextObj:MovieClip = objs.shift();
nextObj.x = (offset+i) * nextObj.width;
nextObj.y = j * nextObj.height;
}
}
}
offset+=colNum;
}

Related

How to change MovieClip transparency based on mouse position?

So, I'm trying to make a grid of rectangles each get more transparent the closer the mouse is to it.
Using some basic maths, I thought I had got it, but instead it seems I got a weird graphic bug(maybe?) shown here:
The middle of the rings is where the mouse is.
Part of code that deals with transparency:
private function update(e:Event = null):void
{
for (var i:int = 0; i < buttons.length; i++) {
lightFact = getDistance(buttons[i])
lightBrightness = lightPower - (lightFact * 10)
buttons[i].alpha = lightBrightness
}
}
getDistance is just getting distance from the block to the mouse.
Each rectangle is a movie clip, if that matters.
If you are trying to do this:
Then I think your problem is basically that your alpha value is ranging from 0 to about 3000 or something like that. That's going to cause strange effects. The value needs to range smoothly from 0 to 1 (so it needs to be a floating point number as in Number).
Here is the code which generated the image above which I wrote for you that will get you started in the right direction:
package
{
import flash.display.*;
import flash.events.*;
public class lightFactTest extends MovieClip
{
private var boxesArray: Array = new Array();
private var xDist: Number = 0;
private var yDist: Number = 0;
private var d: Number = 0;
private var size_Glow : Number = 0;
private var size_Radius : Number = 0;
public function lightFactTest(): void
{
// creates a background for rectangles array.
var BG_box: Sprite = new Sprite();
BG_box.graphics.lineStyle();
BG_box.graphics.beginFill(0x080839);
BG_box.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
BG_box.graphics.endFill();
addChild(BG_box);
//# creates a grid of sprites (rectangles).
for (var i:int = 0; i < (stage.stageWidth / 10); i++)
{
for (var j:int = 0; j < (stage.stageHeight / 10); j++)
{
var box: Sprite = new Sprite();
box.graphics.lineStyle();
box.graphics.beginFill(0xFFFFFF);
box.graphics.drawRect(0, 0, 10, 10);
box.graphics.endFill();
addChild(box);
box.x += i*10; //+ 50;
box.y += j*10; //+ 50;
boxesArray.push(box);
}
}
addEventListener(Event.ENTER_FRAME, lightCalc);
}
private function lightCalc(e: Event): void
{
size_Glow = 3.5;
size_Radius = 0.64;
//# iterates through the array calculating each distance and then alpha.
for (var i:int = 0; i < boxesArray.length; i++)
{
xDist = Math.abs(stage.mouseX - boxesArray[i].x);
yDist = Math.abs(stage.mouseY - boxesArray[i].y);
//var d: Number = Math.pow(xDist * xDist + yDist * yDist, 0.5);
d = Math.sqrt(xDist * xDist + yDist * yDist) / (size_Radius / 5);
//# This is the code that you really need to focus on...
boxesArray[i].alpha = Math.min(1 / d * 10, 1 ) * (Math.PI / 0.5 - Math.min(size_Radius, 0) ) * size_Glow;
}
}
}
}
Hope that helps!

My bar charts overlap eachother. Need help to solve it

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();

how to make this road not scale itself.And make equally big portion(like size big) sections of the road

Im currently trying to make a road movement animation but cant figure how the road must not scale itself.
The whole code isn`t mine it is from a tutorial ,I just tried to modify it to my needs ,but I cant do the part that the road should move like if Im seeing it from above(bird view) ,at always same speed.
currently i have this swf file
http://www.stouchgames.com/APKs/Road.swf
I dont want it to be like little lines in the top and then in the bottom a big line that moves.I just want to be equally Big lines that move from top to bottom.
So far i have a simple movieClip with 2 frames and the frames have the graphics in this picture:
http://stouchgames.com/APKs/road.jpg
and this code :
package {
import flash.display.MovieClip;
import flash.events.Event;
public class Main extends MovieClip {
//Depth of the visible road
private const roadLines:int = 320;
//Dimensions of the play area.
private const resX:int = 480;
private const resY:int = 320;
//Line of the player's car.
private const noScaleLine:int = 8;
//All the road lines will be accessed from an Array.
private var yMap:Array = [];
private var lines:Array = [];
private var halfWidth:Number;
private var lineDepth:int;
private const widthStep:Number = 0;
private var playerY:Number;
private var speed:int = 2;
private var texOffset:int = 100;
public function Main() {
//Populate the zMap with the depth of the road lines
for (var i:int = 0; i < roadLines; i++) {
yMap.push(1 / (i - resY));
}
playerY = 100 / yMap[noScaleLine];
for (i = 0; i < roadLines; i++) {
yMap[i] *= playerY;
}
//Make the line at the bottom to be in front of the rest,
//and add every line at the same position, bottom first.
lineDepth = numChildren;
for (i = 0; i < roadLines; i++) {
var line = new Road();
lines.push(line);
addChildAt(line, lineDepth);
line.x = resX / 2;
line.y = resY - i;
}
//Scaling the road lines according to their position
addEventListener(Event.ENTER_FRAME, race);
}
private function race(event:Event):void {
for (var i:int = 0; i < roadLines; i++) {
if ((yMap[i] + texOffset) % 100 > 50) {
lines[i].gotoAndStop(1);
} else {
lines[i].gotoAndStop(2);
}
}
texOffset = texOffset + speed;
while (texOffset >= 100) {
texOffset -= 100;
}
}
}
}
i did try to just make just 2 road movieClips with the different graphics ,then use a
for (var i:int = 0; i < 8; i++) {
if (((i % 2) == 0)) {
var line = new Road ;
lines.push(line);
addChildAt(line,lineDepth);
line.x = resX / 2;
line.y = resY - i * 50;
line.alpha = .2;
}
if (((i % 2) == 1)) {
var line = new Road2 ;
lines.push(line);
addChildAt(line,lineDepth);
line.x = resX / 2;
line.y = resY - i * 50;
line.alpha = .5;
}
but then when i get in the Event.EVERY frame function i cant make them move smoothly ... and decided it must be done by the 1st way cause of the much more detailed ending and cause in the end if i want to change the resolutions of the road i can do it much easier with it . Ofcourse i could be wrong cause i haven`t done such a thing like this before.
So can someone help ?
replace yMap[i] with i in race function:
for (var i:int = 0; i < roadLines; i++) {
if ((i + texOffset) % 100 > 50) {
lines[i].gotoAndStop(1);
} else {
lines[i].gotoAndStop(2);
}
}

Moving movieclips across the stage on FrameEnter

I'm making an image gallery and I want to have a bunch of thumbnails on the bottom of the screen that smoothly slide from side to side when the mouse moves.
I'm working with a custom class for the container (Tiles) and a custom class for the thumbnails (ImageIcon).
I have a ComboBox which allows users to to choose a gallery. When the user chooses a gallery, the following code is run and the thumbnails should reload. The problem here is that the icons appear on top of each other instead of side by side, also switching categories should remove the old one (see the first for loop), but it does not. Also, the Icons are not animating properly. The animation code is below as well. Right now, only one of the icons will move. The icons should move in order from side to side, stopping when the last few icons hit the edge of the screen, so that they don't get "lost" somewhere off to the side.
Gallery Loader Code:
public function loadCategory(xml:XML = null) {
if (xml != null) {
dp = new DataProvider(xml);
for (var k:int = 0; k < this.numChildren; k++) {
this.removeChild(this.getChildAt(k));
}
var black:DropShadowFilter = new DropShadowFilter(0, 45, 0x000000, 1, 3, 3, 1, 1);
var white:DropShadowFilter = new DropShadowFilter(0, 45, 0xFFFFFF, 1, 2, 2, 1, 1);
for (var i:int = 0; i < dp.length; i++) {
var imgicon:ImageIcon = new ImageIcon();
imgicon.addEventListener(MouseEvent.CLICK, showImage);
imgicon.width = 100;
imgicon.x = (i * (imgicon.width + 20));
imgicon.path = dp.getItemAt(i).data;
imgicon.loadIcon();
imgicon.filters = [black, white];
stage.addEventListener(Event.ENTER_FRAME, moveIcon);
this.addChild(imgicon);
}
} else {
//Failed to load XML
}
}
Icon Animation Code:
public function moveIcon(e:Event){
var speed = 0;
speed = Math.floor(Math.abs(this.mouseX/20));
var image = this.getChildAt(k);
var imagebox = image.width + 20;
var edge:Number = (800/2);
if (this.mouseX > 0) {
for (var k:int = 0; k < this.numChildren; k++) {
if (image.x - (imagebox/2) + speed < -edge + (k * imagebox)) {
speed = 0;
}
image.rotationY = Math.floor(image.x/20);
image.x -= Math.floor(speed);
}
} else {
for (var j = this.numChildren; j >= 0; j--) {
if (image.x + speed > edge - ((imagebox * j) )) {
speed = 0;
}
image.rotationY = Math.floor(image.x/20);
image.x += Math.floor(speed);
}
}
}
As I see it, you have three questions (You should have put these at the end of your question instead of "What is wrong with my code?"). One of the main principles of programming is breaking problems into smaller parts.
How do I line up the ImageIcon beside each other?
How do I remove the old ImageIcon, when switching categories?
How do I animate ALL the ImageIcons together, based on the mouse position, with constraints on either side?
Question 1
I can't see anything wrong, but just check that when you are setting imgicon.x, that imgicon.width is actually set.
Question 2
Instead of relying on numChildren and getChildAt(), I would create a currentIcons array member variable, and when you create a new ImageIcon, just push it onto the array. Then when you want to remove them, you can just loop through the array like this:
for each (var cIcon:ImageIcon in currentIcons)
{
cIcon.removeEventListener(MouseEvent.CLICK, showImage);
removeChild(cIcon);
}
currentIcons = [];
As you can see, I am also removing any listeners that I have added. This is best practice. Then clearing the array when I have removed all the icons.
Question 3
I can see a few things wrong with your code. First, in the line where image is set, k is not set yet!
Here you can also use the currentIcons array, but you probably can't use a for each in loop, because that gives you the items out of order. Just a normal for loop will be better.
I haven't tested this code for the moveIcon method, but the idea should work. You may have to tweek it though:
public function moveIcon(e:Event):void
{
var speed:Number = Math.floor(this.mouseX / 20); // Removed "abs".
var imageBox:Number = currentIcons[0].width;
var edge:Number = 800 / 2;
for (var i:int = 0; i < currentIcons.length; i++)
{
var image:ImageIcon = currentIcons[i] as ImageIcon;
image.x += speed;
image.rotationY = Math.floor(image.x / 20);
var min:int = -edge + (i * imagebox);
if (image.x < min) image.x = min;
var max:int = edge - (imagebox * i);
if (image.x > max) image.x = max;
}
}
EDIT* Sorry, it was supposed to be a greater than in the last if statement, but I had a less than by accident.

How to modify position of children inside loop in AS3

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;
}