I am making a game with Java and LWJGL..
Basically I want to write my game's fps on the screen, but I really don't understand how i should do that.
I am thinking its something related to the Graphics class, am i right?
Graphics g = new Graphics();
g.setColor(Color.YELLOW);
g.setFont(new Font("Impact", Font.PLAIN, 20));
g.drawString(fps + " FPS", 20, 30);
g.dispose();
This code returns me an error..it says that the constructor of the graphics class isn't implemented right.
Any ideas?
To draw, you need the draw handle for the original Graphics object and not by creating a new one yourself.
As far as I can tell, for a basic game, your controlling class should be extending BasicGame which provides a render method, from which you can grab a Graphics object.
See: BasicGame and render
I imagine what you need to do is override that method, like this:
public void render(GameContainer container, Graphics g) throws SlickException {
//grab graphics g here and use it.
}
For a basic template, look here.
You can't just create new Graphics instance from scratch and hope it will draw what you want and where you want.
Graphics contexts are obtained from other graphics contexts or are
created by calling getGraphics on a component.
If you want to put sime text on the screen with LWJGL then search exact and you will find a lot of solutions. Even on youtube.
Related
I have a simple question to ask.
Is it possible to do an affine transform outside the paint/paintComponent context?
For instance, let's say i want to create a Shape made of a GeneralPath and then rotate it 45°.
Is it possible to create that object and then rotate it always in the class constructor instead of creating the object and then rotate it in the paint/paintComponent method?
Thank you very much.
UPDATE
Thank you very much for the info guys.
So today i have made a simple test as you suggested and it works.
This is with the Affine transform inside the paintComponent method, commented:
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(new Color(230, 230, 230));
g2.fill(enne.getNuvola());//enne.getNuvola(): code from an omitted class. returns a Shape of a cloud
g2.setColor(new Color(20, 20, 20));
/*
AffineTransform t = AffineTransform.getTranslateInstance(400,400);
g2.transform(t);
*/
g2.fill(rock.getRocket());
}//paintComponent
and this is the affine transform inside the class constructor of a GeneralPath
public class Rocket {
GeneralPath rocket;
public Rocket(){
rocket = new GeneralPath();
rocket.moveTo(10,10);
rocket.lineTo(15,15);
rocket.lineTo(15,50);
rocket.lineTo(5,50);
rocket.lineTo(5,15);
rocket.lineTo(10,10);
rocket.closePath();
AffineTransform t = AffineTransform.getTranslateInstance(400,400);
rocket.transform(t);
}//Rocket Costruttore
public GeneralPath getRocket(){
return this.rocket;
}
}//Rocket
But now i have another question:
Do i have to protect the current state of the current trasform also in the Rocket class like it is suggested to do for the paintComponent method in the java transforming tutorial?
Use the getTransform method to get the current transform.
Use transform, translate, scale, shear, or rotate to concatenate a transform.
Perform the rendering.
Restore the original transform using the setTransform method.
Again, thank you very much for your answers
No, the transform should be reset only to restore the state of the Graphics object, because that Graphics object could be reused by the system for other drawings. If you do the transform without a Graphics object, you don't need to worry about that.
Note for the future that you should not ask new questions by editing old questions, because this is confusing. You should post a completely new question (possibly linking your old question).
I'll start off by telling you what Im trying to do if thats OK, as Im not certain the route Im struggling with is even the best way of achieving my ends.
I have a JFrame containing two JPanels. One contains a number of buttons (buttonPanel), the other is, initially, blank (displayPane). When buttons are pressed the stuff shown in displayPanel changes. The way this is working is each press of a button creates a new object that extends JPanel and then adds that to displayPane
So all the above is working fine and dandy (although I freely admit it may not be the best way of doing it) except for one particular case.
In this particular case I need to create a JLayeredPanel and then draw a clipped image on it. JLayeredPanel because I want to draw some stuff on top of it, clipped because I only want to show part of the area (which exact part is passed to the constructor).
Now, the problem Im having is this. The only way I know to draw a clipped image is through g=thingie.getGraphics(), g.setClip(Shape shape), g.drawImage(various). However, all of that relies on being able to get graphics. But because I am assembling the object first there is no graphics object associated with the JLayeredPane (because its not displayed) so getGraphics is returning null and g.setClip() is throwing a Null Pointer Exception.
Obviously I am doing this wrong somehow and somewhere. Any help would be appreciated, sorry if the question is confusing. I tried to include as much detail as possible and now I am a little concerned I've muddied the issue. I'll keep an eye on this and clarify if required.
Warning!: Wrong answer, see below the line
Why don't you just create a new Graphics object, paint on it and then use it with the update() method?
Graphics g = new Graphics();
g.drawStuff();
thingie.update(g);
This showd be correct
As stated on the comments the previous solution was wrong but it can be done with an Double buffer, create a buffered image and draw on it, then override the paint method of the jLayeredPane pane to draw the image.
private void addStuff() {
BufferedImage bi =
new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR);
Graphics bufferedGraphics = bi.getGraphics();
//Paint stuff
bufferedGraphics.drawLine(0, 0, 50, 50);
javax.swing.JLayeredPane layered;
layered = new JLayeredPane() {
#Override
public void paint(Graphics g) {
g.drawImage(bi, 0, 0, null);
}
};
this.add(layered);
this.validate();
this.repaint();
}
I am making a Java game, and the game lags a lot when I paint out the graphics.
The way I am currently painting out the graphics is to make a BufferedImage, get the Graphics2D from it, then do a whole bunch of:
g2d.drawImage(loadedImages.getImage(),x,y,null);
After I print all of the images to the BufferedImage, I paint the BufferedImage to the screen.
There are a lot of images I paint to the BufferedImage. Is there a better way to do this that would speed up the painting time?
I do not know much about graphics and graphic cards. Should I use a graphics card? Should I paint directly to the screen? Should I use something entirely different than drawImage()?
The performance should be good if you're drawing a reasonable amount of images.
Make sure you're not creating new BufferedImages every time you draw to the screen. For example, you might have a Resources singleton in which you manage all of your images so that you only load and unload each image once.
If you really want more performance, you'll want to use OpenGL. See LWJGL, libgdx, or JOGL. You may also want to consider 2D graphics libraries like Slick.
I've found it useful to extend java.awt.Canvas and use
BufferStrategy bs;
void init() {
createBufferStrategy(2);// or 3 for triple-buffering
bs = getBufferStrategy();
}
and then the actual draw() method looks like
void draw() {
Graphics g = bs.getDrawGraphics();
g.drawImage(image, x, y, w, h, null);
// Draw more things here...
// You can also make calls like `myObject.draw(g)` and whatever
// you draw onto `g` within those calls will show up.
bs.show();
g.dispose();
}
This is what I use for drawing a lot of things. And then within each myObject.draw(g) call, there are sometimes multiple other similar calls all chained up. Most often my main draw() method has one or two for loops in it that just say for(Entity e: entities) e.draw(g); or something similar. Then the whole drawing chain is kicked off from there.
I am trying to create a pen tool using mouse listeners:
public void mouseDragged(MouseEvent e) {
imageL.setCoordinates(originalPos, e.getPoint());
imageL.repaint();
originalPos = e.getPoint();
}
The paint function in the JLabel (imageL) receives two sets of points that allow drawing a line based upon the mouse drag. The only issue is that every time the drag is performed, the new layer does not contain the line drawn from the previous mouse drag. The paint function of the JLabel is as follows:
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(drawingColour);
g2d.drawLine(originCors.x,originCors.y,endCors.x,endCors.y);
}
So essentially my question is: How do I "add" the new line to the current layer?
any help would be great,
Thanks in advance
You want to draw in a JComponent's (and JLabel extends from JComponent) paintComponent method, not the paint method unless you plan to handle all the painting of the component's borders and children. Next, you may wish to have your drawing component hold an ArrayList of Point and add Points to this array list in the mouseDragged method. Then the paintComponent method can iterate through the list and paint all the lines. If all you want to do is paint one line, then have the painting JLabel hold both points in a class field.
Michael,
For a start, in swing (a JLabel is a swing component, as apposed to the older AWT library) the recommended practice is to override the paintComponent method (not the "paint" method). See The Java Tutorials: Custom Painting for the hows & whys of it.
If you want to custom-paint a-list-of-lines then you're going to have to do just that... not just the "new" one. One way around this is to "update" an image with each new line, and then custom-paint that... this is slightly quicker as you only "paint" the each line once, at the cost of using more memory (to maintain the "backgroun image")... but this technique lends itself to "double buffering", which avoids "that flickering" you get when you draw directly to the screen. See The Java Tutorials: Working with Images for the details. It's actually pretty straight forward.
I suggest you google for "java double buffering example" (avoid Rose India, it's full of crap).
Cheers. Keith.
I'm Basically programming a simple game engine but I'm having problems with my sprites/images not appearing when they should... or at all!
I'll try and keep this as simple as possible. I have a Sprite, GameEngine and Display class. In the gameloop, I have a method that sets the new position of my Sprite (so it just sets the x and y variables). Next I call a transform method which does the following:
public void transform() {
affineTransform.setToIdentity();
affineTransform.translate(x, y);
}
Following that, I then call a draw method in the Sprite:
public void draw() {
graphics2D.drawImage(image, affineTransform, jFrame);
}
Finally, in my thread I then call repaint() on the JFrame (the Display class). My paint method for that class is as follows:
public void paint(Graphics g) {
g.drawImage(backbuffer, insets.left, insets.top, this);
}
But nothing is appearing, apart from a black screen!
I'm also getting confused between Graphics g, and Graphics2D and when to use either. (The overridden paint method uses Graphics g). For the record, I do have a Graphics2D variable in the class that is created by calling backbuffer.createGraphics();
Another thing that is confusing me is this AffineTransform... I've read the documentation but I'm still utterly confused on how and when to use it - and what exactly it seems to do. Is there any explanation in relatively simple terms?
Surely this should be working... am I missing something out here?
To answer part of your question:
From the Graphics2D JavaDoc
This Graphics2D class extends the Graphics class to provide more sophisticated control over geometry, coordinate transformations, color management, and text layout. This is the fundamental class for rendering 2-dimensional shapes, text and images on the Java(tm) platform.
Essentially, with Graphics2D you can do much more than you can with Graphics. And with a Sun JVM 1.5+, it should be safe to cast the Graphics object you get in paint() to Graphics2D
I just noticed this: For the record, I do have a Graphics2D variable in the class that is created by calling backbuffer.createGraphics();
You should make sure you're not drawing on a Graphics[2D] canvas (I'll use this term to refer to the drawable area that the Graphics[2D] object provides) that you later throw away. If you're drawing your image on a separate canvas, you should ensure that you then draw that image onto your actual display canvas.
I don't really have a good explanation of AffineTransform but maybe these will help?
http://www.javalobby.org/java/forums/t19387.html
https://secure.wikimedia.org/wikipedia/en/wiki/Affine_transformation
From Wikipedia - In general, an affine transformation is composed of linear transformations (rotation, scaling or shear) and a translation (or "shift"). Several linear transformations can be combined into a single one. Basically, you use this class to perform operations such as rotation, translation, zoom etc.