I'm trying to set the dimensions for this game i want to create. The error is at while(running); I went over it for an hour but i can't seem to catch the error. I'm using NetbeansIDE also setPreserredSize (new Dimension(WIDTH, HEIGHT)); gives me an error, it is asking to Create a method " setPrefferedSize(java.awt.Dimension)"in.com.francesc.game.Game
private void setPreserredSize(Dimension dimension) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
when i run it i get this error
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - illegal start of type
at com.francescstudio.game.Game.<init>(Game.java:67)
at com.francescstudio.game.Start.main(Start.java:16)
Java Result: 1
heres all the code
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
/**
*
* #author francesc
*/
public class Game extends JPanel implements KeyListener, Runnable {
public static final long SerialVersionUID = 1L;
public static final int WIDTH = 400;
public static final int HEIGHT = 630;
public static final Font main = new Font("Bebas Nue Regular", Font.PLAIN, 28);
private Thread game;
private boolean running;
private BufferedImage Image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private long startTime;
private long elapse;
private boolean set;
public Game() {
setFocusable(true);
setPreserredSize (new Dimension(WIDTH, HEIGHT));
addKeyListener(this);
}
private void update() {
}
private void render() {
Graphics2D g = (Graphics2D) Image.getGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, WIDTH, HEIGHT);
// render board
g.dispose();
Graphics2D g2d = (Graphics2D) getGraphics();
g2d.drawImage(Image, 0, 0, null);
g2d.dispose();
}
#Override
public void run() {
}
int fps = 0, update = 0;
long fpsTimer = System.currentTimeMillis();
double nsPerUpdate = 1000000000.0 / 60;
// last update time in nano seconds
double then = System.nanoTime();
double unprocessed = 0;
while (running){
boolean shouldRender = false;
double now = System.nanoTime();
unprocessed += (now - then) / nsPerUpdate;
then = now;
// update queque
while (unprocessed >= 1) {
update++;
update();
unprocessed--;
shouldRender = true;
}
// render
if (shouldRender) {
fps++;
render();
shouldRender = false;
} else {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public synchronized start(){
if(running)return;
running = true;
game = new Thread (this, "game");
game.start();
}
public synchronized stop (){
if(!running) return;
running = false;
System.exit(0);
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
Your problem is while (running) {} isn't inside of a method, you defined it in the class where it will never get called.
EDIT:
Your code should look something a little more like this
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
/**
*
* #author francesc
*/
public class Game extends JPanel implements KeyListener, Runnable {
public static final long SerialVersionUID = 1L;
public static final int WIDTH = 400;
public static final int HEIGHT = 630;
public static final Font main = new Font("Bebas Nue Regular", Font.PLAIN, 28);
private Thread game;
private boolean running;
private BufferedImage Image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private long startTime;
private long elapse;
private boolean set;
public Game() {
setFocusable(true);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
addKeyListener(this);
}
private void update() {}
private void render() {
Graphics2D g = (Graphics2D) Image.getGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, WIDTH, HEIGHT);
// render board
g.dispose();
Graphics2D g2d = (Graphics2D) getGraphics();
g2d.drawImage(Image, 0, 0, null);
g2d.dispose();
}
#Override
public void run() {
int fps = 0, update = 0;
long fpsTimer = System.currentTimeMillis();
double nsPerUpdate = 1000000000.0 / 60;
// last update time in nano seconds
double then = System.nanoTime();
double unprocessed = 0;
while (running) {
boolean shouldRender = false;
double now = System.nanoTime();
unprocessed += (now - then) / nsPerUpdate;
then = now;
// update queque
while (unprocessed >= 1) {
update++;
update();
unprocessed--;
shouldRender = true;
}
// render
if (shouldRender) {
fps++;
render();
shouldRender = false;
} else {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public synchronized start(){
if(running)return;
running = true;
game = new Thread (this, "game");
game.start();
}
public synchronized stop (){
if(!running) return;
running = false;
System.exit(0);
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
Related
I am a hobbyist attempting to implement some classics in Java 2D. I have problems getting some background images to scroll properly. Main problem seems to be the occurence of what I believe is called Tearing, ie old parts of "frames" are displayed giving a flickering effect in some parts of the image. Google tells me that it is probably related to missing VSYNC in windowed Java applications, and that it is impossible/very difficult to fix completely. However before giving up I thought to try asking here.
I have assembeled the code below as a bare bone example to illustrate the problem.
Any help of improving this code to reduce the Tearing/flickering would be much appreciated.
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class ScrollTest {
private static int WIDTH = 320, HEIGHT = 240;
public static void main(String[] args) {
//System.setProperty("sun.java2d.opengl","True"); //Does not seem to make any difference
new ScrollTest().run(WIDTH, HEIGHT, 4, 1, "ScrollTest");
}
private boolean isRunning;
protected JFrame window;
protected Canvas canvas;
private BufferStrategy bs;
private int FPS = 100;
private long targetTime = 1000 / FPS;
protected int width;
protected int height;
protected float scale;
protected float aspect;
protected String title;
protected BufferedImage screenImage;
private BufferedImage bgImage;
private int bgTop;
private float offsetX;
public void run(int width, int height, float scale, float aspect, String title) {
this.width = width;
this.height = height;
this.scale = scale;
this.aspect = aspect;
this.title = title;
isRunning = false;
try {
init();
isRunning = true;
gameLoop();
}
finally {
lazilyExit();
}
}
public void init() {
canvas = new Canvas();
canvas.setPreferredSize(new Dimension((int)(width*scale), (int)(height*scale*aspect)));
window = new JFrame();
window.getContentPane().add(canvas);
window.setResizable(false);
window.setTitle(title);
window.pack();
window.setLocationRelativeTo(null);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
canvas.createBufferStrategy(3);
bs = canvas.getBufferStrategy();
screenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//bgImage = loadBImage("res/res_DoubleDragon/Area 1_C_crop.png");
try {
bgImage = toCompatibleImage(ImageIO.read(new URL("https://spritedatabase.net/files/arcade/603/Background/Area1.png")));
} catch (Exception ex) {
ex.printStackTrace();
}
bgTop = HEIGHT-bgImage.getHeight(null)+20;
}
public BufferedImage loadBImage(String filename)
{
try {
return toCompatibleImage(ImageIO.read(new File(filename)));
} catch (IOException e) {
System.out.println("Image file not found");
return null;
}
}
public void gameLoop() {
long timestamp;
long usedTime;
long sleepTime;
long elapsedTime=0;
while (isRunning)
{
timestamp = System.nanoTime();
update(elapsedTime);
System.out.println(elapsedTime);
Graphics2D g = (Graphics2D)screenImage.getGraphics();
draw(g);
g.dispose();
Graphics2D g2 = (Graphics2D) bs.getDrawGraphics();
g2.scale(scale,scale*aspect);
g2.drawImage(screenImage,0,0,null);
bs.show();
g2.dispose();
usedTime = System.nanoTime() - timestamp;
sleepTime = targetTime - usedTime / 1000000;
if(sleepTime < 0) sleepTime = 5;
try {
Thread.sleep(sleepTime);
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
elapsedTime=(System.nanoTime()-timestamp) / 1000000;
}
}
public void update(long elapsedTime) {
offsetX -= .05f*elapsedTime;
offsetX = Math.min(offsetX, 0);
offsetX = Math.max(offsetX, WIDTH - bgImage.getWidth(null));
}
public void draw(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.drawImage(bgImage, Math.round(offsetX), bgTop, null);
}
public void stop() {
isRunning = false;
}
/**
Exits the VM from a daemon thread. The daemon thread waits
2 seconds then calls System.exit(0). Since the VM should
exit when only daemon threads are running, this makes sure
System.exit(0) is only called if neccesary. It's neccesary
if the Java Sound system is running.
*/
public void lazilyExit() {
Thread thread = new Thread() {
public void run() {
// first, wait for the VM exit on its own.
try {
Thread.sleep(2000);
}
catch (InterruptedException ex) { }
// system is still running, so force an exit
System.exit(0);
}
};
thread.setDaemon(true);
thread.start();
}
private static final GraphicsConfiguration GFX_CONFIG = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
public static BufferedImage toCompatibleImage(BufferedImage image) {
/*
* if image is already compatible and optimized for current system settings, simply return it
*/
if (image.getColorModel().equals(GFX_CONFIG.getColorModel())) {
return image;
}
System.out.println("incompatible image");
// image is not optimized, so create a new image that is
final BufferedImage new_image = GFX_CONFIG.createCompatibleImage(image.getWidth(), image.getHeight(), image.getTransparency());
// get the graphics context of the new image to draw the old image on
final Graphics2D g2d = (Graphics2D) new_image.getGraphics();
// actually draw the image and dispose of context no longer needed
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
// return the new optimized image
return new_image;
}
}
My laptop's resolution is 1920x1080. I recently opened my game from another laptop with 1360x768. The JPanel changed size and half of the game was outside the screen. I understand that my game dimensions x 4 are bigger than the second laptop's resolution. But, is there a way to make it adjust to every screen? Any ideas?
package Main;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import GameState.GameStateManager;
import Handlers.Keys;
#SuppressWarnings("serial")
public class GamePanel extends JPanel implements Runnable, KeyListener {
// dimensions
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 4;
// game thread
private Thread thread;
private boolean running;
private int FPS = 60;
private long targetTime = 1000 / FPS;
// image
private BufferedImage image;
private Graphics2D g;
// game state manager
private GameStateManager gsm;
// other
private boolean recording = false;
private int recordingCount = 0;
private boolean screenshot;
public GamePanel() {
super();
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
addKeyListener(this);
thread.start();
}
}
private void init() {
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
running = true;
gsm = new GameStateManager();
}
public void run() {
init();
long start;
long elapsed;
long wait;
// game loop
while (running) {
start = System.nanoTime();
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
if (wait < 0) wait = 5;
try {
Thread.sleep(wait);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void update() {
gsm.update();
Keys.update();
}
private void draw() {
gsm.draw(g);
}
private void drawToScreen() {
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);
g2.dispose();
if (screenshot) {
screenshot = false;
try {
java.io.File out = new java.io.File("screenshot " + System.nanoTime() + ".gif");
javax.imageio.ImageIO.write(image, "gif", out);
} catch (Exception e) {
}
}
if (!recording)
return;
try {
java.io.File out = new java.io.File("C:\\out\\frame" + recordingCount + ".gif");
javax.imageio.ImageIO.write(image, "gif", out);
recordingCount++;
} catch (Exception e) { }
}
public void keyTyped(KeyEvent key) { }
public void keyPressed(KeyEvent key) {
if (key.isControlDown()) {
if (key.getKeyCode() == KeyEvent.VK_R) {
recording = !recording;
return;
}
if (key.getKeyCode() == KeyEvent.VK_S) {
screenshot = true;
return;
}
}
Keys.keySet(key.getKeyCode(), true);
}
public void keyReleased(KeyEvent key) {
Keys.keySet(key.getKeyCode(), false);
}
}
You should be basing the size of game on the resolution of the screen.
You can easily get the resolution by using:
System.out.println(Toolkit.getDefaultToolkit().getScreenSize());
The next issue is are you using a full screen for your game or is you game displayed in a frame. If you are using a frame with decorations, then you also need to account for the size of the title bar and borders around the frame. This information can only be accessed after the frame has been packed.
frame.pack();
System.out.println("Frame Insets : " + frame.getInsets() );
So now the size of your game board would be the size of the screen less the insets of the frame decorations.
I was trying to follow these tutorials http://zetcode.com/tutorials/javagamestutorial/animation/ and none of the three examples on that page seem to be working for me. One of them uses a swing timer, one uses the utility timer, and the last and supposedly most effective and accurate according to the page uses a thread to animate.
I will show you the one using the thread, since it is the way that I think I will be doing thing's when using animation for making games.
ThreadAnimationExample.java (in the tutorial it is called star.java but obviously that wont work)
import java.awt.EventQueue;
import javax.swing.JFrame;
public class ThreadAnimationExample extends JFrame {
public ThreadAnimationExample() {
add(new Board());
setTitle("Star");
pack();
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame ex = new ThreadAnimationExample();
ex.setVisible(true);
}
});
}
}
Board.java (the main class)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Board extends JPanel
implements Runnable {
private final int B_WIDTH = 350;
private final int B_HEIGHT = 350;
private final int INITIAL_X = -40;
private final int INITIAL_Y = -40;
private final int DELAY = 25;
private Image star;
private Thread animator;
private int x, y;
public Board() {
loadImage();
initBoard();
}
private void loadImage() {
ImageIcon ii = new ImageIcon("star.png");
star = ii.getImage();
}
private void initBoard() {
setBackground(Color.BLACK);
setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
setDoubleBuffered(true);
x = INITIAL_X;
y = INITIAL_Y;
}
#Override
public void addNotify() {
super.addNotify();
animator = new Thread(this);
animator.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawStar(g);
}
private void drawStar(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(star, x, y, this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
private void cycle() {
x += 1;
y += 1;
if (y > B_HEIGHT) {
y = INITIAL_Y;
x = INITIAL_X;
}
}
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (true) {
cycle();
repaint();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0) {
sleep = 2;
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("Interrupted: " + e.getMessage());
}
beforeTime = System.currentTimeMillis();
}
}
}
If you are using Eclipse you should create a source folder and add that image to the source folder. Then you could use this:
ImageIcon ii = new ImageIcon( getClass().getResource("/imageName.png") );
For some reason, my program can't find an image. I've tried absolutely everything and made sure the file path is exact. It worked fine in my previous game but now it just won't find the image at all.
Entity class
package Entities;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Entity
{
public double x, y, width, height, dx, dy;
public BufferedImage image;
public Entity(String s)
{
try
{ //error occurs here
image = ImageIO.read(getClass().getResourceAsStream(s));
}
catch (IOException e)
{
e.printStackTrace();
}
width = image.getWidth();
height = image.getHeight();
}
public void update()
{
x += dx;
y += dy;
}
public void draw(Graphics2D g)
{
g.drawImage(image, (int)x, (int)y, null);
}
}
GamePanel class
package Main;
//import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import Entities.Entity;
#SuppressWarnings("serial")
public class GamePanel extends JPanel implements Runnable, KeyListener
{
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 2;
//game thread
private Thread thread;
private boolean running;
private int fps = 60;
private long targetTime = 1000/fps;
//image
private BufferedImage image;
private Graphics2D g;
//test
public Entity e;
public GamePanel()
{
super();
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setFocusable(true);
requestFocus();
}
public void addNotify()
{
super.addNotify();
if(thread == null)
{
thread = new Thread(this);
addKeyListener(this);
thread.start();
}
}
public void init()
{
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
running = true;
e = new Entity("Resources/Test/test.png");
}
#Override
public void keyPressed(KeyEvent key)
{
//p1.keyPressed(key.getKeyCode());
}
#Override
public void keyReleased(KeyEvent key)
{
//p1.keyReleased(key.getKeyCode());
}
#Override
public void keyTyped(KeyEvent arg0)
{
}
#Override
public void run()
{
init();
long start;
long elapsed;
long wait;
//game loop
while(running)
{
start = System.nanoTime();
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed/1000000;
if(wait < 0)
{
wait = 5;
}
try
{
Thread.sleep(wait);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
private void drawToScreen()
{
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);
g2.dispose();
}
private void draw()
{
//e.draw(g);
}
private void update()
{
}
}
This is the error
Exception in thread "Thread-2" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at Entities.Entity.<init>(Entity.java:19)
at Main.GamePanel.init(GamePanel.java:67)
at Main.GamePanel.run(GamePanel.java:93)
at java.lang.Thread.run(Unknown Source)
A path Resources/Test/test.png suggest a relative path from the location of the class reference used to try and load it.
Since you are using your Entity class to try and load the image, and Entity resides in the Entities package, this will generate an absolute path (from the context of the class path) of /Entities/Resources/Test/test.png, which is obviously incorrect.
Try using /Resources/Test/test.png instead (assuming the Resources resides at the top of the path tree, for example...
+ Resources
+ Test
- test.png
+ Entities
- Entity
+ Main
- GamePanel
I believe my code will describe what I wrote, But the problem is, is that When I run it, I get that infamous "Exception in thread "Animator" java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0" Error. I have searched for answers but have yet to find why this is happening.
package com.shparki.TowerDefense;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
//==================== PROGRAM VARIABLES ====================//
private static final int WIDTH = 300;
private static final int HEIGHT = WIDTH / 16 * 9;
private static final int SCALE = 4;
private static final int TARGET_FPS = 45;
private static final int PERIOD = 1000 / TARGET_FPS;
private boolean debug = true;
private volatile boolean running = false;
private volatile boolean gameOver = false;
private volatile boolean paused = false;
private Thread animator;
private TowerDefense frame;
private double currentFPS;
//==================== PROGRAM METHODS ====================//
public GamePanel(TowerDefense td){
frame = td;
setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setVisible(true);
}
public void addNotify(){
super.addNotify();
startGame();
}
public void startGame(){
if (!running && animator == null){
animator = new Thread(this, "Animator");
animator.start();
}
}
public void stopGame(){
running = false;
}
public void run(){
running = true;
Long beforeTime, timeDiff, sleepTime;
while(running){
beforeTime = System.currentTimeMillis();
update();
render();
paintScreen();
timeDiff = System.currentTimeMillis() - beforeTime;
sleepTime = PERIOD - timeDiff;
if (sleepTime <= 0){
sleepTime = 5L;
}
currentFPS = (1000 / ( timeDiff + sleepTime ));
try{
Thread.sleep(sleepTime);
} catch (InterruptedException ex) { ex.printStackTrace(); }
}
System.exit(0);
}
//==================== DRAWING METHODS ====================//
private Graphics dbg;
private Image dbImage;
public void paintComponenet(Graphics g){
super.paintComponent(g);
if (dbImage != null){
g.drawImage(dbImage, 0, 0, null);
}
}
public 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 ex) { System.out.println("Graphics context error: " + ex); }
}
public void doubleBuffer(){
if (dbImage == null){
dbImage = createImage(getWidth(), getHeight());
if (dbImage == null){
System.out.println("dbImage is null");
return;
} else {
dbg = dbImage.getGraphics();
}
}
}
//==================== UPDATE METHODS ====================//
public void update(){
}
//==================== RENDER METHODS ====================//
public void render(){
doubleBuffer();
Graphics2D g2d = (Graphics2D) dbg;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
}
And this is my frame class:
package com.shparki.TowerDefense;
import java.awt.BorderLayout;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JFrame;
public class TowerDefense extends JFrame implements WindowListener{
public TowerDefense(String name){
super(name);
setResizable(false);
setLayout(new BorderLayout());
add(new GamePanel(this), BorderLayout.CENTER);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public void windowActivated(WindowEvent arg0) { }
public void windowClosed(WindowEvent arg0) { }
public void windowClosing(WindowEvent arg0) { }
public void windowDeactivated(WindowEvent arg0) { }
public void windowDeiconified(WindowEvent arg0) { }
public void windowIconified(WindowEvent arg0) { }
public void windowOpened(WindowEvent arg0) { }
public static void main(String[] args){
new TowerDefense("Tower Defense Game");
}
}
The JFrame has not been packed then the height and widths are requested here in GamePanel
dbImage = createImage(getWidth(), getHeight());
resulting in 0x0 dimension for the JPanel.
The reason is that Swing invokes addNotify (where startGame resides) almost immediately once the parent component has been set for the component.
You could invoke startGame explicitly after pack has been called.
add(gamePanel, BorderLayout.CENTER);
pack();
gamePanel.startGame();