Interactive programming with Processing

From Knowledge Kitchen
Jump to: navigation, search


This example shows code for a Space Invaders type of game.

Images

You will need to import these three images with into your project's src folder:

alien.png

alien.png

bullet.png

bullet.png

spaceship.png

spaceship.png

App class

package edu.nyu.cs.fb1258;

import java.util.ArrayList;

import edu.nyu.cs.fb1258.Alien;
import edu.nyu.cs.fb1258.Spaceship;
import edu.nyu.cs.fb1258.Bullet;
import processing.core.*;

/**
 * Basic controller for Space Invaders
 * @author Foo Barstein
 * @version 0.1
 */
public class App extends PApplet {
	
	//window size of this app
	private final int w = 800;
	private final int h = 400;
	
	//make constants for some common colors... it's ok to make constants public
	public final int BLACK = this.color(0,0,0);
	public final int WHITE = this.color(255,255,255);
	
	//make constants for some common spacing... it's ok to make constants public
	public final static int ALIEN_SPACING = 20; 
	public final static int APP_MARGIN = 60; 
	public final static int NUM_ALIENS = 20;
	
	//variable to hold the spaceship
	private Spaceship spaceship;

	//an array to hold our friendly aliens
	private ArrayList<Alien> aliens = new  ArrayList<Alien>(); //will hold a bunch of  aliens

	//an array list that will hold any bullets  that are currently on screen.
	private ArrayList<Bullet> bullets = new  ArrayList<Bullet>();

	//setters and getters
	/**
	 * Getter for the ArrayList of Alien objects currently on the screen
	 * @return ArrayList of Alien objects
	 */
	public ArrayList<Alien> getAliens() {
		return this.aliens;
	}

	/**
	 * Setter for the ArrayList of Alien objects currently on the screen.
	 * @param aliens An ArrayList of Alien objects
	 */
	public void setAliens(ArrayList<Alien> aliens) {
		this.aliens = aliens;
	}

	/**
	 * Getter for the ArrayList of Bullet objects currently on the screen
	 * @return ArrayList of Bullet objects
	 */
	public ArrayList<Bullet> getBullets() {
		return this.bullets;
	}

	/**
	 * Setter for the ArrayList of Bullet objects currently on the screen.
	 * @param aliens An ArrayList of Bullet objects
	 */
	public void setBullets(ArrayList<Bullet> bullets) {
		this.bullets = bullets;
	}

	
	/**
	 * Called once to set up window
	 */
	public void settings() {
		this.size(this.w, this.h); //set window size		
	}
	
	/**
	 * Called once on load. Used to create the  window and "global" settings.
	 */
	public void setup() {
		this.background(this.BLACK); //set background  color
		
		//initialize spaceship
		this.spaceship = new Spaceship(this); // pass reference to this App object
		
		//initialize all aliens
		int x = App.APP_MARGIN; //x position of  first alien
		int y = App.APP_MARGIN; //y position of  first alien

		//loop as many times as there are aliens
		for (int i=0; i<App.NUM_ALIENS; i++) {
			
			//create a new alien for each  element of the array
			Alien alien = new Alien(x, y, this);  //pass the x,y coords and a  reference to this App class
			this.aliens.add(alien); //add this  alien to the array list

			//update x so the  next alien we draw appears further  to the right
			x += alien.getWidth() + App.ALIEN_SPACING; 
			
			//stay within bounds of the screen
			if (x > this.width - alien.getWidth() - App.APP_MARGIN) {
				//move down to the next line  before drawing next alien
				x = App.APP_MARGIN; //reset back  to left side of screen
				y += alien.getHeight() + App.ALIEN_SPACING; //upadte y so the  next row of aliens appears  further down the screen
			}
			
		}
	}
	
	/**
	 * Called repeatedly approximately 24 times  per second (Processing's default "frame  rate").  Used to update the animation and  enforce game play logic.
	 */
	public void draw() {
		//wipe the screen blank
		this.background(this.BLACK);
		
		//draw the spaceship
		this.spaceship.move(); //have the spaceship  move itself to a new location
		this.spaceship.draw(); //have the spaceship  draw itself to the screen
		
		//loop through ArrayList of bullets
		for (int i=0; i<this.bullets.size(); i++) {
			Bullet bullet = this.bullets.get(i);
			bullet.move(); //have the bullet  move itself to a new location
			bullet.draw(); //have the bullet  draw itself to the screen
		}
		
		//loop through ArrayList of aliens
		for (int i=0; i<this.aliens.size(); i++) {
			Alien alien = this.aliens.get(i);
			alien.move(); //have each alien move  itself to a new location
			alien.draw(); //have each alien draw  itself to the screen
		}
		
		//detect any collisions between bullets  and aliens
		//do this by brute force looping through  all combinations of bullets and aliens  and checking their positions
		ArrayList<Alien> aliensToRemove = new  ArrayList<Alien>(); //will hold the next  generation of aliens
		ArrayList<Bullet> bulletsToRemove = new  ArrayList<Bullet>(); //will hold the  next generation of bullets
		for (Bullet bullet : this.bullets) {
			for (Alien alien : this.aliens) {
				//our Bullet class has a static  method that checks whether there  is a collision
				if (Bullet.isCollision(bullet,  alien)) {
					//if there is a collision,  remove the bullet and the  alien from the screen
					aliensToRemove.add(alien); // add this alien to the list  that we will remove
					bulletsToRemove.add(bullet);  //add this bullet to the  list that we will remove
				}
			}
		}
		
		//enter all aliens we earmarked as  removable into removal proceedings
		for (Alien alien : aliensToRemove) {
			alien.kill(); //tell the alien to  kill itself
		}
		
		//remove all bullets we earmarked as  removable
		for (Bullet bullet:bulletsToRemove) {
			bullet.kill(); //tell the bullet to  kill itself
		}

	}

	/**
	 * Called whenever a key is pressed by the  user.  Move the spaceship left or right or  fires a bullet, depending on the key.
	 */
	public void keyPressed() {
		//the variable key holds a char  representing the key that was pressed.
		//processing has a few constants that  come in handy in determining which key  was pressed

		//left and right keys have codes
		if (this.key == PConstants.CODED) {
			switch (this.keyCode) {
				case PConstants.LEFT:
					this.spaceship.goLeft(); //turn left
					break;
				case PConstants.RIGHT:
					this.spaceship.goRight(); //turn right
					break;
				case PConstants.UP:
					this.spaceship.goUp(); //turn up
					break;
				case PConstants.DOWN:
					this.spaceship.goDown(); //turn down
					break;
			}
		}
		//space key does not have a code
		else if (key == ' ') {
			//handle space key
			this.spaceship.shoot();
		}
	}	
	
	/**
	 * Automatically called to start your program.  This method calls PApplet's main method and passes it the class name of this class.
	 * @param args Command-line arguments (ignored)
	 */
	public static void main(String[] args) {
		PApplet.main("edu.nyu.cs.fb1258.App");
	}
	
}

Alien

package edu.nyu.cs.fb1258;

import processing.core.PApplet;
import processing.core.PImage;

/**
 * The alien class
 * @author Foo Barstein
 * @version 0.1
 */
public class Alien {

	//will hold a reference to the App object, which inherits from PApplet and therefore handles all the  Processing-specific stuff
	private App app;
	
	//make sure the image file is in the src  folder
	private final static String ALIEN_IMAGE_PATH  = "alien.png"; //alien image file
	private PImage img; //will hold the image to  use for this alien
	
	private final static int MAX_SPEED = 4; // maximum speed the alien will move in any  direction
	
	private boolean isAlive = true; //flag to  hold living status of this alien

	public int x, y; //position
	private int speedX, speedY; //speed in both  directions

	public Alien(int x, int y, PApplet app) {
		//set up initial properties for this  alien
		this.app = (App) app; //keep a  reference to the PApplet class to handle  all Processing-specific functions and  variables

		//set position
		this.x = x; //x position
		this.y = y; //y position
		
		//set random speeds
		this.speedX = this.getRandomSpeed();
		this.speedY = this.getRandomSpeed();
		
		//load the alien image and store in  PImage variable
		this.img = app.loadImage(Alien.ALIEN_IMAGE_PATH);
		
	}

	/**
	 * Get the width of this alien, based on the  width of its image.
	 * @return int width of this image
	 */
	public int getWidth() {
		return this.img.width; //return the PImage object's width property
	}
	
	/**
	 * Get the height of this alien, based on  the width of its image.
	 * @return int height of this image
	 */
	public int getHeight() {
		return this.img.height; //return the PImage object's height property
	}
	
	/**
	 * Get a random speed.
	 * @return random int between min and max  speed settings
	 */
	public int getRandomSpeed() {
		//generate a random int between the  alien's -MAX_SPEED and +MAX_SPEED
		int speed = (int) ((Math.random() * Alien.MAX_SPEED * 2) - Alien.MAX_SPEED);
		return speed;
	}


	/**
	 * Moves this alien to a new position.
	 * Setter for x and y properties.
	 */
	public void setPosition(int x, int y) {
		this.x = x;
		this.y = y;
	}
	
	/**
	 * Sets by how much this alien moves each  frame.
	 * Setter for speedX and speedY properties.
	 */
	public void setSpeed(int speedX, int speedY)  {
		this.speedX = speedX;
		this.speedY = speedY;
	}
	
	/**
	 * Kill this alien.
	 * Simply sets this alien's isAlive  attribute to false and removes it from the  PApplet's list of aliens;
	 */
	public void kill() {
		this.isAlive = false;
		this.app.getAliens().remove(this); //remove  this alien from the list of aliens
	}
	
	/**
	 * Draws this alien to the PApplet screen.   Each alien draws itself to the main app  screen in this way.
	 */
	public void draw() {
		//no point drawing a dead alien...
		if (this.isAlive) {
			//draw the image using PApplet's  image method
			this.app.image(this.img, this.x, this.y);
		}
	}

	/**
	 * Move this alien to a randomly-generated new position
	 */
	public void move() {
		int speedX = this.getRandomSpeed(); // new speed in x direction
		int speedY = this.getRandomSpeed(); // new speed in y direction

		this.setSpeed(speedX, speedY); //update  internal speed info
		
		int newX = this.x + this.speedX; // calculate new x position
		int newY = this.y + this.speedY; // calculate new y position

		//keep this alien within the borders!
		if (newX < 0) newX = this.app.width; //if  it went too far to the left, wrap it to  the right
		else if (newX > this.app.width) newX = 0; //if it went too far to the right, wrap  it to the left
		if (newY < 0) newY = this.y; //if it  went too far up, don't let it go any  further
		else if (newY + this.getHeight() > this.app.width) newY = this.y; //if it went too  far down, don't let it go any further
		
		//update to the new position
		this.setPosition(newX, newY);
	}
	
}

Spaceship class

package edu.nyu.cs.fb1258;

import processing.core.PApplet;
import processing.core.PImage;

/**
 * 
 * This class represents the spaceship.
 * @author Foo Barstein
 * @version 0.1
 *
 */
public class Spaceship {

	//will hold a reference to the App object, which inherits from PApplet and therefore handles all the  Processing-specific stuff
	PApplet app;
	
	//make sure the image file is in the src  folder
	private final static String SPACESHIP_IMAGE_PATH = "spaceship.png"; // image file
	private PImage img; //will hold the image to  use for this spaceship
	
	private int x, y; //position
	private int speedX = 5; //speed in x  direction... start out going to the right
	private int speedY = 5; //speed in Y direction... the y position is changed by this amount every time the ship goes up or down
	
	public Spaceship(PApplet app) {
		//set up initial properties for this  alien
		this.app = app; //keep a reference to  the PApplet class to handle all  Processing-specific functions and  variables

		//position it on screen
		this.x = (int) (this.app.width / 2); //x  position centered on screen
		this.y = this.app.height - App.APP_MARGIN; // y position close to bottom of screen
		
		//load the image and store in PImage  variable
		this.img = this.app.loadImage(Spaceship.SPACESHIP_IMAGE_PATH);
	}

	/**
	 * Get the width of this spaceship, based on  the width of its image.
	 */
	public int getWidth() {
		return this.img.width;
	}
	
	/**
	 * Get the height of this spaceship, based  on the width of its image.
	 */
	public int getHeight() {
		return this.img.height;
	}
	
	/**
	 * Slide the spaceship further to the right  or left, depending upon the current  direction it's moving.
	 */
	public void move() {
		int newX = this.x + this.speedX; // calculate move by whichever amount is  specified in speedX variable.
		
		//check bounds
		boolean outOfBoundsToTheLeft = newX < 0  + App.APP_MARGIN; //too far to the left?
		boolean outOfBoundsToTheRight = newX >  this.app.width - this.getWidth() - App. APP_MARGIN; //too far to the right?

		//if out of bounds...
		if (outOfBoundsToTheRight ||  outOfBoundsToTheLeft) {
			 //reverse direction
			this.toggleDirection(); //inverts  the sign of speed
			newX = this.x + this.speedX; // calculate move in new direction
		}
		
		//make update to position
		this.x = newX;
		
	}
	
	/**
	 * Sets by how much this spaceship moves  each frame.
	 * Setter for speedX property.
	 */
	public void setSpeed(int speedX) {
		this.speedX = speedX;
	}
	
	/**
	 * Draws this alien to the PApplet screen.   Each alien draws itself to the main app  screen in this way.
	 */
	public void draw() {
		//draw the image using PApplet's image  method
		this.app.image(this.img, this.x, this.y);
	}

	/**
	 * Move this spaceship in the opposite  direction from which it is currently moving
	 */
	public void toggleDirection() {
		this.speedX = -this.speedX; //invert the  sign of the speed it's currently moving
	}
	
	/**
	 * Set speed such that the spaceship moves  to the right.
	 */
	public void goRight() {
		//set speed to a positive value
		this.speedX = Math.abs(this.speedX);
	}

	/**
	 * Set speed such that the spaceship moves to the right.
	 */
	public void goLeft() {
		//set speed to a negative value
		this.speedX = -Math.abs(this.speedX);
	}

	/**
	 * Set speed such that the spaceship moves to up.
	 */
	public void goUp() {
		//set speed to a negative value
		this.y = this.y - Math.abs(this.speedY);
		
		//check bounds
		boolean isTooFarUp = this.y < 0 + this.getHeight();

		//if the spaceship is too far up...
		if (isTooFarUp) {
			//reposition this spaceship at the bottom of the screen
			this.y = app.height - this.getHeight();
		}
	}
	
	/**
	 * Set speed such that the spaceship moves to up.
	 */
	public void goDown() {
		//set speed to a negative value
		this.y = this.y + Math.abs(this.speedY);

		//check bounds
		boolean isTooFarDown = this.y > this.app.height - this.getHeight();

		//if the spaceship is too far up...
		if (isTooFarDown) {
			//reposition this spaceship at the bottom of the screen
			this.y = 0;
		}
	}
	
	/**
	 * Shoots a bullet out of the spaceship.
	 */
	public void shoot() {
		//create a new bullet object positioned  at the center of this spaceship
		int x = (int) (this.x + (this.getWidth()  / 2)); //the center x position of this  spaceship
		int y = (int) (this.y - (this. getHeight() / 2)); //the center y  position of this spaceship

		//create bullet object
		Bullet bullet = new Bullet(x, y, this.app);
		
	}

}

Bullet class

package edu.nyu.cs.fb1258;

import processing.core.PApplet;
import processing.core.PImage;

public class Bullet {

	//will hold a reference to the App object, which inherits from PApplet and therefore handles all the  Processing-specific stuff
	private App app;
	
	//make sure the image file is in the src  folder
	private final static String BULLET_IMAGE_PATH = "bullet.png"; //image  file
	private PImage img; //will hold the image to  use for this bullet
	
	public int x, y; //position
	private int speedY = -10; //speed in y  direction... going up-screen
	
	public Bullet(int x, int y, PApplet app) {
		//set up initial properties for this  bullet
		this.app = (App) app; //keep a reference  to the PApplet class to handle all  Processing-specific functions and  variables

		//position it on screen
		this.x = x;
		this.y = y;
		
		//load the image and store in PImage  variable
		this.img = app.loadImage(Bullet.BULLET_IMAGE_PATH);
		
		//add this Bullet object to the  PApplet's list of bullets
		this.app.getBullets().add(this);

	}

	/**
	 * Get the width of this bullet, based on  the width of its image.
	 */
	public int getWidth() {
		return this.img.width; //return the PImage object's width property
	}
	
	/**
	 * Get the height of this bullet, based on  the width of its image.
	 */
	public int getHeight() {
		return this.img.height; //return the PImage object's height property
	}
	
	/**
	 * Slide the bullet further up the screen.
	 */
	public void move() {
		int newY = this.y + this.speedY; // calculate move by whichever amount is  specified in speedY variable.
		
		//check bounds
		boolean outOfBoundsToTheTop = newY < 0 +  this.getHeight(); //too far up the  screen?

		//if out of bounds...
		if (outOfBoundsToTheTop) {
			 //remove it from the array of  bullets
			this.app.getBullets().remove(this); //aren't  ArrayLists great?
		}
		
		//make update to position
		this.y = newY;
		
	}
	
	/**
	 * Sets by how much this spaceship moves  each frame.
	 * Setter for speedX property.
	 */
	public void setSpeed(int speedY) {
		this.speedY = speedY;
	}

	/**
	 * Kill this bullet.
	 * Simply removes this bullet from the  PApplet's list of bullets;
	 */
	public void kill() {
		this.app.getBullets().remove(this); //remove this  bullet from the list of aliens
	}
	

	/**
	 * Draws this alien to the PApplet screen.   Each alien draws itself to the main app  screen in this way.
	 */
	public void draw() {
		//draw the image using PApplet's image  method
		this.app.image(this.img, this.x, this.y);
	}
	
	/**
	 * Static method to check collision between any bullet and any alien
	 */
	public static boolean isCollision(Bullet  bullet, Alien alien) {
		boolean collision = false; //flag to  indicate whether a collision has been  detected
		
		//check whether bullet is within the box  representing the alien
		if (bullet.x >= alien.x && bullet.x +  bullet.getWidth() <= alien.x + alien. getWidth()) {
			if (bullet.y >= alien.y && bullet.y  + bullet.getHeight() <= alien.y +  alien.getHeight()) {
				collision = true;
			}
		}
		
		return collision;
	}
	

}

Interactive Computing

If you liked making games, take more application-oriented courses! Computer science is not about making applications or games. Further reading on this difference here and here. (Note the opinions expressed in those links are not necessarily endorsed by me - they simply give you some perspective on the issue).


What links here