I've got quite a rudementary question that I can't really seem to fix myself. I've already looked into similar answers, but none of the implementations seem to be possible implementations for me.
Basically I have an image(png) that moves around in a little box (here is the game).
The problem I'm facing is that the image should flip if you change the direction the sprite is moving (left-right) and that it should be able to jump.
The transitions work fine separately, but when I try to jump when faced left it turns right in the jump.
I need to remove the baddie-left before jumping, I suppose. But it doesn't seem to work when I've done it...
Full disclaimer: We are not supposed to use anything but 'normal' js (ie. no jquery).
Here is the js:
switch(key) {
case 32: //jumping
if(!baddie.classList.contains('baddie-jumping')){
baddie.classList.add('baddie-jumping');
window.setTimeout(function(){
baddie.classList.remove('baddie-jumping');
}, 350);
}
break;
case 37: //moving left
if (left_available(left - step)){
if(!baddie.classList.contains('baddie-left')){
baddie.classList.add('baddie-left');
}
left = left - step;
} else {
left = 150;
top = 130;
}
break;
case 38:
if (top_available(top - step)){
top = top - step;
} else {
left = 150;
top = 130;
}
break;
case 39: //moving right
if (left_available(left + step)){
if(baddie.classList.contains('baddie-left')){
baddie.classList.remove('baddie-left');
}
left = left + step;
} else {
left = 150;
top = 130;
}
break;
case 40:
if (top_available(top + step)){
top = top + step;
} else {
left = 150;
top = 130;
}
break;
}
And the css:
.content {
/* If #content position is absolute, the #baddie position will be given in reference to it's parent, which is #content
* Makes it easier to do collision calculations */
position: absolute;
width: 400px;
height: 300px;
border: solid 1px #000;
}
.baddie{
/* Baddie's postition must be absolute, otherwise we can't move him by changing top and left */
position: absolute;
height: 50px;
width: 50px;
/* Change this to your own baddie! */
background: url("../img/viking.png");
background-size: 50px;
transition: all 0.35s ease;
}
.baddie-left {
transform: rotateY(180deg);
}
.baddie-jumping {
transform: scale(1.5) translateY(-40px);
}
When you add .baddie-jumping class, it just overwrite transform property of .baddie-left class. You should add to your css:
.baddie-left.baddie-jumping {
transform: scale(1.5) translateY(-40px) rotateY(180deg);
}
Related
I have an element I am zooming in (one button) and then rotating (another button)
When I zoom in on the element the scale gets updated, then when I go to rotate element the scale is not kept from the zoom (but it really is, I can see the value is maintained browser debug) but it zooms back out to the initial scale when rotate is clicked.
let spin = 0;
let zoom = 1;
$('#SpinRight').click(function(){
//I know for a fact scale keeps value here, but zooms back out to original size when I //click spin
spin += 25;
$('#element').css({'transform' : 'rotate(' + spin + 'deg'});
})
$('#Magnify').click(function(){
zoom += 0.1;
$('#element').css({'transform' : 'scale(' + zoom + ')'});
})
transform rules don't stack, so if you do:
transform: rotate(45deg);
transform: scale(0.5);
The scale transform replaces the rotate rule, it doesn't add to it. If you want both you need to specify them both in a single rule:
transform: rotate(45deg) scale(0.5);
You could keep track of the rotation and scale in css properties and then have a rule that applies them both. (Or just apply them the way you're already doing it, but do both for each update.)
const demo = document.querySelector('.demo');
let rotate = 0;
let scale = 1;
document.querySelector('.rotate').addEventListener('click', () => {
demo.style.setProperty('--rotate', `${rotate += 10}deg`);
});
document.querySelector('.scale').addEventListener('click', () => {
demo.style.setProperty('--scale', scale += 0.1);
});
.demo {
--rotate: 0;
background: skyblue;
width: 100px;
height: 100px;
transform: rotate(var(--rotate, 0)) scale(var(--scale, 1));
}
button {
position: relative; /* just so the buttons stay on top */
}
<div class="demo"></div>
<button class="rotate">Rotate</button>
<button class="scale">Scale</button>
I'm creating a simple game: drag en element far enough (200px) The console logs fine, when I drag the element 200px the console reads 200px, but I still get the wrong message.(not there yet)..
function far_enough() {
console.log('You have moved the box ' + el.offsetLeft + 'pixels');
if(el.offsetleft == 200){
console.log('200px great!');
} else {
console.log('not there yet!');
}
}
}
To answer your question, element.offsetLeft can return a decimal value. This means that it may return 200.01px instead of 200px exactly. This is what's causing your code to not work. A simple work-around is simply to use Math.round(element.offsetLeft) to return an integer value. However, even when using this, there's a chance that the offsetLeft does not return 200px exactly, especially when you drag the element too fast (the browser does not repaint for each pixel moved). Another solution is to use a range like from 200px to 250px.
I suppose that you're using position: absolute and manipulating left CSS property to cause the element to be draggable. However, moving elements with transform is better than using position. I highly suggest reading this article on why.
As you're moving your element using transform now, the offsetLeft value of the element never changes. Therefore, you can alternatively get the rendered box position using getBoundingClientRect(). Here's an example using a getBoundingClientRect(), which returns a left value relative to the viewport.
const draggable = document.querySelector('#draggable')
function farEnough() {
const box = draggable.getBoundingClientRect()
// Get center of box; move center of box by 200px to return true
let center = box.left + (box.right - box.left) / 2
if (center >= 200 && center <= 300) return true
else return false
}
let dragging = false
let dragStartX = null
let dragStartY = null
let draggableMovedX = null
let draggableMovedY = null
function dragHandler(e) {
dragging = true
dragStartX = e.clientX
dragStartY = e.clientY
}
function moveHandler(e) {
if (dragging) {
let moveX = e.clientX - dragStartX + draggableMovedX
let moveY = e.clientY - dragStartY + draggableMovedY
draggable.style.transform = `translate(${moveX}px, ${moveY}px)`
if (farEnough()) {
draggable.removeEventListener('mousedown', dragHandler)
window.removeEventListener('mousemove', moveHandler)
window.removeEventListener('mouseup', leaveHandler)
dragging = false
dragStartX = null
dragStartY = null
// 175px so that the center of the box is exactly at 200px from the left
draggable.style.transform = `translate(175px, ${moveY}px)`
console.log('You did it! You moved it 200px to the right!')
}
}
}
function leaveHandler(e) {
dragging = false
dragStartX = null
dragStartY = null
const box = draggable.getBoundingClientRect()
draggableMovedX = box.left
draggableMovedY = box.top
}
draggable.addEventListener('mousedown', dragHandler)
window.addEventListener('mousemove', moveHandler)
window.addEventListener('mouseup', leaveHandler)
body,
html {
width: 100%;
height: 100%;
position: relative;
margin: 0;
}
#draggable {
width: 50px;
height: 50px;
border-radius: 5px;
background: #121212;
cursor: grab;
}
#draggable:active {
cursor: grabbing;
}
#line {
position: absolute;
top: 0;
left: 200px;
width: 2px;
height: 100%;
background: red;
transform: translateX(-50%);
}
<div id="draggable"></div>
<div id="line"></div>
try
function far_enough()
{
let leftOffset = el.offsetLeft;
console.log('You have moved the box ' + leftOffset + 'pixels');
if (leftOffset == 200)
{
console.log('200px great!');
}
else
{
console.log('not there yet!');
}
}
I'm trying to make a simple image move on the screen with the arrow keys up, down, left and right. It works fine except that the image keeps going out of the window and I can't see. What I want to do is keep the image within the window bounds and not go out of it.
Here's my code:
let height = $(window).height();
let width = $(window).width();
$(document).keydown(function(key) {
switch (parseInt(key.which, 10)) {
// Left arrow key pressed
case 37:
if ($('img').position().left > 0) {
$('img').animate({
left: "-=20px"
}, 'fast');
}
break;
// Up Arrow Pressed
case 38:
if ($('img').position().top > 0) {
$('img').animate({
top: '-=20px'
}, 'fast');
}
break;
// Right Arrow Pressed
case 39:
if ($('img').position().left < width) {
$('img').animate({
left: '+=20px'
}, 'fast');
}
break;
// Down Arrow Pressed
case 40:
if ($('img').position().top < height) {
$('img').animate({
top: '+=20px'
}, 'fast');
}
break;
}
});
body {
width: 100%;
height: 100%;
background: blue;
overflow: hidden;
/*This is the solution*/
}
img {
position: relative;
left: 0;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<img src="http://pngimg.com/uploads/mario/mario_PNG129.png" />
Seems like you just need to account for one more calculation. Using the right movement as an example, what happens if the current right position of the image is 5px from the edge of the screen? Then ($('img').position().right > width) would compute to true and it would move 20px, putting it 15px off the screen.
So, you simply need to account for this potential.
if($('img').position().right > 0){
distance = ( ($('img').position().left - width) < 20 ) ? ($('img').position().left - width) : 20;
$('img').animate({left: "+="+distance+"px"}, 'fast');
}
Here we are saying, if the current position of the image is less than 20px from the right edge, only move it that difference, otherwise, move it 20px.
Similar logic would need to be applied to the bottom to ensure the image does not move more than the height of the screen.
I would recommend applying the same logic to the bottom and left as well. The reason it doesn't move off the screen currently is because you are starting from 0,0 and move 20px at a time. It will always come back to 0,0. However, if you have to move it to the right 12px to stay within bounds, then when you move it back, you could run into the same issue on the left. Hope that makes sense.
i hope my code will bring you some clues
$(document).ready(function(){
//alert("This page has loaded!");
//Below is code which hides a paragraph when the button is clicked
$("button").click(function(){
$("p").hide("slow", function(){
alert("The paragraph is now hidden");
});
});
//let width=Math.max($(document).width(), $(window).width());
//let height=Math.max($(document).height(), $(window).height());
let height=$(window).height();
let width=$(window).width();
var w =document.body.clientWidth;
var h = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
//Below is code which allows for the character to move - why not try craft your own
//version?
$(document).keydown(function(key) {
//document.write(Math.max($(document).height(), $(window).height()));
// document.write(Math.max($(document).width(), $(window).width()));
switch(parseInt(key.which,10) ) {
// Left arrow key pressed
case 37:
if($('img').position().left>1 ){
$('img').animate({left: "-=70px"}, 'fast');}
break;
// Up Arrow Pressed
case 38:
if($('img').position().top >1 ){
$('img').animate({top: '-=20px'},'fast');}
break;
// Right Arrow Pressed
case 39:
if($('img').position().left<(w-185) ){
$('img').animate({left: '+=70px'},'fast');}
break;
// Down Arrow Pressed
case 40:
if($('img').position().top<(h-185) ){
$('img').animate({top: '+=70px'},'fast');}
break;
}
});
});
img {
position: relative;
left: 0;
top: 0;
right: 0;
}
body{
width: 100%;
height: 100%;
background: cyan;
overflow: auto;
}
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' type='text/css' href='stylesheet.css'/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!--Including jQuery -->
<script type='text/javascript' src="script.js"></script> <!-- Including the scripting file -->
</head>
<body>
<img
src="http://staublicht.net/wordpress/wp-content/uploads/2011/08/walk_animation.gif"/>
</body>
</html>
I have a overlay with empty height and width that covers the whole page once its clicked using a button, this overlay transition from top 0 left 0 all the way down to bottom right. once this over lay is closed I edited the css property using java script so that it transition finished on the bottom right.
The first time opening and close this overlay, it works fine, however the second time I open it, instead of starting from top left, it starts from bottom right and moves all the way to top left. I cant seem to fix this problem. I try resetting the left to 0 and top to 0 but it doesnt work.
document.querySelectorAll(".overlay_background")[0].addEventListener("click", parent);
function parent(event) {
this.style.left = this.clientWidth + "px";
this.style.top = this.clientHeight + "px";
this.style.height = 0;
this.style.width = 0;
}
function child(event) {
event.stopPropagation();
}
function http_request_availability() {
document.getElementById("overlay_background_id").style.left = "0";
document.getElementById("overlay_background_id").style.top = "0";
console.log(document.getElementById("overlay_background_id"));
document.getElementById("overlay_background_id").style.height = "100vh";
document.getElementById("overlay_background_id").style.width = "100vw";
document.getElementById("overlay_background_id").style.backgroundColor = "rgba(0,0,0, 0.5)";
document.body.style.overflow = "hidden";
}
.overlay_background {
position: fixed;
overflow: hidden;
height: 0;
width: 0;
left: 0;
top: 0;
transition: 0.7s ease;
z-index: 1;
}
<div class="overlay_background" id="overlay_background_id">
Hi this is my overlay
</div>
<button class='btn_ws' onclick='http_request_availability();'>Book Work-Shop</button></div>
The problem is your overlay never resets to its original position of top 0 and left 0.
Try adding this to the end of your parent() function:
var self = this;
setTimeout(function() {
self.style.left = 0;
self.style.top = 0;
}, 700);
This will reset the left and top positions to 0 after 700 ms has passed (the duration of the transition).
I'm trying to implement drag and drop for Mobile Safari.
Basically I want to drag a div via touch while it plays a looping CSS animation. I also want to determine when it's above a drop target and do something special.
I'm using elementFromPoint to determine what elements my div is being dragged over on touchmove events. However, the dragged div is always the topmost element. So before querying, I set it to display: none. However, this has the effect of resetting my animation every frame in which the touch moves.
How do I determine what I'm dragging above without resetting my CSS animation every time I query?
JSFiddle using touch events in WebKit.
HTML On every touchmove I move the drag div.
<div id='drop'>Drop here</div>
<div id='drag'>Drag me</div>
JavaScript
var drag = document.getElementById('drag');
var drop = document.getElementById('drop');
drag.addEventListener('touchmove', move, true);
function move(e) {
var touch = e.changedTouches[0];
drag.style.left = touch.pageX - 25 + 'px';
drag.style.top = touch.pageY - 25 + 'px';
drag.style.display = 'none';
if (drop === document.elementFromPoint(touch.pageX, touch.pageY)) {
drag.classList.add('in-drop-zone');
} else {
drag.classList.remove('in-drop-zone');
}
drag.style.display = 'inline';
}
CSS
div {
position: absolute;
}
div#drag {
width: 50px;
height: 50px;
background-color: blue;
-webkit-transform-origin: 50% 50%;
-webkit-animation: sway 1s infinite alternate;
}
div#drop {
width: 100px;
height: 100px;
background-color: green;
left: 200px;
top: 200px;
}
div#drag.in-drop-zone {
background-color: yellow;
}
#-webkit-keyframes sway {
from {
-webkit-transform: rotate(-30deg);
}
to {
-webkit-transform: rotate(30deg);
}
}
You could probably set pointer-events: none and then pointer-events: auto, but that seems pretty hacky. A better option is to have an intersection function:
var drag = document.getElementById('drag');
var drop = document.getElementById('drop');
var drop_bbox = drop.getBoundingClientRect();
window.addEventListener('touchmove', move, true);
window.addEventListener('mousemove', move, true);
function move(e) {
drag.style.left = e.clientX - 25 + 'px';
drag.style.top = e.clientY - 25 + 'px';
var drag_bbox = e.target.getBoundingClientRect();
drag.className = rectsIntersect(drag_bbox, drop_bbox) ? "in-drop-zone" : null;
}
function rectsIntersect(r1, r2) {
if (!r1 || !r2) return false;
return r2.left < (r1.left+r1.width) &&
(r2.left+r2.width) > r1.left &&
r2.top < (r1.top+r1.height) &&
(r2.top+r2.height) > r1.top;
};
Here is a JSFiddle http://jsfiddle.net/duopixel/SvPpw/