Javascript function not changing the css of an html div on call - javascript

I am trying to create a function for my game of pong for the ball to move around within a frame. When I call the function I am using a function called setStyle() to change the position of the ball every 100 milliseconds.
After I saw that it did not work I console logged the left and top positions to find that the function was getting called but the amount of pixels it was located at was the same.
//Javascript
function ballMove(){
var x = 5;
var y = 5;
var maxHeight = getStyle('frame', 'top') + getStyle('frame', 'height');
var maxWidth = getStyle('frame', 'left') + getStyle('frame', 'width');
var ballLeft = getStyle('ball', 'left');
var ballTop = getStyle('ball', 'top');
var minLeft = getStyle('frame', 'left');
var minTop = getStyle('frame', 'top');
if(ballTop >= minTop){
setStyle('ball', 'top', (ballTop + y) + "px");
}
else if(ballTop <= maxHeight){
setStyle('ball', 'top', (ballTop - y) + "px");
}
if(ballLeft >= minLeft){
setStyle('ball', 'left', (ballLeft + x) + "px");
}
else if(ballLeft <= maxWidth){
setStyle('ball', 'left', (ballLeft - x) + "px");
}
console.log(ballLeft);
console.log(ballTop);
}
function startIntervals(){
setInterval(ballMove, 100);
console.log("starting...");
}
Here is my css
#ball{
position: relative;
background-color: white;
height: 10px;
width: 10px;
left: 50px;
}
and the html
<body onload="startIntervals();">
<div id="main-div">
<div id="title">Pong</div>
<div id="frame">
<div id="paddlewasd">
</div>
<div id="paddlearrow">
</div>
<div id="ball">
</div>
</div>
</div>
I expected the ball to move but instead the function gets called and the left and top positions stay the same.My code

Although it depends fairly significantly on the rest of the code that wasn't posted the following implementations of getStyle and setStyle along with a css defintion of #frame allows the ball to move diagonally 5pixels right and down every 100 milliseconds
function getStyle(id, style) {
var element = document.getElementById(id);
var computedStyle = window.getComputedStyle(element);
var selectedStyle = computedStyle[style];
// Check if the style value matches a 'pixel' string format, if it does extract the numeric part and parse it as an integer
var pixelTokens = /([\d]*)px$/.exec(selectedStyle);
if (pixelTokens) {
return parseInt(pixelTokens[1]);
}
return selectedStyle;
}
function setStyle(id, style, value) {
var element = document.getElementById(id);
return element.style[style] = value;
}
function ballMove() {
var x = 5;
var y = 5;
var maxHeight = getStyle('frame', 'top') + getStyle('frame', 'height');
var maxWidth = getStyle('frame', 'left') + getStyle('frame', 'width');
var ballLeft = getStyle('ball', 'left');
var ballTop = getStyle('ball', 'top');
var minLeft = getStyle('frame', 'left');
var minTop = getStyle('frame', 'top');
if (ballTop >= minTop) {
setStyle('ball', 'top', (ballTop + y) + "px");
} else if (ballTop <= maxHeight) {
setStyle('ball', 'top', (ballTop - y) + "px");
}
if (ballLeft >= minLeft) {
setStyle('ball', 'left', (ballLeft + x) + "px");
} else if (ballLeft <= maxWidth) {
setStyle('ball', 'left', (ballLeft - x) + "px");
}
console.log(ballLeft);
console.log(ballTop);
}
function startIntervals() {
setInterval(ballMove, 100);
console.log("starting...");
}
#ball {
position: relative;
background-color: white;
height: 10px;
width: 10px;
left: 50px;
}
#frame {
width: 300px;
height: 300px;
top: 0px;
left: 0px;
background-color: green;
}
<body onload="startIntervals();">
<div id="main-div">
<div id="title">Pong</div>
<div id="frame">
<div id="paddlewasd">
</div>
<div id="paddlearrow">
</div>
<div id="ball">
</div>
</div>
</div>
</body>

Related

How to make the point to be spawned have the same coordinates to the "left" or "top" as the previous point

I need to make it so that it is possible to connect the dice only with straight lines. But to do this, I need each subsequent dice to have a common "top" or "left" coordinate with the previous dice and at the same time a partial random is preserved.
Here is an example:
Here is my code:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Игральные кости</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="icon" type="image/png" href="./dice.png">
</head>
<body>
<div id="main-container">
<div id="square-container">
</div>
<canvas id="overlay"></canvas>
</div>
</body>
<script src="./script.js"></script>
</html>
html,
body {
margin: 0;
padding: 0;
}
#main-container {
width: 100%;
margin: 10px
}
#square-container {
width: 700px;
height: 600px;
position: absolute;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
background: #dddddd;
border: 5px solid #6b6b6b;
border-radius: 5px;
z-index: 1;
}
#overlay {
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
position: absolute;
top: 0;
left: 0;
}
.js-is-target {
position: absolute;
width: 56px;
height: 56px;
/*background: blue;*/
border-radius: 30px;
}
.square {
top: 13px;
left: 13px;
position: relative;
width: 30px;
height: 30px;
background: red;
background-size: contain;
border-radius: 5px;
z-index: 10;
}
.active-target {
box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.5);
}
//links to images of dice
var imgArr = [
'./dotsOnDice/dice1.jpg',
'./dotsOnDice/dice2.jpg',
'./dotsOnDice/dice3.jpg',
'./dotsOnDice/dice4.jpg',
'./dotsOnDice/dice5.jpg',
'./dotsOnDice/dice6.jpg'
]
//random number from 3 to 6
var randomAmount = Math.floor(Math.random() * (6 - 3 + 1)) + 3;
//limit for recursion
var limitDice = 0;
function addDice() {
// if the limit is equal to a random number, the recursion function is interrupted
if (limitDice === randomAmount) {
return
}
//random number from 2 to 5
let randomAmountImg = Math.floor(Math.random() * (5 - 2 + 1)) + 2;
//random numbers for dice coordinates
let position = {
top: Math.random() * 520,
left: Math.random() * 600
}
//saved previous coordinates for comparison
let positionAfter = {
top: 0,
left: 0
}
//creating an id that we press later
let idSquare = 'idSquare-' + limitDice;
//subtract the previous coordinates from the current coordinates
let top = position.top - positionAfter.top;
let left = position.left - positionAfter.left;
//we compare the positions of the previous coordinates to avoid a large number of overlaps
if (top > 50 || left > 50) {
positionAfter.top = position.top;
positionAfter.left = position.left;
//adding dice to the playing field
let square = $('<div class="js-is-target"><div id="' + idSquare + '" class="square"></div></div>');
square.appendTo('#square-container').css({ left: position.left + 'px', top: position.top + 'px' });
if (limitDice === 0) {
$('#idSquare-0').css('background-image', 'url(' + imgArr[randomAmountImg] + ')');
} else if (limitDice === 1) {
$('#idSquare-1').css('background-image', 'url(' + imgArr[randomAmountImg] + ')');
} else if (limitDice === 2) {
$('#idSquare-2').css('background-image', 'url(' + imgArr[randomAmountImg] + ')');
} else if (limitDice === 3) {
$('#idSquare-3').css('background-image', 'url(' + imgArr[randomAmountImg] + ')');
} else if (limitDice === 4) {
$('#idSquare-4').css('background-image', 'url(' + imgArr[randomAmountImg] + ')');
} else if (limitDice === 5) {
$('#idSquare-5').css('background-image', 'url(' + imgArr[randomAmountImg] + ')');
}
limitDice += 1;
}
addDice();
}
addDice();
//here we store the canvas field
const canvas = document.getElementById('overlay');
//here we set the format in 2D for canvas
const ctx = canvas.getContext('2d');
//here we store the width and height of the canvas field. We set the height and width in HTML
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
//in the variable we store the element that we clicked on
let targetEl = null;
//in the variable we store the coordinates of the center of the element we clicked on
let targetCenter = null;
//we check whether you clicked on the mouse or not
var down = false;
//coordinates of the pressed cursor mouseCoords
var mouseCoords = {
x: 0,
y: 0
}
//coordinates of the starting point
var centerCoords = {
x: 760,
y: 280
}
//в этой функции мы вычисляем где центр у прямоугольника
function getCenter(el) {
//if not true, the function terminates and returns null
if (!el) return null;
//we save the coordinates in the rect constant using the getBoundingClientRect method
const rect = el.getBoundingClientRect();
//returning the x and y coordinates. Here we calculate the center of the rectangle
return {
x: rect.left + rect.width / 2 + window.scrollX,
y: rect.top + rect.height / 2 + window.scrollY,
}
}
//connection points
function joinPoints(ctx, from, to) {
//dotted line size
const dashSize = 10;
//draw a dotted line and write the size in the arguments
ctx.setLineDash([dashSize]);
//setting the gradient
var stroke = ctx.createLinearGradient(from.x, from.y, to.x, to.y);
//setting the color and position
stroke.addColorStop(0, 'blue');
stroke.addColorStop(1, 'red');
//passing the colors to the strokeStyle property to set the color
ctx.strokeStyle = stroke;
//line thickness
ctx.lineWidth = 5;
//draw a contour (line)
ctx.beginPath();
//moves the contour point to the specified coordinates without drawing a line. Starting point
ctx.moveTo(from.x, from.y);
//adds a new contour point and creates a line to this point from the last specified point. End point
ctx.lineTo(to.x, to.y);
//draw a line
ctx.stroke();
}
//when you click the mouse
$(document).mousedown(function (e) {
down = true;
mouseCoords.x = e.pageX;
mouseCoords.y = e.pageY;
});
//when moving the mouse
$(document).mousemove(function (event) {
if (down) {
mouseCoords.x = event.pageX;
mouseCoords.y = event.pageY;
console.log(mouseCoords.x + ' ' + mouseCoords.y);
}
});
//when we release the mouse button
$(document).mouseup(function (e) {
down = false;
});
$(".js-is-target").hover(function (e) {
if (down) {
down = false;
//we transmit data about which js-is-target we clicked on
targetEl = e.target;
//we write down where the center of the object we clicked on is. We calculate using the getCenter() function
targetCenter = getCenter(targetEl);
//changing the coordinates of the starting point
centerCoords.x = targetCenter.x;
centerCoords.y = targetCenter.y;
}
});
//first we count, then we draw a line from ctx.lineTo to ctx.moveTo
function drwaDot() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'red';
ctx.moveTo(mouseCoords.x, mouseCoords.y);
ctx.lineTo(centerCoords.x, centerCoords.y);
ctx.stroke();
};
//the drawing interval of our line
var intervalId = setInterval(function () {
if (down) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
joinPoints(ctx, { x: centerCoords.x, y: centerCoords.y }, mouseCoords);
} else {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}, 10);
jsfiddle link
under the comment "//we compare the positions of the previous coordinates to avoid a large number of overlaps" changed the condition:
if(top < 10 || left < 10){
dice spawn code
}
That's what came out of it:

trying to animate an element to different positions using JavaScript

based on this this tutorial on w3 schools I wrote a function(move) that animates an element(div) using the setInterval() method, my problem is when I try to call the function move() several times the div does an unexpected behavior, I tried to use async/await but it didn't work.
async function moveArray(destination) {
//move through array of addresses
for (let i = 0; i < destination.length - 1; i++) {
await move(destination[i], destination[i + 1]);
}
}
async function move(pos, add) {
//moves element from position to address
var elem = document.getElementById("object");
var id = setInterval(frame, 15);
function frame() {
if (pos.x == add.x && pos.y == add.y) {
clearInterval(id);
return;
} else {
//if element haven't reached its target
// we add/substract 1 from the address and update styling
if (pos.x != add.x) {
pos.x += add.x > pos.x ? 1 : -1;
elem.style.left = pos.x + "px";
}
if (pos.y != add.y) {
pos.y += add.y > pos.y ? 1 : -1;
elem.style.top = pos.y + "px";
}
}
}
}
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#object {
width: 50px;
height: 50px;
position: absolute;
background: red;
}
<button onclick="moveArray( [{x:0,y:0}, {x:140, y:150}, {x:130, y:110}, {x:70, y:65}] )">
move
</button>
<div id="container">
<div id="object"></div>
//object to be animated
</div>
The weird behavior is caused because the move function is being called multiple times simultaneously in the for loop. This happens because your async functions do not know when they are done.
Instead of making move async, which it doesn't have to if it is not awaiting anything, return a Promise from the start and call you animation code inside of it. When the point is reached when animation has to end, resolve the promise.
Doing it like this will make your await statement in the for loop wait for the move function to reach the resolve call before continuing with the next animation.
async function moveArray(destination) {
//move through array of addresses
for (let i = 0; i < destination.length - 1; i++) {
await move(destination[i], destination[i + 1]);
}
}
function move(pos, add) {
return new Promise(resolve => {
var elem = document.getElementById("object");
var id = setInterval(frame, 15);
function frame() {
if (pos.x == add.x && pos.y == add.y) {
clearInterval(id);
// Fulfill promise when position is reached.
resolve();
} else {
if (pos.x != add.x) {
pos.x += add.x > pos.x ? 1 : -1;
elem.style.left = pos.x + "px";
}
if (pos.y != add.y) {
pos.y += add.y > pos.y ? 1 : -1;
elem.style.top = pos.y + "px";
}
}
}
});
}
<!DOCTYPE html>
<html>
<head>
<style>
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#object {
width: 50px;
height: 50px;
position: absolute;
background: red;
}
</style>
</head>
<body>
<button onclick="moveArray( [{x:0,y:0}, {x:140, y:150}, {x:130, y:110}, {x:70, y:65}] )">
move
</button>
<div id="container">
<div id="object"></div>
//object to be animated
</div>
<script src="animation.js"></script>
</body>
</html>

How to prevent element from exceeding his container borders

I have a square, when clicked it appears in a random location and it also change size (so for example if I have a 30px box but it is 10px from the left border I still get 10px outside the gamespace).
sometimes the square exceed his container border
How can I make sure that the square will never exceed his container?
function position() {
var positionTop = Math.random() * 100;
var positionLeft = Math.random() * 100;
var position = "position:relative;top:" + positionTop + "%;left:" + positionLeft + "%;"
return position;
}
document.getElementById("shape").onclick = function() {
document.getElementById("shape").style.cssText = position();
}
#gameSpace {
width: 100%;
height: 470px;
background: blue;
margin: 0;
padding-top: 30px;
}
#playSpace {
width: 90%;
height: 90%;
margin: 0 auto;
margin-top: 10px;
border: 1px black solid;
}
#shape {
width: 100px;
height: 100px;
background-color: red;
}
<div id="gameSpace">
<div id="playSpace">
<!-- here we put the shape -->
<div id="shape"></div>
</div>
</div>
You need to set position: relative; to the parent element and position: absolute; to the shape element. Then use max min value for random where max is the parent width/height and subtract the shape width/height ...
This is snippet before update
function position() {
var playSpace = document.querySelector('#playSpace');
var shape = document.getElementById("shape");
var maxHeight = playSpace.offsetHeight - shape.offsetHeight;
var maxWidth = playSpace.offsetWidth - shape.offsetWidth;
var positionTop = Math.random() * (maxHeight - 0) + 0;
var positionLeft = Math.random() * (maxWidth - 0) + 0;
// think of this like so:
// var positionTop = Math.random() * (max - min) + min;
// more information about it https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
var position = "position:absolute;top:" + positionTop + "px;left:" + positionLeft + "px;"
return position;
}
document.getElementById("shape").onclick = function() {
document.getElementById("shape").style.cssText = position();
}
#gameSpace {
width: 100%;
height: 470px;
background: blue;
margin:0;
padding-top: 30px;
}
#playSpace {
position: relative; /* add this line */
width: 90%;
height: 90%;
margin: 0 auto;
border: 1px black solid;
}
#shape {
width: 100px;
height: 100px;
background-color: red;
}
<div id="gameSpace">
<div id="playSpace">
<!-- here we put the shape -->
<div id="shape"></div>
</div>
</div>
Updated after comment
Not sure how you added the size() function but probably the problem was with using ...cssText that you overwrote the changes. So now I changed the code with passing the element to the functions and then only change the single CSS statements which need to be changed.
function position(element) {
var playSpace = document.querySelector('#playSpace');
var shape = document.getElementById("shape");
var maxHeight = playSpace.offsetHeight - shape.offsetHeight;
var maxWidth = playSpace.offsetWidth - shape.offsetWidth;
var positionTop = Math.random() * (maxHeight - 0) + 0;
var positionLeft = Math.random() * (maxWidth - 0) + 0;
// think of this like so:
// var positionTop = Math.random() * (max - min) + min;
// more information about it https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
element.style.position = 'absolute';
element.style.top = positionTop + "px";
element.style.left = positionLeft + "px";
}
function size(element) {
var sizeMath = (Math.random() * 200) + 50;
element.style.width = sizeMath + "px";
element.style.height = sizeMath + "px";
}
document.getElementById("shape").onclick = function() {
size(document.getElementById("shape"));
position(document.getElementById("shape"));
}
#gameSpace {
width: 100%;
height: 470px;
background: blue;
margin:0;
padding-top: 30px;
}
#playSpace {
position: relative; /* add this line */
width: 90%;
height: 90%;
margin: 0 auto;
border: 1px black solid;
}
#shape {
width: 100px;
height: 100px;
background-color: red;
}
<div id="gameSpace">
<div id="playSpace">
<!-- here we put the shape -->
<div id="shape"></div>
</div>
</div>
You can use a specify the range (min/max) in Math.random function and then use this function Math.floor(Math.random() * (max - min + 1)) + min; to limit the returned value of the random function between min and max.
maxTop : height of the container - height of shape
maxLeft : width of the container - width of shape
minTop : 0
minLeft : 0
You need to use position:absolute and px value on shape for this to work
See code snippet:
function position() {
var minTop = 0;
var maxTop = document.getElementById("playSpace").clientHeight - document.getElementById("shape").clientHeight;
var minLeft = 0;
var maxLeft = document.getElementById("playSpace").clientWidth - document.getElementById("shape").clientWidth ;
var positionTop = Math.floor(Math.random() * (maxTop - minTop + 1) + minTop);
var positionLeft = Math.floor(Math.random() * (maxLeft - minLeft + 1) + minLeft);
var position = "position:absolute;top:" + positionTop + "px;left:" + positionLeft + "px;"
return position;
}
document.getElementById("shape").onclick = function() {
document.getElementById("shape").style.cssText = position();
}
#gameSpace {
width: 100%;
height: 470px;
background: blue;
margin: 0;
padding-top: 30px;
text-align:center;
}
#playSpace {
width: 90%;
height: 90%;
border: 1px black solid;
position:relative;
display:inline-block;
}
#shape {
width: 100px;
height: 100px;
background-color: red;
}
<div id="gameSpace">
<div id="playSpace">
<!-- here we put the shape -->
<div id="shape"></div>
</div>
</div>
With CSS calc, limit the position inside playSpace area (you can use different units, here % and px).
Then with offsetTop/offsetLeft, get the real position of the square and avoid negative positions (when positionTop < 100px or positionLeft < 100px).
function position() {
var positionTop = Math.random() * 100;
var positionLeft = Math.random() * 100;
var position = "position:relative;top: calc(" + positionTop + "% - 100px);left: calc(" + positionLeft + "% - 100px);";
return position;
}
document.getElementById("shape").onclick = function() {
var shapeDiv = document.getElementById("shape");
shapeDiv.style.cssText = position();
var top = shapeDiv.offsetTop;// Result of calc(" + positionTop + "% - 100px) in px
if(top < 0) {
shapeDiv.style.top = '0px';
}
var left = shapeDiv.offsetLeft;// Result of calc(" + positionLeft + "% - 100px) in px
if(left < 0) {
shapeDiv.style.left = '0px';
}
}
Don't forget to add position: relative to #playSpace, to get offsetTop/left correct
#playSpace {
position:relative;/* mandatory */
}
You can get the parent element size, so that in your scirpt, use a condition to prevent the square to exceed.
function position() {
var maxWidth = document.getElementById("playSpace").offsetWidth;
var maxTop = document.getElementById("playSpace").offsetHeight;
var positionTop = Math.random() * 100;
var positionLeft = Math.random() * 100;
if (positionTop > maxTop) { positionTop = maxTop;)
if (positionLeft > maxWidth) { positionLeft = maxWidth;)
var position = "position:relative;top:" + positionTop + "%;left:" + positionLeft + "%;"
return position;
}
I'm not sure if .offsetWidth and .offsetHeight works well, but you got the idea :)
By tweaking just a little your positionTop and positionLeft variable, I managed to keep the square inside. You just need to change the maximum % that it needs to have to not exceed the container. I found that 75% for the top and 80% for the left seems to be the max!
var positionTop = Math.floor(Math.random() * 75) ;
var positionLeft = Math.random() * 80;
Here's a fiddle
If you set the containing element to position: relative; and the inner element with position: absolute; the inner elements top left right and bottom properties will calculate from the borders of the containing element.
Here is a good source of css positioning.
In your case additional validation should be set to positionTop and positionLeft.
positionTop should be in the interval [( shapeHeight/2 ) - (100 - shapeHeight/2 ) ]
positionLeft should be in the interval [( shapeWidth/2 ) - (100 - shapeWeight/2 ) ]

Creating Toggle effect in Javascript

I am just starting to learn about Javascript for animation. I have created this super simple example, which when clicked moves 3 blocks from a central position, to top, top-left and top-right position (I am building up to a sort of Context Action button type thing). But I would now like to be able to click again and if the animation is "out", then it will execute in reverse. I tried adding an if else, using the elem1.style.bottom == 350 parameter to define whether pos would increment or decrement, but it didn't work. Similarly, I was unable to get a clicked boolean to persist between clicks.
JSFiddle
html:
<body>
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id ="container">
<div id ="animate1"></div>
<div id ="animate2"></div>
<div id ="animate3"></div>
</div>
</body>
css:
#container {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#animate1 {
width: 50px;
height: 50px;
left: 175px;
bottom: 175px;
position: absolute;
background-color: red;
z-index:3;
}
#animate2 {
width: 50px;
height: 50px;
left: 175px;
bottom: 175px;
position: absolute;
background-color: blue;
}
#animate3 {
width: 50px;
height: 50px;
left: 175px;
bottom: 175px;
position: absolute;
background-color: green;
}
Javascript:
function myMove() {
var elem1 = document.getElementById("animate1");
var elem2 = document.getElementById("animate2");
var elem3 = document.getElementById("animate3");
var start = 350;
var pos = 175;
var id = setInterval(frame, 5);
var clicked = false;
function frame() {
if (pos == 350) {
clearInterval(id);
clicked = !clicked;
} else {
if (clicked == false){ pos++; } else { pos--;}
elem1.style.bottom = pos + 'px';
elem1.style.left = start - pos + 'px';
elem2.style.bottom = pos + 'px';
elem2.style.left = pos + 'px';
elem3.style.bottom = pos + 'px';
}
}
}
How would I achieve this?
I think this is what you want: http://jsfiddle.net/3pvwaa19/20/
It creates a variable to keep track of whether the animation has happened and it moves your pos variable to the same location - - outside of the main function, so that the values won't get lost after each click:
var moved = false;
var pos = 175;
Yes, you can do it with if(elem1.style.bottom =="350px") {...}else{...:
function myMove() {
var elem1 = document.getElementById("animate1");
var elem2 = document.getElementById("animate2");
var elem3 = document.getElementById("animate3");
if (elem1.style.bottom == "350px"){
var start = 175;
var pos = 350;
var id = setInterval(frame, 5);
function frame() {
if (pos == 175) {
clearInterval(id);
} else {
pos--;
elem1.style.bottom = pos + 'px';
elem1.style.left = 2*start - pos + 'px';
elem2.style.bottom = pos + 'px';
elem2.style.left = pos + 'px';
elem3.style.bottom = pos + 'px';
}
}
} else {
var start = 350;
var pos = 175;
var id = setInterval(frame, 5);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem1.style.bottom = pos + 'px';
elem1.style.left = start - pos + 'px';
elem2.style.bottom = pos + 'px';
elem2.style.left = pos + 'px';
elem3.style.bottom = pos + 'px';
}
}
}
}

How to detect object collision for this JavaScript game

Trying to put together a small game for practice and I came across a issue. The point is to catch the goblin but I don't know how to make the game detect that player has hit the goblin.
So far you can only detect touched if your position Y and X matches with the enemies axis. How can I either increase the width for both or a better way of detecting touch.
try it out here: https://jsfiddle.net/acbkk7cs/4/
Style:
#map{
margin: 0 auto;
height: 510px;
width: 510px;
background-image:url(background.png);
}
.character{
background-image:url(character.png);
z-index:1;
position: relative;
top: 150px;
left: 150px;
height: 32px;
width: 33px;
}
.monster{
background-image:url(monster.png);
position: relative;
height: 32px;
width: 30px;
}
Javascript:
$(document).ready(function(){
var char = {
player : $(".character"),
x: 150,
y: 150
};
var monster = {
npc : $(".monster"),
x: 100,
y: 100
};
var keypush = {};
$(document).on("keydown keyup", function(e){
var keyN = e.which;
keypush[keyN] = e.type === "keydown";
});
function moveCharacter(){
if (keypush[37]) char.x -=2;
if (keypush[38]) char.y -=2;
if (keypush[39]) char.x +=2;
if (keypush[40]) char.y +=2;
char.player.css({transform:"translate3D("+ char.x +"px, "+ char.y +"px, 0)"});
monster.npc.css({transform:"translate3D("+ monster.x +"px, "+ monster.y +"px, 0)"});
var playerPosX = char.player.position().top;
var monsterPosX = monster.npc.position().top;
var playerPosY = char.player.position().left;
var monsterPosY = monster.npc.position().left;
if ( playerPosX === monsterPosX
&& playerPosY === monsterPosY
){
document.getElementById("pos").innerHTML="Touched";
} else {
document.getElementById("pos").innerHTML="Off";
}
//backend logs
console.log(char.x);
}
(function engine(){
moveCharacter();
window.requestAnimationFrame(engine);
}());
});
HTML:
<div id = "map">
<div class = "character">
</div>
<div class = "monster">
<p id = "pos" style = "color:yellow;font- weight:bold;position:relative;left:5px;font-size:20px;">Position: </p>
</div>
</div>
The easiest and fastest way is to calculate the distance between the character and the monster: fiddle using circle collision.
var dx = playerPosX - monsterPosX,
dy = playerPosY - monsterPosY,
touchDistance = 30;
if ( Math.sqrt( dx * dx + dy * dy ) < touchDistance )
document.getElementById("pos").innerHTML="Touched";
else
document.getElementById("pos").innerHTML="Off";
Here, I eyeballed the touchDistance, but it's actual value should be the sum of the radius of the player sprite and the radius of the monster sprite. This works best if they are circles:
/**
* (ax,ay) and (bx,by) are the center positions, and ar, br their radii.
*/
function circleCollision( ax, ay, ar, bx, by, br ) {
return Math.sqrt( (ax-bx)*(ax-bx) + (ay-by)*(ay-by) ) <= ar + br;
}
A second common way to determine collision is to use 'bounding boxes', or in this case, rectangles/squares: Fiddle using rectangle collision.
function rectangleCollision( pLeft, pTop, pRight, pBottom, mLeft, mTop, mRight, mBottom ) {
return
( (pLeft >= mLeft && pLeft < mRight ) || (pRight >= mLeft && pRight < mRight ) )
&& ( (pBottom >= mTop && pBottom < mBottom) || (pTop >= mTop && pTop < mBottom) )
}

Categories