Public Group

# Pong collision problem

This topic is 4654 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm in the process of coding Pong using Managed DirectX, but my collision detection is having problems. What I know so far is that there's an issue with how I'm implementing velocity and that it sometimes goes through the paddle depending on the speed. Depending on the value of xv (x-velocity), the ball will always hit the paddles(8), go right through(6 or 10), hang on the right paddle(5), or not move at all(4). When the ball does move, it appears to travel to the left faster than to the right, even though I think I'm only changing the x-velocity by keeping the same number and switching between +/-. Note that I'm not using any threads or other timing mechanisms. The source is below, made so that you can copy and paste into a VC#/#develop project, referencing the DirectX libraries. If you spot a problem, state clearly what it is and if possible, how it can be fixed.
using System;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
using dx = Microsoft.DirectX;
using d3d = Microsoft.DirectX.Direct3D;
using din = Microsoft.DirectX.DirectInput;

public class pong : Form
{
private Rectangle[] rects;
private Point[] points;
private d3d.Device d3ddev;
private din.Device dindev;
private Graphics gfx;
private int xv, yv, dir;
private int p1, p2;
private System.Random srand;

public pong()
{
this.ClientSize = new Size(800, 600);
this.Text = "Pong in Direct3D";
this.gfx = this.CreateGraphics();
rects = new Rectangle[3];
points = new Point[3];
points[0] = new Point(0, 250);
points[1] = new Point(398, 298);
points[2] = new Point(790, 250);
rects[0].Location = points[0];
rects[0].Width = 10;    rects[0].Height = 100;
rects[1].Location = points[1];
rects[1].Width = 4;     rects[1].Height = 4;
rects[2].Location = points[2];
rects[2].Width = 10;    rects[2].Height = 100;
xv = 6;
yv = 0;
p1 = p2 = 0;
srand = new System.Random();
}

public void initgfx()
{
d3d.PresentParameters d3dpp = new PresentParameters();
d3dpp.Windowed = true;
d3ddev = new d3d.Device(0, d3d.DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, d3dpp);
}

public void initkey()
{
dindev = new din.Device(SystemGuid.Keyboard);
dindev.SetCooperativeLevel(this, CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Background);
dindev.Acquire();
}

public void getinput()
{
foreach (Key k in dindev.GetPressedKeys())
{
if (k == Key.W && points[0].Y>0)    points[0].Y-=4;
if (k == Key.S && points[0].Y<500)  points[0].Y+=4;
if (k == Key.O && points[2].Y>0)    points[2].Y-=4;
if (k == Key.L && points[2].Y<500)  points[2].Y+=4;
}
}

public void startup()
{
int b = 0;
while (b == 0)
{
gfx.DrawString("Press 'b' to begin the game.", new System.Drawing.Font(FontFamily.GenericSerif, 20),
Brushes.Red, new Point(50, 100));
foreach (Key k in dindev.GetPressedKeys())
if (k == Key.B) b = 1;
}
}

public void checkhit()
{
if (rects[1].Left == rects[0].Right)
{
xv = -xv;
}
if (rects[1].Right == rects[2].Left)
{
xv = -xv;
}
}

public void update()
{
rects[0].Y = points[0].Y;
rects[2].Y = points[2].Y;
int xn = points[1].X + xv;
if (xv > 0)
{
while (points[1].X + 4 < xn)
{
points[1].X++;
checkhit();
gfx.DrawString(xv.ToString(), new System.Drawing.Font("Arial", 12), Brushes.Yellow, new Point(0, 512));
}
}
if (xv < 0)
{
while (points[1].X > xn)
{
points[1].X--;
checkhit();
gfx.DrawString(xv.ToString(), new System.Drawing.Font("Arial", 12), Brushes.Yellow, new Point(0, 128));
}
}
if (xv == 0)
gfx.DrawString("?", new System.Drawing.Font("Arial", 12), Brushes.Orange, new Point(0, 0));
//    points[1].X += xv;
//    points[1].Y += yv;
rects[1].X = points[1].X;
rects[1].Y = points[1].Y;
}

public void render()
{
getinput();
checkhit();
update();
d3ddev.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
d3ddev.BeginScene();
gfx.FillRectangles(Brushes.White, rects);
d3ddev.EndScene();
d3ddev.Present();

}

public void play()
{
this.initgfx();
this.initkey();
this.Show();
this.startup();
while (this.Created)
{
this.render();
Application.DoEvents();
}
}

public static void Main()
{
pong p = new pong();
p.play();
}
}



##### Share on other sites
Hi.
If you look closely at your checkhit function, you will easily see one problem: your are checking for strict equality between a paddle side and the ball side.
This leads to the ball going through the paddles (if the distance between each paddle is not a multiple of the xv speed).
I advise to change it thus:
public void checkhit()    {        if (rects[1].Left <= rects[0].Right)            {            xv = -xv;            //do not forget to reposition the ball so that             //it does not look like as though it bit the paddle            }        if (rects[1].Right => rects[2].Left)            {            xv = -xv;            //do not forget to reposition the ball so that             //it does not look like as though it bit the paddle            }    }

Now look closely at your update function: when xv is positive, you add 4 to your ball x position. This looks like legacy code since it nullifies the xn calculation when the xv is 4. Another problem is that your update function increments in a loop the ball x position but never gets rendered: this is a waste of code. I understand you wanted to do fine check against each paddle, but with the modification I gave you above, it is unnecessary.
I suggest the following:

public void update()   {        //update paddles and ball position        rects[0].Y = points[0].Y;        rects[2].Y = points[2].Y;        points[1].X += xv;        //check for hit        checkhit();        if (xv == 0)            gfx.DrawString("?", new System.Drawing.Font("Arial", 12), Brushes.Orange, new Point(0, 0));        else            gfx.DrawString(xv.ToString(), new System.Drawing.Font("Arial", 12), Brushes.Yellow, new Point(0, 512));        //update ball rect        rects[1].X = points[1].X;        rects[1].Y = points[1].Y;    }

Try those out. It should be better. When you have such a problem, trace your program manually on a sheet of paper and test the critical cases (ball against paddle, ball near paddle, ball with velocity xv, etc...). Most often in such cases you will soon see logic bugs.
Ghostly yours,
Red.

##### Share on other sites
Thanks for the tip. I improved the checkhit and update functions to make it more playable, though the flicker is still there when I call GDI+ in Managed DirectX. Next, I'll work on timing, scorekeeping, and some GUI work.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 9
• 13
• 9
• 9
• 15
• ### Forum Statistics

• Total Topics
634076
• Total Posts
3015353
×