If you don't mind, going to do a little journal entry on this as I finish the game. This is going to be pretty long, I just feel like sharing this.
Why am I rewriting all this code?
- I'm not rewriting everything, but how most things function now. Also it's great practice, since I'm really lazy.
Step 1:
-Testing if the ball stops at the x of the player's paddle.
Create a detectCollision method, return type bool, call the method every time in the for loop, also make sure to create the ball rectangle after the for loop. (which I didn't do last time, the ball rectangle was drawn before.) Also this time, the Ball class has more control of ball movement.
Code:
bool detectCollisions()
{
if (Ball.Position.X + Ball.Size.X >= Player.Position.X)
{
return true;
}
return false;
}
Step 2:
Make sure the ball stops exactly at the right pixel. (The ball will stay there forever because the for loop always breaks if the detectCollision method returns true.
Step 2:
- Make the ball rebound off of the paddles.
Made the rebound method, now I'm trying to get a perfect screenshot of the ball hitting the paddle, to see if the pixels are exact. I didn't want to keep restarting the game, so I made the ball rebound East when Ball.X reaches 0. I also fixed up the detectCollision method and for loop.
Code:
bool detectCollisions(out Ball.HitTypes hitType)
{
if (Ball.Position.X + Ball.Size.X >= Player.Position.X)
{
hitType = Ball.HitTypes.PlayerMiddle;
return true;
}
if (Ball.Position.X <= 0)
{
hitType = Ball.HitTypes.EnemyMiddle;
return true;
}
hitType = Ball.HitTypes.None;
return false;
}
The detect collision now requires a Ball HitType out parameter to determine what type of collision it was.
The for loop now uses this new change for the Ball.Rebound method to determine which direction to change the ball.
Code:
for (int i = 1; i <= Ball.CurrentSpeed; i++ )
{
Ball.HitTypes hitType;
if (detectCollisions(out hitType))
{
Ball.Rebound(hitType);
Ball.Move();
break;
}
Ball.Move();
}
///////////////////// THIS IS THE BALL.REBOUND METHOD
static public void Rebound(HitTypes hitType)
{
switch (hitType)
{
case HitTypes.PlayerMiddle:
CurrentDirection = Directions.West;
break;
case HitTypes.EnemyMiddle:
CurrentDirection = Directions.East;
break;
}
}
Also the reason why I wanted to try and get the perfect screenshot of the ball moving 13 pixels every Draw() call was to make sure the ball never went past the paddle.
(Sorry for not showing the pixel grid in this one. But that's one pixel)
All I wanted is that one more pixel, then the ball goes back. I tried to figure this one out for a while, but I just couldn't. So I just decided to move along, ignore that one pixel off, because the ball is moved at such a speed that I doubt anybody will have time to notice that one pixel off, no matter what...
(Like 1 hour later)
Ok, I finally found out the ball wasn't ever a pixel off, I'm not sure why, maybe I could NEVER get that screenshot of the ball on that one pixel, but some how have a million other photos with the ball one pixel off. I set the speed to 1, and it actually did hit the paddle. The speed shouldn't make any differences because I even tested with a speed with 100, it still never passes the paddle.
Next, I extend the collision method to only detect when the ball hits the paddle, not just the X.
Code:
if (
Ball.Position.X + Ball.Size.X == Player.Position.X &&
(Ball.Position.Y >= Player.Position.Y || Ball.Position.Y + Ball.Size.Y >= Player.Position.Y) &&
(Ball.Position.Y <= Player.Position.Y + Player.Size.Y || Ball.Position.Y + Ball.Size.Y <= Player.Position.Y + Player.Size.Y)
)
{
hitType = Ball.HitTypes.PlayerMiddle;
return true;
}
Next, we have the Enemy collision, but first we need to make the Enemy follow the Ball's Y (Since I actually made the Enemy start elsewhere on the Y axis). This method will also be used as the Enemy's "AI", but not yet, and it's not going to be exactly the Ball's Y, but near it.
I actually have a method already, from earlier, set up.
Code:
static public void UpdateEnemy()
{
Enemy.Position.Y = Ball.Position.Y + (Ball.Size.Y / 2) - (Enemy.Size.Y / 2);
if (Enemy.Position.Y + Enemy.Size.Y >= BottomWallY - 5)
{
Enemy.Position.Y = (BottomWallY - Enemy.Size.Y) - 5;
}
if (Enemy.Position.Y <= TopWallHeight + 5)
{
Enemy.Position.Y = (TopWallHeight) + 5;
}
}
Oh, the fun and possibilities. And the horrible GIF recording too. But actually, you can see the ball actually hits the paddle once, on the right, which relieves me of that worry I still have on the "one or more pixels off" collision detection. On the left you can see one frame in the GIF of the ball hitting the enemy paddle, but one pixel off. This is because the ball is moved 1 pixel to the right in less than milliseconds, to make sure the ball isn't still being detected as a collision, and can move along to the East.