I'm having an issue instantiating a class in Java, essentially it generates a new world every tick, which is a bit frustrating when the program runs.
Whereas all I need to do is instantiate it then access a variable inside the class.
Here's the code:
Background.java
public class Background extends UserView {
private BufferedImage bg;
private static Game game;
public Background(World w, int width, int height) {
super(w, width, height);
try {
bg = ImageIO.read(new File("data/background.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void paintBackground(Graphics2D g) {
super.paintBackground(g);
game = new Game();
g.drawImage(bg, 0, 0, this);
int level = game.getLevel();
g.drawString("Level: " + level, 25, 25);
}
}
Game.java
public Game() {
// make the world
level = 1;
world = new Level1();
world.populate(this);
// make a view
view = new Background(world, 500, 500);
// uncomment this to draw a 1-metre grid over the view
// view.setGridResolution(1);
// display the view in a frame
JFrame frame = new JFrame("Save the Princess");
// quit the application when the game window is closed
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
// display the world in the window
frame.add(view);
// don't let the game window be resized
frame.setResizable(false);
// size the game window to fit the world view
frame.pack();
// make the window visible
frame.setVisible(true);
// get keyboard focus
frame.requestFocus();
// give keyboard focus to the frame whenever the mouse enters the view
view.addMouseListener(new GiveFocus(frame));
controller = new Controller(world.getPlayer());
frame.addKeyListener(controller);
// start!
world.start();
}
/** Run the game. */
public static void main(String[] args) {
new Game();
}
Any help would be appreciated! Thank you!
Well you probably need to think about the class concept nad its dependencies, but this is the easiest and fastest approach in your case to keep only one instance of Game :
public class Background extends UserView {
private BufferedImage bg;
private static Game game = new Game();
public Background(World w, int width, int height) {
super(w, width, height);
try {
bg = ImageIO.read(new File("data/background.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void paintBackground(Graphics2D g) {
super.paintBackground(g);
g.drawImage(bg, 0, 0, this);
int level = game.getLevel();
g.drawString("Level: " + level, 25, 25);
}
}
If you add more code and say what you want and what you get, we can say you more about it.
Related
public class bioscope extends Component{
static int width;
static int height;
public void paint(Graphics g){
try {
BufferedImage crow = ImageIO.read(new File("photos/houseCrow.jpg"));
this.width = crow.getWidth();
this.height = crow.getHeight();
System.out.println(this.height);
System.out.println(this.width);
g.drawImage(crow, 0, 0, null);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Bioscope: Have a peek!");
frame.getContentPane().add(new bioscope());
frame.setVisible(true);
frame.setSize(bioscope.width, bioscope.height);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setResizable(false);
System.out.println(bioscope.height);
System.out.println(bioscope.width);
}
}
Output window has zero height and width, which is frustrating but still seems explicable. What stuns me is the output of println commands. I expected this to be a four line output: 492,640,492,640. But it prints out 0,0 first, and apparently halts. But go fullscreen, and 492,640 will be appended at the printout! Now you-know-who would invoke println every time you go fullscreen, and another 492,640 would be appended. Sort of similar appendings will occur if you minimize or try to resize JFrame window.
Why this would happen, and why JFrame window wasn't of dimensions 492,640 at the first place? The image was attached successfully, though, as could be seen if I resized the window.
I'm not sure if you expect your two static fields width and height to have any effect on the actual dimensions of the component, or if you're just using them for debugging. The static fields you have declared shadow the width and height fields in Component. It would be more appropriate to use getWidth() and getHeight() to track the actual values used by the super class.
It prints 0, 0 first because the static fields are not initialized until the first paint. The paint method is only called when the frame is redrawn, which is why you see the log line every time you change the size of the window.
Try this:
public class bioscope extends JComponent {
transient BufferedImage crow;
public bioscope() {
try {
crow = ImageIO.read(new File("photos/houseCrow.jpg"));
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
setPreferredSize(new Dimension(crow.getWidth(), crow.getHeight()));
}
public void paint(Graphics g){
g.drawImage(crow, 0, 0, null);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Bioscope: Have a peek!");
bioscope bioscope = new bioscope();
frame.getContentPane().add(bioscope);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
frame.setResizable(false);
}
}
I'm trying to learn to program my first game and I would like to understand correctly every step I make. I'll face double buffering and other things later.
I'm just trying to load an image in the game loop.
I have two classes. The first it's just a jframe calling the start method.
I wonder if there is some ugly code, in here (I think so).
So, why are my images not showing up?
public class myPanel extends JPanel implements Runnable{
//FIELDS
public static int WIDTH = 1024;
public static int HEIGHT = WIDTH / 16 * 9;
private BufferedImage bg;
private BufferedImage charac;
private boolean running;
private Thread t1;
private int startposX = WIDTH / 2;
private int startposY = HEIGHT / 2;
private int cordX = startposX;
private int cordY = startposY;
int speed = 50;
//METHODS
public synchronized void start (){
running = true;
t1 = new Thread (this);
t1.start();
}
public synchronized void stop (){
running = false;
try {
t1.join();
System.out.println("The game stopped");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//INIT
public myPanel(){
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
requestFocus();
addKeyListener(this);
}
//MAIN RUN METHOD
public void run(){
while (running){
load();
System.out.println("The game runs");
repaint();
}
}
//PAINT WITH GRAPHICS METHOD
public void paint (Graphics g){
super.paint(g);
g.drawImage(bg, 0, 0, this);
g.drawImage(charac, 110, 280, this);
}
//LOAD IMAGES IN MEMORY
public void load (){
try {
String path1 = "res/bg.png";
bg = ImageIO.read(new File (path1));
String path2 = "res/charac.png";
charac = ImageIO.read(new File (path2));
} catch (IOException e) {
e.printStackTrace();
}
}
So, I did some testing about paint vs paintcomponent and I just saw that the first draws on top of the jpanel background. Anyway, I can't still see anything changing the lines to
public void run(){
while (running){
load();
System.out.println("The game runs");
}
}
//PAINT WITH GRAPHICS METHOD
public void paintComponent (Graphics g){
super.paint(g);
g.drawImage(bg, 0, 0, null);
g.drawImage(charac, 110, 280, null);
}
//LOAD IMAGES METHOD AS ABOVE
And yes, I've added the panel to the frame, here is the other class
public class Game {
public static void main (String [] args){
JFrame frame = new JFrame();
frame.setIgnoreRepaint(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new myPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
myPanel game = new myPanel();
game.start();
}
Ive got a JFrame and set the LayoutManager to BorderLayout and then proceeded to add my JLabel with an image. However when i resize the frame the JLabel doesnt resize. I have not added any components to North, S, E and so on. I was hoping to simply have the image inside the label fill up the entire frame leaving my menu in tact of course.
Forgive me if this seems arrogant, but I have nothing else to go on.
I did a quick sample
See the red line around the image, that's the JLabel's border. As you can see, the label is been re-sized to fill the entire area.
This is the code I used to produce the sample
public class LayoutFrame extends JFrame {
public LayoutFrame() throws HeadlessException {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Image image = null;
URL url = getClass().getResource("/layout/issue78.jpg");
try {
image = ImageIO.read(url);
} catch (IOException ex) {
ex.printStackTrace();
}
JLabel label = new JLabel(new ImageIcon(image));
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
label.setBorder(new LineBorder(Color.RED, 4));
setLayout(new BorderLayout());
add(label);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
LayoutFrame frame = new LayoutFrame();
frame.setSize(200, 200);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
}
Obviously, you'll need to supply your own image ;).
Don't forget, the label WON'T scale the content for you, if that's your goal, you'll need to implement your own component to achieve this.
If you're still having problems, I would suggest (in the absence of further evidence) that your label may not be in the container you think it is or the containers layout manager is not what you think it is.
UPDATE
I don't know why you're having issues with components going missing or issues with you menu. Are mixing heavy and light weight components??
Sample with menu bar
After reading your question a little closer, I've devised a simple resizing image pane sample. For speed, I've relied on my libraries, but it should be reasonably easy to implementation your own code in place of my calls
public class ImagePane extends JPanel {
protected static final Object RESIZE_LOCK = new Object();
private BufferedImage image;
private BufferedImage scaledImage;
private Timer resizeTimer;
public ImagePane() {
URL url = getClass().getResource("/layout/issue78.jpg");
try {
image = ImageIO.read(url);
} catch (IOException ex) {
ex.printStackTrace();
}
resizeTimer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Simple thread factory to start a slightly lower
// priority thread.
CoreThreadFactory.getUIInstance().execute(new ResizeTask());
}
});
resizeTimer.setCoalesce(true);
resizeTimer.setRepeats(false);
}
#Override
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
resizeTimer.restart();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if (scaledImage != null) {
// This simply returns a rectangle that takes into consideration
//the containers insets
Rectangle safeBounds = UIUtilities.getSafeBounds(this);
System.out.println("scaledImage = " + scaledImage.getWidth() + "x" + scaledImage.getWidth());
int x = ((safeBounds.width - scaledImage.getWidth()) / 2) + safeBounds.x;
int y = ((safeBounds.height - scaledImage.getHeight()) / 2) + safeBounds.y;
g2d.drawImage(scaledImage, x, y, this);
}
}
protected class ResizeTask implements Runnable {
#Override
public void run() {
synchronized (RESIZE_LOCK) {
if (image != null) {
int width = getWidth();
int height = getHeight();
System.out.println("width = " + width);
System.out.println("height = " + height);
// A simple divide and conquer resize implementation
// this will scale the image so that it will fit within
// the supplied bounds
scaledImage = ImageUtilities.getScaledInstanceToFit(image, new Dimension(width, height), ImageUtilities.RenderQuality.High);
System.out.println("scaledImage = " + scaledImage.getWidth() + "x" + scaledImage.getWidth());
repaint(); // this is one of the few thread safe calls
}
}
}
}
}
Best option is to sub class ImageIcon and override its paintIcon method to simply paint the image using the Graphics.paint( x, y, width, height ...).
im trying to set a background image on a JPanel that resizes with the panel. I have no problem in showing the picture, but as soon as I use:
background = background.getScaledInstance(300, -1, Image.SCALE_SMOOTH );
nothing is shown. Any ideas on why?
The code:
import javax.swing.*;
import java.awt.*;
public class LoginJPanel extends JPanel
{
private Image background;
public LoginJPanel()
{
super();
background = new ImageIcon("C:\\ASYS\\Stories\\Authentication UI\\AVDsplashscreen_tiny.jpg").getImage();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
background = background.getScaledInstance(300, -1, Image.SCALE_SMOOTH );
g.drawImage(background, 0, 0, this);
}
public static void main (String[] args)
{
LoginJPanel ip = new LoginJPanel();
JFrame jf = new JFrame ();
jf.setLayout (new BorderLayout ());
jf.add (ip, BorderLayout.CENTER);
jf.setSize (1000, 600);
jf.setLocation (150, 150);
jf.setVisible (true);
jf.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
}
}
In the end what I made is (as suggested by the comments) to move the scaling outside the paint method. I created a public method which is called from the parent components to notify the panel about the new size, and scale the picture acording to that:
public void initSize(int _width, int _height)
{
int h = background.getHeight(null);
int w = background.getWidth(null);
if (w - _width > h - _height)
{
scaleVertically(_width, _height);
}
else
{
scaleHorizontally(_width, _height);
}
}
I guess I should do this on some listener because this is not very elegant, but I didn't know how to do so.
I am writing a 2D game with Swing. For the menu I use JButtons and now I want to use a JPasswordField. The problem is: If I try to write something in it, the programme crashes.
I located the error to this single line of code:
frame.getLayeredPane().paintComponents(graphics);
The password field is not painted properly and the programme crashes. But if I don't use this line, no component does show up. I think this is because I use double buffering, but I need this for the game itself.
The JFrame is created here:
public void createFrame() {
RepaintManager.setCurrentManager(new RepaintManager() {
#Override
public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {}
#Override
public void addInvalidComponent(final JComponent invalidComponent) {}
#Override
public void markCompletelyDirty(final JComponent aComponent) {}
#Override
public void paintDirtyRegions() {}
});
frame = new JFrame("Bubble Trouble");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
maximizeFrame(getFirstCompatibleMode(displayModes));
//setFullScreen(getFirstCompatibleMode(displayModes));
frame.setResizable(false);
frame.setUndecorated(true);
frame.setIgnoreRepaint(true);
frame.setVisible(true);
((JComponent) frame.getContentPane()).setOpaque(false);
JPanel panel = new JPanel();
main.getComponentHandler().initComponents(panel);
main.getKeyHandler().registerKeys(main.getComponentHandler().getPanel());
panel.setOpaque(false);
panel.addMouseListener(main.getMouseListener());
frame.getContentPane().add(panel);
frame.createBufferStrategy(2);
}
This method is called to repaint and so refresh the game:
public void draw() {
Graphics graphics = null;
JFrame frame = screenHandler.getFrame();
BufferStrategy bufferStrategy = frame.getBufferStrategy();
try {
graphics = (Graphics) bufferStrategy.getDrawGraphics();
switch(main.getStatus()) {
case MENU_MAIN: drawMainMenu(graphics); break;
case MENU_GAME: drawGameMenu(graphics); break;
case GAME: drawGame(graphics); break;
case LEVELCHANGE: drawLevelChange(graphics); break;
case SCORE: drawScore(graphics); break;
}
drawHertz(graphics);
graphics.translate(frame.getInsets().left, frame.getInsets().top);
frame.getLayeredPane().paintComponents(graphics);
if (!bufferStrategy.contentsLost())
bufferStrategy.show();
} catch (IllegalStateException e) {}
finally {
if (graphics != null) graphics.dispose();
}
Toolkit.getDefaultToolkit().sync();
Thread.yield();
}