So far I have a java app where I draw a circle(player) and then draw a green rectangle on top(gun barrel). I have it so when the player moves, the barrel follows with it. I want it to find where the mouse is pointing and then rotate the barrel accordingly. For an example of what I mean look at this video I found http://www.youtube.com/watch?v=8W7WSkQq5SU See how the player image reacts when he moves the mouse around?
Here's an image of what the game looks like so far:
So how do I rotate it like this? Btw I don't like using affinetransform or Graphics2D rotation. I was hoping for a better way. Thanks
Using the Graphics2D rotation method is indeed the easiest way. Here's a simple implementation:
int centerX = width / 2;
int centerY = height / 2;
double angle = Math.atan2(centerY - mouseY, centerX - mouseX) - Math.PI / 2;
((Graphics2D)g).rotate(angle, centerX, centerY);
g.fillRect(...); // draw your rectangle
If you want to remove the rotation when you're done so you can continue drawing normally, use:
Graphics2D g2d = (Graphics2D)g;
AffineTransform transform = g2d.getTransform();
g2d.rotate(angle, centerX, centerY);
g2d.fillRect(...); // draw your rectangle
g2d.setTransform(transform);
It's a good idea to just use Graphics2D anyway for anti-aliasing, etc.
Using AffineTransform, sorry, only way I know how :P
public class RotatePane extends javax.swing.JPanel {
private BufferedImage img;
private Point mousePoint;
/**
* Creates new form RotatePane
*/
public RotatePane() {
try {
img = ImageIO.read(getClass().getResource("/MT02.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
mousePoint = e.getPoint();
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
double rotation = 0f;
int width = getWidth() - 1;
int height = getHeight() - 1;
if (mousePoint != null) {
int x = width / 2;
int y = height / 2;
int deltaX = mousePoint.x - x;
int deltaY = mousePoint.y - y;
rotation = -Math.atan2(deltaX, deltaY);
rotation = Math.toDegrees(rotation) + 180;
}
int x = (width - img.getWidth()) / 2;
int y = (height - img.getHeight()) / 2;
g2d.rotate(Math.toRadians(rotation), width / 2, height / 2);
g2d.drawImage(img, x, y, this);
x = width / 2;
y = height / 2;
g2d.setStroke(new BasicStroke(3));
g2d.setColor(Color.RED);
g2d.drawLine(x, y, x, y - height / 4);
g2d.dispose();
}
}
Will produce this effect
The red line (point out from the center) will want to follow the cursor.
Related
I am new to programming and I've been trying to get and set the icon to circle but it's not being updated. I want to set every icon that was set to JLabel will become circular.
class CircleLabel extends JLabel {
private Icon icon;
private int borderSize;
#Override
protected void paintComponent(Graphics g) {
if (getIcon() != null) {
icon = getIcon();
int width = getWidth();
int height = getHeight();
int diameter = Math.min(width, height);
int x = width / 2 - diameter / 2;
int y = height / 2 - diameter / 2;
int border = borderSize * 2;
diameter -= border;
Dimension size = getAutoSize(icon, diameter);
BufferedImage img = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2_img = img.createGraphics();
g2_img.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2_img.fillOval(0, 0, diameter, diameter);
Composite composite = g2_img.getComposite();
g2_img.setComposite(AlphaComposite.SrcIn);
g2_img.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2_img.drawImage(toImage(icon), 0, 0, size.width, size.height, null);
g2_img.setComposite(composite);
g2_img.dispose();
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(255, 255, 255));
diameter += border;
g2.fillOval(borderSize, borderSize, diameter, diameter);
g2.drawImage(img, x - borderSize, y + borderSize, null);
} else {
System.out.println("No Icon!");
}
super.paintComponent(g);
}
private Dimension getAutoSize(Icon image, int size) {
int w = size;
int h = size;
int iw = image.getIconWidth();
int ih = image.getIconHeight();
double xScale = (double) w / iw;
double yScale = (double) h / iw;
System.out.println(xScale);
System.out.println(yScale);
double scale = Math.max(xScale, yScale);
int width = (int) (scale * iw);
int height = (int) (scale * ih);
if (width < 1) {
width = 1;
}
if (height < 1) {
height = 1;
}
return new Dimension(width, height);
}
private Image toImage(Icon icon) {
return ((ImageIcon) icon).getImage();
}
}
If I set the icon manually and removed the icon from the label, it will work but when I add the icon to the label through properties, it will not work.
icon = new ImageIcon(getClass().getResource("/Attachments/user.png"));
I found this on YouTube and wanted to apply it to the application I'm trying to build.
I have a static number of slots for the number in the wheel game. Start from number 00 to number 1 (clockwise). The position count is 0 to 37 in my Collection array. Currently, I successful place the ball position in the middle of the number with 1 degree. But I unable to calculate a correct value for each of the position when I tried to pass in the number position.
I already tried messing with the calculation, it either the ball sit in the middle between the number or out of range!
public class WheelDisplay extends JPanel implements ConstantVariable {
private Image image;
private ImageObserver imageObserver;
private float degrees = 1;
private int post = 0;
public WheelDisplay() {
ImageIcon icon = new ImageIcon(IMAGE_LOCATION);
image = icon.getImage();
imageObserver = icon.getImageObserver();
}
/** Credit to stackoverflow forum : https://stackoverflow.com/questions/25923480/simple-circle-rotation-simulate-motion **/
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int circleDiameter = Math.min(getWidth(), getHeight());
double circleRadius = circleDiameter / 2;
int offSetX = (getWidth() - circleDiameter) / 2;
int offSetY = (getHeight() - circleDiameter) / 2;
g2d.drawImage(image, offSetX, offSetY, circleDiameter, circleDiameter, imageObserver);
g2d.setColor(Color.BLUE);
int ballDiameter = (int) (circleDiameter * 0.02);
int ballRadius = ballDiameter / 2;
Point p = getPointOnCircle(this.degrees, circleRadius * 0.9, circleRadius);
int valueX = offSetX + p.x - ballRadius;
int valueY = offSetY + p.y - ballRadius;
g2d.fillOval(valueX, valueY, ballDiameter, ballDiameter);
g2d.dispose();
}
private Point getPointOnCircle(float degress, double circleRadius, double innerCircleRadius) {
//The calculation that allow ball sit in the middle of each number when spin
double rads = ((Math.PI * degress) / 38);
// Calculate the outter point of the line
int xCordinate = Math.round((float) (innerCircleRadius + Math.cos(rads) * circleRadius));
int yCordinate = Math.round((float) (innerCircleRadius + Math.sin(rads) * circleRadius));
return new Point(xCordinate, yCordinate);
}
public void setDegree(int x) {
this.degrees += 2;
this.post = x; // The number of position coming from Collection (0-37)
}
}
The ball supposes to sit in the middle of each 38 numbers in the wheel image.
Hope that someone can point out which part I'm doing wrong!
The image that I'm using is this.
Below is the code from "Filthy Rich Clients" by Romain Guy and Chet Haase
private class ImageViewer extends JComponent {
private BufferedImage image, landscape;
private ImageViewer() {
try {
image = ImageIO.read(new File("picture.png"));
landscape = ImageIO.read(new File("landscape.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
BufferedImage temp = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = temp.createGraphics();
if (shadow.isSelected()) {
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g2.drawImage(image, x + 4, y + 10, null);
Composite oldComposite = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, 0.75f));
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setComposite(oldComposite);
g2.drawImage(image, x, y, null);
} else {
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g2.drawImage(image, x, y, null);
Composite oldComposite = g2.getComposite();
g2.setComposite(AlphaComposite.SrcIn);
x = (getWidth() - landscape.getWidth()) / 2;
y = (getHeight() - landscape.getHeight()) / 2;
g2.drawImage(landscape, x, y, null);
g2.setComposite(oldComposite);
}
g2.dispose();
g.drawImage(temp, 0, 0, null);
}
}
It is a part of the code to obtain the following output with different states when checkbox is checked:-
What i dont understand is
1)what is the line
BufferedImage temp = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
doing there because if I write only the following code and run nothing is obtained in the output.
BufferedImage temp = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = temp.createGraphics();
if (jcb.isSelected()) {
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g2.drawImage(image, x + 4, y + 10, null);
}
2)What is the need to obtain g2 after creating the 'temp' bufferedImage? Can't I do it directly like
Graphics2D g2=(Graphics2D)g.create();
3)What is practical difference between TYPE_INT_RGB and TYPE_INT_ARGB.?
This is double buffering:
http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html
You first draw on an off-screen image, which in this case is backed by a BufferedImage object referenced in the variable temp; then you do whatever to the off-screen image; finally, you print the result on the component, via g.drawImage(temp, ...). This is not to have the user see glitches or artifacts due to the image being constructed directly on the screen.
I have painted a BufferedImage on a JPanel with the following code.
protected void paintComponent(Graphics g) {
if (image != null) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
double x = (getWidth() - scale * imageWidth) / 2;
double y = (getHeight() - scale * imageHeight) / 2;
AffineTransform at = AffineTransform.getTranslateInstance(x, y);
at.scale(scale, scale);
g2.drawRenderedImage(image, at);
}
}
How can I add a mouse click listener to that image? Additionally, I want to get the click coordinate of the image, not the JPanel.
Add a MouseListener to the pane as per normal.
In the mouseClicked method check to see if the Point is within the rectangle of the image...
public void mouseClicked(MouseEvent evt) {
if (image != null) {
double width = scale * imageWidth;
double height = scale * imageHeight;
double x = (getWidth() - width) / 2;
double y = (getHeight() - height) / 2;
Rectangle2D.Double bounds = new Rectangle2D.Double(x, y, width, height);
if (bounds.contains(evt.getPoint()) {
// You clicked me...
}
}
}
I want to draw a circle (with 1 or 2 for loops) using pixels position (starts from top left and ends at bottom right)
I successfully drew a rectangle with this method:
private void drawrect(int width,int height,int x,int y) {
int top=y;
int left=x;
if(top<0){
height+=top;
top=0;
}
if(left<0){
width+=left;
left=0;
}
for (int j = 0; j <width; j++) {
for (int i = 0; i <height; i++) {
pixels[((i+top)*w)+j+left] = 0xffffff;//white color
}
}
}
The pixels array contains the pixel index followed by it's color.
pixels[index]=color;
Before that I use this code for "image" and "pixels" array (if this helps you)
img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
But how can I draw only the white pixels like in this image and ignore the other pixels?
Here is the code for drawing circle with pixels: It uses the formula xend = x + r cos(angle) and yend = y + r sin(angle).
#include <stdio.h>
#include <graphics.h>
#include <stdlib.h>
#include <conio.h>
#include <bios.h>
#include <math.h>
void DrawCircle(int x, int y, int r, int color)
{
static const double PI = 3.1415926535;
double i, angle, x1, y1;
for(i = 0; i < 360; i += 0.1)
{
angle = i;
x1 = r * cos(angle * PI / 180);
y1 = r * sin(angle * PI / 180);
putpixel(x + x1, y + y1, color);
}
}
Reference: http://www.softwareandfinance.com/Turbo_C/DrawCircle.html
You can calculate the minimum angle between two pixels and improve the Kathir solution
...
void DrawCircle(int x, int y, int r, int color)
{
static const double PI = 3.1415926535;
double x1, y1;
// calculates the minimun angle between two pixels in a diagonal.
// you can multiply minAngle by a security factor like 0.9 just to be sure you wont have empty pixels in the circle
double minAngle = acos(1 - 1/r);
for(double angle = 0; angle <= 360; angle += minAngle)
{
x1 = r * cos(angle);
y1 = r * sin(angle);
putpixel(x + x1, y + y1, color);
}
}
Since you already have a BufferedImage, why not create a graphics object for it and use that to draw the circle? That way you don't have to reinvent the wheel:
BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
g.setColor(Color.WHITE);
g.fillOval(x, y, width, height);
Update
Here is a SSCCE:
public class DrawCircleExample extends Canvas {
private static final int WIDTH = 32;
private static final int HEIGHT = 32;
public static void main(String[] args) {
JFrame f = new JFrame("Draw circle example");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new DrawCircleExample());
f.pack();
f.setVisible(true);
}
private final BufferedImage img;
public DrawCircleExample() {
img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
g.setColor(Color.WHITE);
g.fillOval(8, 8, 14, 14);
}
#Override
public void paint(Graphics g) {
g.drawImage(img, 0, 0, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(),img.getHeight());
}
}
It should produce an image like this:
One way to do this would be to test, for each point in the rectangle, whether or not the distance from that pixel to the center of the square is less than the intended radius of the circle. You could then draw the pixels that pass the test and skip the pixels that don't. The ratio of the area of the circle to the area of the total square is π/4, which is about .77, so this actually isn't all that inefficient.
If you want to draw an arbitrary oval that fits in the rectangle, you can use this same idea, but would modify the computation that would determine the distance to the center such that you give proportionally less weight to the long axis of the ellipse.
Hope this helps!
Sorry for the delay
This code works perfectly
private void drawcircle(int x,int y,int radius){
for(int i=x;i<radius*2;i++)
for(int j=x;j<radius*2;j++){
int d= (int) Math.sqrt((i-radius)*(i-radius)+(j-radius)*(j-radius));
if(d<radius)
pixels[i+j*WIDTH]=346346;
}
}