-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpong_utilities.cpp
154 lines (133 loc) · 4.15 KB
/
pong_utilities.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "vex.h"
#include "screen/screen_functions.h"
#include "screen/pong_utilities.h"
#include "drive/drive.h"
using namespace vex;
//TELLS IF RED/BLUE LOST
bool redGameover = false;
bool blueGameover = false;
//BALL CONSTRUCTOR
Ball::Ball(){
x = SYSTEM_DISPLAY_WIDTH/2; y = SYSTEM_DISPLAY_HEIGHT/2; r = 10;
cx = 0.6; cy = 0.2;
}
//BALL COLLISION FUNCTIONS
bool Ball::pointCircle(float px, float py, float cx, float cy, float cr){
if(distanceFormula(px, py, cx, cy) < cr){
return true;
} else {
return false;
}
}
bool Ball::linePoint(float x1, float y1, float x2, float y2, float px, float py) {
// get distance from the point to the two ends of the line
float d1 = distanceFormula(px,py, x1,y1);
float d2 = distanceFormula(px,py, x2,y2);
// get the length of the line
float lineLen = distanceFormula(x1,y1, x2,y2);
// since floats are so minutely accurate, add
// a little buffer zone that will give collision
float buffer = 0.1; // higher # = less accurate
// if the two distances are equal to the line's
// length, the point is on the line!
// note we use the buffer here to give a range,
// rather than one #
if (d1+d2 >= lineLen-buffer && d1+d2 <= lineLen+buffer) {
return true;
}
return false;
}
bool Ball::lineCircle(float x1, float y1, float x2, float y2, float cx, float cy, float r) {
// is either end INSIDE the circle?
// if so, return true immediately
bool inside1 = pointCircle(x1,y1, cx,cy,r);
bool inside2 = pointCircle(x2,y2, cx,cy,r);
if (inside1 || inside2) return true;
// get length of the line
float distX = x1 - x2;
float distY = y1 - y2;
float len = sqrt( (distX*distX) + (distY*distY) );
// get dot product of the line and circle
float dot = ( ((cx-x1)*(x2-x1)) + ((cy-y1)*(y2-y1)) ) / pow(len,2);
// find the closest point on the line
float closestX = x1 + (dot * (x2-x1));
float closestY = y1 + (dot * (y2-y1));
// is this point actually on the line segment?
// if so keep going, but if not, return false
bool onSegment = linePoint(x1,y1,x2,y2, closestX,closestY);
if (!onSegment) return false;
// optionally, draw a circle at the closest
// point on the line
//fill(255,0,0);
//noStroke();
//ellipse(closestX, closestY, 20, 20);
// get distance to closest point
distX = closestX - cx;
distY = closestY - cy;
float distance = sqrt( (distX*distX) + (distY*distY) );
if (distance <= r) {
return true;
}
return false;
}
//BALL FUNCTIONS
void Ball::display(){
Brain.Screen.setFillColor(green);
Brain.Screen.drawCircle(x, y, r);
}
static int blueScore = 0;
static int redScore = 0;
void Ball::move(float px, float py, float pw, float ph, float px2, float py2, float pw2, float ph2){
y += cy; x += cx;
if(x+(3*r) > SYSTEM_DISPLAY_WIDTH || x-(3*r) < 0){
if(lineCircle(px+pw, py, px+pw, py+ph, x, y, r) || lineCircle(px2, py2, px2, py2+ph2, x, y, r)){
cx *= -1;
if(lineCircle(px+pw, py, px+pw, py+ph, x, y, r)){
float val = map(cy, py, py+ph, 0.3, -0.3);
cy += val;
}
if(lineCircle(px2, py2, px2, py2+ph2, x, y, r)){
float val = map(cy, py2, py2+ph2, 0.3, -0.3);
cy += val;
}
} else {
if(x+(r) > SYSTEM_DISPLAY_WIDTH){
redGameover = true;
}
if(x-(r) < 0){
blueGameover = true;
}
}
}
if(y-(r) < 0 || y+(3*r) > SYSTEM_DISPLAY_HEIGHT){
cy *= -1;
}
if(lineCircle(px+pw, py, px+pw, py+ph, x, y, r)){
blueScore++;
}
if(lineCircle(px2, py2, px2, py2+ph2, x, y, r)){
redScore++;
}
Brain.Screen.setFillColor(black);
Brain.Screen.setFont(fontType::prop20);
Brain.Screen.printAt(5, 30, "Blue Score: %d", blueScore);
Brain.Screen.printAt(SYSTEM_DISPLAY_WIDTH-150, 30, "Red Score: %d", redScore);
}
//PADDLE CONSTRUCTOR
Paddle::Paddle(int xx){
w = 25; h = 100; x = xx; y = SYSTEM_DISPLAY_HEIGHT/2 + (h/2);
}
//PADDLE FUNCTIONS
void Paddle::display(){
if(x < SYSTEM_DISPLAY_WIDTH/2){
Brain.Screen.setFillColor(blue);
} else {
Brain.Screen.setFillColor(red);
}
Brain.Screen.drawRectangle(x, y, w, h);
}
void Paddle::move(){
if(buttonPressed(x, x + w, 0, SYSTEM_DISPLAY_HEIGHT)){
y = Brain.Screen.yPosition() - h/2;
}
}