I am having some problems drawing lines in my Java program.
I wish to play with some Maze Generation Algorithms but am currently struggling to set up a board to visualize the process and creation of the mazes. Below is my current Setup:
I generate a grid (2D Array) 50 x 25, each block is 20 pixels wide and 20 pixels tall, now for each grid I want to draw each of the four walls as lines.
I get the starting x and y coordinate of each block by multiplying the for loop values (used to traverse the array) by the block size. For Example if I am currently looking at grid[2][3] then the pixel coordinates will be (40, 60). My problem is that the South wall and the East Wall are not being drawn, nothing is showing in my program even though the coordinates are being generated, my North Wall and West Wall are however being drawn.
I am trying to get the walls Coordinates by adjusting the positions as follows, if I want to draw the south wall and the starting x and y coordinates of the block are (40, 60). Then the 2 points that should be used to draw the South Wall should be, (40, 80) and (60, 80).
Below is the Render Method that I am currently using:
private void renderBoard(Graphics g) {
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
Node node = grid[i][j];
// Draw the Node's Background
g.setColor(Color.BLACK);
g.fillRect(i * blockSize, j * blockSize, blockSize, blockSize);
// Draw the Node's North Wall
if (node.walls.contains(Walls.NORTH)) {
Line line = new Line(i, j, Walls.NORTH, blockSize);
// System.out.println("Point1 (X1: " + line.x1 + " Y1: " + line.y1 + ") Point2 (X2: " + line.x2 + " Y2: " + line.y2 + ")");
g.setColor(Color.WHITE);
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
// Draw the Node's South Wall
if (node.walls.contains(Walls.SOUTH)) {
Line line = new Line(i, j, Walls.SOUTH, blockSize);
g.setColor(Color.WHITE);
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
}
}
Again the North wall is drawn while nothing is drawn for the South Wall. I initially thought it might be because I was passing in the two for loop variables in the wrong order. But that didn't seem to change anything
This is my Line Class:
class Line {
// Current X Y Coordinates in the Grid
private int x;
private int y;
// The Lines Start and End Coordinates
public int x1, x2;
public int y1, y2;
public Line(int x, int y, Walls wall, int blocksize) {
// Here we get the pixel coordinate based off of the current Array Position
this.x = (x * blocksize);
this.y = (y * blocksize);
switch(wall) {
case NORTH:
x1 = this.x;
y1 = this.y;
x2 = this.x + blocksize;
y2 = this.y;
break;
case SOUTH:
x1 = this.x;
y1 = this.y + blocksize;
x2 = this.x + blocksize;
y2 = this.y + blocksize;
break;
case EAST:
x1 = this.x + blocksize;
y1 = this.y;
x2 = this.x + blocksize;
y2 = this.y + blocksize;
break;
case WEST:
x1 = this.x;
y1 = this.y;
x2 = this.x;
y2 = this.y + blocksize;
break;
}
}
}
I have a sneaking suspicion that I am doing something really really silly or missing something very small, any help would be gladly appreciated
Related
I am trying to hollow out a sphere, I already achieved this however it is incredibly slow (A few seconds for a sphere with a radius of 5, a few minutes for a sphere with a radius of 100)
This is my code:
BlockPos pos = player.getBlockPos();
int startX = pos.getX();
int startY = pos.getY();
int startZ = pos.getZ();
int squaredRadius = radius * radius;
int x1;
int y1;
int z1;
int flags = 2 | 8 | 16 | 32;
BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0);
BlockState state = Blocks.AIR.getDefaultState();
for (int x = startX - radius; x < startX + radius; x++) {
for (int y = Math.max(0, startY - radius), maxY2 = Math.min(255, startY + radius); y < maxY2; y++) {
for (int z = startZ - radius; z < startZ + radius; z++) {
x1 = x - startX;
y1 = y - startY;
z1 = z - startZ;
if (x1 * x1 + y1 * y1 + z1 * z1 <= squaredRadius)
world.setBlockState(blockPos.set(x, y, z), state, flags);
}
}
}
How could I speed this up? (Or is it already as fast as it can be?)
EDIT: For a 100 radius it takes roughly 8 minutes on my machine
Update: I managed to fix it! What I did was make a mixin into World#setBlockState(BlockPos, BlockState, int) and check if the flags were some number I set (999 in my case), and if it where I canceled the method execution right after the block state was set, saving huge amounts of time when placing a lot of blocks. However, it did not send the chunks to the player so what you have to do is simply send all the chunks you changed to the player, I did this by storing all the chunks I changed and for each player in the world I sent a ChunkDataS2CPacket with the new chunk to the player, which fixed my problem entirely, it works like a charm :D
EDIT: It also does not do block updates/lighting updates
I have a method in my project that runs only if both of the following conditions are true: the user presses the E key, and a pixel in the player's immediate vicinity is red on the unseen bitmap. The bitmap governs collision in my game. Here is the method:
private void doors(int x, int y) {
int doorColor = 0xFFFF0000;
int w = 0;
int h = 0;
while (bitmap.getRGB(x - 1, y) == doorColor)
x--;
while (bitmap.getRGB(x, y - 1) == doorColor)
y--;
while (bitmap.getRGB(x + w + 1, y) == doorColor)
w++;
while (bitmap.getRGB(x, y + h + 1) == doorColor)
h++;
for (int x2 = x; x2 < x + w + 1; x2++) {
for (int y2 = y; y2 < y + h + 1; y2++) {
foreground.setRGB(x2, y2, 0x00FFFFFF);
bitmap.setRGB(x2, y2, 0xFFFFFFFF);
}
}
}
}
This method, when given the x and y coordinates of the found red pixel, finds the top left corner of the red rectangle on the bitmap, and then finds the width and height of said rectangle. Once it has done this, it changes the colors of all the pixels in the rectangle to white, and clears the section of the foreground image to give the appearance of an opened door.
This method of opening the door works, but it takes long enough that the game visibly freezes for a few frames. Is there any way to avoid this?
Here is my bitmap:
And here is my foreground image:
Ok, I have a little problem: I'm trying to code an engine capable of rendering 3d lines onto a 2d plane, but I'm having some trouble with it.
I have a point3d class, which takes x y and z coords, a line3d class, which takes two point3d endpoints, and I have a world object containing an arraylist of line3d's. I also have point2d and line2d, which are just like their 3d counterparts, except that they lack a z coordinate.
Here's the render method:
public void render(){
for(Line3d line : world.lines){ //for every 3d line in the world
panel.l3d(line, world.main); //render that line
}
panel.repaint(); //repaint the graphic
}
Which calls upon the l3d method:
public void l3d(Line3d line, Camera view){
Point2d start = p3Top2(line.start, view), end = p3Top2(line.end, view); //convert 3d points to 2d points
if(start==null || end==null)return; //if either is null, return
lineAbs(new Line2d(start, end)); //draw the line
}
Which calls upon p3Top2:
public Point2d p3Top2(Point3d point, Camera view){ //convert 3d point to 2d point on screen
int relativeZed = point.z - view.z; //difference in z values between camera and point
if(relativeZed <= 0)return null; //if it's behind the camera, return
int sx, sy, ex, ey, tx, ty; //begin declaring rectangle formed from extending camera angle to the z coord of the point(angle of 1 = 90 degrees)
sx = (int) (view.x - (width / 2) - relativeZed * (width * view.angle)); //starting x of rectangle
ex = (int) (view.x + (width / 2) + relativeZed * (width * view.angle)); //ending x
sy = (int) (view.y - (height / 2) - relativeZed * (height * view.angle)); //starting y
ey = (int) (view.y + (height / 2) + relativeZed * (height * view.angle)); //ending y
tx = point.x - sx; //difference between point's x and start of rectangle
ty = point.y - sy; //same for y
float px = (float)tx / (float)(ex - sx), py = (float)ty / (float)(ey - sy); //px and py are the ratios of the point's x/y coords compared to the x/y of the rectangle their in
return new Point2d((int)(px * width), (int)(py * height)); //multiply it by the width and height to get positions on screen
}
And also on lineAbs:
public void lineAbs(Line2d line){
Point2d start = line.start;
Point2d end = line.end;
if(start.x>end.x){
start = line.end;
end = line.start;
}
int y = start.y; //starting y point
int white = 0xffffff;
for(int x = start.x; x<end.x; x++){ //for each x in the line
if(x < 0 || y < 0 || x > canvas.getWidth() || y > canvas.getHeight())continue; //if the point is outside of the screen, continue
y += line.getSlope().slope; //increment y by the slope
canvas.setRGB(x, y, white); //draw the point to the canvas
}
}
'canvas' is a BufferedImage being drawn to the screen. With an arbitrary camera and angle of 1, as well as a few arbitrary lines thrown in, I do see each line, but they don't appear to be rendered properly. For example, when I have three point3d's as vertices, and three lines, each with a different combination of two of the points, the lines don't appear to meet at all, although each one is visible.
I suspect the issue is in my p3Top2, but I'm not sure where, can you tell?
So I'm supposed to make a program where a ball bounces around a drawingpanel for 10 seconds. The ball has to bounce off the sides of the panel if it hits them. Right now when the ball hits the bottom panel instead of bouncing it appears in the middle of the screen and moves in the opposite direction until it hits the top and disappears.
I'm pretty sure the problem is in this part of my code...
(Earlier in the code I declared x to 1, y to 250, dx to 1, and dy to 1)
//Changes dirction
public static int newDirection1(int x, int dx, int size){
if (x < 0 || x > 500 || (x + size) < 0 || (x + size) > 500) {
dx *= -1;
return dx;
} else {
return dx;
}
}
//Changes direction
public static int newDirection2(int y, int dy, int size){
if (y < 0 || y > 500 || (y + size) < 0 || (y + size) > 500) {
dy *= -1;
return dy;
} else {
return dy;
}
}
//Moves ball one step
public static void move(Graphics g, Color color, int size, int x1, int y1, int x2, int y2){
g.setColor(Color.WHITE);
g.fillOval(x1, y1, size, size);
g.setColor(color);
g.fillOval(x2, y2, size, size);
}
//Pauses for 10ms
public static void sleep(int millis, DrawingPanel panel){
panel.sleep(millis);
}
public static void bounceLoop(DrawingPanel panel, Graphics g, Color color, int size, int x, int dx, int y, int dy, int millis){
int x1 = x + dx;
int x2 = x + dx;
int y1 = y + dy;
int y2 = y + dy;
for (int i = 0; i < 1000; i++) {
x1 = x + dx * i;
x2 = (x + dx * i) + dx;
y1 = y + dy * i;
y2 = (y + dy * i) + dy;
dx = newDirection1(x2, dx, size);
dy = newDirection2(y2, dy, size);
move(g, c, size, x1, y1, x2, y2);
sleep(millis, panel);
}
}
}
in the loop don't use:
x1 = x + dx * i
use
x1 = x1 + dx
(same for y)
because whenever dx is going to change, and multiply by -1, instead of continuing from where it was, and go to the other direction, it's going to continue from the other side of your panel, or a point that is really off.
Also a few things that could possibly fix the coding:
1- you don't need a dx parameter for your getNewDirection, you only need the coordinate.
2- the boundry conditions may give you errors, give it a small offset that can't be visible to the naked eye to avoid errors with creating objects outside the created panel or whatever you are using
I am trying to make a small program that will move the mouse from the current position to the given position. Here is a method that i can use which will move the mouse from one point to another but without animation:
moveMouse(int x, int y);
This will move the mouse from the current coordinates to x,y on screen without animation. Now my job is to move the mouse to that coordinate, but it should also show the mouse moving one pixel at a time. I need to create a loop which moves the mouse cursor few pixels x and y at a time so that Here is what i have been thinking:
public void moveMouseAnimation(x,y){
//Integers x2 and y2 will be the current position of the mouse cursor
boolean isRunning = true;
while(isRunning){
delay(10); // <- 10 Milliseconds pause so that people can see the animation
x2 -= 1;
y2 -= 1;
moveMouse(x2,y2);
if(x2 == x && y2 == y) isRunning = false; //Ends loop
}
}
Now i need to find correct x2 and y2 values so that the mouse moves in a straight line and reaches x and y at last. Could someone help me.
You want the Bresenham's line algorithm. It is commonly used to draw a line between two points, but you, instead of drawing a line, will move the mouse along it.
Below is the code to do that. This code uses Bresenham Line Algo. For more ref on soln try http://en.wikipedia.org/wiki/Bresenham's_line_algorithm if you are looking not to have jagged lines
boolean steep = Math.abs(y1 - y0) > Math.abs(x1 - x0);
if (steep) {
int t;
// swap(x0, y0);
t = x0;
x0 = y0;
y0 = t;
// swap(x1, y1);
t = x1;
x1 = y1;
y1 = t;
}
if (x0 > x1) {
int t;
// swap(x0, x1);
t = x0;
x0 = x1;
x1 = t;
// swap(y0, y1);
t = y0;
y0 = y1;
y1 = t;
}
int deltax = x1 - x0;
int deltay = Math.abs(y1 - y0);
int error = deltax / 2;
int ystep;
int y = y0;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for (int x = x0; x < x1; x++) {
if (steep)
moveMouse(y, x);
else
moveMouse(x, y);
error = error - deltay;
if (error < 0) {
y = y + ystep;
error = error + deltax;
}
}
The problem that you are attempting to solve is that of linear interpolation, in that you have a linear function, that of a line between the starting point (x0, y0) and the ending point (x1, y1).
Luckily the solution is simple. The Wikipedia article gives examples almost exactly what you're trying to do.
http://en.wikipedia.org/wiki/Linear_interpolation
You could interpolate a straight line....basically fitting y=mx+b to the given points.