I made a game that moves players on the keyboard and increases scores by eating random coins.
When you touch TNT, HP is lowered, and when you touch coffee, HP is raised. Prints on screen using Graphics g.
Now I'm going to add a timer. I want to make a game in which players record high scores within the time limit.
There are many things that I don't know yet. Please give me advice
and here's my code. Thank you for reading it.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class CoinEat1 extends JFrame {
private Image bufferImage;
private Graphics screenGraphic;
private Clip clip;
private Image backgroundImage = new ImageIcon("src/images/배경.jpg").getImage();
private Image player = new ImageIcon("src/images/1P.png").getImage();
private Image coin = new ImageIcon("src/images/코인.png").getImage();
private Image TNT = new ImageIcon("src/images/폭탄.png").getImage();
private Image Coffee = new ImageIcon("src/images/커피.png").getImage();
private int playerX,playerY;
private int playerWidth = player.getWidth(null);
private int playerHeight = player.getHeight(null);
private int coinX,coinY;
private int coinWidth = coin.getWidth(null);
private int coinHeight = coin.getHeight(null);
private int TNTX,TNTY;
private int TNTWidth = TNT.getWidth(null);
private int TNTHeight = TNT.getHeight(null);
private int CoffeeX,CoffeeY;
private int CoffeeWidth = Coffee.getWidth(null);
private int CoffeeHeight = Coffee.getHeight(null);
private int score;
private int HP;
private boolean playerup, down, left, right;
public CoinEat1() {
setTitle("동전JAVA");
setVisible(true);
setSize(Main.SCREEN_WIDTH,Main.SCREEN_HEIGHT);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_UP:
playerup=true;
break;
case KeyEvent.VK_DOWN:
down=true;
break;
case KeyEvent.VK_LEFT:
left=true;
break;
case KeyEvent.VK_RIGHT:
right=true;
break;
}
}
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_UP:
playerup=false;
break;
case KeyEvent.VK_DOWN:
down=false;
break;
case KeyEvent.VK_LEFT:
left=false;
break;
case KeyEvent.VK_RIGHT:
right=false;
break;
}
}
});
Init();
while(true){
try {
Thread.sleep(20);
} catch(InterruptedException e) {
e.printStackTrace();
}
keyProcess();
CoinCrashCheck();
TNTCrashCheck();
CoffeeCrashCheck();
}
}
public void Init() {
score = 0;
HP = 100;
playerX = (Main.SCREEN_WIDTH-playerWidth)/2;
playerY = (Main.SCREEN_HEIGHT-playerHeight)/2;
coinX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
coinY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
TNTX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
TNTY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
CoffeeX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
CoffeeY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerWidth))+30;
playsound("src/music/BGM.wav",true);
}
public void keyProcess() {
if (playerup && playerY - 3 > 30) playerY-=3;
if (down && playerY + playerHeight + 3 < Main.SCREEN_HEIGHT) playerY+=3;
if (left && playerX -3 > 0) playerX-=3;
if (right && playerX + playerWidth + 3 < Main.SCREEN_WIDTH) playerX+=3;
}
public void CoinCrashCheck(){
if (playerX+playerWidth > coinX && coinX+coinWidth > playerX && playerY+playerHeight > coinY && coinY+coinHeight > playerY){
score += 100;
playsound("src/music/coin.wav",false);
coinX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
coinY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
}
}
public void TNTCrashCheck() {
if (playerX+playerWidth > TNTX && TNTX+TNTWidth > playerX && playerY+playerHeight > TNTY && TNTY+TNTHeight > playerY){
HP -= 25;
TNTX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
TNTY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
}
}
public void CoffeeCrashCheck() {
if (playerX+playerWidth > CoffeeX && CoffeeX+CoffeeWidth > playerX && playerY+playerHeight > CoffeeY && CoffeeY+CoffeeHeight > playerY){
HP += 25;
CoffeeX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
CoffeeY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
}
}
public void playsound(String pathName, boolean isLoop) {
try {
clip = AudioSystem.getClip();
File audioFile = new File(pathName);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
clip.open(audioStream);
clip.start();
if(isLoop)
clip.loop(Clip.LOOP_CONTINUOUSLY);
}catch (LineUnavailableException e) {
e.printStackTrace();
}
catch (UnsupportedAudioFileException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
public void paint(Graphics g) {
bufferImage = createImage(Main.SCREEN_WIDTH,Main.SCREEN_HEIGHT);
screenGraphic = bufferImage.getGraphics();
screenDraw(screenGraphic);
g.drawImage(bufferImage,0,0,null);
}
public void screenDraw(Graphics g){//이미지를 출력해줄 paint 메소드
g.drawImage(backgroundImage,0,0,null);
g.drawImage(player,playerX,playerY,null);
g.drawImage(coin,coinX,coinY,null);
g.drawImage(TNT,TNTX,TNTY,null);
g.drawImage(Coffee,CoffeeX,CoffeeY,null);
g.setColor(Color.white);
g.setFont(new Font("Arial",Font.BOLD,35));
g.drawString("SCORE : "+score, 30, 80);
g.drawString("HP : " + HP, 30, 120);
this.repaint();
}
public static void main(String[] args) {
new CoinEat1();
}
}
I want to make a game in which players record high scores within the
time limit.
I think you need to make a count down timer.
First, define these variables globally
// Timer Stuff
private Timer mGameTimer;
private int mTimeLeft = 20;
private final int mDelay = 1000; // Start after 1 second
private final int mPeriod = 1000; // Ticks every 1 second
Create a method named SetupTimer()
private void SetupTimer() {
mGameTimer = new Timer();
mGameTimer.scheduleAtFixedRate(new TimerTask() {
public void run() {
if (mTimeLeft == 1) {
mTimeLeft--;
mGameTimer.cancel();
// Handle your game over thing
} else {
mTimeLeft--;
}
}
}, mDelay, mPeriod);
}
Call it in your constructor
public CoinEat1() {
...
SetupTimer();
...
}
Finally change your screenDraw method
public void screenDraw(Graphics g) {
g.drawImage(backgroundImage, 0, 0, null);
g.drawImage(player, playerX, playerY, null);
g.drawImage(coin, coinX, coinY, null);
g.drawImage(TNT, TNTX, TNTY, null);
g.drawImage(Coffee, CoffeeX, CoffeeY, null);
g.setColor(Color.white);
g.setFont(new Font("Arial", Font.BOLD, 35));
g.drawString("SCORE : " + score, 30, 80);
g.drawString("HP : " + HP, 30, 120);
g.drawString("Time Left : " + mTimeLeft, 30, 160); //Redraws your time
this.repaint();
}
Related
I am trying to built psuedo-galaga and I want consistent movement of my JComponents. They are laid out in a null layout, custom JPanel within a custom JFrame container. When I move my character, the speed of the bullets changes - by using the timer I am trying to limit the frame rate so that they move consistently but that has not worked.
Why does my code slow down when the user is moving? I feel like it is a focus subsystem issue or that I should maybe be using multiple threads?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Frame extends JFrame {
private Dimension dimension;
private final int WIDTH, HEIGHT;
private JPanel screen;
public Frame(int width, int height) {
WIDTH = width;
HEIGHT = height;
dimension = new Dimension(WIDTH, HEIGHT);
this.setPreferredSize(dimension);
this.setResizable(false);
this.setMinimumSize(dimension);
this.setMaximumSize(dimension);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
this.setTitle("Galaga");
this.setBackground(Color.black);
this.setForeground(Color.white);
screen = new LevelOneScreen(dimension);
this.getContentPane().add(screen);
screen.requestFocus();
screen.requestFocusInWindow();
}
public void display() {
this.pack();
this.setVisible(true);
this.repaint();
if(screen instanceof LevelOneScreen && ((LevelOneScreen) screen).isDone()) {
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class LevelOneScreen extends JPanel {
public static ArrayList<LevelOneBullet> enemyBullets;
private ArrayList<LevelOneEnemy> enemies;
private boolean direction;
private Dimension dimension;
private User user;
private int score;
private boolean isDone;
public LevelOneScreen(Dimension dimension) {
this.dimension = dimension;
isDone = false;
enemies = new ArrayList<LevelOneEnemy>();
enemyBullets = new ArrayList<LevelOneBullet>();
direction = true;
this.setLayout(null);
setBackground(Color.BLACK);
createEnemies();
createUser();
user.requestFocusInWindow();
user.requestFocus();
score = 0;
this.setSize(dimension);
this.setVisible(true);
}
private void createUser() {
user = new User((int) (dimension.getWidth() / 2), (int) (dimension.getHeight() - 100));
user.setVisible(true);
this.add(user);
}
private void createEnemies() {
BufferedImage img = null;
try {
img = ImageIO.read(new File("Enemy1.png"));
} catch (IOException e) {
System.out.println("Error Reading \"Enemy1.png\"");
}
// dimension.width
for (int i = 0; i < 15; i++) {
enemies.add(new LevelOneEnemy(i * 40 + 5, 30, img));
enemies.get(i).setVisible(true);
}
for (LevelOneEnemy e : enemies) {
this.add(e);
}
}
private void paintEnemies(Graphics g) {
for (LevelOneEnemy e : enemies) {
e.paint(g);
if (!direction)
e.setLocation(e.getX() - 1, e.getY());
else
e.setLocation(e.getX() + 1, e.getY());
}
if (enemies.get(enemies.size() - 1).getX() + 45 > dimension.getWidth() && direction) {
direction = false;
} else if (enemies.get(0).getX() < 5 && !direction) {
direction = true;
}
}
private void paintCollisionObjects(Graphics g) {
if (!enemies.isEmpty()) {
paintEnemies(g);
// check for bullet collision
if (!user.getBullets().isEmpty()) {
for (int i = enemies.size() - 1; i >= 0; i--) {
for (int j = user.getBullets().size() - 1; j >= 0; j--) {
if (enemies.get(i).getBounds().intersects(user.getBullets().get(j).getBounds())) {
this.remove(enemies.get(i));
enemies.remove(i);
user.getBullets().remove(j);
score += 100;
// To prevent ArrayOutOfBoundsException when
// Enemies are destroyed faster than they're removed
if (enemies.size() == 0)
break;
}
}
}
}
// check for user collision
if (!enemies.isEmpty()) {
for (int i = enemies.size() - 1; i >= 0; i--) {
if (enemies.get(i).getBounds().intersects(user.getBounds())) {
enemies.get(i).setLocation(0, getParent().getHeight() + 100);
this.remove(enemies.get(i));
enemies.remove(i);
user.decrementHealth();
score += 100;
}
}
}
if (!enemyBullets.isEmpty()) {
for (int i = enemyBullets.size() - 1; i >= 0; i--) {
enemyBullets.get(i).paint(g);
if (enemyBullets.get(i).getY() > getParent().getHeight() + 50) {
enemyBullets.remove(i);
} else if (enemyBullets.get(i).getBounds().intersects(user.getBounds())) {
enemyBullets.remove(i);
user.decrementHealth();
}
}
}
}
}
public void paintComponent(Graphics g) {
this.requestFocusInWindow();
super.paintComponent(g);
user.paintComponent(g);
paintCollisionObjects(g);
if(!isDone && enemies.isEmpty())
isDone = true;
}
public boolean isDone() {
return isDone;
}
public boolean isDead() {
return user.healthPercent() < .1;
}
public int getScore() {
return score;
}
public double getHealth() {
return user.healthPercent();
}
public String toString() {
String s = "Level One Screen\n";
for (int i = 0; i < this.getComponentCount(); i++) {
s = s + this.getComponent(i) + "\n";
}
return s;
}
}
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
#SuppressWarnings("serial")
public class LevelOneBullet extends JComponent {
private Image img;
private int dy;
public LevelOneBullet(int x, int y, boolean isEnemy) {
BufferedImage img = null;
try {
if(isEnemy)
img = ImageIO.read(new File("EnemyLaserShot.png"));
else
img = ImageIO.read(new File("UserLaserShot.png"));
} catch (IOException e) {
if(isEnemy)
System.out.println("Error Reading \"EnemyLaserShot.png\"");
else
System.out.println("Error Reading \"UserLaserShot.png\"");
}
this.img = img;
super.setLocation(x, y);
this.setVisible(true);
this.setBounds(x, y, 16, 30);
dy = isEnemy ? 3 : -3;
}
public void paint(Graphics g) {
g.drawImage(img, super.getX(), super.getY(), 16, 30, null);
//super.setLocation(super.getX(), super.getY() + dy);
this.setBounds(super.getX(), super.getY()+dy, 16, 30);
}
public String toString() {
return "LevelOneBullet: #" + super.getX() + ", " +super.getY();
}
}
import java.awt.Graphics;
import java.awt.Image;
import java.util.Random;
import javax.swing.JComponent;
#SuppressWarnings("serial")
public class LevelOneEnemy extends JComponent {
private Image im;
private int health;
private int shootSeed;
private long time;
private long lastTimeFired;
public LevelOneEnemy(int x, int y, Image im, int health) {
Random rand = new Random();
super.setBounds(x, y, 30, 30);
super.setLocation(x, y);
this.im = im;
this.health = health;
shootSeed = rand.nextInt(1000)+5000;
time = System.currentTimeMillis();
lastTimeFired = 0;
}
public LevelOneEnemy(int x, int y, Image im) {
Random rand = new Random();
super.setBounds(x, y, 30, 30);
super.setLocation(x, y);
this.im = im;
this.health = 100;
shootSeed = rand.nextInt(1000)+6000;
time = System.currentTimeMillis();
lastTimeFired = 0;
}
public LevelOneEnemy(int x, int y, Image im, boolean isLevelOne) {
Random rand = new Random();
super.setBounds(x, y, 30, 30);
super.setLocation(x, y);
this.im = im;
this.health = 100;
shootSeed = rand.nextInt(1000)+6000;
time = System.currentTimeMillis();
lastTimeFired = 0;
}
public void paint(Graphics g) {
if((System.currentTimeMillis()-time) % shootSeed < (shootSeed/30) &&
System.currentTimeMillis() - lastTimeFired > 5000) {
LevelOneScreen.enemyBullets.add(new LevelOneBullet(this.getX()+15, this.getY()+10, true));
lastTimeFired = System.currentTimeMillis();
}
g.drawImage(im, super.getX(), super.getY(), 30, 30, null);
}
public int getHealth() {
return health;
}
public String toString() {
return "LevelOneEnemy #(" + this.getX() + ", " + this.getY() + ")";
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class Runner {
public final static int SCREENHEIGHT = 1000;
public final static int SCREENWIDTH = 800;
private static Frame frame;
public static void main(String[] args) {
frame = new Frame(SCREENWIDTH, SCREENHEIGHT);
FrameRateListener listen = new FrameRateListener();
Timer timer = new Timer(34, listen);
timer.start();
}
private static class FrameRateListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
frame.display();
}
}
}
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
public class UserKeyboardListener implements KeyListener {
private int dx, dy;
private int shoot;
private int speed;
private ArrayList<Integer> keysPressed;
public UserKeyboardListener() {
keysPressed = new ArrayList<Integer>();
shoot = 0;
speed = 1;
}
#Override
public void keyTyped(KeyEvent e) {
}
public int getdx() {
return dx;
}
public int getdy() {
return dy;
}
public int getShoot() {
return shoot;
}
public boolean decrementShoot() {
if (shoot - 1 < 0) {
return false;
} else {
shoot = shoot - 1;
return true;
}
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
} else {
if (!keysPressed.contains(key))
keysPressed.add(key);
if(keysPressed.contains(KeyEvent.VK_C))
speed = 2;
else
speed = 1;
if (keysPressed.contains(KeyEvent.VK_RIGHT) && keysPressed.contains(KeyEvent.VK_LEFT)) {
dx = 0;
} else if (keysPressed.contains(KeyEvent.VK_RIGHT)) {
dx = 1*speed;
} else if (keysPressed.contains(KeyEvent.VK_LEFT)) {
dx = -1*speed;
} else {
dx = 0;
}
if (keysPressed.contains(KeyEvent.VK_UP) && keysPressed.contains(KeyEvent.VK_DOWN)) {
dy = 0;
} else if (keysPressed.contains(KeyEvent.VK_UP)) {
dy = -1*speed;
} else if (keysPressed.contains(KeyEvent.VK_DOWN)) {
dy = 1*speed;
} else {
dy = 0;
}
}
}
#Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
shoot++;
} else {
if (keysPressed.contains(key))
keysPressed.remove(keysPressed.indexOf(key));
if(keysPressed.contains(KeyEvent.VK_C))
speed = 2;
else
speed = 1;
if (keysPressed.contains(KeyEvent.VK_RIGHT) && keysPressed.contains(KeyEvent.VK_LEFT)) {
dx = 0;
} else if (keysPressed.contains(KeyEvent.VK_RIGHT)) {
dx = 1*speed;
} else if (keysPressed.contains(KeyEvent.VK_LEFT)) {
dx = -1*speed;
} else {
dx = 0;
}
if (keysPressed.contains(KeyEvent.VK_UP) && keysPressed.contains(KeyEvent.VK_DOWN)) {
dy = 0;
} else if (keysPressed.contains(KeyEvent.VK_UP)) {
dy = -1*speed;
} else if (keysPressed.contains(KeyEvent.VK_DOWN)) {
dy = 1*speed;
} else {
dy = 0;
}
}
}
public String toString() {
return "UserKeyListener: (" + dx + ", " + dy + ")";
}
}
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
#SuppressWarnings("serial")
public class User extends JComponent {
private Image im;
private double health;
private double initialHealth;
private double healthDecrement;
private double stamina;
private int staminaDecrement;
private long lastBulletFired;
private ArrayList<LevelOneBullet> bullets;
public User(int x, int y, double health) {
BufferedImage img = null;
try {
img = ImageIO.read(new File("UserShip.png"));
} catch (IOException e) {
System.out.println("Error Reading \"UserShip.png\"");
}
bullets = new ArrayList<LevelOneBullet>();
super.setLocation(x, y);
super.setBounds(x, y, 50, 50);
this.addKeyListener(new UserKeyboardListener());
this.im = img;
this.health = 100 * health;
this.initialHealth = 100;
this.healthDecrement = 100/5.0;
this.stamina = 100;
this.staminaDecrement = 10;
this.setFocusable(true);
}
public User(int x, int y) {
BufferedImage img = null;
try {
img = ImageIO.read(new File("UserShip.png"));
} catch (IOException e) {
System.out.println("Error Reading \"UserShip.png\"");
}
bullets = new ArrayList<LevelOneBullet>();
super.setLocation(x, y);
super.setBounds(x, y, 50, 50);
this.addKeyListener(new UserKeyboardListener());
this.im = img;
this.health = 100;
this.initialHealth = 100;
this.healthDecrement = health/5.0;
this.stamina = 100;
this.staminaDecrement = 10;
this.setFocusable(true);
}
public void paintComponent(Graphics g) {
this.requestFocus();
this.requestFocusInWindow();
if (this.getKeyListeners().length > 0 &&
this.getKeyListeners()[0] instanceof UserKeyboardListener) {
UserKeyboardListener listen = (UserKeyboardListener) this.getKeyListeners()[0];
if(listen.getdx() != 0) {
if(this.getX()+listen.getdx() + this.getWidth() < this.getParent().getWidth() &&
this.getX()+listen.getdx() > 5)
this.setLocation(this.getX() + listen.getdx(), this.getY());
if(this.getX() < 10) {
this.setLocation(10, this.getY());
}
else if(this.getX()+this.getWidth() > this.getParent().getWidth() - 10)
this.setLocation(this.getParent().getWidth()-10-this.getWidth(), this.getY());
}
if(listen.getdy() != 0) {
if(this.getY() + listen.getdy() > 30 &&
this.getY()+this.getHeight()+listen.getdy() < this.getParent().getHeight()-10)
this.setLocation(this.getX(), this.getY()+listen.getdy());
if(this.getY() < 30) {
this.setLocation(30, this.getY());
}
else if(this.getY()+this.getHeight() > this.getParent().getHeight()-10)
this.setLocation(this.getX(), this.getParent().getHeight()-10-this.getHeight());
}
if (listen.getShoot() > 0 && stamina > 10) {
bullets.add(new LevelOneBullet(super.getX() + 17, super.getY() - 5, false));
decrementStamina();
listen.decrementShoot();
lastBulletFired = System.currentTimeMillis();
}
}
for (int i = bullets.size() - 1; i >= 0; i--) {
bullets.get(i).paint(g);
if (bullets.get(i).getY() < -50)
bullets.remove(i);
}
if(System.currentTimeMillis() - lastBulletFired > 1000 && stamina < 100) {
stamina += .5;
}
g.drawImage(im, super.getX(), super.getY(), this.getWidth(), this.getHeight(), null);
}
public double healthPercent() {
return health/initialHealth;
}
public void decrementHealth() {
health -= healthDecrement;
}
public double staminaPercent() {
return stamina / 100.0;
}
public void decrementStamina() {
stamina -= staminaDecrement;
}
public String toString() {
return "User: " + "(" + super.getX() + ", " + super.getY() + ")";
}
public ArrayList<LevelOneBullet> getBullets() {
return bullets;
}
}
The issue came from what #VGR said, updating components position in the paintComponents(..) method. This should be done from another method that is called when the timer's action occurs. This then updates the positions of the JComponents based off of when they should be refreshed from the timer rather than when paintComponents(..) is called - which we do not have control over.
I made a game that moves players on the keyboard and increases scores by eating random coins.
When you touch TNT, HP is lowered, and when you touch coffee, HP is raised. Prints on screen using Graphics g.
Now I'm going to make the game start screen. I have already created a start button for another class, and when you press the button, a new game window appears. But I can't see the game screen and it's lagging. Even the close button doesn't press well, so we're forcing it through the To Do Manager. Can I know what the problem is? It's okay if the game doesn't run as a new window and comes out of the same window. Please help me.
I'll show you the Start button class and the Game class in turn. My English is not good, so thank you for reading the long question.
★★★ StartButtonClass ★★★
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class gamestart {
public static void main(String[] args) {
JFrame frame = new JFrame("Start up frame");
JButton newGameButton = new JButton("New Game");
frame.setLayout(new FlowLayout());
frame.add(newGameButton);
frame.setVisible(true);
newGameButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JFrame newGameWindow = new JFrame("A new game!");
newGameWindow.setVisible(true);
newGameWindow.add(new CoinEat1());
newGameWindow.pack();
}
});
frame.pack();
}
}
★★★ GameClass ★★★
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class CoinEat1 extends JFrame {
private Image bufferImage;
private Graphics screenGraphic;
private Clip clip;
private Image backgroundImage = new ImageIcon("src/images/배경.jpg").getImage();
private Image player = new ImageIcon("src/images/1P.png").getImage();
private Image coin = new ImageIcon("src/images/코인.png").getImage();
private Image TNT = new ImageIcon("src/images/폭탄.png").getImage();
private Image Coffee = new ImageIcon("src/images/커피.png").getImage();
private int playerX,playerY;
private int playerWidth = player.getWidth(null);
private int playerHeight = player.getHeight(null);
private int coinX,coinY;
private int coinWidth = coin.getWidth(null);
private int coinHeight = coin.getHeight(null);
private int TNTX,TNTY;
private int TNTWidth = TNT.getWidth(null);
private int TNTHeight = TNT.getHeight(null);
private int CoffeeX,CoffeeY;
private int CoffeeWidth = Coffee.getWidth(null);
private int CoffeeHeight = Coffee.getHeight(null);
private int score;
private int HP;
private boolean playerup, down, left, right;
public CoinEat1() {
setTitle("동전JAVA");
setVisible(true);
setSize(Main.SCREEN_WIDTH,Main.SCREEN_HEIGHT);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_UP:
playerup=true;
break;
case KeyEvent.VK_DOWN:
down=true;
break;
case KeyEvent.VK_LEFT:
left=true;
break;
case KeyEvent.VK_RIGHT:
right=true;
break;
}
}
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_UP:
playerup=false;
break;
case KeyEvent.VK_DOWN:
down=false;
break;
case KeyEvent.VK_LEFT:
left=false;
break;
case KeyEvent.VK_RIGHT:
right=false;
break;
}
}
});
Init();
while(true){
try {
Thread.sleep(20);
} catch(InterruptedException e) {
e.printStackTrace();
}
keyProcess();
CoinCrashCheck();
TNTCrashCheck();
CoffeeCrashCheck();
}
}
public void Init() {
score = 0;
HP = 100;
playerX = (Main.SCREEN_WIDTH-playerWidth)/2;
playerY = (Main.SCREEN_HEIGHT-playerHeight)/2;
coinX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
coinY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
TNTX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
TNTY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
CoffeeX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
CoffeeY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerWidth))+30;
playsound("src/music/BGM.wav",true);
}
public void keyProcess() {
if (playerup && playerY - 3 > 30) playerY-=3;
if (down && playerY + playerHeight + 3 < Main.SCREEN_HEIGHT) playerY+=3;
if (left && playerX -3 > 0) playerX-=3;
if (right && playerX + playerWidth + 3 < Main.SCREEN_WIDTH) playerX+=3;
}
public void CoinCrashCheck(){
if (playerX+playerWidth > coinX && coinX+coinWidth > playerX && playerY+playerHeight > coinY && coinY+coinHeight > playerY){
score += 100;
playsound("src/music/coin.wav",false);
coinX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
coinY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
}
}
public void TNTCrashCheck() {
if (playerX+playerWidth > TNTX && TNTX+TNTWidth > playerX && playerY+playerHeight > TNTY && TNTY+TNTHeight > playerY){
HP -= 25;
TNTX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
TNTY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
}
}
public void CoffeeCrashCheck() {
if (playerX+playerWidth > CoffeeX && CoffeeX+CoffeeWidth > playerX && playerY+playerHeight > CoffeeY && CoffeeY+CoffeeHeight > playerY){
HP += 25;
CoffeeX = (int)(Math.random()*(Main.SCREEN_WIDTH+1-playerWidth));
CoffeeY = (int)(Math.random()*(Main.SCREEN_HEIGHT+1-playerHeight-30))+30;
}
}
public void playsound(String pathName, boolean isLoop) {
try {
clip = AudioSystem.getClip();
File audioFile = new File(pathName);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
clip.open(audioStream);
clip.start();
if(isLoop)
clip.loop(Clip.LOOP_CONTINUOUSLY);
}catch (LineUnavailableException e) {
e.printStackTrace();
}
catch (UnsupportedAudioFileException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
public void paint(Graphics g) {
bufferImage = createImage(Main.SCREEN_WIDTH,Main.SCREEN_HEIGHT);
screenGraphic = bufferImage.getGraphics();
screenDraw(screenGraphic);
g.drawImage(bufferImage,0,0,null);
}
public void screenDraw(Graphics g){//이미지를 출력해줄 paint 메소드
g.drawImage(backgroundImage,0,0,null);
g.drawImage(player,playerX,playerY,null);
g.drawImage(coin,coinX,coinY,null);
g.drawImage(TNT,TNTX,TNTY,null);
g.drawImage(Coffee,CoffeeX,CoffeeY,null);
g.setColor(Color.white);
g.setFont(new Font("Arial",Font.BOLD,35));
g.drawString("SCORE : "+score, 30, 80);
g.drawString("HP : " + HP, 30, 120);
this.repaint();
}
public static void main(String[] args) {
new CoinEat1();
}
}
So I've pretty much thrown together a basic game in java by following a bunch of different tutorials - the problem is i cant manage to figure out how to get my sprite to move in different directions. Here is the code for my main
package com.game.src.main;
import java.awt.Canvas;
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.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 850;
public static final int HEIGHT = 650;
public static final int SCALE = 1;
public final String TITLE = "Racing Game!";
static ServerSocket serverSocket;
static Socket socket;
static DataOutputStream out;
private boolean running = false;
private Thread thread;
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
private BufferedImage spriteSheet = null;
private BufferedImage spriteSheet2 = null;
private BufferedImage background = null;
private BufferedImage MenuBackground = null;
private Player p;
private Player2 p2;
private Menu menu;
public static enum STATE {
MENU,
GAME
};
public static STATE State = STATE.MENU;
public void init() {
BufferedImageLoader loader = new BufferedImageLoader();
try {
spriteSheet = loader.loadImage("/Sprite_Sheet.png");
background = loader.loadImage("/Track.png");
MenuBackground = loader.loadImage("/MenuBG.fw.png");
}
catch (IOException e) {
e.printStackTrace();
}
menu = new Menu();
addKeyListener(new KeyInput(this));
this.addMouseListener(new MouseInput());
p = new Player(365, 500, this);
p2 = new Player2(365, 550, this);
}
private synchronized void start() {
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
private synchronized void stop() {
if(!running)
return;
running = false;
try {
thread.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(1);
}
public void run() {
init();
long lastTime = System.nanoTime();
final double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
int updates = 0;
int frames = 0;
long timer = System.currentTimeMillis();
while(running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
if(delta >= 1) {
tick();
updates++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println(updates + " FPS, TICKS " + frames);
updates = 0;
frames = 0;
}
}
stop();
}
private void tick() {
if(State == STATE.GAME){
p.tick();
p2.tick();
}
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
g.drawImage(MenuBackground, 0, 0, null);
if(State == STATE.GAME){
//Drawing the main games background
g.drawImage(background, 0, 0, null);
p.render(g);
p2.render(g);
}
else if(State == STATE.MENU){
menu.render(g);
}
g.dispose();
bs.show();
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(State == STATE.GAME){
if(key == KeyEvent.VK_RIGHT){
p.setVelX(5);
}
if(key == KeyEvent.VK_D){
p2.setVelX2(5);
}
else if(key == KeyEvent.VK_LEFT) {
p.setVelX(-5);
}
else if(key == KeyEvent.VK_A) {
p2.setVelX2(-5);
}
else if(key == KeyEvent.VK_DOWN) {
p.setVelY(5);
}
else if(key == KeyEvent.VK_S) {
p2.setVelY2(5);
}
else if(key == KeyEvent.VK_UP) {
p.setVelY(-5);
}
else if(key == KeyEvent.VK_W) {
p2.setVelY2(-5);
}
}
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT){
p.setVelX(0);
}
if(key == KeyEvent.VK_D){
p2.setVelX2(0);
}
else if(key == KeyEvent.VK_LEFT) {
p.setVelX(0);
}
else if(key == KeyEvent.VK_A) {
p2.setVelX2(0);
}
else if(key == KeyEvent.VK_DOWN) {
p.setVelY(0);
}
else if(key == KeyEvent.VK_S) {
p2.setVelY2(0);
}
else if(key == KeyEvent.VK_UP) {
p.setVelY(0);
}
else if(key == KeyEvent.VK_W) {
p2.setVelY2(0);
}
}
public static void main(String args[]) throws Exception {
Game game = new Game();
game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
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();
System.out.println("Starting server....");
serverSocket = new ServerSocket(7777);
System.out.println("Server started");
socket = serverSocket.accept();
System.out.println("Connecting from: " + socket.getInetAddress());
out = new DataOutputStream(socket.getOutputStream());
out.writeUTF("This is a test of Java Sockets");
System.out.println("Data has been sent");
}
public BufferedImage getSpriteSheet() {
return spriteSheet;
}
public BufferedImage getSpriteSheet2() {
return spriteSheet2;
}
}
This is my player class
package com.game.src.main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class Player {
private double x;
private double y;
private double velX = 0;
private double velY = 0;
private BufferedImage player;
BufferedImageLoader loader = new BufferedImageLoader();
BufferedImage SpriteSheet = null;
public Player(double x, double y, Game game) {
this.x = x;
this.y = y;
//New instance of Sprite sheet - reading from buffered image loader
SpriteSheet ss = new SpriteSheet(game.getSpriteSheet());
player = ss.grabImage(1, 1, 50, 50);
try {
SpriteSheet = loader.loadImage("/Sprite_Sheet.png");
}
catch(Exception e) {
e.printStackTrace();
}
}
public void tick() {
x+=velX;
y+=velY;
//Adding basic collision
if(x < 0 + 50) {
x = 0 + 50;
}
if(x >= 850 - 100) {
x = 850 - 100;
}
if(y < 0 + 100) {
y = 0 + 100;
}
if(y >= 650 - 100){
y = 650 - 100;
}
}
public void render(Graphics g){
//Draw Track
Color c1 = Color.green;
g.setColor( c1 );
g.fillRect( 150, 200, 550, 300 ); //grass
Color c2 = Color.black;
g.setColor( c2 );
g.drawRect(50, 100, 750, 500); // outer edge
g.drawRect(150, 200, 550, 300); // inner edge
Color c3 = Color.yellow;
g.setColor( c3 );
g.drawRect( 100, 150, 650, 400 ); // mid-lane marker
Color c4 = Color.white;
g.setColor( c4 );
g.drawLine( 425, 500, 425, 600 ); // start line
g.drawImage(player, (int)x, (int)y, null);
}
public double getX(Graphics g){
return x;
}
public double getY(){
return y;
}
public void setX(double x){
this.x = x;
}
public void setY(double y){
this.y = y;
}
public void setVelX(double velX){
this.velX = velX;
}
public void setVelY(double velY){
this.velY = velY;
}
}
I have two players in this game but i'm really stuck on how i can change the sprites direction by 22.5% in a desired direction so if i pressed the up key for player 1 it would rotate my car 22.5% north etc. I have a sprite sheet with 16 sprites for each player for every change in angle by 22.5% This is really confusing me and i'm not sure how i can implement this,
Thanks for taking the time to look
This is a basic example of spinning a sprite
What this is maintain's a virtual state which the Player object inspects in order to determine how it should be changed accordingly. This separates the action from the result, meaning that it would be possible to substitute the action (arrow up key) with some other action, but still obtain the same result.
This example also uses the key bindings API, which doesn't suffer from the same focus related issues that KeyListener does, but this is a pure Swing API and won't be compatiable with Canvas, but is a nice demonstration ;)
The real magic occurs in the characters paint method...
public void paint(Graphics2D g2d) {
Graphics2D g = (Graphics2D) g2d.create();
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.rotate(Math.toRadians(angle), character.getWidth() / 2, character.getHeight() / 2);
g.transform(at);
g.drawImage(character, 0, 0, null);
}
Basically, this creates a AffineTransformation which is then compounded to produce the result we need. That is, first it's anchor position is translated to the characters x/y position and then rotated about the characters center point. Because it's been translated, we can simply paint the character at 0x0. This much easier then try to calculate the characters rotation anchor somewhere else in virtual space - IMHO
The character is rotated by pressing either the Up or Down arrow keys. While pressed, the character will continue to rotate, this is a feature of the example for demonstration purpose.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RotateCharater {
public static void main(String[] args) {
new RotateCharater();
}
public RotateCharater() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private DefaultState state;
private Player player;
public TestPane() {
player = new Player();
state = new DefaultState();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "upKeyPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "upKeyReleased");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "downKeyPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "downKeyReleased");
ActionMap am = getActionMap();
am.put("upKeyPressed", new UpKeyAction(state, true));
am.put("upKeyReleased", new UpKeyAction(state, false));
am.put("downKeyPressed", new DownKeyAction(state, true));
am.put("downKeyReleased", new DownKeyAction(state, false));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
player.update(state);
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
player.paint(g2d);
g2d.dispose();
}
public class UpKeyAction extends AbstractAction {
private DefaultState state;
private boolean pressed;
public UpKeyAction(DefaultState state, boolean pressed) {
this.state = state;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
state.setUpKeyPressed(pressed);
}
}
public class DownKeyAction extends AbstractAction {
private DefaultState state;
private boolean pressed;
public DownKeyAction(DefaultState state, boolean pressed) {
this.state = state;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
state.setDownKeyPressed(pressed);
}
}
}
public interface State {
public boolean isUpKeyPressed();
public boolean isDownKeyPressed();
}
public class DefaultState implements State {
private boolean upKeyPressed;
private boolean downKeyPressed;
public boolean isDownKeyPressed() {
return downKeyPressed;
}
public boolean isUpKeyPressed() {
return upKeyPressed;
}
public void setDownKeyPressed(boolean downKeyPressed) {
this.downKeyPressed = downKeyPressed;
upKeyPressed = false;
}
public void setUpKeyPressed(boolean upKeyPressed) {
this.upKeyPressed = upKeyPressed;
downKeyPressed = false;
}
}
public class Player {
private BufferedImage character;
private int x = 100 - 32, y = 100 - 32;
private double angle;
public Player() {
try {
character = ImageIO.read(getClass().getResource("/Character.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void paint(Graphics2D g2d) {
Graphics2D g = (Graphics2D) g2d.create();
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.rotate(Math.toRadians(angle), character.getWidth() / 2, character.getHeight() / 2);
g.transform(at);
g.drawImage(character, 0, 0, null);
}
public void update(State state) {
if (state.isUpKeyPressed()) {
angle -= 22.5;
} else if (state.isDownKeyPressed()) {
angle += 22.5;
}
}
}
}
Remember, this is just an example used to present the concept ;)
i'm trying to create a game. And almost everytime I move, it's leaving a trail
Code:
package lt.mchackers.gametest.main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import lt.mchackers.gametest.handlers.InputHandler;
/**
* Main class for the game
*/
public class Main extends JFrame
{
private static final long serialVersionUID = -828018325337767157L;
boolean isRunning = true;
int fps = 30;
int windowWidth = 320;
int windowHeight = 320;
int speed;
BufferedImage backBuffer;
Insets insets;
InputHandler input;
int x = 0;
int y = 0;
int xa = 0;
int ya = 0;
Coordinates coords = new Coordinates(0, 0);
public static void main(String[] args)
{ Main game = new Main();
game.run();
System.exit(0);
}
/**
* This method starts the game and runs it in a loop
*/
public void run()
{
initialize();
while(isRunning)
{
long time = System.currentTimeMillis();
update();
draw();
// delay for each frame - time it took for one frame
time = (1000 / fps) - (System.currentTimeMillis() - time);
if (time > 0)
{
try
{
Thread.sleep(time);
}
catch(Exception e){}
}
}
setVisible(false);
}
/**
* This method will set up everything need for the game to run
*/
void initialize()
{
setTitle("Game Tutorial");
setSize(windowWidth, windowHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
insets = getInsets();
setSize(insets.left + windowWidth + insets.right,
insets.top + windowHeight + insets.bottom);
backBuffer = new BufferedImage(windowWidth, windowHeight, BufferedImage.TYPE_INT_RGB);
input = new InputHandler(this);
Graphics bbg = backBuffer.getGraphics();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("map"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
String line = null;
try {
BufferedImage gray = ImageIO.read(new File("gray.png"));
BufferedImage black = ImageIO.read(new File("black.png"));
while ((line = reader.readLine()) != null) {
for(String s : line.split(""))
{
if (s.contains("*"))
{
bbg.drawImage(gray, xa-32, ya, null);
}
else if (s.contains("#"))
{
bbg.drawImage(black, xa-32, ya, null);
}
if (xa < 320)
{
xa += 32;
}
else
{
ya += 32;
xa = 0;
}
System.out.println(xa);
System.out.println(ya);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* This method will check for input, move things
* around and check for win conditions, etc
*/
void update()
{
if (input.isKeyDown(KeyEvent.VK_NUMPAD0))
{
speed -= 1;
}
if (input.isKeyDown(KeyEvent.VK_NUMPAD1))
{
speed += 1;
}
if (input.isKeyDown(KeyEvent.VK_RIGHT))
{
coords.setCoords(coords.getX() + 32, coords.getY());
}
if (input.isKeyDown(KeyEvent.VK_LEFT))
{
coords.setCoords(coords.getX() - 32, coords.getY());
}
if (input.isKeyDown(KeyEvent.VK_UP))
{
coords.setCoords(coords.getX(), coords.getY() - 32);
}
if (input.isKeyDown(KeyEvent.VK_DOWN))
{
coords.setCoords(coords.getX(), coords.getY() + 32);
}
//System.out.println(x);
//System.out.println(y);
//System.out.println(speed);
if (coords.getY() < 0)
{
coords.setCoords(coords.getX(), 0);
}
if (coords.getX() < 0)
{
coords.setCoords(0, coords.getY());
}
if (coords.getX() > windowWidth - 32)
{
coords.setCoords(windowWidth - 32, coords.getY());
}
if (coords.getY() > windowHeight - 32)
{
coords.setCoords(coords.getX(), windowHeight - 32);
// y = windowHeight - 32;
}
}
/**
* This method will draw everything
*/
void draw()
{
Graphics g = getGraphics();
//this.setBackground(Color.BLACK);
//super.paintComponents(g);
backBuffer.setRGB(x, y, Color.BLACK.getRGB());
Graphics bbg = backBuffer.getGraphics();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("map"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
String line = null;
try {
BufferedImage gray = ImageIO.read(new File("gray.png"));
BufferedImage black = ImageIO.read(new File("black.png"));
while ((line = reader.readLine()) != null) {
for(String s : line.split(""))
{
if (s.contains("*") && xa + 32!= coords.getX() && ya - 32 != coords.getY())
{
bbg.drawImage(gray, xa-32, ya, null);
}
else if (s.contains("#") && xa + 32 != coords.getX() && ya - 32 != coords.getY())
{
bbg.drawImage(black, xa-32, ya, null);
}
if (xa < 320)
{
xa += 32;
}
else
{
ya += 32;
xa = 0;
}
//System.out.println(xa);
//System.out.println(ya);
}
}
} catch (IOException e) {
e.printStackTrace();
}
bbg.setColor(Color.WHITE);
xa = 0;
ya = 0;
System.out.println(coords.getX());
bbg.setColor(Color.WHITE);
bbg.fillRect(coords.getX(),coords.getY(), 32,32);
System.out.println(coords.getY());
//bbg.setColor(Color.BLACK);
//bbg.drawOval(x, y, 20, 20);
g.drawImage(backBuffer, insets.left, insets.top, this);
}
}
Thanks for help.
Check out my code from here, to get a hint as to how to paint stuff in a game loop properly.
Basically what you need to take care of is double buffering to prevent any flickering and also repainting the background so that you don't leave out any trail of rectangles.
You can also check out the Killer Game Programming in Java online book, which can help you learn the game programming concepts and their implementation.
The concept of double buffering is simple. Since painting on the screen takes more time than updating the states of the objects in the gameplay, we use two canvas to prevent any flickering issues which arise when objects are painted directly on the screen.
When the object states are updated in the game loop, it is rendered in a background canvas. The background canvas is then copied to the screen which takes less time compared to painting directly on the screen. And while this copying is happening, the object states are updated again and they are rendered on the background canvas again, which is then copied to the screen. Repeat this over and over, and you get the double buffering.
Basically you keep a buffer of screen which is to be painted and your game renders objects in the buffer which is then copied to the screen.
Here's a code which I think might help you understand the concept:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class GamePanel extends JPanel implements Runnable
{
private static final long serialVersionUID = 6892533030374996243L;
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
private Thread animator;
private volatile boolean running = false;
private volatile boolean isGameOver = false;
private volatile boolean isUserPaused = false;
private volatile boolean isWindowPaused = false;
private Graphics dbg;
private Image dbImage = null;
private static final int NO_DELAYS_PER_YIELD = 16;
private static final int MAX_FRAME_SKIPS = 5;
private static final Color backgroundColor = new Color(245, 245, 245);
private static long fps = 30;
private static long period = 1000000L * (long) 1000.0 / fps;
private static volatile boolean isPainted = false;
public GamePanel()
{
setBackground(backgroundColor);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
requestFocus();
readyForPause();
// Add key listeners here...
}
public void addNotify()
{
super.addNotify();
startGame();
}
void startGame()
{
if (animator == null || !running)
{
animator = new Thread(this);
animator.start();
}
}
void stopGame()
{
running = false;
}
private void readyForPause()
{
addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
if ((keyCode == KeyEvent.VK_ESCAPE) || (keyCode == KeyEvent.VK_Q)
|| (keyCode == KeyEvent.VK_END) || (keyCode == KeyEvent.VK_P)
|| ((keyCode == KeyEvent.VK_C) && e.isControlDown()))
{
if (!isUserPaused)
setUserPaused(true);
else
setUserPaused(false);
}
}
});
}
// This is the game loop. You can copy-paste it even in your own code if you want to.
public void run()
{
long beforeTime, afterTime, timeDiff, sleepTime;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
beforeTime = System.nanoTime();
running = true;
while (running)
{
requestFocus();
gameUpdate();
gameRender();
paintScreen();
afterTime = System.nanoTime();
timeDiff = afterTime - beforeTime;
sleepTime = (period - timeDiff) - overSleepTime;
if (sleepTime > 0)
{
try
{
Thread.sleep(sleepTime / 1000000L);
}
catch (InterruptedException e)
{
}
overSleepTime = (System.nanoTime() - afterTime - sleepTime);
}
else
{
excess -= sleepTime;
overSleepTime = 0L;
if (++noDelays >= NO_DELAYS_PER_YIELD)
{
Thread.yield();
noDelays = 0;
}
}
beforeTime = System.nanoTime();
int skips = 0;
while ((excess > period) && (skips < MAX_FRAME_SKIPS))
{
excess -= period;
gameUpdate();
skips++;
}
isPainted = true;
}
System.exit(0);
}
private void gameUpdate()
{
if (!isUserPaused && !isWindowPaused && !isGameOver)
{
// Update the state of your game objects here...
}
}
private void gameRender()
{
if (dbImage == null)
{
dbImage = createImage(WIDTH, HEIGHT);
if (dbImage == null)
{
System.out.println("Image is null.");
return;
}
else
dbg = dbImage.getGraphics();
}
dbg.setColor(backgroundColor);
dbg.fillRect(0, 0, WIDTH, HEIGHT);
// Render your game objects here....
// like: xyzObject.draw(dbg);
// or dbg.drawOval(...);
if (isGameOver)
gameOverMessage(dbg);
}
private void gameOverMessage(Graphics g)
{
// Paint a game over message here..
}
private void paintScreen()
{
Graphics g;
try
{
g = this.getGraphics();
if ((g != null) && (dbImage != null))
g.drawImage(dbImage, 0, 0, null);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
catch (Exception e)
{
System.out.println("Graphics context error : " + e);
}
}
public void setWindowPaused(boolean isPaused)
{
isWindowPaused = isPaused;
}
public void setUserPaused(boolean isPaused)
{
isUserPaused = isPaused;
}
}
Then you can simply add your game panel to your JFrame like following:
import java.awt.GridBagLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
public class GameFrame extends JFrame
{
private static final long serialVersionUID = -1624735497099558420L;
private GameFrame gamePanel = new GamePanel();
public GameFrame()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Game");
addWindowListener(new FrameListener());
getContentPane().setLayout(new GridBagLayout());
getContentPane().add(gamePanel);
pack();
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
}
public class FrameListener extends WindowAdapter
{
public void windowActivated(WindowEvent we)
{
gamePanel.setWindowPaused(false);
}
public void windowDeactivated(WindowEvent we)
{
gamePanel.setWindowPaused(true);
}
public void windowDeiconified(WindowEvent we)
{
gamePanel.setWindowPaused(false);
}
public void windowIconified(WindowEvent we)
{
gamePanel.setWindowPaused(true);
}
public void windowClosing(WindowEvent we)
{
gamePanel.stopGame();
}
}
public static void main(String args[])
{
new GameFrame();
}
}
How do I make the player and the world scroll at the same time?
because no matter what i do it always has a small delay...
My point is this: my game is a 2d sidescroller (terraria/minecraft/rpg) game and I need to be able to move the terrain together with the world...
Player.java
package game.test.src;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
public class Player {
static final int MOVE_UP = 0, MOVE_DOWN = 1, MOVE_LEFT= 2, MOVE_RIGHT = 3;
private World world;
private Rectangle playerRect;
private Image playerImg;
//Block Variables
private int hoverX, hoverY;
private boolean hovering = false;
protected static int xDirection;
protected static int yDirection;
private Weapon weapon;
public Player(World world){
this.world = world;
playerImg = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/Character.png").getImage();
playerRect = new Rectangle(50, 0, 10, 36);
weapon = new Weapon(weapon.PICKAXE);
}
private static void setXDirection(int d){
xDirection = d;
}
private static void setYDirection(int d){
yDirection = d;
}
public void update()
{
move();
checkForCollision();
}
private void checkForCollision() {
}
private void move()
{
playerRect.x += xDirection;
playerRect.y += yDirection;
gravity();
}
private void gravity()
{
for(int i=0;i<world.arrayNum; i++)
{
if(!world.isSolid[i])
{
setYDirection(1);
}
else if(world.isSolid[i] && playerRect.intersects(world.blocks[i]))
{
setYDirection(0);
}
}
}
//MotionEvents
public void mousePressed(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseMoved(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
int px = playerRect.x;
int py = playerRect.y;
for(int i = 0; i < world.arrayNum; i++)
{
if(weapon.isEquipped(Weapon.PICKAXE) &&
x > world.blocks[i].x && x < world.blocks[i].x + world.blocks[i].width &&
y > world.blocks[i].x && y < world.blocks[i].y + world.blocks[i].height && world.isSolid[i] &&
(world.blocks[i].x + (world.blocks[i].width / 2) ) <= (px + playerRect.width/2) + weapon.WEAPON_RADIUS &&
(world.blocks[i].x + (world.blocks[i].width / 2) ) >= (px + playerRect.width/2) - weapon.WEAPON_RADIUS &&
(world.blocks[i].y + (world.blocks[i].height / 2) ) <= (py + playerRect.height/2) + weapon.WEAPON_RADIUS &&
(world.blocks[i].y + (world.blocks[i].height / 2) ) >= (py + playerRect.height/2) - weapon.WEAPON_RADIUS)
{
hovering = true;
hoverX = world.blocks[i].x;
hoverY = world.blocks[i].y;
break;
}
else
hovering = false;
}
}
public void mouseDragged(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
//Drawing Methods
public void draw(Graphics g)
{
g.drawImage(playerImg, playerRect.x, playerRect.y, null);
if(hovering)
drawBlockOutline(g);
}
private void drawBlockOutline(Graphics g)
{
g.setColor(Color.black);
g.drawRect(hoverX, hoverY, world.blocks[0].width,world.blocks[0].height);
}
private class Weapon
{
public static final int UNARMED = 0;
public static final int PICKAXE = 1;
public static final int GUN = 2;
public int CURRENT_WEAPON;
public int WEAPON_RADIUS;
public Weapon(int w)
{
switch(w)
{
default:
System.out.println("No weapon selected");
break;
case UNARMED:
CURRENT_WEAPON = UNARMED;
WEAPON_RADIUS = 100;
break;
case PICKAXE:
CURRENT_WEAPON = PICKAXE;
WEAPON_RADIUS = 100;
break;
case GUN:
CURRENT_WEAPON = GUN;
WEAPON_RADIUS = 100;
break;
}
}
public void selectWeapon(int w)
{
switch(w)
{
default:
System.out.println("No weapon selected");
break;
case UNARMED:
CURRENT_WEAPON = UNARMED;
WEAPON_RADIUS = 100;
break;
case PICKAXE:
CURRENT_WEAPON = PICKAXE;
WEAPON_RADIUS = 100;
break;
case GUN:
CURRENT_WEAPON = GUN;
WEAPON_RADIUS = 100;
break;
}
}
public boolean isEquipped(int w)
{
if(w == CURRENT_WEAPON)
{
return true;
}
else
return false;
}
}
public void moveMap(){
for(Rectangle r : world.blocks){
r.x += xDirection;
r.y += yDirection;
}
}
public static void stopMoveMap(){
setXDirection(0);
setYDirection(0);
}
private static void setXDirection1(int dir){
xDirection = dir;
}
private static void setYDirection1(int dir){
yDirection = dir;
}
public static void navigatePlayer(int nav){
switch(nav){
default:
System.out.println("default case entered... Doing nothing.");
break;
case MOVE_UP:
setYDirection1(-1);
break;
case MOVE_DOWN:
setYDirection1(1);
break;
case MOVE_LEFT:
setXDirection1(-1);
break;
case MOVE_RIGHT:
setXDirection1(1);
break;
}
}
}
World.java
package game.test.src;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.ImageIcon;
public class World {
public Rectangle[] blocks;
public boolean[] isSolid;
public Image[] blockImg;
public final int arrayNum = 500;
//Block Images
public Image BLOCK_GRASS, BLOCK_DIRT, BLOCK_STONE, BLOCK_SKY;
private int x, y, xDirection, yDirection;;
//map navigation
static final int PAN_UP = 0, PAN_DOWN = 1, PAN_LEFT= 2, PAN_RIGHT = 3;
public World(){
BLOCK_GRASS = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_grass.png").getImage();
BLOCK_DIRT = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_dirt.png").getImage();
BLOCK_STONE = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_stone.png").getImage();
BLOCK_SKY = new ImageIcon("H:/2D game test/Game test 2/src/game/test/src/images/tile_sky.png").getImage();
blocks = new Rectangle[500];
blockImg = new Image[500];
isSolid = new boolean[arrayNum];
loadArrays();
}
private void loadArrays(){
for(int i = 0; i < arrayNum; i++){
if(x >= 500){
x = 0;
y += 20;
}
if(i >= 0 && i < 100){
blockImg[i] = BLOCK_SKY;
isSolid[i] = false;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if(i >= 100 && i < 125){
blockImg[i] = BLOCK_GRASS;
isSolid[i] = true;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if(i >= 125 && i < 225){
blockImg[i] = BLOCK_DIRT;
isSolid[i] = true;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if(i >= 225 && i < 500){
blockImg[i] = BLOCK_STONE;
isSolid[i] = true;
blocks[i] = new Rectangle(x, y, 20, 20);
}
x += 20;
}
}
public void draw(Graphics g){
for(int i = 0; i < arrayNum; i++){
g.drawImage(blockImg[i], blocks[i].x, blocks[i].y, null);
}
}
public void moveMap(){
for(Rectangle r : blocks){
r.x += xDirection;
r.y += yDirection;
}
}
public void stopMoveMap(){
setXDirection(0);
setYDirection(0);
}
private void setXDirection(int dir){
xDirection = dir;
}
private void setYDirection(int dir){
yDirection = dir;
}
public void navigateMap(int nav){
switch(nav){
default:
System.out.println("default case entered... Doing nothing.");
break;
case PAN_UP:
setYDirection(-1);
break;
case PAN_DOWN:
setYDirection(1);
break;
case PAN_LEFT:
setXDirection(-1);
break;
case PAN_RIGHT:
setXDirection(1);
break;
}
}
}
GamePanel.java
package game.test.src;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable {
//Double buffering
private Image dbImage;
private Graphics dbg;
//JPanel variables
static final int GWIDTH = 500, GHEIGHT = 400;
static final Dimension gameDim = new Dimension(GWIDTH, GHEIGHT);
//Game variables
private static final int DELAYS_BEFORE_YIELD = 10;
private Thread game;
private volatile boolean running = false;
private long period = 6*1000000; //ms -> nano
//Game Objects
World world;
Player p1;
public GamePanel(){
world = new World();
p1 = new Player(world);
setPreferredSize(gameDim);
setBackground(Color.WHITE);
setFocusable(true);
requestFocus();
//Handle all key inputs from user
addKeyListener(new KeyAdapter(){
#Override
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT){
Player.navigatePlayer(Player.MOVE_LEFT);
world.navigateMap(World.PAN_LEFT);
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
Player.navigatePlayer(Player.MOVE_RIGHT);
world.navigateMap(World.PAN_RIGHT);
}
if(e.getKeyCode() == KeyEvent.VK_UP){
Player.navigatePlayer(Player.MOVE_UP);
world.navigateMap(World.PAN_UP);
}
if(e.getKeyCode() == KeyEvent.VK_DOWN){
Player.navigatePlayer(Player.MOVE_DOWN);
world.navigateMap(World.PAN_DOWN);
}
}
#Override
public void keyReleased(KeyEvent e){
Player.stopMoveMap();
world.stopMoveMap();
}
#Override
public void keyTyped(KeyEvent e){
}
});
addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e)
{
}
#Override
public void mouseReleased(MouseEvent e)
{
}
#Override
public void mouseClicked(MouseEvent e)
{
}
});
addMouseMotionListener(new MouseAdapter()
{
public void mouseMoved(MouseEvent e)
{
p1.mouseMoved(e);
}
public void mouseDragged(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
});
}
public void run(){
long beforeTime, afterTime, diff, sleepTime, overSleepTime = 0;
int delays = 0;
while(running){
beforeTime = System.nanoTime();
gameUpdate();
gameRender();
paintScreen();
afterTime = System.nanoTime();
diff = afterTime - beforeTime;
sleepTime = (period - diff) - overSleepTime;
//if sleepTime is between peiod and 0, then sleep
if(sleepTime < period && sleepTime > 0)
{
try{
Thread.sleep(sleepTime/1000000L);
overSleepTime = 0;
}catch(InterruptedException ex){
Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, "EXCEPTION");
}
}
//the diff was greater than the period
else if(diff > period)
{
overSleepTime = diff - period;
}
else if(++delays >= DELAYS_BEFORE_YIELD)
{
Thread.yield();
delays = 0;
overSleepTime = 0;
}
//the loop took less time than expected
else
{
overSleepTime = 0;
}
}
}
private void gameUpdate(){
if(running && game != null){
world.moveMap();
p1.update();
}
}
private void gameRender(){
if(dbImage == null){ // Create the buffer
dbImage = createImage(GWIDTH, GHEIGHT);
if(dbImage == null){
System.err.println("dbImage is still null!");
return;
}else{
dbg = dbImage.getGraphics();
}
}
//Clear the screen
dbg.setColor(Color.WHITE);
dbg.fillRect(0, 0, GWIDTH, GHEIGHT);
//Draw Game elements
draw(dbg);
}
/* Draw all game content in this method */
public void draw(Graphics g){
world.draw(g);
p1.draw(g);
}
private void paintScreen(){
Graphics g;
try{
g = this.getGraphics();
if(dbImage != null && g != null){
g.drawImage(dbImage, 0, 0, null);
}
Toolkit.getDefaultToolkit().sync(); //For some operating systems
g.dispose();
}catch(Exception e){
System.err.println(e);
}
}
public void addNotify(){
super.addNotify();
startGame();
}
private void startGame(){
if(game == null || !running){
game = new Thread(this);
game.start();
running = true;
}
}
public void stopGame(){
if(running){
running = false;
}
}
private void log(String s){
System.out.println(s);
}
}
thanks for the help!