Im searching for an algorythem to get the location of a hexagon in a grid.
I found this one but it doesnt seam to work:
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
grid[i][j] = new Hexagon(x+(j*((3*Hexagon.S)/2)), y+((j%2)*Hexagon.A)+(2*i*Hexagon.A));
}
}
The output is kind of strange:
output
This is the window-creating class(just a test class):
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Grid extends JPanel {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
int width = 2;
int height = 4;
int x = 100;
int y = 100;
Hexagon[][] grid = new Hexagon[width][height];
JFrame f = new JFrame();
Container cp = f.getContentPane();
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
grid[i][j] = new Hexagon(x+(j*((3*Hexagon.S)/2)), y+((j%2)*Hexagon.A)+(2*i*Hexagon.A));
cp.add(grid[i][j]);
}
}
f.setLayout(null);
f.setBounds(100, 100, 300, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
The Hexagon.java class:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import javax.swing.JButton;
public class Hexagon extends JButton {
public static final int S = 50;
public static final int A = (int) (Math.sqrt(3)*(S/2));
private static final long serialVersionUID = 1L;
private final int x, y;
private final Polygon shape;
public Hexagon(int x, int y) {
this.x = x;
this.y = y;
this.shape = initHexagon();
setSize(2*S, 2*A);
setLocation(x-S, y-A);
setContentAreaFilled(false);
}
private Polygon initHexagon() {
Polygon p = new Polygon();
p.addPoint(x+(S/2), y-A);
p.addPoint(x+S, y);
p.addPoint(x+(S/2), y+A);
p.addPoint(x-(S/2), y+A);
p.addPoint(x-S, y);
p.addPoint(x-(S/2), y-A);
return p;
}
protected void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.drawPolygon(this.shape);
}
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(4));
g2.drawPolygon(this.shape);
}
public boolean contains(int x, int y) {
return this.shape.contains(x, y);
}
}
As i said, this class worked just fine using non-rectangular shapes.
There was no clipping or such.
You've posted your definition of Hexagon too late, so I copy-pasted a modified version of a similar class from my collection of code snippets.
Here is one way to generate a hexagonal grid:
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComponent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.function.*;
public class Hexagons extends JPanel {
private static final long serialVersionUID = 1L;
/** Height of an equilateral triangle with side length = 1 */
private static final double H = Math.sqrt(3) / 2;
static class Hexagon {
final int row;
final int col;
final double sideLength;
public Hexagon(int r, int c, double a) {
this.row = r;
this.col = c;
this.sideLength = a;
}
double getCenterX() {
return 2 * H * sideLength * (col + (row % 2) * 0.5);
}
double getCenterY() {
return 3 * sideLength / 2 * row;
}
void foreachVertex(BiConsumer<Double, Double> f) {
double cx = getCenterX();
double cy = getCenterY();
f.accept(cx + 0, cy + sideLength);
f.accept(cx - H * sideLength, cy + 0.5 * sideLength);
f.accept(cx - H * sideLength, cy - 0.5 * sideLength);
f.accept(cx + 0, cy - sideLength);
f.accept(cx + H * sideLength, cy - 0.5 * sideLength);
f.accept(cx + H * sideLength, cy + 0.5 * sideLength);
}
}
public static void main(String[] args) {
final int width = 50;
final int height = 50;
final Hexagon[][] grid = new Hexagon[height][width];
for(int row = 0; row < height; row++) {
for(int col = 0; col < width; col++) {
grid[row][col] = new Hexagon(row, col, 50);
}
}
JFrame f = new JFrame("Hexagons");
f.getContentPane().setLayout(new GridLayout());
f.getContentPane().add(new JComponent() {
#Override public void paint(Graphics g) {
g.setColor(new Color(0xFF, 0xFF, 0xFF));
g.fillRect(0,0,1000,1000);
g.setColor(new Color(0,0,0));
final int[] xs = new int[6];
final int[] ys = new int[6];
for (Hexagon[] row : grid) {
for (Hexagon h: row) {
final int[] i = {0};
h.foreachVertex((x, y) -> {
xs[i[0]] = (int)((double)x);
ys[i[0]] = (int)((double)y);
i[0]++;
});
g.drawPolygon(xs, ys, 6);
g.drawString(
"(" + h.row + "," + h.col + ")",
(int)(h.getCenterX() - 15),
(int)(h.getCenterY() + 12)
);
}
}
}
});
f.setBounds(0, 0, 500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
try {
Thread.sleep(100);
} catch (Throwable e) {
} finally {
f.repaint();
}
}
}
It produces the following output:
Sorry for the lack of anti-aliasing. A few hints:
Height H of an equilateral triangle with unit side length is sqrt(3) / 2
The six offsets from the center are (0, +1), (H, +1/2), (H, -1/2), (0, -1), (-H, -1/2), (-H, +1/2), everything times side length.
Distance between rows is 1.5, distance between columns is 2 * H (times scaling constant = side length).
Every odd row is shifted by (0, H) (times scaling constant).
The position of (row,col)-th hexagon is (1.5 * row, 2 * H * (col + 0.5 * (row % 2))) (times constant).
If you want to rotate the hexagons such that two of their sides are horizontal, you have to flip rows and columns.
Related
I'm using the java.awt graphics class, and I'm trying to make rows and squares.
I can't seem to get the layout of the rows correctly.
I'm trying to code 8 rows with 3 columns each. However, I just get 2 rows with 12 columns.
If somebody can help me to create the outcome that I want, that would be greatly appreciated.
Here's my code:
g.setColor(Color.WHITE);
int x = 70;
int y = 80;
int w = 30;
int h = 35;
for(int row = 0; row < 3; row++) {
for(int col = 0; col < 4; col++) {
g.fillRect( x, y, w, h );
g.fillRect( x, y + h + 20, w, h );
x += w + 15;
}
System.out.println();
}
Here's the output: 2 rows, 12 columns of squares
Beware of how you are updating your position information. For example, you should only be updating the x position in the inner loop and resetting to 0 before entering the inner loop, and the y position should only be updated on each new row.
Alternatively, you could calculate the position directly, based on the row/column index and the row/column height, as demonstrated below.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private static int COLUMN_COUNT = 3;
private static int ROW_COUNT = 8;
private static int COLUMN_WIDTH = 30;
private static int ROW_HEIGHT = 35;
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(3 * COLUMN_WIDTH, 8 * ROW_HEIGHT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int columnWidth = getWidth() / 3;
int rowHeight = getHeight() / 8;
int x = 0;
int y = 0;
for (int row = 0; row < ROW_COUNT; row++) {
for (int col = 0; col < COLUMN_COUNT ; col++) {
if (col % 2 == 0) {
x = columnWidth * col;
y = rowHeight * row;
g2d.fillRect(x + 2, y + 2, columnWidth - 4, rowHeight - 4);
}
}
}
g2d.dispose();
}
}
}
this is my first time asking a question on stack overflow.
I've been following this tutorial on making a 2D game with java and have come across a problem...
When run my program it renders my sprite sheet very weirdly:
My JFrame:
his JFrame:
I have no Idea what is causing this problem but here is my code. i'm sorry if it is too long.
game.java:
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import com.leekman.game.gfx.screen;
import com.leekman.game.gfx.spriteSheet;
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = 1L;
public boolean running = false;
public static final int WIDTH = 160;
public static final int HEIGHT = WIDTH / 12 * 9;
public static final int SCALE = 3;
public static final String NAME = "Game";
private JFrame frame;
public int tickCount = 0;
private BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
private screen scrn;
public Game() {
setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
frame = new JFrame(NAME);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(this, BorderLayout.CENTER);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void init() {
scrn = new screen(WIDTH, HEIGHT, new spriteSheet("/Sprite_sheet.png"));
}
private synchronized void start() {
running = true;
new Thread(this).start();
}
private synchronized void stop() {
running = false;
}
#Override
public void run() {
long lastTime = System.nanoTime();
double NSpertick = 1000000000D / 60D;
int ticks= 0;
int frames = 0;
long lastTimer = System.currentTimeMillis();
double unproccesedTime = 0;
init();
while (running) {
long now = System.nanoTime();
unproccesedTime += (now - lastTime) / NSpertick;
lastTime = now;
boolean shouldRender = true;
while (unproccesedTime >= 1) {
ticks++;
tick();
unproccesedTime -= 1;
shouldRender = true;
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (shouldRender) {
frames++;
render();
}
if (System.currentTimeMillis() - lastTimer >= 1000) {
lastTimer += 1000;
System.out.println(frames+", "+ticks);
frames = 0;
ticks = 0;
}
}
}
public void tick() {
tickCount++;
for (int i = 0; i < pixels.length; i++) {
pixels[i] = i + tickCount;
}
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
scrn.render(pixels, 0, WIDTH);
Graphics g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.drawRect(0, 0, getWidth(), getHeight());
g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}
public static void main(String[] args) {
new Game().start();
}
}
spriteSheet.java:
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class spriteSheet {
public String path;
public int width;
public int height;
public int[] pixels;
public spriteSheet(String path) {
BufferedImage image = null;
try {
image = ImageIO.read(spriteSheet.class.getResourceAsStream(path));
} catch (IOException e) {
e.printStackTrace();
}
if (image == null) {
return;
}
this.path = path;
this.height = image.getHeight();
this.width = image.getWidth();
pixels = image.getRGB(0, 0, width, height, null, 0, width);
for (int i = 0; i < pixels.length; i++) {
pixels[i] = (pixels[i] & 0xff) / 64;
}
for (int i = 0; i < 8; i++) {
System.out.println(pixels[i]);
}
}
}
screen.java:
public class screen {
public static final int MAP_WIDTH = 64;
public static final int MAP_WIDTH_MASK = MAP_WIDTH - 1;
public int[] tiles = new int[MAP_WIDTH * MAP_WIDTH];
public int[] colours = new int[MAP_WIDTH * MAP_WIDTH * 4];
public int Xoffset = 0;
public int Yoffset = 0;
public int height;
public int width;
public spriteSheet sheet;
public screen(int width, int height , spriteSheet sheet) {
this.height = height;
this.width = width;
this.sheet = sheet;
for (int i = 0; i < MAP_WIDTH * MAP_WIDTH; i++) {
colours[i * 4 + 0] = 0xff00ff;
colours[i * 4 + 1] = 0x00ffff;
colours[i * 4 + 2] = 0xffff00;
colours[i * 4 + 3] = 0xffffff;
}
}
public void render(int[] pixels, int offset, int row) {
for (int yTile = Yoffset >> 3; yTile <= (Yoffset + height) >> 3; yTile++) {
int yMin = yTile * 8 - Yoffset;
int yMax = yMin + 8;
if (yMin < 0) {
yMin = 0;
}
if (yMax > height) {
yMax = height;
}
for (int xTile = Xoffset >> 3; xTile <= (Xoffset + width) >> 3; xTile++) {
int xMin = xTile * 8 - Xoffset;
int xMax = xMin + 8;
if (xMin < 0) {
xMin = 0;
}
if (xMax > width) {
xMax = width;
}
int tileIndex = (xTile & (MAP_WIDTH_MASK)) + (yTile & (MAP_WIDTH_MASK)) * MAP_WIDTH;
for (int y = yMin; y < yMax; y++) {
int sheetpix = y + ((y + Yoffset) & 7) * sheet.width + ((xMin + Xoffset) & 7);
int tilepix = offset + xMin + y * row;
for (int x = xMin; x < xMax; x++) {
int colour = tileIndex * 4 + sheet.pixels[sheetpix++];
pixels[tilepix++] = colours[colour];
}
}
}
}
}
}
Any help would be very much appreciated, thanks!!
I am having trouble replicating the picture for my assignment. I would appreciate any tips or solutions. I believe I have the general idea down, but I am having a hard time figuring out the math to replicate the image and doing everything in a single loop.
My program needs to meet these criteria:
Match the Image
Generate a random color for each pair of parabolic curve
Work with any width or height
Use a single loop to draw the entire figure.
Here is the image:
This is what I have tried so far
public static final int WIDTH = 500;
public static final int HEIGHT = 500;
public static final int LINE_INCREMENT = 5;
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(WIDTH, HEIGHT);
Graphics g = panel.getGraphics();
int d = 0;
int iterations = HEIGHT/LINE_INCREMENT;
Random rand = new Random();
int red = 0, green = 0, blue = 0;
red = rand.nextInt(128) + 128;
green = rand.nextInt(128) + 128;
blue = rand.nextInt(128) + 128;
g.setColor(new Color(red,green,blue));
for(int y = 0; y < iterations; y++) {
g.drawLine(0, d, d, HEIGHT);
g.drawLine(WIDTH, d, d, 0);
d += LINE_INCREMENT;
}
red = rand.nextInt(128) + 128;
green = rand.nextInt(128) + 128;
blue = rand.nextInt(128) + 128;
g.setColor(new Color(red,green,blue));
d = 0;
for (int x = 0; x < iterations/2; x++) {
g.drawLine(WIDTH/4, d + HEIGHT/4, d + WIDTH/4, HEIGHT - HEIGHT/4);
g.drawLine(d + WIDTH/4, WIDTH/4, WIDTH - WIDTH/4, d + WIDTH/4);
d += LINE_INCREMENT;
}
}
The output:
The way to implement it is by overriding paintComponent:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ParabolicCurves extends JFrame {
private static final int SIZE = 600;
private static final int LINE_INCREMENT = 5;
private static final int NUM_OF_PATTERNS = 4;
private Random rand = new Random();
ParabolicCurves() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JPanel panel = new DrawingPanel(SIZE);
add(panel, BorderLayout.CENTER);
pack();
setVisible(true);
}
class DrawingPanel extends JPanel{
public DrawingPanel(int size) {
setPreferredSize(new Dimension(size, size));
setBackground(Color.WHITE);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int red, green, blue, delta , iterations;
int height, width ,startX, startY, endX, endY ;
Rectangle boundingRrectangle = getBounds();
for(int pattern = 0 ; pattern < NUM_OF_PATTERNS; pattern++) {
red = rand.nextInt(128) + 128;
green = rand.nextInt(128) + 128;
blue = rand.nextInt(128) + 128;
g.setColor(new Color(red,green,blue));
height = (int) boundingRrectangle.getHeight();
width = (int) boundingRrectangle.getWidth();
startX = (int) boundingRrectangle.getX();
startY = (int) boundingRrectangle.getY();
endX = startX+width;
endY = startY+ height;
iterations = Math.min(width, height)/LINE_INCREMENT;
delta = 0;
for (int x = 0; x < iterations ; x++) {
g.drawLine(startX, startY+delta, startX+delta, endY);
g.drawLine(endX, startY+delta, startX+delta, startY);
delta += LINE_INCREMENT;
}
//change bounding rectangle
boundingRrectangle = new Rectangle(startX+(width/4),
startY+(width/4), width/2, height/2);
}
}
}
public static void main(String[] args) {
new ParabolicCurves();
}
}
Output:
I'm working on a java programming exercise where we have to draw a circular spiral using the drawArc method so that the result looks similar to this:
I've been working on this for a while and this is what I have so far:
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class CircSpiral extends JPanel {
public void paintComponent(Graphics g) {
int x = 100;
int y = 120;
int width = 40;
int height = 60;
int startAngle = 20;
int arcAngle = 80;
for (int i = 0; i < 5; i++) {
g.drawArc(x, y, width, height, startAngle, arcAngle);
g.drawArc(x + 10, y + 10, width, height, startAngle + 10, arcAngle);
x = x + 5;
y = y + 5;
startAngle = startAngle - 10;
arcAngle = arcAngle + 10;
}
}
public static void main(String[] args) {
CircSpiral panel = new CircSpiral();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(300, 300);
application.setVisible(true);
}
}
My code gives me this result:
I know the problem lies in my arguments for the drawArc method because the numbers aren't right, but I don't know how to go about making the numbers go in a circular manner. Any help is appreciated. Thank you!
Your idea is almost right. I did some modifications. You need to inverse the angle to draw the other side of the spiral and use fixed point to startAngle.
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class CircSpiral extends JPanel {
public void paintComponent(Graphics g) {
int x = getSize().width / 2 - 10;
int y = getSize().height/ 2 - 10;
int width = 20;
int height = 20;
int startAngle = 0;
int arcAngle = 180;
int depth = 10;
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
// g.drawArc(x + 10, y + 10, width, height, startAngle + 10, -arcAngle);
// x = x - 5;
y = y - depth;
width = width + 2 * depth;
height = height + 2 * depth;
g.drawArc(x, y, width, height, startAngle, -arcAngle);
} else {
// g.drawArc(x + 10, y + 10, width, height, startAngle + 10, arcAngle);
x = x - 2 * depth;
y = y - depth;
width = width + 2 * depth;
height = height + 2 * depth;
g.drawArc(x, y, width, height, startAngle, arcAngle);
}
}
}
public static void main(String[] args) {
CircSpiral panel = new CircSpiral();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(300, 300);
application.setVisible(true);
}
}
If this were my project, yes I'd draw my arcs in a loop, but within the loop, I'd try to make the arc's bounding box bigger but still centered over the same location. To do this I'd decrement x and y by some small constant, say DELTA (which I'd set to == 1), and I'd increment width and height by 2 * DELTA. I'd also leave my arcAngle unchanged but rather would change my startAngle in the loop like so: startAngle = startAngle - arcAngle;.
For example, this:
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class CircSpiral extends JPanel {
private static final int DELTA = 1;
private static final int ARC_ANGLE = 20;
private static final int PREF_W = 300;
private static final int PREF_H = PREF_W;
private static final int LOOP_MAX = 400;
public void paintComponent(Graphics g) {
int x = PREF_W / 2;
int y = PREF_H / 2;
int width = 1;
int height = 1;
int startAngle = 0;
int arcAngle = ARC_ANGLE;
for (int i = 0; i < LOOP_MAX; i++) {
g.drawArc(x, y, width, height, startAngle, arcAngle);
x = x - DELTA;
y = y - DELTA;
width += 2 * DELTA;
height += 2 * DELTA;
startAngle = startAngle - arcAngle;
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
public static void main(String[] args) {
CircSpiral panel = new CircSpiral();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.pack();
application.setLocationRelativeTo(null);
application.setVisible(true);
}
}
Would result in this:
The following code will output this image:
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class CircSpiral extends JPanel {
public void paintComponent(Graphics g) {
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
int numIterations = 5;
int arcWidth = 10;
int arcGrowDelta = 30;
for (int i = 0; i < numIterations; i++) {
g.drawArc(centerX - arcWidth, centerY - arcWidth, 2 * arcWidth, 2 * arcWidth, 0, 180);
arcWidth += arcGrowDelta;
g.drawArc(centerX - arcWidth, centerY - arcWidth, 2 * arcWidth - arcGrowDelta, 2 * arcWidth, 180, 180);
}
}
public static void main(String[] args) {
CircSpiral panel = new CircSpiral();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(300, 300);
application.setVisible(true);
}
}
The idea is very simple, just draw the upper half of a circle, like this:
Then increment the arc size by a constant factor and draw the bottom half of the circle but making the end point of this circle and the upper circle match, for it, just substrate the arcGrowDelta from the bottom circle width:
And repeat.
This is my solution:
package mainpack;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JPanel;
public class SpiralPanel extends JPanel {
private static final long serialVersionUID = 1L;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
int width = 10;
int height = 10;
int startAngle = 0;
int arcAngle = 180;
int x = (getWidth() - width) / 2;
int y = (getHeight() - height) / 2;
int i = 0;
int t = 0;
while (i < 36) {
g2d.drawArc(x + t, y, width, height, startAngle, arcAngle);
if (i % 2 == 0) {
t -= 10;
}
y -= 5;
width += 10;
height += 10;
startAngle += 180;
i++;
}
}
}
I am a beginner to java and finally managed how to create the spiral.
Here is my code:
int lineLength = 20; //starting line length
int x = getWidth() / 2; //start drawing from center of JPanel
int y = getHeight() / 2; //start drawing from center of JPanel
for( int counter = 0; counter < 10; counter++ )
{
g.drawArc( x, y, lineLength, lineLength, 0, 180 ); //draws top semicircle of equal width and height
lineLength += 20; //increases arc diameter
x -= 20; //moves x coordinate left
g.drawArc( x, y - 10, lineLength, lineLength, 0, -180 ); //draws bottom semicircle; 'y - 10' joins the 2 semicircles
lineLength += 20; //increases arc diameter
y -= 20; //moves y coordinate up
}
If you're willing to let some good old trigonometry do the work, you could use this:
import java.awt. *;
import javax.swing. *;
import java.math.*;
public class Spiral extends JFrame {
public Spiral()
{
// Set Window
setTitle("Spirale");
setSize(1500, 1500);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public void paint(Graphics g)
{
super.paint(g);
for(double i = 1; i < 50000; i++)
{
int locY = 600 - (int) (Math.cos((Math.PI*i)/1800)*i/50);
int locX = 600 - (int) (Math.sin((Math.PI*i)/1800)*i/50);
g.drawLine(locX, locY, locX, locY);
}
}
public static void main(String[] args) {
new Spiral();
}
}
I have been working on a game via youtube tutorial, some of you may recognize it as the one presents by designsbyzephr and have run into an issue. I am fairly sure the code is correct as I have used the call before in a previous project. I am getting an array out of bounds exception even when using the full project source code posted on github. Any suggestions?
package Game;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import GFX.Screen;
import GFX.SpriteSheet;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 160;
public static final int HEIGHT = WIDTH / 12 * 9;
public static final int SCALE = 3;
public static final String NAME = "Game";
private JFrame frame;
public boolean running = false;
public int tickcount = 0;
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
private Screen screen;
public Game() {
setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
frame = new JFrame(NAME);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(this, BorderLayout.CENTER);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void init() {
screen = new Screen(WIDTH, HEIGHT, new SpriteSheet("/Sprites/spritesheet.png"));
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
screen.render(pixels, 0, WIDTH);
Graphics g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}
public synchronized void start() {
running = true;
new Thread(this).start();
}
public synchronized void stop() {
running = false;
}
public void run() {
long lastTime = System.nanoTime();
double nsPerTick = 1000000000D / 60D;
int ticks = 0;
int frames = 0;
long lastTimer = System.currentTimeMillis();
double delta = 0;
init();
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / nsPerTick;
lastTime = now;
boolean shouldRender = true;
while (delta >= 1) {
ticks++;
tick();
delta -= 1;
shouldRender = true;
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (shouldRender) {
frames++;
render();
}
if (System.currentTimeMillis() - lastTimer >= 1000) {
lastTimer += 1000;
frames = 0;
ticks = 0;
}
}
}
public void tick() {
tickcount++;
for (int i = 0; i < pixels.length; i++)
pixels[i] = i + tickcount;
}
public static void main(String[] args) {
new Game().start();
}
}
package GFX;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class SpriteSheet {
public String path;
public int width;
public int height;
public int[] pixels;
public SpriteSheet(String path) {
BufferedImage image = null;
try
{
image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path));
}
catch (IOException e)
{
e.printStackTrace();
}
if (image == null) return;
this.path = path;
this.width = image.getWidth();
this.height = image.getHeight();
pixels = image.getRGB(0, 0, width, height, null, 0, width);
for (int i = 0; i < pixels.length; i++) {
pixels[i] = (pixels[i] & 0xff) / 64;
}
for (int i = 0; i < 8; i++)
System.out.println(pixels[i]);
}
}
package GFX;
public class Screen {
public static final int MAP_WIDTH = 64;
public static final int MAP_WIDTH_MASK = MAP_WIDTH - 1;
public int[] tiles = new int[MAP_WIDTH * MAP_WIDTH];
public int[] colors = new int[MAP_WIDTH * MAP_WIDTH];
public int xOffset = 0;
public int yOffset = 0;
public int width;
public int height;
public SpriteSheet sheet;
public Screen(int width, int height, SpriteSheet sheet) {
this.width = width;
this.height = height;
this.sheet = sheet;
for (int i = 0; i < MAP_WIDTH * MAP_WIDTH; i++) {
colors[i * 4 + 0] = 0xff00ff;
colors[i * 4 + 1] = 0x00ffff;
colors[i * 4 + 2] = 0xffff00;
colors[i * 4 + 3] = 0x0000ff;
}
}
public void render(int[] pixels, int offset, int row) {
for (int yTile = yOffset >> 3; yTile <= (yOffset + height) >> 3; yTile++) {
int yMin = yTile * 8 - yOffset;
int yMax = yMin + 8;
if (yMin < 0)
yMin = 0;
if (yMin > height)
yMax = height;
for (int xTile = xOffset >> 3; xTile <= (xOffset + width) >> 3; xTile++) {
int xMin = xTile * 8 - xOffset;
int xMax = xMin + 8;
if (xMin < 0)
xMin = 0;
if (xMin > width)
xMax = width;
int tileIndex = (xTile & (MAP_WIDTH_MASK))
+ (yTile & (MAP_WIDTH_MASK)) * MAP_WIDTH;
for (int y = yMin; y < yMax; y++) {
int sheetPixel = ((y + yOffset) & 7) * sheet.width
+ ((xMin + xOffset) & 7);
int tilePixel = offset + xMin + y * row;
for (int x = xMin; x < xMax; x++) {
int color = tileIndex * 4 + sheet.pixels[sheetPixel++];
pixels[tilePixel++] = colors[color];
}
}
}
}
}
}
That is all the code so far. the error is as follows
Exception in thread "Thread-2" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at GFX.SpriteSheet.(SpriteSheet.java:22)
at Game.Game.init(Game.java:54)
at Game.Game.run(Game.java:91)
at java.lang.Thread.run(Unknown Source)
it is in this line
image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path));
your program cannot find file so it is returning null and a null pointer exception is thrown when you try and read from null
you need to make sure there is a file"/Sprites/spritesheet.png" relative to where you are running the program