I was working on an animation on processing. Then, I have a question about the loop. Normally, my code is more long. However, I made a simple code which can usefull also for the beginners.
My sample code:
void setup(){
println("Line between points " + curr + " and " + (curr+1));
println("initial X: " + initialX + " initial Y: " + initialY );
println("final X: " + finalX + " final Y: " + finalY );
counter = 0; // reset counter;
}
void draw() {
point(initialX, initialY);
println(initialX, initialY, p);
}
So, like you see I used "Bresenhams Algorithm" for drawing the lines. However when I draw the lines it doesn't draw the lines between points. It's just drawing a little bit. Normally my text file is so long. How to I draw lines that can follow from first x and y coordinates to last x and y coordinates without disconnection?
This is implementation of a version of Bresenham's algorithm using balancing the positive and negative error between the x and y coordinates:
/*
String[] coordinates = { // Creating an array for my text file.
"117 191",
"96 223",
"85 251",
"77 291",
"78 323",
"84 351",
"97 378",
"116 404",
"141 430"
};
*/
int[][] points;
int deltaX, deltaY;
int initialX, initialY; // Initial point of first coodinate
int finalX, finalY; // Final point of first coodinate
int counter = 0;
int curr = 0;
int sx, sy, err;
void setup() {
size(500, 500);
strokeWeight(4);
frameRate(25);
coordinates = loadStrings("coordinates.txt");
beginShape(); // It combines the all of vertexes
points = new int[coordinates.length][2];
int row = 0;
for (String line : coordinates) {
String[] pair = line.split(" ");
points[row] = new int[] { Integer.parseInt(pair[0]), Integer.parseInt(pair[1])};
println(points[row][0]); // print x
println(points[row][1]); // print y
row++;
}
fixLines();
endShape(CLOSE);
}
void fixLines() {
int ix = curr % points.length;
int jx = (curr + 1) % points.length;
initialX = points[ix][0];
initialY = points[ix][1];
finalX = points[jx][0];
finalY = points[jx][1];
deltaX = abs(finalX - initialX);
sx = initialX < finalX ? 1: -1;
deltaY = -abs(finalY - initialY);
sy = initialY < finalY ? 1: -1;
err = deltaX + deltaY;
println("Line between points " + curr + " and " + (curr+1));
println("[" + initialX + ", " + initialY + "] - [" + finalX + ", " + finalY + "]");
println("deltaX=" + deltaX);
}
void draw() {
point(initialX, initialY);
if (initialX == finalX && initialY == finalY) {
curr++;
if (curr == points.length) {
noLoop();
} else {
fixLines();
}
} else {
int e2 = 2 * err;
if (e2 >= deltaY) {
err += deltaY;
initialX += sx;
}
if (e2 <= deltaX) {
err += deltaX;
initialY += sy;
}
}
}
The output is very close to linear implementation:
I try updating method draw to update deltaY and continue drawing until deltaY != 0 but result does not look good. Most likely you need to review your implementation of the algorithm and related calculations.
void draw()
{
point(initialX, initialY);
println(initialX, initialY, p);
if (finalX > initialX )
initialX++;
else
initialX--;
if (p < 0) {
p = p + 2 * deltaY;
} else {
if (initialY > finalY)
initialY--;
else
initialY++;
p = p + 2 * deltaY - 2 * deltaX;
}
deltaY = abs(finalY - initialY); // update deltaY
counter++;
if (counter > deltaX) {
if (deltaY > 0) {
counter--;
} else {
curr++;
if (curr == points.length) {
noLoop(); // possibly you should break out of the main loop here
} else {
fixLines();
}
}
}
}
Implementation with line(initialX, initialY, finalX, finalY); looks much better.
void draw()
{
point(initialX, initialY);
println(initialX, initialY, p);
line(initialX, initialY, finalX, finalY);
curr++;
if (curr == points.length) {
noLoop();
} else {
fixLines();
}
}
Related
I'm trying to build a Snake Game, where the snake is eating square orbs.
Before, the program was running perfectly, but when I ran it a couple of days ago, it yelled at me for something about a NullPointerException. I tried looking for what caused it, and it was in my Snake class.
Here is the code for the main class:
Snake s;
Score score;
//Menu m;
int sc1 = 20;
PVector food;
void setup() {
size(700, 700);
//m = new menu;
//m.show();
s = new Snake();
score = new Score();
//m.startGame();
frameRate(10);
}
void pickLocation() {
int cols = width/sc1;
int rows = height/sc1;
food = new PVector(floor(random(cols-20)), floor(random(rows-20)));
food.mult(sc1);
}
void draw() {
background(51);
if (s.eat(food)) {
pickLocation();
score.addPoints(10);
}
pickLocation();
score.show();
s.update();
s.show();
s.death();
if (s.dead == true) {
score.highScores();
}
if (score.totalScore != s.i/10) {
score.totalScore = s.i * 10;
}
if (s.dead && score.totalScore < score.highScore) {
score.totalScore = 0;
}
fill(255, 0, 100);
rect(food.x, food.y, sc1, sc1);
}
void keyPressed() {
if (keyCode == UP) {
s.dir(0, -1);
} else if (keyCode == DOWN) {
s.dir(0, 1);
} else if (keyCode == RIGHT) {
s.dir(1, 0);
} else if (keyCode == LEFT) {
s.dir(-1, 0);
}
}
The menu I commented out right now.
The Score class:
class Score {
int totalScore = 0; //will add the total score to the
int highScore; //will hold the user's high score in it.
int tempScore; //will hold the user's score after the snake dies.
Score() {
}
//this method is used when the snake eats the
//food. Eating the food will give 10 points to it.
void addPoints(int x) {
totalScore = totalScore + x;
}
//this method will calculate to see if the user
//has a new high score, only if the snake has
//officially died.
void highScores() {
if (totalScore > highScore) {
text("new highscore!", height/2, width/2);
highScore = totalScore;
totalScore = 0;
}
}
void show() {
text("Score: " + totalScore, 20, 20);
text("High Score: " + highScore, 20, 40);
}
}
And finally, my Snake class, where the problem is located at:
class Snake {
float x, y;
float xSpeed = 1;
float ySpeed = 0;
int total = 0;
ArrayList<PVector> tail = new ArrayList<PVector>();
boolean dead = false;
int i = 0;
Snake() {
}
boolean eat (PVector pos) {
float d = dist(x, y, pos.x, pos.y);
if (d < 1) {
total++;
return true;
} else {
return false;
}
}
void dir(float x, float y) {
xSpeed = x;
ySpeed = y;
}
void death() {
for (i = 0; i < tail.size(); i++) {
PVector pos = tail.get(i);
float d = dist(x, y, pos.x, pos.y);
if (d < 1) {
println("starting over");
total = 0;
tail.clear();
dead = true;
} else {
dead = false;
}
}
}
void update() {
if (total > 0) {
if (total == tail.size() && !tail.isEmpty()) {
tail.remove(0);
}
tail.add(new PVector(x, y));
}
x = x + xSpeed * sc1;
y = y + ySpeed * sc1;
x = constrain(x, 0, width-sc1);
y = constrain(y, 0, height-sc1);
}
void show() {
fill(0, 255, 0);
for (PVector v : tail) {
rect(v.x, v.y, sc1, sc1);
}
rect(x, y, sc1, sc1);
//rect(x, y, w, h);
}
}
My question is, is there something who can recognize the error and what should I do to fix such an error, please.
You need to get into the habit of debugging your code to understand exactly what's going on. You know that this line is throwing the NPE:
float d = dist(x, y, pos.x, pos.y);
So next, you need to understand the values of every variable on that line. You could just print them out:
boolean eat (PVector pos) {
println("x: " + x);
println("y: " + y);
println("pos: " + pos);
float d = dist(x, y, pos.x, pos.y);
If you do this, you'll see this output:
x: 0.0
y: 0.0
pos: null
This tells you that your pos variable is null, which is what's causing your NullPointerException.
Now you can trace backwards through your code to understand why the eat() function is being given a null argument.
In the future, please narrow your problem down to a MCVE instead of posting your whole program.
I have a color picker palette class and i want to send the color information while the client changes the color ( OnTouch ) through the bluetooth class in separate java file. The bluetooth Fragment is working and connecting perfectly . The problem is that the write method is working in its class but when i initialize it and try to use it in the color palette class it crashes on the test.
The working write() method in the bluetooth class :
private int col;
public void write(int color) {
col=color;
if(socket.isConnected()) {
// data = "r " + Color.red(color) + "/n" + "g " + Color.green(color) + "/n" + "b " + Color.blue(color) + "/n";
try {
/* byte[] dataToSend = {(byte) r,(byte)Color.red(color),(byte)Color.green(color),(byte) Color.blue(color), 0x0A};
//remove spurious line endings from color bytes so the serial device doesn't get confused
for (int i=0; i<dataToSend.length-1; i++){
if (dataToSend[i] == 0x0A){
dataToSend[i] = 0x0B;
}
}*/
// mmOutStream.write(data.getBytes());
mmOutStream.write(("r " + Color.red(col) + '\n').getBytes());
mmOutStream.write(("g " + Color.green(col) + '\n').getBytes());
mmOutStream.write(("b " + Color.blue(col) + '\n').getBytes());
} catch (IOException e) {
}
}
else
{
Toast.makeText(getContext(),
String.format("Not connected."),
Toast.LENGTH_SHORT).show();
}
}
The way i am trying to use the method in the color palette class(ColorPicker.java) :
BluetoothFragment rat = new BluetoothFragment();
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
int x = (int) event.getX();
int y = (int) event.getY();
int cx = x - getWidth() / 2;
int cy = y - getHeight() / 2;
double d = Math.sqrt(cx * cx + cy * cy);
if (d <= colorWheelRadius) {
colorHSV[0] = (float) (Math.toDegrees(Math.atan2(cy, cx)) + 180f);
colorHSV[1] = Math.max(0f, Math.min(1f, (float) (d / colorWheelRadius)));
invalidate();
} else if (x >= getWidth() / 2 && d >= innerWheelRadius) {
colorHSV[2] = (float) Math.max(0, Math.min(1, Math.atan2(cy, cx) / Math.PI + 0.5f));
invalidate();
}
return true;
}
rat.write(getColor());
return super.onTouchEvent(event);
}
In my player class the position vector of the player is consistently adding to the velocity vector of the class. I have an oldPosition Vector as well to see if the player has moved. I am using a 2d boolean array for collision throughout my game.
Here is the Player class.
public Player(){
this.velocity = new Vector2();
this.position = new Vector2(MapGrid.MAP_WIDTH / 2, MapGrid.MAP_HEIGHT + 200);
this.oldPosition = position;
this.gridPosition = new Vector2((int)(this.position.x / MapGrid.CELL_SIZE), (int)(this.position.y / MapGrid.CELL_SIZE));
}
public void create(){
this.canFall = true;
}
public void update(){
velocity.x += MainScreen.GRAVITY.x;
System.out.println("Grid calc x- " + (int)(this.position.x / MapGrid.CELL_SIZE));
System.out.println("Grid calc y- " + (int)(this.position.y / MapGrid.CELL_SIZE));
System.out.println("position top x- " + this.position.x);
System.out.println("position top y- " + this.position.y);
this.gridPosition.x = (int)(this.position.x / MapGrid.CELL_SIZE);
this.gridPosition.y = (int)(this.position.y / MapGrid.CELL_SIZE);
oldPosition.x = getGridPosition().x;
oldPosition.y = getGridPosition().y;
position.x += velocity.x;
position.y += velocity.y;
if(oldPosition.x == getGridPosition().x || oldPosition.y == getGridPosition().y){
hasMoved = false;
}
else{
hasMoved = true;
}
if(!canFall){
velocity.y = 0;
}else
velocity.y += MainScreen.GRAVITY.y;
if(Gdx.input.isKeyPressed(Keys.A)){
velocity.x -= 10 * Gdx.graphics.getDeltaTime();
}
else if(Gdx.input.isKeyPressed(Keys.D)){
velocity.x += 10 * Gdx.graphics.getDeltaTime();
}else
velocity.x = 0;
System.out.println("position after input x- " + this.position.x);
System.out.println("position after input y- " + this.position.y);
}
and here is the MapGrid class.
CELL_SIZE = 50
public void create(){
for(int x = 0; x < mapGrid.length; x++){
for(int y = 0; y < mapGrid[x].length; y++){
mapGrid[x][y] = false;
}
}
}
public void addToMap(Collidables object){
objectList.add(object);
}
public void update(){
for(int l = 0; l < objectList.size(); l++){
mapGrid[(int) objectList.get(l).getGridPosition().x][(int) objectList.get(l).getGridPosition().y] = true;
if(objectList.get(l).hasMoved()){
mapGrid[(int) objectList.get(l).getOldGridPosition().x][(int) objectList.get(l).getOldGridPosition().y] = false;
}
if(!objectList.get(l).isAlive()){
mapGrid[(int) objectList.get(l).getGridPosition().x][(int) objectList.get(l).getGridPosition().y] = false;
objectList.get(l).destroy();
}
}
}
and lastly the collision handler class
private Entity entity;
private MapGrid mapGrid;
public CollisionHandler(MapGrid mapGrid, Entity entity){
this.entity = entity;
this.mapGrid = mapGrid;
}
public void update(){
}
#Override
public void run() {
if(mapGrid.getGrid()[(int) (entity.getGridPosition().x + 1)][(int) entity.getGridPosition().y]){
entity.setCanMoveRight(false);
}else
entity.setCanMoveRight(true);
System.out.println("X: " + (int) (entity.getGridPosition().x - 1));
System.out.println("Y: " + (int) (entity.getGridPosition().y));
/*=============================*/
/*ONE LINE UNDER IS WHERE THE */
/*=========ERROR LIES!=========*/
/*=============================*/
if(mapGrid.getGrid()[(int) (entity.getGridPosition().x - 1)][(int) entity.getGridPosition().y]){
entity.setCanMoveLeft(false);
}else
entity.setCanMoveLeft(true);
if(mapGrid.getGrid()[(int) (entity.getGridPosition().x)][(int) entity.getGridPosition().y - 1]){
entity.setCanFall(false);
}else
entity.setCanFall(true);
}
When I run the game the game shows for a couple seconds and then crashes with the following error report.
The first two lines(grid calc) calculate where the player is in the grid, which is the players position / the cell size of the grid.
The second two lines(position top) of the console is the players position on screen.
The third two lines (position after input) is the same log as the normal position but I printed it at the bottom of the update method after the input.
And lastly the fourth 2 lines are printed from the collision handlers run method where the error lies.
I can't seem to find why the players grid coordinates are seemingly being divided constantly when in fact that is not happening. The grid coordinates are based on the players position divided by the cell size(50) and yet the players grid coordinates are being sent to -1 which is of course what is causing the error. I have looked everywhere and really need help here.
I have a class called SimplePolygon that creates a polygon with coordinates provided by the user. I am trying to define a method to compute the area of the polygon. It's an assignment and course instructor wants us to use the following formula to compute the area.
I can use either formula. I chose the right one.
My code gives me the wrong area. I don't know what's wrong.
public class SimplePolygon implements Polygon {
protected int n; // number of vertices of the polygon
protected Point2D.Double[] vertices; // vertices[0..n-1] around the polygon
public double area() throws NonSimplePolygonException {
try
{
if(isSimple()==false)
throw new NonSimplePolygonException();
else
{
double sum = 0;
for(int i = 0; i < vertices.length - 1; i++)
if(i == 0)
sum += vertices[i].x * (vertices[i+1].y - vertices[vertices.length - 1].y);
else
sum += vertices[i].x * (vertices[i+1].y - vertices[i-1].y);
double area = 0.5 * Math.abs(sum);
return area;
}
}
catch(NonSimplePolygonException e)
{
System.out.println("The Polygon is not simple.");
}
return 0.0;
}
The following is a tester code. The polygon is a rectangle with area 2, but the output is 2.5
Point2D.Double a = new Point2D.Double(1,1);
Point2D.Double b = new Point2D.Double(3,1);
Point2D.Double c = new Point2D.Double(3,2);
Point2D.Double d = new Point2D.Double(1,2);
SimplePolygon poly = new SimplePolygon(4);
poly.vertices[0] = a;
poly.vertices[1] = b;
poly.vertices[2] = c;
poly.vertices[3] = d;
System.out.println(poly.area());
Now that you've fixed the trivial boundary case, you're missing another boundary and your loop is wrong. Corrected code with debug:
public double area()
{
double sum = 0;
for (int i = 0; i < vertices.length ; i++)
{
if (i == 0)
{
System.out.println(vertices[i].x + "x" + (vertices[i + 1].y + "-" + vertices[vertices.length - 1].y));
sum += vertices[i].x * (vertices[i + 1].y - vertices[vertices.length - 1].y);
}
else if (i == vertices.length - 1)
{
System.out.println(vertices[i].x + "x" + (vertices[0].y + "-" + vertices[i - 1].y));
sum += vertices[i].x * (vertices[0].y - vertices[i - 1].y);
}
else
{
System.out.println(vertices[i].x + "x" + (vertices[i + 1].y + "-" + vertices[i - 1].y));
sum += vertices[i].x * (vertices[i + 1].y - vertices[i - 1].y);
}
}
double area = 0.5 * Math.abs(sum);
return area;
}
There is one missing term from the sum: vertices[n-1].x * (vertices[0].y - vertices[n-2].y).
Before the edit of the question there was also a problem with the first term:
Furthermore, if i==0 the term should be vertices[i].x * (vertices[i+1].y - vertices[n-1].y).
Assuming that n is equal to vertices.length.
The simplest way to code the loop is probably:
n = vertices.length;
sum =0;
for (int i = 0; i < n; i++) {
sum += vertices[i].x * (vertices[(i + 1) % n].y - vertices[(i + n - 1) % n].y);
}
I found another way,
Add first element again into polygon array
So that we can avoid "Out of bound" case as well as many If conditions.
Here is my solution:
public class PolygonArea {
public static void main(String[] args) {
PolygonArea p = new PolygonArea();
System.out.println(p.calculateArea());
}
Point[] points = new Point[5];
public double calculateArea() {
points[0] = new Point("A", 4, 10);
points[1] = new Point("B", 9, 7);
points[2] = new Point("C", 11, 2);
points[3] = new Point("D", 2, 2);
/** Add first entry again to polygon */
points[4] = new Point("A", 4, 10);
double sum = 0.0;
for (int i = 0; i < points.length - 1; ++i) {
sum += (points[i].X * points[i + 1].Y) - (points[i + 1].X * points[i].Y);
}
return Math.abs(sum / 2);
}
class Point {
final String _ID;
final int X;
final int Y;
public Point(String id, int x, int y) {
_ID = id;
X = x;
Y = y;
}
}
}
I am currently creating a maze using a pair of boolean array (horizontal and vertical) in order to draw lines for the maze.
The maze only every displays 5 bools from the array at one time. Then, I have an user who is always centered and as he moves through the maze the next set of bools are drawn. This is working as it should.
The issue that I am having is: when the user moves to a certain part of the maze the for loop drawing the lines becomes higher than the bool array and therefore crashes the app. Please find below some code snippets.
The onDraw:
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, width, height, background);
int currentX = maze.getCurrentX(),currentY = maze.getCurrentY();
int drawSizeX = 6 + currentX;
int drawSizeY = 6 + currentY;
currentX = currentX - 2;
currentY = currentY - 2;
for(int i = 0; i < drawSizeX - 1; i++) {
for(int j = 0; j < drawSizeY - 1; j++) {
float x = j * totalCellWidth;
float y = i * totalCellHeight;
if(vLines[i + currentY][j + currentX]) {
canvas.drawLine(x + cellWidth, //start X
y, //start Y
x + cellWidth, //stop X
y + cellHeight, //stop Y
line);
}
if(hLines[i + currentY][j + currentX]) {
canvas.drawLine(x, //startX
y + cellHeight, //startY
x + cellWidth, //stopX
y + cellHeight, //stopY
line);
}
}
//draw the user ball
canvas.drawCircle((2 * totalCellWidth)+(cellWidth/2), //x of center
(2 * totalCellHeight)+(cellWidth/2), //y of center
(cellWidth*0.45f), //radius
ball);
}
EDIT 1 - The Move -
public boolean move(int direction) {
boolean moved = false;
if(direction == UP) {
if(currentY != 0 && !horizontalLines[currentY-1][currentX]) {
currentY--;
moved = true;
}
}
if(direction == DOWN) {
if(currentY != sizeY-1 && !horizontalLines[currentY][currentX]) {
currentY++;
moved = true;
}
}
if(direction == RIGHT) {
if(currentX != sizeX-1 && !verticalLines[currentY][currentX]) {
currentX++;
moved = true;
}
}
if(direction == LEFT) {
if(currentX != 0 && !verticalLines[currentY][currentX-1]) {
currentX--;
moved = true;
}
}
if(moved) {
if(currentX == finalX && currentY == finalY) {
gameComplete = true;
}
}
return moved;
}
If there is anything else that I need to clarify please let me know.
Thanks in advance.
drawSizeX/Y indexes over the array when currentX/Y is high enough (length-6)
So limit the values to Math.min(current + 6, array.length)