I'm developing a 2D game with javascript. I have to detect if a player is in a certain position (a door or a wall) in order to make some actions. The collisions work well on my desktop but if I change resolution all positions i checked before doesn't work anymore. Is there any way to improve a good collision detection system that works also if i change the desktop's resolution ?
What i'm doing right now is pretty like this :
Here is the html structure:
<div id="container">
<div id="main">
<img id="palyer" src="../img/sprites/pleyer.png">
</div>
Here is the css:
#container{
margin: auto;
width: 60%;
height: 80%;}
#main{
position: relative;
margin: auto;
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-size: contain; }
#player{
position: relative;
top: 100px;
left: 400px;}
And the js:
var position = $("#player").position();
if((position.left<=55)&&(position.top>=183)&&(position.top<=215)){
changeRoom();}
It is hard to suggest without seeing the rest of the code, but one way around the problem is to have two variables to hold values for X and Y ratios. Then you multiply all your coordinates by these ratios every time you use it. The last piece needed is to update those ratios every time your game is resized, with something like this
window.onresize = function onResize(event) {
var canvas = document.getElementById('myGameScreen'); // reference to your html element
var newHeight = canvas.clientHeight;
var newWidth = canvas.clientWidth;
var ratioY = newHeight / oldHeight;
var ratioX = newWidth / oldWidth;
...
...
...
// save new dimensions for the next resize event
oldHeight = newHeight;
oldWidth = newWidth;
}
Related
I'm creating an Electron program that loops a video comprising of adverts. The video spans the entire window. Let's call this window A.
There is a second, smaller window used to configure aspects of window A. Let's call this window B.
The purpose of window B is to control aspects of window A in real time, such as overlaying a message over the video or hiding the video controls. Here's an image to explain further:
Seen in the photo above, there is a further window open displaying a smaller video. Let's call this window C. The blue rectangle can be dragged around and represents a message that will be display over the video on window A.
If I save the coordinates of that rectangle and create an element on the window A video, the coordinates don't match up due to the difference in window sizes. What I can't figure out is how to take the coordinates in window C and apply them to window A correctly. I've tried working with clientWidth/clientHeight and messing with numerous CodePen's to no avail.
Any help would be greatly appreciated.
Each pixel in the smaller div equals X pixels in the bigger div. That's the ratio to multiply with. Let's assume mouse movement inside smaller div is like dragging and affecting the bigger div.
var small = document.querySelector(".small");
var big = document.querySelector(".big");
var rectangle = document.querySelector(".rectangle");
var ratioX = big.clientWidth / small.clientWidth
var ratioY = big.clientHeight / small.clientHeight
small.addEventListener("mousemove", function(ev) {
var mx = ev.offsetX
var my = ev.offsetY
rectangle.style.left = mx * ratioX + "px"
rectangle.style.top = my * ratioY + "px"
})
.small {
width: 100px;
height: 50px;
border: 1px solid black;
}
.big {
width: 300px;
height: 150px;
border: 1px solid black;
position: relative;
overflow: hidden;
}
.rectangle {
width: 20px;
height: 20px;
background: blue;
position: absolute;
}
Mouse over this:
<div class="small">
</div>
Will move this:
<div class="big">
<div class="rectangle">
</div>
</div>
I'm very newbie to webdev, but I need to draft a landingpage with some trick effects.
I need to put a "stencil image" (png with transp) over a moving (mouse hover) background.
Basically, I managed to do that, but I having a big issue: If I resize browser, the background shows behind first plane image, (because I can't rezise background to browser size).
So, the main codes are:
html code:
<div id="bkg-image" class="blur"></div>
<div>
<img src="./imgs/stencil.png" class="firstPlane" />
</div>
CSS code:
#bkg-image {
background: url('./imgs/background.jpg') no-repeat center center fixed;
position: absolute;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
width: 75%;
height: 75%;
z-index: 0;
-webkit-filter: brightness(1.7);
}
.firstPlane {
display: block;
position: absolute;
top: 0px;
left: 0px;
max-width: 100%;
height: auto;
width: auto;
z-index: 2;
}
JS code:
$(document).ready(function() {
var movementStrength = 75;
var height = movementStrength / $(window).height();
var width = movementStrength / $(window).width();
$(".firstPlane").mousemove(function(e) {
var pageX = e.pageX - ($(window).width() / 2);
var pageY = e.pageY - ($(window).height() / 2);
var newvalueX = width * pageX * -1;
var newvalueY = height * pageY * -1;
$('#bkg-image').css("background-position", newvalueX + "px " + newvalueY + "px");
});
});
Any idea how to crop the excess background or how to rescale it to fit behind firstplane image?
note: blur class is just for an animated blur effect, not relevant to this.
I took the java script from a net tutorial.
My first aproach was using webkit mask-image, but seens it don't works, now I'm trying this method.
Thanks a lot for any help
You are doing it upside down. This is how it should be.
$(document).ready(function() {
$("#bkg-image").mousemove(function(e) {
$('.firstPlane').css({left: e.pageX + "px", top: e.pageY + "px"});
});
});
I need invert the selection: I need read the mouse position on first plane and apply movement to the bkg image. (your script only works if I switch #bkg-image and .firstPlane). My issue isn't read the movement, but crop bkg-image to not show it bellow 1st plane when I have a small and tall browser window.
The solution would be a mask/clip image, but its not working for svg graphics or PNG for me, so I give up and tried with a big black PNG with transp on it to show background.
Something like this: (https://codepen.io/caraujo/pen/rVOZKJ) but with a logo (vector or png), but mask/image clip is not working for me :/
I have image with width: 100%; height: auto; and on this image are other elements with position: absolute; left: x; top: x; (it's a game).
When I was resizing the page, elements weren't moving (it was messing up), so I wrote this:
// on start
var img = document.getElementById('world_image');
startImageSize.w = img.clientWidth;
startImageSize.h = img.clientHeight;
actImageSize.w = startImageSize.w;
actImageSize.h = startImageSize.h;
// on resize
var img = document.getElementById('world_image');
actImageSize.w = img.clientWidth;
actImageSize.h = img.clientHeight;
// update (each tick)
$("#cr_" + this.ID).animate({
"left" : (this.x - ((startImageSize.w - actImageSize.w) / 2)) + "px",
"top" : (this.y - ((startImageSize.h - actImageSize.h) / 2)) + "px"
}, speed);
But it's not working corretly, here is short GIF representing what is happening:
A "red point" is moving faster than it shoud be.
// EDDIT! JSFiddle with whole project https://jsfiddle.net/BrunonDEV/18mqyd8r/1/
What am I doing wrong?
I wouldn't try to reposition those in JS - it's slow, makes resizing janky, and chews the javascript cycles you'll need for actually running your game, and it's not necessary anyway. Why not just set your dot's position in %, like this:
.map {
background: #68B1FF url('https://upload.wikimedia.org/wikipedia/commons/5/5e/BlankMap-World-Sovereign_Nations.svg') center top no-repeat;
background-size: contain;
position: relative;
height: 0;
padding-top: 51.2%; /* The original map image is 1104 x 566px. This is the aspect ratio as a percentage of height to width */
width: 100%;
}
.marker {
border-radius: 50%;
width: 1vw; /* These allow the markers to scale with the map */
height: 1vw;
background: red;
min-height: 8px;
max-height: 16px;
min-width: 8px;
max-width: 16px;
position: absolute;
}
<div class="map">
<div class="marker" style="top: 20%; left: 33%;"></div>
</div>
One of the important pieces here is fixed aspect ratio boxes in CSS - if you set height to 0, and padding-top (or bottom) to a percentage, the padding height is calculated as a percentage of the width, not the height as you might expect.
For bonus points, you should use an SVG map image - then it'll scale cleanly, too.
I'm building a fluid website in which an image must scale to a maximum size depending on the viewport of the browser (minus some margins). I don't want the image to crop or lose its original proportions, so depending on the width or height it should resize to the maximum size possible without cropping.
I wrote some javascript code, but since I'm not a hardcore coder I was wondering how to fix this in the right way. The script works, but has a bug when resizing. It seems that it only processes one if statement when resizing the browser window.
function setSizes() {
var margin_top = 100;
var margin_right = 85;
var margin_bottom = 10;
var margin_left = 85;
// get image width and height
var img_w = $('.gallery_img').width();
var img_h = $('.gallery_img').height();
// calculate viewport width and height
var vp_w = $(window).width() - margin_right - margin_left;
var vp_h = $(window).height() - margin_top - margin_bottom;
//
if (vp_w <= img_w || vp_w > img_w) {
// new width
var img_w_new=vp_w;
// calculate new height
var img_h_new=Math.round((img_h*img_w_new) / img_w);
}
//
if (vp_h <= img_h || vp_h > img_h) {
// new height
var img_h_new=vp_h;
// calculate new width
var img_w_new=Math.round((img_w*img_h_new) / img_h);
}
// change image width and height to new width and new height
$('.gallery_img').width(img_w_new);
$('.gallery_img').height(img_h_new);
}
// onload
$(window).load(function(){ setSizes(); });
// on resize
$(window).bind("resize", function() { setSizes(); });
I searched for a solution for quite some time, but most scripts I found only check and change the width.
Does somebody know how to fix this?
Thanx!
this might be a lame answer but why don't you just use css width setting?
see http://jsfiddle.net/dXm4r/
I think this is a wrong approach? It would be more natural to define width of enclosing container in percents and than define width 100% on image. Something like this:
div.img-container {
width: 30%;
}
div.img-container img {
display: block;
width: 100%;
}
<div class="img-conatiner">
<img src="...
</div>
Please pay attention to the fact that in img CSS rule there is no height specified, this will allow browsers to properly scale image without loosing quality.
You have a line to change the width; simply add a line to change the height, based on your height variable. You can figure out what the height should be by dividing the new width by the old width. Basically, that is the multiple of widths in the new width, which is equal to the multiple of heights in the new height. Therefore, if you multiply that number to the old height, you would get the new height.
Here is the equation you could use:
img_h_new = (img_w_new / img_w) * img_h;
And this is the function you could use with your width function:
$('.gallery_img').height(img_w_new);
http://blog.francois-becker.net/post/2012/08/16/HTMLCSS-container-of-a-maximized-image
you can done it by css ,just apply this css to your image element
.img { /* image*/
position: absolute;
top: 10px;
right: 85px;
bottom: 10px;
left: 85px;
width: calc( 100% - 170px); /* 170 = marging left + right*/
height: calc(100% - 20px); /* 20px = marging top + bottomt*/
background-size: cover;
box-sizing: border-box;
padding: 0px;
}
body { /* container*/
margin: 0px;
padding: 0px;
height: 100%
width:100%;
overflow:hidden;
}
<html>
<body>
<img class="img" src="http://kingofwallpapers.com/picture/picture-004.jpg" > </img>
</body>
</html>
How can I scale a div to fit inside the browser view port but preserve the aspect ratio of the div. How can I do this using CSS and/or JQuery?
Thanks!
You don't need javascript for this. You can use pure CSS.
A padding-top percentage is interpreted relative to the containing block width. Combine it with position: absolute on a child element, and you can put pretty much anything in a box that retains its aspect ratio.
HTML:
<div class="aspectwrapper">
<div class="content">
</div>
</div>
CSS:
.aspectwrapper {
display: inline-block; /* shrink to fit */
width: 100%; /* whatever width you like */
position: relative; /* so .content can use position: absolute */
}
.aspectwrapper::after {
padding-top: 56.25%; /* percentage of containing block _width_ */
display: block;
content: '';
}
.content {
position: absolute;
top: 0; bottom: 0; right: 0; left: 0; /* follow the parent's edges */
outline: thin dashed green; /* just so you can see the box */
}
The display: inline-block leaves a little extra space below the bottom edge of the .aspectwrapper box, so another element below it won't run flush against it. Using display: block will get rid of it.
Thanks to this post for the tip!
Another approach relies on the fact that browsers respect an image's aspect ratio when you resize only its width or height. (I'll let google generate a 16x9 transparent image for demonstration purposes, but in practice you would use your own static image.)
HTML:
<div class="aspectwrapper">
<img class="aspectspacer" src="http://chart.googleapis.com/chart?cht=p3&chs=160x90" />
<div class="content">
</div>
</div>
CSS:
.aspectwrapper {
width: 100%;
position: relative;
}
.aspectspacer {
width: 100%; /* let the enlarged image height push .aspectwrapper's bottom edge */
}
.content {
position: absolute;
top: 0; bottom: 0; right: 0; left: 0;
outline: thin dashed green;
}
Thanks to Geoff for the tip on how to structure the math and logic. Here's my jQuery implementation, which I'm using to size a lightbox so it fills the window:
var height = originalHeight;
var width = originalWidth;
aspect = width / height;
if($(window).height() < $(window).width()) {
var resizedHeight = $(window).height();
var resizedWidth = resizedHeight * aspect;
}
else { // screen width is smaller than height (mobile, etc)
var resizedWidth = $(window).width();
var resizedHeight = resizedWidth / aspect;
}
This is working well for me right now across laptop and mobile screen sizes.
I have a different pure HTML/CSS approach which does not rely on padding or absolute positioning. Instead it uses em units and relies on the CSS min() function plus a little bit of math.
Imagine that we want a viewport div with 16:9 aspect ratio which always fits the browser window and is centered in the axis with excess space. Here's how we can accomplish that:
HTML
<body>
<div class="viewport">
<p>
This should be a 16:9 viewport that fits the window.
</p>
</div>
</body>
CSS
body {
width: 100vw;
height: 100vh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: white;
font-size: min(1vw, 1.778vh);
}
div.viewport {
width: 100em;
height: 56.25em;
background-color: lightblue;
}
div.viewport > p {
font-size: 3em;
text-align: center;
}
You can experiment with this in a sample JSFiddle here.
The secret sauce is in the body font-size. It should be set to min(1vw, Avh), where A is the aspect ratio you want the div to have, i.e. width / height. In the example above we're using 1.778, which is approximately 16 / 9.
In CSS, em units are based on the font-size of the element, which is inherited from parent element if not explicitly set. For your viewport div, set the width to 100em (NOT rem) and the height to Iem, where I is the inverse of the aspect ratio expressed as a percentage, i.e. 100 / A or 100 * height / width. In the example above we're using 56.25, which is 100 * 9 / 16.
One bonus of this approach is that all of your nested elements may also use em units so that they always scale precisely with the size of the viewport. You can see this used on the p element in the example.
Note that as an alternative to the above, you may set the font-size on your html element and use rem units everywhere. CSS rem units are similar to em units but always relative to the root element's font-size.
Javascipt:
//Responsive Scaling
let outer = document.getElementById('outer'),
wrapper = document.getElementById('wrap'),
maxWidth = outer.clientWidth,
maxHeight = outer.clientHeight;
window.addEventListener("resize", resize);
resize();
function resize(){
let scale,
width = window.innerWidth,
height = window.innerHeight,
isMax = width >= maxWidth && height >= maxHeight;
scale = Math.min(width/maxWidth, height/maxHeight);
outer.style.transform = isMax?'':'scale(' + scale + ')';
wrapper.style.width = isMax?'':maxWidth * scale;
wrapper.style.height = isMax?'':maxHeight * scale;
}
HTML:
<div id="wrap">
<div id="outer">
{{ fixed content here }}
</div>
</div>
Styling:
/* Responsive Scaling */
#wrap {
position: relative;
width: 1024px;
height: 590px;
margin: 0 auto;
}
#outer {
position: relative;
width: 1024px;
height: 590px;
transform-origin: 0% 0%;
overflow: hidden;
}
This is possible with JQuery and a bit of maths.
Use JQuery to get the view ports width and height as well as the divs current dimensions.
$(document).width();
Calculate the divs current aspect ratio. eg width/height
You need a bit of logic to determine whether to set the width or height first, then use the initial ratio to calculate the other side.
jQuery has a plugin that grows an object until one of it's sides reaches a certain px-value. Coupling this will the viewport's height, you could expand any element to that size: jQuery MaxSide.