Canvas Ball bounces in wrong direction when pong paddle is moving - javascript
I would like to start off with a note. I tried using a jsfiddle but for some reason HTML5 canvas does not work. So as a workaround I used http://jsbin.com/gugihuwegopa/1/. To edit with this site, click the edit button at the top right corner of the window. Anyway, my problem is, when the paddle is not moving, the ball bounces correctly off all sides (The nomove variable has nothing to do with that, its just to make it disappear with the "w" key). However, when I move the paddle with the mouse towards the ball, it gets stuck inside the paddle. I think this is because it is not updating the location of the paddle fast enough so that the ball ends up inside of it, and my code continues to cause the ball to bounce even while inside. (until moving the paddle rapidly away and it gets unstuck). Yes I have tried putting the cxt.fillRect before the cxt.arc(). Sometimes the ball will travel through the paddle as well. I figure a way to fix this would be factoring in the direction of the ball in my two if statements:
if(y+ymove>=w && y+ymove<=w+h && x>=s && x<=s+l ) ymove*=-1; //top and bottom
if(x+xmove>=s && x+xmove<=s+l && y+ymove<=w+h && y+ymove>=w ) xmove*=-1; //left and right
Some other methods I have tried include:
if(y+ymove>=w && y+ymove<=w+h && x>=s && x<=s+l && centerY+17.5 < y+ymove+5 && centerX+12.5 < x+xmove+5) ymove*=-1; //top and bottom, extra +5 for radius
if(x+xmove>=s && x+xmove<=s+l && y+ymove<=w+h && y+ymove>=w && centerX+12.5 < x+xmove+5 && centerY+17.5 < y+ymove+5) xmove*=-1; //left and right
So basically I just need the ball to bounce correctly no matter how I move the paddle. Feel free to edit all you want, even if it means adding more if statements. All I ask is absolutely NO JQuery. Thanks in advance.
I would recommend to do your code more friendly in order to get help, removing comments and keep only the parts you need to fix.
About your problem one thing you could do is to use a flag, if the ball is hitting the paddle set the flag to True, do the redirection once and stop checking for the collision until the flag is false.
For sure there should be a better workaround but that's a start.
You must think of collision handling as having (at least) two phases : Collision detection and Collision resolution. Here you solve the collision only by changing speed, but both objects might still intersect if one speed is very high : one object might well be inside the other : So you have also to solve position, or, if you prefer 'push' the ligthest object out of the heaviest. You can do this by using a few min/max on the x,y,w,h of both objects.
OR, There's another 'dynamic' method to avoid object overlap : Have the collision handling time-driven. Split the collision handling into time sub-steps, making a stop on each collision. You must compute the time when the next collision will happen, then move everyone to that time, then update only the speeds, and do this again until enough time elapsed. So there not even a chance an overlap can happen : you 'stop the watch' on collision, then change speed, then restart time again. And several collision can happen in one frame, a case that won't be handled properly by a single-pass algorithm (case when a ball hit near a corner).
An example : Say your game frame time, 'dt' is 16 ms, now you detect the ball hits paddle at 10.2ms -> you make both object moves for 10.2ms (x+=vx*10.2/y...), solve their speed (only), then you ask your collision engine to iterate a further 5.8ms.
It's a little work but i did it in my game engine, it works fine.
(Hope i've been more helping than confusing... :-) )
Related
Make ball move away from ball on click
There are some questions similar to this one and I have read them all but what I need is of a very specific nature. Essentially I have a ball with a round area around it that can be clicked. When you click this area, the ball should move in the direction opposite to the direction of the click compared to the center of the ball. So if you click right under the ball it should move up. I have managed to this this by using the following function clickBall(event){ //finding position of click var rect = document.getElementById("theBall").getBoundingClientRect(); var ballX=rect.left-294.8641870117188; var ballY=rect.top-60.125; click[0] = event.clientX-313.999593505859423; click[1] = event.clientY-79; distanceX=ballX-click[0]; console.log(distanceX); distanceY=ballY-click[1]; console.log(distanceY); ballMoving=true; ballPosition = click; //document.getElementById("theBall").style.left=(ballX+distanceX)+"px"; //document.getElementById("theBall").style.top=(ballY+distanceY)+"px"; } moveBall gets called by update which runs every frame function moveBall(){ if(ballMoving){ moveTime-=1; if(moveTime<0){ //control move time moveTime=ballMoveTime; ballMoving=false; } ballPosition[0]+=distanceX/150*moveTime; ballPosition[1]+=distanceY/150*moveTime; ballSpeed-=ballSpeedReducion; checkCollision(); document.getElementById("theBall").style.left=ballPosition[0]+"px"; document.getElementById("theBall").style.top=ballPosition[1]+"px"; } } sorry about all the weird numbers i had to do some adjustments, but anyways. The problem with this is, it makes the ball move away from the click point, but if you click really close to the ball, it moves just a little, and if u click as far away as u can inside the blue area, it moves way too much. I tried to solve this by having if statements that find if X and Y are positive or negative and makes them 1 or -1 accordingly, but this makes them only be able to move diagonally... I need a way to make it so it moves just as much no matter how far the click is from the ball. Any suggestions would be appreciated.
Phaser Js - How to flip Image after colliding with world bounds?
In my game some dogs are randomly walking. Suppose they are moving from left to right, what I need is when it reaches the right boundary of the game world, then the dog animation should be flipped and vice versa. I know that flipping can be achieved when we give dog.scale.x = -1. But I don't know when this should be applied, I have set dog.body.collideWorldBounds = true;. Also now I am using myGame.physics.arcade.velocityFromRotation(dog.rotation, 100, dog.body.velocity); for moving the dog, let me know if any other options. The js code can be see here: http://jsfiddle.net/abhiklpm/rbfg0h9o/1/ and a working demo in this link: http://abhilashrs.com/game
You've a couple of options: 1) Monitor the dogs velocity.x and adjust the scale.x accordingly. So if the velocity changes from negative to positive, you flip the scale as required. 2) Collide with a hidden object instead of the world bounds. By doing this you can take advantage of collision callbacks and adjust the dog scale as required.
How can I permanently get X/Y position of my finger on a mobile device? [duplicate]
I am working on a Transformer Pad and developing a drawing plate. I use PhoneGap(javascript) to write the code instead of JAVA. But the touchmove event is quite weird. I think as I move my finger on the pad, it will continuously to collect the coordinates which I touch on the canvas. BUT IT DOES NOT! It's ridiculous, it only collect "1" coordinate: the first point on the canvas my finger moves to. Here are my code about the "Touch && Move event": function touchStart(event){ if (event.targetTouches.length == 1) { var touch = event.targetTouches[0]; if (event.type == "touchstart") { line_start_x= touch.pageX- canvas_org_x; line_start_y= touch.pageY- canvas_org_y; context.beginPath(); context.moveTo(line_start_x, line_start_y); }//if }//if 1 }//function. function Touch_Move(event){ line_end_x= event.touches[0].pageX- canvas_org_x; line_end_y= event.touches[0].pageY- canvas_org_y; context.lineTo(line_end_x, line_end_y); context.stroke(); test++; } I don't know why each time I move my finger on the pad, trying to draw a line, curve, or anything I want. As the finger moves, only a VERY SHORT segment appears. So I declare a variable:"var test=0" in the beginning of this js file. I found that although I move my finger on the pad without leaving it or stopping, the value of "test" remains 1. It means that I move my finger on it. But it doesn't continuously to trigger the event: "Touch_Move". What can I do now? I need a corresponding event to "mousemove" on touch pad. At least, the event has to continuously be triggered. Thank you!
Oh, Jesus. I finally find the answers: Please take reference for this site. If you work on an Android System,remember the 'touchmove' only fire ONCE as your finger moves around the pad. So if you wanna draw a line or something, you have to do this: function onStart ( touchEvent ) { if( navigator.userAgent.match(/Android/i) ) { // if you already work on Android system, you can skip this step touchEvent.preventDefault(); //THIS IS THE KEY. You can read the difficult doc released by W3C to learn more. } And if you have more time, you can read the W3C's document about introducing the 'movetouch', it is REALLY hard to understand. The doc sucks.
JavaScript Canvas - stop animation after collision
I have problem with canvas animation. I created a character (black-evil box) that can be moved. After it touch another box (red) it stops. The animation is simple - the player.x deducted from boxes[i].x makes the blocks (and the camera) moving. The problem is that "camera" (or viewport - don't know how to call it) should also stop. I tried to change the variable left to 0 after a collision, but it's not working Live example: http://jsfiddle.net/wA73R/ How to fix that? How to stop all things after collision?
Making Javascript TileEngine Scrollable in Canvas
The basis for the code is from John E. Graham's blog http://johnegraham2.com/blog/2010/09/25/project-javascript-2d-tile-engine-with-html5-canvas-part-4-using-zones-for-further-optimization/ It works perfectly for drawing a screen's worth of tiles, but I cannot for the life of me figure out how to adjust it 1 row/column at a time based on pressing up, down, left, or right keys. Here is an example with the transparency to help visualize the zones http://simplehotkey.com/Javascript/canvas.html (loading positions of 1,188 tiles but only draws a couple hundred to fill the screen) I had it loading an array with 70,000 entries and it was still quick because it's only drawing whats on the screen, but cannot figure out how to slide everything based on input... I've come up with a couple ideas and am not sure what's the best way. One screen worth of tiles is shown here: tilesArray = [ 0,0,0,0,0,0,0,1,2,9,6,0,0,7,0,0,1,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,9,0, 0,9,9,9,9,9,9,0,7,2,0,0,0,0,0,1,2,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,0,7,2,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]; Where 0 is a wall tile (around perimeter), 9 a floor tile, 7 a door and a couple other random tiles. That is exactly what is loaded to the screen, but I cannot figure out how to shift everything 1 tile in either direction based on input, up, down, left, right. The one idea I'm leaning towards now, is just to use that array above as the basis for rendering, and somehow feeding the new values into it based on keyboard input, from another array. Maybe slicing from another, much larger array (holding all the tiles for the entire level) and using that slice to populate the array that's actually rendered??? That's replacing every tile every frame though... for getting player input I was using: //Key listener document.onkeydown = function(e){ e = e?e:window.event; console.log(e.keyCode + "Down"); switch (e.keyCode){ case 38: //UP KEY Game.inputReaction('up'); //Game.moveDir('up'); break; case 40: //DOWN KEY //Game.inputReaction(40); //Game.moveDir('down'); break; case 37: //Left Key //Game.inputReaction(37); break; } } The other alternative is to try to adjust the tiles already on the screen and add new tiles but this engine isn't using global variables so I'm not sure how to affect the tile engine programatically based on input....like I can add another method (inputReaction(num)) and trigger some actions from my keyboard input (console.log()) but I can't access the other methods actually drawing the tiles. Or maybe I have to make a copy of the object, change it and return it? but it's pretty complex. I think it might be easier to adjust the array values that are being fed into the "engine" (array above) rather than changing around how the engine is calculating what's being drawn. Can you confirm this?
Add a camera abstraction that you can move around on the map, then shift the drawing positions according to the camera position. When the camera moves south 10px, all tiles move north 10px, same with east and west. Since you only draw the tiles that are visible, there won't be much of a performance loss. The renderer looks at the camera to figure out what needs to be drawn and you can expose the camera object to the outside to manipulate it. That way you only need to change the camera position to change what is shown on the screen. I did this in a proof of concept tiling engine a year ago and I was able to smoothly scroll and scale huge tilemaps. If you start changing the array itself, your performance will suffer and you won't be able to scroll smoothly since you can only go in steps of one tile and not one pixel.