I am currently in the process of coding a kind of drawing tool in Processing. I want to be able to draw a black line with the mouse, but have it fade away again. For this I first thought of working with a black ellipse that fades from black to white. This ellipse is then linked to the mouse pointer via mouseX and mouseY. Because I want each drawn ellipse to fade from black to white individually (to create the effect that the line fades again), I thought of working with objects. This works so far, but the fading does not work yet.
I want the ellipse at the mouse pointer to always be black and then only change to white once the mouse pointer has been moved further or drawn further... just like a fade...
Should I use an ArrayList for this? And say that a new object should be drawn at the MouseX and MouseY position per frame? Do I need PVector for this?
This is what I came up for this so far:
float counter;
PGraphics pg;
Brush myBrush;
void setup() {
size(600, 600);
pg = createGraphics(width, height);
}
void draw() {
//background(255);
color from = color(0);
color to = color(255);
color faded = lerpColor(from, to, counter);
myBrush = new Brush(faded, mouseX, mouseY);
myBrush.display();
}
class Brush {
color tempC;
float xpos;
float ypos;
color c;
Brush(color tempC, float tempXpos, float tempYpos) {
c = tempC;
xpos = tempXpos;
ypos = tempYpos;
}
void display() {
noStroke();
fill(c);
ellipse(xpos, ypos, 50, 50);
counter = counter + 0.01;
}
}
The issue you're struggling with here is that you can only know how to fade the line once the line has been drawn, but you draw it while the user move the mouse.
To deal with this issue, I would suggest to store every information needed to draw the line in an object, and update it as the user is drawing. As you guessed, you could totally use an ArrayList to achieve this.
I modified your code quite heavily to simplify my own life, and I commented the result so it would be easier for you to re-cast it into your own project on your own terms.
I used objects to keep everything tidy. The logic here goes as follow: The Canvas object contains the drawing. It's made of Line objects, which are themselves made of Dots.
Here's the commented code:
Canvas canvas;
void setup() {
size(600, 600);
canvas = new Canvas();
}
void draw() {
// instead of drawing only once, we're going to save every line the user draw in teh canvas object
background(255);
// the canvas object has to calculate stuff, then display itself
canvas.Update();
canvas.Display();
}
// setting up the mousePressed and mouseReleased events so the canvas object "knows"
void mousePressed() {
canvas.mouseDown = true;
}
void mouseReleased() {
canvas.mouseReleased = true;
canvas.mouseDown = false;
}
class Canvas {
boolean mouseDown;
boolean mouseReleased = true;
ArrayList<Line> lines = new ArrayList<Line>(); // every line will be stored in this list
Brush brush; // the brush object can be modified with different sizes or colors
Canvas() {
// here i use a default brush, but you can experiment different colors or sizes
brush = new Brush(color(0, 200, 0), color(0), color(255), 50);
}
void Update() {
brush.highlight = mouseDown; // so the user has visual feedback while drawing
if (mouseDown) {
if (mouseReleased) { // if this is a "new" line, add a line object to store it
lines.add(new Line(brush.colorFrom, brush.colorTo));
mouseReleased = false;
}
// add a dot at the mouse's current position, then update the fading
lines.get(lines.size()-1).Add(new Dot(mouseX, mouseY, brush.diameter, brush.colorFrom));
lines.get(lines.size()-1).ApplyFade();
}
}
void Display() {
// for every Line, draw every Dot... then don't forget to display the brush!
for (Line l : lines) {
for (Dot d : l.dots) {
d.Display();
}
}
brush.Display();
}
}
// A line is a bunch of dots and two colord (for the fade effect)
class Line {
ArrayList<Dot> dots = new ArrayList<Dot>();
color colorFrom, colorTo;
Line(color colorFrom, color colorTo) {
this.colorFrom = colorFrom;
this.colorTo = colorTo;
}
void Add(Dot d) {
dots.add(d);
}
// This method calculate how many dots there are in the line to better distribute the shades of the fade
void ApplyFade() {
for (int i=0; i<dots.size(); i++) {
Dot d = dots.get(i);
d.c = lerpColor(colorFrom, colorTo, (float) i/dots.size());
}
}
}
// a Dot has a size, a position and a color
class Dot {
float xpos;
float ypos;
float diameter;
color c;
Dot(float xpos, float ypos, float diameter, color c) {
this.xpos = xpos;
this.ypos = ypos;
this.diameter = diameter;
this.c = c;
}
void Display() {
noStroke();
fill(c);
ellipse(xpos, ypos, diameter, diameter);
}
}
// this class is overdesigned so in the future you can change the brush's characteristics like the fade'S colors or simply it's size
class Brush {
boolean highlight;
float diameter, xpos, ypos;
color circleColor, colorFrom, colorTo;
Brush(color circleColor, color colorFrom, color colorTo, float diameter) {
this.circleColor = circleColor;
this.colorFrom = colorFrom;
this.colorTo = colorTo;
this.diameter = diameter;
}
void Display() {
stroke(circleColor);
strokeWeight(5);
noFill();
ellipse(mouseX, mouseY, diameter, diameter);
if (highlight) { // if the mouse's button is down, give visual feedback about the brush
stroke(0);
strokeWeight(4);
ellipse(mouseX, mouseY, diameter, diameter);
stroke(255);
strokeWeight(3);
ellipse(mouseX, mouseY, diameter, diameter);
}
}
}
Hope this helps. I'll be around if you have questions about the code. Have fun!
Here is a version with an ArrayList and Object... The problem here is that all ellipse objects fade away at the same time... I would like to achieve that each ellipse is first drawn black and then after time X becomes white... Like a fingerprint on a sensor for example... A lot of pressure: black, little pressure (or no pressure): fade to white... Later on I want to draw everything on a PGraphics layer – therefore there is alyready this variable...
float counter;
PGraphics pg;
ArrayList<PVector> positionsList;
Brush myBrush;
void setup() {
size(600, 600);
positionsList = new ArrayList<PVector>();
pg = createGraphics(width, height);
}
void draw() {
background(255);
color from = color(0);
color to = color(255);
color faded = lerpColor(from, to, counter);
for (PVector p : positionsList) {
myBrush = new Brush(faded, p.x, p.y);
myBrush.display();
}
positionsList.add(new PVector(mouseX, mouseY));
counter = counter + 0.01;
}
class Brush {
color tempC;
float xpos;
float ypos;
color c;
Brush(color tempC, float tempXpos, float tempYpos) {
c = tempC;
xpos = tempXpos;
ypos = tempYpos;
}
void display() {
noStroke();
fill(c);
ellipse(xpos, ypos, 50, 50);
}
}
Related
I like working with Processing array functions but when I draw things using this function, I realize it's storing every single drawn shape in the memory, which is causing spikes in CPU. (Especially when it goes up to a few thousands)
How to bake the drawing then remove the array objects on mouserelease? I mean, can Processing behave those objects as a single image after every stroke then I'd clear the array using .remove(0) function?
Here's my code:
ArrayList <Drawing> drawings = new ArrayList <Drawing>();
void setup() {
size(400, 400);
background(255);
colorMode(HSB);
}
void draw() {
background(255);
for (int i=0;i<drawings.size();i++) {
drawings.get(i).display();
}
println(drawings.size());
}
void mouseDragged() {
drawings.add(new Drawing(mouseX, mouseY));
}
class Drawing {
float x, y, r;
color c;
Drawing(float ax, float ay) {
x=ax;
y=ay;
r=random(2, 20);
c=color(random(100, 200), 255, 255, 88);
}
void display() {
noStroke();
fill(c, 100);
ellipse(x,y, r, r);
}
}
If you want to store the objects into the ArrayList only while the mouse is pressed (drawing new objects) and just have all the old objects to be static on the background out of the ArrayList you can do something like this:
ArrayList<Drawing> drawings = new ArrayList();
boolean flag = false;
void setup()
{
size(400, 400);
background(255);
colorMode(HSB);
loadPixels();
}
void draw()
{
updatePixels();
if(flag)
{
for(Drawing drawing : drawings)
{
drawing.display();
}
}
println(drawings.size());
}
void mouseDragged()
{
flag = true;
Drawing drawing = new Drawing(mouseX, mouseY);
drawings.add(drawing);
}
void mouseReleased()
{
flag = false;
loadPixels();
drawings = new ArrayList();
}
class Drawing
{
float x, y, r;
color c;
Drawing(float ax, float ay)
{
x=ax;
y=ay;
r=random(2, 20);
c=color(random(100, 200), 255, 255, 88);
}
public void display()
{
noStroke();
fill(c, 100);
ellipse(x,y, r, r);
}
}
The function loadPixels() stores into the pixels[] array all the pixels of the screen, while updatePixels() draws the pixels in pixels[] on the canvas. This way you can just empty your ArrayList every time the mouse is released and, even though when the ArrayList gets some thousands of elements you still get some CPU spikes, when the mouse is not being dragged or the ArrayList has less than a couple thousands of elements it is less CPU consuming.
If you don't need to access the drawings objects later (say to change properties), you can simply cache the rendering onto a separate PGraphics layer:
PGraphics drawings;
void setup() {
size(400, 400);
colorMode(HSB);
drawings = createGraphics(width, height);
// use drawing commands between beginDraw() / endDraw() calls
drawings.beginDraw();
drawings.background(255);
drawings.colorMode(HSB);
drawings.noStroke();
drawings.endDraw();
}
void draw() {
background(255);
// PGraphics extends PImage so you can render it the same way
image(drawings, 0, 0);
println((int)frameRate);
}
void mouseDragged() {
drawRandomCircle(drawings, mouseX, mouseY);
}
void drawRandomCircle(PGraphics layer, float x, float y){
float diameter = random(2, 20);
layer.beginDraw();
layer.fill(color(random(100, 200), 255, 255, 88));
layer.ellipse(x, y, diameter, diameter);
layer.endDraw();
}
Otherwise you can make use of PShape:
PShape drawings;
void setup() {
size(400, 400, P2D);
smooth();
background(255);
colorMode(HSB);
// create a PShape group to append circles to later
drawings = createShape(GROUP);
}
void draw() {
background(255);
// render PShape
shape(drawings);
println(drawings.getChildCount() + " shapes at ~" + (int)frameRate + "fps");
}
void mouseDragged() {
drawings.addChild(addRandomCircle(mouseX, mouseY));
}
PShape addRandomCircle(float x, float y){
float diameter = random(2, 20);
// create an ellipse PShape with the desired dimensions, position, fill and (no)stroke
PShape circle = createShape(ELLIPSE, x, y, diameter, diameter);
circle.setFill(color(random(100, 200), 255, 255, 88));
circle.setStroke(false);
return circle;
}
As mentioned in my comment check out Processing > Examples > Demos > Performance > StaticParticlesRetained
If you need later access to each added circle/drawing you can iterate over the parent PShape:
// iterate though nested PShapes
for(int i = 0 ; i < drawings.getChildCount(); i++){
// access each PShape
PShape drawing = drawings.getChild(i);
// access PShape properties
println("drawings[" + i + "] has " + drawing.getVertexCount() + " vertices");
}
Should you need extra functionality (like a separate property to animate), you can always extend PShape: re-use what's already there add what you need on top:
PShape drawings;
void setup() {
size(400, 400, P2D);
smooth();
background(255);
colorMode(HSB);
// create a PShape group to append circles to later
drawings = createShape(GROUP);
}
void draw() {
background(255);
// use custom functionality
for(int i = 0 ; i < drawings.getChildCount(); i++){
// cast from PShape superclass to the custom Drawing subclass
Drawing drawing = (Drawing)drawings.getChild(i);
// use the custom functionality
drawing.update(i);
}
// render PShape
shape(drawings);
println(drawings.getChildCount() + " shapes at ~" + (int)frameRate + "fps");
}
void mouseDragged() {
drawings.addChild(new Drawing((PGraphicsOpenGL)g, mouseX, mouseY));
}
class Drawing extends PShapeOpenGL{
float x, y, diameter;
Drawing(PGraphicsOpenGL pg, float x, float y){
// call PShape super constructor setting this as a primitive (e.g. POINT, LINE, RECT, ELLIPSE, etc.)
super(pg, PShape.PRIMITIVE);
setKind(ELLIPSE);
diameter = random(2, 20);
// set (ellipse) shape parameters
setParams(new float[]{x, y, diameter, diameter});
// fill
setFill(color(random(100, 200), 255, 255, 88));
// disable stroke
setStroke(false);
// remember original position
this.x = x;
this.y = y;
}
// a custom functionality on top of PShape
void update(int index){
float offset = map(sin((frameCount + ((index+1) * 10)) * 0.025), -1.0, 1.0, -15, 15);
// reset transformations
this.resetMatrix();
// translate backwards
this.translate(-x, -y);
// translate back + the offset
this.translate(x + offset, y);
}
}
For the full list of functionalities see PShape javadocs
Starting with the simplest thing though. If you want to simply render many shapes without changing them later PGraphics will do the trick
I am trying to create a round brush with blurred edges in Processing through the following code. The circle shape is drawn pixel by pixel because in the actual version, I try to draw with pixels taken from the PGraphic pg.
PFont font;
PGraphics pg;
int X;
int Y;
int rad = 20;
void setup (){
size(800, 800, P2D);
background(0);
noStroke();
pg = createGraphics(800, 800, JAVA2D);
pg.beginDraw();
pg.fill(255);
pg.noStroke();
pg.textFont(font);
pg.textSize(400);
pg.pushMatrix();
pg.translate(width/2, height/2-140);
pg.textAlign(CENTER, CENTER);
pg.text("b", 0 , 0);
pg.popMatrix();
pg.endDraw();
}
void draw () {
image(pg,0,0);
}
void mousePressed(){
X = mouseX;
Y = mouseY;
}
void mouseDragged(){
for (int x=0; x<rad; x++) {
for (int y=0; y<rad; y++) {
float distance = sqrt(pow(x,2)+pow(y,2));
float alpha = 255-map(distance,0,rad,0,255);
if (sqrt(pow(x,2)+pow(y,2)) < rad){
pg.beginDraw();
pg.set(mouseX+x,mouseY+y,color(255,255,255, alpha));
pg.set(mouseX-x,mouseY+y,color(255,255,255, alpha));
pg.set(mouseX+x,mouseY-y,color(255,255,255, alpha));
pg.set(mouseX-x,mouseY-y,color(255,255,255, alpha));
pg.endDraw();
}
}
}
}
Create a function which draw a single dot to a PGraphics object:
void DrawPen(PGraphics pg, int cptX, int cptY, int r) {
pg.beginDraw();
for (int x = 0; x < r; ++x) {
for (int y = 0; y < r; ++y) {
float distance = sqrt(x*x + y*y);
float alpha = 255-map(distance,0,r,0,255);
if (distance < r) {
pg.set(cptX+x,cptY+y,color(255,255,255, alpha));
pg.set(cptX-x,cptY+y,color(255,255,255, alpha));
pg.set(cptX+x,cptY-y,color(255,255,255, alpha));
pg.set(cptX-x,cptY-y,color(255,255,255, alpha));
}
}
}
pg.endDraw();
}
Draw a dot to a separate PGraphics object in setup
PGraphics pg;
PGraphics pg_pen;
int rad = 20;
void setup (){
size(800, 800, P2D);
pg = createGraphics(800, 800, JAVA2D);
pg.beginDraw();
// [...]
pg.endDraw();
pg_pen = createGraphics(2*rad, 2*rad, JAVA2D);
DrawPen(pg_pen, rad, rad, rad);
}
When the mouse is dragged then blend the pg_pen to the common PGraphics object (pg) at the current mouse position:
void mouseDragged(){
pg.beginDraw();
pg.image(pg_pen, mouseX-rad, mouseY-rad);
pg.endDraw();
}
For the seek of completeness the draw function:
void draw () {
background(0);
image(pg,0,0);
}
[...] and tried to get the color from the white part to draw on the black part.
Add a color parameter to the DrawPen function and clear the pen PGraphics before drawing to it:
void DrawPen(PGraphics pg, int cptX, int cptY, int r, color c) {
pg.beginDraw();
pg.clear();
for (int x = 0; x < r; ++x) {
for (int y = 0; y < r; ++y) {
float distance = sqrt(x*x + y*y);
float alpha = 255-map(distance,0,r,0,255);
if (distance < r) {
color pc = color(red(c),green(c),blue(c), alpha);
pg.set(cptX+x,cptY+y,pc);
pg.set(cptX-x,cptY+y,pc);
pg.set(cptX+x,cptY-y,pc);
pg.set(cptX-x,cptY-y,pc);
}
}
}
pg.endDraw();
}
Get the color in the mouse pressed event call back and change the color of the pen:
void mousePressed() {
color c = pg.get(mouseX, mouseY);
println(c);
DrawPen(pg_pen, rad, rad, rad, c);
}
Note, the color is get from the pg object and not from the screen. If you want to get the color from the screen then it has to be (without .pg):
color c = get(mouseX, mouseY);
Further the color is changed any time when any mouse is pressed (pressed not dragged). Possibly you want to change the color when the right mouse button is pressed and paint when the left mouse button is pressed:
void mousePressed() {
if (mouseButton == RIGHT) {
color c = pg.get(mouseX, mouseY);
println(c);
DrawPen(pg_pen, rad, rad, rad, c);
}
}
add a "background(0);" before "image(pg,0,0);" in your drawing method, that way you reset the background every time, if you don't do that the program will keep drawing every frame images on top of each other's, which will make the low opacity pixel gain opacity slowly every frame until reaching 100%
void draw () {
background(0);
image(pg,0,0);
}
Edit:
After testing your code I noticed there was a problem with the way you were creating those circles, making it super slow to run (every frame you go through that double for loop to draw one circle ) and also gave that weird black edges problem, so here is what I did:
First I used your variable pg and drew one circle on it on the startup, Then I declared another PGraphics 'pg_all', where I drew one pg every call of the mousedrag method, I tested it on multiple backgrounds it seems like working fine, here is the final code, let me know if you didn't understand a part or want to do it differently:
PFont font;
PGraphics pg;
PGraphics pg_all;
int X;
int Y;
int rad = 20;
void setup (){
size(800, 800, P2D);
background(0);
noStroke();
pg_all = createGraphics(800, 800, JAVA2D);
pg_all.beginDraw();
pg_all.endDraw();
pg = createGraphics(800, 800, JAVA2D);
pg.beginDraw();
for (int x=0; x<rad; x++) {
for (int y=0; y<rad; y++) {
float distance = sqrt(pow(x,2)+pow(y,2));
float alpha = 255-map(distance,0,rad,0,255);
if (sqrt(pow(x,2)+pow(y,2)) < rad){
pg.beginDraw();
pg.set(20+x,20+y,color(255,255,255, alpha));
pg.set(20-x,20+y,color(255,255,255, alpha));
pg.set(20+x,20-y,color(255,255,255, alpha));
pg.set(20-x,20-y,color(255,255,255, alpha));
pg.endDraw();
}
}
}
pg.endDraw();
}
void draw () {
background(0);
image(pg_all,0,0);
}
void mouseDragged(){
X = mouseX;
Y = mouseY;
pg_all.beginDraw();
pg_all.image(pg,X-rad,Y-rad);
pg_all.endDraw();
}
I am making a program which draws circles in the clicked place.
For the first click it draws circle which is not exactly in the same place I have clicked.
But furthermore, for other clicks it just draws circles one on the other. as i find out it is because the coordinates of click won't change.
my main:
public static void main(String[] args)
{
JFrame frame = new JFrame();
//set window size
frame.setSize(1000, 1000);
//set the title
frame.setTitle("Oval Draw");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//add panel to frame and make it visible
MouseComponent component = new MouseComponent();
frame.add(component);
frame.setVisible(true);
}
and the MouseComponent class:
public class MouseComponent extends JPanel implements MouseListener
{
boolean drawPoint = true;
boolean drawLine = false;
boolean drawOval = false;
public MouseComponent()
{
super();
pointX = 0;
pointY = 0;
lineX = 0;
lineY = 0;
addMouseListener(this);
}
int pointX, pointY, lineX, lineY;
int[] ArrayX,ArrayY;
#Override
public void paintComponent(Graphics g)
{
for(int i=0; i<10; i++)
{
super.paintComponent(g);
if(drawLine)
{
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color startrandomColor = new Color(red, green, blue);
red = (int) (Math.random() * 255);
green = (int) (Math.random() * 255);
blue = (int) (Math.random() * 255);
Color endrandomColor = new Color(red, green, blue);
Graphics2D g2d = (Graphics2D) g;
// this.addMouseListener(this);
GradientPaint gradient = new GradientPaint(70, 70, startrandomColor,
150, 150, endrandomColor);
g2d.setPaint(gradient);
g2d.translate( lineX, lineY);
g2d.fillOval(70, 70, 100, 100);
System.out.print(lineX);
System.out.print(" ");
System.out.print(lineY);
System.out.print(" ");
System.out.print(pointX);
System.out.print(" ");
System.out.print(pointY);
System.out.print(" ");
// repaint();
}
else if(drawPoint)
{
// g.drawOval(pointX-5,pointY-5,10,10);
}
}
}
public void mouseClicked(MouseEvent mouse)
{
if(!drawPoint)
{
pointX = mouse.getX();
pointY = mouse.getY();
drawPoint = true;
}
else if(!drawLine)
{
lineX = mouse.getX();
lineY = mouse.getY();
drawLine = true;
}
repaint();
}
public void mouseEntered(MouseEvent mouse){ }
public void mouseExited(MouseEvent mouse){ }
public void mousePressed(MouseEvent mouse){ }
public void mouseReleased(MouseEvent mouse){ }
}
This here:
if(!drawPoint)
{
pointX = mouse.getX();
pointY = mouse.getY();
drawPoint = true;
}
simply doesn't make too much sense. You init drawPoint to true ... so you will never enter the if block and collect the click coordinates.
And beyond that: when you look into your other method --- the code to draw points is commented out.
Suggestion: step back; don't try to do 5 things at the same time. Write the code it takes to
fetch mouse coordinates after a click
draw circles around that coordinate
and get that to work. Forget about drawing lines, shapes, whatever for now.
And when you have a class that does nothing but that click+draw circles; then create a new class, where you add more features. Your "real" problem right now is that you started working on various features; and that your attempts to "integrate" them into a single class left you with something that is confusing, and not surprising ... not working!
Long story short: forgot about that strange logic that you have in your code right now to "toggle" between drawing points and lines. Draw points. And then, when that works ... add some radio buttons; or a drop down menu and use that to control if you want to draw lines or points. Don't make that "implicit" by toggling booleans in your event handler code!
boolean drawPoint = true;
boolean drawLine = false; cause it to print the first time. After that both are set to true so it will not change coordinates.
Essentially, in this program bugs move around the screen eating food.
The issue that I am having is that graphics "circle" repaints fine and moves around the frame, but none of the bugs are repainted (However they are drawn initially).
I've tested it with console outputs and the x and y coordinates of the bugs do update, but the graphic in the frame does not.
So my question is, why is it the x/y of the circle is updated and repainted, but the bugs are not?
(As far as I can see, I'm approaching the task of changing the bugs x/y in the same way as with the circle)
(I've removed some of the things like the world getters and setters, and cut the code down a bit. The actual program has a movebug() method which handles the moving of the bugs in a correct fashion with hit detection.)
public class Run extends JPanel implements ActionListener{
double x, y, velX, velY, newx, newy;
public Timer t;
private static AWorld world1;
ArrayList<Ellipse2D> graphicBugArrayList = new ArrayList<Ellipse2D>();
public Run(){
x = 150;
y = 150;
velX = 2;
velY = 2;
t = new Timer(5, this);
setWorld1(new AWorld());
getWorld1().populatemap();
AWorld.direction directionchecker;
repaint();
t.start();
}
public void paintComponent(Graphics g){
//Creating circle that move
g.setColor(Color.BLACK);
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle = new Ellipse2D.Double(x, y, 10, 10);
//creating and drawing the bugs
for(int i=0; i<world1.getNumberofbugs(); i++)
{
Ellipse2D obscircle = new Ellipse2D.Double(getWorld1().bugArrayList.get(i).getHPosition(), getWorld1().bugArrayList.get(i).getVPosition(), 14, 15);
graphicBugArrayList.add(obscircle);
g2.setPaint(Color.RED);
g2.fill(graphicBugArrayList.get(i));
g2.draw(graphicBugArrayList.get(i));
}
//Drawing the circle that moves
g2.setPaint(Color.BLACK);
g2.draw(circle);
}
public void actionPerformed(ActionEvent arg0) {
//Moving the circle
if(x<0 || x > 500)
{
velX = -velX;
}
if(y<0 || y > 500)
{
velY = -velY;
}
x += velX;
y -= velY;
//Test moving the bugs
getWorld1().bugArrayList.get(i).setHPosition(getWorld1().bugArrayList.get(i).getHPosition()+1);
repaint();
}
}
You never clear your graphicBugArrayList, but only draw the first few elements over and over. Try this in your loop:
for(int i=0; i<world1.getNumberofbugs(); i++)
{
Ellipse2D obscircle = new Ellipse2D.Double(getWorld1().bugArrayList.get(i).getHPosition(), getWorld1().bugArrayList.get(i).getVPosition(), 14, 15);
graphicBugArrayList.add(i, obscircle);
g2.setPaint(Color.RED);
g2.fill(graphicBugArrayList.get(i));
g2.draw(graphicBugArrayList.get(i));
}
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.