How to resize 2d game without "squeezing" it? - java

I am trying to make my second java game (2D) but i have run in a problem: The game will be in fullscreen, but how can i make it so it is scaled properly for each screen? While researching i found out that (almost) everyone is saying the same thing: render it on a Buffered image first and then render the image on the screen resolution, which i understund how to do (
BufferedImage i = new BufferedImage(width, height, 1);
BufferStrategy bs = this.getBufferStrategy();
Graphics2D g2 = i.createGraphics();
if(bs == null){
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
//g2.draw....
g.dispose();
bs.show();
)
but wont that make everything look squeezed or streched?
P.s. if you know any way of making it scale only by keeping the starting resolution (leaving black on both sides) i would accept it
P.s.Sorry for my english.Hope i explained it good enough (if not ask me to clarify)

Related

Can someone please explain the following piece of code? It is a code for double buffering used for game development in java

I wanted to use double buffering for my code and I found this in the internet. But I dont understand how it works.
private Image doubleBuffer;
public void update(Graphics g) {
Dimension size = getSize();
if (doubleBuffer == null || doubleBuffer.getWidth(this) != size.width || doubleBuffer.getHeight(this) != size.height){
doubleBuffer = createImage(size.width, size.height);
}
if (doubleBuffer != null) {
Graphics g2 = doubleBuffer.getGraphics();
paint(g2);
g2.dispose();
g.drawImage(doubleBuffer, 0, 0, null);
}
else {
paint(g);
}
The double buffer technique works in such way that you render/draw all graphics to an offscreen buffer (offscreen image), often called a backbuffer. Once all rendering/drawing is complete, the backbuffer is drawn/copied to the screen buffer.
The code starts with getting the dimensions of what is presumably the screen or window. Then the code checks if the doublebuffer (e.g. the backbuffer) exists, or if the backbuffer's width and height (dimensions) differ from the screen buffer (for example if user has resize its window or changed screen resolution). If the doublebuffer (backbuffer) does not exist or the dimensions are different, a new buffer is created with the same dimensions as the screen.
The code checks if the creation was successful (or that the doublebuffer exists), gets the graphics context of the buffer, calls paint() (where presumably all rendering is done) with the backbuffers graphics context, and then copy the backbuffer to the screen.
If, for some reason, the code was unable to create the buffer, the paint() method is called with the graphics context to the screen (I assume the variable g contains the graphics context to the screen), and rendering is done directly to this graphics context (e.g. to the screen).
I hope this helps.
Good luck with your game.

How can I paint an image from BufferStrategy to Png file?

I've created a Java program that generates snowflakes and I'd like to save the image created as a .png file once the program finishes drawing.
I've searched on Internet, but I've found only programs using BufferedImage, while I use a BufferStrategy, so I don't know exactly where to start.
The draw method in my program uses a BufferStrategy to create the Graphics component.
For example, to draw a simple line the method is:
bs = display.getCanvas().getBufferStrategy();
if (bs == null) {
display.getCanvas().createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
g.clearRect(0, 0, width, height);
g.setColor(Color.BLACK);
g.drawLine(0, 0, 50, 50);
What I would like is to get an exact copy of what has been drawn on the screen by the program to be saved as a .png image.
Hope you can help me.
Why not take a screenshot and then past it onto MS paint or some other(and better) image editing software like Photoshop or fire alpaca? That should solve your problem.
The common denominator between BufferedStrategy and BufferedImage is Graphics, so you want to write a paint routine so that you can simply pass a reference of Graphics to it
public void render(Graphics g) {
g.clearRect(0, 0, width, height);
g.setColor(Color.BLACK);
g.drawLine(0, 0, 50, 50);
}
Then you can pass what ever context you want.
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_RGB);
Graphics2D g2d = img.createGraphics();
render(g2d);
g2d.dispose();
Then you can use ImageIO.write to write the image to disk. See Writing/Saving an Image for more details

Black image when drawing Image on Canvas

I am working on a game in which I am use Canvas to display my graphics. I haven't (and don't plan on) using any Swing components...
In my render method:
I am using a BufferStrategy that I get from the canvas.
BufferStrategy bs = this.getBufferStrategy();
if(bs == null){
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
Later in the same method I end up drawing images(entities, trees, map, etc.), disposing of g, and showing the reference 'bs'.
...drawings onto canvas(entities, trees, map, etc.)
//END RENDER
g.dispose();
bs.show();
In between when I //END RENDER and finish drawing to g I ask if the game is paused. If so I am create a BufferedImage from what was made by g. I render that BufferedImage and then render my inventory screen on top of that:
BufferedImage img = new BufferedImage(this.width, this.height, BufferedImage.TYPE_3BYTE_BGR);
Graphics gx = img.getGraphics();
game.paint(gx);
g.drawImage(img, 0, 0, Color.CYAN, this);
interfaceLayer.render(g);
I am getting a black BufferedImage in my reference img.
Am I doing something wrong by using a BufferStrategy? Should I not be using two different Graphics objects?
Here is a picture of what it looks like before and after I pause the game to get an idea.
Instead of:
g.drawImage(img, 0, 0, Color.CYAN, this);
I changed it to:
g.drawImage(img, 20, 20, Color.CYAN, this);
Just some arbitrary x,y so you can get the idea of whats going on with they layering.
Dont mind the gray box. It is a fillRect() that I will eventually be expanding as part of the graphics in my inventory screen.
Why the black image?

How to move everything in Graphics2D by x,y coordinates.

I need to move already made BufferedImage by x,y coordinates and then draw another things on it with Graphics2D object. I tried to use this code to do that :
Graphics2D g = img.createGraphics();
g.translate(x, y);
but it doesn't work. Is there any way to move everything in Graphics2D object and then draw on it or I have to use this code to do that:
BufferedImage temp = new BufferedImage(img.getWidth(),img.getHeight(),BufferedImage.TYPE_INT_ARGB);
Graphics2D g = temp.createGraphics();
g.drawImage(img,x, y,null);
Using this code and then drawing only few elements rather than making whole image from scratch isn't big leap in performance so I think making new BufferedImage then drawing image on it isn't best way. I would rather just create Graphics2D object from already made image and then just move it by a few pixels diagonally, but I couldn't find the way to do that.
From the Graphics2d docs when you use translate:
All coordinates used in subsequent rendering operations on this graphics context are relative to this new origin.
You are defining a transformation that affects future operations. After calling translate if you were to call a method on graphics like draw3DRect(0, 0, ... snipped ... ) the starting coordinates 0,0 would be translated by x,y.
I think your best bet might be to use the methods of BufferedImage to move all the pixels before you get the graphics object. You have getRgb and setRgb
A naive example of moving the pixels:
BufferedImage buffImg = ImageIO.read(img);
int width = buffImg.getWidth();
int horizontalOffset = 10;
int verticalOffset = 10;
int widthToMove = width - horizontalOffset;
int heightToMove = buffImg.getHeight() - verticalOffset;
int[] rgb = buffImg.getRGB(0, 0, widthToMove, heightToMove, null, 0, widthToMove);
buffImg.setRGB(horizontalOffset,verticalOffset,widthToMove, heightToMove,rgb, 0, widthToMove);
This still leaves you with some work to do because there is a strip at the top and to the left that you need to fill with background colour.
If it's going to be used on big images you might want to use a buffer int[] and pass it to getRGB in a loop, getting and setting in chunks.

Image Quality Gets Ruined In Java Graphics2D Rotate

I am experiencing an issue with rotating an Image with the Graphics2D rotate method.
Here's an image of the issue I'm having:
As I move the ball, the image gets completely distorted as it rotates.
Here's my rotate method:
public static void rotate(BufferedImage img, Rectangle rect, int degrees) {
Graphics2D g = (Graphics2D) img.createGraphics();
g.rotate(degrees, rect.x + rect.width/2, rect.y + rect.height/2);
g.drawImage(img, rect.x, rect.y, rect.width, rect.height, null);
g.dispose();
}
Is there anything I can do to avoid the quality loss?
So currently as the ball moves, you rotate the image a few degrees and overwrite the original image with the new one? Each time the image is rotated, a tiny bit of distortion is added; over many rotations, the distortion is compounded.
Instead, just keep the original image in memory and also store the number of degrees it should appear to be rotated on screen. Then each time you render it, rotate the original image by the current number of degrees.
I know this is a pretty old question but for anyone looking to do something similar try putting the following code before your g.drawImage
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
That should help to make the image look a better.

Categories