0

I am working on creating pong but I have been having trouble with Collision.How can I add a pixel accurate Collision? I've created a collision when only using a main file but I can't figure it out when using header files.Can someone write out the code for Collision and add to a Collision.h and Collision.cpp for easy storage and modification.

main.cpp

#include "stdafx.h"
#include <SFML\Graphics.hpp>
#include "Paddle.h"
#include "Ball.h"
#include <iostream>
int main()
{
    sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "Pong", 
    sf::Style::Close| sf::Style::Resize| sf::Style::Titlebar);
    Paddle paddle1;
    Paddle paddle2;
    Ball ball;
    while (window.isOpen()) {
        sf::Event evnt;
        while (window.pollEvent(evnt))
        {
            switch (evnt.type)
            {  
            case sf::Event::Closed:
                window.close();
                break;
            }
        }
        paddle1.Update();
        paddle2.Update();
        ball.Update(ballDirectionX,ballDirectionY);
        window.clear();
        paddle1.Draw(window);
        paddle2.Draw(window);
        ball.Draw(window);
        window.display();
   }
   return 0;
}

Paddle.h

#pragma once
#include <SFML\Graphics.hpp>
class Paddle
{
public:
    Paddle();
    ~Paddle();
    void Draw(sf::RenderWindow& window);
    void Update();
    sf::RectangleShape paddle1;
    sf::RectangleShape paddle2;
private:
};

Paddle.cpp

#include "stdafx.h"
#include "Paddle.h"
Paddle::Paddle()
{
    paddle1.setSize(sf::Vector2f(20.0f, 120.0f));
    paddle1.setFillColor(sf::Color::Red);
    paddle2.setSize(sf::Vector2f(20.0f, 120.0f));
    paddle2.setFillColor(sf::Color::Green);
    paddle2.setPosition(sf::Vector2f(1900.0f, 0.0f));
}
Paddle::~Paddle()
{
} 
void Paddle::Draw(sf::RenderWindow& window)
{
    window.draw(paddle1);
    window.draw(paddle2);
}
void Paddle::Update()
{
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
        paddle1.move(sf::Vector2f(0, -3));
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
        paddle1.move(sf::Vector2f(0, 3));
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
        paddle2.move(sf::Vector2f(0, -3));
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
        paddle2.move(sf::Vector2f(0, 3));
    }
}

Ball.h

#pragma once
#include <SFML\Graphics.hpp>
class Ball
{
public:
     Ball();
     ~Ball();
     void Draw(sf::RenderWindow& window);
     void Update() {
     }
     sf::CircleShape ball;
private:    

};

Ball.cpp

#include "stdafx.h"
#include "Ball.h"
Ball::Ball()
{
    ball.setRadius(20);
    ball.setPosition(sf::Vector2f(400, 540));
}
Ball::~Ball()
{
}
void Ball::Draw(sf::RenderWindow & window)
{
window.draw(ball);
}
void Ball::Update()
{
}
Eitan
  • 3
  • 5

1 Answers1

1

Since Pong is a very simple game, I suggest you to create an intersect function with a sf::CircleShape and a sf::RectangleShape as arguments, because that's how you are representing your ball and paddles respectively.

I suggest you the following implementation, but there are better ones:

bool intersects(const sf::CircleShape &c, const sf::RectangleShape &r){
    sf::FloatRect fr = r.getGlobalBounds();
    sf::Vector2f topLeft(fr.left, fr.top);
    sf::Vector2f topRight(fr.left + fr.width, fr.top);
    sf::Vector2f botLeft(fr.left, fr.top + fr.height);
    sf::Vector2f botRight(fr.left + fr.width, fr.top + fr.height);

    return contains(c, topLeft) || 
        contains(c, topRight) || 
        contains(c, botLeft) || 
        contains(c, botRight);
}

This is easy, simply check if each corner of the rectangle is inside of the circle, if none of them is contained, that circle and that rectangle don't intersect.

If any of the corners are contained into the circle, they intersects.

The contains() function quite simple in fact:

bool contains(const sf::CircleShape &c, const sf::Vector2f &p){
    sf::Vector2f center = c.getPosition();
    float a = (p.x - center.x);
    float b = (p.y - center.y);
    a *= a;
    b *= b;
    float r = c.getRadius() * c.getRadius();

    return (( a + b ) < r);
}

Is based in this question, but I've separated it in each step for better comprehension.


EDIT

Note that this method only works if rectangles are in a vertical/horizontal orientation, this is, no rotations.

alseether
  • 1,889
  • 2
  • 24
  • 39
  • 1
    If the ball reaches the center of the bat, it will intersect without hitting any corner. – Quentin Mar 08 '18 at 13:17
  • In that case, it won't be difficult to change the method for something like [this line-circle intersection algorithm](https://stackoverflow.com/questions/1073336/circle-line-segment-collision-detection-algorithm) with the advantage of detecting with rotated rectangles too – alseether Mar 08 '18 at 13:20
  • If you add a `getShape()` method in both `Ball` and `Paddle` classes, you could write `intersects` and `contains` directly above `main` – alseether Mar 08 '18 at 15:10
  • Can you write it out for me in how i have my code set up, not just what to but add it to make it easier for me? – Eitan Mar 13 '18 at 21:07