I just need to get this code working. I know it's not good form or very efficient but I just need it to draw the Sierpinski's Triangle, recursively. It reaches the first recursive call, but never gets past it and only draws part of the triangle. I know I'm being stupid and the answer will be obvious but I haven't coded in a long time. Thank you for any help!
import javax.swing.*;
import java.awt.*;
public class recursiveTriangle18 extends JApplet
{
private final int APPLET_WIDTH = 800;
private final int APPLET_HEIGHT = 800;
/*
//x is accross and y is down
point 1 - Right A x[0],y[0] (720,600)
point 2 - Left B x[1],y[1]
point 3 - Top C x[2],y[2]
point 4 draws back to point 1 to complete triangle
*/ private int[] xPos = {720, 80, 400, 720};
private int[] yPos = {600, 600, 40, 600};
//-----------------------------------------------------------------
// Sets up the basic applet environment.
//-----------------------------------------------------------------
public void init()
{
setBackground (Color.white);
setSize (APPLET_WIDTH, APPLET_HEIGHT);
}
//-----------------------------------------------------------------
// Draws a rocket using polygons and polylines.
//-----------------------------------------------------------------
public void paint (Graphics page)
{
page.setColor (Color.BLUE);
page.drawPolyline (xPos, yPos, xPos.length);
Triangle(xPos,yPos, 0, page);
}//end of paint
public void Triangle(int[] xPos, int[] yPos, int flag, Graphics page)
{
//Find the distance between 2 points ex. - x,y & x1,y1
int x = xPos[0];
int x1 = xPos[1];
int x2 = xPos[2];
int x3 = xPos[3];
int y = yPos[0];
int y1 = yPos[1];
int y2 = yPos[2];
int y3 = yPos[3];
double dist = Math.sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1));
//find the mid points of each line segment
while (dist >= 100){
int midpointx = ((x+x1)/2);
int midpointy = ((y+y1)/2);
int midpointx1 = ((x1+x2)/2);
int midpointy1 = ((y1+y2)/2);
int midpointx2 = ((x2+x3)/2);
int midpointy2 = ((y2+y3)/2);
//make the x and y array (3 points + first point to finish triangle)
//create x,y Array using the midpoints you calculated
int [] xpoints = {midpointx2, midpointx, midpointx2};
int [] ypoints = {midpointy2,y, midpointy, midpointy2};
int [] xpoints1 = {midpointx, midpointx1, x1, midpointx};
int [] ypoints1 = {midpointy, midpointy1, y1, midpointy};
int [] xpoints2 = {midpointx1, midpointx2,x2,midpointx1};
int [] ypoints2 = {midpointy1, midpointy2,y2,midpointy1};
page.drawPolyline(xpoints1, ypoints1, xpoints1.length);
page.drawPolyline(xpoints2, ypoints2, xpoints2.length);
page.drawPolyline(xpoints, ypoints, xpoints.length);
//if the segment/distance is 300 or so, good length to stop
// Recursive calls for each section of triangle
Triangle(xpoints, ypoints, flag, page);
Triangle(xpoints2, ypoints2, flag, page); // how to get here?
Triangle(xpoints1, ypoints1, flag, page);
}
}
//end of Triangle
}
Triangle(xpoints, ypoints, flag, page);
Triangle(xpoints2, ypoints2, flag, page); // how to get here?
Every Triangle call is making another call to Triangle, so it's an infinite recursion that never returns. You need an if (stop condition) block around the recursive calls to tell it when to stop recursing.
There's also another issue:
double dist = Math.sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1));
//find the mid points of each line segment
while (dist >= 100){
You never update the value of dist, so this is an infinite loop.
Related
I am trying to understand a java game code but cant move past this problem.
This is a snake and apple game. I don't understand the few lines where I have commented out with "???". I dont understand how is this snake moving. I dont understand draw and move method, especially the move method.
public class GamePanel extends JPanel implements ActionListener {
static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH*SCREEN_HEIGHT)/(UNIT_SIZE*UNIT_SIZE);
static final int DELAY = 75;
final int x[] = new int[GAME_UNITS];
final int y[] = new int[GAME_UNITS];
int bodyParts = 6;
int applesEaten;
int appleX;
int appleY;
char direction = 'R';
boolean running = false;
Timer timer;
Random random;
public void draw (Graphics g) {
for(int i=0; i<SCREEN_HEIGHT/UNIT_SIZE; i++) {
g.drawLine(i*UNIT_SIZE, 0 , i*UNIT_SIZE, SCREEN_HEIGHT);//x1,y1,x2,y2 ,basically first point and last point
g.drawLine(0, i*UNIT_SIZE , SCREEN_WIDTH, i*UNIT_SIZE);
}
g.setColor(Color.red);
g.fillOval(appleX, appleY, UNIT_SIZE, UNIT_SIZE);
for (int i=0; i<bodyParts;i++) {//?????????????what does this mean ?
if(i==0) {
g.setColor(Color.green);
g.fillRect(x[i],y[i], UNIT_SIZE, UNIT_SIZE);//??
}
else {
g.setColor(new Color(45,180,0));
g.fillRect(x[i],y[i],UNIT_SIZE,UNIT_SIZE);
}
}
}
public void move () {
for(int i = bodyParts;i>0;i--) {//?????????????what does this mean ?, why i--
x[i] = x[i-1];///?????????????????????what does this mean ?
y[i] = y[i-1];/////what does this mean ?
}
switch(direction) {
case 'R':
y[0] = y[0] + UNIT_SIZE; //????????????????what is this doing ???
break;
}
Iterate through the integers from 0 to bodyParts
Draw a square of size UNIT_SIZE*UNIT_SIZE at the coordinate (x[i],y[i])
The head of the snake (first coordinate stored in x and y) is green, the rest of the body is light blue
The snake moves by altering the position of its bodyparts one by one, setting the current element's position to that of the following element, this starts from the back to avoid having to create temporary variables
After having altered the position of every bodyPart of the snake the head's position is altered as well, if direction equaled 'R', then the snake's head "goes down" by UNIT_SIZE. (it results in the snake's head going down because in Swing the top-left of the screen is the starting point, so the coordinate pair (0,0), by adding to the head's height coordinate (y) you're moving it away from the top, which is down.
A program I'm modifying is supposed to use a drawing panel to randomly move a square, starting from the center, either left or right and use an array to tally the position it moves to while the square stays on screen (the panel is 400 x 400 and the square is 10 x 10, so there are only 40 possible positions it can move to) After the square goes off screen, I have to print a histogram that shows how many times the square moved to that index (i.e if the square moved from the x coordinate of 200 to 190, index 19 would get a tally) Here is my code:
import java.awt.*;
import java.util.*;
public class RandomWalkCountSteps {
// DrawingPanel will have dimensions HEIGHT by WIDTH
public static final int HEIGHT = 100;
public static final int WIDTH = 400;
public static final int CENTER_X = WIDTH / 2;
public static final int CENTER_Y = HEIGHT / 2;
public static final int CURSOR_DIM = 10;
public static final int SLEEP_TIME = 25; // milliseconds
public static void main( String[] args ) {
DrawingPanel panel = new DrawingPanel( WIDTH, HEIGHT );
Random rand = new Random();
walkRandomly( panel, rand );
}
public static void walkRandomly( DrawingPanel panel, Random rand ) {
Graphics g = panel.getGraphics();
int[] positionCounts = new int[ WIDTH / CURSOR_DIM ];
// start in center of panel
int x = CENTER_X;
int y = CENTER_Y;
// Draw the cursor in BLACK
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
// randomly step left, right, up, or down
while ( onScreen( x, y ) ) {
panel.sleep( SLEEP_TIME );
// Show a shadow version of the cursor
g.setColor(Color.GRAY);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
if ( rand.nextBoolean() ) { // go left
x -= CURSOR_DIM;
}
else { // go right
x += CURSOR_DIM;
}
positionCounts[ x / CURSOR_DIM ]++;
histogram(positionCounts, x, y);
// draw the cursor at its new location
g.setColor(Color.BLACK);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
}
}
public static boolean onScreen( int x, int y ) {
return 0 <= x && x < WIDTH
&& 0 <= y && y < HEIGHT;
}
public static void histogram(int[] positionCounts, int x, int y) {
if (onScreen(x, y) == false) {
for (int i = 0; i < WIDTH / CURSOR_DIM; i++) {
System.out.print(i + ": ");
for (int j = 1; j <= positionCounts[i]; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
}
My problem was that I couldn't find a good place to initialize the array so that it wouldn't re-initialize every time I passed the x coordinate to the histogram method. Now that I thought I had it in the right place, I get this error message on both calls to histogram in the method walkRandomly "error: method histogram in class RandomWalkCountSteps cannot be applied to given types;" I'm fairly new to java and programming in general, so there's probably something I'm missing regarding arrays as parameters. Thanks in advance.
histogram takes two parameters, positionCounts of type int[] and x of type int. In walkRandomly, you call histogram twice: once with an argument positionCounts of type int[] and once with an argument x of type int. That’s why the compiler complains that the method ”cannot be applied to given types”: the method histogram(int[], int) can’t be applied to (called with) the given types, i.e., histogram(int[]) and histogram(int).
I’m not sure what you’re trying to do with this code, but I’d guess that you want remove the first call and change the second call (inside of the while loop) to histogram(positionCounts, x).
(You’ve edited your code, so my answer doesn’t make much sense.)
My final goal is to have a method, lets say:
Rectangle snapRects(Rectangle rec1, Rectangle rec2);
Imagine a Rectangle having info on position, size and angle.
Dragging and dropping the ABDE rectangle close to the BCGF rectangle would call the method with ABDE as first argument and BCGF as second argument, and the resulting rectangle is a rectangle lined up with BCGF's edge.
The vertices do not have to match (and preferrably won't so the snapping isn't so restrictive).
I can only understand easily how to give the same angle, but the position change is quite confusing to me. Also, i believe even if i reached a solution it would be quite badly optimized (excessive resource cost), so I would appreciate guidance on this.
(This has already been asked but no satisfatory answer was given and the question forgotten.)
------------------------------------------------------------------
Edit: It seems my explanation was insufficient so I will try to clarify my wishes:
The following image shows the goal of the method in a nutshell:
Forget about "closest rectangle", imagine there are just two rectangles. The lines inside the rectangles represent the direction they are facing (visual aid for the angle).
There is a static rectangle, which is not to be moved and has an angle (0->360), and a rectangle (also with an angle) which I want to Snap to the closest edge of the static rectangle. By this, i mean, i want the least transformations possible for the "snap to edge" to happen.
This brings many possible cases, depending on the rotation of the rectangles and their position relative to each other.
The next image shows the static rectangle and how the position of the "To Snap" rectangle changes the snapping result:
The final rotations might not be perfect since it was done by eye, but you get the point, it matters the relative position and also both angles.
Now, in my point of view, which may be completely naive, I see this problem solved on two important and distinct steps on transforming the "To Snap" rectangle: Positioning and Rotation
Position: The objective of the new position is to stick to the closest edge, but since we want it to stick paralell to the static rectangle, the angle of the static rectangle matters. The next image shows examples of positioning:
In this case, the static rectangle has no angle, so its easy to determine up, down, left and right. But with angle, there are alot more possibilities:
As for the rotation, the goal is for the "to snap" rectangle to rotate the minimum needed to become paralell with the static rectangle:
As a final note, in regard of implementation input, the goal is to actually drag the "to snap" rectangle to wherever position i wish around the static rectangle and by pressing a keyboard key, the snap happens.
Also, it appears i have exagerated a little when i asked for optimization, to be honest i do not need or require optimization, I do prefer an easy to read, step by step clear code (if its the case), rather than any optimization at all.
I hope i was clear this time, sorry for the lack of clarity in the first place, if you have any more doubts please do ask.
The problem is obviously underspecified: What does "line up" for the edges mean? A common start point (but not necessarily a common end point)? A common center point for both edges? (That's what I assumed now). Should ALL edges match? What is the criterion for deciding WHICH edge of the first rectangle should be "matched" with WHICH edge of the second rectangle? That is, imagine one square consists exactly of the center points of the edges of the other square - how should it be aligned then?
(Secondary question: In how far is optimization (or "low resource cost") important?)
However, I wrote a few first lines, maybe this can be used to point out more clearly what the intended behavior should be - namely by saying in how far the intended behavior differs from the actual behavior:
EDIT: Old code omitted, update based on the clarification:
The conditions for the "snapping" are still not unambiguous. For example, it is not clear whether the change in position or the change in the angle should be preferred. But admittedly, I did not figure out in detail all possible cases where this question could arise. In any case, based on the updated question, this might be closer to what you are looking for.
NOTE: This code is neither "clean" nor particularly elegant or efficient. The goal until now was to find a method that delivers "satisfactory" results. Optimizations and beautifications are possible.
The basic idea:
Given are the static rectangle r1, and the rectangle to be snapped, r0
Compute the edges that should be snapped together. This is divided in two steps:
The method computeCandidateEdgeIndices1 computes the "candidate edges" (resp. their indices) of the static rectangle that the moving rectangle may be snapped to. This is based on the folowing criterion: It checks how many vertices (corners) of the moving rectangle are right of the particular edge. For example, if all 4 vertices of the moving rectangle are right of edge 2, then edge 2 will be a candidate for snapping the rectangle to.
Since there may be multiple edges for which the same number of vertices may be "right", the method computeBestEdgeIndices computes the candidate edge whose center has the least distance to the center of any edge of the moving rectangle. The indices of the respective edges are returned
Given the indices of the edges to be snapped, the angle between these edges is computed. The resulting rectangle will be the original rectangle, rotated by this angle.
The rotated rectangle will be moved so that the centers of the snapped edges are at the same point
I tested this with several configurations, and the results at least seem "feasible" for me. Of course, this does not mean that it works satisfactory in all cases, but maybe it can serve as a starting point.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class RectangleSnap
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
RectangleSnapPanel panel = new RectangleSnapPanel();
f.getContentPane().add(panel);
f.setSize(1000,1000);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class SnapRectangle
{
private Point2D position;
private double sizeX;
private double sizeY;
private double angleRad;
private AffineTransform at;
SnapRectangle(
double x, double y,
double sizeX, double sizeY, double angleRad)
{
this.position = new Point2D.Double(x,y);
this.sizeX = sizeX;
this.sizeY = sizeY;
this.angleRad = angleRad;
at = AffineTransform.getRotateInstance(
angleRad, position.getX(), position.getY());
}
double getAngleRad()
{
return angleRad;
}
double getSizeX()
{
return sizeX;
}
double getSizeY()
{
return sizeY;
}
Point2D getPosition()
{
return position;
}
void draw(Graphics2D g)
{
Color oldColor = g.getColor();
Rectangle2D r = new Rectangle2D.Double(
position.getX(), position.getY(), sizeX, sizeY);
AffineTransform at = AffineTransform.getRotateInstance(
angleRad, position.getX(), position.getY());
g.draw(at.createTransformedShape(r));
g.setColor(Color.RED);
for (int i=0; i<4; i++)
{
Point2D c = getCorner(i);
Ellipse2D e = new Ellipse2D.Double(c.getX()-3, c.getY()-3, 6, 6);
g.fill(e);
g.drawString(""+i, (int)c.getX(), (int)c.getY()+15);
}
g.setColor(Color.GREEN);
for (int i=0; i<4; i++)
{
Point2D c = getEdgeCenter(i);
Ellipse2D e = new Ellipse2D.Double(c.getX()-3, c.getY()-3, 6, 6);
g.fill(e);
g.drawString(""+i, (int)c.getX(), (int)c.getY()+15);
}
g.setColor(oldColor);
}
Point2D getCorner(int i)
{
switch (i)
{
case 0:
return new Point2D.Double(position.getX(), position.getY());
case 1:
{
Point2D.Double result = new Point2D.Double(
position.getX(), position.getY()+sizeY);
return at.transform(result, null);
}
case 2:
{
Point2D.Double result = new Point2D.Double
(position.getX()+sizeX, position.getY()+sizeY);
return at.transform(result, null);
}
case 3:
{
Point2D.Double result = new Point2D.Double(
position.getX()+sizeX, position.getY());
return at.transform(result, null);
}
}
return null;
}
Line2D getEdge(int i)
{
Point2D p0 = getCorner(i);
Point2D p1 = getCorner((i+1)%4);
return new Line2D.Double(p0, p1);
}
Point2D getEdgeCenter(int i)
{
Point2D p0 = getCorner(i);
Point2D p1 = getCorner((i+1)%4);
Point2D c = new Point2D.Double(
p0.getX() + 0.5 * (p1.getX() - p0.getX()),
p0.getY() + 0.5 * (p1.getY() - p0.getY()));
return c;
}
void setPosition(double x, double y)
{
this.position.setLocation(x, y);
at = AffineTransform.getRotateInstance(
angleRad, position.getX(), position.getY());
}
}
class RectangleSnapPanel extends JPanel implements MouseMotionListener
{
private final SnapRectangle rectangle0;
private final SnapRectangle rectangle1;
private SnapRectangle snappedRectangle0;
RectangleSnapPanel()
{
this.rectangle0 = new SnapRectangle(
200, 300, 250, 200, Math.toRadians(-21));
this.rectangle1 = new SnapRectangle(
500, 300, 200, 150, Math.toRadians(36));
addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
g.setColor(Color.BLACK);
rectangle0.draw(g);
rectangle1.draw(g);
if (snappedRectangle0 != null)
{
g.setColor(Color.BLUE);
snappedRectangle0.draw(g);
}
}
#Override
public void mouseDragged(MouseEvent e)
{
rectangle0.setPosition(e.getX(), e.getY());
snappedRectangle0 = snapRects(rectangle0, rectangle1);
repaint();
}
#Override
public void mouseMoved(MouseEvent e)
{
}
private static SnapRectangle snapRects(
SnapRectangle r0, SnapRectangle r1)
{
List<Integer> candidateEdgeIndices1 =
computeCandidateEdgeIndices1(r0, r1);
int bestEdgeIndices[] = computeBestEdgeIndices(
r0, r1, candidateEdgeIndices1);
int bestEdgeIndex0 = bestEdgeIndices[0];
int bestEdgeIndex1 = bestEdgeIndices[1];
System.out.println("Best to snap "+bestEdgeIndex0+" to "+bestEdgeIndex1);
Line2D bestEdge0 = r0.getEdge(bestEdgeIndex0);
Line2D bestEdge1 = r1.getEdge(bestEdgeIndex1);
double edgeAngle = angleRad(bestEdge0, bestEdge1);
double rotationAngle = edgeAngle;
if (rotationAngle <= Math.PI)
{
rotationAngle = Math.PI + rotationAngle;
}
else if (rotationAngle <= -Math.PI / 2)
{
rotationAngle = Math.PI + rotationAngle;
}
else if (rotationAngle >= Math.PI)
{
rotationAngle = -Math.PI + rotationAngle;
}
SnapRectangle result = new SnapRectangle(
r0.getPosition().getX(), r0.getPosition().getY(),
r0.getSizeX(), r0.getSizeY(), r0.getAngleRad()-rotationAngle);
Point2D edgeCenter0 = result.getEdgeCenter(bestEdgeIndex0);
Point2D edgeCenter1 = r1.getEdgeCenter(bestEdgeIndex1);
double dx = edgeCenter1.getX() - edgeCenter0.getX();
double dy = edgeCenter1.getY() - edgeCenter0.getY();
result.setPosition(
r0.getPosition().getX()+dx,
r0.getPosition().getY()+dy);
return result;
}
// Compute for the edge indices for r1 in the given list
// the one that has the smallest distance to any edge
// of r0, and return this pair of indices
private static int[] computeBestEdgeIndices(
SnapRectangle r0, SnapRectangle r1,
List<Integer> candidateEdgeIndices1)
{
int bestEdgeIndex0 = -1;
int bestEdgeIndex1 = -1;
double minCenterDistance = Double.MAX_VALUE;
for (int i=0; i<candidateEdgeIndices1.size(); i++)
{
int edgeIndex1 = candidateEdgeIndices1.get(i);
for (int edgeIndex0=0; edgeIndex0<4; edgeIndex0++)
{
Point2D p0 = r0.getEdgeCenter(edgeIndex0);
Point2D p1 = r1.getEdgeCenter(edgeIndex1);
double distance = p0.distance(p1);
if (distance < minCenterDistance)
{
minCenterDistance = distance;
bestEdgeIndex0 = edgeIndex0;
bestEdgeIndex1 = edgeIndex1;
}
}
}
return new int[]{ bestEdgeIndex0, bestEdgeIndex1 };
}
// Compute the angle, in radians, between the given lines,
// in the range (-2*PI, 2*PI)
private static double angleRad(Line2D line0, Line2D line1)
{
double dx0 = line0.getX2() - line0.getX1();
double dy0 = line0.getY2() - line0.getY1();
double dx1 = line1.getX2() - line1.getX1();
double dy1 = line1.getY2() - line1.getY1();
double a0 = Math.atan2(dy0, dx0);
double a1 = Math.atan2(dy1, dx1);
return (a0 - a1) % (2 * Math.PI);
}
// In these methods, "right" refers to screen coordinates, which
// unfortunately are upside down in Swing. Mathematically,
// these relation is "left"
// Compute the "candidate" edges of r1 to which r0 may
// be snapped. These are the edges to which the maximum
// number of corners of r0 are right of
private static List<Integer> computeCandidateEdgeIndices1(
SnapRectangle r0, SnapRectangle r1)
{
List<Integer> bestEdgeIndices = new ArrayList<Integer>();
int maxRight = 0;
for (int i=0; i<4; i++)
{
Line2D e1 = r1.getEdge(i);
int right = countRightOf(e1, r0);
if (right > maxRight)
{
maxRight = right;
bestEdgeIndices.clear();
bestEdgeIndices.add(i);
}
else if (right == maxRight)
{
bestEdgeIndices.add(i);
}
}
//System.out.println("Candidate edges "+bestEdgeIndices);
return bestEdgeIndices;
}
// Count the number of corners of the given rectangle
// that are right of the given line
private static int countRightOf(Line2D line, SnapRectangle r)
{
int count = 0;
for (int i=0; i<4; i++)
{
if (isRightOf(line, r.getCorner(i)))
{
count++;
}
}
return count;
}
// Returns whether the given point is right of the given line
// (referring to the actual line *direction* - not in terms
// of coordinates in 2D!)
private static boolean isRightOf(Line2D line, Point2D point)
{
double d00 = line.getX1() - point.getX();
double d01 = line.getY1() - point.getY();
double d10 = line.getX2() - point.getX();
double d11 = line.getY2() - point.getY();
return d00 * d11 - d10 * d01 > 0;
}
}
I'm making my first game using Java on Android. I need to draw a lot of pixels which together should create a line. My first approach was to make a large array of booleans, create a loop, and draw a pixel when the associated boolean was true.
It wasn't a good idea of course (the array is about 200x300). Now I remember only the position of the first pixel of the line, and every next pixel has to remember his follower. It works pretty well, but when the line gets longer (but still not very long), the efficiency is bad (<20 fps after 4000 frames).
This is the function that I use to draw a line (only one for now). Can anybody help me improve its efficiency?
public void drawLine(Canvas canvas, int beginx, int beginy) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
paint.setStrokeWidth(3);
int x = beginx;
int y = beginy;
while(C.mGrid[x][y].nx != -1) {
//canvas.drawLine(x, y, C.mGrid[x][y].nx, C.mGrid[x][y].ny, paint);
canvas.drawPoint(x, y, paint);
Grid temp = C.mGrid[x][y];
if ((C.mGrid[x][y].nx == x) && (C.mGrid[x][y].ny == y)) break;
x = temp.nx;
y = temp.ny;
}
}
and Grid.java:
package com.qwak.achtung;
public float x = 0,y = 0;
public int px = -1, py = -1, nx = -1, ny = -1;
public Grid(float x, float y) {
this.x = x;
this.y = y;
}
public void set(int px, int py, int nx, int ny) {
this.px = px;
this.py = py;
this.nx = nx;
this.ny = ny;
}
public void setp(int px, int py) {
this.px = px;
this.py = py;
}
public void setn(int nx, int ny) {
this.nx = nx;
this.ny = ny;
}
PS: It looks like this http://c.wrzuta.pl/wi10559/11f7d10b00110e504e25ebd3/0/andek 14 is fps (on my phone (samsung Spica) it run better - 40 but after a while it decreases to 20 and even less) and 983 is number of frames at all.
There is a drawLine method in the canvas object.
Use the example here: How to draw a line in android
canvas.drawLine(0, 0, 20, 20, paint);
If you want to draw a curve. Find the function of the curve. A Parabola for example is x=y^2. You can get points from the curve: 1 = 1, 2 = 4, 3 = 9, 4 = 16... etc.. If your drawing pixel by pixel you can plug in your x and get your y and draw it.
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
paint.setStrokeWidth(3);
for(int i = beginx; i < CanvasWidth; i++)
{
int x = i;
int y = i * i; //x=y^2
canvas.drawPoint(x, y, paint);
}
To keep a record of points that were visited you could do the following:
class Point
{
int x;
int y;
}
List<Point> points = new List<Point>();
onMove(int newX, int newY)
{
Point p = new Point();
p.x = newX;
p.y = newY;
points.add(p);
}
onDraw()
{
for(Point p : points)
{
canvas.drawPoint(p.x, p.y, paint);
}
}
You want to look into the bresenham algorithm. A bresenham algorithm is a method to draw or rasterize a line. It's a bit different from the subdivision of a grid in a certain angle for example a morton-curve. It's a bit like compute the scalar product for every angle like recall here Traversing a 2D array in an angle.
In the effort to learn more about applets and Java, I am experimenting making wave applets by drawing lines (drawLine) and making animated line graphs.
I can make a static graph just fine. However I am struggling with the animated aspect of the graph: the axes of the graph should move from left to right, increasing and growing larger than 0.
My problem is translating my needs into a solution. Can anyone give me any pointers with my problem?
I have a multidimensional array indexed by points containing the x and y of a particular point. I have tried modifying my render function to decrease the Xs to make it appear as if it is moving left but this doesn't work right.
What approach am I looking to take? How different will my approach be if the values of Y could change due to user action or added data?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
/**
* A graph that should in the future represent a wave according to my inputs
*
* #authorImprofane
* #version 1
*/
public class Graph extends JFrame
{
private InnerGraph inner;
private int width;
private Random RNG;
private int height;
private int[][] series;
private int xoffset;
int prevx = 0;
int prevy = 0;
/**
* Constructor for objects of class Graph
*/
public Graph(int width, int height) throws InterruptedException
{
RNG = new Random();
setTitle(" Graph");
series = new int[width][2];
this.width = width;
this.height = height;
inner = new InnerGraph(width, height);
add(inner, BorderLayout.CENTER);
setVisible(true);
inner.preparePaint();
pack();
updateGraph();
}
public static void main(String[] args) throws InterruptedException
{
new Graph(300, 300);
}
public void updateGraph() throws InterruptedException
{
// virtual x is how far along on the x axis we are, I ignore the 'real' X axis
int vx = 0;
int point = 0;
int xdecay = 0;
int inc = 5;
// how many times we need to plot a point
int points = (int) java.lang.Math.floor( width / inc );
System.out.println(points);
inner.preparePaint();
// draw all points to graph
// make some junk data, a saw like graph
for (vx = 0 ; vx < points ; vx++) {
series[vx] = new int[] { vx*inc, ( (vx*inc) % 120 ) };
}
Thread.sleep(150);
int n = 5;
while(n > 0) {
System.out.println(xdecay);
inner.preparePaint();
for (vx = 0 ; vx < points ; vx++) {
inner.updateSeries(vx, xdecay);
inner.repaint();
Thread.sleep(50);
}
xdecay += inc;
// shift the data points to the left
int[][] nseries = new int[points][2];
// System.arraycopy(series, 1, nseries, 0, points-1);
n--;
}
}
public class InnerGraph extends JPanel
{
private Graphics g;
private Image img;
private int gwidth;
private int gheight;
Dimension size;
public InnerGraph(int width, int height)
{
gwidth = width;
gheight = height;
size = new Dimension(1, 1);
}
/**
* Try make panel the requested size.
*/
public Dimension getPreferredSize()
{
return new Dimension(gwidth, gheight);
}
/**
* Create an image and graphics context
*
*/
public void preparePaint()
{
size = getSize();
img = inner.createImage( (size.width | gwidth), (size.height | gheight) );
g = img.getGraphics();
}
/**
* Draw a point to the chart given the point to use and the decay.
* Yes this is bad coding style until I work out the mathematics needed
* to do what I want.
*/
public void updateSeries(int point, int decay)
{
g.setColor(Color.blue);
int nx = series[point][0];
series[point][0] -= decay;
if ( point-1 >= 0 ) {
series[point-1][0] -= decay;
}
int ny = series[point][1];
prevx -= decay;
g.drawLine(prevx-decay, prevy, nx-decay, ny );
prevx = nx-decay;
prevy = ny;
}
public void paintComponent(Graphics g)
{
g.drawImage(img, 0, 0, null);
}
}
}
First, it looks like you are subtracting the decay too often in the updateSeries method.
Below is a new version of that method.
public void updateSeries(int point, int decay)
{
g.setColor(Color.blue);
int nx = series[point][0];
series[point][0] -= decay;
if ( point-1 >= 0 ) {
series[point-1][0] -= decay;
}
int ny = series[point][1];
// prevx -= decay;
// g.drawLine(prevx-decay, prevy, nx-decay, ny );
g.drawLine(prevx, prevy, nx-decay, ny );
prevx = nx-decay;
prevy = ny;
}
With those changes, the lines draw better, but they draw so slowly that the animation is hard to see. You probably need to build a new graphics and swap the whole thing so that you don't have to watch each individual line segment being drawn.
For a starter you could check out the following example (and the ones related to this)
Scroll Chart #java2s.com