Prevent overlap of randomly placed elements - javascript

$(this).css({
position: 'absolute',
left: Math.random() * ($('.parentcontainer').width() - $(this).width()),
top: Math.random() * ($('.parentcontainer').height() - $(this).height())
});
I got this each loop that will randomly place elements within a div. The problem with this is that the elements will overlap each other sometimes because they are absolute positioned. Is there anyway to go around this in js to check position? or maybe rewrite this with margin values? Thanks a ton!

There's a few different ways you can do to achieve this. I find it easiest to try to define the problem in one sentence:
New square's position must be at least X distance from current square positions
Using this sentence, we can make some simple theories as to how the code will work.
Assuming all squares are 50x50 pixels, we can write some checks.
Here are some pseudo code steps we could follow:
Generate a random position for newSquare
Compare the x and y positions of newSquare to all existing squares
If either of the x and y positions of newSquare are further away from the other squares, newSquare can be placed
Otherwise, try again
var container = $('#container');
var squareSize = 50;
var containerSize = 500;
for (var i = 0; i < 20; i++) {
var foundSpace = false;
while (!foundSpace) {
// Generate random X and Y
var randX = Math.floor(Math.random() * (containerSize - squareSize));
var randY = Math.floor(Math.random() * (containerSize - squareSize));
var hitsSquare = false;
var squares = container.children();
squares.each(function(index, square) {
var square = $(square);
// parseInt() because .css() returns a string
var left = parseInt(square.css('left'));
var top = parseInt(square.css('top'));
// Check boundaries
var hitsSquareX = Math.abs(left - randX) < squareSize;
var hitsSquareY = Math.abs(top - randY) < squareSize;
// Will overlap a square
if (hitsSquareX && hitsSquareY) {
hitsSquare = true;
// jQuery break .each()
return false;
}
});
// If doesn't overlap any square
if (!hitsSquare) {
foundSpace = true;
var newSquare = $('<div class="square">');
newSquare.offset({
left: randX,
top: randY
});
container.append(newSquare);
}
}
}
#container {
position: relative;
}
.square {
position: absolute;
background-color: red;
width: 48px;
/* border adds 2px */
height: 48px;
/* border adds 2px */
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
</div>

You should look for collision detection.
In my opinion this is a great tutorial: https://www.youtube.com/watch?v=XYzA_kPWyJ8, but there are several other great ones out there.
Good luck :)

Related

How do I calculate the arc of a projectile in javascript?

I am creating a game for coursework, two tanks placed on a canvas with input boxes for the initial velocity and angle of the turret, then a button to fire a projectile (currently a div element in the shape of a circle), which calls a function in this case it is fire1. I have messed around for a few days and can't seem to get it to work, "bullet" is my div element.
function fire1 () {
var canvas = document.getElementById("canvas")
var bullet = document.getElementById("bullet");
bullet.style.visibility = "visible"
var start = null;
var intialVelocity = velocity1.value
var angle = angle1.value
var g = 9.81;
var progress, x, y;
function step(timestamp) {
if(start === null) start = timestamp;
progress = (timestamp - start)/1000;
x = (turret1.x + 80) + (intialVelocity*progress)
y = (turret1.y - 400) + (intialVelocity*progress)*Math.sin(angle*toRadians) - (0.5*g*(progress^2));//)
bullet.style.left = x + "px";
bullet.style.bottom = y + "px";
requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
Below is my css bit of my bullet.
#bullet {
position: absolute;
left: 0;
bottom: 50%;
width: 1em;
height: 1em;
border-radius: 0.5em;
background: red;
visibility: hidden;
}
I am very new to javascript, css and html so help would be very appriciated, I'm trying to incorporate the trajectory formula will this work? I also want it to be animated so it follows a path when fired. Thanks
I fixed this a long time ago but forgot to update with solution, below is how x and y are calculated for the trajectory:
x = ((turret.anchorX + negative*(initialVelocity*progress*Math.cos(angle*toRadians)))); //x-coordinate for bullet calculated by using x=ut.
y = ((720 - turret.anchorY + (initialVelocity*progress*Math.sin(angle*toRadians)) + (0.5*g*(Math.pow(progress,2))))); //y-coordinate for bullet calculated by usnig ut+0.5at^2.

How can I improve the accuracy of Math.atan()?

I was trying to do some comparison between the angles of points, but quickly I ran into some strange results.
In this example I try rotate lines so that they point to the center, but the lines seem to angle more than they should quite quickly. Then, right above and below the center the lines start to point in all sorts of directions (These values are beyond the mathematical range of atan(x)).
How can I get accurate results from Math.atan()? Is there an alternative method to do this calculation?
I uploaded a 'working' version to this fiddle:
https://jsfiddle.net/0y2p6p3n/. I am working in Chrome.
html:
<div id="content">
</div>
javascript:
let points = [];
let amount = 1000;
let width = 300;
let height = 300;
for (let i = 0; i<amount;i++) {
let x = Math.random();
let y = Math.random();
let point = {x, y};
points.push(point);
points[i].tan = Math.atan(0.5 - points[i].y)/(0.5 - points[i].x);
points[i].error = Math.abs(points[i].tan) > 3.14/2 ? true : false;
}
for (let point of points) {
let line = document.createElement("div");
line.classList.add("line");
line.style.marginTop = point.y*height + "px";
line.style.marginLeft = point.x*width + "px";
line.style.transform = "rotateZ(" + ((point.tan*(180/Math.PI))) + "deg)";
point.error == true && line.classList.add("error");
document.getElementById("content").appendChild(line);
}
css:
#content {
position: relative;
}
.line {
position: absolute;
height: 1px;
width: 10px;
background-color: black;
}
.error {
background-color: red;
}
You are using
points[i].tan = Math.atan(0.5 - points[i].y)/(0.5 - points[i].x);
It should be
points[i].tan = Math.atan( (0.5 - points[i].y)/(0.5 - points[i].x) );
let points = [];
let amount = 1000;
let width = 300;
let height = 300;
for (let i = 0; i<amount;i++) {
let x = Math.random();
let y = Math.random();
let point = {x, y};
points.push(point);
points[i].tan = Math.atan( (0.5 - points[i].y)/(0.5 - points[i].x) );
points[i].error = Math.abs(points[i].tan) > 3.14/2 ? true : false;
}
for (let point of points) {
let line = document.createElement("div");
line.classList.add("line");
line.style.marginTop = point.y*height + "px";
line.style.marginLeft = point.x*width + "px";
line.style.transform = "rotateZ(" + ((point.tan*(180/Math.PI))) + "deg)";
point.error == true && line.classList.add("error");
document.getElementById("content").appendChild(line);
}
#content {
position: relative;
}
.line {
position: absolute;
height: 1px;
width: 10px;
background-color: black;
}
.error {
background-color: red;
}
<div id="content"></div>
As you mentioned, the exact asymptotes (i.e. pi/2 and -pi/2) are outside of the valid domain of atan, which makes taking the atan of those values impossible. You also may have to deal with the fact that atan always returns a reference angle, which may not be the quadrant you want your answer to be in. These are very well known issues, and most languages have a simple cure, called atan2. In the case of javascript, please see the MDN reference for atan2.
The change to your code is simple; simply change
points[i].tan = Math.atan(0.5 - points[i].y)/(0.5 - points[i].x);
to
points[i].tan = Math.atan2(0.5 - points[i].y, 0.5 - points[i].x);
If you check out the updated fiddle, you may see its behavior has improved considerably.
atan2 doesn't give you higher precision, but it does give you values over the complete range of [0..2pi], without you having to do all the extra work of figuring out which quadrant the answer should be in, as well as supporting pi/2 and -pi/2 within its range. It is helped in doing so by knowing whether the x or the y (or both) is negative, a fact which gets hidden if you do the division yourself.
It should be noted that the most significant change I made to your code was not atan2, however, it was changing around your use of parenthesis. While I'm an advocate for using atan2 any time you would normally use atan, your actual issue was misuse of parenthesis, making Oriol's answer the right one.

Have child divs fill parent div with set proportions

I would like to create a function with jQuery/javascript that would fill a parent div with children divs of random sizes that add up the size of the parent.
For example, 10 child divs to fill a container div with proportions 1200px x 600px
<div class="container">
<!-- 10 child divs with random height and width. -->
</div>
You can use a function which splits a rectangle into two subrectangles, and recursivelly split these.
When splitting a rectangle into two parts, if it must contain an even number N of subrectangles, each part will have N/2 subrectangles.
When splitting a rectangle into two, if it must contain an odd number of leaf subrectangles, the bigger part will have one more child than the other.
function fillWithChilds(el, N) {
function rand(n) {
/* weight=100 means no random
weight=0 means totally random */
var weight = 50;
return Math.floor(weight*n/2+n*(100-weight)*Math.random())/100;
}
function main(N, x, y, hei, wid) {
if(N < 1) return;
if(N === 1) {
var child = document.createElement('div');
child.className = 'child';
child.style.left = x + 'px';
child.style.top = y + 'px';
child.style.width = wid + 'px';
child.style.height = hei + 'px';
el.appendChild(child);
return;
}
var halfN = Math.floor(N/2);
if(wid > hei) {
var newWid = rand(wid);
if(2*newWid > wid) halfN = N-halfN;
main(halfN, x, y, hei, newWid);
main(N-halfN, x+newWid, y, hei, wid-newWid);
} else {
var newHei = rand(hei);
if(2*newHei > hei) halfN = N-halfN;
main(halfN, x, y, newHei, wid);
main(N-halfN, x, y+newHei, hei-newHei, wid);
}
}
main(N, 0, 0, el.clientHeight, el.clientWidth);
}
fillWithChilds(document.getElementById('wrapper'), 11);
#wrapper {
background: #ccf;
position: relative;
height: 300px;
width: 400px
}
.child {
background: #cfc;
outline: 2px solid red;
position: absolute;
}
<div id="wrapper"></div>
The distributing will be a pain. I think there's a jQuery library out there that handles some of it... I'll poke around. This is a pretty fun problem, though.
Here's what I've go so far. It's a bit sparse.
http://jsfiddle.net/twPQ7/2/
The part that attempts to determine how many more components it should build is the rough part. I'm trying to keep this down to as few loops as possible:
var containerSize = getContainerSize();
var elementWidth = 0;
var elementHeight = 0;
// width
while (elementWidth < containerSize.x)
{
var size = generateElement();
elementWidth += size.x;
elementHeight += size.y;
}
// height, if not already full
while (elementHeight < containerSize.y)
{
var size = generateElement();
elementWidth += size.x;
elementHeight += size.y;
}
Cleaned it up a bit. Check the fiddle again: http://jsfiddle.net/twPQ7/2/
// determine the size of the container
var containerSize = getContainerSize();
var elementWidth = 0;
var elementHeight = 0;
// iteratively generate elements until we've hit the width of the container
while (elementWidth < containerSize.x)
{
var size = generateElement();
elementWidth += size.x;
// keep track of the tallest element.
if (size.y > elementHeight) elementHeight = size.y;
}
// iteratively generate elements until we've hit the height of the container
while (elementHeight < containerSize.y)
{
var size = generateElement();
elementHeight += size.y;
}

Using Zigfu (kinect) in canvas element of HTML5

I went through the initial tutorial for making a user radar on Zigfu's website. I am having trouble getting this radar to work in the canvas element.
I want to using the drawing methods in canvas, so I don't want it in the container.
Here is my code so far taken directly from the tutorial. Thanks so much for reading!
function loaded() {
var radardiv = document.getElementById('container');
var radar = {
onuserfound: function (user) {
var userdiv = document.createElement('div');
userdiv.className = 'user';
user.radarelement = userdiv;
radardiv.appendChild(user.radarelement);
},
onuserlost: function (user) {
radardiv.removeChild(user.radarelement);
},
ondataupdate: function (zigdata){
for (var userid in zigdata.users){
var user = zigdata.users[userid];
var pos = user.position;
//console.log(pos);
var el = user.radarelement;
var parentElement = el.parentNode;
var zrange = 2000;
var xrange = 700;
var pixelwidth = parentElement.offsetWidth;
var pixelheight = parentElement.offsetHeight;
var heightscale = pixelheight / zrange;
var widthscale = pixelwidth / xrange;
el.style.left = (((pos[0] / xrange) + 0.5) * pixelwidth - (el.offsetWidth / 2)) + "px";
el.style.top = ((pos[2] / zrange) * pixelheight - (el.offsetHeight / 2)) - 150 + "px";
}
}
};
zig.addListener(radar);
}
document.addEventListener('DOMContentLoaded', loaded, false);
<body>
<div id = 'container'></div>
</body>
</html>
<style>
div#container {
width: 800px;
height: 600px;
border: 1px solid black;
overflow: hidden;
}
div.user {
position: relative;
width: 10px;
height: 10px;
background-color: red;
}
It seems you are missing tags around the javascript, as well as some css for the users radar. Also - your 'container' div is missing a >
Try copying the code from the bottom of http://zigfu.com/en/zdk/tutorials/, or - check out http://zigfu.com/en/zdk/recipes/#omercy16 for a cleaner implementation of the users radar.
The radar used in the tutorial makes use of DOM div placement and positioning.
Unfortunately this can't be used inside the canvas element.
There are ways to overlay over the canvas and other workarounds. See: Placing a <div> within a <canvas>
You can also take the data directly from the plugin and draw to the canvas yourself.
Here is a demo using three.js and zigfu to draw the skeleton onto a canvas:
http://blog.kinect.tonkworks.com/post/30569123887/kinect-online-app-javascript-dev-tutorial-1

using htmt5 gradient and javascript, simulate wood grain

have a chess board in TABLE, each square a TD.
how would one use html5 gradients (and javascript for randomness) to create a wood texture background for the dark squares?
I'm grabbing a big wood texture (change to one you like) and grabbing a random piece of it at 50% opacity, then underneath is a random brownish color to add a unique undertone to each square. You can adjust all these to get an effect you want. I messed with some gradients and they looked silly.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script>
<style>
div {
width: 100px; height: 100px; margin: 1px;
}
div.texture {
background: url(http://gallery.hd.org/_exhibits/textures/wood-grain-closeup-1-DHD.jpg);
opacity:0.4; filter:alpha(opacity=100);
}
</style>
<script>
$(function(){
$('div.bg').each(function(){
// make each square a random brown
var browns = new Array('CD853F','8B4513','A0522D');
var col = Math.floor(Math.random()*3);
$(this).css('background-color',browns[col]);
// the dimensions of your texture minus square size
var image_width = 500;
var image_height = 400;
// get a random positions
var x = Math.floor(Math.random()*image_width);
var y = Math.floor(Math.random()*image_height);
// make them negative
x = x - (x * 2);
y = y - (y * 2);
var d = $(this).children('div.texture');
d.css('background-position', x+'px'+' '+y+'px');
});
});
</script>
<div class='bg'><div class='texture'></div>
<div class='bg'><div class='texture'></div>

Categories

Resources