Elements used in the Balls and Things games for the RETRO.

Dependents:   RETRO_BallsAndPaddle RETRO_BallAndHoles

Shapes.cpp

Committer:
maxint
Date:
2015-03-02
Revision:
8:19dd2a538cbe
Parent:
7:4fa3edaa1201

File content as of revision 8:19dd2a538cbe:

#include "mbed.h"
#include "Shapes.h"



///////////////////
// POINT
///////////////////
Point::Point()
{   // constructor
    x1=0;
    y1=0;
}

Point::Point(int x, int y)
{   // constructor
    x1=x;
    y1=y;
}

int Point::getX()
{
    return x1;
}

int Point::getY()
{
    return y1;
}

void Point::set(int x, int y)
{
    x1=x;
    y1=y;
}


///////////////////
// LINE
///////////////////

Line::Line(int x,int y, int xx, int yy)
{
    x1 = x;
    x2 = xx;
    y1 = y;
    y2 = yy;
}

Line::Line(Point p1, Point p2)
{
    x1 = p1.getX();
    x2 = p2.getX();
    y1 = p1.getY();
    y2 = p2.getY();
}

Point Line::get1()
{
    return(Point(x1, y1));
}

Point Line::get2()
{
    return(Point(x2, y2));
}


float Line::getSizeFloat()
{   // get the size of the vector
    return(sqrt((float)(x2-x1)*(float)(x2-x1)+(float)(y2-y1)*(float)(y2-y1)));
}

int Line::getSize()
{   // get the size of the vector
    return((int)getSizeFloat());
}

Rectangle Line::getBoundingRectangle()
{
    return(Rectangle(x1, y1, x2, y2));
}

int Line::getDistance(Point pt)
{   // get the distance of a line to a point
    // TODO: more precise calculation, currently it's a kind-of lame approximation
    Line ln1(get1(), pt);
    Line ln2(get2(), pt);
    int nDist1=ln1.getSize();
    int nDist2=ln2.getSize();
    int nDistApprox=nDist1+nDist2-getSize();
    
    // simple distance calculation:
    //    if distance to either line-end combined equal to the line-length, the point is on the line
    //    if the point is nearby, the difference might be good approximation of the distance
    if(nDistApprox<nDist1 && nDistApprox<nDist2)
        return(nDistApprox);
    
    return(min(nDist1,nDist2));
}




///////////////////
// RECTANGLE
///////////////////

Rectangle::Rectangle(int x,int y, int xx, int yy)
{
    x1 = x;
    x2 = xx;
    y1 = y;
    y2 = yy;
}

Rectangle::Rectangle(Point pt1, Point pt2)
{
    x1 = pt1.getX();
    x2 = pt2.getX();
    y1 = pt1.getY();
    y2 = pt2.getY();
}

bool Rectangle::collides(Point pt)
{
    if(pt.getX() >= x1 && pt.getX() <= x2) {
        if(pt.getY() >= y1 && pt.getY() <= y2) {
            return true;
        }
    }
    return false;
}

bool Rectangle::collides(Rectangle r)
{   // check if two rectangles collide
    // method: compare rectangle sides
    // see http://stackoverflow.com/questions/7610129/simple-collision-detection-android
    if ((getX2() < r.getX1()) || // A is to the left of B
        (r.getX2() < getX1()) || // B is to the left of A
        (getY2() < r.getY1()) || // A is above B
        (r.getY2() < getY1()))   // B is above A
        return(false);
    return(true);
}

Point Rectangle::get1()
{
    return(Point(x1, y1));
}

Point Rectangle::get2()
{
    return(Point(x2, y2));
}

Point Rectangle::get3()
{
    return(Point(x2, y1));
}

Point Rectangle::get4()
{
    return(Point(x1, y2));
}
 

 
int Rectangle::getX1()
{
    return x1;
}
 
int Rectangle::getX2()
{
    return x2;
}
 
int Rectangle::getY1()
{
    return y1;
}
 
int Rectangle::getY2()
{
    return y2;
}
 
int Rectangle::getCenterX()
{
    return x1 + (x2-x1)/2;
}
 
int Rectangle::getCenterY()
{
    return y1 + (y2-y1)/2;
}

Point Rectangle::getCenter()
{
    return(Point(x1 + (x2-x1)/2, y1 + (y2-y1)/2));
}

void Rectangle::set(Rectangle rNew)
{
    x1=rNew.getX1();
    y1=rNew.getY1();
    x2=rNew.getX2();
    y2=rNew.getY2();
}

bool Rectangle::isHorizontal()
{
    return(x2-x1 > y2-y1);
}


void Rectangle::move(Vector v)
{
    x1+=rint(v.x);
    y1+=rint(v.y);
    x2+=rint(v.x);
    y2+=rint(v.y);
}


///////////////////
// CIRCLE
///////////////////
Circle::Circle(int x,int y, int r)
{
    x1=x;
    y1=y;
    r1=r;
}

Point Circle::getCenter()
{
    return(Point(x1, y1));
}

int Circle::getRadius()
{
    return(r1);
}

int Circle::getX()
{
    return(x1);
}

int Circle::getY()
{
    return(y1);
}

void Circle::setX(int x)
{
    x1=x;
}

void Circle::setY(int y)
{
    y1=y;
}

void Circle::setXY(int x, int y)
{
    x1=x;
    y1=y;
}

void Circle::move(int x, int y)
{
    x1+=x;
    y1+=y;
}

void Circle::move(Vector v)
{
    x1+=rint(v.x);
    y1+=rint(v.y);
}


Rectangle Circle::getBoundingRectangle()
{
    return(Rectangle(x1-r1, y1-r1, x1+r1, y1+r1));
}

bool Circle::collides(Line ln)
{   // see if a circle collides with a line
    // check 1: first check using bounding rectangles
    // check 2: distance of line-ends to center or circle
    // check 3: check if distance to line is smaller than radius
    
    // Simple check 1:  using bounding rectangles
    Rectangle rCircle=getBoundingRectangle();
    if(!rCircle.collides(ln.getBoundingRectangle()))
        return(false);
    
    // Simple check 2: distance of line-ends to center or circle
    Point ptCenter=getCenter();
    Line lnA(ptCenter, ln.get1());
    if(lnA.getSize()<=r1)
        return(true);
    Line lnB(ptCenter, ln.get2());
    if(lnB.getSize()<=r1)
        return(true);

    // check 3: check if distance to line is smaller than radius
    if(ln.getDistance(ptCenter) <= r1)
        return(true);

    return(false); 
}