How could I make my Snowmans arms wave using Graphics 2D? - java

So I am currently creating a drawing that creates a Snowman, as well as some other objects in the background. I got the drawing part down, it looks just as it should, but I wanted to add a little bit of movement within it. I used Graphics2D to draw all my shapes, lines, ellipses, etc., but I'm not sure how/if I can make the Snowmans arms wave back and forth with the drawLine method.
I provided the code for the entire Snowman here. It's very simple, as I said it just uses Graphics2D to draw everything. The arm1 and arm2 are near the bottom.
public class Snowman {
private int x;
private int y;
private int width;
private int height;
public Snowman(int x, int y, int width, int height) {
this.x=x;
this.y=y;
this.width=width;
this.height=height;
}
public void draw(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
// the body of the snowman
g2.setColor(Color.WHITE);
g2.fillOval(x+125, y+40, 200, 200);
g2.fillOval(x+75, y+140, 300, 300);
g2.fillOval(x+25, y+290, 400, 400);
// the buttons
g2.setColor(Color.BLACK);
g2.fillOval(x+210, y+210, 40, 40);
g2.fillOval(x+210, y+270, 40, 40);
g2.fillOval(x+210, y+330, 40, 40);
// the eyes and mouth
g2.fillOval(x+190, y+98, 20, 20);
g2.fillOval(x+245, y+98, 20, 20);
g2.drawArc(x+180, y+120, 100, 50, 200, 140);
// arm1
g2.drawLine(x+75, y+270, x, y+90);
//arm2
g2.drawLine(x+375, y+270, x+450, y+90);
// the hat
g2.setColor(Color.BLACK);
g2.fillRect(x+177, y+40, 100, 30);
g2.fillRect(x+202, y, 50, 50);
}
}
Is there a way I can implement something to make them move? Or would I have to draw these another way?

you can add a method that adjusts the coordinates of the hand, and this method might contain some if statement so say if the hand reached specific x it will subtract from x to go to the other direction. And then call this method inside the draw function

Related

drawArc() rendering is inconsistent when the arc length changes

I need to draw an arc around a volume knob, the arc length represents the volume.
I tried with Graphics.drawArc() and Arc2D.Double, but the result is not good: the path of the arc is not exactly the same for different extent values.
public class ArcComponent extends JComponent
{
private ImageIcon knobImage = new ImageIcon(ArcComponent.class.getResource("Knob-w37.png"));
int arcLength = 220; // Degrees
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Paint knob image
knobImage.paintIcon(this, g2, 20, 20);
// Add arc
var arc = new Arc2D.Double(22, 22, 32, 32, 220 - arcLength, arcLength, Arc2D.OPEN);
g2.setColor(Color.CYAN);
g2.setStroke(new BasicStroke(2));
g2.draw(arc);
g2.dispose();
}
void shorter()
{
arcLength -= 5;
if (arcLength < 0)
{
arcLength = 260;
}
repaint();
}
void longer()
{
arcLength += 5;
if (arcLength > 260)
{
arcLength = 0;
}
repaint();
}
}
How could I ensure that the path of the arc is always the same?
EDIT: added knob image painting
A dirty trick: draw the complete circle and ovewrite the part that you don't need with a shape, same color of background.
Something like this:
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape circle=new Ellipse2D.Double(20, 20, 30, 30);
g2.setColor(Color.CYAN);
g2.setStroke(new BasicStroke(2f));
g2.draw(circle);
Shape arc=new Arc2D.Double(10,10,50,50,230,360-arcLength,Arc2D.PIE);
g2.setColor(getBackground());
g2.fill(arc);
g2.dispose();
}
Unfortunately this requires the arc to be drawn before any other thing in the same area, but you can probably deal with this.
EDIT: For the additional constraint, the inconsistent rendering is actually due to the stroke, so try creating a thick shape and fill it, example:
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
double thickness=8.0; //This replaces your stroke width
GeneralPath shape=new GeneralPath();
shape.append(new Arc2D.Double(20-thickness/2,20-thickness/2, 30+thickness, 30+thickness, 230, -arcLength, Arc2D.OPEN),false);
shape.append(new Arc2D.Double(20+thickness/2,20+thickness/2, 30-thickness, 30-thickness, 230-arcLength, arcLength, Arc2D.OPEN),true);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.CYAN);
g2.fill(shape);
g2.dispose();
}
Simply draw a full circle and clip on the arc shape (with some padding to ensure everything gets drawn).
Graphics2D g2 = (Graphics2D) g.create();
Ellipse2D circle = new Ellipse2D.Double(20, 20, 30, 30);
int d = 2;
Arc2D arc = new Arc2D.Double(20 - d, 20 - d, 30 + 2 * d, 30 + 2 * d, 230, -arcLength, Arc2D.PIE);
g2.setColor(Color.CYAN);
g2.setClip(arc);
g2.setStroke(new BasicStroke(2f));
g2.draw(circle);
knobImage.paintIcon(this, g, 20, 20);

Plotting Logarithmic and Exp graph in Java

I am doing my coursework on Java and I am stuck in doing the graphs for 3 functions. X-x^2, ln(x-1)-1 and e^x-3x.
I have already tried to set up JFrame with axis and even code for x-x^2 that plots graph for that function.
int x,y;
int ax,by;
String s="deba";
String se ="deba";
public Plotfunct1(){
setTitle("Function graph");
setSize(900,700);
setLayout(null);
setVisible(true);
setResizable(false);
x = 30;
y = 300;
}
#Override
public void paint(Graphics g){
g.setColor(Color.BLACK);
g.drawString("Y", 310, 40);
g.drawString("Y'", 310, 600);
g.drawString("X", 30, 314);
g.drawString("X'", 600, 314);
if(x==300&&y==300){
g.drawString("Origin(0,0)", 310, 314);
}
g.drawLine(300, 30, 300, 600);
g.drawLine(30,300,600,300);
if(x>599||y<40){
x = 30;
y=300;
}
if(x<600&&y>30&&y!=600){
ax = x-300;
by = y-300;
ax++;
by = (int) (.095*(ax-Math.pow(ax,2)));
x=300+ax;
y=300-by;
}
g.fillOval(x, y, 3, 3);
repaint();
}
}
I need to plot the last 2 functions I have tried everything that I could come up with changing the Math.pow to Math.log but then I just get one line
Have you tried using Polygons?
I dont have experience with the Graphics class, but seems like fillOval() only draws circles, it does not apply for logarithmic functions.
Check this answer. You can add points to the graph using addPoint() on the Polygon, then draw the polygon on the Graphic using drawPolyline(). All you have to do is adjust the formula.

Finding pixels covered by an oval in Java Canvas

I'm creating a graphical display to show whether a user is approaching a danger zone. For this i'm using a display similar to that of an archery board. The idea is to start in the center, but as the user gets closer to the danger zone enter the orange zone. And once the user breaks the 'safety threshold' enter the red zone. My idea is to draw a point on the board depending on what value the user gives me.
To draw this board I do the following.
Graphics2D g2d = (Graphics2D) bs.getDrawGraphics();
g2d.setColor(Color.white);
g2d.fillRect(0, 0, 800, 600); //set screen to white
g2d.setColor(Color.red);
g2d.fillOval(250, 250, 175, 175); //draw outerlayer of board as red
g2d.setColor(Color.black);
g2d.drawOval(250, 250, 175, 175);//give this red an outline
g2d.setColor(Color.orange);
g2d.fillOval(275, 275, 125, 125); //draw innerlayer as orange
g2d.setColor(Color.black);
g2d.drawOval(275, 275, 125, 125);//give this orange an outline
g2d.setColor(Color.green);
g2d.fillOval(300, 300, 75, 75); //draw innermost layer as green
g2d.setColor(Color.black);
g2d.drawOval(300, 300, 75, 75); //give the green an outline
First of all I could probably improve this, but that's not the main issue for now.
Instead my issue is finding exactly the pixels covered by each part of the board.
I've been using x+(width/2), y+(height/2) to get the center point
Thus using:
g2d.drawString(String.valueOf("X"), 338, 338);
To draw the center point of my green oval. This doesn't seem overly accurate but anyway.
I thought I would be able to simply give the outer edge as the x,y co-ords and the inner edge as the x+height, y+width co-ords as so:
g2d.drawOval(500, 500, 75, 75);
g2d.drawString(String.valueOf("X"), 537, 537); //centre???
g2d.drawString(String.valueOf("X"), 575, 575); //inneredge?x+width, y+height
g2d.drawString(String.valueOf("X"), 500, 500); //outer edge x+y co-ords
However, I think due to the oval shape this doesn't work.
I would be very grateful if someone could show me how to find the pixel range that each oval covers.
EDIT: Below is the board that i'm using, is it possible to find the pixel range for each color(Red,Orange,Green)?
Understanding a bit more what you wanted, here is the trick (using trigonometry):
int force = ...; // from 0 to 250
int radius = ...; // radius of the target (50 for example)
int centerX = ...; // X-coordinate of the center of the target
int centerY = ...; // Y-coordinate of the center of the target
double direction = Math.toRadians(Math.random() * 360); // a random angle between 0° and 360°
double x = (force * radius / 250.0d) * Math.cos(direction) + centerX; // X-coordinate of the new point
double y = (force * radius / 250.0d) * Math.sin(direction) + centerY; // Y-coordinate of the new point
Point2D point = new Point2D.Double(x,y); // Then you can plot this point on your target
All of your ovals appear to be circles. So, let's create a Circle model class.
You would call the draw method from a JPanel paintComponent method.
You would call the contains method when you want to see if a point is inside or on the edge of a circle.
You would keep track of all of the circles in a List, so you can maintain the order of the circles.
package com.ggl.testing;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public class Circle {
private final int radius;
private final Color color;
private final Point location;
public Circle(int x, int y, int radius, Color color) {
this.location = new Point(x, y);
this.radius = radius;
this.color = color;
}
public boolean contains(int x, int y) {
double distance = Point.distance(x, y, location.x, location.y);
double radiusD = radius;
if (radiusD >= distance) {
return true;
} else {
return false;
}
}
public void draw(Graphics g) {
g.setColor(color);
g.fillOval(location.x - radius, location.y - radius, radius + radius,
radius + radius);
}
}
Use a concrete Ellipse2D for each zone. Then you can use g2d.fill() to draw the zone. Since an Ellipse2D is also a Shape, you can use the contains(Point2D p) method to check if a point is in bounds. Since the circles overlap, you'll have to check them in front-to-back order.

graphing data from a website

I am creating a program where I plot the maximum daily temperature for a specific city using data retrieved directly from the National Weather Service web site. I have the data, but the program errors when I try to create the actual graph. My error says that I need a return type but if you look a my code, I have one. Its in OOP format so the code I will show you is part of the implementation class. Can someone tell me how to fix my error?
My error:
invalid method declaration; return type required
My Code:
public class createGraph
{
Picture canvas = null;
Graphics g = null;
Graphics2D g2 = null;
DrawingGraph(int length, int height, Color color)
{
canvas = new Picture(length, height);
canvas.setAllPixelsToAColor(color);
g = canvas.getGraphics();
g2 = (Graphics2D)g;
g2.setColor(color);
}
public void drawARectangle(Color color, int x1, int y1, int width, int height)
{
g2.setColor(color);
g2.drawRect(x1, y1, width, height);
}
public Picture getGraph()
{
return canvas;
}
g.drawString("Maximum Temperature Readings", 196, 65);
g.drawString("Pensacola, FL - August, 2009", 205, 80);
int xPos = 97;
for(int day = 1; day <= 31; day++)
{
xPos = xPos + 13;
g.drawLine(xPos, 500, xPos, 510);
}
for(int yPos = 100; yPos <= 500; yPos +=40)
{
g.drawLine(93,yPos, 100, yPos);
}
g.drawString("100", 70, 105);
g.drawString("90", 75, 145);
g.drawString("80", 75, 185);
g.drawString("70", 75, 225);
}
The final graph should end up looking like this:
This code here:
DrawingGraph(int length, int height, Color color)
{
canvas = new Picture(length, height);
canvas.setAllPixelsToAColor(color);
g = canvas.getGraphics();
g2 = (Graphics2D)g;
g2.setColor(color);
}
Is that supposed to be a method or the constructor? If it's a normal method, you need void, or if it's the constructor, it should be the same name as the class.
You also have lots of code which is not in a method at all.
DrawingGraph isn't an function nor a Constructor, if it's meant to be an function, it needs am return-Type, if it should be a Constructor, it must have the same name as the class.
Also, the last part of your class, after getGraph(), must be in a function, but is located directly in the class body.
Just declare an new Function and move it in it an call it.
the class name starts with a lowerCase.
Are you shure that you did't swap "lowerCase" and "DrawingGraph" ?

How can I rotate an onscreen component in Java?

import javax.swing.*;
import java.awt.*;
public class JFrameAnimationTest extends JFrame {
public static void main(String[] args) throws Exception{
AnimationPanel animation = new AnimationPanel();
JFrameAnimationTest frame = new JFrameAnimationTest();
frame.setSize(600, 480);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(animation);
frame.setVisible(true);
for(int i = 0; i < 100; i++) {
animation.incX(1);
//animation.incY(1);
animation.repaint();
Thread.sleep(10);
}
}
}
class AnimationPanel extends JPanel {
int x = 10;
int y = 10;
public AnimationPanel() {
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawRect(x, y, 20, 20);
g.fillRect(x, y, 20, 20);
}
protected void incX(int X) {
x += X;
}
protected void incY(int Y) {
y += Y;
}
}
So anyways theres my code. It probably looks a bit jumbled as I am not used to stackoverflow just yet so I apologize.
Here's my question: This program makes this small rectangle slowly move to the right; how can I add rotation to the rectangles movement during that time period?
Note: I haven't actually compiled this code, but you get the gist.
public void paintComponent( Graphics g )
{
super.paintComponent( g );
Graphics2D g2d = (Graphics2D) g;
// The 20x20 rectangle that you want to draw
Rectangle2D rect = new Rectangle2D.Double( 0, 0, 20, 20 );
// This transform is used to modify the rectangle (an affine
// transform is a way to do operations like translations, rotations,
// scalings, etc...)
AffineTransform transform = new AffineTransform();
// 3rd operation performed: translate the rectangle to the desired
// x and y position
transform.translate( x + 10, y + 10 );
// 2nd operation performed: rotate the rectangle around the origin
transform.rotate( rotation );
// 1st operation performed: translate the rectangle such that it is
// centered on the origin
transform.translate( -10, -10 );
// Apply the affine transform
Shape s = transform.createTransformedShape( rect );
// Fill the shape with the current paint
g2d.fill( s );
// Stroke the edge of the shape with the current paint
g2d.draw( s );
}
Also note that you should really be using something like a javax.swing.Timer when you modify x, y, and rotation and when you call repaint(). That way all of it happens on the event dispatch thread.

Categories

Resources