So, i've coded this canvas animation and I would like the shape to move faster though when doing so the shapes desync.
When I increment the values show below, so that the shapes would faster, they do so but eventually move away from eachother and desync.
if (this.dir[i][j] === 'downright') { //go down and right
this.boxLines[i][j].y += 1;
this.boxLines[i][j].x += 1;
}
if (this.dir[i][j] === 'downleft') { //go down and left
this.boxLines[i][j].y += 1;
this.boxLines[i][j].x -= 1;
}
if (this.dir[i][j] === 'upright') { //go up and right
this.boxLines[i][j].y -= 1;
this.boxLines[i][j].x += 1;
}
if (this.dir[i][j] === 'upleft') { //go up and left
this.boxLines[i][j].y -= 1;
this.boxLines[i][j].x -= 1;
}
Any way to fix that or could i go about it some other way?
Link to jsfiddle: https://jsfiddle.net/frankpettersson/nqmy3fkd/7/
Related
I'm trying to create a slider with an image gallery and to make it scroll smooth using the requestAnimationFrame.
It works almost perfect except one thing. If you slide more then 2 times in any direction the scroll speeds up and it looks bad. I would like to have the same speed every time I slide to right or left.
Can anyone give me a hint of how to do that?
var currentPos = -200;
var incrementer = .05;
var id;
function scrollNext() {
incrementer += 1;
currentPos = Math.pow(1.05, incrementer);
item.scrollLeft += currentPos;
id = requestAnimationFrame(scrollNext);
if (!curr_slide.nextElementSibling) {
if (item.scrollLeft >= curr_slide.offsetLeft) {
item.scrollTo(curr_slide.offsetLeft, 0);
cancelAnimationFrame(id);
}
if (item.scrollLeft < curr_slide.offsetLeft) {
item.scrollTo(curr_slide.offsetLeft, 0);
cancelAnimationFrame(id);
}
} else {
if (item.scrollLeft >= curr_slide.nextElementSibling.offsetLeft) {
item.scrollTo(curr_slide.nextElementSibling.offsetLeft, 0);
cancelAnimationFrame(id);
}
}
}
scrollNext();
curr_slide.nextElementSibling.classList.add('activeSlide');
curr_dot.nextElementSibling.classList.add('currentDot');
I'm making a sliding puzzle (something like this) using HTML, CSS and JavaScript/jQuery.
Everything works fine, but I want to add a sliding transition each time a slide moves.
The code works based on the following logic:
12, 16 or 48 <div>s are created (depending on the level of difficulty).
A background-image is assigned to all of them, and cropped accordingly to simulate a "piece" of the original image.
They all have a class of image, and also piece<number>, where <number> is the number of the tile. The last tile (piece12, piece16 or piece48) also has a class of voidBlock, that removes the background-image. This is the empty tile that permits the ones directly next to it to move into its place. All the other tiles have an additional class, imgBlock.
When one of the tiles that are next to the voidBlock is clicked, it exchanges classes with the voidBlock. For example, if we were to click piece6, which happens to be next to the voidBlock(let's say the difficulty is set to easy, and thus voidBlock is piece12), this would happen:
The original voidBlock changes its piece12 class to piece6.
The original voidBlock changes its voidBlock class to imgBlock.
The original piece6 changes its piece6 class to piece12.
The original piece6 changes its imgBlock class to voidBlock.
After that, a draw() function is called; it sets the background-position of each tile, depending on its piece number.
As you might have guessed by now, none of the <div>s actually move. They remain still as the background-position of their background-image changes through their classes.
Although I do have some experience in programming (namely in Python and Java), web development in general is very new to me. I have tried various methods of transitioning, but the best thing I could come up with was to have the background image move each time a tile moved (which is just weird and unintuitive).
My question is, thus: is there any way to have an animation/transition of the tiles sliding each time that they move?
Code
(the lines that are commented out have nothing to do with the question)
CSS:
Part of the main.css file:
.image {
background-image: url(/Users/user/puzzle-test/img/image001.jpg);
width: 200px;
height: 200px;
display: inline-block;
vertical-align: top;
margin: 10px 10px 10px 10px;
}
.voidBlock {
background-image: none;
}
.imgBlock {
background-image: url(/Users/user/puzzle-test/img/image001.jpg);
}
JavaScript/jQuery:
The <div> click handler:
var clickHandler = function() {
var voidPosX = $(".voidBlock").css("left");
var voidPosY = $(".voidBlock").css("top");
voidPosX = parseInt(voidPosX.substring(0, voidPosX.length-2));
voidPosY = parseInt(voidPosY.substring(0, voidPosY.length-2));
var posX = $(this).css("left");
var posY = $(this).css("top");
posX = parseInt(posX.substring(0, posX.length-2));
posY = parseInt(posY.substring(0, posY.length-2));
if((voidPosX == posX - finalWidth) && (voidPosY == posY)){
posX -= finalWidth;
voidPosX += finalWidth;
move($(this));
}else if((voidPosX == posX + finalWidth) && (voidPosY == posY)){
posX += finalWidth;
voidPosX -= finalWidth;
move($(this));
}else if((voidPosY == posY - finalHeight) && (voidPosX == posX)){
posY -= finalHeight;
voidPosY += finalHeight;
move($(this));
}else if((voidPosY == posY + finalHeight) && (voidPosX == posX)){
posY += finalHeight;
voidPosY -= finalHeight;
move($(this));
}
}
The move function (used in the click handler) (h and v are the horizontal and vertical dimensions of the puzzle):
function move(element) {
//moveCounter++;
var temp = element.attr("class").split(" ");
for(var i = 0; i < temp.length; i++){
if(temp[i].substring(0, 5) == "piece"){
var pieceNum = temp[i].substring(5);
}
}
element.addClass("tempBlock1");
$(".voidBlock").addClass("tempBlock2");
element.filter(".tempBlock1").addClass("piece"+(h*v));
element.filter(".tempBlock1").removeClass("piece"+pieceNum);
element.filter(".tempBlock1").addClass("voidBlock");
element.filter(".tempBlock1").removeClass("imgBlock");
$(".voidBlock").filter(".tempBlock2").addClass("piece"+pieceNum);
$(".voidBlock").filter(".tempBlock2").removeClass("piece"+(h*v));
$(".voidBlock").filter(".tempBlock2").addClass("imgBlock");
$(".voidBlock").filter(".tempBlock2").removeClass("voidBlock");
$(".tempBlock1").removeClass("tempBlock1");
$(".tempBlock2").removeClass("tempBlock2");
draw();
}
The draw function (the numbers 800 and 600 represent the dimensions of the image):
function draw() {
//var imgSelect = $("input[type='radio'][name='bgImage']:checked").val();
var j = 1;
for(var pY = 0; pY > -600; pY -= finalHeight){
for(var pX = 0; pX > -800; pX -= finalWidth){
$(".piece"+j).css("background-position", pX+"px "+pY+"px");
//$(".piece"+j).css("background-image", "url(/Users/user/puzzle-test/img/"+imgSelect+".jpg)");
//$(".piece"+j).find(".helpNum").text(j);
j++;
}
}
//$(".move").text("Moves: " + moveCounter);
$(".voidBlock").css("background-image", "none");
//$(".grid").find("img").attr("src", "img/"+imgSelect+".jpg");
//$(".image:not(.voidBlock)").css("cursor", "pointer");
//$(".voidBlock").css("cursor", "default");
}
Finally, the <div>s are created by the shuffle function, like this (pieces is a shuffled array of the puzzle pieces, basically used to tell where to position each tile):
// DRAW
for(var i = 0; i < pieces.length; i++){
// HTML
var el = "<div class=\"image piece"+(pieces[i])+"\"><p class=\"helpNum\"></p></div>";
$(".grid").append(el);
$(".piece"+(h*v)).addClass("voidBlock");
}
// CSS div positioning
var j = 0;
for(var pY = 0; pY > -600; pY -= finalHeight){
for(var pX = 0; pX > -800; pX -= finalWidth){
$(".piece"+pieces[j]).css({left: pX, top: pY});
j++;
}
}
I finally solved it thanks to #BillyNate 's answer, which was to set the position property of the <div>s to absolute, then move them by changing the top and left properties.
I'm trying to do a copy of the original super mario game using html5 canvas just for fun and to learn more about the canvas tool and it's animation but i am stuck at making Mario do it's jump here is my jsfiddle : http://jsfiddle.net/2tLCk/1/
how should i fix my up function to make mario jump and return back to the ground like in this website http://blog.nihilogic.dk/ i tried to understand it's code but i couldn't ?
if (keydown.up) {
vy += gravity;
character.CurentPos = 11;
character.x += character.speed;
character.y += vy;
}
Here's a jumping Mario http://jsfiddle.net/2tLCk/22/.
If jumping is 1 - going up. If jumping is 2 - going down.
if(jumping){
if(jumping == 1) {
if(character.y > 140) character.y -= gravity;
else jumping = 2;
} else if(jumping == 2) {
if(character.y < 184) character.y += gravity;
else{
character.y = 184;
jumping = false;
character.CurentPos = 6;
}
}
}else if(keydown.up) {
jumping = 1;
character.CurentPos = 11;
}
And you would probably want to use this https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame instead of setInterval().
You basically want the gravitiy to be always active, not only when pushing the down key.
When jumping (key up) you have to add to vy. Like this:
if(keydown.up) {
vy += -2;
}
vy += gravity;
if(character.y > 184) { // simple collision detection for ground floor
vy = 0;
character.y = 184;
}
//character.CurentPos = 11;
//character.x += character.speed;
character.y += vy;
see http://jsfiddle.net/pjQb3/
I would do something like this:
// Global forces
character.vy += gravity;
// User input
if (keydown.up) {
character.vy += -2;
}
// Final location
if (character.y + character.vy >= 184) {
// Update player location.
character.y += character.vy;
} else {
// Player was about to move past ground so place player directly on ground
// and reset velocity.
character.y = 184;
character.vy = 0;
}
I've been trying to code a solution to project Euler's problem 349 in javascript (I know this is a less than ideal language for this). The problem is basically Langtons ant but with 10^18 moves. A full description of the challenge can be seen here . I managed to get some working code where I use a array as the grid of squares. If a value in the array is 1 then its black, if its 0, its white. Now the problem with this code is it is much too slow, it takes about 28 seconds to calculate 1 million moves. Any ideas on how I might go about optimizing this code?
var grid = [];
for (i = 0; i < 1000000; i++) {
grid.push(0);
}
var sum = 0;
var orientation = 0;
var position = (grid.length / 2);
var rowLength = Math.sqrt(1000000);
var mover = function() {
switch (orientation) {
case -360:
position += 1;
break;
case -270:
position += rowLength;
break;
case -180:
position -= 1;
break;
case -90:
position -= rowLength;
break;
case 0:
position += 1;
break;
case 90:
position += rowLength;
break;
case 180:
position -= 1;
break;
case 270:
position -= rowLength;
break;
case 360:
position += 1;
break;
default:
alert("fault in clockwise switch");
}
};
var check = function() {
for (i = 0; i < grid.length; i++) { //counts all blacks (1's)
if (grid[i]) {
sum += 1;
}
}
};
var movement = function() {
for (i = 0; i < 1000000; i++) { // end condition of i is number of steps
if (grid[position]) //if it lands on a black
{
grid[position] = 0;
if (orientation === 360) { //keeps orientation below 360
orientation = 0;
}
orientation += 90; //90 degree clockwise turn
mover();
} else if (!grid[position]) { //if it lands on a white
if (!grid[position]) {
if (orientation === -360) {
orientation = 0;
}
grid[position] = 1;
orientation -= 90;
mover();
}
}
}
};
movement();
check();
console.log(position);
console.log(sum);
Langtons's ant eventually falls into a pattern and builds a "highway". You don't need to actually run for 10^18 iterations to identify this pattern and use it to predict the number of black squares at any future time.
I've been trying to get this javascript animation to work for hours now, and I got nothing. The problem isn't getting my div box to move from left to right(or from top to bottom), it's the opposite of each case that I have trouble with it. Here's what I have so far(In addition, I have set boundaries set to keep my moving box contained within the view window so if it hits any one of sides, it should move to the opposite direction). Any help is awesome at this point.
Note: the next step is to create a bouncing effect for the box, but i'll worry about that once i get simple animation working.
setInterval(function(){
if(parseInt(box.style.left) > parseInt(viewDim.width - 57)){
box.style.left -= parseInt(box.style.left) - 2 + 'px';
/* } else if(parseInt(box.style.left) < 0){
//debug_log("HIT!!");
//parseInt(box.style.left) += 2 + 'px';
} else if(parseInt(box.style.top) > parseInt(viewDim.height-58)){
} else if(parseInt(box.style.top) < 0){*/
} else {
box.style.left = parseInt(box.style.left) + 2 + 'px';
//box.style.top = parseInt(box.style.top) + 5 + 'px';
}
}, 20);
Code like this always works for me:
var boxWidth = 57, delta = 2;
setInterval(function(){
var left = parseInt(box.style.left);
if(left >= parseInt(viewDim.width - boxWidth)){
delta = -2;
}
if (left <= 0) {
delta = 2;
}
box.style.left = left + delta + 'px';
}, 20);
Although you have your solution now, I couldn't help myself from making complete code here.
The bouncing box bounces around inside the parent element. Tested in IE8, FF3, and Opera11.
This can give an idea, how to do it with jQuery
http://jsfiddle.net/rFkpy/
$('#myDiv').click(function() {
$(this).animate({
left: '+=250'
}, 1500, "easeOutBounce", function() {
// callBack
});
});