So i'm learning to create a java game on eclipse. I learned adding shapes and such. I also learned how to paint the shapes (change the colours) I was wondering how to add an image to the shape. This is the code for painting the rectangle.
public void paintColumn(Graphics g, Rectangle column)
{
g.setColor(Color.blue.darker());
g.fillRect(column.x, column.y, column.width, column.height);
}
Start by having a look at Reading/Loading an Image for details about how to load a image, also, have a look at 2D Graphics for more details about 2D Graphics API.
Basically, you load the image, you draw it and then draw the shape around it.
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.setColor(Color.RED);
g2d.drawRect(x, y, img.getWidth(), img.getHeight());
g2d.dispose();
Now, this just draws the rectangle over the image, if you want to, somehow "frame" the image instead, you could fill the rectangle, making it larger then the image, but you'd have to fill first, then draw the image
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.setColor(Color.RED);
g2d.fillRect(x - 10, y - 10, img.getWidth() + 20, img.getHeight() + 20);
g2d.drawImage(img, x, y, this);
g2d.dispose();
Simply create a BufferedImage object:
BufferedImage image = ImageIO.read(filename);
Then instead of doing g.drawShape do:
g.drawImage(image, [starting x], [starting y], [image width], [image height], [image observer]);
In your case, you probably won't need an image observer, so you can just put null in that spot.
Then what would be easiest is to just draw your rectangle on top of the image. Even though the image will not actually be "inside" the the rectangle, the layered effect will make it look as if it is. You can use drawRect instead of fillRect so you just get a border around your image.
To ensure that your rectangle ends up on top of the image, and doesn't get covered since the image is the same size, make sure to put the drawRect line after the drawImage.
g.drawRect([starting x], [starting y], [width], [height]);
Check out these Graphics Java Docs for more information on drawing images.
Related
I need some assistance fixing my vertical health bar. It tracks health correctly and updates, but because of how Java draws (from the top left corner, i.e. (0,0)), the bar appears to be upside down. I would like to flip the health bar so it would appear correctly but I am unsure how to do so.
The division in the codes x and y is just to place the bar in the correct position on the canvas. The multiplier is to scale up the health bar to fit a graphical overlay I made for it.
private void drawHealthBar(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
g2.fillRect(WIDTH - (WIDTH / 50), HEIGHT / 2, 10, ships.get(0).getHealth() * 6);
}
Setup the coordinate system how you want, using transform() and translate(). So:
you want the origin to be at (0, height); bottom left.
then you want to flip the Y axis.
Example code:
AffineTransform tform = AffineTransform.getTranslateInstance( 0, height);
tform.scale( 1, -1);
g2.setTransform( tform);
you need to shift bar depending on amount of health left, like this:
private void drawHealthBar(Graphics g) {
final Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.red);
final int w = 10;
final int h = ships.get(0).getHealth() * 6; // calculate height first
final int x = WIDTH - (WIDTH / 50);
final int y = HEIGHT / 2 + (MAX_HEIGHT - h); // shift by height of whitespace
g2.fillRect(x, y, w, h);
}
I'm making a 2D card game. In it I have a custom font uses drawString from the Graphics library to draw it in with custom color and size. Problem is that this seems incredibly unoptimized. I can't seem to find out why. With 5 cards on screen, each one using this method 4 times each, I got from 3,800 fps down to 350 fps. Here's the way I draw text:
public static void drawString(Graphics g, String text, int xPos, int yPos, boolean center, Color c, Font font) {
g.setColor(c);
g.setFont(font);
int x = xPos;
int y = yPos;
if (center) {
FontMetrics fm = g.getFontMetrics(font);
x = xPos - fm.stringWidth(text) / 2;
y = (yPos - fm.getHeight() / 2) + fm.getAscent();
}
g.drawString(text, x, y);
}
After a bit of googling here's how I did it. This image is created when a Card UI element is added to the screen. Then is used to just overlay on the card's image. The x and y scaling is done in a separate class. The code mentioned in the original comment is in the Text class, along with the other drawRestrictedText method:
public BufferedImage createTextOverlayImage(){
BufferedImage overlay = new BufferedImage(imageWidth, height, BufferedImage.TYPE_INT_ARGB);
Graphics g = overlay.createGraphics();
Text.drawString(g, name,
(imageWidth / 2) + wd.getScaleX(18),
wd.getScaleY(21),
true,
Color.black, Assets.font20Bold);
Text.drawString(g, cost + "",
wd.getScaleX(28),
wd.getScaleY(28),
true,
Color.blue, Assets.font28Bold);
Text.drawRestrictedString(g, keyWords,
wd.getScaleX(20),
wd.getScaleY(162),
imageWidth,
Color.magenta,
Assets.font18Bold);
Text.drawRestrictedString(g, description,
wd.getScaleX(20),
wd.getScaleY(185),
imageWidth - wd.getScaleX(35),
Color.black,
Assets.font18);
return overlay;
}
Here's the site I used for reference: http://www.java2s.com/Tutorials/Java/Graphics_How_to/Text/Write_text_onto_image.htm
I need to draw white text with black outline on a Graphics object I get from an image. I first draw the same text 4 times (moved left or right by one pixel) with black color and then once with white color. However this won't work well if outline needs to be more than 1px wide, and really seems like a hack. Is there a better way to do this?
final BufferedImage image = ImageIO.read(new File("./test.jpg"));
Graphics g = image.getGraphics();
g.setFont(g.getFont().deriveFont(45F));
// coordinates
int x = 100;
int y = 100;
String text = "Hello world";
g.setColor(Color.black);
g.drawString(text, x + 1, y - 1);
g.drawString(text, x + 1, y + 1);
g.drawString(text, x - 1, y - 1);
g.drawString(text, x - 1, y + 1);
g.setColor(Color.white);
g.drawString(text, x, y);
screenshot: https://i.imgur.com/ONLsPxy.png
The other option is to use below piece of code of creating a shape and then first drawing outline and then fill it:
Graphics2D g2d = (Graphics2D)g;
AffineTransform transform = g2d.getTransform();
transform.translate(x, y);
g2d.transform(transform);
g2d.setColor(Color.black);
FontRenderContext frc = g2d.getFontRenderContext();
TextLayout tl = new TextLayout(text, g.getFont().deriveFont(45F), frc);
Shape shape = tl.getOutline(null);
g2d.setStroke(new BasicStroke(5f));
g2d.draw(shape);
g2d.setColor(Color.white);
g2d.fill(shape);
Output:
I have very little experience with Java, and I am an amateur programmer. So mind my vocabulary.
I want to be able to stick a static rectangle on top of a rotating rectangle.
So far when I try to add another object it spins with the other image. I have tried setting the rotation to zero but that doesn't seem to work. I have also tried to create another class that draws components separately and added them to the frame using frame.add. I have also tried creating another part to the Draw class that has no effect on the GUI. Here is my current Draw class. Any help is appreciated.
class DrawRectangle extends JPanel {
#Override
public void paintComponent(Graphics g) {
int h = this.getHeight();
int w = this.getWidth();
Graphics2D g2 = (Graphics2D) g;
//draw background
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, w, h);
//draw roatiing rectangle
g2.setColor(Color.CYAN);
Rectangle rRec = new Rectangle(w / 4, h / 4, 2 * w / 4, 2 * h / 4);
double wr = rRec.getX() + rRec.getWidth() / 2;
double hr = rRec.getY() + rRec.getHeight() / 2;
g2.rotate(Math.toRadians(count), wr, hr);
g2.fill(rRec);
g2.fillRect(w / 3, h / 3, 2 * w / 3, 2 * h / 3);
}
public void paintComponent2(Graphics g) {
int h = this.getHeight();
int w = this.getWidth();
Graphics2D g2 = (Graphics2D) g;
}
}
So far when I try to add another object it spins with the other image.
Create a separate Graphics object to do the rotation so you don't affect the properties of the Graphics object passed into the painting method:
//Graphics2D g2 = (Graphics2D) g;
Graphics2D g2 = (Graphics2D)g.create();
// painting code
g2.dispose();
Move your g2.fill(rRec); BEFORE the rotate call, and it should work (I just tested it out).
This way, you will draw your static rectangle before the rotation, perform the rotation, THEN draw your second rectangle. Assuming your count variable is incremented somewhere, it should show the second rectangle being rotated.
I want to move this small rectangle about the circumference of the circle, so that I looks and moves like a canon.
Code
private void doDrawing(Graphics g){
g.setColor(Color.BLUE);
g.fillArc(-CANON_RADIUS/2, this.getHeight()-CANON_RADIUS/2, CANON_RADIUS, CANON_RADIUS, 0, 90);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLUE);
Rectangle rect = new Rectangle(CANON_RADIUS/2, this.getHeight()-CANON_RADIUS/2, CANON_WIDTH, CANON_HEIGHT);
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(-60), rect.getX() + rect.width/2, rect.getY() + rect.height/2);
Shape transformed = transform.createTransformedShape(rect);
g2d.fill(transformed);
}
This code rotates rectangle about its centre. How can I rotate rectangle around the circumference?
First things first, you can use a transformation matrix for this, like you are already using:
http://en.wikipedia.org/wiki/Transformation_matrix
Edit:
looking at your code, you want to rotate your canon around an anchor. Please look at the javadocs:
http://docs.oracle.com/javase/7/docs/api/java/awt/geom/AffineTransform.html
public void rotate(double theta,
double anchorx,
double anchory)
the first argument is your rotation, the last two arguments have to be the middle of your cannon base! like screen.height and 0 for your example:
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(-60), 0, Screen.height);
Shape transformed = transform.createTransformedShape(rect);
g2d.fill(transformed);
second approach could be move the middle of your rotated rectangle around the radius of your base.
like (pseudocode):
Point p = circle.getPoint();
shape.moveto(p.x-(shape.width/2),p.y-(shape.height/2));
g2d.fill(shape);