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.
Related
I'm trying to figure out if there's any way to draw images (drawRect(), drawOval(), etc.) based on if/else statements or by using an ActionListener.
I don't want to post the complete problem because this is for an assignment, but for my own scenario:
If I have a button on a JPanel named "draw rectangle" and I have the x, y, width, and height from user input, is there any way I can attach an actionListener to "draw rectangle" that could somehow draw the rectangle using those values (passed by reference?).
I know I can use paintComponent, but I can't put that into the ActionListener and it seems to do things of its own accord and not based on a specific user's actions.
I don't really have any code for this because I can't figure out how to do it at all.
If I have a button on a
JPanel named "draw rectangle" and I have the
x, y, width, and height from user input, is there any way I can attach
an actionListener to "draw rectangle" that could somehow draw the
rectangle using those values (passed by reference?).
The short answer is yes.
Generally, you'll need to save the rectangle instructions in a model, and have the JPanel redraw the model when any of the shape buttons are pressed.
Let's take your rectangle example. What do you need to know to draw a rectangle on a JPanel? You need a starting point (upper left) and an ending point (lower right). You can use a java.awt.Point to hold the starting and ending point. You can set the thickness of the line, in pixels. You can set the color of the rectangle, using a JColorChooser. You can also set the rectangle to be an outline or filled with the chosen color.
That description will be similar for a line and a triangle. A circle is a little different, with a center point and a radius. As you can see, we already have a lot of information to keep track of just with these simple geometric shapes.
Then there's the issue of the drawing surface itself. It's possible to have a drawing surface larger than your computer screen can show. You can put the drawing surface inside of a JScrollPane.
All of these things must be determined so you can build the model of your application. You do this before you build the view using Swing components and the controller using action listeners.
Making a paint-like application that works by saving mouse points in an arraylist. My idea is to have a "points" arraylist with all the previously drawn stuff, and a "temp" arraylist to get and modify the current brush stroke the user just entered. This is necessary as the user can change the color and size, so my idea is to modify the current brush stroke based off what buttons have been pressed, then add that brush stroke to the rest of the picture. I searched around StackOverflow and found some code but cant get it to work how I want to (assuming I found the right code).
#Override
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
final Graphics2D g = (Graphics2D)g1.create();
try {
g.setColor(brushColor);
for (Point point : tempArrayList){
g.fillOval(point.x, point.y, brushSize, brushSize);
}
} finally {
g.dispose();
}
The problem is that I need to clear the tempArrayList for the next brush stroke, which I can do when they change the color/size, but then it erases what was previously there. I am starting to think that I don't even need the "points" arraylist as descibed above because I was hoping that the g1 graphic would just save what the g graphic created.
I guess I just need to figure out how to add the g graphic to g1
Painting is controlled by the Swing API, there is a expectation that whenever paintComponent is called, you will repaint the entire state of the component (as part of your component might have been damaged due to some system event), so the short answer is, no, you can't...however....
You Could...
Paint to a BufferedImage instead and paint the BufferedImage when paintComponent is called
You Could...
Establish a series of "paintable" objects which contain information about what is to be painted and how it is to the painted, including the brush stroke, stroke color and fill color.
These would then be added to some kind of List and "painted" when the paintComponent method is called
Check out Custom Painting Approaches for exampled of painting from:
A List of objects
A BufferedImage.
The examples show how to draw Rectangles of different colours.
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).
What I would like is to give circles a fill color with a gradient that starts from the middle and then as it moves out to the edges becomes progressively more transparent, giving a blur effect. What is the simplest way of doing this?
Try setting an appropiately defined java.awt.RadialGradientPaint (using Colors with alpha), then render your circles using that. You may need to translate the graphics coordinate system to get the gradient centered in the circle. (http://docs.oracle.com/javase/7/docs/api/java/awt/RadialGradientPaint.html)
Or just make an image in a graphics program and simply draw the image.
Using AWT, how do you import an image into a rectangle you have drawn? I want to assign the background to that particular rectangle only.
Set the Rectangle as the clipping region.
Draw the image at a point so (part of) it is inside the clipping region.
Clear the clip.
Draw the rectangle.
As seen in this answer (the shape here is of text, but same principle applies).
The most common approach is to override the the paint method in your component. Have a look at Graphics.drawImage(). Example: Drawing an Image
If you decide to move to Swing, you can take advantage of Swing's optimizied painting model, overriding paintComponent instead of paint.
See: Performing Custom Painting