I'm creating a game that implements a finite automaton and I don't know if I'm doing it right. Any advice?
Game class
import java.awt.Canvas;
import java.awt.event.KeyListener;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable, KeyListener
{
public final String TITLE = "Game";
public final int WIDTH = 640;
public final int HEIGHT = 680;
public int LEVEL = 1;
public int FPS = 0;
public int SCORE = 0;
public int LIFE = 5;
private boolean running = false;
private Thread thread;
private BufferedImage textBackground = null;
private BufferedImage spriteSheet = null;
private BufferedImage background = null;
private int enemyCount = 3;
private int enemyKilled = 0;
private int enemyNotKilled = 0;
private boolean target = false;
private String targetText = "";
private Controller c;
private LinkedList<Enemy> e = new LinkedList<Enemy>();
private Enemy enemy;
public void init()
{
requestFocus();
try
{
spriteSheet = ImageIO.read(getClass().getResource("/spritesheet.png"));
background = ImageIO.read(getClass().getResource("/background.png"));
}
catch(IOException e)
{
e.printStackTrace();
}
textBackground = getSprite(1, 1, 96, 32);
c = new Controller(textBackground, this);
addKeyListener(this);
c.createEnemy(enemyCount);
e = c.getEnemy();
}
private void start()
{
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
private void stop()
{
if(!running)
return;
running = false;
try
{
thread.join();
}
catch(Exception e)
{
e.printStackTrace();
}
System.exit(1);
}
public void run()
{
init();
long lastTime = System.nanoTime();
final int framesPerSecond = 30;
double ns = 1000000000 / framesPerSecond;
double delta = 0;
int framesCount = 0;
long timer = System.currentTimeMillis();
int update = 0;
while(running)
{
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
//if(LIFE == 0)
// break; game over
if(delta >= 1)
{
update();
delta--;
update++;
}
render();
framesCount++;
if(System.currentTimeMillis() - timer > 1000)
{
timer += 1000;
System.out.println("Update : " + update + " --- FPS : " + framesCount);
FPS = framesCount;
framesCount = 0;
update = 0;
}
}
stop();
}
private void update()
{
c.update();
if(enemyKilled + enemyNotKilled >= enemyCount)
{
targetText = "";
LEVEL++;
enemyKilled = 0;
enemyNotKilled = 0;
enemyCount += 2;
c.createEnemy(enemyCount);
}
}
private void render()
{
BufferStrategy bs = getBufferStrategy();
if(bs == null)
{
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawImage(background, 0, 0, null);
c.render(g);
g.dispose();
bs.show();
}
public void keyPressed(KeyEvent ek)
{
int key = ek.getKeyCode();
char character = Character.toLowerCase(ek.getKeyChar());
boolean result = isValid(key);
if(result && !target)
{
for(int i = 0; i < e.size(); i++)
if(e.get(i).getFirstLetter() == character && e.get(i).getOnScreen())
{
enemy = e.get(i);
targetText = enemy.getText();
enemy.addIndex(1);
target = true;
break;
}
}
else if(result && targetText.charAt(enemy.getIndex()) == character)
enemy.addIndex(1);
}
public void keyReleased(KeyEvent ek) { }
public void keyTyped(KeyEvent ek) { }
public static void main(String[] args)
{
Game game = new Game();
game.setPreferredSize(new Dimension(game.WIDTH, game.HEIGHT));
game.setMaximumSize(new Dimension(game.WIDTH, game.HEIGHT));
game.setMinimumSize(new Dimension(game.WIDTH, game.HEIGHT));
JFrame frame = new JFrame(game.TITLE);
frame.add(game);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
//frame.setLocationRelativeTo(null);
frame.setVisible(true);
game.start();
}
public boolean isValid(int key)
{
return key >= 65 && key <= 90 ? true : false;
}
public BufferedImage getSprite(int col, int row, int width, int height)
{
return spriteSheet.getSubimage((col * 32) - 32, (row * 32) - 32, width, height);
}
public int getEnemyCount()
{
return enemyCount;
}
public void setEnemyCount(int b)
{
enemyCount = b;
}
public int getEnemyKilled()
{
return enemyKilled;
}
public void setEnemyKilled(int b)
{
enemyKilled = b;
}
public int getEnemyNotkilled()
{
return enemyNotKilled;
}
public void setEnemyNotkilled(int enemyNotKilled)
{
this.enemyNotKilled = enemyNotKilled;
}
public int getScore()
{
return SCORE;
}
public void setScore(int b)
{
SCORE = b;
}
public int getLife()
{
return LIFE;
}
public void setLife(int b)
{
LIFE = b;
}
public boolean getTarget()
{
return target;
}
public void setTarget(boolean b)
{
target = b;
}
public String getTargetText()
{
return targetText;
}
public void setTargetText(String b)
{
targetText = b;
}
}
Enemy Class
import java.awt.Font;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.text.AttributedString;
public class Enemy
{
private double x ,y;
private String text;
private char firstLetter;
private AttributedString as;
private Controller c;
private BufferedImage background;
private Game game;
private int index = 0;
private int textLength = 0;
private double speed = 0.0;
private int stringWidth = 0;
private boolean onScreen = false;
public Enemy(double x, double y, double speed, BufferedImage background, Controller c, Game game, String text, int stringWidth)
{
this.x = x;
this.y = y;
this.background = background;
this.text = text;
this.game = game;
this.c = c;
this.speed = speed;
firstLetter = this.text.charAt(0);
textLength = this.text.length();
this.stringWidth = stringWidth;
}
public void update()
{
y += speed;
if(y >= 0)
onScreen = true;
if(index >= textLength)
{
game.setScore(game.getScore() + 5);
game.setTargetText("");
c.removeEnemy(this);
game.setEnemyKilled(game.getEnemyKilled() + 1);
game.setTarget(false);
}
if(y >= game.HEIGHT - 50)
{
if(game.getLife() != 0)
game.setLife(game.getLife() - 1);
c.removeEnemy(this);
game.setEnemyNotkilled(game.getEnemyNotkilled() + 1);
if(game.getTargetText().equals(text))
{
game.setTarget(false);
game.setTargetText("");
}
}
}
public void render(Graphics g)
{
g.drawImage(background, (int)x, (int)y, null);
as = new AttributedString(text);
if(index >= 1)
as.addAttribute(TextAttribute.FOREGROUND, Color.WHITE, 0, index);
as.addAttribute(TextAttribute.FONT, new Font("Consolas", Font.BOLD, 12), 0, text.length());
g.drawString(as.getIterator(), (int)x + getAdd(stringWidth), (int)y + 13);
}
public double getX()
{
return x;
}
public double getY()
{
return y;
}
public String getText()
{
return text;
}
public char getFirstLetter()
{
return firstLetter;
}
public void addIndex(int b)
{
index += b;
}
public int getIndex()
{
return index;
}
public int getTextLength()
{
return textLength;
}
public int getAdd(int width)
{
return (96 / 2) - (width / 2);
}
public boolean getOnScreen()
{
return onScreen;
}
}