I am creating a top down shooter that has zombies follow you and rotate to aim directly at you. If there are up to 5 zombies following there is no flickering. If there are over 5 zombies there is a flicker on all other images drawn to the screen. It seems to me that as more zombies get added it is causing the game to run slower and for it to draw the other images slightly out of place every now and again.
I am using Graphics2D and rotating the image. The image after being drawn is then rotated back to the original position so it doesn't affect other images being drawn after it.
How can I stop the flickering and slight movement in pixels?
Thanks in advance!
Here is the code for the zombies...
package com.game.stayalive;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;
public class Zombie extends Sprite {
Zombie() {
x = -50;
width = Display.spriteWidth;
height = Display.spriteHeight;
DELAY = rand.nextInt(8)+8;
life = 5;
}
long lastUpdate;
boolean barrierDestroyed = false;
public void drawZombie(Graphics g,int playerX, int playerY) {
if (!visible) {
return;
}
Graphics2D g2d = (Graphics2D) g;
direction = Math.atan2(y - playerY, x - playerX);
g2d.rotate(direction - Math.PI / 2.0, x + width / 2, y + height / 2);
if(DELAY > 10){
g2d.setColor(Color.green.darker());
}else{
g2d.setColor(Color.red.darker());
}
// Main body rectangle
g2d.drawRect(x, y, width, height);
// Left arm
g2d.drawRect(x - width / 2, y, width / 2, height);
g2d.fillRect(x - width / 2, y, width / 2, height);
// Right arm
g2d.drawRect(x + width, y, width / 2, height);
g2d.fillRect(x + width, y, width / 2, height);
// Main body filled
if(DELAY > 10){
g2d.setColor(Color.green);
}else{
g2d.setColor(Color.red);
}
g2d.fillRect(x, y, width, height);
g2d.rotate(-(direction - Math.PI / 2.0), x + width / 2, y + height / 2);
}
long waited = System.currentTimeMillis();
long waitTime;
public void setWaitTime(long waitTime){
this.waitTime = waitTime;
if (System.currentTimeMillis() - waited < waitTime) {
return;
}
}
int moveSpeed = 10;
public void collisionDetection(Zombie zombie1, Zombie zombie2) {
xAcc += gradientX;
yAcc += gradientY;
x = (int) xAcc;
y = (int) yAcc;
if (zombie1.getRect().intersects(zombie2.getRect()) && zombie1.visible && zombie1.life > 0) {
xAcc -= gradientX;
yAcc -= gradientY;
xAcc += (gradientX/10)+rand.nextDouble()-0.5;
yAcc += (gradientY/10) + rand.nextDouble()-0.5;
x = (int) xAcc;
y = (int) yAcc;
}
xAcc -= gradientX;
yAcc -= gradientY;
x = (int) xAcc;
y = (int) yAcc;
}
Random rand = new Random();
long spawnRate = 10000, lastZombieAdded;
public void addZombie() {
if (System.currentTimeMillis() - lastZombieAdded > spawnRate) {
Display.zombie.add(new Zombie());
Display.zombie.get(Display.zombie.size()-1).visible = true;
Display.zombie.get(Display.zombie.size()-1).setWaitTime(500);
Display.zombie.get(Display.zombie.size()-1).xAcc = rand.nextInt(950);
Display.zombie.get(Display.zombie.size()-1).yAcc = rand.nextInt(600);
lastZombieAdded = System.currentTimeMillis();
}
}
public void removeZombie(){
for (int i = 0; i < Display.zombie.size(); i++) {
if(!Display.zombie.get(i).visible ){
Display.zombie.remove(i);
}
}
}
double gradientX, gradientY;
public void move() {
setWaitTime(waitTime);
if (life <= 0) {
visible = false;
}
if (System.currentTimeMillis() - lastUpdate > DELAY) {
xAcc += gradientX;
yAcc += gradientY;
x = (int) xAcc;
y = (int) yAcc;
lastUpdate = System.currentTimeMillis();
}gradientX = -Math.cos(direction);
gradientY = -Math.sin(direction);
}
}
The JPanel Class...
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
player.drawPlayer(g2d);
for (int i = 0; i < zombie.size(); i++) {
if (zombie.get(i).visible) {
zombie.get(i).drawZombie(g2d,playerX,playerY);
}
}
for (int i = 0; i < pistol.size(); i++) {
if (pistol.get(i).visible) {
pistol.get(i).drawPistol(g2d);
}
}
for (int i = 0; i < machineGun.size(); i++) {
if (machineGun.get(i).visible) {
machineGun.get(i).drawMachineGun(g2d);
}
}
for (int i = 0; i < flamethrower.size(); i++) {
if (flamethrower.get(i).visible) {
flamethrower.get(i).draw(g2d);
}
}
reloadBar.drawReloadBar(g2d);
selector.drawSelector(g2d);
money.draw(g2d);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
@Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (true) {
cycle();
repaint();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0) {
sleep = 2;
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("interrupted");
}
beforeTime = System.currentTimeMillis();
}
}
}
"zombie" is an Array List of the class Zombie. "Pistol" and the others are also Array Lists used for bullets etc. The cycle method that gets called is used to move all the images, add images and check for collisions. Apologies for how unorganized the code is. (I will soon put it in separate methods to neaten things up)
See Question&Answers more detail:
os