#Ball bounce with fake height in tennis game 2D
1 messages ยท Page 1 of 1 (latest)
I have a few ideas:
1- Actually simulate the ball trajectory. Once the ball is hit by the paddle, create the new velocity vector and then either use the physics engine to let the ball fly, or simulate it yourself (calculate the accelerations based on the forces like air drag, gravity, integrate the acceleration to find speed, and impose this new speed in the dynamic rigid body). This would make the game realistic, but since the game is 2d, it doesn't make a lot of sense.
2- Establish the ball initial point (where it's hit by the paddle) and arbitrarily establish the final point (based on where it is, the angle that it was hit and by how strong it was hit by the paddle), and just interpolate from one point to another using Vector3.MoveTowards, or better, Lerp with extrapolation. In this case, the ball is at the player's height when it's hit (initial position), and at ground level when it arrives on the destination point, and keeps moving forward (by extrapolating the lerp function) and up again, so you'll have to establish this third point where the ball hits the ground again.
I recommend you to play "Tennis" from Atari, you seem to be looking for the same dynamic
I know it sounds like I'm oversimplifying your game, but this Tennis Atari game was actually good. The console had a button behind to set the difficulty to Normal or Expert
On expert mode, you could get sharper angles to hit the ball
the ball was sent to a straight angle when it hit the center of the paddle, and to a sharper angle (towards the diagonal) when the ball hit the paddle's corner. It doesn't make sense from a physics point of view, but it made the game interesting
looking at your code, it seems like the paddle has a round shape and then you decide where the ball will go based on where the ball was hit. I like it. It gives the player the control to know exactly how to hit the ball to send it to a certain place. However, it doesn't take into account the ball's current speed and direction. I think it's a good decision, games don't have to be physically accurate. Also it'd be a shit ton of work to make it accurate ๐
so the 2d movement of the ball is all set, all you need to do is establish the height. The atari game seems to have a constant parabolic function that makes the ball oscillate up and down constantly, which makes sense for a game. Then the ball will just hit the ground on the back of the court when it goes fast, and close to the net when it's hit with a low force
So you could just go with height = k* abs( sin(w) ), which will make the ball go up and down in a frequency of w, at a height of k
I also updated the code and removed the animation, because I guess I won't have to use it anymore. https://hatebin.com/rvnypmmhje
So, I should not change anything in how and at what speed the ball moves with respect to the player? Also, if you can help me or guide me a little on how to implement the elevation logic you say I would appreciate it very much. I'm still a beginner when it comes to more specific or advanced mechanics of Unity haha
Nice, so the 2d mechanics is working, good!
for the elevation, I'd say:
Create a "private float ballElevation" in the script that controls de ball
Create a const float racketElevation = 1.0 (could be anything)
Create a float racketTimer = 0.0
Every time the ball is hit by the paddle, make racketTimer = Time.time
Inside Update(), you update the ball elevation like ballElevation = racketElevation * Mathf.Abs( Math.Sin ( racketTimer * omega ) )
Oh, yeah, we need to declare private float omega = 1.0, and you can tune this thing later. Omega represents the ball velocity to bounce up and down
the funcion Math.Sin will oscilate if you put a timer inside, right?
Now, if you take the absolute value of it, it'll oscillate like this:
(which is the ball bouncing up and down)
(maybe we should establish a parabolic function, but I'm pretty sure the SIN will look nice)
but ABS(SIN(timer)) might be too fast or too slow, so what you do is put a constant inside to help you scale it up or down, which I called omega
You could even do tests like when the ball crosses the net, check if ballHeight < netHeight THEN ballHitsNet
(I'm not sure it's a good mechanic, but you gotta try ๐ )
now that you have the ball height, you just scale the ball object up and down according to the height. I'd guess you could make
transform.scale.x = (ballHeight + delta) / racketElevation
(I added the multiplier so the scale doesn't become zero when touching the ground; also, you gotta change the y scale as well)
so far so good?
Thanks for the explanation, I will test the code tomorrow and let you know how it goes.
Some other errors are that at the moment of being hit, it immediately becomes as small as possible and starts the cycle of size change, regardless of the height it was at before being hit. Another thing is that if possible I would like to set something so that the ball does not bounce when it is still, being that it bounces when it is thrown.
Ah, it's because we're using mathf.sin, and sin(0)=0
Then, as soon as you hit the ball, it disappears
So, try replacing sin with cos
Or, better, make it sin( (t-t0 + shift) *omega)
The shift variable should adjust the ball height when it's hit. If it's zero, the ball will be small when hit, if the shift var = pi/2, the ball will be big when you hit it
If the ball is too small, increase the delta variable, say, 0.5 instead of 0.1
Now, to make the ball not change the size when hit, that's something else completely... We might have to rethink of what do we want for the code
Maybe we have to start thinking of actually simulating the physics
To simulate the vertical physics, you integrate the acceleration to find speed, and integrate speed to find position. Do you want me to explain more?
Right now the ball seems to bounce on the other side, which should not be the case
I just had another idea, which is to control the ball height based on the position over the table
I'll write something later and send here
Using Mathf.Cos does not reverse the effect, but it looks even less realistic as it is still quite small when hit. That's why I chose to use Mathf.Sin, but maybe in the long run it loses the realism and immersion that I try to give visually to the game.
Do you think I could achieve a better visual effect that way?
I think it could work that you establish the initial ball height when it was hit, and pre-set where, on the other side of the court (or table) will the ball hit the ground (and be the smallest), and where it will be at its high point again, based on the speed the ball was hit. So we remove the Mathf.Sin, and introduce a linear interpolation
for example,
float tableMinY = 0; float tableMidY = 5f; float tableMaxY = 10f; float ballScaleMin = 0.1f; float ballScaleMax = 1.0f; BallWasHit() { ballWasHitAtY = ball.transform.position.y; ballWasHitAtSpeed = racket.rigidbody.velocity.y; ballHitsGroundAtY = mathf.clamp(ballWasHitAtSpeed, -5f, 5f) + tableMidY; //if the ball vertical speed is negative, the target is on the lower court ballHitsGroundAtY = mathf.clamp(ballHitsGroundAtY, tableMinY, tableMaxY); } Update { float t = Mathf.Abs((ball.transform.position.y - ballWasHitAtY) / ( ballHitsGroundAtY - ballWasHitAtY)); float ballHeightScale = Mathf.Lerp (ballWasHitAtY, ballHitsGroundAtY, t ); ball.transform.scale = Vector3.one * ballHeightScale; }
I didn't test it, but you get the idea
also, the code above is only interpolating between the initial and final points where the scale is zero
after the ball reaches the target, you have to start scaling it up again using a new target even further
I'm pretty sure I messed up with the signs somewhere inside the Update function
but you can do it ๐
(I typically write my codes very fast with the ideas and then come back fixing the math signs, interpolations, clamps, abs, etc)
bruh
Is there a ball bouncing there?
Nope
doesn't sound like you're on the right place then