Hey I am trying to draw a grid. I have dreated a 2D array and I am trying to fill it with Rectangle2D's. I would like the grid to be equal squares where a character can alk on. Here is my code:
public class GameWindow
{
public static int[][] map = {
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0},
{0, 2, 1, 0, 0}
};
public static double[][] board;
public static Rectangle2D setBoard()
{
Rectangle2D.Double tile = new Rectangle2D.Double(10, 10, 10, 10);
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
board[i][j] = tile;
}
}
}
public static int rows = 6;
public static int columns = 5;
public static int[][] next = new int[rows][columns];
public static void main(String[] args)
{
for(int i = 0; i < map.length; i++)
{
for(int j = 0; j < map[i].length; j++)
{
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}
}
There is a compile error and it is not letting me store rectangles in this array. Also I have doubts that it would even make a grid.
Well, board is an array of double and you are trying to put a Rectangle in there!!! You need:
public static Rectangle2D[][] board = new Rectangle2D[10][10];
And you need to decide where exactly the Rectangles will be located on screen somehow. You should not create a single Rectangle and place it in each location of the board.
public static Rectangle2D setBoard()
{
Rectangle2D.Double tile;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
tile = new Rectangle2D.Double(x, y, w, h);//how will you determine x and y here
board[i][j] = tile;
}
}
}
The code within setBoard has a couple of errors. First, you are creating a single Rectangle2D.Double instance, which you then reuse many times when building the contents of board. This means that if you make a change to any entry in board, all of the entries will be changed - the array contains 100 references to the same object.
The second issue, which is likely causing your compile error, is that board has type double[][] but you're trying to put a Rectangle2D.Double into it, which is a different "double" to your array. You can only put double values into your array.
Related
I have a simple 2D polygon with 4 points.
int[] x = {38, 100, 80, 18};
int[] y = {50, 50, 100, 100};
Polygon poly = new Polygon(x, y, 4);
The above polygon is just an example. The polygon above could really be anything as long as the polygon is always convex, always has 4 points, and is a parallelogram. I need to split it into any number of even parts, all proportional to the bigger polygon, as long as the number is a square number. Is there any simple way I can do this? I am using Graphics on a Jframe if that's important at all.
The code below works for any convex 4-sided polygon. When the initial polygon is a parallelogram, the resultant sub-polygons are by nature all parallelograms too, all with the same size, i.e. they are even-sized.
Since the desired number of parts must be a square number, it means we can simply split the 4-sided polygon horizontally and vertically into partsPerSide = sqrt(parts).
When we split a 4-sided polygon into multiple parts, we may end up with coordinates that are not exact integers. We can simply round the value to an integer, but then the pieces wouldn't be exactly even in size. Whether that is acceptable is a matter of choice. Visually, the rounding can be noticed, since the lines won't be 100% straight.
In the code below, we assume that rounding is not acceptable, i.e. we want exact even sizes. If rounding is ok, simply comment out the if (rounded != delta) throw new ArithmeticException() code at the end, then call splitFourSided() with the desired number of partsPerSide.
Enough talk, here is the code:
private static Polygon[][] splitFourSided(Polygon poly, int partsPerSide) {
if (poly.npoints != 4)
throw new IllegalArgumentException("Polygon must be 4-sided");
if (partsPerSide <= 0)
throw new IllegalArgumentException("There must be a positive number of parts per side");
int[][] x = splitFourSided(poly.xpoints, partsPerSide);
int[][] y = splitFourSided(poly.ypoints, partsPerSide);
Polygon[][] pieces = new Polygon[partsPerSide][partsPerSide];
for (int row = 0; row < partsPerSide; row++) {
for (int col = 0; col < partsPerSide; col++) {
pieces[row][col] = new Polygon(
new int[] { x[row][col], x[row][col+1], x[row+1][col+1], x[row+1][col] },
new int[] { y[row][col], y[row][col+1], y[row+1][col+1], y[row+1][col] },
4);
}
}
return pieces;
}
private static int[][] splitFourSided(int[] xy, int parts) {
// To visualize, assume values are [topLeft, topRight, bottomRight, bottomLeft].
// The 'xy' array is either the x-coordinates or the y-coordinates.
// First we split left and right sides, e.g. for 3 parts:
// From: ┌ To: ┐
// ├ ┤
// ├ ┤
// └ ┘
// Then we split between those:
// ┌─┬─┬─┐
// ├─┼─┼─┤
// ├─┼─┼─┤
// └─┴─┴─┘
int[] from = splitRange(xy[0], xy[3], parts);
int[] to = splitRange(xy[1], xy[2], parts);
int[][] grid = new int[parts + 1][];
for (int i = 0; i <= parts; i++)
grid[i] = splitRange(from[i], to[i], parts);
return grid;
}
private static int[] splitRange(int from, int to, int parts) {
int[] prorated = new int[parts + 1];
for (int i = 0; i <= parts; i++)
prorated[i] = prorate(from, to, i, parts);
return prorated;
}
private static int prorate(int from, int to, int index, int parts) {
if (index == 0)
return from;
if (index == parts)
return to;
double delta = (to - (double) from) * index / parts;
int rounded = (int) Math.round(delta);
if (rounded != delta)
throw new ArithmeticException("Cannot prorate to integer value");
return from + rounded;
}
Test
int[] x = {38, 100, 80, 18};
int[] y = {50, 50, 100, 100};
Polygon poly = new Polygon(x, y, 4);
splitAndDrawFourSided(g, poly, 2);
private static void splitAndDrawFourSided(Graphics g, Polygon poly, int partsPerSide) {
Polygon[][] pieces = splitFourSided(poly, partsPerSide);
for (int row = 0; row < partsPerSide; row++)
for (int col = 0; col < partsPerSide; col++)
g.drawPolygon(pieces[row][col]);
Graphics gMain = g.create();
try {
gMain.setColor(Color.RED);
gMain.drawPolygon(poly);
} finally {
gMain.dispose();
}
}
Result
To search for a valid number of parts, we can add a search loop, and change the coordinates so they are only divisible by 7.
int[] x = {37, 100, 79, 16};
int[] y = {50, 50, 99, 99};
Polygon poly = new Polygon(x, y, 4);
for (int partsPerSide : new int[] { 2, 3, 5, 7, 11, 13, 17, 19 }) {
try {
splitAndDrawFourSided(g, poly, partsPerSide);
break; // stop when successful
} catch (#SuppressWarnings("unused") ArithmeticException ignored) {
continue; // try next number of parts
}
}
Result
If we remove the rounding check, that code will of course always just split by 2 parts per side, i.e. into 4 parts. This shows the effect of rounding, e.g. in this case the center row coordinates ended up a bit to the right, causing the black and red lines to not match up. Even without the red line depicting the input parallelogram, the rounding can be noticed. Anti-aliasing helps, but it can still be noticed that the vertical lines aren't 100% straight.
Just to add a surprise factor to my game, I have decided to invert the background colors randomly. When the player collects, let's say, 21 golden bacon strips the background changes. By modifying the bitmap's pixels, I have done this through the following code:
public void invert() {
int length = BackBitmap.getWidth() * BackBitmap.getHeight();
int[] array = new int[length];
BackBitmap.getPixels(array, 0, BackBitmap.getWidth(), 0, 0, BackBitmap.getWidth(), BackBitmap.getHeight());
int[] array2 = new int[length];
int a2 = 0;
for(int col = 0; col < BackBitmap.getHeight(); col++){
for (int row = 0; row < BackBitmap.getWidth();row++){
array2[a2] = BackBitmap.getPixel(row,col);
a2++;
}
}
for (int i=0;i<length;i++){
array[i] = 0xFFFFFF - array2[i];
}
BackBitmap = BackBitmap.copy(Bitmap.Config.ARGB_8888, true);
BackBitmap.setPixels(array, 0, BackBitmap.getWidth(), 0, 0, BackBitmap.getWidth(), BackBitmap.getHeight());
}
However once the colors are inverted, the game encounters major lag. To my surprise I thought this way of updating bitmap would be the most effective - memory-wise. What would be the right way to approach this error?
public void invert() {
int length = BackBitmap.getWidth() * BackBitmap.getHeight();
int[] array = new int[length];
int[] array2 = new int[length];
BackBitmap.getPixels(array2, 0, BackBitmap.getWidth(), 0, 0, BackBitmap.getWidth(), BackBitmap.getHeight());
for (int i=0;i<length;i++){
array[i] = 0xFFFFFF - array2[i];
}
BackBitmap = BackBitmap.copy(Bitmap.Config.ARGB_8888, true);
BackBitmap.setPixels(array, 0, BackBitmap.getWidth(), 0, 0, BackBitmap.getWidth(), BackBitmap.getHeight());
}
This is how I would write it. You were writing to array and then rewriting it without using it.
This may not reduce lag significantly but it may help to a degree.
I am fairly new to java programming, and I've hit a bit of a roadblock with how I should create these objects in a game I'm making.
Here's a sample of code:
public static Sprite backwardNullHelm = new Sprite(16, 0, 0, SpriteSheet.armor);
public static Sprite backwardNullHelm_1 = new Sprite(16, 1, 0, SpriteSheet.armor);
public static Sprite backwardNullHelm_2 = new Sprite(16, 2, 0, SpriteSheet.armor);
public static Sprite forwardNullHelm = new Sprite(16, 0, 1, SpriteSheet.armor);
public static Sprite forwardNullHelm_1 = new Sprite(16, 1, 1, SpriteSheet.armor);
public static Sprite forwardNullHelm_2 = new Sprite(16, 2, 1, SpriteSheet.armor);
public static Sprite rightNullHelm = new Sprite(16, 0, 2, SpriteSheet.armor);
public static Sprite rightNullHelm_1 = new Sprite(16, 1, 2, SpriteSheet.armor);
public static Sprite rightNullHelm_2 = new Sprite(16, 2, 2, SpriteSheet.armor);
public static Sprite leftNullHelm = new Sprite(16, 0, 3, SpriteSheet.armor);
public static Sprite leftNullHelm_1 = new Sprite(16, 1, 3, SpriteSheet.armor);
public static Sprite leftNullHelm_2 = new Sprite(16, 2, 3, SpriteSheet.armor);
This is how I'm declaring sprites for the character's headgear.
Here's the constructor if necessary:
public Sprite(int size, int x, int y, SpriteSheet sheet)
I'm storing them in arrays like this:
backwardHelmet[0] = Sprite.backwardNullHelm;
backwardHelmet[1] = Sprite.backwardNullHelm_1;
backwardHelmet[2] = Sprite.backwardNullHelm_2;
forwardHelmet[0] = Sprite.forwardNullHelm;
forwardHelmet[1] = Sprite.forwardNullHelm_1;
forwardHelmet[2] = Sprite.forwardNullHelm_2;
rightHelmet[0] = Sprite.rightNullHelm;
rightHelmet[1] = Sprite.rightNullHelm_1;
rightHelmet[2] = Sprite.rightNullHelm_2;
leftHelmet[0] = Sprite.leftNullHelm;
leftHelmet[1] = Sprite.leftNullHelm_1;
leftHelmet[2] = Sprite.leftNullHelm_2;
The directions refer to which direction the character is facing (a top down perspective) and the numbers(in the object name) refer to the animation state.
Is there anyway for me to be able to "label" the objects (i.e. attach a number to it somehow) so I can use a loop to place them into the arrays?
Do you mean a loop like this?
for (int i=0; i<3; i++){
backwardHelmet[i] = new Sprite(16, i, 0, SpriteSheet.armor);
forwardHelmet[i] = new Sprite(16, i, 1, SpriteSheet.armor);
rightHelmet[i] = new Sprite(16, i, 2, SpriteSheet.armor);
leftHelmet[i] = new Sprite(16, i, 3, SpriteSheet.armor);
}
You could even assign directions to integers like backward=0, forward=1, right=2, left=3and have a multidimensional array and a double for cycle:
for (int i=0; i<3; i++){
for (int j=0; j<4; j++){
helmet[i][j] = new Sprite(16, i, j, SpriteSheet.armor);
}
}
While #AndreaDusza's answer may fit your needs better, if having all of the objects in one array isn't a dealbreaker, you can do it like this:
Sprite[] sprites = new Sprite[12];
for( int i = 0 ; i!=12 ; i++ )
{
sprites[i] = new Sprite(16, i%3, i/3, SpriteSheet.armor);
}
This way:
0,1,2 positions are backwards
3,4,5 positions are forwards
6,7,8 positions are right
9,10,11 positions are left
I am attempting to iterate through a 2D array of integers to generate a tiled map using Java's Graphics2D.
int[][] mapArray = {{1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1}};
public void draw(Graphics2D g2d){
for(int y = 0; y < mapArray.length; y++){
for(int x = 0; x < mapArray[0].length; x++){
if(mapArray[x][y] == 1){
ImageIcon ic = new ImageIcon("/Textures/stone.jpg");
g2d.drawImage(ic.getImage(), x, y, null);
}
else if(mapArray[x][y] == 0){
ImageIcon ic = new ImageIcon("/Textures/water.jpg");
g2d.drawImage(ic.getImage(), x, y, null);
}
I just can't seem to wrap my head around the logic of iterating a 2D array. Ideally, each 0 would represent a water tile while each 1 would represent a stone tile. Every time I run this I get a NullPointerException.
x and y are wrong way around
public void draw(Graphics2D g2d){
for(int y = 0; y < mapArray.length; y++){
for(int x = 0; x < mapArray[y].length; x++){ //you want to use y here not 0
if(mapArray[y][x] == 1){ //first box is outer array second is inner one
ImageIcon ic = new ImageIcon("/Textures/stone.jpg");
g2d.drawImage(ic.getImage(), x, y, null);
} else if(mapArray[y][x] == 0){
ImageIcon ic = new ImageIcon("/Textures/water.jpg");
g2d.drawImage(ic.getImage(), x, y, null);
}
}
}
}
I could see potentially two big issues in your code, in your code "y" represents rows and "x" represents columns but in your if statement you are picking [column][row] and while having a dry run you are probabily counting [row][column] and secondly you are always counting columns that are present in first row. if your data structure is always nXn in such case it will work but in any other case you would have different results and you might encounter ArrayIndexOutofBound exception.
I am trying to fill a rectangle of pixels, but I always get Arrayindexoutofbounds at the below line:
targetwr.setPixels(i, j, 3, 3, pixel);
Here is my code:
WritableRaster sourcewr = source.getRaster();
BufferedImage bi = new BufferedImage(source.getWidth(),
source.getHeight(), BufferedImage.TYPE_INT_ARGB);
WritableRaster targetwr = bi.getRaster();
for (int i = 0; i < sourcewr.getWidth() - rate; i += rate) {
for (int j = 0; j < sourcewr.getHeight() - rate; j += rate) {
int[] pixel = null;
pixel = sourcewr.getPixel(i, j, pixel);
System.out.println(i + " " + j);
targetwr.setPixels(i, j, 3, 3, pixel);
}
}
Pretty straightforward. The sourcewr raster is larger than the targetwr raster. You are iterating over the length and height of the sourcewr and never check to see if the coordinates are in-bounds for the targetwr.
You can check to see if i and j are within bounds or ensure that the rasters are the same size before the nested for loops. e.g.,
if(i < targetwr.getWidth() && j < targetwr.getHeight()) {
targetwr.setPixels(i, j, 3, 3, pixel);
}
This is obviously also affected by the variable rate, whatever that is. It's not defined in your code snippet.