I want to animate multiple paths in sequence, for example, I have
Path[] line and Path[] circle
so when I do for example
line[0].moveTo(x, y);
graphPath[j].lineTo(x, y);
I want to animate this part first and when
finish I want to add circle in same x,y postion
circle[0].addCircle(x, y, 10, Path.Direction.CW);
what I have done so far inside onDraw()
#Override
protected void onDraw(Canvas canvas) {
for (int j = 0; j < 2; j++) {
if (dataPoints2[j] != null) {
float x = leftPadding;
float y = height * getDataPoint(0, j) + topPadding;
graphPath[j].moveTo(x, y);
circlePath[j].addCircle(x, y, 10, Path.Direction.CW);
for (int i = 1; i < dataPoints2[j].size(); i++) {
x = width * (((float) i ) / dataPoints2[j].size()) + leftPadding;
y = height * getDataPoint(i, j) + topPadding;
graphPath[j].lineTo(x, y);
circlePath[j].addCircle(x, y, 10, Path.Direction.CW);
}
}
}
PathMeasure measure = new PathMeasure(graphPath[0], false);
length = measure.getLength();
ObjectAnimator animator = ObjectAnimator.ofFloat(Chart.this, "phase", 1.0f, 0.0f);
animator.setDuration(8000);
animator.start();
for (int j = 0; j < graphPath.length; j++) {
canvas.drawPath(graphPath[j], linePaint[j]);
canvas.drawPath(circlePath[j], circlePaint[j]);
}
}
public void setPhase(float phase){
linePaint[0].setPathEffect(createPathEffect(length, phase, 0.0f));
invalidate();
}
private static PathEffect createPathEffect(float pathLength, float phase, float offset)
{
return new DashPathEffect(new float[] { pathLength, pathLength },
Math.max(phase * pathLength, offset));
}
this will draw the circle then animate the line connecting the circle points
what I need is to animate the line and draw circle when the line reaches every x,y points
Related
I am trying to create some trippy "animation" such as this image; Trippy circles
I can just place another circle into the circle by brute-forcing it. However, I am pretty sure that there is an easier way of doing it by either using "while" or "for". I am pretty new to coding so I have no idea which logic to use.
Here is my brute-forced code below.
int m = millis();
void setup(){
size(1136,936);
}
void draw(){
ellipseMode(CENTER);
frameRate(1.3);
background(255);
if (millis() > m + 1000){
for (int diameter = 0; diameter < 500; diameter = diameter+1) {
float r1 = random(1,1000);
float r2 = random(1,900);
fill(255);
circle(r1, r2, diameter);
fill(0);
circle(r1,r2,diameter/2);
}
}
}
Thanks!
This comes close to what your example looks like (based on your original code):
int m = millis();
void setup(){
size(1136,936);
}
int colors[] = { 0, 255 };
void draw(){
ellipseMode(CENTER);
//frameRate(1.3);
background(255);
if (millis() > m + 1000) {
for (int i = 0; i < 500; i = i+1) {
float x = random(1,1000);
float y = random(1,900);
float radius = 300;
float delta = 30;
int counter = 0;
while (radius >= delta) {
fill(colors[counter % colors.length]);
ellipse(x, y, radius, radius);
counter++;
radius -= delta;
}
}
}
}
So I am nearly at the end.
I have been researching the whole day on how to do this.
Draw a path which grows(animation) from one point to another.
I have tried it with Matrix, but that just ended with turning my whole paths.
Here is a image of my project:
my project
My goal is to draw a animated path from one circle to the other.
Code:
public void init(#Nullable AttributeSet attr) {
circle = new Paint();
circle.setColor(Color.GREEN);
circle.setStyle(Paint.Style.FILL);
circle.setAntiAlias(true);
line = new Paint();
line.setColor(Color.GREEN);
line.setStyle(Paint.Style.STROKE);
line.setStrokeWidth(10);
line.setAntiAlias(true);
Collections.addAll(height, 100, 20, 50, 40, 70, 10, 50); // in percent
System.out.println(height.size() + " this is the size");
}
#Override
protected void onDraw(Canvas canvas) {
float y = getHeight() / 20 * 14;
float x = getWidth() / 8;
float radius = (canvas.getWidth() * canvas.getHeight()) / 40940;
for (int c = 1; c < 8; c++) {
System.out.println("at " + c);
canvas.drawCircle(x * c, y - ((getHeight() / 20) * (height.get(c - 1) / 10)), radius, circle);
points.add(new PointF(x * c, (y - ((getHeight() / 20) * (height.get(c - 1) / 10)))));
}
}
Please Help,
Thanks
you just need animate the path using ValueAnimator
create one path object
Path path = new Path();
and create animator
ValueAnimator animator = new ValueAnimator();
float startX = // starting circle x co-ordinate
float startY = // starting circle y co-ordinate
float endX = // end circle x co-ordinate
float endY = // end circle y co-ordinate
PropertyValuesHolder propertyX = PropertyValuesHolder.ofFloat("x",startX,endX);
PropertyValuesHolder propertyY = PropertyValuesHolder.ofFloat("y",startY,endY);
valueAnimator.setValues(propertyX,propertyY);
valueAnimator.setDuration(1000); // animation time
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float x = (float) animation.getAnimatedValue("x");
float y = (float) animation.getAnimatedValue("y");
path.lineTo(x,y);
invalidate();
}
});
valueAnimator.start();
and in onDraw() draw the path
canvas.drawPath(path,paint);
When I run the code it generates 16 rectangles with a random size, random position, and a random color. It is then supposed to turn white if it is colliding with another rectangle. Most of the time it works fine but every so often rectangles turn white when they are not colliding with anything.
Main
int boxCount = 16;
Box[] boxes = new Box[boxCount];
void setup(){
size(500, 500);
for(int i = 0; i < boxCount; i++){
boxes[i] = new Box(random(50, width - 50), random(50, height - 50), random(20, 50), random(20, 50), color(random(0, 255), random(0, 255), random(0, 255)));
}
}
void draw(){
for(int i = 0; i < boxCount; i++){
boxes[i].create();
for(int x = 0; x < boxCount; x++){
if(boxes[i] != boxes[x]){
boxes[i].collide(boxes[x]);
}
}
}
}
Class
class Box{
float x;
float y;
float w;
float h;
color c;
Box(float _x, float _y, float _w, float _h, color _c){
x = _x;
y = _y;
w = _w;
h = _h;
c = _c;
}
void create(){
fill(c);
rect(x, y, w, h);
}
void collide(Box o){
float right = x + (w / 2);
float left = x - (w / 2);
float top = y - (h / 2);
float bottom = y + (h / 2);
float oRight = o.x + (o.w / 2);
float oLeft = o.x - (o.w / 2);
float oTop = o.y - (o.h / 2);
float oBottom = o.y + (o.h / 2);
if(right > oLeft && left < oRight && bottom > oTop && top < oBottom){
c = color(255, 255, 255);
}
}
}
rect doesn't draw a rectangle around center point, by default the rectangle is drawn at a top left position (x, y) with a size (with, height).
You've 2 possibilities to solve the issue:
Either change the collision detection method:
class Box{
// [...]
void collide(Box o){
if(x < o.x+o.w && o.x < x+w && y < o.y+o.h && o.y < y+h){
c = color(255, 255, 255);
}
}
}
Or set the CENTER rectMode(), which will cause the rectangle to be drawn as you expect it:
class Box{
// [...]
void create(){
fill(c);
rectMode(CENTER);
rect(x, y, w, h);
}
// [...]
}
I have this code and I should modify it to do 2 things:
draw the surface in solid mode using the basic lighting (lights() and a unique fill()) and
draw the surface with a two color gradient (red for low values of z and yellow for high values, for instance) For that,I was advised use a fill() call before each vertex()
This is my code for the 1st one, the problem is that I do not want the grid to show after I have applied the color.
// Drawing a 3D function
float rotX = 0.0, rotY = 0.0;
int lastX, lastY;
float distX = 0.0, distY = 0.0;
// Function steps
int steps = 50;
// z scale
float scaleZ = 200.0;
// z zoom
float zoomZ = -300.0;
// Graphic size
float gX = 500.0, gY = 500.0;
void setup()
{
size(500, 500, P3D);
noFill();
strokeWeight(0.005);
}
float function(float x, float y)
{
return x*x*x + y*y*y;
}
void draw() {
lights();
background(0);
// We center the results on window
translate(gX/2, gY/2, zoomZ);
// Rotation
rotateY(rotY + distX);
rotateX(rotX + distY);
// Centering around (0, 0);
translate(-gX/2, -gY/2);
// Function covers
// 400 x 400 x scaleZ
scale(gX, gY, scaleZ);
// Drawing the function
fill(167);
drawFunction();
// Drawing axes
stroke(255, 0, 0);
line(0,0,0,2000,0,0);
stroke(0,255,0);
line(0,0,0,0,2000,0);
stroke(0,0,255);
line(0,0,0,0,0,2000);
}
void drawFunction()
{
float x, y, z;
int i = 0, j = 0;
float in_steps = 1.0 / steps;
float[][] matrix = new float[steps+1][steps+1];
for (y = 0.0, j = 0; y <= 1.0; y+=in_steps, j++)
for (x = 0.0, i = 0; x <= 1.0; x+=in_steps, i++)
matrix[i][j] = function(x, y);
stroke(167);
for (j = 0, y = 0.0; j < steps; j++, y+=in_steps) {
beginShape(QUAD_STRIP);
for (i = 0, x = 0.0; i <= steps; i++, x+=in_steps) {
vertex(x, y, matrix[i][j]);
vertex(x, y + in_steps, matrix[i][j+1]);
}
endShape();
}
}
void mousePressed()
{
lastX = mouseX;
lastY = mouseY;
}
void mouseDragged()
{
distX = radians(mouseX - lastX);
distY = radians(lastY - mouseY);
}
void mouseReleased()
{
rotX += distY;
rotY += distX;
distX = distY = 0.0;
}
The lights() are already proper set in your code.
Use noStroke() to get rid of the lines. noStroke disables drawing outlines.
The color of the filled areas can be set by passing RGB (red, green and blue) values to fill().
The values are integral values in the range[0, 255]. The RGB vlaue for red is (255, 0, 0) and the RGB value for yellow is (255, 255, 0).
A gradient color form red to yellow can be achieved by
fill(255, z*255, 0);
where z is in [0.0, 1.0]. If z = 0.0 the result is red (255, 0, 0) and if z = 1.0 the result is yellow (255, 255, 0). All values for z in between 0.0 and 1.0 result in a linear interpolation between read and yellow.
e.g.
for (j = 0, y = 0.0; j < steps; j++, y+=in_steps) {
beginShape(QUAD_STRIP);
noStroke(); // no lines
for (i = 0, x = 0.0; i <= steps; i++, x+=in_steps) {
fill(255, matrix[i][j] * 255, 0); // interpolate between red and yellow
vertex(x, y, matrix[i][j]);
fill(255, matrix[i][j+1] * 255, 0); // interpolate between red and yellow
vertex(x, y + in_steps, matrix[i][j+1]);
}
endShape();
}
I'm writing a Raytracer in Java, I've gotten to the point where I can create objects, rays, test for intersections and then colour pixels. I've also got some basic anti aliasing done. My problem is that if a create a sphere, which should be in the centre of the world (i.e 0.0, 0.0, 0.0) and then draw the image, I end up with a picture like this.
When the red circle should be in the middle of the image.
Main method
public static void main(String[] args) {
System.out.println("Rendering...");
long start = System.nanoTime();
// Setting up the size of the image to be rendered
world = new World(1920, 1080, 1.0);
image = new Image("image.png");
sampler = new SimpleSampler(4);
projector = new OrthographicProjector();
// Main loop of program, goes through each pixel in image and assigns a colour value
for (int y = 0; y < world.viewPlane.height; y++) {
for (int x = 0; x < world.viewPlane.width; x++) {
// Render pixel colour
trace(x, y);
}
}
image.saveImage("PNG");
long end = System.nanoTime();
System.out.print("Loop Time = " + ((end - start)/1000000000.0f));
}
Trace method
public static void trace(int x, int y) {
Colour colour = new Colour();
//int colour = RayTracer.world.backgroundColour.toInteger();
for (int col = 0; col < sampler.samples; col++) {
for (int row = 0; row < sampler.samples; row++) {
Point2D point = sampler.sample(row, col, x, y);
Ray ray = projector.createRay(point);
double min = Double.MAX_VALUE;
Colour tempColour = new Colour();
for (int i = 0; i < world.worldObjects.size(); i++) {
double temp = world.worldObjects.get(i).intersect(ray);
if (temp != 0 && temp < min) {
min = temp;
tempColour = world.worldObjects.get(i).colour;
}
}
colour.add(tempColour);
}
}
colour.divide(sampler.samples*sampler.samples);
image.buffer.setRGB(x, y, colour.toInteger());
}
World.java
public class World {
public ViewPlane viewPlane;
public ArrayList<Renderable> worldObjects;
public Colour backgroundColour;
public World(int width, int height, double size) {
viewPlane = new ViewPlane(width, height, size);
backgroundColour = new Colour(0.0f, 0.0f, 0.0f);
worldObjects = new ArrayList<Renderable>();
worldObjects.add(new Sphere(new Point3D(0.0, 0.0, 0.0), 50, new Colour(1.0f, 0.0f, 0.0f)));
//worldObjects.add(new Sphere(new Point3D(-150.0, 0.0, 0.0), 50, new Colour(1.0f, 0.0f, 0.0f)));
//worldObjects.add(new Sphere(new Point3D(0.0, -540.0, 0.0), 50, new Colour(0.0f, 1.0f, 0.0f)));
}
}
SimpleSampler.java
public class SimpleSampler extends Sampler {
public SimpleSampler(int samples) {
this.samples = samples;
}
public Point2D sample(int row, int col, int x, int y) {
Point2D point = new Point2D(
x - RayTracer.world.viewPlane.width / 2 + (col + 0.5) / samples,
y - RayTracer.world.viewPlane.width / 2 + (row + 0.5) / samples);
return point;
}
}
OrthographicProjector.java
public class OrthographicProjector extends Projector{
public Ray createRay(Point2D point) {
Ray ray = new Ray();
ray.origin = new Point3D(
RayTracer.world.viewPlane.size * point.x,
RayTracer.world.viewPlane.size * point.y,
100);
ray.direction = new Vector3D(0.0, 0.0, -1.0);
return ray;
}
}
I have a feeling that somewhere along the way I've mixed an x with a y and this has rotated the image, but I haven't been able to track down the problem. If you would like to see any more of my code I would be happy to show it.
In SimpleSampler.java:
Point2D point = new Point2D(
x - RayTracer.world.viewPlane.width / 2 + (col + 0.5) / samples,
y - RayTracer.world.viewPlane.width / 2 + (row + 0.5) / samples);
You use width for both coordinates. Maybe you should use width and height.