Skip to content

Instantly share code, notes, and snippets.

@macklinu
Last active December 23, 2015 11:49
Show Gist options
  • Select an option

  • Save macklinu/6630759 to your computer and use it in GitHub Desktop.

Select an option

Save macklinu/6630759 to your computer and use it in GitHub Desktop.
Asteroids snippet
class Asteroid {
PVector location;
PVector velocity;
PVector acceleration;
float mass;
String tweet;
float x, y, w, h;
boolean hit;
boolean dead;
float hitTime, textTime;
// standard constructor
Asteroid(float x, float y, float w, String tweet) {
this.x = x;
this.y = y;
this.w = map(w, 0, 140, 10, 140);
mass = map(w, 0, 140, 280, 800);
this.tweet = tweet;
location = new PVector(x, y);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
hit = dead = false;
textTime = 6000;
}
// used to make a copy of a to-be-destroyed asteroid
Asteroid(Asteroid a) {
this.x = a.x;
this.y = a.y;
this.w = map(a.w, 0, 140, 10, 140);
mass = map(a.w, 0, 140, 280, 800);
this.tweet = a.tweet;
location = new PVector(a.x, a.y);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
hit = dead = false;
textTime = 6000;
}
void applyForce(PVector force) {
PVector f = PVector.div(force, mass);
acceleration.add(f);
}
void update() {
velocity.add(acceleration);
location.add(velocity);
acceleration.mult(-0.01);
}
void display() {
if (hit) {
// want to implement a time system to display tweets in the asteroid field instead of a textbox
dead = true;
}
else {
stroke(255);
noFill();
ellipse(location.x, location.y, w, w);
}
}
void hit(boolean b) {
hit = b;
hitTime = millis();
}
/////////////
// getters //
/////////////
PVector repel(Asteroid a) {
PVector force = PVector.sub(location, a.location); // Calculate direction of force
float distance = force.mag(); // Distance between objects
distance = constrain(distance, 1.0, 10000.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction
float strength = (g * mass * a.mass) / (distance * distance); // Calculate gravitional force magnitude
force.mult(-1*strength); // Get force vector --> magnitude * direction
return force;
}
boolean isHit() {
return hit;
}
boolean isDead() {
return dead;
}
String getTweet() {
return tweet;
}
}
// draw() == main() loop in Processing
// removing some code
// original here: https://github.com/macklinu/senior-thesis-data-viz/blob/master/macklinu_senior_thesis/all_code/asteroids/asteroids.pde
ArrayList<Asteroid> asteroids;
ArrayList<Asteroid> tempAsteroids;
Gun gun;
void draw() {
// determine if SNES controller or keyboard is game controller
// draw the screen
// draw elements on screen (gun, asteroids, bullets, etc.)
// iterate through on screen asteroids
ListIterator<Asteroid> it = asteroids.listIterator(); // all on-screen asteroids
List<Bullet> activeBullets = gun.getBullets(); // current on-screen bullets
List<Asteroid> deadAsteroids = new ArrayList<Asteroid>(); // temp dead asteroid pool
List<Bullet> deadBullets = new ArrayList<Bullet>(); // temp dead bullet pool
while (it.hasNext()) { // while there are asteroids
Asteroid a = it.next(); // a = the asteroid we're looking at
// check each bullet for collisions
for (Bullet b : activeBullets) {
checkCollision(a, b);
if (b.isOffScreen()) deadBullets.add(b); // if the bullet leaves the screen
if (a.isHit()) { // if the asteroid is hit
deadBullets.add(b);
allTweets += a.getTweet() + "\n\n"; // add tweet to tweet text box on the right side of the screen
tweetArea.setText(allTweets).scroll(1); // scroll down the list as new tweets are populated
}
}
if (a.isDead()) deadAsteroids.add(a);
// apply gravitational force to the asteroids and gun
PVector aForce = a.repel(a);
a.applyForce(aForce);
PVector force = gun.attract(a);
a.applyForce(force);
a.update(); // update the asteroid
a.display(); // draw the asteroid
} // end of while loop
if (deadAsteroids.size() > 0) asteroids.removeAll(deadAsteroids);
if (deadBullets.size() > 0) activeBullets.removeAll(deadBullets);
// this is actually where the on-screen asteroids are created
// this method prevents concurrent modification/iteration
if (tempAsteroids.size() > 0) {
for (int i = 0; i < tempAsteroids.size(); i++) {
Asteroid temp = tempAsteroids.get(i); // get the temp asteroid
asteroids.add(new Asteroid(temp)); // create a new asteroid with the temporary asteroid's exact same properties
tempAsteroids = new ArrayList<Asteroid>(); // clear the tempAsteroids pool since we've added them to the main asteroid pool
}
}
}
void checkCollision(Asteroid a, Bullet b) {
if (dist(a.location.x, a.location.y, b.location.x, b.location.y) < a.w/2) { // works with an ellipse
a.hit(true); // asteroid was hit
}
}
class Bullet {
PVector location;
PVector velocity;
float r;
float speed;
float dx, dy;
Bullet(float lx, float ly, float angle) {
speed = 5;
// calculating angle of firing
if (angle >= 0 && angle <= 90) {
dx = map(angle, 0, 90, 0, 1);
dy = map(angle, 0, 90, -1, 0);
}
else if (angle >= 90 && angle <= 180) {
dx = map(angle, 90, 180, 1, 0);
dy = map(angle, 90, 180, 0, 1);
}
else if (angle >= 180 && angle <= 270) {
dx = map(angle, 180, 270, 0, -1);
dy = map(angle, 180, 270, 1, 0);
}
else if (angle >= 270 && angle <= 360) {
dx = map(angle, 270, 360, -1, 0);
dy = map(angle, 270, 360, 0, -1);
}
location = new PVector(lx, ly);
velocity = new PVector(dx * speed, dy * speed);
r = 3;
}
void update() {
location.add(velocity);
}
void display() {
// Display circle at x location
stroke(255);
noFill();
ellipse(location.x, location.y, r*2, r*2);
}
boolean isOffScreen() {
if (location.x+r < 0 || location.x+r > width
|| location.y+r < 0 || location.y+r > height) return true;
else return false;
}
}
class Gun {
ArrayList<Bullet> bullets = new ArrayList<Bullet>();
PVector location; // current position on screen
float x, y, w, h;
float angle, a;
float r;
float mass;
float amt;
Gun(float x, float y) {
this.x = x;
this.y = y;
location = new PVector(x, y);
mass = 10;
w = 10;
h = 15;
angle = 0;
a = 0;
amt = 1;
}
void rot(float a) {
this.a += a;
if (this.a > 360) this.a %= 360.;
if (this.a < 0) this.a += 360.;
}
void moveX(float mx) {
location.x += mx;
}
void moveY(float my) {
location.y += my;
}
PVector attract(Asteroid a) {
PVector force = PVector.sub(location, a.location); // Calculate direction of force
float d = force.mag(); // Distance between objects
d = constrain(d, 5.0, 25.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
float strength = (g * mass * a.mass) / (d * d); // Calculate gravitional force magnitude
force.mult(strength); // Get force vector --> magnitude * direction
return force;
}
void update() {
// update gun angle and all bullets
r = radians(a)+radians(angle);
for (Bullet b: bullets) {
b.update();
}
}
void display() {
noFill();
stroke(255);
pushMatrix();
translate(location.x, location.y);
rotate(r);
triangle(0, -h/2, w/2, h/2, -w/2, h/2);
popMatrix();
for (Bullet b: bullets) {
b.display();
}
}
void fire() {
bullets.add(new Bullet((location.x + (sin(r)*h/2)), (location.y + (cos(r)*-h/2)), (abs(a) % 360.)));
}
ArrayList<Bullet> getBullets() {
return bullets;
}
PVector getLocation() {
return location;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment