// Wutong Yang \\
// Tank Shooting \\
// "W" "A "S "D \\
// Move Four Direction \\
// "J" \\
// FIRE \\
// Surive As Long As You can \\
// Enjoy The game \\
// declare globals
int numberOfMonster=10;
Monster[] Monsters=new Monster[numberOfMonster];
Tank tank;
Cannon[] cannonList = new Cannon[10000]; // Allocate enough space for large amount of cannons, to avoid seg fault.
float scale=1; // Used to directly change the size of the tank and cannons.
int validCannon =0; // Used to organize cannons on the screen.
// keyboard controls
boolean upPressed;
boolean downPressed;
boolean leftPressed;
boolean rightPressed;
boolean firePressed;
boolean theFirstCannon=true; // Used to make sure shooting only one cannon for each press.
int death;
int score;
void setup() {
// set up window size ,frame rate
size(800, 600);
frameRate(60);
// instantiate game objects
tank=new Tank();
createMonsters();
for (int i=0; i<10000; i++) {
cannonList[i]=new Cannon();
}
}
void createMonsters() {
for (int i=0; i<Monsters.length; i++) {
Monsters[i]=new Monster();
}
}
void draw() {
if (firePressed&&theFirstCannon) // make sure one cannon for each "j" pressed.
{
validCannon++;
cannonList[validCannon-1].update1(); // load it as an active cannon
theFirstCannon = false;
}
for (int i=0; i<validCannon; i++) {
cannonList[i].update2(); // move the cannons on the screen
}
for (int i=0; i<Monsters.length; i++) {
Monsters[i].update();
}
tank.update();
// clear background
background(40, 206, 52);
for (int i=0; i<Monsters.length; i++) {
Monsters[i].display();
}
for (int i=0; i<validCannon; i++) {
cannonList[i].display();
}
tank.display();
textSize(32);
fill(score, 102, 153);
text("score:", 10, 30); // score display
text(score,120,30);
fill(255, 0, 0);
text("death", 10, 60); // death display
text(death,120,60);
}
void keyPressed() {
// detect if player is pressing up, down, left, or right
switch(key) {
case 'w':
upPressed=true;
break;
case 's':
downPressed=true;
break;
case 'a':
leftPressed=true;
break;
case 'd':
rightPressed=true;
break;
case 'j':
firePressed=true; // press to fire
break;
}
}
void keyReleased() {
// detect if player has released up, down, left or right
switch(key) {
case 'w':
upPressed=false;
break;
case 's':
downPressed=false;
break;
case 'a':
leftPressed=false;
break;
case 'd':
rightPressed=false;
break;
case 'j':
{
firePressed=false;
theFirstCannon=true; // make sure one cannon for one press
}
break;
}
}class Cannon {
PVector position = new PVector();
PVector velocity = new PVector();
Cannon() {
position.set(1000, 1000); // make sure the cannons do not appear on the screen being fired out
}
void update1() {// used to fire
// update positions and velocity of the cannons being fired out based on the current direction of the tank
// 0, 1, 2, 3 for up down left and right
if (tank.direction==0)
{
position.set(tank.position.x, tank.position.y-10*scale);
velocity.set(0, -5);
}
if (tank.direction==1)
{
velocity.set(0, 5);
position.set(tank.position.x, tank.position.y+10*scale);
}
if (tank.direction==2)
{
velocity.set(-5, 0);
position.set(tank.position.x-20*scale, tank.position.y);
}
if (tank.direction==3)
{
velocity.set(5, 0);
position.set(tank.position.x+20*scale, tank.position.y);
}
}
void update2() {// used to move
position.add(velocity);
if (!((position.x<800)&&(position.x>0)&&(position.y<600)&&(position.y>0))) // if the cannon moves out of the screen, cancel it to make sure it does not hit monsters who are not on the visible screen and change the score
{
position.set(1000, 1000);
velocity.set(0, 0);
}
}
void display() {
if ((velocity.x!=0)||(velocity.y!=0)) // only draw when it is valid, save memory and time
{
rectMode(CENTER);
fill(255, 0, 0);
rect(position.x, position.y, 1*scale, 1*scale);
}
for (int i=0; i<10; i++) {
if (dist(position.x, position.y, Monsters[i].position.x, Monsters[i].position.y)<20) // check if the cannon hit one of the 20 monsters. destroy it
{
score++;
Monsters[i] = new Monster();
}
}
}
}class Monster {
PVector position=new PVector(50, 50); // Initialization. Make it into the while loop.
PVector velocity=new PVector();
float monsterColor;
Monster() {
init();
}
void init() {
// set initial Monster values
while ((position.x<width)&&(position.x>0)&&(position.y>0)&&(position.y<height)) // this is the best way to randomize the monsters and make sure it does not appear on the screen at first
{
position.x=random(-200, width+200);
position.y=random(-200, height+200);
}
velocity.x=(tank.position.x-position.x)/125;//Velocity updated off the current tank position.
velocity.y=(tank.position.y-position.y)/125;//make sure the monsters was chasing the tank from the beginning.
monsterColor=random(255);
}
void update() {
// move monster towards the tank
position.add(velocity);
// if monster has moved off sponing areas, re-initialize it
if ((position.x<-200)||(position.x>width+200)||(position.y<-200)||(position.y>height+200)) {
init();
}
}
void display() {
stroke(monsterColor);
strokeWeight(1);
fill(monsterColor);
// tentacles
line(position.x-10, position.y-10, position.x+10, position.y+10);
line(position.x-10, position.y+10, position.x+10, position.y-10);
// face
ellipse (position.x, position.y, 10, 10);
// eyes
fill(255-monsterColor);
ellipse (position.x+2, position.y-2, 2, 2);
ellipse (position.x-2, position.y-2, 2, 2);
if (dist(position.x, position.y, tank.position.x, tank.position.y)<20) // check if it hit the core of the tank. yes: restart the game, clear the score, increment the death
{
death++;
setup();
}
}
}class Tank {
PVector position = new PVector();
int direction; // decide display of the tank, and cannon direction
Tank() {
position.set(400, 300); // spone at mid
direction = 2; // start towards left
}
void update() {
//change the direction of the tank
if (upPressed) {
position.add(0, -2);
direction = 0;
}
if (downPressed) {
position.add(0, 2);
direction = 1;
}
if (leftPressed) {
position.add(-2, 0);
direction = 2;
}
if (rightPressed) {
position.add(2, 0);
direction = 3;
}
if(position.x>800){
position.x=0;
}
if(position.x<0){
position.x=800;
}
if(position.y>600){
position.y=0;
}
if (position.y<0){
position.y=600;
}
}
void display() {
//the body first
scale = 3;
rectMode(CENTER);
fill(0);
rect(position.x, position.y, 10*scale, 10*scale);
fill(255);
// the core
ellipse (position.x, position.y, 6*scale, 6*scale);
fill(0);
strokeWeight(1);
stroke(0);
// barrel position
if (direction==2)// leftward
{
line(position.x-3*scale, position.y, position.x-6*scale, position.y);
rectMode(CORNERS);
rect(position.x-9*scale, position.y-1*scale, position.x-6*scale, position.y+1*scale);
}
if (direction==0)//upward
{
line(position.x, position.y-3*scale, position.x, position.y-6*scale);
rectMode(CORNERS);
rect(position.x-1*scale, position.y-9*scale, position.x+1*scale, position.y-6*scale);
}
if (direction==1)//downward
{
line(position.x, position.y+3*scale, position.x, position.y+6*scale);
rectMode(CORNERS);
rect(position.x-1*scale, position.y+6*scale, position.x+1*scale, position.y+9*scale);
}
if (direction==3)// rightward
{
line(position.x+3*scale, position.y, position.x+6*scale, position.y);
rectMode(CORNERS);
rect(position.x+9*scale, position.y+1*scale, position.x+6*scale, position.y-1*scale);
}
}//end of display
}