How to make a bullets aim towards the mouse, but not continue to follow it?

How can I make my bullets follow the mouse position momentarily, but then forget its position so it wont continue to follow the mouse

Bullet Class

class Bullet
{
  PVector pos;
  PVector spd;
  float damage;
  PVector d;

  //constructor
  Bullet (float x, float y)
  {
    pos = new PVector (x, y);
  }

  void update ()
  {
    display();
    move();
  }

  //methods
  void display ()
  {
    fill (#EDED54);
    ellipse (pos.x, pos.y, 7, 7);
  }

  void move ()
  {
    if (t != null && PVector.dist(t,pos) > 7)
    {
      d = PVector.sub(t, pos);
      d.setMag(20);
      pos.add(d);
    }

    if (key == ' ')
    {
      t = new PVector(mouseX, mouseY);
    }
  }
  
/**
  void keyReleased ()
  {
    if (key == ' ')
    {
      setTarg = true;
    } else
    {
      setTarg = false;
    }
  }
  **/
}

Main Class

//ArrayLists
ArrayList<Bullet> bList = new ArrayList<Bullet>();
ArrayList<Zombie> zList = new ArrayList<Zombie >();
//global variables
int stage = 0;
int score = 0;
int startTime;
int pausedTime;
int zNumbs = 1;
float healthSize = 200;
float pSpd = 3;
float zSlow = 0;
float zHealth = 50;
float zY = -100;
boolean runningTimer = true;
PVector t = null;
//fonts
PImage background1;
PImage background2;
PFont font;

//player
Player player;
//-------------------------------------------------------------------
void setup ()
{
  size (800, 600);
  background1 = loadImage ("zombie.png");
  background2 = loadImage ("sand.png");
  font = createFont("text.ttf", 32);

  //Player
  player = new Player ();
  createZombies();
}
//-------------------------------------------------------------------
void draw ()
{
  stages ();
}
//-------------------------------------------------------------------
void stages ()
{
  if (stage == 0) //homescreen
  {
    stage0();
  } else if (stage == 1) //play screen
  {
    desert ();
    timer();
    score();
    if (bList.size() > 0)
    {
      collision();
    }
    health();
    displayZombies();
    player.display();
    displayBullets();
  } else if (stage == 2) //shop
  {
    stage2();
  } else if (stage == 3) //death screen
  {
    stage3();
  } else if (stage == 4) //how-to-play
  {
    stage4();
  } else if (stage == 5)//cheats
  {
    stage5();
  }
}
//-------------------------------------------------------------------
void desert ()
{
  image (background2, 0, 0);
}
//-------------------------------------------------------------------
void createZombies()
{
  for (int i=0; i<30; i++)
  {
    Zombie z = new Zombie (i*150+150, -100);
    zList.add(z);
  }
}
//-------------------------------------------------------------------
void displayZombies()
{
  for (int i=0; i<zNumbs; i++)
  {
    Zombie z = zList.get(i);
    z.update();

    if (zHealth <= 0)
    {
      zList.remove(z);
    }

    if (millis()/1000-startTime == 5)
    {
      zNumbs = 2;
    }
    
    if (millis()/1000-startTime == 10)
    {
      zNumbs = 4;
    }
  }
}
//-------------------------------------------------------------------
void displayBullets()
{
  for (int i=0; i<bList.size(); i++)
  {
    Bullet b = bList.get(i);
    b.update();
  }
}
//-------------------------------------------------------------------
void keyReleased ()
{
  if (key == ' ')
  {
    Bullet b = new Bullet(player.pos.x, player.pos.y-20);
    bList.add(b);
  }

  //put the key released code from bullet here and create a pvector that sets the target and sends it to bullet class
}
//-------------------------------------------------------------------
void timer ()
{
  fill (0);
  //textSize(30);
  textFont(font);
  text ("Time:", 15, 35);
  text (millis()/1000-startTime+"s", 105, 35);
}
//-------------------------------------------------------------------
void health ()
{
  fill (0);
  rect (300, 550, 200, 20);
  fill (0, 255, 0);
  rect (300, 550, healthSize, 20);
  fill (255, 0, 0);
  textSize (15);
  text ("HEALTH", 370, 565);

  if (healthSize <= 0)
  {
    stage = 3;
    runningTimer = false;
  }
}
//-------------------------------------------------------------------
void score ()
{
  fill (0);
  text ("SCORE: "+score, 590, 35);
}
//-------------------------------------------------------------------
void stage0 ()
{
  image (background1, 0, 0);
  fill (#3F813E);
  textFont(font);
  textSize (64);
  text ("ZOMBIE SURVIVAL", 100, 80);
  textSize (45);
  fill (255, 0, 0);
  text ("PLAY", 40, 200);
  text ("HOW-TO-PLAY", 40, 325);
  text ("CHEATS", 40, 450);
}
//-------------------------------------------------------------------
void stage_buttons()
{
  if (mouseX > 38 && mouseX < 178 && mouseY > 162 && mouseY < 216 && stage == 0)
  {
    stage = 1;
  }

  if (mouseX > 38 && mouseX < 400 && mouseY > 288 && mouseY < 343 && stage == 0)
  {
    stage = 4;
  }

  if (mouseX > 38 && mouseX < 230 && mouseY > 411 && mouseY < 468 && stage == 0)
  {
    stage = 5;
  }
  //---
  if (mouseX > 380 && mouseX < 445 && mouseY > 550 && mouseY < 580 && stage == 4)
  {
    stage = 0;
  }
  //---
  if (mouseX > 380 && mouseX < 445 && mouseY > 550 && mouseY < 580 && stage == 5)
  {
    stage = 0;
  }
  //---
  if (mouseX > 500 && mouseX < 700 && mouseY > 280 && mouseY < 480 && stage == 3)
  {
    stage = 0;
    healthSize = 200;
  }

  if (runningTimer == true)
  {
    startTime = millis()/1000;
  } else
  {
    pausedTime = millis() - startTime;
  }
}
//-------------------------------------------------------------------
void stage2 ()//shop
{
}
//-------------------------------------------------------------------
void stage3 ()//death screen
{
  background (0);

  textSize (100);
  fill (255, 0, 0);
  text("YOU DIED", 150, 130);
  textSize (40);
  text("ALIVE FOR: ", 50, 280);
  if (runningTimer == false)
  {
    text (pausedTime/1000+"s", 295, 280);
  }
  text("SCORE: "+score, 50, 430);

  fill (#3F813E);
  ellipse (600, 380, 200, 200);
  textSize (30);
  fill (0);
  text ("BACK TO", 535, 370);
  text ("MENU", 560, 410);
}
//-------------------------------------------------------------------
void stage4 ()//how-to-play
{
  background(0);
  fill (255, 0, 0);
  textSize(64);
  text("HOW-TO-PLAY", 150, 100);

  fill (#3F813E);
  textSize(25);
  text("Welcome to Zombie Survival! In order to survive, you need", 30, 200);
  text("to know the basics. To move, use your mouse, and press", 30, 240);
  text("anywhere on the map to move your player where you want", 30, 280);
  text("to go. To shoot, use the spacebar. You will not survive", 30, 320);
  text("with just the basics. Press 's', to enter the shop and buy the", 30, 360);
  text("necessary equipment. Shoot as many zombies as you can,", 30, 400);
  text("and survive for as long as possibe. Good luck!", 30, 440);

  fill(255, 0, 0);
  text ("EXIT", 380, 570);
}
//-------------------------------------------------------------------
void stage5 ()//cheats
{
  background(0);

  fill(255, 0, 0);
  textSize(25);
  text ("EXIT", 380, 570);
}
//-------------------------------------------------------------------
void collision ()
{
  for (int i = 0; i<zList.size(); i++)
  {
    Zombie z = zList.get(i);
    for (int j=0; j<bList.size(); j++)
    {
      Bullet b = bList.get(j);
      if (PVector.dist(z.pos, b.pos) < 50)
      {
        zHealth = zHealth - 10;
        bList.remove(b);
      }
    }
  }
}
//-------------------------------------------------------------------
void mouseReleased ()
{
  stage_buttons();
}
//-------------------------------------------------------------------

Zombie Class

class Zombie
{
  PVector pos;
  float size;
  PVector d;
  boolean setTarg = false;
  PVector t = null;
  PImage enemy;
  PImage enemyHurt;

  Zombie (float x, float y)
  {
    pos = new PVector (x, y);
    size = 50;

    enemy = loadImage ("enemy.png");
    enemyHurt = loadImage ("enemyHurt.png");
  }

  void update ()
  {
    move();
    coins();
    display();
    health();
  }

  void display ()
  {
    fill (#58AA75);   
    image (enemy, pos.x-50, pos.y);   
  }
  void move ()
  {
    if (t != null && PVector.dist(t, pos) > 25)
    {
      d = PVector.sub(t, pos);
      d.setMag(0.30);
      pos.add(d);
    }

    if (setTarg = true)
    {
      t = new PVector(player.pos.x-20, player.pos.y-20);
    }
    
    if (PVector.dist(t, pos) < 70)
    {
      healthSize = healthSize - 0.25;
      zSlow = 2;
    }
    else 
    {
      zSlow = 0;
    }
  }
   
  void coins ()
  {
    fill (#ECED3C);
    text ("COIN: "+score,590,35);
  }
  
  void health ()
  {
    fill (0);
    rect (pos.x-35, pos.y+95, 50, 10);
    fill (0,255,0);
    rect (pos.x-35, pos.y+95, zHealth, 10);
  }

  void mouseReleased ()
  {
    if (mousePressed)
    {
      setTarg = true;
    } else
    {
      setTarg = false;
    }
  }
}

Player Class

class Player
{
  //attributes
  PVector pos;
  boolean setTarg = false;
  PVector d;
  PVector t = null;
  //constructor
  Player ()
  {
    pos = new PVector (400, 550);
  }

  void display ()
  {
    move();
    player();
  }

  void player ()
  {
    float pivotX = 400;
    float pivotY = 550;

    pushMatrix();
    translate (pivotX, pivotY); //chatGPT code

    float mouseAngle = atan2(mouseY - pivotY, mouseX - pivotX); //chatGPT code

    rotate(mouseAngle);
    /*
    fill(#D9DB90);
    //player
    ellipse(pivotX, pivotY, 50, 50);
    //gun
    fill (0);
    rect(pivotX+25, pivotY-5, 25, 10);
    */
    popMatrix();
    
    fill(#D9DB90);
    //player
    ellipse(pos.x, pos.y, 50, 50);
    //gun
    fill (0);
    rect(pos.x+25, pos.y-5, 25, 10);
  }

  void move ()
  {
    if (t != null && PVector.dist(t,pos) > 25)
    {
      d = PVector.sub(t, pos);
      d.setMag(pSpd-zSlow);
      pos.add(d);
    }

    if (setTarg = true)
    {
      if (mousePressed)
      {
        t = new PVector(mouseX, mouseY);
      }
    }
  }
  
  void mouseReleased ()
  {
    if (mousePressed)
    {
      setTarg = true;
    } 
    else
    {
      setTarg = false;
    }
  }
    
}

That’s your starting point.

When you shoot, add a new bullet to the list.

but also set the t !!! b.t = new PVector(mouseX, mouseY);

void keyReleased ()
{
  if (key == ' ')
  {
    Bullet b = new Bullet(player.pos.x, player.pos.y-20);
    b.t = new PVector(mouseX, mouseY);   // !!!!!
    bList.add(b);
  }

don’t set t throughout, only initially when you shoot.

(you got several t, make sure you set and keep only the t of the Bullet class)

Chrisir

that’s dangerous

that says, set setTarg to true (which is not what you want!)

    if (setTarg = true)

Improvement

what you want is == which means "if setTarg is equal to true "

if (setTarg == true)

or in short

if (setTarg)

mouseReleased ()

won’t work inside the class.

Task

put the key released code from bullet here and create a pvector that sets the target and sends it to bullet class

Did you do this???

My current version




//ArrayLists
ArrayList<Bullet> bList = new ArrayList<Bullet>();
ArrayList<Zombie> zList = new ArrayList<Zombie>();

//global variables
int stage = 0;
int score = 0;
int startTime;
int pausedTime;
int zNumbs = 1;
float healthSize = 200;
float pSpd = 3;
float zSlow = 0;
float zHealth = 50;
float zY = -100;
boolean runningTimer = true;
PVector t = null;
//fonts
PImage background1;
PImage background2;
PFont font;

//player
Player player;

//-------------------------------------------------------------------

void setup ()
{
  size (800, 600);
  background1 = loadImage ("zombie.png");
  background2 = loadImage ("sand.png");
  font = createFont("text.ttf", 32);

  //Player
  player = new Player ();
  createZombies();
}
//-------------------------------------------------------------------
void draw ()
{
  stages ();
}
//-------------------------------------------------------------------
void stages ()
{
  if (stage == 0) //homescreen
  {
    stage0();
  } else if (stage == 1) //play screen
  {
    desert ();
    timer();
    score();
    if (bList.size() > 0)
    {
      collision();
    }
    health();
    displayZombies();
    player.display();
    displayBullets();
  } else if (stage == 2) //shop
  {
    stage2();
  } else if (stage == 3) //death screen
  {
    stage3();
  } else if (stage == 4) //how-to-play
  {
    stage4();
  } else if (stage == 5)//cheats
  {
    stage5();
  }
}
//-------------------------------------------------------------------
void desert ()
{
  background(0); 
  //image (background2, 0, 0);
}
//-------------------------------------------------------------------
void createZombies()
{
  for (int i=0; i<30; i++)
  {
    Zombie z = new Zombie (i*150+150, -100);
    zList.add(z);
  }
}
//-------------------------------------------------------------------
void displayZombies()
{
  for (int i=0; i<zNumbs; i++)
  {
    Zombie z = zList.get(i);
    z.update();

    if (zHealth <= 0)
    {
      zList.remove(z);
    }

    if (millis()/1000-startTime == 5)
    {
      zNumbs = 2;
    }

    if (millis()/1000-startTime == 10)
    {
      zNumbs = 4;
    }
  }
}
//-------------------------------------------------------------------
void displayBullets()
{
  for (int i=0; i<bList.size(); i++)
  {
    Bullet b = bList.get(i);
    b.update();
  }
}
//-------------------------------------------------------------------
void keyPressed ()
{
  Bullet b ;

  if (key == ' ')
  {
    b= new Bullet(player.pos.x, player.pos.y-20);
    bList.add(b);
  }

  //{
  //  if (key == ' ')
  //  {
  //    b.setTarg = true;
  //  } else
  //  {
  //    b.setTarg = false;
  //  }
  //}

  //put the key released code from bullet here and create a pvector that sets the target and sends it to bullet class
}
//-------------------------------------------------------------------
void timer ()
{
  fill (0);
  //textSize(30);
  //textFont(font);
  text ("Time:", 15, 35);
  text (millis()/1000-startTime+"s", 105, 35);
}
//-------------------------------------------------------------------
void health ()
{
  fill (0);
  rect (300, 550, 200, 20);
  fill (0, 255, 0);
  rect (300, 550, healthSize, 20);
  fill (255, 0, 0);
  textSize (15);
  text ("HEALTH", 370, 565);

  if (healthSize <= 0)
  {
    stage = 3;
    runningTimer = false;
  }
}
//-------------------------------------------------------------------
void score ()
{
  fill (0);
  text ("SCORE: "+score, 590, 35);
}
//-------------------------------------------------------------------
void stage0 ()
{
  //image (background1, 0, 0);
  background(1);

  fill (#3F813E);

  // textFont(font);

  textSize (64);
  text ("ZOMBIE SURVIVAL", 100, 80);
  textSize (45);
  fill (255, 0, 0);
  text ("PLAY", 40, 200);
  text ("HOW-TO-PLAY", 40, 325);
  text ("CHEATS", 40, 450);
}
//-------------------------------------------------------------------
void stage_buttons()
{
  if (mouseX > 38 && mouseX < 178 && mouseY > 162 && mouseY < 216 && stage == 0)
  {
    stage = 1;
  }

  if (mouseX > 38 && mouseX < 400 && mouseY > 288 && mouseY < 343 && stage == 0)
  {
    stage = 4;
  }

  if (mouseX > 38 && mouseX < 230 && mouseY > 411 && mouseY < 468 && stage == 0)
  {
    stage = 5;
  }
  //---
  if (mouseX > 380 && mouseX < 445 && mouseY > 550 && mouseY < 580 && stage == 4)
  {
    stage = 0;
  }
  //---
  if (mouseX > 380 && mouseX < 445 && mouseY > 550 && mouseY < 580 && stage == 5)
  {
    stage = 0;
  }
  //---
  if (mouseX > 500 && mouseX < 700 && mouseY > 280 && mouseY < 480 && stage == 3)
  {
    stage = 0;
    healthSize = 200;
  }

  if (runningTimer == true)
  {
    startTime = millis()/1000;
  } else
  {
    pausedTime = millis() - startTime;
  }
}
//-------------------------------------------------------------------
void stage2 ()//shop
{
}
//-------------------------------------------------------------------
void stage3 ()//death screen
{
  background (0);

  textSize (100);
  fill (255, 0, 0);
  text("YOU DIED", 150, 130);
  textSize (40);
  text("ALIVE FOR: ", 50, 280);
  if (runningTimer == false)
  {
    text (pausedTime/1000+"s", 295, 280);
  }
  text("SCORE: "+score, 50, 430);

  fill (#3F813E);
  ellipse (600, 380, 200, 200);
  textSize (30);
  fill (0);
  text ("BACK TO", 535, 370);
  text ("MENU", 560, 410);
}
//-------------------------------------------------------------------
void stage4 ()//how-to-play
{
  background(0);

  fill (255, 0, 0);
  textSize(64);
  text("HOW-TO-PLAY", 150, 100);

  fill (#3F813E);
  textSize(25);
  text("Welcome to Zombie Survival! In order to survive, you need", 30, 200);
  text("to know the basics. To move, use your mouse, and press", 30, 240);
  text("anywhere on the map to move your player where you want", 30, 280);
  text("to go. To shoot, use the spacebar. You will not survive", 30, 320);
  text("with just the basics. Press 's', to enter the shop and buy the", 30, 360);
  text("necessary equipment. Shoot as many zombies as you can,", 30, 400);
  text("and survive for as long as possibe. Good luck!", 30, 440);

  fill(255, 0, 0);
  text ("EXIT", 380, 570);
}
//-------------------------------------------------------------------
void stage5 ()//cheats
{
  background(0);

  fill(255, 0, 0);
  textSize(25);
  text ("EXIT", 380, 570);
}
//-------------------------------------------------------------------
void collision ()
{
  for (int i = 0; i<zList.size(); i++)
  {
    Zombie z = zList.get(i);
    for (int j=0; j<bList.size(); j++)
    {
      Bullet b = bList.get(j);
      if (PVector.dist(z.pos, b.pos) < 50)
      {
        zHealth = zHealth - 10;
        bList.remove(b);
      }
    }
  }
}
//-------------------------------------------------------------------
void mouseReleased ()
{
  stage_buttons();
  //  setTarg = false;
}
//-------------------------------------------------------------------

// ===================================================================================

class Zombie
{
  PVector pos;
  float size;
  PVector d;
  boolean setTarg = false;
  PVector t = null;
  PImage enemy;
  PImage enemyHurt;

  Zombie (float x, float y)
  {
    pos = new PVector (x, y);
    size = 50;

    enemy = loadImage ("enemy.png");
    enemyHurt = loadImage ("enemyHurt.png");
  }

  void update ()
  {
    move();
    coins();
    display();
    health();
  }

  void display ()
  {
    fill (#58AA75);   
    text ("enemy", pos.x-50, pos.y);
  }
  void move ()
  {
    if (t != null && PVector.dist(t, pos) > 25)
    {
      d = PVector.sub(t, pos);
      d.setMag(0.30);
      pos.add(d);
    }

    if (setTarg = true)
    {
      t = new PVector(player.pos.x-20, player.pos.y-20);
    }

    if (PVector.dist(t, pos) < 70)
    {
      healthSize = healthSize - 0.25;
      zSlow = 2;
    } else 
    {
      zSlow = 0;
    }
  }

  void coins ()
  {
    fill (#ECED3C);
    text ("COIN: "+score, 590, 35);
  }

  void health ()
  {
    fill (0);
    rect (pos.x-35, pos.y+95, 50, 10);
    fill (0, 255, 0);
    rect (pos.x-35, pos.y+95, zHealth, 10);
  }

  void mouseReleased ()
  {

    setTarg = false;
  }
}

// ===================================================================================

class Player
{
  //attributes
  PVector pos;
  boolean setTarg = false;
  PVector d;
  PVector t = null;
  //constructor
  Player ()
  {
    pos = new PVector (400, 550);
  }

  void display ()
  {
    move();
    player();
  }

  void player ()
  {
    float pivotX = 400;
    float pivotY = 550;

    pushMatrix();
    translate (pivotX, pivotY); //chatGPT code

    float mouseAngle = atan2(mouseY - pivotY, mouseX - pivotX); //chatGPT code

    rotate(mouseAngle);
    /*
    fill(#D9DB90);
     //player
     ellipse(pivotX, pivotY, 50, 50);
     //gun
     fill (0);
     rect(pivotX+25, pivotY-5, 25, 10);
     */
    popMatrix();

    fill(#D9DB90);
    //player
    ellipse(pos.x, pos.y, 50, 50);
    //gun
    fill (0);
    rect(pos.x+25, pos.y-5, 25, 10);
  }

  void move ()
  {
    if (t != null && PVector.dist(t, pos) > 25)
    {
      d = PVector.sub(t, pos);
      d.setMag(pSpd-zSlow);
      pos.add(d);
    }

    if (setTarg == true)
    {
      if (mousePressed)
      {
        t = new PVector(mouseX, mouseY);
      }
    }
  }

  void mouseReleased ()
  {
    if (mousePressed)
    {
      setTarg = true;
    } else
    {
      setTarg = false;
    }
  }
}

// ===================================================================================


class Bullet
{
  PVector pos;
  PVector spd;
  float damage;
  PVector d;

  PVector t; 

  //constructor
  Bullet (float x, float y)
  {
    pos = new PVector (x, y);

    t = new PVector(mouseX, mouseY);
    d = PVector.sub(t, pos);
    d.setMag(2);
  }

  void update ()
  {
    display();
    move();
  }

  //methods
  void display ()
  {
    fill (#EDED54);
    ellipse (pos.x, pos.y, 2, 7);
  }

  void move ()
  {
    if (t != null && PVector.dist(t, pos) > 7)
    {
      if (d!=null)
        pos.add(d);
    }

    if (key == ' ')
    {
    }
  }

  /**
   void keyReleased ()
   {
   if (key == ' ')
   {
   setTarg = true;
   } else
   {
   setTarg = false;
   }
   }
   **/
}