Basic computer course project University

i was doing an assignment for my basic level computer course. what i wanted was to draw pac man ghosts in different colors (3 color choices) and 3 pac man ghosts at time = 3 which will slowly increase as the ghosts are killed. i havent went to the killing part yet because i cant draw the ghosts properly. my code draws all 3 ghosts and stacks them on top of each other. how do i draw 3 separate ghosts of random colors (from the 3 colors )

PImage startpage1;
PImage charaA;
PImage ball;
int t=3;
PImage enemy[] = new PImage [t] ;
int startTxtPo; 
int textboxend;
int extX, extY;
boolean gamestart;
int state = 0;
int xPo, yPo, xPoRec, yPoRec;
int recWidth, recHeight, fillspeed;
int time;
int movespeed;
int enemymove[] = new int[t];
int enemyX[] = new int [t];
int enemyY[] = new int [t];
int type;



PImage gamepage2;
int charaWid, charaHght;
int charaStartX, charaStartY;
boolean isUp, isDown, isLeft, isRight;

void setup()
{
  size(1500,900);
  startpage1 = loadImage("startpage1.png");
  charaA = loadImage("charaA.png");
  gamepage2 = loadImage("gamepage2.png");
  ball = loadImage("ball.png");
  startTxtPo = 880;
  textboxend = 1437;
  gamestart = false;
  xPo = yPo = xPoRec = yPoRec = 0;
  recWidth = 0;
  recHeight = height;
  fillspeed = 25;
  movespeed = 4;
  charaWid = charaHght = 75;
  charaStartX = width/2;
  charaStartY = height/2;
  extX = 38;
  extY = 864;
  time = 0;
  type = 0;
  
  for (int i = 0; i<enemy.length; i= i+1)
  {
    enemy[i] = loadImage("enemy"+i+".png");
    enemyX[i] = int(random(0,width - charaWid));
    enemyY[i] = -75;
    enemymove[i] = 2;
  }
  isUp = false;
  isDown = false;
  isLeft = false;
  isRight = false;
}

void draw()
{
  if (state == 0)
  {
    homePage();
  }else if (state == 1)
  {
    gamestart();
  }
  else if (state == 2)
  {
    fill(0);
    rect(xPoRec,yPoRec,recWidth,recHeight);
    recWidth = recWidth + fillspeed;
    if (recWidth >= width)
    {
      helpPage();
      fill(0);
      rect(xPoRec,yPoRec,recWidth,recHeight);
      xPoRec = xPoRec + fillspeed;
      if (xPoRec >= width)
      {
        xPoRec = xPoRec;
      }
    }
  }else if (state == 3)
  {
    fill(0);
    rect(xPoRec,yPoRec,recWidth,recHeight);
    recWidth = recWidth + fillspeed;
    if (recWidth >= width)
    {
      scoreboardPage();
      fill(0);
      rect(xPoRec,yPoRec,recWidth,recHeight);
      xPoRec = xPoRec + fillspeed;
      if (xPoRec >= width)
      {
        xPoRec = xPoRec;
      }
    }
  }
}

void homePage()
{
  image(startpage1, xPo, yPo, width, height);
  image(charaA, 300, 500, 300,300);
  //println("(" + mouseX +" , " +mouseY+")"); //find out the  X/Y coordinates of mouse
  fill(255,255,255);
  textSize(150);
  text("All-Terrain War", 216, 165);
  textSize(100);
  text("Start", startTxtPo, 384);
  text("Help", startTxtPo, 534);
  text("Scoreboard", startTxtPo, 684);
  textSize(50);
  text("Exit", extX, extY);
  xPoRec = 0;
  recWidth = 0;
}

void gamestart()
{
  gamestart = true;
  image(gamepage2, xPo, yPo, width, height);
  image(charaA, charaStartX, charaStartY, charaWid, charaHght);
  time = time +1;
  fill(0);
  textSize(25);
  text("Time: " + time/60 + " s", extX, extY);
   for(int i=0; i< enemy.length; i = i+1)
   {
     if (time/60 >= 3)
     {
       enemySpwn(enemyX[i], enemyY[i], charaWid, charaHght, type);
       if (enemyY[i] <= charaStartY)
       {
         enemyY[i] = enemyY[i] + enemymove[i];
       }else if (enemyY[i] > charaStartY)
       {
         enemyY[i] = enemyY[i] - enemymove[i];
       }
       if (enemyX[i] < charaStartX)
       {
         enemyX[i] = enemyX[i] + enemymove[i];
       }else if (enemyX[i] > charaStartX)
       {
         enemyX[i] = enemyX[i] - enemymove[i];
       }
       type = type +1;
       if (type >= enemy.length)
       {
         type = 0;
       }
     }
   }
  
  if (isUp == true)
  {
    charaStartY = charaStartY - movespeed;
    if (charaStartY <= 0)
    {
      charaStartY = 0;
    }
  }
  if (isDown == true)
  {
    charaStartY = charaStartY + movespeed;
    if (charaStartY >= height - 75)
    {
      charaStartY = height - 75;
    }
  }
  if (isLeft == true)
  {
    charaStartX = charaStartX - movespeed;
    if (charaStartX <= 0)
    {
      charaStartX = 0;
    }
  }
  if (isRight == true)
  {
    charaStartX = charaStartX + movespeed;
    if (charaStartX >= width - 75)
    {
      charaStartX = width -75;
    }
  }
}

void enemySpwn(int x, int y, int w, int h, int c)
{
  for(c=0; c<enemy.length; c=c+1)
  {
    image(enemy[c], x, y, w, h);
  }
}

void helpPage()
{
  image(startpage1, xPo, yPo, width, height);
  image(charaA, 300, 500, 300,300);
  fill(255,255,255);
  textSize(50);
  text("w,a,s,d to move,", startTxtPo, 384);
  text("mouseclick to shoot", startTxtPo, 434);
  text("Press p or P to pause", startTxtPo, 534);
  textSize(50);
  text("Exit", extX, extY);
}

void scoreboardPage()
{
  image(startpage1, xPo, yPo, width, height);
  image(charaA, 300, 500, 300,300);
  //println("(" + mouseX +" , " +mouseY+")"); //find out the  X/Y coordinates of mouse
  fill(255,255,255);
  textSize(100);
  text("High Scores", 814, 220);
  textSize(50);
  text("Exit", extX, extY);
}
void mousePressed()
{
  if (mouseX > startTxtPo && mouseX < textboxend && mouseY > 300 && mouseY < 384)
  {
    state = 1;
    gamestart = true;
  }else if (mouseX > startTxtPo && mouseX < textboxend && mouseY > 450 && mouseY < 534)
  {
    state = 2;
    //println("help");
  }else if (mouseX > startTxtPo && mouseX < textboxend && mouseY > 600 && mouseY < 684)
  {
    state = 3;
    //println("scoreboard");
  }
  if (mouseX > extX && mouseX < extX + 100 && mouseY > extY-50 && mouseY < extY && state == 2)
  {
    state = 0;
  }else if (mouseX > extX && mouseX < extX + 100 && mouseY > extY-50 && mouseY < extY && state == 3)
  {
    state = 0;
  }
}
void keyPressed()
{
  if(key == 'w'||key == 'W')
  {
    isUp = true;
  }
  if(key == 's'||key == 'S')
  {
    isDown = true;
  }
  if(key == 'a'||key == 'A')
  {
    isLeft = true;
  }
  if(key =='d'||key == 'D')
  {
    isRight = true;
  }
  
}

void keyReleased()
{
   if(key == 'w'||key == 'W')
  {
    isUp = false;
  }
  if(key == 's'||key == 'S')
  {
    isDown = false;
  }
  if(key == 'a'||key == 'A')
  {
    isLeft = false;
  }
  if(key =='d'||key == 'D')
  {
    isRight = false;
  }
}

https://drive.google.com/file/d/1BpXreD38CRnYHlU7GdQdTfVRPn2EtLZu/view?usp=sharing

By providing us a link to a place where we can download all the image files needed, including a working version of your code that runs, and asking a good question, you are awarded two pineapples. :pineapple: :pineapple:

I think the first issue that needs to be addressed is that you are drawing three ghosts for every ghost that is drawn. Notice that the function that eventually draws your ghosts is called enemySpwn(). When draw() calls gamestart(), we get to this loop that loops over all three ghosts, making the call to draw then:

for(int i=0; i< enemy.length; i = i+1)
   {
     if (time/60 >= 3)
     {
       enemySpwn(enemyX[i], enemyY[i], charaWid, charaHght, type);

But now look at what enemySpwn() actually does:

void enemySpwn(int x, int y, int w, int h, int c)
{
  for(c=0; c<enemy.length; c=c+1)
  {
    image(enemy[c], x, y, w, h);
  }
}

It is ALSO trying to loop over all the ghosts! WHOOPS! We don’t need to loop over them again - this function just needs to draw the one ghost, since it already gets called three times by the loop inside gamestart(). So if we remove that loop:

void enemySpwn(int x, int y, int w, int h, int c) {
  image(enemy[c], x, y, w, h);
}

And try running with those changes, we can see that we now get three ghosts, one of each color. Thus, the problem is fixed.


But can we do better? I think so. Your code is… kind of a mess. If the enemySpwn() function was called draw_ghost() instead, say, you might have wondered why it was looping over three ghosts instead of not drawing just one, and caught the above issue immediately. That is, the names of things are a bit… misleading. They could be clearer.

You might also consider using classes. Your code would be vastly simplified if you had, say, a Ghost class and a Button class.

1 Like

i have no idea what classes are. this is a basic course that is used to introduce computing to faculty of science year 1 students. the project was to make a game. and i decided to bite of more than i could chew because i want to do a major in comp science

is there a general code i can write so that the ghosts do not overlap? i did something similar for charaStartX and charaStartY so that the character does not go out of screen [under void gamestart()]. but the ghost coordinates are in an array. how do i call these coordinates?

You should be able to call the respective coordinates by calling the array at the position the respective ghost is. If you ghost was enemy[2] then the coordinates should be x[2] and y[2]. But to be honest, you really should look into classes. They would make you code so much more readable, and also save a lot of time and provide many options that make it much easier to do what you need, like managing 3 ghosts independently.

Fair enough. So far, so good.

Classes are a major topic in Computer Science; you will have to learn all about them if you hope to major in Computer Science.

https://processing.org/tutorials/objects/

ok. i will do that asap. but that will have to wait for tmr. gotta get to bed quick since i have a mid term at 9.30 in the morning.

  1. From several variables to arrays - Processing 2.x and 3.x Forum
  2. From several arrays to classes - Processing 2.x and 3.x Forum

how many variables can i have in a class? does the variable type have to go in the order i saw in the examples (can i have like maybe an int instead of a float)?

AFAIK, it’s as many as we declare them.

As long as a field doesn’t depend on another 1, we can declare them in any order.

We declare a field picking a datatype for it, just like a regular variable or parameter.

just want to ask how to increase number of ghosts? because the above part which caused the ghosts to stack on top of one another (answered by tfguy44) i thought it was to provide 3 different type of ghosts i could draw and following that i wanted another line of code which will create as many ghosts as i want.

We’re serious: You should use classes.

One of the main perks of using classes is that it is very easy to suddenly have more of a thing. Like more ghosts. Like different types of ghosts.


Let’s actually use classes now.

Pretend you are a ghost. I’m serious. You are a ghost. What do you need to know about yourself to be a good ghost?

I can think of a few things:

  • You need to know your X position.
  • You need to know your Y position.
  • You need to know what color you are, that is, you need to know which image to use when you get drawn.

You are a ghost. What can you do?

  • You can get drawn.
  • You can move.
  • You can start existing.

That’s enough. Now we can map out a basic Ghost object:

class Ghost {
  float x; // The X position for this ghost.
  float y; // The Y position for this ghost.
  int type; // The color (or type) of this ghost.

  // When a new Ghost starts existing, this function happens.
  Ghost() {
    x = random(width); // The starting X position is random.
    y = -30; // The starting Y position is above the screen.
    type = int(random( enemy.length )); // The type is random, for now.
  }
  
  // This is how a Ghost moves.
  void move(){
    // TODO: Fill this in.
  }

  // This is how a Ghost is drawn.
  void draw(){
    move();
    image( enemy[type], x, y );
  }
}
1 Like

And we can use it too!

class Ghost {
  float x;
  float y;
  int type;
  Ghost() {
    x = random(width);
    y = -30;
    type = int(random(enemy.length));
  }
  void move() {
    y++;
  }
  void draw() {
    move();
    image( enemy[type], x, y );
  }
}

Ghost[] ghosts = new Ghost[100];
PImage[] enemy = new PImage[3];

PImage startpage1;
PImage charaA;
PImage ball;
int startTxtPo; 
int textboxend;
int extX, extY;
boolean gamestart;
int state = 0;
int xPo, yPo, xPoRec, yPoRec;
int recWidth, recHeight, fillspeed;
int time;
int movespeed;

PImage gamepage2;
int charaWid, charaHght;
int charaStartX, charaStartY;
boolean isUp, isDown, isLeft, isRight;

void setup() {
  size(1500, 900);
  startpage1 = loadImage("startpage1.png");
  charaA = loadImage("charaA.png");
  gamepage2 = loadImage("gamepage2.png");
  ball = loadImage("ball.png");
  startTxtPo = 880;
  textboxend = 1437;
  gamestart = false;
  xPo = yPo = xPoRec = yPoRec = 0;
  recWidth = 0;
  recHeight = height;
  fillspeed = 25;
  movespeed = 4;
  charaWid = charaHght = 75;
  charaStartX = width/2;
  charaStartY = height/2;
  extX = 38;
  extY = 864;
  time = 0;
  // Load enemy images - just three of them!
  for (int i = 0; i<enemy.length; i= i+1) {
    enemy[i] = loadImage("enemy"+i+".png");
  }
  // Create Ghosts! 100 of them!
  for ( int i = 0; i < ghosts.length; i++) {
    ghosts[i] = new Ghost();
  }
  isUp = false;
  isDown = false;
  isLeft = false;
  isRight = false;
}

void draw()
{
  if (state == 0)
  {
    homePage();
  } else if (state == 1)
  {
    gamestart();
  } else if (state == 2)
  {
    fill(0);
    rect(xPoRec, yPoRec, recWidth, recHeight);
    recWidth = recWidth + fillspeed;
    if (recWidth >= width)
    {
      helpPage();
      fill(0);
      rect(xPoRec, yPoRec, recWidth, recHeight);
      xPoRec = xPoRec + fillspeed;
    }
  } else if (state == 3)
  {
    fill(0);
    rect(xPoRec, yPoRec, recWidth, recHeight);
    recWidth = recWidth + fillspeed;
    if (recWidth >= width)
    {
      scoreboardPage();
      fill(0);
      rect(xPoRec, yPoRec, recWidth, recHeight);
      xPoRec = xPoRec + fillspeed;
    }
  }
}

void homePage()
{
  image(startpage1, xPo, yPo, width, height);
  image(charaA, 300, 500, 300, 300);
  //println("(" + mouseX +" , " +mouseY+")"); //find out the  X/Y coordinates of mouse
  fill(255, 255, 255);
  textSize(150);
  text("All-Terrain War", 216, 165);
  textSize(100);
  text("Start", startTxtPo, 384);
  text("Help", startTxtPo, 534);
  text("Scoreboard", startTxtPo, 684);
  textSize(50);
  text("Exit", extX, extY);
  xPoRec = 0;
  recWidth = 0;
}

void gamestart() {
  gamestart = true;
  image(gamepage2, xPo, yPo, width, height);
  image(charaA, charaStartX, charaStartY, charaWid, charaHght);
  time = time +1;
  fill(0);
  textSize(25);
  text("Time: " + time/60 + " s", extX, extY);

  // Move and draw all the ghosts.
  for( int i = 0; i < ghosts.length; i++){
    ghosts[i].draw();
  }

  if (isUp == true)
  {
    charaStartY = charaStartY - movespeed;
    if (charaStartY <= 0)
    {
      charaStartY = 0;
    }
  }
  if (isDown == true)
  {
    charaStartY = charaStartY + movespeed;
    if (charaStartY >= height - 75)
    {
      charaStartY = height - 75;
    }
  }
  if (isLeft == true)
  {
    charaStartX = charaStartX - movespeed;
    if (charaStartX <= 0)
    {
      charaStartX = 0;
    }
  }
  if (isRight == true)
  {
    charaStartX = charaStartX + movespeed;
    if (charaStartX >= width - 75)
    {
      charaStartX = width -75;
    }
  }
}

void enemySpwn(int x, int y, int w, int h, int c)
{
  for (c=0; c<enemy.length; c=c+1)
  {
    image(enemy[c], x, y, w, h);
  }
}

void helpPage()
{
  image(startpage1, xPo, yPo, width, height);
  image(charaA, 300, 500, 300, 300);
  fill(255, 255, 255);
  textSize(50);
  text("w,a,s,d to move,", startTxtPo, 384);
  text("mouseclick to shoot", startTxtPo, 434);
  text("Press p or P to pause", startTxtPo, 534);
  textSize(50);
  text("Exit", extX, extY);
}

void scoreboardPage()
{
  image(startpage1, xPo, yPo, width, height);
  image(charaA, 300, 500, 300, 300);
  //println("(" + mouseX +" , " +mouseY+")"); //find out the  X/Y coordinates of mouse
  fill(255, 255, 255);
  textSize(100);
  text("High Scores", 814, 220);
  textSize(50);
  text("Exit", extX, extY);
}
void mousePressed()
{
  if (mouseX > startTxtPo && mouseX < textboxend && mouseY > 300 && mouseY < 384)
  {
    state = 1;
    gamestart = true;
  } else if (mouseX > startTxtPo && mouseX < textboxend && mouseY > 450 && mouseY < 534)
  {
    state = 2;
    //println("help");
  } else if (mouseX > startTxtPo && mouseX < textboxend && mouseY > 600 && mouseY < 684)
  {
    state = 3;
    //println("scoreboard");
  }
  if (mouseX > extX && mouseX < extX + 100 && mouseY > extY-50 && mouseY < extY && state == 2)
  {
    state = 0;
  } else if (mouseX > extX && mouseX < extX + 100 && mouseY > extY-50 && mouseY < extY && state == 3)
  {
    state = 0;
  }
}
void keyPressed()
{
  if (key == 'w'||key == 'W')
  {
    isUp = true;
  }
  if (key == 's'||key == 'S')
  {
    isDown = true;
  }
  if (key == 'a'||key == 'A')
  {
    isLeft = true;
  }
  if (key =='d'||key == 'D')
  {
    isRight = true;
  }
}

void keyReleased()
{
  if (key == 'w'||key == 'W')
  {
    isUp = false;
  }
  if (key == 's'||key == 'S')
  {
    isDown = false;
  }
  if (key == 'a'||key == 'A')
  {
    isLeft = false;
  }
  if (key =='d'||key == 'D')
  {
    isRight = false;
  }
}

This is far from perfect. I vastly simplified the movement. But look - now you know where to put the ghosts’ movement! Just go to the Ghost class, and adjust the move() function!

hi @SeanTYH, Please make sure to provide brief descriptions to your links for future readers. :slight_smile:

No, enemySpwn() is no longer needed. The Ghost class now deals with drawing a Ghost’s image.

Make sure you are not confusing ghosts, which should be an array of Ghost objects, with a specific Ghost object. Without seeing the line of code that’s causing the error, it’s hard to fix it.

1 Like

is there any way i could stop the ghosts from colliding with each other? i was recommended by the teaching assistant to use something along the lines of this:

void drawGhost(int x, int y, int w, int h, int i) //old enemyspwn() not needed anymore
{
image(enemy[i], x, y, w, h);
//old function draws ghost thrice here on top one of one another her
enemyY[i] = enemyY[i] + enemymoveY[i];
enemyX[i] = enemyX[i] + enemymoveX[i];
if (enemyY[i] <= charaStartY)
{
enemymoveY[i] = 2;
} else if (enemyY[i] > charaStartY)
{
enemymoveY[i] = -2;
}
if (enemyX[i] < charaStartX)
{
enemymoveX[i] = 2;
} else if (enemyX[i] > charaStartX)
{
enemymoveX[i] = -2;
}
type = type +1;
if (type >= enemy.length)
{
type = 0;
}

//redo // this was what i was recommended to do. at point of collision change their direction to negative so //they dont collide. something went wrong though so we were going crazy trying to fix it.
for (int c= 0; c<enemy.length; c=c+1)
{
for (int j=0; j< enemy.length; j=j+1)
{
if (c!=j&&enemyX[j] + charaWid > enemyX[c]-20 && enemyX[j] < enemyX[c]+charaWid)
{
fill(255, 0, 0);
text(“collision”, enemyX[c], enemyY[c]);
if(c%2==0 && time%60 == 3) // another suggested to use time to limit something.
enemymoveX[c] = -enemymoveX[c];
}
if (c!=j && enemyY[j] +charaHght > enemyY[c] && enemyY[j] < enemyY[i] + charaHght)
{
enemymoveY[c] = -enemymoveY[c]; // one teaching assistant said to do this
}
}
}

}

i tried to make a new class that contains the main character while working on the collisions because i read that i need to make both classes in order to compare the coordinates of either class. ( cannot make static reference to non static method) however now when i try to run the game the whole thing lags and unable to continue past the transition screen. i highlighted the areas where i think the error most likely is. what should i change to run the game smoothly the way i want it? (ps i changed the images becuz of copyright the teachers said so)

working one ( pre-collision detection)
https://drive.google.com/file/d/1Nmx5C2nkimuB5eo17KFx1E6mpYVmbp-A/view?usp=sharing

error i introduce new class
https://drive.google.com/file/d/1hvlrsNAeLod1QcyhS7ltkumiqg8tyEKR/view?usp=sharing

UPDATE i think i successfully made a class for the player character but can move the character (RESOLVED)
i think i m starting to get the hang of this
https://drive.google.com/file/d/1e9zqrE5tylUVZewUlImv3TfftY6_zr7V/view?usp=sharing

the bullets not appearing for a new shooting class i m trying to put in. what error did i make?
https://drive.google.com/file/d/1YR3WigJlE9eexe3PRdoHQ3x7DfLDHyNV/view?usp=sharing

1 Like

is it a necessity to use a class for bullets? could i use an array instead? but would using an array mess up the a future collision line of code cuz i have array and class in the same statement?

//enemyX from Ghost() from class Ghost.
eg. if(bullet + bulletWid>= enemyX && bullet < enemyX+ charaWid)
{
text(gameover,…)
etc
}

Classes should make working with your different sorts of objects much easier - not complicate it! It occurs to me that you might benefit greatly from a working example sketch. Here is one for you:

class Player {
  float x, y;
  Player() {
    x = width/2;
    y = height/2;
  }
  void draw() {
    move();
    fill(0, 0, 200);
    rect(x-10, y-10, 20, 20);
  }
  void move() {
    if (keys[0]) y--;
    if (keys[1]) y++;
    if (keys[2]) x--;
    if (keys[3]) x++;
  }
}

class Foe {
  boolean alive;
  float x, y, s;
  color c;
  Foe() {
    alive = true;
    c = color(random(128, 255), 0, 0);
    x = random(width);
    y = random(height);
    while (dist(x, y, width/2, height/2) < 100) {
      x = random(width);
      y = random(height);
    }  
    s = 20;
  }
  boolean draw() {
    if (alive) { 
      move();
      if ( collided() ) alive = false;
      fill(c);
      rect(x, y, s, s);
    }
    return (alive);
  }
  void move() {
  }
  boolean collided() {
    for ( int i = bullets.size()-1; i>=0; i--) {
      if (
        x < bullets.get(i).x && bullets.get(i).x < x + s &&
        y < bullets.get(i).y && bullets.get(i).y < y + s ) {
        bullets.get(i).alive = false;
        return (true);
      }
    }
    return (false);
  }
}

class Bullet {
  boolean alive;
  float x, y, a;
  Bullet() {
    alive = true;
    x = player.x;
    y = player.y;
    a = atan2(mouseY - player.y, mouseX - player.x);
  }
  boolean draw() {
    move();
    if (alive) {
      fill(255);
      ellipse(x, y, 5, 5);
    }
    return(alive);
  }
  void move() {
    x += 3 * cos(a);
    y += 3 * sin(a);
  }
}

Player player;
Foe[] foes = new Foe[100];
ArrayList<Bullet> bullets = new ArrayList();

void setup() {
  size(600, 400);
  player = new Player();
  for (int i = 0; i < foes.length; i++) foes[i] = new Foe();
  noStroke();
}

void draw() {
  background(0);
  for (int i = bullets.size()-1; i >= 0; i--) if ( !bullets.get(i).draw() ) bullets.remove(i);
  for (int i = 0; i < foes.length; i++) foes[i].draw();
  player.draw();
}

void mousePressed() {
  bullets.add( new Bullet() );
}

// Simple Keys by TfGuy44, V1, 11/18/2018
boolean[] keys=new boolean[4];void keyPressed(){k(true);}void keyReleased(){k(false);}
char[] check_for={'w','s','a','d','W','S','A','D',UP,DOWN,LEFT,RIGHT};void k(boolean b)
{for(int i=0;i<check_for.length;i++)if(check_for[i]==keyCode)keys[i%keys.length]=b;}

The important thing to notice here is that even though I am working with three different types of objects, there is no confusion about where the logic for anything is. The Player class handles how the player is drawn and moved. The Foe class deals with drawing enemies, checking to see if a foe has been hit by a bullet, and (maybe later) moving the enemies. The Bullet class deals with the bullets: how they move, creating a new one, keeping track of its position, drawing it, and (maybe later you could add this) checking to see if it is still in the window.

Also notice how simple the setup() and draw() functions are, despite having three different kinds of things. For each thing there is, the most complex operations I am doing is looping over the list or ArrayList of them and removing the dead ones!