How to determine a shape touches another shape or not using kineticjs? - html5-canvas

I have a number of shapes in my kinetc layer. If I drag and drop a shape somewhere else in the layer, how to determine the dropped shape touches another shape or not?

The thing you need to do is create a mathematical representation of the shapes you have. For most simple collision detection, you can use bounding-boxes.
Basically, if you have a circle, you can create a representation of it as being bounded in a box.
Then if you have a square, you can check if the bounding box of the square (which is the square itself) is intersecting with the bounding box of the circle.
I wrote an answer to this a while ago: HTML5 / kineticJS getIntersection function implementation
function checkCollide(pointX, pointY, objectx, objecty, objectw, objecth) { // pointX, pointY belong to one rectangle, while the object variables belong to another rectangle
var oTop = objecty;
var oLeft = objectx;
var oRight = objectx+objectw;
var oBottom = objecty+objecth;
if(pointX > oLeft && pointX < oRight){
if(pointY > oTop && pointY < oBottom ){
return 1;
}
}
else
return 0;
};
used like this:
var children = layer.getChildren();
for( var i=0; i<children.length; i++){ // for each single shape
for( var j=0; j<children.length; j++){ //check each other shape
if(i != j){ //skip if shape is the same
if(checkCollide(children[i].getX(), children[i].getY(), children[j].getX(), children[j].getY(), children[j].getWidth(), children[j].getHeight()))
alert('top left corner collided');
}
}
}
This works great if the shape you have is a rectangle of some sort, but not that great if you have two circles, as they have a radius. So this suffices for a quick check of collision, next you need another function which will check collisions more precisely.
You can also try using kineticjs with box2d, there are a bunch of tutorials out there on the topic.

Related

3D three.js Create the ground surface of a 3D building

Following my post last week three.js How to programatically produce a plane from dataset I come back to the community to solve a problem of definition of surface occupied on the ground by a 3D building.
The solution proposed in comments in this post works for this building but is not universal.
To make it universal I chose the following method: when the walls are built I create their clone in another group (see this previous post for walls creation)
// prepare the clones
var clones = new THREE.Group();
scene.add(clones);
var num=0;
// drawing the real walls
var wallGeometry = new THREE.PlaneGeometry(size,(hstair*batims[i][1]));
val = 0xFFFFFF;
opa = 0.5;
if(deltaX > deltaY){val = 0x000000; opa = 0.05;} // shaded wall
var wallMaterial = new THREE.MeshBasicMaterial({color:val,transparent:true, opacity:opa, side:THREE.DoubleSide});
var walls = new THREE.Mesh(wallGeometry, wallMaterial);
walls.position.set((startleft+endleft)/2,(hstair*batims[i][1])/2,(startop+endtop)/2);
walls.rotation.y = -rads;
scene.add(walls);
// add the pseudo-walls to scene
var cloneGeometry=new THREE.PlaneGeometry(long,3);
var cloneMaterial=new THREE.MeshBasicMaterial({color:0xff0000,transparent:true,opacity:0.5,side:THREE.DoubleSide});
var clone=new THREE.Mesh(pseudomursGeometry,pseudomursMaterial);
clone.position.set((startleft+endleft)/2,3,(startop+endtop)/2);
clone.rotation.y=-rads;
clones.add(clone);
num++;
The idea is now to rotate this pseudo-building so that the longest wall is vertical, which allows me to determine the exact floor area occupied with its boundingBox:
var angle=turn=0;
for(i=0; i<dists.length; i++) { // dists is the array of wall lengths
if(dists[i]==longs[0]){ // longs is the reordered lengths array
angle=angles[i][1]; // angle of the longest wall
}
}
// we can now rotate the whole group to put the longest wall vertical
if(angle>0){
turn = angle*-1+(Math.PI/2);
}
else {
turn = angle+(Math.PI/2);
}
clones.rotation.y=turn;
It works perfectly as long as the building has a right angle, whatever its shape: triangle, rectangle, bevel, right angle polygons,
var boundingBox = new THREE.Box3().setFromObject(clones);
var thisarea = boundingBox.getSize();
// area size gives the expected result
console.log('AREA SIZE = '+thisarea.x+' '+thisarea.y+' '+thisarea.z);
...but not when there are no more right angles, for example a trapezoid
The reason is that we rotate the group, and not the cloned walls. I can access and rotate each wall by
for(n=0;n<num;n++){
thisangle = clones.children[n].rotation.y;
clones.children[n].rotation.y = turn-thisangle;
}
But the result is wrong for the others pseudo-walls:
So the question is: how to turn each red pseudo-wall so that the longest one is vertical and the others remain correctly positioned in relation to it? In this way, any building with any shape can be reproduced in 3D with its internal equipment. Any idea on how to achieve this result?
A weird & ugly but well-working solution:
// 1. determines which is the longest side
for(i=0; i<dists.length; i++) {
if(dists[i]==longs[0]){
longest=i;
break; // avoid 2 values if rectangle
}
}
// 2. the group is rotated until the longest side has an angle in degrees
// close to 0 or 180
var letsturn = setInterval(function() {
clones.rotation.y += 0.01;
var group_rotation = THREE.Math.radToDeg(clones.rotation.y); // degrees
var stop = Math.round(angles[longest][0] - group_rotation);
// 3. stop when longest wall is vertical
if( (stop>=179 && stop<=181) || (stop>=-1 && stop<=1) ) {
clearInterval(letsturn);
createPlane() // we can now use boundingBox in reliability
}
}, 1);
et voilĂ .

Shape appears to have less vertexes than shape data THREE.JS

I'm trying to create a smooth "wave" when the mouse moves over isometric logo shape.
I've created in in processing now I'm trying to recreate it in THREE.js
The shape acts strangely - the shape doesn't look as smooth when elevated compared to the processing sketch. If you look at the edges you can see segments that are not supposed to be there. I'm not sure what causes this.
Basically the shape is created through a loops that goes over 2 arrays:
for (var i = 0; i < xpos0.length; i++) {
shape.lineTo(xpos0[i], ypos0[i]);
}
Then it animates through another for loop that checks the distance between verteces[i].x and mouse location intersection with the ground
for (let p = 0; p < mesh.geometry.vertices.length; p=p+1) {
let delta = Math.abs(mesh.geometry.vertices[p].x - intersects[0].point.x);
mesh.geometry.vertices[p].z = bump2(-2, 2000, -1, 2, delta);
}
z value is calculated through this function:
function bump2(a,b,c,d,xval) {
xval = parseFloat(xval);
// console.log(typeof xval);
return Math.exp(a / (-xval * xval / b + c) + d) * -1;
}
https://codepen.io/NotYetDesignLab/pen/JjYaqRJ
How it looks on THREE.JS
notice how some segments appear "broken", like it's made of stiff parts instead of the many points that make up the segment in the array and give the illusion of "paper".
THIS IS HOW IT'S SUPPOSED TO LOOK: (Processing/java)
This has been done using Processing. Notice how the elevation of the edges is smooth and not broken.

Algorithm: How to disperse smaller spheres into a direction within a large sphere

I am trying to write a C source code visualization program which I expect to draw out function hierarchy using spheres inside spheres.
For a simple example, in code like this:
#include "stdio.h"
int pow(int base, int power) {
while(--power) {
base*=base;
}
return base;
}
int checkOdd(int i) {
if (i%2==0) return 0;
else return 1;
}
int checkPrime(int i) {
int j = i;
if (!checkOdd(i)) {
return 0;
}
for(j=1; j<i/2; j++) {
if (i%j==0) {
return 0;
}
}
return 1;
}
int main() {
int a = 3;
int b = 2;
int res = pow(a,b);
int bl = checkPrime(res);
printf("%d",res);
return 1;
}
The largest sphere which is the main function has two functions inside it, pow and checkPrime, which are two spheres inside main's sphere. Checkprime function's sphere has checkOdd's sphere in it.
I would like it so that the children spheres are somewhat clumped together in one side of the larger sphere, because I would like some space left out for putting in other things. However, the spheres must not touch each other, and the radius of the spheres are pre-determined and can not change to accomodate drawing accurately. I need an algorithm which determines the perfect center coordinates which would allow the smaller spheres not to touch each other while still being collected to one side of the larger sphere.
I have a 3D vector which shows the direction at which the smaller spheres must be concentrated in, looking from the center of the larger sphere. In the case of the picture, my 3D vector is facing bottom-down in a 2D-sense looking at the screen.
Currently my algorithm produces this by dispersing the sphere's center around a circle projected onto the larger sphere's surface, but it fails as the spheres overlap. Can anyone enlighten me with a way to disperse smaller spheres to one direction within the larger sphere?
I am using OpenGL and I prepared a function which can draw those transparent mesh spheres by feeding center coordinate and radius. I have knowledge of parent sphere's center and radius in designing this algorithm.

How to smooth the blocks of a 3D voxel world?

In my (Minecraft-like) 3D voxel world, I want to smooth the shapes for more natural visuals. Let's look at this example in 2D first.
Left is how the world looks without any smoothing. The terrain data is binary and each voxel is rendered as a unit size cube.
In the center you can see a naive circular smoothing. It only takes the four directly adjacent blocks into account. It is still not very natural looking. Moreover, I'd like to have flat 45-degree slopes emerge.
On the right you can see a smoothing algorithm I came up with. It takes the eight direct and diagonal neighbors into account in order to come up with the shape of a block. I have the C++ code online. Here is the code that comes up with the control points that the bezier curve is drawn along.
#include <iostream>
using namespace std;
using namespace glm;
list<list<dvec2>> Points::find(ivec2 block)
{
// Control points
list<list<ivec2>> lines;
list<ivec2> *line = nullptr;
// Fetch blocks, neighbours start top left and count
// around the center block clock wise
int center = m_blocks->get(block);
int neighs[8];
for (int i = 0; i < 8; i++) {
auto coord = blockFromIndex(i);
neighs[i] = m_blocks->get(block + coord);
}
// Iterate over neighbour blocks
for (int i = 0; i < 8; i++) {
int current = neighs[i];
int next = neighs[(i + 1) % 8];
bool is_side = (((i + 1) % 2) == 0);
bool is_corner = (((i + 1) % 2) == 1);
if (line) {
// Border between air and ground needs a line
if (current != center) {
// Sides are cool, but corners get skipped when they don't
// stop a line
if (is_side || next == center)
line->push_back(blockFromIndex(i));
} else if (center || is_side || next == center) {
// Stop line since we found an end of the border. Always
// stop for ground blocks here, since they connect over
// corners so there must be open docking sites
line = nullptr;
}
} else {
// Start a new line for the border between air and ground that
// just appeared. However, corners get skipped if they don't
// end a line.
if (current != center) {
lines.emplace_back();
line = &lines.back();
line->push_back(blockFromIndex(i));
}
}
}
// Merge last line with first if touching. Only close around a differing corner for air
// blocks.
if (neighs[7] != center && (neighs[0] != center || (!center && neighs[1] != center))) {
// Skip first corner if enclosed
if (neighs[0] != center && neighs[1] != center)
lines.front().pop_front();
if (lines.size() == 1) {
// Close circle
auto first_point = lines.front().front();
lines.front().push_back(first_point);
} else {
// Insert last line into first one
lines.front().insert(lines.front().begin(), line->begin(), line->end());
lines.pop_back();
}
}
// Discard lines with too few points
auto i = lines.begin();
while (i != lines.end()) {
if (i->size() < 2)
lines.erase(i++);
else
++i;
}
// Convert to concrete points for output
list<list<dvec2>> points;
for (auto &line : lines) {
points.emplace_back();
for (auto &neighbour : line)
points.back().push_back(pointTowards(neighbour));
}
return points;
}
glm::ivec2 Points::blockFromIndex(int i)
{
// Returns first positive representant, we need this so that the
// conditions below "wrap around"
auto modulo = [](int i, int n) { return (i % n + n) % n; };
ivec2 block(0, 0);
// For two indices, zero is right so skip
if (modulo(i - 1, 4))
// The others are either 1 or -1
block.x = modulo(i - 1, 8) / 4 ? -1 : 1;
// Other axis is same sequence but shifted
if (modulo(i - 3, 4))
block.y = modulo(i - 3, 8) / 4 ? -1 : 1;
return block;
}
dvec2 Points::pointTowards(ivec2 neighbour)
{
dvec2 point;
point.x = static_cast<double>(neighbour.x);
point.y = static_cast<double>(neighbour.y);
// Convert from neighbour space into
// drawing space of the block
point *= 0.5;
point += dvec2(.5);
return point;
}
However, this is still in 2D. How to translate this algorithm into three dimensions?
You should probably have a look at the marching cubes algorithm and work from there. You can easily control the smoothness of the resulting blob:
Imagine that each voxel defines a field, with a high density at it's center, slowly fading to nothing as you move away from the center. For example, you could use a function that is 1 inside a voxel and goes to 0 two voxels away. No matter what exact function you choose, make sure that it's only non-zero inside a limited (preferrably small) area.
For each point, sum the densities of all fields.
Use the marching cubes algorithm on the sum of those fields
Use a high resolution mesh for the algorithm
In order to change the look/smoothness you change the density function and the threshold of the marching cubes algorithm. A possible extension to marching cubes to create smoother meshes is the following idea: Imagine that you encounter two points on an edge of a cube, where one point lies inside your volume (above a threshold) and the other outside (under the threshold). In this case many marching cubes algorithms place the boundary exactly at the middle of the edge. One can calculate the exact boundary point - this gets rid of aliasing.
Also I would recommend that you run a mesh simplification algorithm after that. Using marching cubes results in meshes with many unnecessary triangles.
As an alternative to my answer above: You could also use NURBS or any algorithm for subdivision surfaces. Especially the subdivision surfaces algorithms are spezialized to smooth meshes. Depending on the algorithm and it's configuration you will get smoother versions of your original mesh with
the same volume
the same surface
the same silhouette
and so on.
Use 3D implementations for Biezer curves known as Biezer surfaces or use the B-Spline Surface algorithms explained:
here
or
here

Ball and brick collision handling

I have made the game, "Breakout". A small fun side-project.
Now, I usually do not make games, so collision-handling is not something I normally think about.
I have a paddle, a ball and some bricks.
For now, when there is a collision (I draw rectangles around each of the objects mentioned), I simply change the Y value of the ball to -Y.
This works fine, EXCEPT if the ball hits a brick from the side (either East or West). The side-effect is not pretty and ruins the gameplay.
I think I can safely assume that instead of the above technique, I need to change the X value to -X when this happens.
So far I have: if (ballRect.IntersectsWith(brickRect))
ballRect and brickRect being rectangles around each object.
Now, what if I created a rectangle around the eastern border of the brick, the western border, etc? I guess the width would be about a pixel.
If collision happens with western or eastern rectangle, then the balls X value should be -X.
And vice versa.
What about the corners though? Should I just randomly choose which rectangle to control of x corner?
Or perhaps should I make a rectangle around each corner? the rectangle being 1*1 in side.
If there is a collision => -x AND -y values of the ball?
Please share your thoughts.
Here is the process so far:
foreach (var brick in Bricks)
{
if (brick.IsAlive)
{
var brickRect = new Rectangle(brick.X, brick.Y, BrickWidth, BrickHeight);
if (ballRect.IntersectsWith(brickRect)) //Ball has hit brick. lets find out which side of the brick
{
var brickRectNorth = new Rectangle(brick.X, brick.Y + BrickHeight, BrickWidth, 1);
var brickRectSouth = new Rectangle(brick.X, brick.Y, BrickWidth, 1);
var brickRectEast = new Rectangle(brick.X, brick.Y, 1, BrickHeight);
var brickRectWest = new Rectangle(brick.X + BrickWidth, brick.Y, 1, BrickHeight);
if (ballRect.IntersectsWith(brickRectNorth) || ballRect.IntersectsWith(brickRectSouth))
{
//STUFF that makes ball.y = -ball.y
}
if (ballRect.IntersectsWith(brickRectWest) || ballRect.IntersectsWith(brickRectEast))
{
//STUFF that makes ball.x = -ball.x
}
}
}
}
Rather than looking for rectangle intersections, I'd intersect the actual edges. At the corner, your ball is touching two edges simultaneously, so its motion vector should be affected by both.
I would keep the single rectangle for collision detection, since that reduces the number of rectangles you need to test in your outer loop, but then once a collision with a brick has been detected, go into an inner loop to detect which edge it was that was hit. If you just test each edge and adjust the vector accordingly for each one, the corner will come for free (as long as you don't break out of the loop when you find the first intersecting edge).
Edit: In response to your updated question:
Actually, this is how I would do it (given your code, this appears to be C# 3.0, so that's what I've assumed below):
foreach(var brick in Bricks) {
if(brick.IsAlive) {
var brickRect = new Rectangle(brick.X, brick.Y, BrickWidth, BrickHeight);
if(ballRect.IntersectsWith(brickRect)) {
// Ball has hit brick. Now let's adjust the ball's vector accordingly
// Convenience variables. Compiler will probably inline.
var brickLeft = brick.X;
var brickRight = brick.X + BrickWidth;
var brickTop = brick.Y;
var brickBottom = brick.Y + BrickHeight;
var ballLeft = ball.X - ball.Radius;
var ballRight = ball.X + ball.Radius;
var ballTop = ball.Y - ball.Radius;
var ballBottom = ball.Y + ball.Radius;
// Test which vector(s) we need to flip
bool flipX = (ballRight >= brickLeft || ballLeft <= brickRight);
bool flipY = (ballTop >= brickBottom || ballBottom <= brickTop);
// Flip the vectors (there are probably ways to optimize this,
// too, but without seeing your code I can't tell).
if(flipY) {
// Stuff that makes ball.y = -ball.y
}
if(flipX) {
// Stuff that makes ball.x = -ball.x
}
}
}
}
Basically, the point is that since you already know the ball actually intersects the brick, you can simplify to a simple box test, which is much faster. Also, there's no need to create extra rectangles for the edges -- just use the edges of the rectangle you already have.

Resources