We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I'm attempting to give my array classes 'Opp' and 'Ally' the same behaviours as the playable 'Balls' So they must all collide with one another and to collide with the puck in order to manoeuvre it in the correct and appropriate direction. Any assistance would be more than greatly appreciated. Thank you! Miles. M
(Please forgive the poor structure of my code, if that can be improved also any advice would be very helpful)
>
boolean keyW = false;
boolean keyA = false;
boolean keyS = false;
boolean keyD = false;
boolean keyUp = false;
boolean keyLeft = false;
boolean keyDown = false;
boolean keyRight = false;
float gVelocity = .2;
final float gVelocityFriction = .99;
final float gElasticity = 1;
ArrayList<Opp> Opps;
ArrayList<Ally> Allys;
Ball player1;
Ball player2;
Ball puck;
int score1, score2;
PFont title;
int mode;
int stage;
void setup() {
stage = 1;
mode = 0;
size(1280, 720);
frameRate(60);
Opps = new ArrayList<Opp>();
for (int i = 0; i < 2; i++) {
Opps.add(new Opp(random(640,1280),random(height)));
}
Allys = new ArrayList<Ally>();
for (int i = 0; i < 2; i++) {
Allys.add(new Ally(random(0,640),random(height)));
}
player1 = new Ball(new PVector(width*3/4, height/2),
new PVector(width*3/4, height/2),
64, 24);
player2 = new Ball(new PVector(width/4, height/2),
new PVector(width/4, height/2),
192, 24);
puck = new Ball(new PVector(width/2, height/2),
new PVector(width/2, height/2),
128, 16);
score1 = 0;
score2 = 0;
}
void draw() {
background(205, 255, 255);
if(stage==1){
rectMode(CENTER);
noStroke();
fill(255, 55, 55, 185);
rect(640, 170, 430, 160);
fill(55, 255, 55, 185);
rect(640, 350, 430, 160);
fill(55, 55, 255, 185);
rect(640, 530, 430, 160);
textAlign(CENTER);
textSize(32);
fill(0);
text("Demo", 640, 180);
text("One Player Start", 640, 360);
text("Two Player Start", 640, 540);
if(mousePressed) {
if (mouseX > 425 && mouseX < 855 && mouseY > 85 && mouseY < 255) {
stage = 2;
mode = 1;
}
}
if(mousePressed) {
if (mouseX > 425 && mouseX < 855 && mouseY > 265 && mouseY < 435) {
stage = 2;
mode = 2;
}
}
if(mousePressed) {
if (mouseX > 425 && mouseX < 855 && mouseY > 445 && mouseY < 615) {
stage = 2;
mode = 3;
}
}
}
if(stage==2){
rectMode(CORNER);
background(205, 255, 255);
noStroke();
fill(255, 55, 55, 185);
rect(0, 0, width/2, height);
fill(55, 55, 255, 185);
rect(width/2, 0, width, height);
fill(205, 5, 5, 95);
rect(0, 180, width/16, height/2);
fill(5, 5, 205, 95);
rect(width*15/16, 180, width, height/2);
for (Opp o : Opps) {
o.applyBehaviors(Opps);
o.update();
o.display();
}
for (Ally a : Allys) {
a.applyBehaviors(Allys);
a.update();
a.display();
}
if (puck.position.x < width/16 && puck.position.y > 180 && puck.position.y < 540 ) {
score2++;
reset(-1);
}
if (puck.position.x > width*15/16 && puck.position.y > 180 && puck.position.y < 540 ) {
score1++;
reset(1);
}
// Ticks and renders test balls
player1.tick();
player2.tick();
puck.tick();
player1.render();
player2.render();
puck.render();
if (mode==1) {
hal(player1, puck, player2, 1);
hal(player2, puck, player1, -1);
}
if (mode==2) {
hal(player1, puck, player2, 1);
//hal(player2, puck, player1, -1);
}
if (mode==3) {
//hal(player1, puck, player2, 1);
//hal(player2, puck, player1, -1);
}
arrowkeyS(player1);
wasd(player2);
Ball tempb1 = new Ball(new PVector(player1.position.x, player1.position.y),
new PVector(player1.last.x, player1.last.y),
0, player1.radius);
Ball tempb2 = new Ball(new PVector(player2.position.x, player2.position.y),
new PVector(player2.last.x, player2.last.y),
0, player2.radius);
Ball temppuck = new Ball(new PVector(puck.position.x, puck.position.y),
new PVector(puck.last.x, puck.last.y),
0, puck.radius);
// Colliding balls 1 and 2
player1.collide(tempb2);
player2.collide(tempb1);
player1.collide(temppuck);
player2.collide(temppuck);
puck.collide(tempb2);
puck.collide(tempb1);
fill(0);
textSize(16);
text("FPS:" + floor(frameRate), width-64, height-8);
fill(0);
textSize(32);
text(score1, width/4, height/16);
text(score2, width*3/4, height/16);
if (score1==5){
stage = 3;
}
if (score2==5){
stage = 4;
}
}
if (stage==3) {
background(205, 255, 255);
noStroke();
fill(255, 55, 55, 185);
rect(0, 0, 1280, 720);
textAlign(CENTER);
textSize(64);
fill(0);
text("Red Team Wins!", 640, 340);
textSize(32);
text("Press 'R' To Restart!", 640, 400);
if (keyPressed) {
if (key == 'r' || key == 'R') {
stage = 1;
score1 = 0;
score2 = 0;
}
}
}
if (stage==4) {
background(205, 255, 255);
noStroke();
fill(55, 55, 255, 185);
rect(0, 0, 1280, 720);
textAlign(CENTER);
textSize(64);
fill(0);
text("Blue Team Wins!", 640, 340);
textSize(32);
text("Press 'R' To Restart!", 640, 400);
if (keyPressed) {
if (key == 'r' || key =='R') {
stage = 1;
score1 = 0;
score2 = 0;
}
}
}
}
// Input
void keyPressed() {
gameKeyPressed();
}
void keyReleased() {
gameKeyReleased();
}
void reset(int winner) {
player1.reset(new PVector(width*3/4, height/2));
player2.reset(new PVector(width/4, height/2));
puck.reset(new PVector(width/2+winner*(width/8), random(height/4, height*3/4)));
}
void hal(Ball tb, Ball tp, Ball opp,int side){
PVector ratio = new PVector(0, 0);
if(tp.position.y != tb.position.y) ratio.y += getSign(tp.position.y-tb.position.y);
if(tp.position.x != tb.position.x) ratio.x += getSign(side*12+tp.position.x-tb.position.x);
if(tp.position.y != opp.position.y) ratio.y += .02*getSign(tp.position.y-opp.position.y);
if(ratio.x != 0) tb.position.x += (gVelocity) * getSign(ratio.x) * sqrt(abs(ratio.x)) / (abs(ratio.x)+abs(ratio.y));
if(ratio.y != 0) tb.position.y += (gVelocity) * getSign(ratio.y) * sqrt(abs(ratio.y)) / (abs(ratio.x)+abs(ratio.y));
}
float getSign(float num) {return num/abs(num);}
// Detects active keyS
void gameKeyPressed() {
if (key == CODED) {
if (keyCode == UP) {
keyUp = true;
keyDown = false;
}
if (keyCode == LEFT) {
keyLeft = true;
keyRight = false;
}
if (keyCode == RIGHT) {
keyRight = true;
keyLeft = false;
}
if (keyCode == DOWN) {
keyDown = true;
keyUp = false;
}
}
if (key == 'w' || key == 'W') {
keyW = true;
keyS = false;
}
if (key == 'a' || key == 'A') {
keyA = true;
keyD = false;
}
if (key == 'd' || key == 'D') {
keyD = true;
keyA = false;
}
if (key == 's' || key == 'S') {
keyS = true;
keyW = false;
}
if (key == 'r' || key == 'R') reset(0);
}
// Detects when keyS go inactive
void gameKeyReleased() {
if (key == CODED) {
if (keyCode == UP) keyUp = false;
if (keyCode == LEFT) keyLeft = false;
if (keyCode == DOWN) keyDown = false;
if (keyCode == RIGHT) keyRight = false;
}
if (key == 'w' || key == 'W') keyW = false;
if (key == 'a' || key == 'A') keyA = false;
if (key == 's' || key == 'S') keyS = false;
if (key == 'd' || key == 'D') keyD = false;
}
void arrowkeyS(Ball tb) {
if (keyDown == true)
// Limits positioneration when two directions are active
if (keyLeft == true || keyRight == true)
tb.position.y += gVelocity/sqrt(2);
else
tb.position.y += gVelocity;
else if (keyUp == true) {
if (keyLeft == true || keyRight == true)
tb.position.y -= gVelocity/sqrt(2);
else
tb.position.y -= gVelocity;
}
if (keyRight == true)
if (keyUp == true || keyDown == true)
tb.position.x += gVelocity/sqrt(2);
else
tb.position.x += gVelocity;
else if (keyLeft == true) {
if (keyUp == true || keyDown == true)
tb.position.x -= gVelocity/sqrt(2);
else
tb.position.x -= gVelocity;
}
}
void wasd(Ball tb) {
// Test ball 2
if (keyS == true)
if (keyA == true || keyD == true)
tb.position.y += gVelocity/sqrt(2);
else
tb.position.y += gVelocity;
else if (keyW == true) {
if (keyA == true || keyD == true)
tb.position.y -= gVelocity/sqrt(2);
else
tb.position.y -= gVelocity;
}
if (keyD == true)
if (keyW == true || keyS == true)
tb.position.x += gVelocity/sqrt(2);
else
tb.position.x += gVelocity;
else if (keyA == true) {
if (keyW == true || keyS == true)
tb.position.x -= gVelocity/sqrt(2);
else
tb.position.x -= gVelocity;
}
}
class Ally {
// All the usual stuff
PVector position;
PVector velocity;
PVector acceleration;
float r;
float maxforce; // Maximum steering force
float maxspeed; // Maximum speed
Ally(float x, float y) {
position = new PVector(x, y);
r = 12;
maxspeed = 3;
maxforce = 0.2;
acceleration = new PVector(0, 0);
velocity = new PVector(0, 0);
}
void applyForce(PVector force) {
acceleration.add(force);
}
void applyBehaviors(ArrayList<Ally> Allys) {
PVector separateForce = separate(Allys);
PVector seekForce = seek(new PVector(puck.position.x,puck.position.y));
separateForce.mult(2);
seekForce.mult(1);
applyForce(separateForce);
applyForce(seekForce);
}
PVector seek(PVector target) {
PVector desired = PVector.sub(target,position); // A vector pointing from the position to the target
desired.normalize();
desired.mult(maxspeed);
PVector steer = PVector.sub(desired,velocity);
steer.limit(maxforce); // Limit to maximum steering force
return steer;
}
PVector separate (ArrayList<Ally> Allys) {
float desiredseparation = r*2;
PVector sum = new PVector();
int count = 0;
for (Ally other : Allys) {
float d = PVector.dist(position, other.position);
if ((d > 0) && (d < desiredseparation)) {
PVector diff = PVector.sub(position, other.position);
diff.normalize();
diff.div(d); // Weight by distance
sum.add(diff);
count++; // Keep track of how many
}
}
// Average -- divide by how many
if (count > 0) {
sum.div(count);
sum.normalize();
sum.mult(maxspeed);
sum.sub(velocity);
sum.limit(maxforce);
}
return sum;
}
void update() {
velocity.add(acceleration);
velocity.limit(maxspeed);
position.add(velocity);
acceleration.mult(0);
}
void display() {
fill(182, 45, 182, 245);
noStroke();
pushMatrix();
translate(position.x, position.y);
ellipse(0, 0, 50, 50);
popMatrix();
}
}
class Opp {
// All the usual stuff
PVector position;
PVector velocity;
PVector acceleration;
float r;
float maxforce;
float maxspeed;
Opp(float x, float y) {
position = new PVector(x, y);
r = 12;
maxspeed = 3;
maxforce = 0.2;
acceleration = new PVector(0, 0);
velocity = new PVector(0, 0);
}
void applyForce(PVector force) {
acceleration.add(force);
}
void applyBehaviors(ArrayList<Opp> Opps) {
PVector separateForce = separate(Opps);
PVector seekForce = seek(new PVector(puck.position.x,puck.position.y));
separateForce.mult(2);
seekForce.mult(1);
applyForce(separateForce);
applyForce(seekForce);
}
PVector seek(PVector target) {
PVector desired = PVector.sub(target,position);
desired.normalize();
desired.mult(maxspeed);
PVector steer = PVector.sub(desired,velocity);
steer.limit(maxforce); // Limit to maximum steering force
return steer;
}
PVector separate (ArrayList<Opp> Opps) {
float desiredseparation = r*2;
PVector sum = new PVector();
int count = 0;
for (Opp other : Opps) {
float d = PVector.dist(position, other.position);
if ((d > 0) && (d < desiredseparation)) {
PVector diff = PVector.sub(position, other.position);
diff.normalize();
diff.div(d);
sum.add(diff);
count++;
}
}
if (count > 0) {
sum.div(count);
sum.normalize();
sum.mult(maxspeed);
sum.sub(velocity);
sum.limit(maxforce);
}
return sum;
}
void update() {
velocity.add(acceleration);
velocity.limit(maxspeed);
position.add(velocity);
acceleration.mult(0);
}
void display() {
fill(62, 43, 181, 245);
noStroke();
pushMatrix();
translate(position.x, position.y);
ellipse(0, 0, 50, 50);
popMatrix();
}
}
class Ball {
PVector position, last;
private int hue, radius;
Ball(PVector t, PVector tl, int th, int tr) {
position = t;
last = tl;
hue = th;
radius = tr;
}
void tick() {
PVector tempp = new PVector();
tempp.set(position.x, position.y);
position.set(position.x + gVelocityFriction*((position.x - last.x)),
position.y + gVelocityFriction*(position.y - last.y));
last.set(tempp.x, tempp.y);
if (position.x < 0) bounceX(0);
if (position.x > width) bounceX(width);
if (position.y < 0) bounceY(0);
if (position.y > height) bounceY(height);
}
void render() {
noStroke();
fill(hue, 25, 185);
ellipse(position.x, position.y, radius*2, radius*2);
}
void collide(Ball hit) {
if (dist(hit.position.x, hit.position.y, position.x, position.y) < hit.radius+radius) {
float phi = atan2(hit.position.y - position.y, hit.position.x - position.x);
float v1 = dist(position.x, position.y, last.x, last.y);
float ang1 = atan2(position.y - last.y, position.x - last.x);
float v2 = dist(hit.position.x, hit.position.y, hit.last.x, hit.last.y);
float ang2 = atan2(hit.position.y - hit.last.y, hit.position.x - hit.last.x);
last.x = position.x-gElasticity*(v2*cos(ang2-phi)*cos(phi)+v1*sin(ang1-phi)*cos(phi+PI/2));
last.y = position.y-gElasticity*(v2*cos(ang2-phi)*sin(phi)+v1*sin(ang1-phi)*sin(phi+PI/2));
tick();
}
}
void bounceY(float bound) {
last.y = bound + gElasticity * (position.y - last.y);
position.y = bound;
}
void bounceX(float bound) {
last.x = bound + gElasticity * (position.x - last.x);
position.x = bound;
}
void reset(PVector t) {
position = t;
last.x = position.x;
last.y = position.y;
}
}
Answers
Edit post, highlight code, press ctrl-o to format
Done; apologies ! Should be more readable now.
See examples, e.g. this one
https://processing.org/examples/bouncybubbles.html