Why does the ball go through the paddle in Squashball game? - javascript

I'm working on yet another squash ball type (paddle hits ball) game using Javascript/HTML and I'm stuck at an issue that seems quite common in other context, but as far as I've looked I've found no good solution for this instance of it. Basically my game (unlike say pong) allows you to move your paddle in any direction. Yet if the paddle moves too fast towards a moving ball, the ball will go through it instead of allowing it to bounce.
I've tried using the velocity of the paddle and the ball to predict the next location of the ball but it still seems
My strategy has come down to tracking the velocity of the paddle and predicting where is it going to be next and then using that for my intersection, to avoid any coordinate gaps lost when moving the paddle to fast.
this.vx = this.x - this.lastX;
this.vy = this.y - this.lastY;
// predict next point
this.nextX = this.x + this.vx;
this.nextY = this.y + this.vy;
Then on my game loop I reverse the velocity if a collision is detected from the point calculation
const { paddle, ball } = this;
const isBallGoingLeft = Math.sign(ball.vx) === -1;
const paddleX = isBallGoingLeft ? paddle.nextX + paddle.w : paddle.nextX;
const nextBallX = isBallGoingLeft ? ball.nextX : ball.nextX + ball.w;
// insersect function found here
// found here: http://paulbourke.net/geometry/pointlineplane/
if (
intersect(
ball.x,
ball.y,
nextBallX,
ball.nextY,
paddleX,
paddle.y,
paddleX,
paddle.y + paddle.h
)
) {
ball.x = isBallGoingLeft ? paddleX : paddle.x - ball.w;
ball.vx = -ball.vx;
}
You can see a full fiddle here: https://jsfiddle.net/r8f0mxjn/4/
I would like to have the ball bounce when the paddle is coming towards it as well as add increase the velocity of the ball from the velocity of the paddle.

Related

Collision check between vectors - moving vectors - HTML, JS, P5

I have created the collision check function for my player to every time when the object (in this case vector - circle) touches the player (also a vector - circle) the game is over.
I have managed to create a logic and there is a collision check working, however it's not calculating the actual distance between elements (instead of ending game when they actually touch its ending when they are some distance from each other.
Both objects are moving - obstacle is moving x+=6 and the player is following the coursor so the speed varies.
I have tried adjusting distance slightly and I have managed to end the game when the x of obstacle is touch x of the player but could not managed actually to when boarders touch. I attach the code I have below;
class Player {
constructor(x, y, r) {
this.pos = createVector(x, y);
this.r = r;
this.vel = createVector(500, 500);
this.mag = 3;
this.velLerp = 0.1;
}
update() {
let mouse = createVector(mouseX - width / 2,
mouseY - height / 2);
mouse.setMag(this.mag);
this.vel.lerp(mouse, this.velLerp);
this.pos.add(this.vel);
collisionCheck(obstacle) {
let d = p5.Vector.dist(this.pos, obstacle.pos);
if (d < this.r + obstacle.r) {
console.log("GAME OVER");
return true;
}
The issue is caused by the fact that the movement of the circles is 3 (this.mag) pixel. You just get the exact point of contact by chance. Most time they are intersecting.
If a collision is detected, change the player's position slightly by an offset of this.r + obstacle.r - d:
collisionCheck(obstacle) {
let d = p5.Vector.dist(this.pos, obstacle.pos);
if (d < this.r + obstacle.r) {
let shift = p5.Vector.sub(this.pos, obstacle.pos);
shift.setMag(this.r + obstacle.r - d);
this.pos.add(shift);
console.log("GAME OVER");
return true;
}
}

Simple AI method to make sprite follow player using car physics?

I am making a top-down car battling game using JavaScript. I need a simple method to make the enemy car follow the player around the map based on the players coordinates. The hard part for me is that I need to make sure the enemy car uses the same turning physics as the player.
What I am looking for is help creating a simple movement formula that will decide when to move forward/backwards and/or when to rotate the enemy in order to bring it closer to the player.
I have tried many various "if enemy.x >player.x .." but I am thinking this is going to require a math function beyond simple logic, maybe something utilizing slope intercept or something but I don't have an idea how to implement
//this is the actual movement algorithm I am using
this.move=function(){
this.angle += this.rotation * Math.PI / 180;
this.nextX = this.x + this.speed * Math.sin(this.angle);
this.nextY = this.y - this.speed * Math.cos(this.angle
//This is how I am moving the player character atm
if(LEFT) {
this.rotation = -1;
}else if(RIGHT) {
this.rotation = 1;
}else {this.rotation = 0;}
if(UP && !BOOST) {
this.speed = 1;
}else if(DOWN) {
this.speed = -1;
}else if(UP && BOOST) {
this.speed = 4;
}else {this.speed = 0;}

Same jumpheight with changing gravity

I am trying to recreate the google-chrome offline Dino game.
In this game the Dino has a gravity-pull on himself and it has a jump velocity, an upwards speed applied when the user presses the space bar.
Over time the obstacles move faster and faster to the player.
When the obstacles move faster the Dino's jump should also be faster.
I tried to make a faster jump by increasing the gravity over time, so the Dino gets pulled down faster. But how do I get the Dino to jump the same height, let's say, 50 pixels upwards, no matter what the gravity is.
I tried working with the formula's:
y = 0.5*a*t^2 + v(0)*t
But I can't come to a correct answer.
The canvas this code is working as regards the top left corner as the origin(0,0). Therefore the jump velocity is negative and the gravity is positive.
This code is inside the Dino class, where this references to the Dino.
In the constructor of the Dino class I have the code
this.y = 0;
this.vy = 0;
this.gravity = 1;
this.speed = 0;
In the update function that is called each x amount of time:
this.speed += 0.001;
this.y += this.vy;
this.vy += this.gravity;
this.gravity += speed*0.001;
The jump function- executes when the spacebar is pressed:
this.vy = (-?);
The amount of pixels the dino jumps gets higher over time. How could I make the Dino jump the same amount of pixels every time no matter the gravity?
So I personally would do this a little differently. I would specify a maximum y; the highest point our object can jump. Then when the player hits the jump button, it will Linearly Interpolate to that position, this works perfectly for your problem as in p5 they've spoiled us with a lerp() function where you can specify the amount to lerp by, so the faster your game gets the quicker we want the player to jump so the higher we set the lerp.
To determine how fast we lerp I've used upSpeed which you will increment as the game progresses:
const MAX_Y = 150;
let y = 370;
let upSpeed = 0.1;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
fill(255, 100, 100);
y = lerp(y, MAX_Y, upSpeed);
ellipse(width / 2, y, 50, 50);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>
And then add your gravity magic to the equation and you've got yourself a game!

JavaScript 2D collision anomaly

I'm experimenting with HTML5 canvas scripting in JavaScript and am having an issue with 2D collision detection. I'm basically checking the coordinates of the "player" against the coordinates of a box I've placed on screen but a strange result is occurring. I know why it's happening, but I don't know how to solve the problem.
Some of my code:
function Arc()
{
// Coordinates.
this.x = 540 / 2;
this.y = 0;
// Radius
this.r = 50;
// Gravity / velicoty.
this.g = 3;
this.vy = 15;
// Bounce.
this.b = -0;
this.speed = 20;
this.max_speed = 20;
this.friction = 0.03444;
}
Arc.prototype.collision = function()
{
for(var i = 0; i < game.sprites.length; i++)
{
if
(
// If the right side of the player is greater than the left side of the object.
this.x + this.r > game.sprites[i].x &&
// If the bottom of the player is greater than (meaning lower than) the top of the object.
this.y + this.r > game.sprites[i].y &&
// If the left side of the player is greater than the right side of the object.
this.x - this.r < game.sprites[i].x + game.sprites[i].w &&
// if the top of the player is greater than (meaning lower than) the bottom of the object.
this.y - this.r < game.sprites[i].y + game.sprites[i].h
)
{
this.y = game.sprites[i].y - this.r;
this.vy *= this.b;
}
}
}
The anomaly is that when I move the player sprite over the left or right of the box, it jumps upwards on the Y-axis because the logical check above is always true. Obviously this is unexpected because the sprite should only interact with the top of the box if a jump has occurred.
Note: I'm not looking for a solution that adds collision to the sides of the box only (that's very simple). Rather, I'm looking for the solution that allows for collision on all sides of the box (including the top) in the same way it currently works but without the anomaly where the sprite suddenly jumps on top of the box upon touching it.
I've reproduced my entire project on JSFiddle for the purposes of demonstration (keys a, d and space bar): http://jsfiddle.net/h5Fun/
Whether or not this is what you want, it solves the problem:
this.x = game.sprites[i].x + 150;
this.vx *= this.b;
The issue was you were setting the incorrect component upon collision. If you want the circle to stop when it hits the rectangle, not go on top of it, then use x, not y.
150 is the size of the rectangle. This means it will stop at the right side of the sprite. The bouncing is already there due to modifying the velocity (this.vx).

Smoothen the animation of Casino wheel

I am developing a casino based game using html5. The animation is working properly but this is not quite smooth i.e. once the wheel stops rotation I move ball as a final repositioning to smoothen the transition but it is not upto the expectation. Complete Code here
BallReposition Function - runs after I wheel stops movement for the final repositioning of the ball to give some reality to the animation.
function ballReposition(){
curX = findNearestOnCircle(curX);
if(curX > deadXRight){
sign = "-";
}else if(curX < deadXLeft){
sign = "+";
}
if(sign == "+"){
curX = parseInt(curX) + ballRepositionIncVal;
curY = Math.floor(Math.abs(getYOnCircle(curX, 130, 1)) + 0.5);
}else{
curX = parseInt(curX) - ballRepositionIncVal;
curY = Math.floor(Math.abs(getYOnCircle(curX, 130, 0)) + 0.5);
}
var xy = normalizeXY(curX, curY);
curX = parseInt(xy.split("-")[0]);
curY = parseInt(xy.split("-")[1]);
surface = document.getElementById("myCanvas");
var surfaceContext = surface.getContext("2d");
//removing older ball image.
surfaceContext.save();
// Translate to the center point of our image
surfaceContext.translate(happy.width * 0.5, happy.height * 0.5);
// Perform the rotation
surfaceContext.rotate(DegToRad(angle));
// Translate back to the top left of our image
surfaceContext.translate(-happy.width * 0.5, -happy.height * 0.5);
surface.getContext("2d").drawImage(happy, 0, 0);
surface.getContext("2d").drawImage(ball, curX, curY);
console.log(curX + curY);
surfaceContext.restore();
ballRepositionIncVal-=5;
if(ballRepositionIncVal <= 0){
clearInterval(myIntervalVar);
}
}
Other function details -
drawCanvas - loads the images and once the images are loaded it will start calling loop function which will rotate the wheel and move the ball in anticlockwise direction.
normalizeXY - used to put the ball at some discrete positions i.e. proper positions below numbers of wheel.
EDIT - Fiddle Configuration updated here
To create a realistic spinning wheel you can use a logarithmic-ish approach to reduce the speed of the wheel.
This means the angle is decremented by small per-centage for each frame. As it is per-centage you will get a smooth ending spin (you will also notice you get the infamous wagon wheel aliasing effect).
This online demo shows the loop isolated (implement as you please):
var angle = 2; /// start angle in radians
ctx.translate(w, h); /// prepare canvas for rotation (w and h = 50%)
ctx.globalAlpha = 0.67; /// optional bonus: motion blur(-ish)
loop(); /// start loop
function loop() {
ctx.rotate(a); /// use incremental rotation
ctx.drawImage(img, -w , -h);
/// spin down and only loop if angle > certain value
a *= 0.995;
/// continue if there is enough "inertia"
if (a > 0.001) requestAnimationFrame(loop);
}
The threshold value for continue the loop determines how "brutal" you want the stop to be. If you want the wheel to appear heavier (more mass) you can decrement the angle with an even tinier increment (eg. try 0.998).
For the ball to bounce around you need to resort to physics modelling, or at least pseudo-physics-modelling. This includes collision detections for all the small details on the wheel as well as sub-time-steps (ray casting) checking and positioning in z-axis.
I feel this is a bit broad to describe here on SO but find a good article on collision detection and physics simulation. Here is a good start with the basics.

Categories