Disabling gravity for a specific object in Matter.js - javascript

I'm working on a project using Matter.js where I want gravity enabled in general, but I want to be able to disabled and re-enable it for a single object at certain times. I do not want to set that object as static, because I want the physics engine to handle it in other ways, I just don't want gravity to affect it.
I found this question that deals with disabling gravity in general, but as I said I want gravity to work for most objects. Is there a simple way to do this?

Here is a simple code snippet that you could have toggle on/off to accomplish what you're asking (where body is the object that should ignore gravity, and noGravity is a boolean that can be toggled to turn it on and off):
Events.on(engine, 'beforeUpdate', function() {
var gravity = engine.world.gravity;
if (noGravity) {
Body.applyForce(body, body.position, {
x: -gravity.x * gravity.scale * body.mass,
y: -gravity.y * gravity.scale * body.mass
});
}
});

Disable the built in gravity and then apply your own selectively, something like this but filter only the bodies you want:
engine.world.gravity.scale = 0;
Events.on(engine, 'beforeUpdate', function() {
var bodies = Composite.allBodies(engine.world);
for (var i = 0; i < bodies.length; i++) {
var body = bodies[i];
if (body.isStatic || body.isSleeping)
continue;
body.force.y += body.mass * 0.001;
}
});

I know this is an old question, but nowadays you can use this:
body.ignoreGravity = true;

I found that was very easy to implement that. Just look for the Engine._bodiesApplyGravity function on the Matter source code and just put whatever condition you need for a body to be excluded.
Engine._bodiesApplyGravity = function (bodies, gravity) {
var gravityScale = typeof gravity.scale !== 'undefined' ? gravity.scale : 0.001;
if ((gravity.x === 0 && gravity.y === 0) || gravityScale === 0) {
return;
}
for (var i = 0; i < bodies.length; i++) {
var body = bodies[i];
// I just added body.ignoreGravity
if (body.isStatic || body.isSleeping || body.ignoreGravity)
continue;
// apply gravity
body.force.y += body.mass * gravity.y * gravityScale;
body.force.x += body.mass * gravity.x * gravityScale;
}
};

This seems to provide a counter force. I'm not sure where the 200 is coming from it just worked. Maybe the engine calculates force twice a cycle.
playerBody.force.y = -engine.world.gravity.y / 200;
You will have to run it every cycle to keep it up.

In my case I wanted an object to follow the mouse. Setting isStatic: true made gravity not apply to give me full control over the object's position.

there is an official working example
this.matter.add.image(100, 100, 'block').setIgnoreGravity(true);
ignoring gravity phaser3 matter physic

Related

JS create an array with unique random numbers

Full code looks like this, ideally we have 4 div boxes that need to be randomly filled with random numbers ansValue, one of them (rightAnsValue with its rightAnsId) is already done and works fine, I've managed to make it unique in comparison to others (code without commented section). But met a problem with making others unique, I keep having some identical values in my boxes. In comments is one way I tried to solve this, but pretty sure there is a much simpler and smarter solution that actually works. I would appreciate if you could help to find an understandable solution to this problem.
(P.S. I've seen similar questions but they are either too dificult or done without JS.)
function createAnswers(){
for(ansId=1; ansId<5; ansId++){
if(ansId!=rightAnsId){
for(i=1; i<10; i++){
digitArray[i-1] = i;
}
genNewRandNum();
// ansArray.length = 3;
// ansArray.push(ansValue);
// for(k=0; k<3; k++){
// if(ansArray[k] == ansArray[k+1] || ansArray[k] == ansArray[k+2]){
// genNewRandNum();
// ansArray[k] = ansValue;
// }else if(ansArray[k+1] == ansArray[k+2]){
// genNewRandNum();
// ansArray[k+1] = ansValue;
// }else{
// break;
// }
// }
if(ansValue!=rightAnsValue){
document.getElementById("box" + ansId).innerHTML = ansValue;
}else{
genNewRandNum();
document.getElementById("box" + ansId).innerHTML = ansValue;
}
}
}
}
The way I generate new numbers:
function genNewRandNum(){
rand1 = digitArray[Math.floor(Math.random() * digitArray.length)];
rand2 = digitArray[Math.floor(Math.random() * digitArray.length)];
ansValue = rand1 * rand2;
}
Replace your genNewRandNum() with below code. I have used IIFE to create a closure variable alreadyGeneratedNumbers thats available inside the function generateRandomNumber() thats returned.
So everytime genNewRandNum() is executed, it checks against alreadyGeneratedNumbers to make sure it always returns a unique between 1 and 9.
var genNewRandNum = (function(){
var alreadyGeneratedNumbers = {};
return function generateRandomNumber() {
var min = Math.ceil(1),
max = Math.floor(9);
randomNumber = Math.floor(Math.random() * (max - min + 1)) + min;
if(alreadyGeneratedNumbers[randomNumber]) {
return generateRandomNumber();
} else {
alreadyGeneratedNumbers[randomNumber] = randomNumber;
return randomNumber;
}
}
})();
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
Note: If you call genNewRandNum() for the 10th time it will throw error. So if you have a use case where you would need to reset it after all numbers from 1 to 9 are returned, then you need to add code to handle that
The easiest way to brute-force this is to use accept/reject sampling. You can do something like so:
uniqueRandomNumbers = function(n, nextRandom)
{
var nums = {}; var m = 0;
while(m < n)
{
var r = nextRandom();
if(! nums.hasOwnProperty(r))
{
nums[r] = true; m++;
}
}
return Object.keys(nums);
}
Here I'm using the fact that js objects are implemented as hashmaps to get a hashset. (This has the downside of converting the numbers to strings, but if you're not planning on imediately doing arithmetic with them this is not a problem.)
In order to get four unique integers between 0 and 9 you can then do something like:
uniqueRandomNumbers(4, function() { return Math.floor(Math.random() * 10); })
If you want something a little better than brute force (which probably isn't relevant to your use case but could help someone googling this), one option is to go through each element and either take or leave it with an appropriate probability. This approach is outlined in the answers to this question.

Read & change rotate value of an Element in SnapSVG

Pls Check out this incomplete fiddle (https://jsfiddle.net/JayKandari/srqLLd97/).
Markup:
<svg id="paper" ></svg>
<div id="workingArea">
<button onclick="calculateTransform()">Get Transform</button>
<div class="results">
Transform: <span class="transformResult"></span>
</div>
<button onclick="rotateText('add')">Rotate + 10 Degrees</button>
<button onclick="rotateText('sub')">Rotate - 10 Degrees</button>
</div>
JS Code:
console.clear();
var paper = Snap("#paper");
var t = paper.text(0, 0, "SnapSVG is Awesome !");
//Translate to 250, 250 & Scale by 2 & 45Deg Rotate
t.transform('T250,250 S2 R45');
// Enable Drag
t.drag();
var calculateTransform = function() {
var currentTransform = t.transform().string;
console.log('test', currentTransform)
$('.results .transformResult').html(currentTransform)
}
var rotateText = function(op) {
// Read Current Rotate Value here.
var rotateVal = 0;
// add/Subtract based on option
if(op == 'add'){
rotateVal += 10;
}else if(op == 'sub') {
rotateVal -= 10;
}
// Calculate newTransform here.
var newTransform = 'T250,250 R' + rotateVal;
// Update object's rotation here.
t.attr({transform: newTransform });
}
Problems:
Read current transformation applied to Element.
Rotate current Element to a specific value.
What you probably are after in your mind is something like this...
var rotateVal = t.transform().localMatrix.split().rotate;
localMatrix gives the matrix specifically applied to that element.
globalMatrix gives the total matrix applying to that element (eg matrices from outer containers).
diffMatrix gives the difference between localMatrix and globalMatrix.
split() ( docs here ) breaks down that matrix into its elements. So we can find 'rotate' from here.
example fiddle
So this is the answer I think you are after.
However, I would actually design the code the slightly different if this is just a minimal example of a more complex design.
Rather than doing something like transform().localMatrix.split().rotate, I would store your own transform components. So something like...
var rotate = 45;
var tx = 250;
var ty = 250;
...then in func
rotate += +10;
var newTransform = 'T'+tx+','+ty+'R'+rotate;
The reason for this, is that you are now controlling precisely the values, and its not really prone to errors (from the lib or misunderstanding about matrices). If you look at your matrix values you display, you will note there are subtle rounding differences, plus with complex matrix calculations, the values aren't quite what we expect and don't always split in a nice easy way that makes sense.
So if this is the main example, the first bit of code will probably suffice. If you are doing more complex transformations, I would think about controlling the values yourself and building up the transform string like the latter example.

Javascript code for making my browser slow down

I'm writing a library for WebWorkers, and I want to test the difference between running a script in the main page thread, versus in one or more workers. The problem is: I can't find out of hand a short function which will strain my browser enough that I can observe the difference.
A quick search didn't return much, but it might just be that I don't really know what to search for; usually I try to optimise my code, not make it slower...
I'm looking for algorithms or patterns that can be easily implemented in pure Javascript, that do not depend on the DOM or XHR, and which can have an argument passed to limit or specify how far the calculation goes (no infinite algorithms); 1s < avg time < 10s.
Extra points if it can be built without recursion and if it does not incur a significant memory hog while still being as processor intensive as possible.
Try using the obvious (and bad) recursive implementation for the Fibonacci sequence:
function fib(x) {
if (x <= 0) return 0;
if (x == 1) return 1;
return fib(x-1) + fib(x-2);
}
Calling it with values of ~30 to ~35 (depending entirely on your system) should produce good "slow down" times in the range you seek. The call stack shouldn't get very deep and the algorithm is something like O(2^n).
/**
* Block CPU for the given amount of seconds
* #param {Number} [seconds]
*/
function slowdown(seconds = 0.5) {
const start = (new Date()).getTime()
while ((new Date()).getTime() - start < seconds * 1000){}
}
slowdown(2)
console.log('done')
Calling this method will slow code down for the given amount of seconds (with ~200ms precision).
Generate an array of numbers in reverse order and sort it.
var slowDown = function(n){
var arr = [];
for(var i = n; i >= 0; i--){
arr.push(i);
}
arr.sort(function(a,b){
return a - b;
});
return arr;
}
This can be called like so:
slowDown(100000);
Or whatever number you want to use.
Check out the benchmarking code referenced by the Google V8 Javascript Engine.
For some reason Bogosort comes to mind. Basically it's a sorting algorithm that consists of:
while not list.isInOrder():
list.randomize()
It has an average complexity of O(n * n!) with little memory, so it should slow things down pretty good.
The main downside is that its running time can be anywhere from O(n) to O(inf) (though really, O(inf) is pretty unlikely).
Everyone seems determined to be complicated. Why not this?
function waste_time(amount) {
for(var i = 0; i < amount; i++);
}
If you're concerned the browser will optimize the loop out of existence entirely, you can make it marginally more complicated:
function waste_time(amount) {
var tot = 0;
for(var i = 0; i < amount; i++)
tot += i;
}
Compute lots of square roots manually?
function sqrt(number, maxDecimal) {
var cDecimal = -1;
var cNumber = 0;
var direction = -1;
while(cNumber * cNumber !== number && cDecimal < maxDecimal) {
direction = -direction;
cDecimal++;
while((cNumber * cNumber - number) / Math.abs(cNumber * cNumber - number) === direction) cNumber += direction * Math.pow(10, -cDecimal);
}
return Math.abs(cNumber);
}
function performTest() {
for(var i = 0; i < 10000; i++) {
sqrt(i, 3);
}
}
Maybe this is what you are looking for:
var threadTest = function(durationMs, outputFkt, outputInterval) {
var startDateTime = (new Date()).getTime();
counter = 0,
testDateTime = null,
since = 0,
lastSince = -1;
do {
testDateTime = (new Date()).getTime();
counter++;
since = testDateTime - startDateTime;
if(typeof outputFkt != 'undefined' && lastSince != since && testDateTime % outputInterval == 0) {
outputFkt(counter, since);
lastSince = since;
}
} while(durationMs > since);
if(typeof outputFkt != 'undefined') {
outputFkt(counter, since);
}
return counter;
}
This method will simply repeat a check in a loop
durationMS - duartion it should run in miliseconds
OPTIONAL:
outputFkt - a callback method, for logging purpose function(currentCount, milisecondsSinceStart)
outputInterval - intervall the output function will be called
I figured since you do not want to test a real function, and even NP-Hard Problems have a ratio between input length and time this could be a easy way. You can measure performance at any interval and of course receive the number of loops as a return value, so you can easily measure how much threads interfere each others performance, with the callback even on a per cycle basis.
As an example here is how i called it (jQuery and Dom usage are here, but as you can see optional)
$(document).ready(function() {
var outputFkt = function(counter, since) {
$('body').append('<p>'+counter+', since '+since+'</p>');
};
threadTest(1000, outputFkt, 20);
});
A last Warning: Of course this function can not be more exact than JS itself. Since modern Browsers can do much more than one cycle in one Milisecond, there will be a little tail that gets cut.
Update
Thinking about it... actually using the ouputFkt callback for more than just output could give great insight. You could pass a method that uses some shared properties, or you could use it to test great memory usage.

how to get the actual box bigger than the others?

i'm new to javascript and i'm having a problem. I want the actual (function updateBoxes) box [boxIx] to be bigger than the other ones but i can't seem to find a code that works. i've tried box[boxIx].size ="100px"; box[boxIx].style.size ="100px"; without result. This is my code;
function init() {
box = document.getElementById("boxes").getElementsByTagName("div");
for (var i=0; i<box.length; i++) {
box[i].style.left = 70*i+"px";
} // End for
boxIx = box.length - 8;
updateBoxes();
} // End init
function browseLeft() {
if (boxIx > 0) boxIx = boxIx - 1;
updateBoxes();
}
// End browseLeft
function browseRight() {
if (boxIx < box.length-1) boxIx = boxIx + 1;
updateBoxes();}
// End browseRight
**function updateBoxes() {
box[boxIx].style.backgroundColor ="#CCC";
box[boxIx].style.top = "20px";
box[boxIx].style.zIndex = 9;**
var z = 8;
for (var i=boxIx-1; i>=0; i--) {
box[i].style.backgroundColor ="#666";
box[i].style.top = "0px";
box[i].style.zIndex = z;
z = z - 1;
} // End for
z = 8;
for (var i=boxIx+1; i<box.length; i++) {
box[i].style.backgroundColor = "#666";
box[i].style.top = "0px";
box[i].style.zIndex = z;
z = z - 1;
} // End for
} // End browseLeft
As thirtydot pointed out, you have two instances of "**" in your sample code that I've removed in the assumption that this is a markdown glitch when editing.
Your example shows only the JavaScript code. The HTML markup and CSS styling you're using would be most helpful. I've created a fiddle for discussion and to resolve this for you here: http://jsfiddle.net/bhofmann/zkZMD/
A few things I noticed that might be helpful:
You're using a magic number 8 in a few places. Can we assume this is the number of boxes? I would store that in a variable for use in the functions.
You used a lot of direct styling. Your code might be cleaner if you used CSS classes to alter the appearance of the boxes.
Unless you're altering the default styling of DIV, you won't see much change by simply setting the left offset.
PS. I took the liberty of invoking the init function on page load because I saw nothing else to invoke it. I don't know what would invoke browseLeft and browseRight but I'll leave that to you.

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