I am loading my level for a game through xml.
I have a loop that test the "name" and adds the sprite accordingly.
I have a map that has tiles that are 80by80 width and height. The maps rows and columns are 6x10.
I am trying to find a way to keep track of which row and column the level loader is on while it is loading the tiles, because i want to do specific things with the coordinates.
I have thought of using a 2d array for this but i am not sure how i would go about doing this in this situation.
Could anyone help me out with this?
EDIT:
Here is what i have tried.
Creating a row and column array
int row[] = new int[6];
int col[] = new int[10];
Now here is where i am stuck, im not sure how i can tell the code when to switch and use a different row. For example..
if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_unwalkable)) {
tile = new Tile(x, y, this.tUnwalkable_tile,
activity.getVertexBufferObjectManager());
tileList.add(tile);
tile.setTag(1);
/*
* Body groundBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld,
* tile, BodyType.StaticBody, wallFixtureDef);
*/
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
Log.e("Tile", "Unwalkable_Tile");
return;
} else if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_Blue_Tile)) {
tile = new Tile(x, y, this.blue,
activity.getVertexBufferObjectManager());
tile.setTag(0);
this.tileList.add(tile);
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
return;
} else if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_Red_Tile)) {
tile = new Tile(x, y, this.red, activity.getVertexBufferObjectManager());
tileList.add(tile);
tile.setTag(0);
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
return;
} else if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_Pink_Tile)) {
tile = new Tile(x, y, this.pink,
activity.getVertexBufferObjectManager());
tileList.add(tile);
tile.setTag(0);
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
return;
} else if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_Yello_Tile)) {
tile = new Tile(x, y, this.yellow,
activity.getVertexBufferObjectManager());
tileList.add(tile);
tile.setTag(0);
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
return;
}
How do i tell it to stay row[1] until the col[10] is reached?
Then switch to row[2] and stay there until col[10] is reached again?
From a design standpoint, your level loader should just be loading the level. Whatever magical transform you want to do on top of that can and most likely should be handled separately.
So just have your level loader create a 2d array of... whatever it's reading. Are you reading a flat set of tile elements? Then count the number of elements read. At any given point, your offset is:
x = count % 10;
y = count / 6;
If you have each row in an encapsulating element, count the rows, and the columns. Same idea.
Now you've got a 2d array (or some object encapsulating it). And you can do whatever transformations you want on it. If you want this in terms of screen space, instead multiply each count by 80.
Edit: from the edit above, it looks like you're declaring separate row and column arrays, which you probably don't want to do. It would more logically be something like:
int[][] tiles = new int[6][];
for (int i = 0; i < 6; i++) {
tiles[i] = new int[10];
}
Then, in your loader, define a counter somewhere (once).
int counter = 0;
You'll switch rows when:
counter > 0 && (counter++) % 10 == 0
But with a 2d array, you can really just think of it as having coordinates, as I mentioned above:
x = counter % 10;
y = counter / 6;
And in the end, you have one tiles[][] variable that holds all the tile data. So you can say:
tiles[x][y] = <whatever data you need to store>
And remember to increment the counter, once you're done.
Related
Can someone explain this code in detail, I don't understand what the multiplication in q.offer(x*m + y) does and what the while loop is doing. This is the requirements for the program:
Starting from a given location on the grid, experiment explores the grid, expanding and labeling all of the cells in a single colony originating from the starting location. Taking as input a grid, the coordinates of a starting location, and a label, experiment will either label that location and all its neighbors or do nothing, depending on the presence or absence of a cell at the given location, respectively; either way, experiment is required to return the size of the labeled colony.
(c) The program is responsible for ensuring that experiment is called start- ing at every location on the grid storing a 1. The reason is that experiment locates only a single colony.
For example, using the first grid above and calling experiment for the first time on the location at the top row and forth column will modify the grid only at the locations labeled A, leaving all the other locations intact.
Once every grid location storing a 1 has been colonized, the program freezes the grid by replacing the 0s on the grid with s (dashes) .
(d) The program is responsible for creating an initial grid of random number of rows and columns in the range [5-20], and for filling the grid randomly with 0s and 1s.
(e) The program is responsible for generating the labels for experiment to use during exploration. Use the alphabet letters A · · · Z and a · · · z as labels (in that order).
public static Map<Character, Integer> experiment(int n, int m, int x, int y, char[][] matrix, int[][] mark, char colony) {
Queue<Integer> q = new LinkedList<Integer>();
q.offer(x*m + y);
mark[x][y] = 1;
matrix[x][y] = colony;
while(!q.isEmpty()) {
int front = q.peek(); q.remove();
int x1 = front / m, y1 = front % m;
if(x1 != 0)
if(mark[x1-1][y1] == 0 && matrix[x1-1][y1] == '1') {
matrix[x1-1][y1] = colony;
mark[x1-1][y1] = 1;
q.offer((x1-1) * m + y1);
}
I just don't understand this part of code. Can someone please explain it.
one possible explanation could be that
x and y are coordinates of grid,
if you loop over x and y as below
for( int x = 0 ; x < width; x++ ){
for( int y = 0 ; y < height; y++ ){
index_of_one_dimensional_array = x*m+y;//where m = width(i.e number if columns in each row)
}
}
seems like the q.offer() functions somehow uses this concept to set a value depending on value of index_of_one_dimensional_array given by x*m+y;
and loop is used to make sure every cell in the grid is processed which happens when the queue is empty
I am trying to finish my code for an assignment I have, but I'm stuck on the last component. I need to create "stars" (small yellow square objects) in the "sky"... a grid of 5 rows of 10 stars. I am in a beginner java class, and I am supposed to being using methods such as star.moveHorizontal() or star.moveVertical(). All of the relevant posts I've searched for have been too complex or out of my comprehension.
I think that I would need to create an array? We haven't even covered that in class... And then have each "star" be x distance (the first star) + 30 units to the right. Then t continue that trend until there are 10 stars in a row. And then get four more rows of 10 stars.
Here is the code I've create for just one star (in the upper left of my window):
Square s1 = new Square();
s1.makeVisible();
s1.changeColor("yellow");
s1.changeSize(5);
s1.moveVertical(-100);
s1.moveHorizontal(-270);
Then I tried to create an array for a square class... I honestly have no idea if that's even legal.
Square[] starArray = new Square[10];
for ( int i=0; i<starArray.length; i++) {
starArray[i] = new Square();
But then I don't understand how I can call each star and make them appear... Please help. I feel so out of my depth. I've tried to research this and try new things for over 2.5 hours now. I will answer any questions you have to the best of my ability. Thank you
If you can make a single star appear and haven't learned about arrays yet, I don't think that is the answer your teacher is looking for. The point of an array is to be a container so you can reference the objects again. If you don't need to go back to the stars in the future, just create them and set their values in a loop.
// Set defaults for spacing and start positions
int horizontalStartPosition = 10;
int horizontalSpacing = 30;
int verticalStartPosition = 10;
int verticalSpacing = 30;
// Outer loop creates the 4 rows
for (int i = 0; i < 4; i++) {
// Inner loop creates each row
for (int j = 0; j < 10; j++) {
// Create the next star in the row
Square s = new Square();
s.makeVisible();
s.changeColor("yellow");
s.changeSize(5);
// Move the star to the correct vertical position for the current row
s.moveVertical(verticalStartPosition + i * verticalSpacing);
// Move the star to the correct horizontal spacing for the next star
s.moveHorizontal(horizontalStartPosition + j * horizontalSpacing);
}
}
You're on the right track. You can use a 2D array with 5 rows and 10 columns. Try something like this:
int numColumns = 10; //the number of columns in the array
int numRows = 5; // the number of rows in the array
Square[][] starArray = new Square[numRows][numColumns]; // the array itself
final int DIST_X = 10; //the distance between columns (use final because this value should not change)
final int DIST_Y = 10; // the distance between rows (use final because this value should not change)
int y = 0; // the initial row's vertical displacement
for ( int i=0; i<numRows; i++) {
int x = 0; // the initial columns horizontal displacement
for ( int j=0; j<numColumns; j++) {
starArray[i][j] = new Square(); //define the square
starArray[i][j].moveHorizontal(x); // move it x units horizontally
starArray[i][j].moveVertical(y); // move it y units vertically
starArray[i][j].makeVisible(); //show the square
x += DIST_X; //update your horizontal displacement so the next column shows up in the correct position
}
y += DIST_Y; //update your vertical displacement so the next row shows up in the correct position
}
Based on what I understand, you would want to call a method which would basically place a star in the grid for you.
I am not fully sure of what you mean, but here is what I can offer you:
You'll want to create a method for placing a star.
private static int X_SPACING = 30;
private static int Y_SPACING = 20;
public Square placeStar(int x, int y){
// This is the same code that you had before.
Square sq = new Square();
sq.changeColor("yellow");
sq.changeSize(5);
sq.moveVertical(-y); // Where Y is the distance from the TOP LEFT.
sq.moveHorizontal(-x);
return sq;
}
public ArrayList<Square> makeRow(int columnsAmount, int y, int startX){
ArrayList<Square> squares = new ArrayList<>();
for(int i = 0; i < columnsAmount; i++)
squares.add(placeStar(startX + (X_SPACING * i), y));
return squares;
}
public ArrayList<Square> makeGrid(int rowsAmount, int columnsAmount){
ArrayList<Square> rslt = new ArrayList<>();
for(int i = 0; i < rowsAmount; i++)
rslt.addAll(makeRow(columnsAmount, (i * Y_SPACING), 0);
return rslt;
}
Basically, calling "makeRow" should create a row of [rowsAmount] stars, which are all separated by [X_SPACING] pixels.
Then, makeGrid will call makeRow multiple times adjusting [y], and this will make you a grid. Feel free to adjust any value in the code.
EDIT: I've added a makeGrid function, and changed a few variables in the makeRow as I mistyped them. I made the functions return an ArrayList, but you shouldn't need them, only if your teachers later ask to modify them later, or something.
I hope this helps, don't hesitate to ask more questions.
Sneling.
I'm creating a voxel engine in Java using LWJGL just for practice, but I'm getting stuck on the chunk management system. More specifically, I'm trying to convert a Chunk, which is just a 3D array of integers for the block id, into an Octree for optimal rendering.
So far, I have the system working, but it's horribly inefficient.
Here's a screenshot of a 16*16*16 chunk with all positions below y=8 set to 1 (the red blocks)
https://raw.githubusercontent.com/ninthworld/Octree/master/screenshot0.png
I added a debugger to the OctNode generator code to find out how many times it needed to access the chunk array, and it came back with 8392704.
It accessed the chunk array over 8 million times just to generate 8 children nodes.
When I set the chunk array to only have blocks below y=4, the program has a blackscreen for almost 30 seconds, and the debugger returns 1623199744 array accesses.
Over 1.6 billion array calls just to generate 68 children nodes.
I obviously need to reduce the number of array calls, that much is certain, but I'm not sure how I would go about doing that. Here's the github page for the project if you'd like to see the entire source code.
Here are the important parts of my code:
Main.java
// Initialize Octree Object
// This is just an extended OctNode object
octree = new Octree(chunk);
octree.generate(lookup);
OctNode.java
public void generate(){
int value = -1;
// Loop through an area an area of width*width*width
for(int x=0; x<width; x++){
for(int y=0; y<width; y++){
for(int z=0; z<width; z++){
// Get the value from the master array based on the node's
// offset + the forloop'd area
int store = array[x+(int)offset.x][y+(int)offset.y][z+(int)offset.z];
// Basically sets the value variable to the value at
// 0, 0, 0 with respect to the offset
if(value < 0)
value = store;
// Then check if the current position's value is the
// same as the first one found (int value), if it's not,
// then this node needs to be subdivided
if(store != value){
// Create 8 children for this node
children = new OctNode[8];
// And for each of the children...
for(int i=0; i<children.length; i++){
// Set their offset equal to this node's offset +
// this node's width/2 all with respect to it's
// individual quadrant (which is related to i)
Vector3f offS = new Vector3f(offset.x + (width/2f)*(i%2), offset.y + (width/2f)*((int)Math.floor(i/2f)%2), offset.z + (width/2f)*((int)Math.floor(i/4f)%2));
// Initialize the new child node
children[i] = new OctNode(array, (int)(width/2f), offS);
// And now do the same thing (recursion), but
// for a smaller area
children[i].generate();
}
}
}
}
}
// This is only called if the node is completely made of one value
if(children == null){
data = value;
}
}
That's the best I can explain it unfortunately. If you could point out an easier, faster way to do the same thing that would be amazing.
You are partitioning the tree too frequently. If you have a 16x16x16 array with all different values, you are going to recurse at every cell except the first, so you will call generate (16x16x16-1) times at the top level, rather than just once; the value of the children array will be overwritten many times over; of course, you will repeat the doing of unnecessary work at the next level down etc.
You should move the decision to subdivide the current octree node outside the nested for loops. For example:
public void generate(){
// Assuming that width >= 1.
int minValue = Integer.MAX_VALUE;
int maxValue = Integer.MIN_VALUE;
// Loop through an area an area of width*width*width
// looking for min and max values in that area.
for(int x=0; x<width; x++){
for(int y=0; y<width; y++){
for(int z=0; z<width; z++){
int store = array[x+(int)offset.x][y+(int)offset.y][z+(int)offset.z];
minValue = Math.min(minValue, store);
maxValue = Math.max(maxValue, store);
}
}
}
if (minValue != maxValue) {
// Subdivide if the min and maxValues are different,
// as above.
children = new OctNode[8];
// etc.
} else {
data = minValue;
}
}
So, what I'm trying to do is run through a picture that is 1024x768 (Or, popMap.getWidth x popMap.getHeight), grab the blue color of it, compare it to the highest blue so far, and if it's more, that blue becomes the new 'newBlue'. Basically, find the highest blue value in an image, closest to 255 blue.
Also, I'm attempting to store the blue value of the entire thing into an array popMapArray, which is a 2d array with 3 columns, storing [blueValue][x][y]. Which I will then sort, to get a list from high to low of the bluest values.
My problem, is that with the code below, it's only storing into the array when column=767.
I get 1024 [blue,row,767], and then the rest are all [0,0,0]
Any clue why? Java, by the way.
for (int row = 0; row < popMap.getWidth(); row++)
{
for (int column = 0; column < popMap.getHeight(); column++)
{
System.out.println(column);
//Find a Pixel
int c = popMap.getRGB(row, column);
int red = (c & 0x00ff0000) >> 16;
//int green = (c & 0x0000ff00) >> 8;
//int blue = c & 0x000000ff;
// and the Java Color is ...
Color color = new Color(red);
int newBlue = color.getBlue();
int oldBlue = lastColor.getBlue();
switch(popArrayRow)
{
case 0:
{
arrayVar = newBlue;
popArrayRow = 1;
break;
}
case 1:
{
arrayVar = row;
popArrayRow = 2;
break;
}
case 2:
{
arrayVar = column;
popArrayRow = 0;
break;
}
}
popArray[row][popArrayColumn] = arrayVar;
//System.out.println(popArray[row][popArrayColumn]);
switch(popArrayColumn)
{
case 0:
{
popArrayColumn = 1;
break;
}
case 1:
{
popArrayColumn = 2;
break;
}
case 2:
{
popArrayColumn = 0;
break;
}
}
if(newBlue > oldBlue)
{
startX = row;
startY = column;
//System.out.print(row);
//System.out.print(",");
//System.out.println(column);
System.out.print("The oldBlue is ");
System.out.println(oldBlue);
lastColor = color;
}
}
}
int red = (c & 0x00ff0000) >> 16;
//int green = (c & 0x0000ff00) >> 8;
//int blue = c & 0x000000ff;
// and the Java Color is ...
Color color = new Color(red);
int newBlue = color.getBlue();
Do you mean "Color color = new Color(c)"? Your newBlue value will always be 0...
Also, what precisely are you trying to do with the popArray construction? Having your state variables adjust themselves once per pixel is probably not going to accomplish what you want... It sounds like you want a SortedMap<int,Point>, keyed on the blueValue, whose value is the x,y coordinate of the points (stored either as an array or a Point object). Then you'd have your data structure, ordered by blue value, and you can read your points off directly.
Best of luck!
You didn't show the declaration go popArray (as well as some other variables which I'm assuming are ints that are initialized to 0). You describe it as "a 2d array with 3 columns". I'm guessing you've declared it as int[1024][3], so it has one row per row in popMap, then your 3 "columns" which are meant to store the blue value, the original x coordinate, and the original y coordinate.
So first of all it is unclear how you expect to store one entry in this array for each pixel in the original image. But maybe my guess about how you declared it is wrong.
In any case, each time through the inner loop you essentially want to set
popArray[currentPixel] = {blueValue, origX, origY}
but instead you are assigning only one of the three value each time through the loop. So you are doing something like
popArray[0][0] = blueValue //first iteration; blueValue from row 0 col 0
popArray[0][1] = 0 //second iteration; row from row 0 col 1
popArray[0][2] = 2 //third iteration; column from row 0 col 2
So hopefully you can already see that something is wrong, since you are populating "columns" that are supposed to go together with values from different iterations of the loop. Even worse, you then start overwriting those values on the next iteration of the inner loop (which will iterate a total of 768 times before row increments):
popArray[0][0] = blueValue // fourth iteration; blueValue from row 0 col 4; overwrite value assigned on first iteration
etc...
Rather than using 3 array "columns" with different meanings to hold these data elements, it would be wise to make a class that holds the three values and makes clear what's what. popArray would contain this object type. Furthermore, I would make it a List instead of an array since it is more flexible and you can simply call Collections.sort() on it at the end; or #jsegal has a good suggestion of using a data structure that sorts as the items are inserted. Which one is better might depend on what you want to do with them later.
I'm trying to create a pyramid of circles to my game, looking similar to this :
alt text http://img266.imageshack.us/img266/3094/lab1213c.jpg
But I can't make it print properly. Constantly I'm getting really strange spirals but nothing close to this. Can anyone give me some tip on proper formula ? My window is 600x600, base of pyramid is 8 .
fields = new Field[BASE*(BASE/2)+4];
int line_count = BASE;
int line_tmp = line_count;
for(int i=0; i< fields.length; i++){
for( int j=line_tmp; j <= line_count; j++){
fields[i] = new Field(0, (150+(line_tmp*5)),(600+line_tmp*5));
}
line_count--;
line_tmp = line_count;
}
The mistakes I see are:
Incorrect array size formula.
Including line_tmp (which seems to be your column counter) in your y expression.
Having two variables, line_count and line_temp that are always equal.
Having your outer loop count by node rather than counting by row.
Having generally meaningless variable names and magic numbers strewn about.
// I use java.util.ArrayList because using its add(..) method is convenient here.
// The proper forumula for anticipated number of nodes is: base×(base+1)÷2
final List<Field> fields = new ArrayList<Field>(BASE*(BASE+1)/2);
// I use a java.awt.Point to store the (x,y) value of the first node of the row.
// This clarifies the meaning, rather than using ints or long inline expressions.
final Point rowStart = new Point(PANEL_WIDTH/2, DIAMETER);
// The number of rows equals the number of nodes on the final row.
for (int row = 1; row <= BASE; row++) {
// The nth row has n nodes.
for (int circle = 0; circle < row; circle++) {
// Each row starts at rowStart and each subsequent circle is offset to
// the right by two times the circle diameter.
fields.add(new Field(0, rowStart.x + circle*DIAMETER*2, rowStart.y));
}
// Each subsequent row starts a little down and to the left of the previous.
rowStart.x -= DIAMETER;
rowStart.y += DIAMETER;
}
Remember to only use this as reference for fixing your own code if this is homework.