I am following a series of tutorials for Java game development tutorials. I already have a basic knowledge of Java, from thenewboston, if that helps. Anyway, I was stuck on this tutorial: http://www.youtube.com/watch?v=hN1v1ZhITDc&feature=c4-overview-vl&list=PL54DB126285ED0420 The program I am creating for this tutorial is sort of like a 2D Minecraft, and at this point, the program should display a window with several tiles of dirt, stone, and sky in specific order. When I run it, it just displays a blank JFrame and I get these errors:
at mineGameMain.World.draw(World.java:80)
at mineGameMain.GamePanel.draw(GamePanel.java:91)
at mineGameMain.GamePanel.gameRender(GamePanel.java:85)
at mineGameMain.GamePanel.run(GamePanel.java:51)
at java.lang.Thread.run(Unknown Source)
I have three classes, Main:
package mineGameMain;
import javax.swing.JFrame;
public class Main extends JFrame{
GamePanel gp;
public Main(){
gp = new GamePanel();
setSize(500, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
add(gp);
}
public static void main(String[] args){
Main m = new Main();
}
}
GamePanel:
package mineGameMain;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
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 Thread game;
private volatile boolean running = false;
//Game Objects
World world;
public GamePanel(){
world = new World();
setPreferredSize(gameDim);
setBackground(Color.WHITE);
setFocusable(true);
requestFocus();
//Handle all key inputs
addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
}
public void keyReleased(KeyEvent e){
}
public void Typed(KeyEvent e){
}
});
}
public void run(){
while(running){
gameUpdate();
gameRender();
paintScreen();
}
}
private void gameUpdate(){
if(running && game != null){
//Update game state
}
}
private void gameRender(){
if(dbImage == null){
dbImage = createImage(GWIDTH, GHEIGHT);
if(dbImage == null){
System.err.println("dbImage IS STILL NULL SO SHUTUPBEQUIET!");
return;
}else{
dbg = dbImage.getGraphics();
}
}
//Clear the screen
dbg.setColor(Color.WHITE);
dbg.fillRect(0, 0, GWIDTH, GHEIGHT);
//draw Game Methods
draw(dbg);
}
/*Draw all game content in this method*/
private void draw(Graphics g) {
world.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();
}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);
}
}
And finally, World:
package mineGameMain;
import java.awt.Image;
import java.awt.*;
import javax.swing.ImageIcon;
public class World {
private Rectangle[] blocks;
private Image[] blockImg;
private final int arrayNum = 500;
//Block images
private Image BLOCK_DIRT_TOP, BLOCK_DIRT, BLOCK_STONE, BLOCK_SKY;
private int x, y;
public World(){
BLOCK_DIRT_TOP = new ImageIcon("/MineGame/src/mineGameMain/Tile_Grass.png").getImage();
BLOCK_DIRT = new ImageIcon("/MineGame/src/mineGameMain/Tile_Dirt.png").getImage();
BLOCK_STONE = new ImageIcon("/MineGame/src/mineGameMain/Tile_Stone.png").getImage();
BLOCK_STONE = new ImageIcon("/MineGame/src/mineGameMain/Tile_Sky.png").getImage();
blocks = new Rectangle[500];
blockImg = new Image[500];
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;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if( i >= 100 && i < 120){
blockImg[i] = BLOCK_DIRT_TOP;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if( i >= 125 && i < 220){
blockImg[i] = BLOCK_DIRT;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if( i >= 225 && i < 500){
blockImg[i] = BLOCK_STONE;
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);
}
}
}
Thank you for your time. If I did something wrong by posting this or if I left out any details please let me know.
Find below a way to turn your question into an SSCCE (actually it is a fixed version of one)
There are quite a few mistakes you should avoid in your code
No need to implement double buffering yourself, Swing is double buffered by default
All access to the UI should be made on the EDT (the Event Dispacthing Thread), not from a random Thread you created. You should also start your UI from the EDT, using invokeLater
To paint a component, override paintComponent and invoke repaint() whenever you want it to be called.
Never use getGraphics on JComponent, always Graphics objects provided as method-arguments (like in paintComponent).
No need to extends JFrame here --> don't extend if you don't need to (you don't actually add behaviour to the JFrame)
Make sure to call setVisible(true) as your last statement for the JFrame.
You forgot to handle block 120 to 125 and block 220 to 225 (probably causing NullPointerException in your draw method (this is likely the root of your error).
When you post a Java error, make sure to post the whole stacktrace and the message provided above the stacktrace (make also sur that people can identify your line numbers, by adding a comment like // this is line 80 of the World class)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main extends JFrame {
GamePanel gp;
public Main() throws MalformedURLException {
gp = new GamePanel();
setSize(500, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(gp);
pack();
setVisible(true);
}
public static class World {
private Rectangle[] blocks;
private Image[] blockImg;
private final int arrayNum = 500;
// Block images
private Image BLOCK_DIRT_TOP, BLOCK_DIRT, BLOCK_STONE, BLOCK_SKY;
private int x, y;
public World() throws MalformedURLException {
BLOCK_DIRT_TOP = new ImageIcon(new URL("http://i909.photobucket.com/albums/ac298/XxEnoAsaIxX/grass2test.png?t=1303852677"))
.getImage();
BLOCK_DIRT = new ImageIcon(new URL(
"http://i909.photobucket.com/albums/ac298/XxEnoAsaIxX/sparsedirtandgrasstile.png?t=1300172998")).getImage();
BLOCK_STONE = new ImageIcon(new URL("http://www.stonetilesupply.com/v/vspfiles/photos/MARBL-BTTCNCLASSICO-2S.jpg")).getImage();
BLOCK_SKY = new ImageIcon(new URL("http://lacoste.scene7.com/is/image/lacoste/swatch_10_CH0783-00_SVH_24?$swatch$")).getImage();
blocks = new Rectangle[500];
blockImg = new Image[500];
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;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if (i >= 100 && i < 120) {
blockImg[i] = BLOCK_DIRT_TOP;
blocks[i] = new Rectangle(x, y, 20, 20);
}
// Here missing block for 120 to 125
if (i >= 120 && i < 125) {
blockImg[i] = BLOCK_STONE;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if (i >= 125 && i < 220) {
blockImg[i] = BLOCK_DIRT;
blocks[i] = new Rectangle(x, y, 20, 20);
}
// Here missing block for 220 to 225
if (i >= 220 && i < 225) {
blockImg[i] = BLOCK_SKY;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if (i >= 225 && i < 500) {
blockImg[i] = BLOCK_STONE;
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 static class GamePanel extends JPanel {
// JPanel variables
// Game Objects
World world;
public GamePanel() throws MalformedURLException {
world = new World();
setPreferredSize(new Dimension(500, 400));
setBackground(Color.WHITE);
setFocusable(true);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
world.draw(g);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new Main();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
Related
So I'm new at java and need some help with my breakout game. My JFrame is just blank and i don't know how to fix it?
So I have a ball class, paddle class, canvas class and a brick class as well as a main class. In my canvas class I set all functions the ball, paddle and bricks has etc. In brick class I draw the bricks. And in my main I do the JFrame but it's blank
Main class :
public class Main {
public static void main(String[] args){
JFrame frame = new JFrame();
Canvas c = new Canvas();
frame.add(c);
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I expect the JFrame to show the game instead of just blank window
package breakout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.KeyEvent;
import breakout.Bricks.Type;
public class Canvas extends JPanel implements ActionListener, MouseMotionListener, MouseListener, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final int HEIGHT = 600;
public static final int WIDTH = 720;
private int horizontalCount;
private BufferedImage image;
private Graphics2D bufferedGraphics;
private Timer time;
private static final Font endFont = new Font(Font.SANS_SERIF, Font.BOLD, 20);
private static final Font scoreFont = new Font(Font.SANS_SERIF, Font.BOLD, 15);
private Paddle player;
private Ball ball;
ArrayList<ArrayList<Bricks>> bricks;
public Canvas() {
super();
setPreferredSize( new Dimension(WIDTH, HEIGHT));
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
bufferedGraphics = image.createGraphics();
time = new Timer (15, this);
player = new Paddle((WIDTH/2)-(Paddle.PADDLE_WIDTH/2));
ball = new Ball (((player.getX() + (Paddle.PADDLE_WIDTH / 2 )) - (Ball.DIAMETER / 2)), (Paddle.Y_POS - (Ball.DIAMETER + 10 )), -5, -5);
bricks = new ArrayList<ArrayList<Bricks>>();
horizontalCount = WIDTH / Bricks.BRICK_WIDTH;
for(int i = 0; i < 8; ++i) {
ArrayList<Bricks> temp = new ArrayList<Bricks>();
#SuppressWarnings("unused")
Type rowColor = null;
switch(i) {
case 0 :
case 2:
rowColor = Type.LOW;
break;
case 1 :
case 3 :
case 5 :
rowColor = Type.MEDIUM;
break;
case 4 :
case 6 :
rowColor = Type.HIGH;
break;
case 7 :
default :
rowColor = Type.ULTRA;
break;
}
for(int j = 0; j < horizontalCount; ++j) {
Bricks tempBrick = new Bricks();
temp.add(tempBrick);
}
bricks.add(temp);
addMouseMotionListener(this);
addMouseListener(this);
addKeyListener(this);
requestFocus();
}
}
public void actionPerformed(ActionEvent e) {
checkCollisions();
ball.Move();
for(int i = 0; i < bricks.size(); ++i) {
ArrayList<Bricks> al = bricks.get(i);
for(int j = 0; j < al.size(); ++j) {
Bricks b = al.get(j);
if(b.dead()) {
al.remove(b);
}
}
}
repaint();
}
private void checkCollisions() {
if(player.hitPaddle(ball)) {
ball.setDY(ball.getDY() * -1);
return;
}
if(ball.getX() >= (WIDTH - Ball.DIAMETER) || ball.getX() <= 0) {
ball.setDX(ball.getDX() * -1);
}
if(ball.getY() > (Paddle.Y_POS + Paddle.PADDLE_HEIGHT + 10)) {
resetBall();
}
if(ball.getY() <= 0) {
ball.setDY(ball.getDY() * -1);
}
int brickRowActive = 0;
for(ArrayList<Bricks> alb : bricks) {
if(alb.size() == horizontalCount) {
++brickRowActive;
}
}
for(int i = (brickRowActive==0) ? 0 : (brickRowActive - 1); i < bricks.size(); ++i) {
for(Bricks b : bricks.get(i)) {
if(b.hitBy(ball)) {
player.setScore(player.getScore() + b.getBrickType().getPoints());
b.decrementType();
}
}
}
}
private void resetBall() {
if(gameOver()) {
time.stop();
return;
}
ball.setX(WIDTH/2);
ball.setDY((HEIGHT/2) + 80);
player.setLives(player.getLives() -1);
player.setScore(player.getScore() <= 1);
}
private boolean gameOver() {
if(player.getLives() <= 1) {
return true;
}
return false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
bufferedGraphics.clearRect(0, 0, WIDTH, HEIGHT);
player.drawPaddle(bufferedGraphics);
player.drawBall(bufferedGraphics);
for(ArrayList<Bricks> row : bricks) {
for(Bricks b : row) {
b.drawBrick(bufferedGraphics);
}
}
bufferedGraphics.setFont(scoreFont);
bufferedGraphics.drawString("Score: " + player.getScore(), 10, 25);
if(gameOver() && ball.getY() >= HEIGHT) {
bufferedGraphics.setColor(Color.black);
bufferedGraphics.setFont(endFont);
bufferedGraphics.drawString("Game Over Score: " + player.getScore(), (WIDTH /2) -85, (HEIGHT/2));
}
if(empty()) {
bufferedGraphics.setColor(Color.black);
bufferedGraphics.setFont(endFont);
bufferedGraphics.drawString("You won. Score: " + player.getScore(), (WIDTH /2) -85, (HEIGHT /2));
time.stop();
}
g.drawImage(image, 0, 0, this);
Toolkit.getDefaultToolkit().sync();
}
private boolean empty() {
for(ArrayList<Bricks> al : bricks) {
if(al.size() != 0) {
return false;
}
}
return true;
}
#Override
public void mouseMoved(MouseEvent e) {
player.setX(e.getX() - (Paddle.PADDLE_WIDTH / 2));
}
#Override
public void mouseClicked(MouseEvent e) {
if(time.isRunning()) {
return;
}
time.start();
}
#Override
public void mouseDragged(MouseEvent e) { }
#Override
public void mouseEntered(MouseEvent arg0) {}
#Override
public void mouseExited(MouseEvent arg0) {}
#Override
public void mousePressed(MouseEvent arg0) {}
#Override
public void mouseReleased(MouseEvent arg0) {}
#Override
public void keyPressed(KeyEvent arg0) {}
#Override
public void keyReleased(KeyEvent arg0) {}
#Override
public void keyTyped(KeyEvent arg0) {}
}
Preparing an MCVE, as required in SO, not only it makes helping much easier.
In many case, while preparing one, you are likely to find the problem, so it is a good debugging tool.
To answer "why is my JFrame blank ?" you could create the minimal code example like the following (copy-paste the entire code into GameBoard.java and run):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameBoard extends JPanel {
static final int HEIGHT = 600, WIDTH = 720, BRICK_ROWS = 8;
private final int horizontalCount;
private static final Font scoreFont = new Font(Font.SANS_SERIF, Font.BOLD, 15);
private final Paddle player;
private final Ball ball;
ArrayList<ArrayList<Brick>> bricks;
public GameBoard() {
super();
setPreferredSize( new Dimension(WIDTH, HEIGHT));
player = new Paddle(WIDTH/2-Paddle.PADDLE_WIDTH/2);
ball = new Ball (player.getX() + Paddle.PADDLE_WIDTH / 2 - Ball.DIAMETER / 2,
Paddle.Y_POS - (Ball.DIAMETER + 10 ));
bricks = new ArrayList<>();
horizontalCount = WIDTH / Brick.BRICK_WIDTH;
for(int i = 0; i < BRICK_ROWS; ++i) {
ArrayList<Brick> temp = new ArrayList<>();
for(int j = 0; j < horizontalCount; ++j) {
Brick tempBrick = new Brick(j*Brick.BRICK_WIDTH , Brick.BRICK_YPOS + i*Brick.BRICK_HEIGHT);
temp.add(tempBrick);
}
bricks.add(temp);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D)g;
g2D.clearRect(0, 0, WIDTH, HEIGHT);
player.drawPaddle(g2D);
ball.drawBall(g2D);
for(ArrayList<Brick> row : bricks) {
for(Brick b : row) {
b.drawBrick(g2D);
}
}
g2D.setFont(scoreFont);
g2D.drawString("Score: " + player.getScore(), 10, 25);
}
}
class Paddle{
public final static int PADDLE_WIDTH = 100, PADDLE_HEIGHT= 30, Y_POS = GameBoard.HEIGHT - 2* PADDLE_HEIGHT;
private int xPos, score;
Paddle(int xPos) {
this.xPos = xPos;
}
void setX(int xPos) {this.xPos = xPos;}
int getX() {return xPos;}
String getScore() {
return String.valueOf(score);
}
void drawPaddle(Graphics2D g2D) {
g2D.setColor(Color.GREEN);
g2D.fillRect(xPos, Y_POS, PADDLE_WIDTH, PADDLE_HEIGHT);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(400,250);
frame.add(new GameBoard());
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
}
class Brick{
final static int BRICK_WIDTH = 80, BRICK_HEIGHT = 15, BRICK_YPOS = 50;
int xPos, yPos;
Brick(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBrick(Graphics2D g2D) {
g2D.setColor(Color.RED);
g2D.fillRect(xPos, yPos, BRICK_WIDTH, BRICK_HEIGHT);
g2D.setColor(Color.BLACK);
g2D.drawRect(xPos, yPos, BRICK_WIDTH, BRICK_HEIGHT);
}
}
class Ball{
final static int DIAMETER = 40;
int xPos, yPos;
Ball(int xPos, int yPos) {
this.xPos = xPos;
this.yPos = yPos;
}
void drawBall(Graphics2D g2D) {
g2D.setColor(Color.BLUE);
g2D.fillOval(xPos, yPos, DIAMETER, DIAMETER);
}
}
This produces the following result, which I believe can serve as the basis of what you wanted to achieve:
Now start adding the missing functionality and see what breaks it.
I'm trying to make a 2D tile based game. I have been encountering an issue when attempting to draw new graphics and the old ones don't seem to have been removed.
If anyone knows why g.dispose isn't clearing the graphics then please help.
Here's my "Main" class:
package Main;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class Main extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
private JFrame frame;
static int size = 40;
static int tilesX = 20;
static int tilesY = 20;
static int width = size * 10;
static int height = size * 10;
private boolean running = false;
public static STATE state = STATE.MENU;
public static PLAYER type = PLAYER.ARCHER;
private Thread thread;
static tileMap grid = new tileMap();
tile[][] map = tileMap.map;
public Main() {
addKeyListener(new controls());
addMouseListener(new mouse());
Dimension wSize = new Dimension(width, height);
setPreferredSize(wSize);
frame = new JFrame();
}
public synchronized void start() {
running = true;
thread = new Thread(this, "game");
thread.start();
}
public synchronized void stop() {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public enum STATE {
MENU, GAME
}
public enum PLAYER {
ARCHER, KNIGHT
}
public static void main(String[] args) {
Main game = new Main();
game.frame = new JFrame("Game");
game.frame.add(game);
game.frame.setResizable(false);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setVisible(true);
game.start();
}
public void run() {
while (running) {
if (state == STATE.MENU) {
menu();
} else if (state == STATE.GAME) {
tick();
render();
}
try {
Thread.sleep(16);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void menu() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(2);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawRect(Main.width / 8, 20, Main.width / 3, 200);
g.drawString("Archer", Main.width / 8, 20);
g.drawRect((Main.width - Main.width / 3) - Main.width / 8, 20,
Main.width / 3, 200);
g.drawString("Knight", (Main.width - Main.width / 3) - Main.width / 8,
20);
g.dispose();
bs.show();
}
private void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D d = (Graphics2D) g;
camera.setCam();
g.translate(-camera.camX, -camera.camY);
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
d.setColor(map[i][j].getC());
d.fillRect(map[i][j].getX(), map[i][j].getY(), Main.size, Main.size);
d.setColor(Color.BLACK);
d.drawRect(map[i][j].getX(), map[i][j].getY(), Main.size, Main.size);
}
}
map[player.p.getX()][player.p.getY()].setC(player.p.getC());
if (type == PLAYER.ARCHER) {
d.drawString("Archer", 5, 15);
} else if (type == PLAYER.KNIGHT) {
d.drawString("Knight", 5, 15);
}
g.dispose();
bs.show();
}
static public void moved() {
tileMap.map[player.p.getX()][player.p.getY()].setC(Color.GREEN);
}
private void tick() {
if (player.p == null) {
player.createP();
}
}
}
Graphics#dispose releases any internal resources that the Graphics context may be holding, reducing the memory overhead, it does not "clear" the context.
From the JavaDocs
Disposes of this graphics context and releases any system resources that it is using. A Graphics object cannot be used after dispose has been called.
What it doesn't do is effect the underlying content, that would be, well, annoying, as using a copy of a Graphics object is a good and easy way to make complex changes without effecting the original context.
To "clear" the context you could use fillRect to paint a color/background before you performing you next cycle of painting. Do this just after Graphics g = bs.getDrawGraphics();
I am creating a game in java. In it, you control a square that follows your mouse. I want to implement collision detection for the square so that it stops slightly within the JFrame and not at the edge. This is very easy when doing this with the arrow keys, but I can't figure it out with the mouseMoved method. Here is the code where the mouseMoved method is:
public void mouseMoved(MouseEvent e){
repaint();
if(e.getX() <= 0)
playerX = 0;
if(e.getX() >= 300)
playerX = 500;
if(e.getY() <= 0)
playerY = 0;
if(e.getY() >= 300)
playerY = 500;
else
playerX = e.getX()-25;
playerY = e.getY()-25;
repaint();
}
Here's the code where the square is created:
public void paintComponent(Graphics g) {
Rectangle player = new Rectangle(playerX, playerY, 50, 50);
g.setColor(Color.blue);
g.fillRect(player.x, player.y, player.width, player.height);
repaint();
}
I don't think you'll need this, but just in case, here's all the code for the GamePanel class, which serves as the panel for my JFrame in the Main class. If you need the Main class let me know but I doubt you will:
package main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
//Global variables
//Double buffering
private Image dbImage;
private Graphics dbg;
//JPanel variables
static final int GWIDTH = 500, GHEIGHT = 500;
static final Dimension gameDim = new Dimension(GWIDTH, GHEIGHT);
//Game variable
private Thread game;
private volatile boolean running = false;
public boolean mouseClicked = false;
//Character variables
int playerX = 150, playerY = 150;
public class Mouse extends MouseAdapter{
public void mousePressed(MouseEvent e){
mouseClicked = true;
}
public void mouseReleased(MouseEvent e){
mouseClicked = false;
}
public void mouseMoved(MouseEvent e){
repaint();
if(e.getX() <= 0)
playerX = 0;
if(e.getX() >= 300)
playerX = 500;
if(e.getY() <= 0)
playerY = 0;
if(e.getY() >= 300)
playerY = 500;
else
playerX = e.getX()-25;
playerY = e.getY()-25;
repaint();
}
}
public GamePanel(){
addMouseMotionListener(new Mouse());
setPreferredSize(gameDim);
setBackground(Color.BLUE);
setFocusable(true);
requestFocus(true);
}
public void run(){
while(running){
}
}
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;
}
//Paint method
}
public void paint(Graphics g){
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent(Graphics g) {
Rectangle player = new Rectangle(playerX, playerY, 50, 50);
g.setColor(Color.blue);
g.fillRect(player.x, player.y, player.width, player.height);
repaint();
}
private void log(String s){
System.out.println(s);
}
}
Thank you for your help. Please let me know if you need anything.
Your movement code is a bit off. You set the x position only if the Y is not out of bounds and always replace the Y value. Can I suggest full blocks in future - they help avoiding problems like this.
playerX = e.getX()-25;
playerY = e.getY()-25;
if(e.getX() <= 0){
playerX = 0;
}
else if(e.getX() >= 300){
playerX = 500;
}
if(e.getY() <= 0){
playerY = 0;
}
else if(e.getY() >= 300){
playerY = 500;
}
This sets the position first and then corrects it if the player is out of the bounds.
I am working on a Java project to simulate the flight of a helicopter in a frame. The helicopter moves on the screen using the arrow keys. I want the helicopter to be able to move infinitely, that is, when the helicopter reaches the edge of the frame, the background should move in the opposite direction to have the effect of endless terrain.
Here is the code I have so far:
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MainFrame extends JFrame
{
private static int FRAME_WIDTH = 800;
private static int FRAME_HEIGHT = 500;
public MainFrame()
{
add(new AnotherBackground(FRAME_WIDTH, FRAME_HEIGHT));
setTitle("Helicopter Background Test");
setSize(FRAME_WIDTH,FRAME_HEIGHT);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args)
{
new MainFrame();
}
}
class AnotherBackground extends JPanel
{
private BufferedImage heliImage = null;
private BufferedImage backImage = null;
private int heliX = 0;
private int heliY = 0;
private int backX = 0;
private int backY = 0;
private int frameWidth = 0;
private int frameHeight = 0;
private int backWidth = 0;
private int backHeight = 0;
public AnotherBackground(int fWidth, int fHeight)
{
frameWidth = fWidth;
frameHeight = fHeight;
this.setFocusable(true);
this.addKeyListener(new HeliListener());
try
{
heliImage = ImageIO.read(new URL("http://imageshack.us/a/img7/2133/helicopter2f.png"));
// 2.7 Meg Crap that is a humungous image! Substitute dummy.
backImage = new BufferedImage(1918,1200,BufferedImage.TYPE_INT_RGB);
}
catch(IOException ex)
{
System.out.println("Problem durinng loading heli image");
}
backWidth = backImage.getWidth();
backHeight = backImage.getHeight();
HeliPainter l = new HeliPainter();
new Thread(l).start();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(backImage, backX, backY, null);
g.drawImage(heliImage, heliX, heliY, null);
}
class HeliListener extends KeyAdapter
{
#Override
public void keyPressed(KeyEvent e)
{
System.out.println(heliX + " " + heliY + " " + backX + " " + backY);
if (e.getKeyCode() == KeyEvent.VK_LEFT)
{
if(heliX > 0)
{
heliX -= 5;
}
else
{
backX += 5;
}
}
else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
{
if(heliX < frameWidth)
{
heliX += 5;
}
else
{
backX -= 5;
}
}
else if (e.getKeyCode() == KeyEvent.VK_UP)
{
if(heliY > 0)
{
heliY -= 5;
}
else
{
backY += 5;
}
}
else if (e.getKeyCode() == KeyEvent.VK_DOWN)
{
if(heliY < frameHeight)
{
heliY += 5;
}
else
{
backY -= 5;
}
}
}
}
class HeliPainter implements Runnable
{
#Override
public void run()
{
try
{
while(true)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
repaint();
}
});
Thread.sleep(1);
}
}
catch(InterruptedException ex)
{
System.out.println("Problem putting thread to sleep");
}
}
}
}
Now there's two images in the code. One is that of a small helicopter, and the other is a large (2.7 meg) background. They are here:
background
helicopter http://imageshack.us/a/img7/2133/helicopter2f.png
How to show the BG continuously?
Have a look through this source which behaves in a more predictable manner, and also includes a nice tweak to the chopper image (animated). ;)
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MainFrame
{
public MainFrame()
{
JFrame f = new JFrame("Helicopter Background Test");
f.add(new AnotherBackground());
//setTitle("Helicopter Background Test"); Redundant..
// Set a preferred size for the content area and pack() the frame instead!
// setSize(FRAME_WIDTH,FRAME_HEIGHT);
// setLocationRelativeTo(null); Better to..
f.setLocationByPlatform(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack(); // Size the GUI - VERY MPORTANT!
f.setVisible(true);
}
public static void main(String[] args)
{
new MainFrame();
}
}
class AnotherBackground extends JPanel
{
private static int PREFERRED_WIDTH = 400;
private static int PREFERRED_HEIGHT = 200;
private BufferedImage heliImage = null;
private BufferedImage heliLeftImage = null;
private BufferedImage heliRightImage = null;
private BufferedImage backImage = null; //getFlippedImage(
private int heliX = 0;
private int heliY = 0;
private int backX = 0;
private int backY = 0;
private int frameWidth = 0;
private int frameHeight = 0;
private int backWidth = 0;
private int backHeight = 0;
public AnotherBackground()
{
frameWidth = PREFERRED_WIDTH;
frameHeight = PREFERRED_HEIGHT;
this.setFocusable(true);
this.addKeyListener(new HeliListener());
try
{
heliLeftImage = ImageIO.read(
new URL("http://imageshack.us/a/img7/2133/helicopter2f.png"));
heliRightImage = getFlippedImage(heliLeftImage);
heliImage = heliLeftImage;
// 2.7 Meg Crap that is an humungous image! Substitute dummy.
backImage = getTileImage(250);
//ImageIO.read(
// new URL("http://i.stack.imgur.com/T5uTa.png"));
backWidth = backImage.getWidth();
backHeight = backImage.getHeight();
//HeliPainter l = new HeliPainter(); // see mention of repaint()
//new Thread(l).start();
} catch(IOException ex) {
// THERE IS NO POINT CONTINUING AFTER THIS POINT!
// unless it is to pop an option pane error message..
System.err.println("Problem during loading heli image");
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT);
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
int normalizeX = (heliRealX-heliX)%backImage.getWidth();
int normalizeY = (heliRealY-heliY)%backImage.getHeight();
int timesRepeatX = (getWidth()/backImage.getWidth())+2;
int timesRepeatY = (getHeight()/backImage.getHeight())+2;
for (int xx=-1; xx<timesRepeatX; xx++) {
for (int yy=-1; yy<timesRepeatY; yy++) {
g.drawImage(
backImage,
(xx*backImage.getWidth())-normalizeX,
(yy*backImage.getHeight())-normalizeY,
this); // A JPanel IS AN ImageObserver!
g.drawImage(heliImage, heliX, heliY, this);
}
}
g.setColor(Color.BLACK);
}
private int heliRealX = 0;
private int heliRealY = 0;
class HeliListener extends KeyAdapter
{
#Override
public void keyPressed(KeyEvent e)
{
int pad = 5;
if (e.getKeyCode() == KeyEvent.VK_LEFT)
{
if(heliX > 0)
{
heliX -= 5;
}
else
{
backX += 5;
}
heliRealX-=5;
heliImage = heliLeftImage;
}
else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
{
// correct for image size + padding
if(heliX+heliImage.getWidth()+pad < getWidth())
{
heliX += 5;
}
else
{
backX -= 5;
}
heliRealX+=5;
heliImage = heliRightImage;
}
else if (e.getKeyCode() == KeyEvent.VK_UP)
{
if(heliY > 0)
{
heliY -= 5;
}
else
{
backY += 5;
}
heliRealY-=5;
}
else if (e.getKeyCode() == KeyEvent.VK_DOWN)
{
// correct for image size + padding
if(heliY+heliImage.getHeight()+pad < getHeight())
{
heliY += 5;
}
else
{
backY -= 5;
}
heliRealY+=5;
}
repaint(); // Replaces need for threads for this simple demo!
}
}
public BufferedImage getFlippedImage(BufferedImage original) {
BufferedImage bi = new BufferedImage(
original.getWidth(),
original.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
AffineTransform at = AffineTransform.getTranslateInstance(bi.getWidth(),1d);
at.concatenate(AffineTransform.getScaleInstance(-1d,1d));
g.setTransform(at);
g.drawImage(original,0,0,this);
g.dispose();
return bi;
}
public BufferedImage getTileImage(int s) {
BufferedImage bi = new BufferedImage(s,s,BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
GradientPaint gp1 = new GradientPaint(
(float)0,(float)s/4, Color.YELLOW,
(float)s/4,0f, Color.GREEN,
true);
g.setPaint(gp1);
g.fillRect(0,0,s,s);
int trans = 165;
GradientPaint gp2 = new GradientPaint(
(float)s/2,(float)s/2, new Color(255,0,0,trans),
0f,(float)s/2, new Color(255,255,255,trans),
true);
g.setPaint(gp2);
g.fillRect(0,0,s,s);
g.dispose();
return bi;
}
}
This is a really simple example (you can only move in a single direction). The basic idea is that there is a prepareView method that is responsible for generating a view of the world based on the available viewable area. If the view is trying to view an area off the map, the map is titled to make up for it.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class InfiniteBackground {
public static void main(String[] args) {
new InfiniteBackground();
}
public InfiniteBackground() {
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 static class TestPane extends JPanel {
protected static final int DELTA = 5;
private BufferedImage terrian;
private BufferedImage heli;
private Point pov;
private Point heliPoint;
private BufferedImage view;
public TestPane() {
pov = new Point();
heliPoint = new Point();
try {
terrian = ImageIO.read(getClass().getResource("/terrain_map.jpg"));
heli = ImageIO.read(getClass().getResource("/helicopter2f.png"));
pov.x = terrian.getWidth() - getPreferredSize().width;
pov.y = ((terrian.getHeight() - getPreferredSize().height) / 2);
heliPoint.x = getPreferredSize().width / 2;
heliPoint.y = getPreferredSize().height / 2;
prepareView();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "goLeft");
am.put("goLeft", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
heliPoint.x -= DELTA;
if (heliPoint.x - (heli.getWidth() / 2) < 0) {
heliPoint.x = (heli.getWidth() / 2);
prepareView();
pov.x -= DELTA;
}
repaint();
}
});
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
protected void prepareView() {
if (getWidth() > 0 && getHeight() > 0) {
view = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = view.createGraphics();
if (pov.x < 0) {
pov.x = terrian.getWidth();
}
g2d.drawImage(terrian, -pov.x, -pov.y, this);
if (pov.x + getWidth() > terrian.getWidth()) {
g2d.drawImage(terrian, -pov.x + terrian.getWidth(), -pov.y, this);
}
g2d.dispose();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (terrian != null) {
Graphics2D g2d = (Graphics2D) g.create();
if (view == null) {
prepareView();
}
g2d.drawImage(view, 0, 0, this);
g2d.drawImage(heli, heliPoint.x - (heli.getWidth() / 2), heliPoint.y - (heli.getHeight() / 2), this);
g2d.dispose();
}
}
}
}
I need some help with making a tiled map, I'm just getting a white screen instead of a map with images ( tiles) on it. Can someone help with that?
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 {
private Rectangle[] blocks;
private Image[] blockImg;
private final int arrayNum = 500;
//Block Images
private Image BLOCK_GRASS, BLOCK_DIRT, BLOCK_STONE, BLOCK_SKY;
private int x, y;
public World(){
BLOCK_GRASS = new ImageIcon("C:/Users/Pim/Desktop/2D game test/Game test 2/src/game/test/src/images/tile_grass").getImage();
BLOCK_DIRT = new ImageIcon("C:/Users/Pim/Desktop/2D game test/Game test 2/src/game/test/src/images/tile_dirt").getImage();
BLOCK_STONE = new ImageIcon("C:/Users/Pim/Desktop/2D game test/Game test 2/src/game/test/src/images/tile_stonek").getImage();
BLOCK_SKY = new ImageIcon("C:/Users/Pim/Desktop/2D game test/Game test 2/src/game/test/src/images/tile_sky").getImage();
blocks = new Rectangle[500];
blockImg = new Image[500];
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;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if(i >= 100 && i < 125)
{
blockImg[i] = BLOCK_GRASS;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if(i >= 125 && i < 225)
{
blockImg[i] = BLOCK_DIRT;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if(i >= 225 && i < 500)
{
blockImg[i] = BLOCK_STONE;
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);
}
}
}
And here is GamePanel.java:
package game.test.src;
import java.awt.*;
import java.awt.event.*;
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 Thread game;
private volatile boolean running = false;
//Game Objects
World world;
public GamePanel(){
world = new World();
setPreferredSize(gameDim);
setBackground(Color.WHITE);
setFocusable(true);
requestFocus();
//Handle all key inputs from user
addKeyListener(new KeyAdapter(){
#Override
public void keyPressed(KeyEvent e){
}
#Override
public void keyReleased(KeyEvent e){
}
#Override
public void keyTyped(KeyEvent e){
}
});
}
public void run(){
while(running){
gameUpdate();
gameRender();
paintScreen();
}
}
private void gameUpdate(){
if(running && game != null){
}
}
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);
}
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;
}
}
}
and Main.java:
package game.test.src;
import javax.swing.JFrame;
public class Main extends JFrame
{
GamePanel gp;
public Main()
{
gp = new GamePanel();
setSize(500, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
add(gp);
}
public static void main(String[] args)
{
Main m = new Main();
}
}
I have slightly modified your code, try
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class World {
private Rectangle[] blocks;
private Image[] blockImg;
private final int arrayNum = 500;
//Block Images
private Image BLOCK_GRASS, BLOCK_DIRT, BLOCK_STONE, BLOCK_SKY;
private int x, y;
public World(){
BLOCK_GRASS = new ImageIcon(Frame1.class.getResource("images/openFile.gif")).getImage();
BLOCK_DIRT = new ImageIcon(Frame1.class.getResource("images/openFile.gif")).getImage();
BLOCK_STONE = new ImageIcon(Frame1.class.getResource("images/openFile.gif")).getImage();
BLOCK_SKY = new ImageIcon(Frame1.class.getResource("images/openFile.gif")).getImage();
blocks = new Rectangle[500];
blockImg = new Image[500];
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;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if(i >= 100 && i < 125)
{
blockImg[i] = BLOCK_GRASS;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if(i >= 125 && i < 225)
{
blockImg[i] = BLOCK_DIRT;
blocks[i] = new Rectangle(x, y, 20, 20);
}
if(i >= 225 && i < 500)
{
blockImg[i] = BLOCK_STONE;
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);
}
}
}
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 Thread game;
private volatile boolean running = false;
//Game Objects
World world;
public GamePanel(){
world = new World();
setPreferredSize(gameDim);
setBackground(Color.WHITE);
setFocusable(true);
requestFocus();
//Handle all key inputs from user
addKeyListener(new KeyAdapter(){
#Override
public void keyPressed(KeyEvent e){
}
#Override
public void keyReleased(KeyEvent e){
}
#Override
public void keyTyped(KeyEvent e){
}
});
}
public void run(){
while(running){
gameUpdate();
// gameRender();
// paintScreen();
repaint();
}
}
private void gameUpdate(){
if(running && game != null){
}
}
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);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
gameRender();
paintScreen(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;
}
}
}
class Main extends JFrame
{
GamePanel gp;
public Main()
{
gp = new GamePanel();
setSize(500, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(gp);
setResizable(false);
setVisible(true);
}
public static void main(String[] args)
{
Main m = new Main();
}
}