Animation and randomiser using html/ js - javascript

I have a page of code in which i want 3 "ghost.png" to be displayed onto a canvas with random coordinates using math.random at a press of a button. Beyond that im also trying to use another function to draw "sac.jpg" onto the canvas aswell as drawing the same ghosts on the same positions as they have been determined by math.random. then in the same function, i want to be able to animate the image "sac.png" using the arrow keys on the keyboard without making the ghost image move along with it. With this goal, i tried to create a code but it does not seem to work. can someone explain?
recap:
function hasard (activates when button is pressed):
a) math.random 6 times to choose x,y coordinates of 3 of the same image
b) place the image in a variable
function dessiner (activates when arrow key is pressed):
a) draw background
b) draw the image from function hasard in the same spot each time until i press the button from the first function to randomize a new pair of coordinates.
c) draw the image "sac.gif" and program it to be able to move using arrow keys.
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="Jeu.css">
</head>
<body>
<canvas id="canvas" width="400" height="400"
style="border-color: 'black'; border-width: 3px; border-style: solid">
</canvas>
<br>
<button type="button"onclick="hasard()"><img src="start.jpg"></button>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var contexte = canvas.getContext("2d");
var x;
var y;
var x1;
var y1;
var x2;
var y2;
var ghost = new Image();
ghost.src = "ghost.png";
function hasard(){
x = 32 +(Math.random() * (400-64));
y = 32 +(Math.random() * (400-64));
x1 = 32 +(Math.random() * (400-64));
y1 = 32 +(Math.random() * (400-64));
x2 = 32 +(Math.random() * (400-64));
y2 = 32 +(Math.random() * (400-64));
contexte.drawImage(ghost,x,y,60,60)
contexte.drawImage(ghost,x1,y1,60,60)
contexte.drawImage(ghost,x2,y2,60,60)
};
var bg = new Image();
bg.src = 'haunted.jpg';
var sac = new Image();
sac.src = "sac.gif";
var a=100;
var b=100;
var dx=0;
var dy=0;
T_fleche_gauche = 37;
T_fleche_droite = 39;
T_fleche_haut = 38;
T_fleche_bas = 40;
document.onkeydown = miseAJourTouche;
function miseAJourTouche(e){
toucheCourante = e.keyCode;
if (toucheCourante == T_fleche_gauche){
dx= -1;
dy=0;
draw(dx,dy);
}
if (toucheCourante == T_fleche_droite){
dx= 1;
dy=0;
draw(dx,dy);
}
if (toucheCourante == T_fleche_haut){
dy= -1;
dx=0;
draw(dx,dy);
}
if (toucheCourante == T_fleche_bas){
dy= 1;
dx=0;
draw(dx,dy);
}
}
function dessiner(x,y){
bg.addEventListener('load', function() {
contexte.drawImage(bg, 100, 20, 200, 200);
image.onload = function(){
contexte.drawImage(ghost,x,y,60,60)
contexte.drawImage(ghost,x1,y1,60,60)
contexte.drawImage(ghost,x2,y2,60,60)
image.onload = function(){
context.drawImage(sac, 0, 0, 70,90);
context.translate(10+a,10+b);
a = a+dx;
b = b+dy;
if (a > 400) a = -80; if (a <-80) a = 400;
if (b > 400) b = -40; if (b <-40) b = 400;
}
window.requestAnimFrame(function() { dessiner(dx,dy) });
}
dessiner();
};
</script>
</body>
</html>

From what I can tell, you are trying to animate ghosts and bag, with the bag being the player controllable item.
While I can't debug the program for you, I can help telling you to use the dev tools of your browser. F12 or Fn + F12 will bring you to the Inspector, where one of the other tabs is console.
Now, in your program, I see you assign image.onload to two functions, with one of them missing a closing curly brace.
image.onload = function(){
contexte.drawImage(ghost,x,y,60,60)
contexte.drawImage(ghost,x1,y1,60,60)
contexte.drawImage(ghost,x2,y2,60,60)
image.onload = function(){
context.drawImage(sac, 0, 0, 70,90);
context.translate(10+a,10+b);
a = a+dx;
b = b+dy;
if (a > 400) a = -80; if (a <-80) a = 400;
if (b > 400) b = -40; if (b <-40) b = 400;
}
I would add a curly brace after the three calls to contexte.drawImage, but I question the choice for two assignments. Also, I don't think image is declared in this scope, but I might be wrong. That's all I see.

If I understand well, you want to draw 3 ghosts with random positions, and a bag also at a random position, and would like to be able to move it with the arrow keys, is that right?
Then, I may suggest several things:
Don't put the update and drawing codes together. You have a drawing function dessiner(x, y) but you also draw in the hasard() and miseAJourTouche(e) functions. This makes things confusing and doesn't help debugging.
Factorize more: for example, in your hasard() function, you makes the calculations 32 +(Math.random() * (400-64)); 6 times. Instead, you could use a function to generate a random number between two values, then initialize your values in an init() function. You can initialize all the variables inside as well as load your images. Depending on what you aim to make, you could also use objects, like a Ghost object that would initialize its coordinates, with its own draw() method, etc. It could be much simpler for the rest.
Be consistent: if you put spaces before and after a +, then do it all the time. Don't use multiple languages inside the same code, you used both English and French (and English makes things easier when asking for help). Also, you can use a tool such as your IDE beautifier function or an online one (I used https://beautifier.io/) to make your code more readable or spot typing issues, like missing curly braces.
I took the liberty of refactoring your code a bit: https://jsfiddle.net/nmerinian/t0c3sh8f/4/
Notes:
I didn't write any condition to prevent the refresh if no key is
pressed, but it's easy to add.
I commented the background drawing part since I don't have the image.
I also commented some variables I didn't use.
I hope this helps.

Related

P5.js Drawing new shapes is causing the older shapes to disappear

i’m working on a complex visualisation project, using p5.js i want to create multiple clusters of shapes to visualise all sorts of data, so i’m looping through the data, checking the objects specified by user and drawing them to canvas, this happens in a nested for loop…the problem i’m facing is when an inner loop is done drawing a cluster of shapes and the overall loop continues and re-enters the inner loop again to draw the next cluster, the older cluster of drawn shapes disappears…i don’t understand why, i thought this had to do with that the shapes are related to the inner loop context/scope and tried to recreate the problem based on that but it appears that this is not the case.
this code for example works perfectly, it draws 5 circles on 20 lines, run by a nested loop
function setup() {
createCanvas(window.innerWidth, window.innerHeight).parent('myContainer');
}
function draw() {
background(220);
x = 100;
y = 100;
for (let i = 1; i <= 20; i++) {
for(let j=1;j<=5;j++){
fill(color(0, 255, 0));
stroke(0);
ellipse(x, y, 80);
x += 90;
}
x = 100;
y += 90;
}
}
while in my code, after the inner loop moves to the next cluster the previous shapes just disappear and only the last cluster is shown…i did a lot of console logging and debugging and made sure that every cluster is actually getting drawn but it just disappears when a new one is created…can anyone please help?
is there anyway to emphasise the library to draw a NEW separate shape…like this?
new ellipse(x,y,rad)
this is my project’s code, it shows where the bug happens
function setup() {
createCanvas(viewWidth, viewHeight).parent('myContainer');
}
function draw() {
//code...
var objects_len = objects.length;
for (var cluster_index = 1; cluster_index < cluster_len; cluster_index++) {
array_center = partition(cluster_index - 1, cluster_len - 1);
for (var object_index = 0; object_index < objects_len; object_index++) {
if (!objects[object_index].deleted) {
draw_simple_object(objects[object_index], data, cluster_index, array_center, cluster_len);
}
}
addClusterName(cluster_index, data, array_center);
}
function draw_simple_object(object, data, cluster_index, array_center, cluster_len) {
.
.
.
//this is where the drawing happens
var center_shape = [array_center[0] + object.centerOffsetX * array_center[2], array_center[1] + object.centerOffsetY * array_center[3]];
if (object.shape === 'ellipse' && enable) {
var size_min = Math.min(array_center[2], array_center[3]) * 2;
fill(colorFill);
stroke(object.colorBorder);
ellipse(center_shape[0], center_shape[1], size_min * width * proportion, size_min * length * proportion);
}
.
.
.
}
}
please help me
Can it be because you are calling the background() function inside the loop? (that part is actually not shown in your snippet)
Solved.
i was using resizeCanvas() in one of the function inside draw() which cleared all content off the canvas before resizing. removing resizeCanvas solves the problem.

What is wrong with my javascript object?

I have just started learning OOP in javascript and I am trying to re-write a simple program using OOP that I had previously written as a procedural program. The program is a reaction tester in which a random shape appears on the screen and the user must click it as quickly as possible. After clicking the shape, the time in seconds that it took for the user to respond is displayed.
I have not gotten very far, I am just trying to make a square of random size and random color appear on the screen, but I can't even manage that. See my code below:
<script type="text/javascript">
function Shape () {
this.x = Math.floor(Math.random()*850);
this.y = Math.floor(Math.random()*850);
this.draw();
}
Shape.prototype.draw = function() {
var shapeHtml = '<div></div>';
var widthAndHeight = Math.floor(Math.random()*400);
var left = Math.floor(Math.random()*850);
var top = Math.floor(Math.random()*850);
this.shapeElement = $(shapeHtml);
this.shapeElement.css({
position: "relative",
left: this.left,
top: this.top,
width: widthAndHeight,
height: widthAndHeight,
});
$("body").append(this.shapeElement);
}
Shape.prototype.colour = function() {
var colours = '0123456789ABCDEF'.split('');
var randomColour = "#";
for (i = 0; i < 6; i++) {
randomColour+=colours[Math.floor(Math.random()*16)];
};
this.shapeElement.css({backgroundColor: 'randomColour'});
}
var square = new Shape();
</script
So far, no square will appear on the screen. All that happens is a div of a random size is appended, but it is always in the upper-left position and has no background color. The console is not helping me because it is not showing that there are any errors in my code. I am extremely confused and finding the transition to OOP is extremely confusing. Any help in understanding why this won't work would be extremely appreciated!
Several small errors:
Warning: function Shape sets up x and y properties that are not used.
Error: Shape.prototype.draw defines variables left and top but refers to them as this.left and this.top in the CSS object initializer. As properties they are undefined - take out the two this. qualifiers.
Error: Shape.prototype.colour is not called, so the DIV elements are transparent. Insert a call this.colour() after, say, setting the CSS.
Error: The css initialiser object value for background color should be the variable name, randomColour not the string literal 'randomColour'. Remove the quote marks from around the identifier.
Severe warning: the for loop in the colour function does not declare i and creates it as an implicit global variable. Insert "use strict"; at the beginning of script files or function bodies to generate an error for undeclared variables.
In summary none of the errors generate errors on the console (undefined CSS values are ignored) but work to prevent the code working.
There are number of issues.
1) colour() method is never called.
2) Referring this.top and this.left inside the css construct won't work either.
3) randomColour is a variable, not a string literal.
Fixed the issues and embedded the code here. Have a look.
function Shape () {
this.x = Math.floor(Math.random()*850);
this.y = Math.floor(Math.random()*850);
}
Shape.prototype.draw = function() {
var shapeHtml = '<div></div>';
var widthAndHeight = Math.floor(Math.random()*400);
var left = Math.floor(Math.random()*850);
var top = Math.floor(Math.random()*850);
this.shapeElement = $(shapeHtml);
this.shapeElement.css({
'margin-left': left,
'margin-top': top,
'width': widthAndHeight,
'height': widthAndHeight,
});
$("body").append(this.shapeElement);
}
Shape.prototype.colour = function() {
var colours = '0123456789ABCDEF'.split('');
var randomColour = "#";
for (i = 0; i < 6; i++) {
randomColour+=colours[Math.floor(Math.random()*16)];
};
this.shapeElement.css({backgroundColor: randomColour});
}
$(document).ready(function() {
var square = new Shape();
square.draw();
square.colour();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Shape</title>
</head>
<body>
<div></div>
</body>
</html>

Drag and Drop not recognizing child of drag object in Animate CC

I'm trying to make a drag and drop, but it's been giving me a bunch of issues. I fix one and another comes up. I had it working where it would see if any part of my drag object entered a target area, but I wanted it to just recognize one part (it's graphic of a pointy thermometer, and you can't measure temperature with the head in real life) demo here.
The error I'm getting is that "Uncaught TypeError: Cannot read property 'drag' of undefined" (I labeled 'drag' on the demo, but its a child movieclip inside the drag object)
also, 'thermometer' and 'drag' are both named instances of movieclips.
The Code:
var dragger = this.thermometer;
//tried this to see if it would help
var tip = this.thermometer.drag;
var right = this.targetRight;
var wrong = this.targetWrong;
For moving it:
dragger.on("pressmove", function(evt){
evt.currentTarget.x = evt.stageX;
evt.currentTarget.y = evt.stageY;
if(intersect(tip, right)){
evt.currentTarget.alpha=0.2;
}
else if(intersect(tip, wrong)){
evt.currentTarget.alpha=0.7;
}
else{
evt.currentTarget.alpha=1;
}
stage.update(evt);
}, this);
For releasing it
dragger.on("pressup", function(evt){
//lock position of drag object and play animation if any
dragger.x = dragger.x;
dragger.y = dragger.y;
if(hitTestArray.length > 1){
dragger.alpha = 1;
stage.update(evt);
}//else{
if(intersect(tip, right)){ //Intersection testing for good (also tried 'dragger.drag' to see if that would work. it didn't)
alert("YAY you're right AND it works!");
dragger.alpha = 1;
}else if(intersect(tip, wrong)){ //intersection Testing for bad
alert("BOO its wrong, but YAY it works");
dragger.alpha = 1;
}
stage.update(evt);
//}
}, this);
UPDATED INTERSECT:
for testing intersection.
function intersect(obj1, obj2){
var objBounds1 = obj1.nominalBounds.clone();
var objBounds2 = obj2.nominalBounds.clone();
var pt = obj1.globalToLocal(objBounds2.x, objBounds2.y);
var h1 = -(objBounds1.height / 2 + objBounds2.height);
var h2 = objBounds2.height / 2;
var w1 = -(objBounds1.width / 2 + objBounds2.width);
var w2 = objBounds2.width / 2;
if(pt.x > w2 || pt.x < w1) return false;
if(pt.y > h2 || pt.y < h1) return false;
return true;
}
To sum up, I need to know how to make it not undefined so that I can test for that little box being in one of the big boxes.
The error is happening because you used this.currentTarget instead of evt.currentTarget on that one line.
Note that your actual code is not the same as the code you posted above. Here is the code in the live demo:
if(intersect(this.currentTarget.drag, right)){
evt.currentTarget.alpha=0.2;
} else if(intersect(this.currentTarget.drag, wrong)){
evt.currentTarget.alpha=0.7;
}
else{
evt.currentTarget.alpha=1;
}
Not sure if this will solve all your issues, but it should at least get you moving forward.
[UPDATE]
Looking a little deeper, there a number of issues that are likely contributing to your intersect function not working:
Your right/left bounds are not correct. EaselJS objects do not have a width or height (more info), so the bounds you set just have an x and y.
You can use nominalBounds to get the proper bounds. This provides the untransformed, original bounds of the symbol. You will have to account for any scaling. In this case, the bounds are:
* left: {x: 0, y: 0, width: 275, height: 300}
* right: {x: 0, y: 0, width: 413, height: 430}
Your intersection will have to consider the display list hierarchy. Specifically, when comparing position and size, they should be relative to each other. If your drag target is positioned inside another clip, it will need to consider the parent positioning. I recommend always doing localToGlobal on coordinates when comparing them.
Example:
// Find the clip's top/left position in the global scope
var p = myContainer.localToGlobal(myClip.x, myClip.y);
// OR
// Find the clip's position in the global scope
var p = myClip.localToGlobal(0, 0);

canvas class javascript

I'm having trouble with my javascript code. I'm trying to create a moving set of circles where each circle has their own attributes. So far I've managed to input all the needed values into an array, but I can't figure out how to use them properly for drawing on canvas.
Here's the javascript:
var radius = 10;
var step = x = y = 0;
var r = g = b = 255;
var circleHolder = [];
var loop = setInterval(function(){update();}, 30);
function Circle(x, y, radius, r, g, b)
{
this.x = x;
this.y = y;
this.radius = radius;
this.r = r;
this.g = g;
this.b = b;
circleHolder.push(this);
}
Circle.prototype.draw = function()
{
Circle.prototype.ctx = document.getElementById("MyCanvas").getContext("2d");
Circle.prototype.ctx.clearRect(0,0,720,720); // clear canvas
Circle.prototype.ctx.beginPath();
Circle.prototype.ctx.strokeStyle = "rgb("+ this.r +", "+ this.g +", "+ this.b +")";
Circle.prototype.ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
Circle.prototype.ctx.stroke();
}
Circle.prototype.update = function ()
{
step += .02;
step %= 2 * Math.PI;
this.x = parseInt((Math.sin(step)) * 150) + 360;
this.y = parseInt((Math.cos(step)) * 150) + 360;
this.radius += 16;
if (this.radius > 200)
{
for (i in circleHolder)
{
if (circleHolder[i]==this)
{
circleHolder.splice(i, 1);
}
}
}
}
function update()
{
var ci = new Circle(x, y, radius, r, g, b);
for (i in circleHolder)
{
ci = circleHolder[i];
ci.update();
ci.draw();
}
}
I'm pretty sure my problem lies within update() {} but I can't figure out how to do it properly.
EDIT: Okay, I've got it working with some changes! Check this Fiddle! I'm getting "ci not defined" error in the console though, and it has a strange bug: Changing the "if (this.radius > 128)" to higher integer it will make the circles spin faster, I don't know why. If you want you can try to change it to 256 and see what happens.
for (var i=0; i < allCircles; i++)
{
ci = circleHolder[i]; <----- This is causing the error
ci.update();
ci.draw();
}
it's not 100% clear to me what you're trying to do, but I tried to fix the main problem
One problem is your for loop.. you shouldn't use for in for arrays, do this instead:
for (var i=0 ; i<circleHolder.length ; i++)
{
ci = circleHolder[i];
ci.update();
ci.draw();
}
see this fiddle
Also I moved your get context and other things that should happen only once into the constructor, instead of having it in the update function.
You're also clearing the canvas before each draw, so the it will only show the last drawn circle per frame. (if you remove the clearRect it looks like one of those old spirographs).
You were also drawing the circles with (255,255,255)(white) so it wasn't showing until the color was changed.
Edit:
Really there are a few problems with this code:
The context shouldn't be inside a circle class if you plan on having many of them.
You should have some object which contains the canvas/context and an array of all circles.
Then have that object manage the updating/drawing.
For starters, unless there's something else going on, outside of this code:
You are using for ... in ... on an array, for-in is for objects, when used on arrays, most browsers will include methods like .splice and .forEach, and not just the numeric 0...n index.
function splice () {}.draw(); doesn't end well.
Also, what is the colour of your page's background? You're setting the rgb colour of each circle to 100% white. You're also clearing the canvas... ...which might well mean that the whole thing is transparent. So if you've got a transparent canvas, white circles and a white background, chances are great you're not going to be seeing anything at all, if this is even working without spitting out an error.
It might make a lot more sense to move your logic around in a way that lets you follow what's going on.
If you make a circle constructor, don't have it do anything but make a new circle.
Inside of your update, create a circle.
THEN put it inside of your circle collection (not in the circle constructor).
In a large application, you will typically call update on ALL objects, and then call draw on ALL objects, rather than updating and drawing one at a time.
Imagine a game that didn't bother to check if you had been hit by a bullet before drawing you and letting you move, for instance.
So inside of your loop, you should have an update and a draw.
Inside of the update, create your circles add them to the list and update the positions of them.
Inside of the draw, draw the circles.
In the future, this will give you the benefit of having things like collision-detection, without having to redraw everything, multiple times per frame.
Also, don't do DOM-access inside of a function that's going to be called many, many times (Circle.draw).
That will demolish your framerate in the future.
Instead, pass the function a dependency (the canvas).
// inside of the main game's scope
var screen = document.getElementById(...).getContext("2d");
// inside of your new draw function, in the animation/game loop
var i = 0, allCircles = circleHolder.length, currentCircle;
for (; i < allCircles; i += 1) {
currentCircle = circleHolder[i];
currentCircle.draw(screen);
}

JavaScript: Collision detection

How does collision detection work in JavaScript?
I can't use jQuery or gameQuery - already using prototype - so, I'm looking for something very simple. I am not asking for complete solution, just point me to the right direction.
Let's say there's:
<div id="ball"></div>
and
<div id="someobject0"></div>
Now the ball is moving (any direction). "Someobject"(0-X) is already pre-defined and there's 20-60 of them randomly positioned like this:
#someobject {position: absolute; top: RNDpx; left: RNDpx;}
I can create an array with "someobject(X)" positions and test collision while the "ball" is moving... Something like:
for(var c=0; c<objposArray.length; c++){
........ and code to check ball's current position vs all objects one by one....
}
But I guess this would be a "noob" solution and it looks pretty slow.
Is there anything better?
Here's a very simple bounding rectangle routine. It expects both a and b to be objects with x, y, width and height properties:
function isCollide(a, b) {
return !(
((a.y + a.height) < (b.y)) ||
(a.y > (b.y + b.height)) ||
((a.x + a.width) < b.x) ||
(a.x > (b.x + b.width))
);
}
To see this function in action, here's a codepen graciously made by #MixerOID.
An answer without jQuery, with HTML elements as parameters:
This is a better approach that checks the real position of the elements as they are being shown on the viewport, even if they're absolute, relative or have been manipulated via transformations:
function isCollide(a, b) {
var aRect = a.getBoundingClientRect();
var bRect = b.getBoundingClientRect();
return !(
((aRect.top + aRect.height) < (bRect.top)) ||
(aRect.top > (bRect.top + bRect.height)) ||
((aRect.left + aRect.width) < bRect.left) ||
(aRect.left > (bRect.left + bRect.width))
);
}
The first thing to have is the actual function that will detect whether you have a collision between the ball and the object.
For the sake of performance it will be great to implement some crude collision detecting technique, e.g., bounding rectangles, and a more accurate one if needed in case you have collision detected, so that your function will run a little bit quicker but using exactly the same loop.
Another option that can help to increase performance is to do some pre-processing with the objects you have. For example you can break the whole area into cells like a generic table and store the appropriate object that are contained within the particular cells. Therefore to detect the collision you are detecting the cells occupied by the ball, get the objects from those cells and use your collision-detecting function.
To speed it up even more you can implement 2d-tree, quadtree or R-tree.
You can try jquery-collision. Full disclosure: I just wrote this and released it. I didn't find a solution, so I wrote it myself.
It allows you to do:
var hit_list = $("#ball").collision("#someobject0");
which will return all the "#someobject0"'s that overlap with "#ball".
Mozilla has a good article on this, with the code shown below.
2D collision detection
Rectangle collision
if (rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x &&
rect1.y < rect2.y + rect2.height &&
rect1.height + rect1.y > rect2.y) {
// Collision detected!
}
Circle collision
if (distance < circle1.radius + circle2.radius) {
// Collision detected!
}
bcm's answer, which has 0 votes at this time, is actually a great, under-appreciated answer. It uses good old Pythagoras to detect when objects are closer than their combined bounding circles. Simple collision detection often uses rectangular collision detection, which is fine if your sprites tend to be, well, rectangular. If they are circular (or otherwise less than rectangular), such as a ball, an asteroid, or any other shape where the extreme corners are usually transparent, you may find this efficient routine to be the most accurate.
But for clarity, here is a more fully realized version of the code:
function doCollide(x1, y1, w1, x2, y2, w2) {
var xd = x1 - x2;
var yd = y1 - y2;
var wt = w2 + w1;
return (xd * xd + yd * yd <= wt * wt);
}
Where the parameters to pass in are the x,y and width values of two different sprite objects.
This is a lightweight solution I've come across -
function E() { // Check collision
S = X - x;
D = Y - y;
F = w + W;
return (S * S + D * D <= F * F)
}
The big and small variables are of two objects, (x coordinate, y coordinate, and w width)
From here.
//Off the cuff, Prototype style.
//Note, this is not optimal; there should be some basic partitioning and caching going on.
(function () {
var elements = [];
Element.register = function (element) {
for (var i=0; i<elements.length; i++) {
if (elements[i]==element) break;
}
elements.push(element);
if (arguments.length>1)
for (var i=0; i<arguments.length; i++)
Element.register(arguments[i]);
};
Element.collide = function () {
for (var outer=0; outer < elements.length; outer++) {
var e1 = Object.extend(
$(elements[outer]).positionedOffset(),
$(elements[outer]).getDimensions()
);
for (var inner=outer; inner<elements.length; innter++) {
var e2 = Object.extend(
$(elements[inner]).positionedOffset(),
$(elements[inner]).getDimensions()
);
if (
(e1.left+e1.width)>=e2.left && e1.left<=(e2.left+e2.width) &&
(e1.top+e1.height)>=e2.top && e1.top<=(e2.top+e2.height)
) {
$(elements[inner]).fire(':collision', {element: $(elements[outer])});
$(elements[outer]).fire(':collision', {element: $(elements[inner])});
}
}
}
};
})();
//Usage:
Element.register(myElementA);
Element.register(myElementB);
$(myElementA).observe(':collision', function (ev) {
console.log('Damn, '+ev.memo.element+', that hurt!');
});
//detect collisions every 100ms
setInterval(Element.collide, 100);
This is a simple way that is inefficient, but it's quite reasonable when you don't need anything too complex or you don't have many objects.
Otherwise there are many different algorithms, but most of them are quite complex to implement.
For example, you can use a divide et impera approach in which you cluster objects hierarchically according to their distance and you give to every cluster a bounding box that contains all the items of the cluster. Then you can check which clusters collide and avoid checking pairs of object that belong to clusters that are not colliding/overlapped.
Otherwise, you can figure out a generic space partitioning algorithm to split up in a similar way the objects to avoid useless checks. These kind of algorithms split the collision detection in two phases: a coarse one in which you see what objects maybe colliding and a fine one in which you effectively check single objects.
For example, you can use a QuadTree (Wikipedia) to work out an easy solution...
Take a look at the Wikipedia page. It can give you some hints.
hittest.js; detect two transparent PNG images (pixel) colliding.
Demo and download link
HTML code
<img id="png-object-1" src="images/object1.png" />
<img id="png-object-2" src="images/object2.png" />
Init function
var pngObject1Element = document.getElementById( "png-object-1" );
var pngObject2Element = document.getElementById( "png-object-2" );
var object1HitTest = new HitTest( pngObject1Element );
Basic usage
if( object1HitTest.toObject( pngObject2Element ) ) {
// Collision detected
}

Categories

Resources