How to make a Bresenham's line algorithm? - java

I wrote a small program, that draws a line from user inputs x1,y1 and x2,y2. For some reason line only works while horizontal, but once line should be vertical, it just shows me a black pixel not a line. I have checked everything and I am pretty sure that I got the algorithm right, but problem is still here.
int x1 = Integer.parseInt(this.jTextFieldX1.getText());
int y1 = Integer.parseInt(this.jTextFieldY1.getText());
int x2 = Integer.parseInt(this.jTextFieldX2.getText());
int y2 = Integer.parseInt(this.jTextFieldY2.getText());
int xi = x2 > x1 ? 1:-1;
int yi = y2 > y1 ? 1:-1;
int dx = Math.abs(x2-x1);
int dy = Math.abs(y2-y1);
int xn= x1;
int yn= y1;
int pn;
canvas.showBlackPixel(xn,yn);
if (dx > dy)
{
pn= 2*dy - dx;
while (xn != x2)
{
if (pn >0)
{
xn=xn + xi;
yn=yn + yi;
pn=pn + 2*dy - 2*dx;
}
else
{
xn = xn + xi;
pn = pn+ 2*dy;
}
canvas.showBlackPixel(xn,yn);
}
{
if (dy > dx)
{
pn= 2*dx - dy;
while (yn != y2)
{
if (pn > 0)
{
xn=xn + xi;
yn=yn + yi;
pn=pn + 2*dx - 2*dy;
}
else
{
yn = yn + yi;
pn = pn + 2*dx;
}
canvas.showBlackPixel(xn,yn);
}
}
}
}
}
How could I fix it?

The problem is with the termination of your statements, which is to say your braces {} are mixed up a little. To be specific, cut down to the relevant bits your code is:
if (dx > dy)
{
...
if (dy > dx)
{
...
}
}
If you fix your braces, then it looks like it should work better.
if (dx > dy)
{
...
}
if (dy > dx)
{
...
}
You'll still have an issue when dx == dy though.

Related

Forcing a square to fit in a grid

The method is supposed to draw a square on a 10x10 grid using the length and x,y coordinate an user inputs and adjust the length in case the square doesn't fit.
I'm having trouble figuring out the math for adjusting the length to fit the grid.
For example, if the user inputs (x-7, y-2, length-4) my square goes out of the grid by 1.
Example
public static void drawSquare(int x, int y, int len) {
if(x+len>10)
len = Math.max(x, len)-Math.min(x, len);
if(y+len>10)
len = Math.max(y, len)-Math.min(y, len);
System.out.println("side length = " + len + ", area = " + len*len);
drawLine(x, y, x+len, y);
drawLine(x+len,y,x+len,y-len);
drawLine(x+len, y-len, x, y-len);
drawLine(x, y-len, x, y);
}
This should do the trick. Just think about how the drawsquare method should call another method drawLine. Think about how to find each point in a square using the two coordinates and the given length of the square, also using if statements to make sure it fits the graph
public class unit3frq {
public void drawSquare(int x, int y, int len) {
// first check whether it fits on the grid
int xsum = x + len; int ydiff = y - len;
if (xsum > 10) xsum = 10 - x; if (ydiff < 0) ydiff = 0 - y;
if ((x - xsum) > (y - ydiff)) xsum = ydiff+x-y;
else ydiff = xsum+y-x;
drawLine(x, y, x, ydiff); // go down
drawLine(x, y, xsum, y); // go right
drawLine(x, ydiff, xsum, ydiff); // down then right
drawLine(xsum, y, xsum, ydiff); // right then down
int side = xsum - x;
System.out.println("side length = " + side + ", area = " + Math.pow(side, 2));
}
public void drawLine(int x1, int y1, int x2, int y2) {
int xdiff = x2 - x1; int ydiff = y2 - y1;
if (xdiff < 0) xdiff = 0 - xdiff; if (ydiff < 0) ydiff = 0 - ydiff;
if (xdiff > ydiff) {
int x = x1; int y = y1;
while (x <= x2) {
System.out.println("(" + x + ", " + y + ")");
x++;
if (ydiff != 0) y += ydiff / xdiff;
}
} else {
int x = x1; int y = y1;
while (y <= y2) {
System.out.println("(" + x + ", " + y + ")");
y++;
if (xdiff != 0) x += xdiff / ydiff;
}
}
}
public static void main(String[] args) {
unit3frq u3 = new unit3frq();
u3.drawSquare(0, 0, 10);
}
}

Unknown NullPointerException 10 ignore> [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
My code is:
public void move() {
moveX();
moveY();
}
public void moveX() {
if(xMove > 0) {
int tx = (int) (x + xMove + bounds.x + bounds.width) / Tile.TILEWIDTH;
if(!collisionWithTile(tx, (int) (y + bounds.y) / Tile.TILEHEIGHT) && !collisionWithTile(tx, (int) (y + bounds.y + bounds.height) / Tile.TILEHEIGHT)) {
x += xMove;
}
} else if(xMove < 0) {
int tx = (int) (x + xMove + bounds.x) / Tile.TILEWIDTH;
if(!collisionWithTile(tx, (int) (y + bounds.y) / Tile.TILEHEIGHT) && !collisionWithTile(tx, (int) (y + bounds.y + bounds.height) / Tile.TILEHEIGHT)) {
x += xMove;
}
}
}
public void moveY() {
if(yMove < 0) {
int ty = (int) (y + yMove + bounds.y + bounds.height) / Tile.TILEHEIGHT;
if(!collisionWithTile((int) (x + bounds.x) / Tile.TILEHEIGHT, ty) && !collisionWithTile((int) (x + bounds.x + bounds.width) / Tile.TILEWIDTH, ty)) {
y += yMove;
}
}
if(yMove > 0) {
int ty = (int) (y + yMove + bounds.y) / Tile.TILEHEIGHT;
if(!collisionWithTile((int) (x + bounds.x) / Tile.TILEHEIGHT, ty) && !collisionWithTile((int) (x + bounds.x + bounds.width) / Tile.TILEWIDTH, ty)) {
y += yMove;
}
}
}
protected boolean collisionWithTile(int x, int y) {
return room.getTile(x, y).isSolid();
}
but when I run it I get a NullPointerException with this StackTrace:
Exception in thread "Thread-0" java.lang.NullPointerException
at com.pixelandbitgames.entities.creature.Creature.collisionWithTile(Creature.java:69)
at com.pixelandbitgames.entities.creature.Creature.moveX(Creature.java:41)
at com.pixelandbitgames.entities.creature.Creature.move(Creature.java:27)
at com.pixelandbitgames.entities.creature.Player.tick(Player.java:19)
at com.pixelandbitgames.states.GameState.tick(GameState.java:23)
at com.pixelandbitgames.game.Game.tick(Game.java:72)
at com.pixelandbitgames.game.Game.run(Game.java:113)
at java.lang.Thread.run(Thread.java:748)
I do not see where this is coming from as collisionWithTile has all its parameters filled. If anyone can help me that would be appriciated. if anyone needs any thing else to help I will deliver. My other classes seem fine and it is just this one. This happens when I try to move. my code for Room.getTile is here:
public Tile getTile(int x, int y) {
if(x < 0 || y < 0 || x >= width || y >= height)
return Tile.floorTile;
Tile t = Tile.tiles[tiles[x][y]];
if(t == null)
return Tile.floorTile;
return t;
}
and this has no way to return null. Is solid is just a return true unless it is overridden.
public boolean isSolid() {
return false;
}
Either room is null, or room.getTile(x, y) returns null. You haven't pasted the relevant bits of those, making it impossible to give more information.

Java libgdx: limiting circular velocity (swinging entity)

I am currently working on a 2D side scroller and have implemented the techniques use in this article for a grapple hook, and it works really well. My problem is I want my player to be able to swing around the rope a little bit to gain a bit of momentum, but currently I can't stop the player from moving all the way up to 90 degrees either side. What techniques can be applied to force this limit?
I have tried using a separate player speed for swinging but this only slows the process down I can still swing up to 90 deg each side.
Here's my update function in the player
public void update(float dt){
//handle friction and air resistance
if(dx !=0){
if(touchingGround) {
// apply friction
if (dx > 0) {
dx -= retardation;
} else {
dx += retardation;
}
} else {
//applied air resistance
if (dx > 0) {
dx -= airResistance;
} else {
dx += airResistance;
}
}
}
// handle gravity
dy -= Constants.GRAVITY * dt;
if(dy < -terminalVelocity){
dy = -terminalVelocity;
}
/*
Handle Player movement
*/
if(right){
if(dx <= maxSpeed){
dx += acceleration;
}
dx = maxSpeed;
}
if(left){
if(dx <= -maxSpeed){
dx -= acceleration;
}
dx = -maxSpeed;
}
if(isGrappling){
//If we collide with something we need to stop grappling
if(hasCollided){
isGrappling = false;
} else {
// This algorithm from here:
// http://gamedev.stackexchange.com/questions/61596/player-rope-swing
float currentD = (float) Math.sqrt(((grappleX - x) * (grappleX - x)) + ((grappleY - y) * (grappleY - y)));
float prevX = getX(), prevY = getY();
if (currentD > grappleRadius) {
Vector2 hookPos = new Vector2(grappleX, grappleY);
Vector2 testPos = (new Vector2(x, y).sub(hookPos)).nor();
y = (hookPos.y + testPos.y * grappleRadius);
x = (hookPos.x + testPos.x * grappleRadius);
// s = d / t
dx += (x - prevX) / dt;
dy += (y - prevY) / dt;
}
}
}
/*
Collision Detection, handle last always!
*/
float oldX = getX(), oldY = getY();
boolean collisionX = false, collisionY = false;
// move on x
x += dx * dt;
// calculate the increment for step in #collidesLeft() and #collidesRight()
increment = collisionLayer.getTileWidth();
increment = getWidth() < increment ? getWidth() / 2 : increment / 2;
if(dx < 0) // going left
collisionX = collidesLeft();
else if(dx > 0) // going right
collisionX = collidesRight();
// react to x collision
if(collisionX) {
setX(oldX);
dx = 0;
}
// move on y
y += dy * dt;
// calculate the increment for step in #collidesBottom() and #collidesTop()
increment = collisionLayer.getTileHeight();
increment = getHeight() < increment ? getHeight() / 2 : increment / 2;
if(dy < 0) {
touchingGround = collisionY = collidesBottom();
// we can only jump 2 times before we have to touch the floor again
if(collisionY){
numberOfJumps = 2;
}
} else if(dy > 0) {
collisionY = collidesTop();
}
// react to y collision
if(collisionY) {
setY(oldY);
dy = 0;
}
hasCollided = collisionX || collisionY;
}
As I am not using any physics engine I chose to just emulate the physics by limiting the angle at which the player can apply force to the swing.
// check if angle permits movement
if(grappleAngle < Math.PI/9 && grappleAngle > -Math.PI/9) {
// handle momentum gaining on rope
if (right) {
dx += swingAcceleration * dt;
}
if (left) {
dx -= swingAcceleration * dt;
}
}

Android Canvas Check if Point is on Line

I have a Custom View which draws lines an saves them to an ArrayList. What I want to be able to do is check if a specified point is on a line inside the Arraylist and return the line. I have been able to do this when the line is straight by using if (l.startX == l.stopX && l.startY < l.stopY but this doesn't work if the line is on an angle. I would also like to do this with drawText and drawCircle. Is there some simple way of doing this that I have missed?
DrawView.java
class Line {
float startX, startY, stopX, stopY;
public Line(float startX, float startY, float stopX, float stopY) {
this.startX = startX;
this.startY = startY;
this.stopX = stopX;
this.stopY = stopY;
}
public Line(float startX, float startY) { // for convenience
this(startX, startY, startX, startY);
}
}
public class DrawView extends View {
Paint paint = new Paint();
ArrayList<Line> lines = new ArrayList<Line>();
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
for (Line l : lines) {
canvas.drawLine(l.startX, l.startY, l.stopX, l.stopY, paint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
lines.add(new Line(event.getX(), event.getY()));
return true;
}
else if ((event.getAction() == MotionEvent.ACTION_MOVE ||
event.getAction() == MotionEvent.ACTION_UP) &&
lines.size() > 0) {
Line current = lines.get(lines.size() - 1);
current.stopX = event.getX();
current.stopY = event.getY();
Invalidate();
return true;
}
else {
return false;
}
}
}
I don't know if there is a canvas library for this but manually you can:
go through your list of lines
form equations for each line in let's say slope-intercept form y = mx + b
plugin in the event.X() and event.Y() into the above equation as x and y for each line
if the 2 sides are equal then your touch event is on that line
After many hours of trying I managed to come up with a an algorithm to check if a point is on a given line using a mixture of slope-intersect formula and if (x = startX && y > startY && y < stopY) Below is the code, it returns true if point is on line otherwise false, hopefully this can save someone time!
public boolean checkPosition(float x, float y, float sx, float sy, float ex, float ey) {
float mX = ex - sx;
float mY = ey - sy;
float smX = sx - ex;
float smY = sy - ey;
float pmX = mX;
float pmY = mY;
float psmX = smX;
float psmY = smY;
float yY = ey - y;
float xX = ex - x;
float sX = sx - x;
float sY = sy - y;
float m = mY / mX;
float b = sy - (m * sx);
if (mX < 0) {
pmX = mX * - 1;
}
if (mY < 0) {
pmY = mY * - 1;
}
if (smX < 0) {
psmX = smX * - 1;
}
if (smY < 0) {
psmY = smY * - 1;
}
if (yY < 0) {
yY = yY * - 1;
}
if (xX < 0) {
xX = xX * - 1;
}
if (sX < 0) {
sX = sX * - 1;
}
if (sY < 0) {
sY = sY * - 1;
}
if (sy == ey && y == sy) {
if (sx >= ex) {
if (x <= sx && x >= ex) return true;
else return false;
}
else if (ex >= sx) {
if (x <= ex && x >= sx) return true;
else return false;
}
else return false;
}
else if (sx == ex && x == sx) {
if (sy >= ey) {
if (y <= sy && y >= ey) return true;
else return false;
}
else if (ey >= sy) {
if (y <= ey && y >= sy) return true;
else return false;
}
else return false;
}
else if (xX <= pmX && sX <= psmX && yY <= pmY && sY <= psmY) {
if (y == (m * x) + b) return true;
else return false;
}
else return false;
}

LIBGDX: How do I draw a filled polygon with the shaperenderer?

I have defined a shape using an array of vertices:
float[] points = new float[]{50,60,50,70,60,70, 60,60,50,60};
And I am drawing this here:
shapeRenderer.polygon(floatNew);
This just gives an outline of the shape.
How do I fill it with colour?
Thanks
Currently, ShapeRenderer supports polygon drawing (by line) but not filling.
This code is clipping the polygon on triangles, and then drawing each triangle separately.
Edit ShapeRenderer.java like this:
EarClippingTriangulator ear = new EarClippingTriangulator();
public void polygon(float[] vertices, int offset, int count)
{
if (shapeType != ShapeType.Filled && shapeType != ShapeType.Line)
throw new GdxRuntimeException("Must call begin(ShapeType.Filled) or begin(ShapeType.Line)");
if (count < 6)
throw new IllegalArgumentException("Polygons must contain at least 3 points.");
if (count % 2 != 0)
throw new IllegalArgumentException("Polygons must have an even number of vertices.");
check(shapeType, null, count);
final float firstX = vertices[0];
final float firstY = vertices[1];
if (shapeType == ShapeType.Line)
{
for (int i = offset, n = offset + count; i < n; i += 2)
{
final float x1 = vertices[i];
final float y1 = vertices[i + 1];
final float x2;
final float y2;
if (i + 2 >= count)
{
x2 = firstX;
y2 = firstY;
} else
{
x2 = vertices[i + 2];
y2 = vertices[i + 3];
}
renderer.color(color);
renderer.vertex(x1, y1, 0);
renderer.color(color);
renderer.vertex(x2, y2, 0);
}
} else
{
ShortArray arrRes = ear.computeTriangles(vertices);
for (int i = 0; i < arrRes.size - 2; i = i + 3)
{
float x1 = vertices[arrRes.get(i) * 2];
float y1 = vertices[(arrRes.get(i) * 2) + 1];
float x2 = vertices[(arrRes.get(i + 1)) * 2];
float y2 = vertices[(arrRes.get(i + 1) * 2) + 1];
float x3 = vertices[arrRes.get(i + 2) * 2];
float y3 = vertices[(arrRes.get(i + 2) * 2) + 1];
this.triangle(x1, y1, x2, y2, x3, y3);
}
}
}
You cant draw a filled Polygon with the shaperender yet. take a look at this from the bugtracker
You can also read that in the API.
public void polygon(float[] vertices)
Draws a polygon in the x/y plane. The vertices must contain at least 3
points (6 floats x,y). The ShapeRenderer.ShapeType passed to begin has
to be ShapeRenderer.ShapeType.Line.
API ShapeRender
Sure if its with ShapeType.Line you just get the outlines.
You need to draw it yourself with Triangles in that case. It should be possible to fill at least Triangles.
Maybe take a look at this from Stackoverflow: drawing-filled-polygon-with-libgdx
Edit your ShapeRenderer.java class replacing polygon() method with the following code:
public void polygon(float[] vertices, int offset, int count) {
if (currType != ShapeType.Filled && currType != ShapeType.Line)
throw new GdxRuntimeException(
"Must call begin(ShapeType.Filled) or begin(ShapeType.Line)");
if (count < 6)
throw new IllegalArgumentException(
"Polygons must contain at least 3 points.");
if (count % 2 != 0)
throw new IllegalArgumentException(
"Polygons must have an even number of vertices.");
checkDirty();
checkFlush(count);
final float firstX = vertices[0];
final float firstY = vertices[1];
if (currType == ShapeType.Line) {
for (int i = offset, n = offset + count; i < n; i += 2) {
final float x1 = vertices[i];
final float y1 = vertices[i + 1];
final float x2;
final float y2;
if (i + 2 >= count) {
x2 = firstX;
y2 = firstY;
} else {
x2 = vertices[i + 2];
y2 = vertices[i + 3];
}
renderer.color(color);
renderer.vertex(x1, y1, 0);
renderer.color(color);
renderer.vertex(x2, y2, 0);
}
} else {
for (int i = offset, n = offset + count; i < n; i += 4) {
final float x1 = vertices[i];
final float y1 = vertices[i + 1];
if (i + 2 >= count) {
break;
}
final float x2 = vertices[i + 2];
final float y2 = vertices[i + 3];
final float x3;
final float y3;
if (i + 4 >= count) {
x3 = firstX;
y3 = firstY;
} else {
x3 = vertices[i + 4];
y3 = vertices[i + 5];
}
renderer.color(color);
renderer.vertex(x1, y1, 0);
renderer.color(color);
renderer.vertex(x2, y2, 0);
renderer.color(color);
renderer.vertex(x3, y3, 0);
}
}
}
Usage:
gdx_shape_renderer.begin(ShapeType.Filled);
gdx_shape_renderer.setColor(fill_r, fill_g, fill_b, fill_a);
gdx_shape_renderer.polygon(vertices);
gdx_shape_renderer.end();
gdx_shape_renderer.begin(ShapeType.Line);
gdx_shape_renderer.setColor(border_r, border_g, border_b, border_a);
gdx_shape_renderer.polygon(vertices);
gdx_shape_renderer.end();

Categories