I am creating a simple Mario style platformer game in java swing. With the help of Youtube I was able to implement a world map using a .txt file and displaying tiles according to a number that represents a tile type:
package tiles;
import main.GamePanel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Objects;
public class TileManager {
GamePanel gp;
public Tile[] tile;
public int mapTileNum[][];
public TileManager(GamePanel gp) {
this.gp = gp;
tile = new Tile[10];
mapTileNum = new int[gp.maxWorldCol][gp.maxWorldRow];
getTileImage();
loadMap("/maps/world1.txt");
}
public void getTileImage() {
try {
tile[0] = new Tile();
tile[0].image = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/tiles/sky.png")));
tile[1] = new Tile();
tile[1].image = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/tiles/ground.png")));
tile[1].collision = true;
tile[2] = new Tile();
tile[2].image = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/tiles/stone.png")));
tile[2].collision = true;
tile[3] = new Tile();
tile[3].image = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/tiles/underground.png")));
tile[3].collision = true;
tile[4] = new Tile();
tile[4].image = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/tiles/black.png")));
} catch(IOException e) {
e.printStackTrace();
}
}
public void loadMap(String filePath) {
try {
InputStream is = getClass().getResourceAsStream(filePath);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
int col = 0;
int row = 0;
while(col < gp.maxWorldCol && row < gp.maxWorldRow) {
String line = br.readLine();
while(col < gp.maxWorldCol) {
String numbers[] = line.split(" ");
int num = Integer.parseInt(numbers[col]);
mapTileNum[col][row] = num;
col++;
}
if(col == gp.maxWorldCol) {
col = 0;
row++;
}
}
br.close();
} catch(Exception e) {
}
}
public void draw(Graphics2D g2) {
int worldCol = 0;
int worldRow = 0;
while(worldCol < gp.maxWorldCol && worldRow < gp.maxWorldRow) {
int tileNum = mapTileNum[worldCol][worldRow];
int worldX = worldCol * gp.tileSize;
int worldY = worldRow * gp.tileSize;
int screenX = worldX - gp.player.worldX + gp.player.screenX;
int screenY = worldY - gp.player.worldY + gp.player.screenY;
if(worldX + gp.tileSize > gp.player.worldX - gp.player.screenX &&
worldX - gp.tileSize < gp.player.worldX + gp.player.screenX &&
worldY + gp.tileSize > gp.player.worldY - gp.player.screenY &&
worldY - gp.tileSize < gp.player.worldY + gp.player.screenY) {
g2.drawImage(tile[tileNum].image,screenX,screenY,gp.tileSize,gp.tileSize,null);
}
worldCol++;
if(worldCol == gp.maxWorldCol) {
worldCol = 0;
worldRow++;
}
}
}
}
I was also able to add collision detection and player movement, however I am not sure how to add gravity. These are my collision and player classes:
package main;
import entity.Entity;
public class CollisionChecker {
GamePanel gp;
public CollisionChecker(GamePanel gp) {
this.gp = gp;
}
public void checkTile(Entity entity) {
int entityLeftWorldX = entity.worldX + entity.solidArea.x;
int entityRightWorldX = entity.worldX + entity.solidArea.x + entity.solidArea.width;
int entityTopWorldY = entity.worldY + entity.solidArea.y;
int entityBottomWorldY = entity.worldY + entity.solidArea.y + entity.solidArea.height;
int entityLeftCol = entityLeftWorldX/gp.tileSize;
int entityRightCol = entityRightWorldX/gp.tileSize;
int entityTopRow = entityTopWorldY/gp.tileSize;
int entityBottomRow = entityBottomWorldY/gp.tileSize;
int tileNum1, tileNum2;
switch(entity.direction) {
case "jump":
entityTopRow = (entityTopWorldY - entity.speed)/gp.tileSize;
tileNum1 = gp.tileM.mapTileNum[entityLeftCol][entityTopRow];
tileNum2 = gp.tileM.mapTileNum[entityRightCol][entityTopRow];
if(gp.tileM.tile[tileNum1].collision || gp.tileM.tile[tileNum2].collision) {
entity.collisionOn = true;
}
break;
case "down":
entityBottomRow = (entityBottomWorldY + entity.speed)/gp.tileSize;
tileNum1 = gp.tileM.mapTileNum[entityLeftCol][entityBottomRow];
tileNum2 = gp.tileM.mapTileNum[entityRightCol][entityBottomRow];
if(gp.tileM.tile[tileNum1].collision || gp.tileM.tile[tileNum2].collision) {
entity.collisionOn = true;
}
break;
case "left":
entityLeftCol = (entityLeftWorldX - entity.speed)/gp.tileSize;
tileNum1 = gp.tileM.mapTileNum[entityLeftCol][entityTopRow];
tileNum2 = gp.tileM.mapTileNum[entityLeftCol][entityBottomRow];
if(gp.tileM.tile[tileNum1].collision || gp.tileM.tile[tileNum2].collision) {
entity.collisionOn = true;
}
break;
case "right":
entityRightCol = (entityRightWorldX + entity.speed)/gp.tileSize;
tileNum1 = gp.tileM.mapTileNum[entityRightCol][entityTopRow];
tileNum2 = gp.tileM.mapTileNum[entityRightCol][entityBottomRow];
if(gp.tileM.tile[tileNum1].collision || gp.tileM.tile[tileNum2].collision) {
entity.collisionOn = true;
}
break;
}
}
}
package entity;
import main.GamePanel;
import main.KeyHandler;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Objects;
public class Player extends Entity {
GamePanel gp;
KeyHandler keyH;
public final int screenX;
public final int screenY;
public Player(GamePanel gp, KeyHandler keyH) {
this.gp = gp;
this.keyH = keyH;
screenX = gp.screenWidth/2 - (gp.tileSize/2);
screenY = gp.screenHeight/2 - (gp.tileSize/2);
solidArea = new Rectangle(0,0,159,159);
setDefaultValues();
getPlayerImage();
}
public void setDefaultValues() {
worldX = gp.tileSize * 8;
worldY = gp.tileSize * 18;
speed = 20;
direction = "right";
}
public void getPlayerImage() {
try {
leftStill = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/player/leftStill.png")));
rightStill = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/player/rightStill.png")));
leftJump = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/player/leftJump.png")));
rightJump = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/player/rightJump.png")));
left1 = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/player/left1.png")));
left2 = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/player/left2.png")));
right1 = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/player/right1.png")));
right2 = ImageIO.read(Objects.requireNonNull(getClass().getResourceAsStream("/player/right2.png")));
} catch(IOException e) {
e.printStackTrace();
}
}
public void update() {
if(keyH.spacePressed || keyH.leftPressed || keyH.rightPressed || keyH.downPressed) {
if(keyH.spacePressed) {
direction = "jump";
} else if(keyH.leftPressed) {
direction = "left";
} else if(keyH.rightPressed) {
direction = "right";
} else if(keyH.downPressed) {
direction = "down";
}
//CHECK TILE COLLISION
collisionOn = false;
gp.cChecker.checkTile(this);
//IF COLLISION IS FALSE, PLAYER CAN MOVE
if(!collisionOn) {
switch (direction) {
case "jump" -> worldY -= speed;
case "left" -> worldX -= speed;
case "right" -> worldX += speed;
case "down" -> worldY += speed;
}
}
spriteCounter++;
int spriteRate = 8;
if(spriteCounter > spriteRate) {
if(spriteNum == 1) {
spriteNum = 2;
} else if(spriteNum == 2) {
spriteNum = 1;
}
spriteCounter = 0;
}
}
}
public void draw(Graphics2D g2) {
BufferedImage image = null;
switch(direction) {
/*case "jump":
if(spriteNum == 1) {
image = up1;
}
if(spriteNum == 2) {
image = up2;
}
break;*/
case "left":
if(spriteNum == 1) {
image = left1;
}
if(spriteNum == 2) {
image = left2;
}
break;
case "right":
if(spriteNum == 1) {
image = right1;
}
if(spriteNum == 2) {
image = right2;
}
break;
}
g2.drawImage(image, screenX, screenY, gp.tileSize, gp.tileSize, null);
}
}
In an unrelated problem, the player can also move off the world map. Any help is appreciated.