I encountered a big sticking point in a Java game I've been coding over the summer. I was working on it pretty steadily until mid-June but since then I've been stuck on a single thing. My character is supposed to be able to charge and shoot qi blasts, and that part works, but *some of the time* I get one or more extra unwanted qi blasts. Actually it happens pretty frequently.
Unlike the single qi blast that is supposed to be created, these ones start out fully charged and they fire off in random directions (instead of in the direction of the mouse). Those are the clues to this mystery I guess. The single qi blast that is created with or without extra ones charges correctly and fires off toward the mouse like it is supposed to. Another clue: it seems like there are a few frames in between the desired qi blast being spawned and the unwanted ones spawning. Like two or three frames - but I'm not entirely sure, so I don't want to throw anyone off.
For my code I started off with the Cherno's game engine that tried to replicate “Realm of the Mad God” and altered and built on it. The qi blast is a QiBlast object which is a type of Projectile object which is a type of Entity object. I am trying to not post all my code here because I have looked at it, gone away from it, and looked at it again - I think the problem could be resolved without me posting all my code, but I will post as needed. Here is the QiBlast class:
public class QiBlast extends Projectile {
SpriteSheet spritesheet_qb_b;
AnimationTimer chargeTimer;
private Mob mob;
private Mouse mouse;
private boolean init = false;
public boolean charging = true;
private boolean fired = false;
// private int x, y;
// private double nx, ny;
private double speed, range, damage;
// private double angle;
private double dx;
private double dy;
//!!!
// no double or triple qi blasts
// bug where it shoots where it shot last time
// range, speed, and damage should also be parameters
public QiBlast(int x, int y, Mob shooter, Mouse mousey) {
super(x, y, shooter);
range = 200;
speed = 4;
//damage = 20;
mouse = mousey;
mob = shooter;
//sprite = Sprite.rotate(Sprite.projectile_arrow, angle);
//rateOfFire = 15;
spritesheet_qb_b = new SpriteSheet("qiblast_blue.png", 94, 63, 3, 2, 30, 30, 1);
sprite = spritesheet_qb_b.getSprites()[3];
//nx = speed * Math.cos(angle);
//ny = speed * Math.sin(angle);
}
public synchronized void update() {
//super.update();
/*
if (level.tileCollision((int) (x + nx), (int) (y + ny), 7, 5, 4)) {
level.add(new ParticleSpawner((int) x, (int) y, 44, 50, level));
remove();
}*/
//change it so you have to hold the mouse button to charge it - if you let go before it is charged, it disappears and makes a sound
if (!init) {
init();
init = true;
}
if (charging) {
// If the player rotates, re-calculate the angle the projectile fires at
if (mouse.mouseDown == false) {
mob.setCharging(false);
remove();
}
//System.out.println("kakakaka");
this.sprite = spritesheet_qb_b.getSprites()[chargeTimer.getFrames()];
if (chargeTimer.getFrames() == 5)
charging = false;
//mob.setCharging(false);
this.x = mob.getX() + 5;
this.y = mob.getY() + 5;
}
if (!charging && mouse.mouseDown == true) {
//
x = mob.getX() + 5;
y = mob.getY() + 5;
}
// need events and stuff for this
if (!charging && mouse.mouseDown == false && !fired) {
fired = true;
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
int getx = (int) b.getX();
int gety = (int) b.getY();
dx = getx - (Game.screen_width / 2);
dy = gety - (Game.screen_height / 2);
//angle = Math.atan2(dy, dx);
//nx = speed * Math.cos(angle);
//ny = speed * Math.sin(angle);
double invlen = 1.0f / Math.sqrt(dx * dx + dy * dy);
nx = speed * dx * invlen;
ny = speed * dy * invlen;
mob.setCharging(false);
move();
}
// !!! also, why are the extra qi blasts fully charged?
// !!! maybe they are old objects that aren't being destroyed properly?
if (!charging && fired) {
move();
}
}
private void move() {
//if (!level.tileCollision(x, y, nx, ny, 7)) {
x += nx;
y += ny;
//}
xOrigin = mob.x;
yOrigin = mob.y;
if (distance() > range) remove();
}
public void init() {
chargeTimer = new AnimationTimer();
chargeTimer.anim_init(100, 5);
//update();
}
private double distance() {
double dist = 0;
dist = Math.sqrt(Math.abs((xOrigin - x) * (xOrigin - x) + (yOrigin - y) * (yOrigin - y)));
return dist;
}
}
//and here is a snippet from the Player class:
private void updateShooting() {
if (m_input.mouseDown == true) {
//System.out.println("kakakaka");
if (qb_charging == false) {
qb_charging = true;
System.out.println("kakakaka");
shoot_qb(x, y, this, m_input);
//System.out.println("kakakaka");
//charging = true;
}
}
for (int i = 0; i < projectiles.size(); i++) {
//System.out.println("kakakaka");
projectiles.get(i).update();
}
}
//and here from the parent of Player, Mob:
protected synchronized void shoot_qb(int x, int y, Mob mob, Mouse mouse) {
if (qb_charging == false) {
Projectile p = new QiBlast(x, y, mob, mouse);
projectiles.add(p);
}
//System.out.println("kakakaka");
}