Java rectangle location is wrong - java

I am messing around with the Graphics class and have noticed that the location and size of the rectangles I draw do not add up.
// Game.HEIGHT = 800
// Game.WIDTH = 800
g.drawRect(Game.WIDTH/2 -50, Game.HEIGHT/2 -50, 100, 100);
This should draw a rectangle in the enter of the screen just using math, but it is quite offset. I feel like I am missing something, because math wise this should work, and I could use some explanation.

Not really an answer, just debugging help.
How do you know the actual size of the panel is 800?
How do you know your x/y values are correct?
Don't use math expressions for parameters. Instead your code should be something like:
int size = 100;
int x = (Game.WIDTH - size) / 2;
int y = (Game.HEIGHT - size) / 2;
System.out.println("Panel size: " + getSize());
System.out.println(x + " : " + y);
g.drawRect(x, y, size, size);
This allows you to display the value of your parameters to make sure they are what you expect them to be.
Instead of hardcoding the width/height of the panel you should use the actual size of the panel as determined by the getSize() method.

Related

Java 15 - Adding Customisable Text to my canvas produces scaling/position issue

I am jumping back into an old bunch of code and my Java is very rough. Please be kind.
Problem: I have an application that draws on the canvas. The placement of the screen objects works well. Even Text attached to other objects. However when I place a Text object on the canvas the scale of the canvas halves. I have fiddled off and on for months and can't seem to find the resolution. Any advice would be helpful.
Below is the code to draw the text on screen it is in a class Visualise2D with the other drawing method. All other objects use the same scale etc. This only occurred since I upgraded to Java 15, last java I used was java 8 and it worked fine.
//TEXT
public void paintText(Graphics2D t2D, Color color,Text t, Font font, double bearing, Rectangle2D bounds, double scale, boolean selected, boolean isRotationTool, double enhance) {
//Draws text where ever the user clicks
FontMetrics fm = t2D.getFontMetrics();
t2D.setFont(default_FONT);
AffineTransform at = new AffineTransform();
int x = (int) ((t.getX() - bounds.getX())*(scale));
int y = (int) ((bounds.getHeight() + bounds.getY() - t.getY()) *(scale));
at.setToRotation(Math.toRadians(bearing+270), x,y);
FontRenderContext frc = t2D.getFontRenderContext();
TextLayout layout = new TextLayout(t.getText(), t2D.getFont(), frc);
t2D.setTransform(at);
if (!(selected)) {
t2D.setColor(color);
}
else
{
//pixel size of the circle
float size = 20;//(float) (fm.stringWidth(t.getText())*0.5);
t2D.setColor(p_selectedObjectsColour);
t2D.setStroke(LINE_100);
//Highlight and origin indicator when selected - START
t2D.setColor(p_selectedObjectsColour);
t2D.draw(new Ellipse2D.Double((((t.getX() - bounds.getX())*scale) - size), (((bounds.getHeight() + bounds.getY() - t.getY())*scale) - size), (size*2), (size*2)));
if(isRotationTool){
t2D.drawString(" : \uu27f3 "+dec1P.format(bearing)+"\u00b0",(float) (x + (fm.stringWidth(t.getText())*1.05)),y);
}
t2D.setColor(p_selectedObjectsColour);
t2D.draw(new Rectangle2D.Double(
(t.getX() - bounds.getX())* scale,
((bounds.getHeight() + bounds.getY() - t.getY())*scale)-fm.getStringBounds(t.toString(), t2D).getHeight(),
t.getBounds().getWidth(),
t.getBounds().getHeight()
));
t2D.drawLine((int) (((t.getX() - bounds.getX())) * scale),
(int)(((bounds.getHeight() + bounds.getY())-(t.getY()))*scale),
(int)(((t.getX())- bounds.getX())*scale)+fm.stringWidth(t.getText()),
(int)(((bounds.getHeight() + bounds.getY())-(t.getY()))*scale));
}
t2D.setColor(color);
//t2D.drawString(t.getText(), x, y);
layout.draw(t2D, x, y);
at.setToRotation(0, x, y);
t2D.setTransform(at);
//This error is to remind you that the Affine transform is not working and the text is in the collection still after it is moved.
}
Below are two images that describe the issue.
Image 1 is the Normal View at Normal Scale
Image 2 is the Alter after Text addition Scale.
If the text is deleted the Scale returns to the first image.
Normal Scale:
Added Text Scale Changes:

Trying to get multiple images out of a single image

I've been stuck at something recently.
What I want to do is to get multiple sub-images out of 1 big image.
So take this example. I have a frame of 128x128 pixels where all the images need to be in.
I'm putting all the bufferedImages inside a list and scaling all those images to 128x128.
The image you see on that link is showing that I need 4 sub-images from that image, so at the end, I have 4 images which are 128x128 but 4 times.
Or if you have an image with 128x384 it will give 3 sub-images going from top to bottom.
https://i.stack.imgur.com/RsCkf.png
I know there is a function called
BufferedImage.getSubimage(int x, int y, int w, int h);
But the problem is that I can't figure out what math I need to implement.
What I tried is if the height or width is higher than 200 then divide it by 2 but that never worked for me.
I'm not sure I fully understand what you are asking, but I think what you want is something like this:
First, loop over the image in both dimensions.
Then compute the size of the tile (the smaller value of 128 and (image dimension - start pos)). This is to make sure you don't try to fetch a tile out of bounds. If your images are always a multiple of 128 in any dimension, you could just skip this step and just use 128 (just make sure you validate that input images follow this assumption).
If you only want tiles of exactly 128x128, you could also just skip the remainder, if the tile is less than 128x128, I'm not sure what your requirement is here. Anyway, I'll leave that to you. :-)
Finally, get the subimage of that size and coordinates and store in the list.
Code:
BufferedImage image = ...;
int tileSize = 128;
List<BufferedImage> tiles = new ArrayList<>();
for (int y = 0; y < image.height(); y += tileSize) {
int h = Math.min(tileSize, image.height() - y);
for (int x = 0; x < image.width(); x += tileSize) {
int w = Math.min(tileSize, image.width() - x);
tiles .add(image.getSubimage(x, y, w, h));
}
}

How can I decode a QR from close up without increasing framingRect size?

My app, which uses ZXing to scan QR codes, can't read a QR Code unless the phone is VERY far away from the code (see picture, 6-7+ inches away and still not reading). The code is centered and well within the framingRect, but the camera seems to only be picking up result points from the top 2 positioning squares. I have increased the size of the framing rectangle through some code which I found here, which does yield a much better result.
Code: (replaces getFramingRect from zxing.camera.cameramanager.Java)
public Rect getFramingRect() {
if (framingRect == null) {
if (camera == null) {
return null;
}
Point screenResolution = configManager.getScreenResolution();
int width = screenResolution.x * 3 / 4;
int height = screenResolution.y * 3 / 4;
Log.v("Framing rect is : ", "width is "+width+" and height is "+height);
int leftOffset = (screenResolution.x - width) / 2;
int topOffset = (screenResolution.y - height) / 2;
framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
Log.d(TAG, "Calculated framing rect: " + framingRect);
}
return framingRect;
}
For reasons beyond my comprehension, with this new larger framing rectangle, codes can be read as soon as they fit inside the rect width, whereas previously the code had to occupy a small region at the center of the rect (see pic).
My Question:
How can I make code scan as soon as it is within the bounds of the framing rect, without increasing the size of the rectangle? Why Is this happening?
Increase the width and height to 4/4 (just leave them as the screen resolution) and then change the framing rect visual representation to make it seem as if the scanner is only inside that. Worked for my app.

Two Shape objects appear to be intersecting at the wrong location?

I am trying to create a Shape with the centre of the ship being in the middle.
one.x and one.z is the X and Z positions of the ship. The ship size is about 100 on the X, and 50 on the Z.
Shape my = new Rectangle(
(int) one.x - disToLeft, // upper-left corner X
(int) one.z - disToTop, // upper-left corner Y
disToLeft + disToRight, // width
disToTop + disToBottom // height
);
I'm then rotating the Shape, to of course be facing the correct way. This appears to work:
int rectWidth = (disToLeft + disToRight);
int rectHeight = (disToTop + disToBottom);
AffineTransform tr = new AffineTransform();
// rotating in central axis
tr.rotate(
Math.toRadians(one.rotation),
x + (disToLeft + disToRight) / 2,
z + (disToTop + disToBottom) / 2
);
my = tr.createTransformedShape(my);
I am then doing the exact same thing with another Shape, and testing for intersection. This works.
However, it feels like the Shape is the incorrect dimensions. Or something. My ship is colliding very far out to one side (outside where it graphically exists), but through the other side, I can almost go right through the ship before any collision is detected!
Basically the Shapes are simply intersecting at the wrong location. And I cannot work out why. Either the shape, the location, or the rotation must be wrong.
int disToLeft = 100;
int disToRight = 100;
int disToTop = 150;
int disToBottom = 100;
These are the distance from the centre to the left, right, top, and bottom sides.
I am using Z instead of Y because my game is in a 3D world and the sea level is pretty much the same (hence I don't need to worry about Y axis collision!).
Update:
After doing a lot of testing, I have discovered that the top of the rectangle is in the middle! I have done a lot of messing around, but without being able to graphically see the squares, it's been very hard to test.
This means that the box is on the side of the ship, like this:
Obviously when the ship on the left rotates to what it's like in this picture, a collision is detected.
It seems that your rotation is wrong. From my understanding of math it should be
tr.rotate(Math.toRadians(one.rotation), x + (disToRight - disToLeft) /2, z + (disToBottom - disToTop) /2);
Note the signs and the order of the variables
Edit:
Let's take apart the formula:
Your Rectangle is defined like this:
x-coordinate (x): one.x-disToLeft
y-coordinate (y): one.z-disToTop
width: disToLeft+disToRight
height: disToTop+disToBottom
The centre of the Rectangle (where you are rotating) is therefore:
(x+width/2)
(y+height/2)
if you replace x, width, y and height with the declarations above you get
(one.x-disToLeft + (disToLeft+disToRight)/2)
(one.z-disToTop + (disToTop+disToBottom)/2)
This is already the point you need, but it can be simplyfied:
one.x- disToLeft + (disToLeft+disToRight)/2
is equal to
one.x-(2*disToLeft/2)+(disToLeft/2)+(disToRight/2)
is equal to
one.x-(distoLeft/2) + (disToRight/2)
is equal to
one.x+(disToRight-disToLeft)/2
The other coordinate works exactly the same.

AndEngine - Getting Center Coordinates of a Sprite

I have a sprite in my game and I want to get it's center coordinates. The sprite can be rotated though so I can't just get it's x/y coordinates then add half of the sprite's width/height because the getWidth and getHeight methods return the dimensions of the original, unrotated sprite.
I tried getSceneCenterCoordinates() but that for some reason returns the same coordinates for all sprites even if they are nowhere near each other.
Here's a graphic to describe what I want, the red dot is the coordinate I want, and the width/height labels on the right side figure respresent what I WANT the getWidth/Height methods to return (but they don't):
You can use coordinates transformer
final float[] spriteCoordinates = sprite.convertLocalToSceneCoordinates(x,y);
final float canonX = spriteCoordinates[VERTEX_INDEX_X];
final float canonY = spriteCoordinates[VERTEX_INDEX_Y];
Sprite sprite_in_fixedpoint_of_the_first_sprite=new Sprite(canonX,canonY,textureregion)
Get the minimum and maximum value of all the corners (for both - x and y components).
Then take average from max and min to get middle:
middleX = (maxX + minX) / 2
Repeat the same for y component.
Consider something like this
Rectangle test = new Rectangle(100, 100, 50, 100, vboManager);
mainScene.attachChild(test);
System.out.println("Before RotCtrX = " + test.getRotationCenterX());
System.out.println("Before RotCtrY = " + test.getRotationCenterY());
test.setRotation(45);
System.out.println("After RotCtrX = " + test.getRotationCenterX());
System.out.println("After RotCtrY = " + test.getRotationCenterY());
and the result are
System.out(4526): Before RotCtrX = 25.0
System.out(4526): Before RotCtrY = 50.0
System.out(4526): After RotCtrX = 25.0
System.out(4526): After RotCtrY = 50.0
AndEngine Entities rotate around the center (unless you change the RotationCenter values), so applying setRotate() will not affect the "center" point location
those "center" points are relative to the Entity, so if you need the actual screen coordinates, you will need to add those to the getX() and getY() values - which BTW also won't change based solely on applying a setRotate()
I figured out how to use getSceneCenterCoordinates() properly, which is to hand it a float[]. Here is my solution:
float[] objCenterPos = new float[2];
obj.sprite.getSceneCenterCoordinates(objCenterPos);
Log.d(this.toString(), "Coordinates: ("+objCenterPos[0]+","+objCenterPos[1]+")");

Categories

Resources