Having a lot of trouble detecting collisions between animated shapes in KineticJS - html

I have one rectangle (rectangle) that is fixed on its x-axis but moves up its y-axis when clicked and moves down its y-axis when released.
I have a setInterval function that creates instances of rectangles (name) that are fixed on their y-axis and are animated to move from right to left across the stage. The y-values are randomly generated in the setInterval function.
I've tried the following functions:
var collisionDetection = function(a,b){
var status = false;
var boardX = 350;
var boardY = a.y();
var attackX = b.x();
var attackY = b.y();
if(boardX == attackX){
console.log('true');
}
}
collisionDetection(rectangle,name)
And:
function doObjectsCollide(a, b) {
if( !(
((a.y() + a.getHeight()) < (b.y())) ||
(a.y() > (b.y + b.getHeight())) ||
((a.x() + a.getWidth()) < b.x()) ||
(a.x() > (b.x() + b.getWidth()))
));
console.log('true');
};
doObjectsCollide(rectangle,name)
Neither of these have worked. I can't tell if it's because instances of the rectangle are created in a setInterval function which makes it some kind of scoping issue, or it's because the x/y values are constantly changing, but collision and animation go hand-in-hand so I don't understand why that would be a problem.
Any help in the right direction would be hugely appreciated.

Try this slightly more efficient refactoring:
Demo: http://jsfiddle.net/m1erickson/hS9P4/
function doRectsCollide(a,b){
var ax=a.x();
var ay=a.y();
var bx=b.x();
var by=b.y();
return(
!(
(bx>ax+a.width()) ||
(bx+b.width()<ax) ||
(by>ay+a.height()) ||
(by+b.height()<ay)
)
);
}

Related

HitTestObject Both MovieClip Actionscript 3.0

I want to make a player and 2 Circles.
When the player hit the first Circle, then the Circle will also move as like player. Continue with the second Circle, if the second circle get hit by the first circle (while the player is moving and pushing the first circle), the second circle will also move as like player's speed movement!
Can you solve the problems, please ... :)
Thank You!
Use the addChild() method.
var circle1Hit:Boolean = false;
var circle2Hit:Boolean = false;
function myHitTest(me:MouseEvent): void
{
if (player.hitTestObject(circle1) && circle1Hit == false){
circle1Hit = true;
var _x:Number = circle1.x - player.x;
var _y:Number = circle1.y - player.y;
player.addChild(circle1)
circle1.x = _x;
circle1.y = _y;
}
if (player.hitTestObject(circle2) && circle2Hit == false)
{
circle2Hit = true;
var _x:Number = circle2.x - player.x;
var _y:Number = circle2.y - player.y;
player.addChild(circle2)
circle2.x = _x;
circle2.y = _y;
}
}
For further reading check out this great tutorial that explains containers and OOP really well. Also check out the one on Arrays from the same author here. By using an array, you could add even more circles to the array and all of them would be able to stick like these two do without having to have a separate bit of code for each circle like we have here.

As 3.0 2 Complementary Sliders

The question is to code with AS 3.0 for 2 sliders in a way that when the first slider is incremented by a uint the other slider decreases by the same uint and vis versa.
So here's the documentation for the Flash Slider class.
Here's how I would go about it:
// Add the sliders to the stage, lets call them `slider1` & `slider2`.
// Store each value of the slider
var slider1Position:Number = slider1.value;
var slider2Position:Number = slider2.value;
// Set liveDragging to true so the CHANGE event is fired continuously
slider1.liveDragging = true;
slider2.liveDragging = true;
// Add event listeners to listen for when they are moved.
slider1.addEventListener(SliderEvent.CHANGE, onSlider1Changing);
slider2.addEventListener(SliderEvent.CHANGE, onSlider2Changing);
function onSlider1Changing(e:SliderEvent):void {
var difference:Number = e.value - slider1Position;
// update the position of the other slider
slider2.value += difference;
}
function onSlider2Changing(e:SliderEvent):void {
var difference:Number = e.value - slider2Position;
// update the position of the other slider
slider1.value += difference;
}
Try that out. I'm hoping that setting the value manually won't trigger a CHANGE event...
Sorry that it did not work. I proceeded this way for the interaction between (slider1) and (slider2) as slave.
var slider1Position:Number = slider1.value;
var slider2Position:Number = slider2.value;
slider2.value = 100; // max value for the sliders is 100 as an example.
slider1.addEventListener(SliderEvent.CHANGE, onSlider1Changing);
function onSlider1Changing(e:SliderEvent):void {
slider1Position = e.value;
slider2.value = 100 - slider1Position;
}
What is missing in the whole code is the other way where slider2 is considered as activator and slider1 as slave.
I hope really not bother with my question.

Maximum call stack size exceeded error / Properly writing constructors

Firstly, I got a 'maximum call stack size exceeded' error on some JavaScript code I'll be posting below, and I'm not sure where it's coming from. I don't think I'm calling anything recursively, and I couldn't find any other cause of the error from looking around. I'm using Chrome to execute the program, and the only details I can get out of the console are 'Vector Vector Vector Vector Vector Vector Vector...' etc. I think this means that the Vector function is recursively calling itself, but, again, I can't figure out where that's happening. So, firstly, here's the Vector function:
function Vector(top,left) { //a vector constructor, with all necessary vector operations
this.top = top; //the 'top' component, which points down
this.left = left; //the 'left' component, which points right
this.in = 0; //the 'in' component, which points out of the screen
this.magnitude = Math.sqrt(this.top*this.top+this.left*this.left); //the magnitude of the vector
this.reverse = new Vector(-this.top,-this.left); //the vector that points opposite of this vector
this.unit = this.Scale(1/this.magnitude); //the unit vector pointing in this vector's direction
this.Scale = Scale; //multiplying vectors by a constant
this.Add = Add; //easier vector addition
this.Subtract = Subtract; //and subtraction
this.Dot = Dot; //a dot product operation
this.Cross = Cross; //the cross product of two planar vectors; it returns the 'in' component of the resulting vector
this.Project = Project; //the projetion of the parameter vector onto this vector
function Scale(scalar) {return new Vector(scalar*this.top,scalar*this.left);}
function Add(vector) {return new Vector(this.top+vector.top,this.left+vector.left);}
function Subtract(vector) {return new Vector(this.top-vector.top,this.left-vector.left);} //the abovedescribed methods
function Dot(vector) {return this.top*vector.top+this.left*vector.left;}
function Cross(vector) {return this.top*vector.left-this.left*vector.top;}
function Project(vector) {return this.Scale(this.Dot(vector)/Math.pow(this.magnitude,2))}
}
var zeroVector = new Vector(0,0);
And here's the full code. Feel free to completely ignore it, though maybe something will be blatantly obvious to you which was impeccably hidden from me.
<!DOCTYPE html>
<html>
<head>
<title>temp</title>
</head>
<body>
<canvas
id="canvas"
height="768px"
width="1366px"
style="position:fixed;top:0px;left:0px;"
/>
</body>
<script>
/*------------------------------------------------------------Composition Center--------------------------------------------------*/ {
window.onload = run; //it'll start running as soon as it's started up
var interval; //the interval variable for the 'run' function
function run() {
interval = setInterval(function() {
for (i=0; i!=0; i++) {
var Point = point;
var vPrime = zeroVector;
var netForce = zeroVector;
for (j=0; j!=0; j++) {
var Edge = edge;
updateCollision(Point,Edge);
}
updatePosition(Point);
updateVelocity(Point);
draw();
}
},16);
}
/*---------------------------------------------------------------------------------------------------------------------------------*/ }
/*-------------------------------------------------------------Physics Engine------------------------------------------------------*/ {
//--Constructors--//
function PointObject(mass,top,left) { //a point object
this.mass = mass; //mass
this.position = new Vector(top,left); //position
this.velocity = zeroVector; //velocity
this.near = nullEdge; //a memory tool which stores the edge the point is close to
}
function Rectangle(top,left,height,width) { //a rectangle that'll be solid, but not affected by gravity or anything
this.position = new Vector(top,left);
this.height = height; //self-explanatory
this.width = width;
}
function Edge(start,end) {
this.start = start; //the start point (vector)
this.end = end; //end point (vector)
this.vector = end.Subtract(start); //the vector pointing from the start to the end point of the edge
this.RUN = new Vector(this.vector.left,-this.vector.top).unit; //the RIGHT pointing UNIT NORMAL vector to the edge vector
this.rightPermeable = false; //whether or not the edge can be passed through from the right to the left
this.leftPermeable = true; //or from the left to the right
}
//--Objects--//
var base = new Rectangle(3/4*768,33,768/4,1300); //the main base solid
var point = new PointObject(1,base.position.top-201,1366/2); //the point object at the center of this whole ordeal
var edge = new Edge(new Vector(base.position.top,base.position.left+base.width),base.position); //a test edge. they'll be auto-assembled later
var nullEdge = new Edge(zeroVector,zeroVector);
var deltaT = .01; //standard time interval
//--Loop o' Physics--//
//Update Collision
function updateCollision(Point,edge) { //check if any points are crossing edges and deal with that
var startToPoint = Point.position.Subtract(edge.start); //the vector from the start point of the edge to the tested point
if (edge.rightPermeable && edge.vector.Cross(startToPoint) < 0) {return "Negatory.";} //if it could only approach from a permeable side, stop testing
if (edge.leftPermeable && edge.vector.Cross(startToPoint) > 0) {return "Negatory.";}
var projection = edge.vector.Project(startToPoint); //the projection of that vector onto the edge vector
if (projection.Dot(edge.vector) < 0) {return "Negatory.";} //if it's not pointing in the same dircetion as the edge vector, it's not gonna hit the edge
var distance = startToPoint.Subtract(projection); //the normal vector to the edge that points to the Point
var velocity = distance.Project(Point.velocity); //the component of the point's velocity orthogonal to the edge
if (distance.Dot(velocity) >= 0) {return "Negatory.";} //if the orthogonal velocity component is pointing 'to the point,' it won't collide
var specificT = distance.magnitude/velocity.magnitude; //the time it'll take for the point to hit the edge, if it continues with it's current velocity
if (deltaT <= specificT) {return "Negatory.";} //if the point can't move far enough to cover the distance, it won't collide
//at this point, the collision will happen
Point.near = edge; //have the point remember that it collided with this edge, so it won't have to be totally re-tested for normal forces
Point.position = Point.position.Add(Point.velocity.Scale(specificT)).Add(distance.Scale(.0001)); //move the point just a wee bit away from the edge
vPrime = Point.velocity.Add(velocity.reverse); //impulse away the velocity orthogonal to the edge
Point.velocity = Point.velocity.Scale(0); //zero the current velocity
}
//Update Position
function updatePosition(Point) {Point.position = Point.position.Add(Point.velocity.Scale(deltaT));} //d=vt, essentially
//Update Velocity
function updateVelocity(Point) { //via forces
var gravity = new Vector(20,0); //gravity... hobviously
netForce = netForce.Add(gravity); //add up all the current forces to get the right normal force
if (Point.near != nullEdge) { //calculating normal force, so it needs to be near an edge
var startToPoint = Point.position.Subtract(Point.near.start);
var projection = Point.near.vector.Project(startToPoint); //same stuff as earlier
var distance = startToPoint.Subtract(projection);
if (distance.magnitude <= .01) { //if it's very near to the edge
normalForce = distance.Project(netForce.reverse); //exert enough force to cancel anything going into the edge
if (normalForce.Dot(distance) > 0) {netForce = netForce.Add(normalForce);} //if it is indeed going into the edge
} else if (distance.magnitude > 1) {Point.near = nullEdge;} //it's not near the edge any more
}
Point.velocity = Point.velocity.Add(netForce.Scale(deltaT/Point.mass)); //v=at, essentially
}
/*---------------------------------------------------------------------------------------------------------------------------------*/ }
/*----------------------------------------------------Graphics----------------------------------------------------------------------*/ {
var c = document.getElementById("canvas").getContext("2d"); //the means for drawing all this
PointObject.prototype.Draw = function() { //the draw method for point objects
c.fillStyle = "#000000"; //a black square with the point at its center pixel
c.fillRect(this.position.left-2,this.position.top-2,5,5);
}
Rectangle.prototype.Draw = function() { //draw method for rectangles
c.fillStyle = "#c0c0c0"; //a grey rectangle; the position is the top left corner
c.fillRect(this.position.left,this.position.top,this.width,this.height);
}
function draw() { //draws everything
c.clearRect(0,0,1366,768); //clear the screen
base.Draw(); //paint stuff
point.Draw();
}
/*----------------------------------------------------------------------------------------------------------------------------------*/ }
/*------------------------------------------------------------Math Tools-------------------------------------------------------------*/ {
//--Vector Tools--//
function Vector(top,left) { //a vector constructor, with all necessary vector operations
this.top = top; //the 'top' component, which points down
this.left = left; //the 'left' component, which points right
this.in = 0; //the 'in' component, which points out of the screen
this.magnitude = Math.sqrt(this.top*this.top+this.left*this.left); //the magnitude of the vector
this.reverse = new Vector(-this.top,-this.left); //the vector that points opposite of this vector
this.unit = this.Scale(1/this.magnitude); //the unit vector pointing in this vector's direction
this.Scale = Scale; //multiplying vectors by a constant
this.Add = Add; //easier vector addition
this.Subtract = Subtract; //and subtraction
this.Dot = Dot; //a dot product operation
this.Cross = Cross; //the cross product of two planar vectors; it returns the 'in' component of the resulting vector
this.Project = Project; //the projetion of the parameter vector onto this vector
function Scale(scalar) {return new Vector(scalar*this.top,scalar*this.left);}
function Add(vector) {return new Vector(this.top+vector.top,this.left+vector.left);}
function Subtract(vector) {return new Vector(this.top-vector.top,this.left-vector.left);} //the abovedescribed methods
function Dot(vector) {return this.top*vector.top+this.left*vector.left;}
function Cross(vector) {return this.top*vector.left-this.left*vector.top;}
function Project(vector) {return this.Scale(this.Dot(vector)/Math.pow(this.magnitude,2))}
}
var zeroVector = new Vector(0,0);
/*-----------------------------------------------------------------------------------------------------------------------------------*/ }
</script>
</html>
Anyway, second thing is about how I've written some bits of the Vector constructor, which may possibly somehow be causing my error. At various points I use 'new Vector()' in the properties and methods of the function, and I don't know if that's illegal or not. I think I've done it before without error, but I'm not sure.
Also, for the 'magnitude,' 'reverse,' and 'unit' properties, should I rephrase them as methods? I think the way they are they're being locked into the magnitude/reverse/unit vector of the vector as it is created, so if the top or left properties are changed, they'll return incorrect values. The only reason I haven't changed them yet is that they strike me more as properties than methods, just conceptually. It hasn't caused any problems yet or anything; just wondering.
If you want this on JSFiddle or something else like that, I'd be happy to oblige you.

How to rotate a rectangle around centroid in flex 3

I am using matrix.rotate method to rotate the rectangle (box in my case).
My rotate event looks like below
public function transformObject(transformEvent:TransformEvent):void{
var numChildrn:int = _markedObjectLayer.numChildren;
var tempMatrix: Matrix = null;
var tempx:Number;
var tempy:Number;
var tempHeight:Number;
var tempWidth:Number;
for(var i:int = 0; i < numChildrn; i++){
var chld:MarkedObject = ObjectLayer.getChildAt(i)
if (chld.selected){
var height:int = (BoxObject) chld.height;
var width:int = (BoxObject) chld.width;
tempMatrix = chld.transform.matrix;
tempHeight=height;
tempWidth=width;
tempMatrix = MatrixTransformer.transform(tempMatrix,transformEvent.angle);
tempMatrix.tx=tempx;
tempMatrix.ty=tempy
chld.transform.matrix = tempMatrix;
}
}
invalidateDisplayList();
}
}
The Matrix.transform method calls matrix.rotate method
public static function transform(sourceMatrix:Matrix,
rotation:Number=0 ):Matrix
{
sourceMatrix = MatrixTransformer.rotate(sourceMatrix, rotation, "degrees");
return sourceMatrix;
}
/**
* Rotates a matrix and returns the result. The unit parameter lets the user specify "degrees",
* "gradients", or "radians".
*/
public static function rotate(sourceMatrix:Matrix, angle:Number, unit:String = "radians"):Matrix {
if (unit == "degrees")
{
angle = Math.PI * 2 *( angle / 360);
}
sourceMatrix. rotate(angle)
return sourceMatrix;
}
The issue is that x and y are left corener of the box and hence it is rotating around left corner. However, if I try to give temp.x and temp.y as centroid value it does not rotate around centroid?
Can any one suggest what am I doing wrong here?
Thanks
Akshay
If you really want or have to use matrices directly, you can do this more conveniently using a built-in flash class: fl.motion.MatrixTransformer:
MatrixTransformer.rotateAroundInternalPoint(matrix, centroidX, centroidY, angleInDegrees);
See the Adobe docs on MatrixTransformer for more information.
However, if you don't need to use the transformation matrix, the simpler solution would be to:
have your objects drawn in such a way that (0, 0) is their centroid
use the simple rotation property from DisplayObject which achieves the same goal in a much simpler manner
Figured it out. It appears that I was not translating them to appropriate coordinate positions before and after rotation
//Step 1 Fix the co-ordinates of rectangle . I added them to an event so that they remain static
if (TransformEvent.X == 0 && TransformEvent.Y == 0)
{
TransformEvent.X = chld.x;
TransformEvent.Y = chld.y;
}
//next get the centroid of rectangle
tempx = TransformEvent.X + width/2;
tempy= TransformEvent.Y +height/2;
// Step 3: translate before rotation
tempMatrix.translate(-1*tempx,-1*tempy);
//Rotate the rectangle
tempMatrix = MatrixTransformer.transform(tempMatrix,transformEvent.angle);
//translate to centroid after rotation
tempMatrix.translate(tempx,tempy);
//assign back the matrix to the rectangle
chld.transform.matrix = tempMatrix;
Thanks for all your help. Also the this site helped me with translation bit
http://www.foxarc.com/blog/article/66.htm

Record Paper.js path object and redraw again later

I draw with a mouse Paper.js. I need to keep these strokes and replay them at the same rate as in the video replay. How can I accomplish this?
In paper.js, the onFrame() function is called up to 60 times per second, while the onMouseMove() function "is called when the mouse moves within the project view", and contains the position of the mouse. By using both functions you can store the mouse motions and replay them later with close to the same time between positions.
var mousePosition = null;
function onMouseMove(event) {
if (mousePosition != null) {
var path = new Path();
path.strokeColor = 'black';
path.moveTo(mousePosition);
path.lineTo(event.point);
}
mousePosition = event.point;
}
var recordedPositions = [];
var delayFrames = 60;
function onFrame(event) {
if (mousePosition != null) {
recordedPositions.push(mousePosition);
if (recordedPositions.length > delayFrames) {
var path = new Path();
path.strokeColor = 'red';
delayedPositionIndex = recordedPositions.length - delayFrames;
path.moveTo(recordedPositions[delayedPositionIndex - 1]);
path.lineTo(recordedPositions[delayedPositionIndex]);
}
}
}
I do not know the timing accuracy/resolution/dependability of onFrame(). Alternatively you could just use javascript timing events as in this answer: How can I use javascript timing to control on mouse stop and on mouse move events