views:

1003

answers:

3

Not sure how to approach this problem.

Basically, I want a Pixel -> Tile representation of a 400x400 window. Each coordinate on the screen, e.g 120x300 should be part of a tile. My smallest sprite is 4 pixels, so we can say that 1 tile = 4 pixels. The player and enemy sprites are all 20 x 20, so each player/bad guy will occupy 5 tiles.

Then I want to use this Map class to:

  • Retrieve the x/y coordinates of a player/monster sprite by suppling the index/id of the tile.

  • Knowing where the boundaries are, so it doesn't move the sprite beyond 400x400, thus hiding it.

  • Collision detection, knowing whether a tile is vacant or not.

How can this be done? Talking specifically about the x,y->tile or tile index->x,y conversion (for drawing the sprites appropriately) here.

+1  A: 

Short answer: Multiplication and Modulo operations.

But if this is stumping you, I'd suggest you do a serious math refresher before trying to write a game.

Also your statement

My smallest sprite is 4 pixels, so we can say that 1 tile = 4 pixels. The player and enemy sprites are all 20 x 20, so each player/bad guy will occupy 5 tiles.

doesn't work out for any reasonable geometry. If by "1 tile = 4 pixels" you mean that the tiles are 2x2, then a player takes 100, not five. If you mean they are 4x4 then players take 25, which still isn't 5.

MarkusQ
Tile=pixels / 4. Small sprite(4x4)= 4/4 = 1 tile. Large sprite (20 x 20) = 20 / 4=5. No? What is stumping me is how the x,y coords will be retrieved based on a tile index, such as 5. Can you show me an example perhaps?
Click Upvote
No. 20 pixels x 20 pixels = 400 square pixels. A 4x4 tile is 16 square pixels. 400/16 = 25 4x4 tiles inside a 400 square pixel region.
Paul
+4  A: 

Firstly, split out the concept of a pixel, which is just concerned with representation, with a tile, which is an actual game object with constraints it places on the game.

I find a good way to disentangle things like this is to start out sketching out the rough API of what you want. Something like:

public class Board {
  public Board (int width, int height){.. }
  public boolean isOccupied(int x, int y){.. }
  public void moveTo(Point from, Point to) { .. 
    (maybe throws an exception for outofbounds )

where all internal units of the board are in tiles, not pixels. Then pixel information can be derived from the board independantly from the tile representation with a bit of internal multiplication-

  public Point getPixelPosition(int xTilePos, int yTilePos, int pixelsPerTile)..

The tiles can be internally represented as a 2d array or a single array, in which case you'd use some kind of internal representation scheme to map your array to the board squares, thus the mod arithmetic.

Steve B.
Some code for that getPixelPosition() and I'll accept your answer :)
Click Upvote
Geez ClickUpvote take a hint. Using the screen as the model is not a good design. use a memory model. color and position is an independent attribute. You can also use the memory model to store other attributes. http://www.fastgraph.com/qfrip.html as an example
jim
Without knowing the x,y attribute how can I draw the sprite on the screen to indicate that its moved from one tile to another ?!
Click Upvote
You need to supply x,y attribs when you do a drawImage
Click Upvote
start out with a 2 dimensional array that represents your area. the value in that area can represent a friendly, enemy or even a background tile. now if t[x,y]=z then blit tile z to screen pos x,y. maybe do a zoom with a 20x20 tile. same t[x,y]=z but use z20 and plot at x*20,y*20 screen.
jim
+1  A: 
/** size of a tile in pixel (for one dimension)*/
int TILE_SIZE_IN_PIXEL = 4;
/** size of a piece in tiles (for one dimension)*/
int PIECE_SIZE_IN_TILE = 5;


public int tileToPixel(int positionInTiles){
    return TILE_SIZE_IN_PIXEL * positionInTiles;
}

/** returns the tile coordinate to which the given tile coordinate belongs 

Note: tileToPixel(pixelToTile(x)) only returns x if x is the upper or left edge of a tile
*/
public int pixelToTile(int positionInPixel){
    return positionInPixel / TILE_SIZE_IN_PIXEL;
}

You'll probably want methods operating on two arguments (x and y at) as well.

For the ID->piece conversion and vice versa you have various approaches available. Which one to choose depends on the exact requirements (speed, size of game ...). So make sure that you are hiding the implementation details, so you can change them later on.

I'd start with a real easy solution:

public class Piece{
    /** x position measured in tiles */
    private int x;
    /** y position measured in tiles */
    private int y;

    /** I don't think you need this, but you asked for it. I'd pass around Piece instances instead */
    private final  Long id;

    public void getX(){
        return x;
    }
    public void getY(){
        return y;
    }

    public void getID(){
        return id;
    }

}

public class Board(){
    private Set<Long,Piece> pieces = new HashMap<Piece>(pieces);

    public Piece getPieceOnTile(int tileX, int tileY){ 
        for(Piece piece:pieces){
             if (isPieceOnTile(piece, tileX, tileY)) return piece;
        }
    }

    private boolean isPieceOnTile(piece, tileX, tileY){
        if (piece.getX() < tileX) return false;
        if (piece.getX() > tileX + PIECE_SIZE_IN_TILE) return false;

        if (piece.getY() < tileY) return false;
        if (piece.getY() > tileY + PIECE_SIZE_IN_TILE) return false;

        return true;
    }
}

Hope that gets you started. All code is writen without a compiler nearby so it will include typos and of course bugs, which may be distributed under the creative commons license.

The approach of keeping the pieces in a set should work well if there are not to many pieces. It should work better than a 2D array as long as most board area does not contain a piece. The whole thing currently assumes there are no overlapping pieces. If you need those getPieceOnTile must return a Collection of pieces. A set if order does not matter, a List if it does.

Jens Schauder
Thanks, but can you tell me how to determine the x.y coords based on the tile number? that's what I haven't been able to figure out
Click Upvote
that's what the tileToPixel method is for
Jens Schauder