First off, some of the values I'll probably reference in other bits of the code:
float viewPositionX = 0;
float viewPositionY = 0;
float shiftX = viewPositionX + Game.ScreenW/2; //Game's screen width divided by 2
float shiftY = viewPositionY + Game.ScreenH/2; //Game's screen height divided by 2
This is the top left corner of the screen, which is the actual recognized position for most things, and the shift being that value moved to the exact center of the screen, no matter what the resolution.
So one of the first things that happens in my program is pulling the map picture into buffer, and establishing a 2D array based on that its dimensions, this is of course taking place in the init section of the game loop.
BufferedImage MapImage = javax.imageio.ImageIO.read(new File("res/testmap.png"));
int width = MapImage.getWidth();
int height = MapImage.getHeight();
int[][] result = new int[height][width];
From there, I fill the 2D array up by reading the pixels from the map's image using a for loop and getRGB.
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
result[row][col] = MapImage.getRGB(col, row);
}
}
We also find the midpoint of the matrix; It's important to note that it must be evenly divisible by 2 or it will return an error.
posX = MapArray.length/2;
posY = MapArray.length/2;
That sets up the entire map array for now, in each position there is a certain color value stored as an integer that we can use later to generate different kinds of tiles depending on the number.
The next part takes place in render. It's very rough around the edges, I know, but it took a lot of effort to figure it all out and make it work as intended. The basic idea is that it establishes a starting point for the player (For now, that is simply the array/2 to find a middle of the map), then draws tiles relative to the player's position in every direction. It determines what tile to draw by pulling the value of that relational position from the map array, and running through a case statement to draw the necessary one.
An important part of this loop is the values of playertileX and playertileY, which are:
int playertileX = (int)((posX+shiftX)/Game.TileSize);
int playertileY = (int)((posY+shiftY)/Game.TileSize);
Or in other words, they're the integer of the player's position (posX+shiftX),(posY+shiftY) which starts off as the very center of the map, and is offset by the camera position, divided by the tile size; in this case, 32.
This allows me to get the value of exactly what 32x32 tile the player is standing on.
for(int X=playertileX-12; X < playertileX+12; X++){Once it has pulled the necessary value (which is as I said before, an integer representing the color value of that pixel space on the map), it runs it through a case statement to determine if it's going to need to render a Water, Stone, or Grass tile. It then draws that tile in the same relative location, but multiplied by the tile-size (32) so they're nice and evenly spaced.
for(int Y=playertileY-15; Y < playertileY+15; Y++){
Tile = MapArray[posX+X][posY+Y];
switch (Tile) {
case -14503604: mapTile1.draw(Y*Game.TileSize+viewPositionY + Game.ScreenH/2, X*Game.TileSize+viewPositionX + Game.ScreenW/2);
break;
case -3947581: mapTile2.draw(Y*Game.TileSize+viewPositionY + Game.ScreenH/2, X*Game.TileSize+viewPositionX + Game.ScreenW/2);
break;
case -12629812: mapTile3.draw(Y*Game.TileSize+viewPositionY + Game.ScreenH/2, X*Game.TileSize+viewPositionX + Game.ScreenW/2);
break;
}
}
}
Whenever the player moves, should they move out of one 32x32 tile to another, the value of playertileY and playertileY are updated and the map tiles are drawn again relative to the new location, so it saves a lot of memory in lieu of just rendering the whole map.
Right now, the only thing resembling collision detection that I have going on is a small check in the update section which basically goes
if(input.isKeyDown(input.KEY_UP)){
Char = movingUp;
viewPositionX += delta *.1f;
if (MapArray[playertileX][playertileY] == -3947581 || MapArray[playertileX][playertileY] == -12629812) {
viewPositionY -= delta *.1f;
}
}
Essentially, if the player's current tile location ever becomes an off-limits tile, for instance water or stone, then reverse their movement. It's crude, it's ugly, and probably the least efficient thing I could do, but it works right now.
For what it's worth, even being a novice project it's taken many cups of coffee and a lot of effort to get here, and I don't intend to give up on learning anytime soon. If there's something you know how to do better, feel free to enlighten me so that I can continue improving and making better code, or maybe in the off-chance someone looking into game design also stumbles onto this post, they can learn too.
That's all for now, thanks for reading!
No comments:
Post a Comment