What does a Graphics object actually represents? - java

Ok, I'm not even sure if that is the right question to ask.
I've been confused by what is A Graphics object for a while now, I used to think that it is simplly a tool to use to change colors and draw to specific container(ie JFrame, JPanel).
However, I've been studying buffering(triple, double, flipping...etc) and how it works for 3 days now, and my confusion has only increased. for instance, why when we need to draw to the buffer(ie BufferStrategy, BufferedImage) we get its own graphics object to draw to it and then we project it to the screen? does the Graphics Object represent the drawing surface (ie the JPanel it self if we're using one to draw custom painting via JPanel#paintComponent(Graphics g)) ?
and so when we're getting the graphics object of a buffer, do we actually get its drawing surface to paint on?
Please somebody explain, any help is appreciated
Thanks

From the API:
A Graphics object encapsulates state information needed for the basic
rendering operations that Java supports. This state information
includes the following properties:
The Component object on which to draw.
A translation origin for rendering and clipping coordinates.
The current clip.
The current color.
The current font.
The current logical pixel operation function (XOR or Paint).
The current XOR alternation color (see setXORMode(java.awt.Color)).
So a Graphics instance contains information about WHERE to draw (a component) as well as HOW to draw it (a color, font, etc). It then gives you methods so you can tell it WHAT to draw (a rectangle, circle, text, etc).

Related

Is Graphics2D.draw performed if the Shape is offscreen?

I'm currently working on some Rendering Code, and I wondered if Graphics2D.draw(Shape) is performed the exact same way onscreen as offscreen.
If it is, is there a way to check if my shape (a Line2D) is onscreen?
Depends on what you mean by "exactly the same way".
As far as calls to draw-something() from your code are concerned, they take place normally. What is different, somewhere in the rendering chain the condition that the shape does not actually fall into the actual rendering area is detected and no pixels are actually output for the shape.
As for detecting if something is "on screen", that depends what you define the screen as. Reasonably you would define it as the area described by your Graphics object (that may well be only part of the screen, or completely off screen, heck it could be a printer!).
Provided you have not changed the clip area of a Graphics instance, getClipBounds() gives you the rectangle where graphics are actually rendered. If your graphics comes from a Swing component, you can also substitute the components dimensions for the rendering area.
Once you have the actual Rectangle, you can make use of the methods provided by Shape to detect collisions (contains(), intersects() etc.).

Relationship between BufferedImage, Graphics, and Canvas for games

I am a fairly new programmer and I am trying to make a very basic game using Java where you just move a sprite around the screen. What I have accomplished so far is make a SpriteSheet class that loads in my sprite sheet and saves a BufferedImage of the spritesheet as a field of that class and a Sprite class that will get a subimage(the sprite itself) from this field and saves it as a field in the Sprite class. I've tested this and it all works like it should. I understand this may not all be typical or the "correct", efficient way of doing things. I'm ok with figuring that out on my own but my problem now is understanding the relationship between BufferedImage, Graphics, and Canvas. I saw a tutorial where a guy saved his sprite as a BufferedImage and used this to create a Graphic. He then painted this Graphic onto a Canvas and added the Canvas to his JFrame. He also fit a BufferStrategy in there somehow connected to his Graphics, and I don't understand that at all. Whenever I try to adapt his method for my purposes, it never works. I've looked over the javadocs countless times for these things and I get them individually, but I just can't seem to understand how they fit together to accomplish my goals.
So in short: can anyone explain how BufferedImage, Graphics, and Canvas all fit together in the context of displaying a sprite for a 2D game, and how is a BufferStrategy used? Appropriate and relevant methods? Will this method be appropriate for rendering moving sprites around 15 fps? etc... My problem does not come from a lack of research or lack of knlowedge necessarily but more from a lack of understanding.
Thank you very much and any advice is greatly appreciated!
BufferedImage is a Image type, which has the capacity to be modified from within the code, but, it has no means by which it can paint it self to the screen.
Canvas is a AWT (heavy weight) container which is typically used for providing activate painting access via it's BufferStrategy. This is displayed to the screen.
Graphics is a abstract graphical library designed to make it easier to perform cross platform renderering.
The Canvas, via it's BufferStragegy provides access to a Graphics instance, which allows you to paint to the Canvas (and by extension, the screen). You use this Graphics context to paint the BufferedImage
A Canvas by itself can't be displayed on the screen, it must be first contained within a window of some type, like java.awt.Frame.
Essentially, the frame shows the user the Canvas, the Canvas provides access to the graphics hardware via the BufferStrategy and Graphics context and the BufferedImage provides a generalised representation of an image/image data which can be painted to the Graphics context (of the Canvas)
Maybe you should start by having a look at the JavaDocs for Canvas, BufferStrategy, BufferStrategy and BufferCapabilities and 2D Graphics for some examples

Translucent fill in paintComponent

I am making a 2D Java game and I'd like to darken stuff in the dark areas. I was wondering if I could use alphatransparent colors in a paintComponent method. If not, does translucent PNGs work or is there effects for darkening images.
Thanks
I would create a new BufferedImage of type TYPE_INT_ARGB, edit straight into the raster data, - set the color of your choice (with desired alpha), and just draw it after everything else, in your paint method. drawImage is pretty fast. And if you want to change the darkness colors, you can set the new alpha values on the fly directly into the data array of the image.
You can use transparency/opacity in java.
Here you can find some basic info on the procedure. The important step is using an AlphaComposite object to set the alpha value of your drawing

Zoom and Pan JPanel with multiple Images drawn on it

I am drawing a tile map, where I draw a different 64x64 pixel image for every tile, and each tile object draws itself.
I also have a player object and zombie objects that also draw themselves. the player and zombie objects have their own affine transform instantiation that modify the g.drawImage I call for each one.
My question is. how would I implement a 'camera' that I can zoom and pan with, to see only the part of the map inside the JPanel?
What I would do is start with a BufferedImage which will act as the final output.
Create it so it's size is width x scale and height x scale.
Obtain a Graphics context from it using BufferedImage#createGraphics and set the context's scale accordingly, using Graphics#scale.
Then paint the output to this Graphics context, don't forget to call Graphics#dispose when you're done.
With this BufferedImage, render this to the screen. This gives you the "zoom" functionality.
For the panning, you can take a look at Java Applet Game 2D Window Scrolling for an example.

Combine two graphics objects in Java

I got two Graphics objects, is it possible to combine them into one?
The answer of Hovercraft Full of Eels is useful, but not what I meant. Say I have two Graphics objects, private Graphics gr1 and private Graphics gr2. Now, how should I merge them in the paintComponent(Graphics) method to draw them to my (for example JPanel)?
The question is not at all about images, but about mere Graphics objects. Sorry, the first paragraph was misleading.
Edit:
In response to Hovercraft Full of Eels:
If you draw in the paintComponent() method, I find it annoying everything is gone if you redraw your screen, and if you want to move something you have to save the coordinates and dimensions of everything, adjust those and get them someway in your Graphics object.
The question I asked myself was accely: What object is best suited or saving a Graphics object. A Graphics object, I thought. but the problem is that if you have (for example) two rectangles, and one moves to the left and one moves to the right you can't if you have 1 Graphics object.
My solution was multiple graphics objects, which can be transformed to simulate movement and then drawn to the screen.
#Hovercraft Full of Eels I think you (and most SO'ers) think this is not a good solution, looking at your answer.
But, an answer saying You're doing it all wrong, you'd better stop programming doesn't help me at all, so please give me an alternative.
You can draw any image into a BufferedImage by getting its Graphics context, drawing in it, and then disposing of the Graphics object. For example
// get a Graphics object from BufferedImage, img1
Graphics g = img1.getGraphics();
// use that g to draw another BufferedImage starting at x, y of 0, 0
g.drawImage(img2, 0, 0, null);
// clean up resources so as not to run out.
g.dispose();
Now img1 shows old img1 with img2 overlying it. If you want the images to be transparent, you'll need to read up on alpha composite and how to use it
Edit
Regarding your edited question:
I got two Graphics objects, is it possible to combine them into one?
The answer of Hovercraft Full of Eels is useful, but not what I meant. Say I have two Graphics objects, private Graphics gr1 and private Graphics gr2. Now, how should I merge them in the paintComponent(Graphics) method to draw it to my (for example JPanel)?
The question is not at all about images, but about mere Graphics objects. Sorry, the first paragraph was misleading.
This request is somewhat confusing to me since I think of Graphics objects as pens or paintbrushes that are used to draw something to an image or the screen. So I don't think that you draw a Graphics object to anything, but rather that you use a Graphics object as a tool to draw to something else that can display or store the graphics. You are going to have to put a lot more effort into asking your question, supplying us with enough details so that we don't have to keep guessing what it is you are trying to do. Please tell us the whole story.
Edit 2
In response to your latest edit to your question:
If you draw in the paintComponent() method, I find it annoying everything is gone if you redraw your screen, and if you want to move something you have to save the coordinates and dimensions of everything, adjust those and get them someway in your Graphics object.
The question I asked myself was accely: What object is best suited or saving a Graphics object. A Graphics object, I thought. but the problem is that if you have (for example) two rectangles, and one moves to the left and one moves to the right you can't if you have 1 Graphics object.
No, a better solution I think is to use a BufferedImage to save that which should persist. When ever you wanted to add an image to the background BufferedImage, you'd obtain the BufferedImage's Graphics object by calling getGraphics() on it, then you'd draw your image to it by using the Graphics object's drawImage(...) method, then you'd call dispose() on the BufferedImage's Graphics object so as not to lose resources.
To draw the background BufferedImage in the background, you'd call it at the top of the paintComponent(...) method, usually just after calling the super.paintComponent(...) method.
My solution was multiple graphics objects, which can be transformed to simulate movement and then drawn to the screen.
#Hovercraft Full of Eels I think you (and most SO'ers) think this is not a good solution, looking at your answer.
Yep, you guess correctly -- I believe that there are better solutions than the one you suggest.
An example of just what I'm getting at can be found in my code post in my answer to this question: changing-jpanel-graphics-g-color-drawing-line.
If you run my code, you'd see this:
To impose images, use an appropriate layout, as shown here.
To compose images, use an appropriate composite rule, as shown here.
Addendum: #HFOE is correct. An instance of Graphics or Graphics2D, sometimes called a graphics context, is a transitory means to apply rendering methods; the target device or off-screen image must exist independently. Classes implementing the Shape interface are good candidates for encapsulating information about what to render in a given context. AffineTest and GraphPanel are examples.

Categories

Resources