physics body moves in browser but not on mac or ios - cocos2d-x

i was trying to move the physics body by changing its coordinate in scheduler and i used this code. if i run this code in browser it will work but after js binding it doesn't work on mac or ios. Physics body doesn't move at all on these devices
init: function{
var mass = 1;
var width = 1, height = 1;
this.playerBody = new cp.Body(mass , cp.momentForBox(mass, width, height));
this.space.addBody(this.playerBody);
this.schedule(this.move);
},
move: function(dt){
this.space.step(dt);
this.playerBody.getPos().x += 2 * dt;
this.playerBody.getPos().y += 2 * dt;
}

Try removing that getPos() from those lines, leave them at: this.playerBody.p.x += 2 * dt;. I think that's most likely the cause of your problem.
Additionally, avoid manipulating the coordinates yourself and let the physics engine handle everything.
For example, you could assign the velocity by hand like this:
init: function{
var mass = 1;
var width = 1, height = 1;
var vx = 1, vy = 1;
this.playerBody = new cp.Body(mass , cp.momentForBox(mass, width, height));
this.space.addBody(this.playerBody);
this.playerBody.vx = vx;
this.playerBody.vy = vy;
this.schedule(this.move);
},
move: function(dt){
this.space.step(dt);
}
Or, if you want to give a "bump" to the object in a certain direction, you could use applyImpulse like this:
init: function{
var mass = 1;
var width = 1, height = 1;
var fx = 1, fy = 1;
this.playerBody = new cp.Body(mass , cp.momentForBox(mass, width, height));
this.space.addBody(this.playerBody);
this.playerBody.applyImpuse(cp.v(fx, fy), cp.v(0,0));
this.schedule(this.move);
},
move: function(dt){
this.space.step(dt);
}
Or, if you want to apply a constant force to the object, change applyImpulse to applyForce in that last example.
Note: the cp.v(0,0) parameter is telling the engine to apply the force to the center of the object, so it should not rotate.
PS: if (and only if) you happen to see some strange behaviour with the physics simulation, look at this answer.

after adding few lines my player started to move in mac
init: function{
var mass = 1;
var width = 1, height = 1;
this.playerBody = new cp.Body(mass , cp.momentForBox(mass, width, height));
this.space.addBody(this.playerBody);
this.schedule(this.move);
},
move: function(dt){
this.space.step(dt);
var a = this.playerBody.local2World(this.playerBody.p);
a.y += 2 * dt;
a.x += 2 * dt ;
a = this.playerBody.world2Local(a);
this.playerBody.p = a;
}
but i don't have explanation of this code

Related

Check if image A exists in image B

I need to check if an image exists in another image using JavaScript, I need to know what are the best approaches (algorithm) and solutions (ex: librarie) to do this operations
I explained what I need to do in this image:
Using the GPU to help in image processing.
Using the 2D API and some simple tricks you can exploit the GPUs power to speed up Javascript.
Difference
To find an image you need to compare the pixels you are looking for (A) against the pixels in the image (B). If the difference between the Math.abs(A-B) === 0 then the pixels are the same.
A function to do this may look like the following
function findDif(imageDataSource, imageDataDest, xx,yy)
const ds = imageDataSource.data;
const dd = imageDataDest.data;
const w = imageDataSource.width;
const h = imageDataSource.height;
var x,y;
var dif = 0;
for(y = 0; y < h; y += 1){
for(x = 0; x < w; x += 1){
var indexS = (x + y * w) * 4;
var indexD = (x + xx + (y + yy) * imageDataDest.width) * 4;
dif += Math.abs(ds[indexS]-dd[indexD]);
dif += Math.abs(ds[indexS + 1]-dd[indexD + 1]);
dif += Math.abs(ds[indexS + 2]-dd[indexD + 2]);
}
}
return dif;
}
var source = sourceCanvas.getContext("2d").getImageData(0,0,sourceCanvas.width,sourceCanvas.height);
var dest = destinationCanvas.getContext("2d").getImageData(0,0,destinationCanvas.width,destinationCanvas.height);
if(findDif(source,dest,100,100)){ // is the image at 100,100?
// Yes image is very similar
}
Where the source is the image we are looking for and the dest is the image we want to find it in. We run the function for every location that the image may be and if the result is under a level then its a good chance we have found it.
But this is very very slow in JS. This is where the GPU can help.
Using the ctx.globalCompositeOperation = "difference"; operation we can speed up the process as it will do the difference calculation for us
When you render with the comp operation "difference" the resulting pixels are the difference between the pixels you are drawing and those that are already on the canvas. Thus if you draw on something that is the same the result is all pixels are black (no difference)
To find a similar image in the image you render the image you are testing for at each location on the canvas that you want to test for. Then you get the sum of all the pixels you just rendered on, if the result is under a threshold that you have set then the image under that area is very similar to the image you are testing for.
But we still need to count all the pixels one by one.
A GPU mean function
The comp op "difference" already does the pixel difference calculation for you, but to get the sum you can use the inbuilt image smoothing.
After you have rendered to find the difference you take that area and render it at a smaller scale with ctx.imageSmoothingEnabled = true the default setting. The GPU will do something similar to an average and can reduce the amount of work JS has to do by several orders of magnitude.
Now instead of 100s or 1000s of pixels you can reduce it down to as little at 4 or 16 depending on the accuracy you need.
An example.
Using these methods you can get a near realtime image in image search with just the basic numerical analysis.
Click to start a test. Results are shown plus the time it took. The image that is being searched for is in the top right.
//------------------------------------------------------------------------
// Some helper functions
var imageTools = (function () {
var tools = {
canvas(width, height) { // create a blank image (canvas)
var c = document.createElement("canvas");
c.width = width;
c.height = height;
return c;
},
createImage : function (width, height) {
var i = this.canvas(width, height);
i.ctx = i.getContext("2d");
return i;
},
image2Canvas(img) {
var i = this.canvas(img.width, img.height);
i.ctx = i.getContext("2d");
i.ctx.drawImage(img, 0, 0);
return i;
},
copyImage(img){ // just a named stub
return this.image2Canvas(img);
},
};
return tools;
})();
const U = undefined;
const doFor = (count, callback) => {var i = 0; while (i < count && callback(i ++) !== true ); };
const setOf = (count, callback) => {var a = [],i = 0; while (i < count) { a.push(callback(i ++)) } return a };
const randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0;
const rand = (min, max = min + (min = 0)) => Math.random() * (max - min) + min;
const randA = (array) => array[(Math.random() * array.length) | 0];
const randG = (min, max = min + (min = 0)) => Math.random() * Math.random() * Math.random() * Math.random() * (max - min) + min;
// end of helper functions
//------------------------------------------------------------------------
function doit(){
document.body.innerHTML = ""; // clear the page;
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
var ctx = canvas.getContext("2d");
// a grid of 36 images
canvas.width = 6 * 64;
canvas.height = 6 * 64;
console.log("test");
// get a random character to look for
const digit = String.fromCharCode("A".charCodeAt(0) + randI(26));
// get some characters we dont want
const randomDigits = setOf(6,i=>{
return String.fromCharCode("A".charCodeAt(0) + randI(26));
})
randomDigits.push(digit); // add the image we are looking for
var w = canvas.width;
var h = canvas.height;
// create a canvas for the image we are looking for
const imageToFind = imageTools.createImage(64,64);
// and a larger one to cover pixels on the sides
const imageToFindExtend = imageTools.createImage(128,128);
// Draw the character onto the image with a white background and scaled to fit
imageToFindExtend.ctx.fillStyle = imageToFind.ctx.fillStyle = "White";
imageToFind.ctx.fillRect(0,0,64,64);
imageToFindExtend.ctx.fillRect(0,0,128,128);
ctx.font = imageToFind.ctx.font = "64px arial black";
ctx.textAlign = imageToFind.ctx.textAlign = "center";
ctx.textBaseline = imageToFind.ctx.textBaseline = "middle";
const digWidth = imageToFind.ctx.measureText(digit).width+8;
const scale = Math.min(1,64/digWidth);
imageToFind.ctx.fillStyle = "black";
imageToFind.ctx.setTransform(scale,0,0,scale,32,32);
imageToFind.ctx.fillText(digit,0,0);
imageToFind.ctx.setTransform(1,0,0,1,0,0);
imageToFindExtend.ctx.drawImage(imageToFind,32,32);
imageToFind.extendedImage = imageToFindExtend;
// Now fill the canvas with images of other characters
ctx.fillStyle = "white";
ctx.setTransform(1,0,0,1,0,0);
ctx.fillRect(0,0,w,h);
ctx.fillStyle = "black";
ctx.strokeStyle = "white";
ctx.lineJoin = "round";
ctx.lineWidth = 12;
// some characters will be rotated 90,180,-90 deg
const dirs = [
[1,0,0,1,0,0],
[0,1,-1,0,1,0],
[-1,0,0,-1,1,1],
[0,-1,1,0,0,1],
]
// draw random characters at random directions
doFor(h / 64, y => {
doFor(w / 64, x => {
const dir = randA(dirs)
ctx.setTransform(dir[0] * scale,dir[1] * scale,dir[2] * scale,dir[3] * scale,x * 64 + 32, y * 64 + 32);
const d = randA(randomDigits);
ctx.strokeText(d,0,0);
ctx.fillText(d,0,0);
});
});
ctx.setTransform(1,0,0,1,0,0);
// get a copy of the canvas
const saveCan = imageTools.copyImage(ctx.canvas);
// function that finds the images
// image is the image to find
// dir is the matrix direction to find
// smapleSize is the mean sampling size samller numbers are quicker
function checkFor(image,dir,sampleSize){
const can = imageTools.copyImage(saveCan);
const c = can.ctx;
const stepx = 64;
const stepy = 64;
// the image that will contain the reduced means of the differences
const results = imageTools.createImage(Math.ceil(w / stepx) * sampleSize,Math.ceil(h / stepy) * sampleSize);
const e = image.extendedImage;
// for each potencial image location
// set a clip area and draw the source image on it with
// comp mode "difference";
for(var y = 0 ; y < h; y += stepy ){
for(var x = 0 ; x < w; x += stepx ){
c.save();
c.beginPath();
c.rect(x,y,stepx,stepy);
c.clip();
c.globalCompositeOperation = "difference";
c.setTransform(dir[0],dir[1],dir[2],dir[3],x +32 ,y +32 );
c.drawImage(e,-64,-64);
c.restore();
}
}
// Apply the mean (reducing nnumber of pixels to check
results.ctx.drawImage(can,0,0,results.width,results.height);
// get the pixel data
var dat = new Uint32Array(results.ctx.getImageData(0,0,results.width,results.height).data.buffer);
// for each area get the sum of the difference
for(var y = 0; y < results.height; y += sampleSize){
for(var x = 0; x < results.width; x += sampleSize){
var val = 0;
for(var yy = 0; yy < sampleSize && y+yy < results.height; yy += 1){
var i = x + (y+yy)*results.width;
for(var xx = 0; xx < sampleSize && x + xx < results.width ; xx += 1){
val += dat[i++] & 0xFF;
}
}
// if the sum is under the threshold we have found an image
// and we mark it
if(val < sampleSize * sampleSize * 5){
ctx.strokeStyle = "red";
ctx.fillStyle = "rgba(255,0,0,0.5)";
ctx.lineWidth = 2;
ctx.strokeRect(x * (64/sampleSize),y * (64/sampleSize),64,64);
ctx.fillRect(x * (64/sampleSize),y * (64/sampleSize),64,64);
foundCount += 1;
}
}
}
}
var foundCount = 0;
// find the images at different orientations
var now = performance.now();
checkFor(imageToFind,dirs[0],4);
checkFor(imageToFind,dirs[1],6); // rotated images need larger sample size
checkFor(imageToFind,dirs[2],6);
checkFor(imageToFind,dirs[3],6);
var time = performance.now() - now;
var result = document.createElement("div");
result.textContent = "Found "+foundCount +" matching images in "+time.toFixed(3)+"ms. Click to try again.";
document.body.appendChild(result);
// show the image we are looking for
imageToFind.style.left = (64*6 + 16) + "px";
imageToFind.id = "lookingFor";
document.body.appendChild(imageToFind);
}
document.addEventListener("click",doit);
canvas {
border : 2px solid black;
position : absolute;
top : 28px;
left : 2px;
}
#lookingFor {
border : 4px solid red;
}
div {
border : 2px solid black;
position : absolute;
top : 2px;
left : 2px;
}
Click to start test.
Not perfect
The example is not perfect and will sometimes make mistakes. There is a huge amount of room for improving both the accuracy and the speed. This is just something I threw together as an example to show how to use the GPU via the 2D API. Some further maths will be needed to find the statistically good results.
This method can also work for different scales, and rotations, you can even use some of the other comp modes to remove colour and normalize contrast. I have used a very similar approch to stabilize webcam by tracking points from one frame to the next, and a veriaty of other image tracking uses.

Working with canvas to display only the drawn image and not whole canvas

With the plugin i found earlier on stackoverflow. Drawing has become smooth and nice. What i want is to only get the image part which i draw cropped from the canvas as an output and not the complete canvas. Can somebody help.
This is the code i am using for my canvas now: http://jsfiddle.net/sVsZL/1/
function canvasDisplay() {
var c=document.getElementById("canvas");
canvasImage=c.toDataURL("image/png");
document.getElementById("SSMySelectedImage").src=canvasImage;
}
Adding another answer because the other one was completely off.
Live Demo
What you need essentially is to keep track of a bounding box. What I do is create an object that holds the min values and max values of where you've drawn. This enables you to keep track of how big the image is and where it begins/ends.
this.dim = {minX : 9999, minY : 9999, maxX : 0, maxY : 0};
Then I created a function that checks the bounds.
this.setDimensions = function(x,y){
if(x < this.dim.minX){
this.dim.minX = x;
}
if(y < this.dim.minY){
this.dim.minY = y;
}
if(x > this.dim.maxX){
this.dim.maxX= x;
}
if(y > this.dim.maxY){
this.dim.maxY = y;
}
}
Make sure to check during clicking or moving.
this.mousedown = function(ev) {
tool.setDimensions(ev._x,ev._y);
};
this.mousemove = function(ev) {
tool.setDimensions(ev._x,ev._y);
};
And this is just a sample function that draws the portion to a new canvas that you could then save with toDataUrl
var button = document.getElementsByTagName("input")[0];
button.addEventListener("click", function(){
var savedCanvas = document.createElement("canvas"),
savedCtx = savedCanvas.getContext("2d"),
minX = PEN.dim.minX,
minY = PEN.dim.minY,
maxX = PEN.dim.maxX,
maxY = PEN.dim.maxY,
width = maxX - minX,
height = maxY - minY;
savedCanvas.width = width;
savedCanvas.height = height;
document.body.appendChild(savedCanvas);
savedCtx.drawImage(canvas,minX,minY,width,height,0,0,width,height);
});

AS3 zooming in and out where mouse clicked not at registration

I am trying to have a masked mouse panned image zoom in and out with a click and a double click mouse event. I got the image to zoom but it always zooms in on the left edge registration point, not where I click. I have absolutely no idea how to code this and have spent the whole day on the internet trying to figure it out with no luck. I am hoping someone can help me to figure this out!
import com.greensock.*;//Greensock Tweening Platform.
//Variables
var percX:Number;
var percY:Number;
var destX:Number;
var destY:Number;
//Image panned and masked
this.mask = mask_mc;
stage.addEventListener(MouseEvent.MOUSE_MOVE,mousemove);
function mousemove(e:MouseEvent) {
if (mask_mc.hitTestPoint(stage.mouseX,stage.mouseY,false)) {
if (imgLoader.width>mask_mc.width) {//Avoids Scrolling if image is under mask area width
percX = mask_mc.mouseX/mask_mc.width;
}
if (imgLoader.height>mask_mc.height) {//Avoids Scrolling if image is under mask area height
percY = mask_mc.mouseY/mask_mc.height;
}
destX = -(imgLoader.width-mask_mc.width)*percX;
destY = -(imgLoader.height-mask_mc.height)*percY;
TweenMax.to(imgLoader,.5,{x:destX,y:destY});
}
}
//Add listeners for the imgLoader movie clip.
imgLoader.doubleClickEnabled = true;
imgLoader.addEventListener(MouseEvent.CLICK, increaseSize);
imgLoader.addEventListener(MouseEvent.DOUBLE_CLICK, decreaseSize);
//This function increases the scale of the image
function increaseSize(event:MouseEvent):void{
TweenLite.to(imgLoader, 1, {scaleX:2, scaleY:2});
}
//This function decreases the scale of the image
function decreaseSize(event:MouseEvent):void{
TweenLite.to(imgLoader, 1, {scaleX:1, scaleY:1});
}
This answer is derived from here
Add this function:
function scaleAroundMouse(objectToScale:DisplayObject, scaleAmount:Number, bounds:Rectangle = null, onComplete:Function = null):TweenLite {
// scaling will be done relatively
var relScaleX:Number = scaleAmount / objectToScale.scaleX;
var relScaleY:Number = scaleAmount / objectToScale.scaleY;
// map vector to centre point within parent scope
var scalePoint:Point = objectToScale.localToGlobal( new Point(objectToScale.mouseX, objectToScale.mouseY));
scalePoint = objectToScale.parent.globalToLocal( scalePoint );
// current registered postion AB
var AB:Point = new Point( objectToScale.x, objectToScale.y );
// CB = AB - scalePoint, objectToScale vector that will scale as it runs from the centre
var CB:Point = AB.subtract( scalePoint );
CB.x *= relScaleX;
CB.y *= relScaleY;
// recaulate AB, objectToScale will be the adjusted position for the clip
AB = scalePoint.add( CB );
// set actual properties
if(bounds){
var limits:Rectangle = new Rectangle(
bounds.x + (bounds.width - (objectToScale.width * relScaleX)),
bounds.y + (bounds.height - (objectToScale.height * relScaleY)),
(objectToScale.width * relScaleX) - bounds.width,
(objectToScale.height * relScaleY) - bounds.height
);
if(AB.x < limits.x) AB.x = limits.x;
if(AB.x > limits.x + limits.width) AB.x = limits.x + limits.width;
if(AB.y < limits.y) AB.y = limits.y;
if(AB.y > limits.y + limits.height) AB.y = limits.y + limits.height;
}
return TweenLite.to(objectToScale,1,{onComplete: onComplete, scaleX: scaleAmount, scaleY: scaleAmount, x: AB.x, y: AB.y);
}
Then update your sizing function to this:
function increaseSize(event:MouseEvent):void{
stopMouseMove();
scaleAroundMouse(imgLoader, 2, null, resumeMouseMove);
}
function decreaseSize(event:MouseEvent):void{
stopMouseMove();
scaleAroundMouse(imgLoader, 1, null, resumeMouseMove);
}
function stopMouseMove():void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE,mousemove);
}
function resumeMouseMove():void {
stage.addEventListener(MouseEvent.MOUSE_MOVE,mousemove);
}
I also added a bounds parameter to the function. This is useful if you never want the edges of you content to be visible within the mask. So if you could use it by passing the bounds of your mask to the function:
scaleAroundMouse(imgLoader, 1, myMask.getBounds(this));
This example uses zoom effect classes that may help achieve the zoom effect you are looking for http://graphics-geek.blogspot.com/2010/06/video-image-zoom-effect-in-flex-4.html.
var mat:Matrix=new Matrix();
mat.translate(-p.x,-p.y);
mat.scale(desiredScale,desiredScale);
mat.translate(p.x,p.y);
yourObject.transform.matrix=mat;
That is taken from a question I posted about a month ago. You can see it here. While I didn't end up going with that specific snippet (I actually went with a modified version of the script LondongDrugs_MediaServ posted), it will work and is much easier to understand and implement.

Actionscript 3: Dynamically adding movieclips constrained to a container

Last Edit: Resolved!
Well, i was unable to find the ENTIRE answer here but i finally got what i was after. thanks very much for all of your help and patience.
as a side note: i think i may have been having problems with using the int and Number types, upon closer inspection of my solution, i realised that Number was being used and not int. turns out number contains floating points and int doesn't. my numbers were probably rounding whenever i tried to fix this my self. for all i know, TDI's answer might have been spot on and the use of int for the padding might have accumulated rounded numbers.. Oh well, you learn something every day..
the correct code to constrain movie clips to a container movie clip (or sprite or whatever) in the fashion i was looking for is this:
var picContainer:PicContainer = new PicContainer();
picContainer.x = stage.stageWidth / 2 - picContainer.width / 2;
picContainer.y = stage.stageHeight / 2 - picContainer.height / 2;
addChild(picContainer);
var totalPics:int = 17;
var pic:Pic = new Pic(); //make an instance just to get its width
var xRange:Number = picContainer.width - pic.width;
var spacing:Number = xRange / (totalPics - 1);
//A little optimization: only need to calculate this number ONCE:
var yLoc:Number = picContainer.height / 2 - pic.height / 2;
for(var i:int = 0; i < totalPics; i++) {
pic = new Pic();
pic.x = i * spacing;
pic.y = yLoc;
picContainer.addChild(pic);
}
the logic is pretty simple, and i don't know why i couldn't get it my self, because i drew diagrams that say exactly this logic. however, i must not have put the numbers in the right places or i wouldn't have had to ask, would i ;P
BONUS CONTENT!
as an added bonus (if anyone finds this thread looking for answers..)
you could also have the 'pic's fan out from the center point (but they'd still be in order of left to right) by using this code:
var picContainer:PicContainer = new PicContainer();
picContainer.x = stage.stageWidth / 2 - picContainer.width / 2;
picContainer.y = stage.stageHeight / 2 - picContainer.height / 2;
addChild(picContainer);
var totalPics:int = 5;
var pic:Pic = new Pic(); //make an instance just to get its width
var padding:Number = (picContainer.width - (pic.width * totalPics)) / (totalPics + 1);
for(var i:int = 0; i < totalPics; i++) {
pic = new Pic();
pic.x = padding + i * (pic.width + padding);
pic.y = picContainer.height / 2 - pic.height / 2;
picContainer.addChild(pic);
}
Try it out, these make for great thumbnail dock engines!
First Edit: Well, there is some progress thanks to TDI but not a complete solution.
you see, the problem remains that the movie clips do not squash completely into the container, the last one or two are left sticking out.
example:
my revised code looks like this:
var newPicContainer:picContainer = new picContainer();
var newPic:pic;
var picwidth:int = 100;
var amountofpics:int = 22;
var i:int;
//add a container
addChild(newPicContainer);
//center our container
newPicContainer.x = (stage.stageWidth/2)- (newPicContainer.width/2);
newPicContainer.y = (stage.stageHeight/2)- (newPicContainer.height/2);
var totalpicwidth:int = picwidth*amountofpics;
var totalpadding:int = newPicContainer.width - totalpicwidth;
var paddingbetween:int = (totalpadding / amountofpics);
for (i = 0; i < amountofpics; ++i)
{
//make a new mc called newPic(and i's value) eg. newPic1
this['newPic' + i] = new pic();
this['newPic' + i].width = picwidth;
//add our pic to the container
newPicContainer.addChild(this['newPic' + i]);
//set the new pics X
if (i != 0)
{
// if i is not 0, set newpic(i)s x to the previous pic plus the previous pics width and add our dynamic padding
this['newPic' + i].x = this['newPic' + (i-1)].x + picwidth + paddingbetween;
}
else
{
this['newPic' + i].x = 0;
}
}
thanks again to anyone in advance!
Original Post:
Hello, First time posting here. I hope I'm not getting anything wrong . my problem is as follows:
I've got a pretty basic for loop that creates a 'thumbnail' and puts it next to the previous one (With a little padding) inside a containing movie clip.
var newPicContainer:picContainer = new picContainer();
var newPic:pic;
var amount:int = 9;
var i:int;
//Add our container
addChild(newPicContainer);
//center our container
newPicContainer.x = (stage.stageWidth/2)- (newPicContainer.width/2);
newPicContainer.y = (stage.stageHeight/2)- (newPicContainer.height/2);
for (i = 0; i < amount; ++i)
{
newPic = new pic();
newPicContainer.addChild(newPic);
//just so i know it's adding them..
trace(newPic.thisOne);
newPic.thisOne = i;
// set this one to its self (+5 for padding..) Times, the amount already placed.
newPic.x = (newPic.width+5) *i;
}
I'm wondering if there is some equation or 'magic math' that I can use to figure out what the length of the container is and have the 'thumbnails' be added relative to that number. basically squashing the thumbnails against each other to make them all fit inside..
something along the lines of:
newPic.x = (newPic.width *i) - stuff here to make it know not to go past the containing width;
I must admit i'm not too great with math and so this part of coding escapes me..
thanks to any takers in advance..
you can get the length of your container by either calling its width property explicitly:
//Container Width
newPicContainer.width;
or the newContainer is also the parent of the added pics:
//Container Width
newPic.parent.width;
then you need to get the total length occupied by you pics:
var arrayOfPics:array = [pic1, pic2, pic3, pic4, pic5];
var picsWidth:Number;
for each (var element:pic in arrayOfPics)
picsWidth =+ element.width;
after than you can subtract the length of the total pics from the container to know your available padding for separation:
var totalPadding:Number = newPicContainer.width - picsWidth;
now you can determine how much padding you can afford between the pics and both sides of the container by dividing the totalPadding by the number of pics, and add an extra padding for the end.
var padding:Number = totalPadding / arrayOfPics.length + 1;
now you can simply add your pics by including the padding
for (var i:int = 0; i < arrayOfPics.length; i++)
{
newPicContainer.addChild(arrayOfPics[i]);
(i == 0) ? arrayOfPics[i].x = padding : arrayOfPics[i].x = arrayOfPics[i - 1].x + arrayOfPics[i - 1].width + padding;
}
Try this...
//maximum available length
var maxLength:int;
// a single thumbnail width
var picWidth:int = 100;
// total number of pics in a container
var maxNumPics:int;
// as long as the maximum available length
// is inferior to the container length
// add a new thumbnail
while( maxLength < newPicContainer.length - 100 )
{
maxLength += 100;
maxNumPics += 1;
}
// calculate the amount of available padding.
var padding:Number = ( newPicContainer.length - maxLength )/ maxNumPics;
//add your thumbs
var picX:int;
for( var i:int ; i < maxNumPics ; ++i )
{
var newPic:Pic = new Pic();
newPic.x = picX;
picX += padding + picWidth;
newPicContainer.addChild( newPic );
}
I'd recommend you look at using the Flex framework (it's a Flash framework), it will make building this sort of view much easier.
You can set a container's layout property, so that items are placed in horizontal, vertical or tiled layouts, and then just add items to the container.
For more info on Flex look here
For info on Flex Layouts

Insane Graphics.lineStyle behavior

I'd like some help with a little project of mine.
Background:
i have a little hierarchy of Sprite derived classes (5 levels starting from the one, that is the root application class in Flex Builder). Width and Height properties are overriden so that my class always remembers it's requested size (not just bounding size around content) and also those properties explicitly set scaleX and scaleY to 1, so that no scaling would ever be involved. After storing those values, draw() method is called to redraw content.
Drawing:
Drawing is very straight forward. Only the deepest object (at 1-indexed level 5) draws something into this.graphics object like this:
var gr:Graphics = this.graphics;
gr.clear();
gr.lineStyle(0, this.borderColor, 1, true, LineScaleMode.NONE);
gr.beginFill(0x0000CC);
gr.drawRoundRectComplex(0, 0, this.width, this.height, 10, 10, 0, 0);
gr.endFill();
Further on:
There is also MouseEvent.MOUSE_WHEEL event attached to the parent of the object that draws. What handler does is simply resizes that drawing object.
Problem:
Screenshot
When resizing sometimes that hairline border line with LineScaleMode.NONE set gains thickness (quite often even >10 px) + it quite often leaves a trail of itself (as seen in the picture above and below blue box (notice that box itself has one px black border)). When i set lineStile thickness to NaN or alpha to 0, that trail is no more happening.
I've been coming back to this problem and dropping it for some other stuff for over a week now.
Any ideas anyone?
P.S. Grey background is that of Flash Player itself, not my own choise.. :D
As requested, a bit more:
Application is supposed to be a calendar-timeline with a zooming "feature" (project for a course at university). Thus i have these functions that have something to do with resizing:
public function performZoom():void
{
// Calculate new width:
var newDayWidth:Number = view.width / 7 * this.calModel.zoom;
if (newDayWidth < 1)
{
newDayWidth = 1;
}
var newWidth:int = int(newDayWidth * timeline.totalDays);
// Calculate day element Height/Width ratio:
var headerHeight:Number = this.timeline.headerAllDay;
var proportion:Number = 0;
if (this.view.width != 0 && this.view.height != 0)
{
proportion = 1 / (this.view.width / 7) * (this.view.height - this.timeline.headerAllDay);
}
// Calculate new height:
var newHeight:int = int(newDayWidth * proportion + this.timeline.headerAllDay);
// Calculate mouse position scale on X axis:
var xScale:Number = 0;
if (this.timeline.width != 0)
{
xScale = newWidth / this.timeline.width;
}
// Calculate mouse position scale on Y axis:
var yScale:Number = 0;
if (this.timeline.height - this.timeline.headerAllDay != 0)
{
yScale = (newHeight - this.timeline.headerAllDay) / (this.timeline.height - this.timeline.headerAllDay);
}
this.timeline.beginUpdate();
// Resize the timeline
this.timeline.resizeElement(newWidth, newHeight);
this.timeline.endUpdate();
// Move timeline:
this.centerElement(xScale, yScale);
// Reset timeline local mouse position:
this.centerMouse();
}
public function resizeElement(widthValue:Number, heightValue:Number):void
{
var prevWidth:Number = this.myWidth;
var prevHeight:Number = this.myHeight;
if (widthValue != prevWidth || heightValue != prevHeight)
{
super.width = widthValue;
super.height = heightValue;
this.scaleX = 1.0;
this.scaleY = 1.0;
this.myHeight = heightValue;
this.myWidth = widthValue;
if (!this.docking)
{
this.origHeight = heightValue;
this.origWidth = widthValue;
}
this.updateAnchorMargins();
onResizeInternal(prevWidth, prevHeight, widthValue, heightValue);
}
}
Yes. I know.. a lot of core, and a lot of properties, but in fact most of the stuff has been disabled at the end and the situation is as described at the top.
this didn't work:
gr.lineStyle(); // Reset line style
Can we see your resizing code?
Also try clearing your line style as well as your fill:
gr.lineStyle(0, this.borderColor, 1, true, LineScaleMode.NONE);
gr.beginFill(0x0000CC);
gr.drawRoundRectComplex(0, 0, this.width, this.height, 10, 10, 0, 0);
gr.endFill();
gr.lineStyle();//<---- add this line
I don't know whether it's flash bug or what it is, but i finally found the solution.
The thing is that in my case when resizing in a nutshell you get like this:
this.width = this.stage.stageWidth / 7 * 365;
When i switch to maximized window this.width gains value 86k+. When i added this piece of code to draw horizontal line, it fixed itself:
var recWidth:Number = this.width;
var i:int;
var newEnd:Number = 0;
for (i = 1; newEnd < recWidth; i++)
{
newEnd = 100 * i;
if (newEnd > recWidth)
{
newEnd = recWidth;
}
gr.lineTo(newEnd, 0);
}
I don't know what is going on.. This is inconvenient...