I'm very new to this. I followed a tutorial (kilobolt by James Cho) and it seems that it implements doublebuffering which apparently prevents animation flicker. But despite it the animation still flickers. BUT it only flickers for the initial use of the animation. Never happens again after that. How do I fix this?
package kiloboltgame;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import kiloboltgame.framework.Animation;
public class StartingClass extends Applet implements Runnable, KeyListener {
enum GameState {
Running, Dead
}
GameState state = GameState.Running;
private static Robot robot;
public static Heliboy hb, hb2;
public static int score = 0;
private Font font = new Font(null, Font.BOLD, 30);
private Image image, currentSprite, character, character2, character3,
characterDown, characterJumped, background, heliboy, heliboy2,
heliboy3, heliboy4, heliboy5;
//
private Image vayneRun[] = new Image[11];
private Image vayneIdle[] = new Image[12];
private Image vayneTumble[] = new Image[8];
private Animation vi, vr, vt;
// private boolean tumble = false;
//
public static Image tilegrassTop, tilegrassBot, tilegrassLeft,
tilegrassRight, tiledirt;
private Graphics second;
private URL base;
private static Background bg1, bg2;
private Animation anim, hanim;
private ArrayList<Tile> tilearray = new ArrayList<Tile>();
@Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Q-Bot Alpha");
try {
base = getDocumentBase();
} catch (Exception e) {
// TODO: handle exception
}
// Image Setups
character = getImage(base, "data/character.png");
character2 = getImage(base, "data/character2.png");
character3 = getImage(base, "data/character3.png");
characterDown = getImage(base, "data/down.png");
characterJumped = getImage(base, "data/jumped.png");
heliboy = getImage(base, "data/heliboy.png");
heliboy2 = getImage(base, "data/heliboy2.png");
heliboy3 = getImage(base, "data/heliboy3.png");
heliboy4 = getImage(base, "data/heliboy4.png");
heliboy5 = getImage(base, "data/heliboy5.png");
background = getImage(base, "data/background.png");
tiledirt = getImage(base, "data/tiledirt.png");
tilegrassTop = getImage(base, "data/tilegrasstop.png");
tilegrassBot = getImage(base, "data/tilegrassbot.png");
tilegrassLeft = getImage(base, "data/tilegrassleft.png");
tilegrassRight = getImage(base, "data/tilegrassright.png");
vi = new Animation();
vr = new Animation();
vt = new Animation();
for (int i = 0; i < vayneRun.length; i++) {
if (i < 10) {
vayneRun[i] = getImage(base, "data/Vayne Running000" + i
+ ".png");
} else if (i < 100) {
vayneRun[i] = getImage(base, "data/Vayne Running00" + i
+ ".png");
}
vr.addFrame(vayneRun[i], 50);
}
for (int i = 0; i < vayneIdle.length; i++) {
if (i < 10) {
vayneIdle[i] = getImage(base, "data/Vayne Idle000" + i + ".png");
} else if (i < 100) {
vayneIdle[i] = getImage(base, "data/Vayne Idle00" + i + ".png");
}
vi.addFrame(vayneIdle[i], 75);
}
for (int i = 0; i < vayneTumble.length; i++) {
if (i < 10) {
vayneTumble[i] = getImage(base, "data/Vayne Tumble000" + i
+ ".png");
} else if (i < 100) {
vayneTumble[i] = getImage(base, "data/Vayne Tumble00" + i
+ ".png");
}
vt.addFrame(vayneTumble[i], 50);
}
anim = new Animation();
anim.addFrame(character, 1250);
anim.addFrame(character2, 50);
anim.addFrame(character3, 50);
anim.addFrame(character2, 50);
hanim = new Animation();
hanim.addFrame(heliboy, 100);
hanim.addFrame(heliboy2, 100);
hanim.addFrame(heliboy3, 100);
hanim.addFrame(heliboy4, 100);
hanim.addFrame(heliboy5, 100);
hanim.addFrame(heliboy4, 100);
hanim.addFrame(heliboy3, 100);
hanim.addFrame(heliboy2, 100);
// currentSprite = anim.getImage();
}
@Override
public void start() {
bg1 = new Background(0, 0);
bg2 = new Background(2160, 0);
robot = new Robot();
// Initialize Tiles
try {
loadMap("data/map1.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
hb = new Heliboy(340, 360);
hb2 = new Heliboy(700, 360);
Thread thread = new Thread(this);
thread.start();
}
private void loadMap(String filename) throws IOException {
ArrayList lines = new ArrayList();
int width = 0;
int height = 0;
BufferedReader reader = new BufferedReader(new FileReader(filename));
while (true) {
String line = reader.readLine();
// no more lines to read
if (line == null) {
reader.close();
break;
}
if (!line.startsWith("!")) {
lines.add(line);
width = Math.max(width, line.length());
}
}
height = lines.size();
for (int j = 0; j < 12; j++) {
String line = (String) lines.get(j);
for (int i = 0; i < width; i++) {
if (i < line.length()) {
char ch = line.charAt(i);
Tile t = new Tile(i, j, Character.getNumericValue(ch));
tilearray.add(t);
}
}
}
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void run() {
if (state == GameState.Running) {
while (true) {
robot.update();
ArrayList projectiles = robot.getProjectiles();
for (int i = 0; i < projectiles.size(); i++) {
Projectile p = (Projectile) projectiles.get(i);
if (p.isVisible() == true) {
p.update();
} else {
projectiles.remove(i);
}
}
updateTiles();
hb.update();
hb2.update();
bg1.update();
bg2.update();
animate();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (robot.getCenterY() > 500) {
state = GameState.Dead;
}
}
}
}
public void animate() {
// anim.update(10);
hanim.update(50);
if (robot.isJumped()) {
currentSprite = vayneTumble[1];
} else if (robot.isTumble()) {
vt.update(10);
if (vt.getAnimTime() == 10)// if tumble done
{
robot.setReadyToJump(true);
robot.setTumble(false);
} else {
currentSprite = vt.getImage();
}
} else if (robot.getSpeedX() > 0)// if moving right
{
vr.update(10);
currentSprite = vr.getImage();
} else if (robot.isJumped() == false && robot.isDucked() == false) {
// if not moving at all
vi.update(10);
currentSprite = vi.getImage();
// vi.update(10);
}
}
@Override
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
second = image.getGraphics();
}
second.setColor(getBackground());
second.fillRect(0, 0, getWidth(), getHeight());
second.setColor(getForeground());
paint(second);
g.drawImage(image, 0, 0, this);
}
@Override
public void paint(Graphics g) {
if (state == GameState.Running) {
g.drawImage(background, bg1.getBgX(), bg1.getBgY(), this);
g.drawImage(background, bg2.getBgX(), bg2.getBgY(), this);
paintTiles(g);
ArrayList projectiles = robot.getProjectiles();
for (int i = 0; i < projectiles.size(); i++) {
Projectile p = (Projectile) projectiles.get(i);
g.setColor(Color.YELLOW);
g.fillRect(p.getX(), p.getY(), 10, 5);
}
g.drawImage(currentSprite, robot.getCenterX() - 90,
robot.getCenterY() - 50, this);
g.drawImage(hanim.getImage(), hb.getCenterX() - 48,
hb.getCenterY() - 48, this);
g.drawImage(hanim.getImage(), hb2.getCenterX() - 48,
hb2.getCenterY() - 48, this);
g.setFont(font);
g.setColor(Color.WHITE);
g.drawString(Integer.toString(score), 740, 30);
g.drawRect((int) robot.rect.getX(), (int) robot.rect.getY(),
(int) robot.rect.getWidth(), (int) robot.rect.getHeight());
g.drawRect((int) robot.rect2.getX(), (int) robot.rect2.getY(),
(int) robot.rect2.getWidth(), (int) robot.rect2.getHeight());
g.drawRect((int) robot.rect3.getX(), (int) robot.rect3.getY(),
(int) robot.rect3.getWidth(), (int) robot.rect3.getHeight());
g.drawRect((int) robot.rect4.getX(), (int) robot.rect4.getY(),
(int) robot.rect4.getWidth(), (int) robot.rect4.getHeight());
g.drawRect((int) robot.footleft.getX(),
(int) robot.footleft.getY(),
(int) robot.footleft.getWidth(),
(int) robot.footleft.getHeight());
g.drawRect((int) robot.footright.getX(),
(int) robot.footright.getY(),
(int) robot.footright.getWidth(),
(int) robot.footright.getHeight());
} else if (state == GameState.Dead) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, 800, 480);
g.setColor(Color.WHITE);
g.drawString("Dead", 360, 240);
}
}
private void updateTiles() {
for (int i = 0; i < tilearray.size(); i++) {
Tile t = (Tile) tilearray.get(i);
t.update();
}
}
private void paintTiles(Graphics g) {
for (int i = 0; i < tilearray.size(); i++) {
Tile t = (Tile) tilearray.get(i);
g.drawImage(t.getTileImage(), t.getTileX(), t.getTileY(), this);
}
}
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Move up");
break;
case KeyEvent.VK_DOWN:
// currentSprite = characterDown;
if (robot.isJumped() == false) {
robot.setDucked(true);
robot.setSpeedX(0);
}
break;
case KeyEvent.VK_LEFT:
robot.moveLeft();
robot.setMovingLeft(true);
break;
case KeyEvent.VK_RIGHT:
robot.moveRight();
robot.setMovingRight(true);
// if (robot.isDucked()) {
// robot.setTumble(true);
// }
break;
case KeyEvent.VK_SPACE:
if(robot.isReadyToJump())
robot.jump();
break;
case KeyEvent.VK_CONTROL:
if (robot.isDucked() == false && robot.isReadyToFire()// &&
// == false
) {
robot.shoot();
robot.setReadyToFire(false);
}
break;
case KeyEvent.VK_Q:
robot.setReadyToFire(false);
robot.setReadyToJump(false);
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Stop moving up");
break;
case KeyEvent.VK_DOWN:
// currentSprite = anim.getImage();
robot.setDucked(false);
break;
case KeyEvent.VK_LEFT:
robot.stopLeft();
break;
case KeyEvent.VK_RIGHT:
robot.stopRight();
break;
case KeyEvent.VK_SPACE:
break;
case KeyEvent.VK_CONTROL:
robot.setReadyToFire(true);
break;
case KeyEvent.VK_Q:
if (!robot.isTumble()) {
robot.setTumble(true);
robot.setReadyToFire(true);
}
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public static Background getBg1() {
return bg1;
}
public static Background getBg2() {
return bg2;
}
public static Robot getRobot() {
return robot;
}
}