[SOLVED] Looping through an images pixels differently

I need to load an image into a level-object. You can see this structure at the end of the OP. It’s basicly a 2D array, of nulls and bricks.
Each black pixel is one brick, each white is a null.

My world, however, starts from the buttom left. So, I need to loop through it in that manner. Or, do something else.
For now, I’ve been looping it so that the whole level appeared upside down.

My current loop:


for (int x = 0; x < length; x++) {
			for (int y = 0; y < 20; y++) {
				Color color = img.getColor(x, y);
				if (color.getRedByte() == 0 && color.getGreenByte() == 0 && color.getBlueByte() == 0) {
					returnValue.setBrick(x, y, new Brick());
				}
			}
		}

What’s odd though, is that my level is rendered correctly, even though the data structure is messed up.


// World-rendering
		int startingX = cameraX/10;
		g.setColor(Color.green);
		for (int x = startingX; x < 50+startingX; x++) {
			for(int y = 0; y < 20; y++) {
				if (level.getBrick(x, y) != null) {
					int k = x * 10;
					int startDrawX = k - cameraX;
					int startDrawY = y * 10;
					g.drawRect(startDrawX, startDrawY, 10, 10);
				}
			}
		}

Finally, the level class, if you want to see how it works.


package com.javadaemon.skrollr.model;

import java.util.ArrayList;

/**
 * A static level.
 * 
 * @author Mads Horndrup
 *
 */
public class StaticWorld {
	
	private ArrayList<Brick[]> worldColumns;
	
	public StaticWorld(int length) {
		worldColumns = new ArrayList<Brick[]>();
		for (int i = 0; i < length; i++) {
			worldColumns.add(new Brick[20]);
		}
	}
	
	public ArrayList<Brick[]> getWorldColumns() {
		return worldColumns;
	}
	
	public Brick getBrick(int x, int y) {
		if (x < 0 || y < 0 || y >= 20) {
			return null;
		}
		else if (x >= worldColumns.size()) {
			return null;
		} else {
			Brick brick = worldColumns.get(x)[y];
			return brick;
		}
	}
	
	public void setBrick(int x, int y, Brick brick) {
		worldColumns.get(x)[y] = brick;
	}
	
	public boolean isInsideBrick(double worldX, double worldY) {
		int x = (int)worldX /10;
		int y = (int) worldY /10;
		System.out.println("method: " + x + " " + y);
		if (getBrick(x, y) == null) {
			return false;
		} else {
			return true;
		}
	}
	
	public double checkBrickTop(double worldX, double worldY, double step) {
		if (isInsideBrick(worldX, worldY)) {
			double shouldBeY = worldY/10 +1 ;
			double diff = shouldBeY - worldY;
			return step - diff;
		} else {
			return step;
		}
	}
}

Thing is, when I use methods like isInsideBrick(0, 0), it grabs the pixel from the top-left corner of the picture, and reports that there is no pixel there. However, by specifying (0, 0) I mean the worlds bottom-left corner, where there is in fact a brick.

So… I believe this is a simple error, of looping through the image when loading, the correct way.

I can elaborate, please ask.

Just flip the y-coordinate?
imageY = imageHeight - 1 - worldY
so if you want the bottom left coordinate, you send in worldY = 0. If your map is 20 tiles high, this will become 20 - 1 - 0 = 19, which is the last (bottom) line of your pixels in your image.

That work’s beautifully.

 for (int x = 0; x < length; x++) {
			for (int y = 0; y < 20; y++) {
				Color color = img.getColor(x, y);
				if (color.getRedByte() == 0 && color.getGreenByte() == 0 && color.getBlueByte() == 0) {
					int newY = 20 - 1 -y;
					returnValue.setBrick(x, newY, new Brick());
					//System.out.println(x +" "+y+" ");
				}
			}
		}

However, now my world is rendered upside down:


// World-rendering
		int startingX = cameraX/10;
		g.setColor(Color.green);
		for (int x = startingX; x < 50+startingX; x++) {
			for(int y = 0; y < 20; y++) {
				if (level.getBrick(x, y) != null) {
					int k = x * 10;
					int startDrawX = k - cameraX;
					int startDrawY = (y * 10);
					g.drawRect(startDrawX, startDrawY, 10, 10);
				}
			}
		}

Any ideas? My worlds 0, 0 is at the lower-left, so it’s kind of the same problem.

Flip it back again? xD

Doesn’t work, quite the same way… Atleast, I couldn’t. :smiley:
Look at the loop:


// World-rendering
		int startingX = cameraX/10;
		g.setColor(Color.green);
		for (int x = startingX; x < 50+startingX; x++) {
			for(int y = 0; y < 20; y++) {
				if (level.getBrick(x, y) != null) {
					int k = x * 10;
					int startDrawX = k - cameraX;
					int startDrawY = (y * 10);
					g.drawRect(startDrawX, startDrawY, 10, 10);
				}
			}
		}

This loops through the map as it should, but the draw coordinates are off… It draws upside down :smiley:

So you need to access the map in two different ways, right? You need it flipped up side down (for checking collisions) and you need it as normal when rendering it. You really shouldn’t have both a flipped version and an unflipped version in memory, so you’ll just have to decide to keep it either flipped or unflipped in memory, and then when you get need to find a brick correct the y-coordinate if you need it flipped compared to how you store it.

Let’s say that you store the map unflipped (you use your original map loading code to create Bricks). Rendering should work fine with just level.getBrick(x, y);. However in all your collision detection code (isInsideBrick(x, y), e.t.c) you flip the y-coordinate (int newY = height - 1 - y;). You should build this into the isInsideBrick() and the other collision methods of course. The level will be rendered correctly, and the collision will be handled correctly. Success!

Now, think about the reason you got into this problem in the first place. Why are you using a coordinate system that is different from the screen’s top left coordinate system? You’re making it a lot harder for yourself by doing it like this.

No, I only have it once. The problem is, in how the rendering loop works. I solved it, though, by altering the way it loops/draws :slight_smile: