Compare commits

...

4 Commits

Author SHA1 Message Date
7616b4daff added some sample events 2025-11-28 21:52:28 +01:00
4c50f99e67 removed warnings 2025-11-28 21:25:18 +01:00
8add9c7d7a added player life display 2025-11-28 21:22:50 +01:00
5fbf815595 added title screen 2025-11-28 20:37:45 +01:00
12 changed files with 228 additions and 29 deletions

View File

@@ -14,7 +14,7 @@
12 12 12 12 12 12 18 41 41 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 41 41 31 26 30 14 15 25 12 12 12 12 12 12 12 12 12 12 12 12 12 18 41 41 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 41 41 31 26 30 14 15 25 12 12 12 12 12 12 12
12 12 12 12 13 12 18 41 41 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 41 41 31 26 30 17 12 12 12 12 13 12 12 12 12 12 12 12 12 13 12 18 41 41 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 41 41 31 26 30 17 12 12 12 12 13 12 12 12 12
12 12 12 12 12 12 24 15 16 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 41 41 31 26 30 17 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 24 15 16 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 41 41 31 26 30 17 12 12 12 12 12 12 12 12 12
12 12 12 12 12 12 12 12 18 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 41 41 31 26 30 17 12 12 12 12 12 13 12 12 12 12 12 12 12 12 12 12 12 18 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 10 10 10 41 41 41 41 41 41 41 41 41 31 26 30 17 12 12 12 12 12 13 12 12 12
12 12 13 12 12 12 12 22 21 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 35 33 34 26 30 17 12 12 13 12 12 12 12 12 12 12 12 13 12 12 12 12 22 21 41 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 35 33 34 26 30 17 12 12 13 12 12 12 12 12 12
12 12 12 12 12 12 12 18 10 10 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 31 26 26 26 30 17 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 18 10 10 10 41 41 41 41 41 41 41 41 41 41 41 31 26 30 41 41 41 41 41 41 41 41 41 41 31 26 26 26 30 17 12 12 12 12 12 12 12 12 12
12 12 12 13 12 12 12 18 10 41 41 41 41 41 41 41 41 41 41 41 41 10 31 26 30 10 41 41 41 41 41 41 41 41 41 31 26 27 28 38 17 12 13 12 12 12 12 12 12 12 12 12 12 13 12 12 12 18 10 41 41 41 41 41 41 41 41 41 41 41 41 10 31 26 30 10 41 41 41 41 41 41 41 41 41 31 26 27 28 38 17 12 13 12 12 12 12 12 12 12

View File

@@ -1,10 +1,7 @@
package de.miaurizius.jgame2d.core; package de.miaurizius.jgame2d.core;
import de.miaurizius.jgame2d.core.enums.GameState; import de.miaurizius.jgame2d.core.enums.GameState;
import de.miaurizius.jgame2d.core.handlers.AssetSetter; import de.miaurizius.jgame2d.core.handlers.*;
import de.miaurizius.jgame2d.core.handlers.CollisionHandler;
import de.miaurizius.jgame2d.core.handlers.KeyHandler;
import de.miaurizius.jgame2d.core.handlers.Sound;
import de.miaurizius.jgame2d.entity.Entity; import de.miaurizius.jgame2d.entity.Entity;
import de.miaurizius.jgame2d.entity.Player; import de.miaurizius.jgame2d.entity.Player;
import de.miaurizius.jgame2d.object.SuperObject; import de.miaurizius.jgame2d.object.SuperObject;
@@ -43,6 +40,7 @@ public class GamePanel extends JPanel implements Runnable {
public CollisionHandler collisionH = new CollisionHandler(this); public CollisionHandler collisionH = new CollisionHandler(this);
public AssetSetter assetSetter = new AssetSetter(this); public AssetSetter assetSetter = new AssetSetter(this);
public UI ui = new UI(this); public UI ui = new UI(this);
public EventHandler eventH = new EventHandler(this);
Thread gameThread; Thread gameThread;
// ENTITY AND OBJECT // ENTITY AND OBJECT
@@ -64,8 +62,8 @@ public class GamePanel extends JPanel implements Runnable {
public void setupGame() { public void setupGame() {
assetSetter.setObject(); assetSetter.setObject();
assetSetter.setNPC(); assetSetter.setNPC();
playMusic(0); //Play main theme //playMusic(0); //Play main theme
gameState = GameState.PLAY; gameState = GameState.TITLE;
} }
public void startGameThread() { public void startGameThread() {
@@ -118,10 +116,16 @@ public class GamePanel extends JPanel implements Runnable {
Graphics2D graphics2d = (Graphics2D) graphics; Graphics2D graphics2d = (Graphics2D) graphics;
// DEBUG // DEBUG
long drawStart = 0; long drawStart;
drawStart = System.nanoTime(); drawStart = System.nanoTime();
// COMPONENTS // TITLE SCREEN
if(gameState == GameState.TITLE) {
ui.draw(graphics2d);
return;
}
// GAME
tileM.draw(graphics2d); tileM.draw(graphics2d);
for (SuperObject superObject : obj) if (superObject != null) superObject.draw(graphics2d, this); for (SuperObject superObject : obj) if (superObject != null) superObject.draw(graphics2d, this);
for(Entity npc : npc) if(npc != null) npc.draw(graphics2d); for(Entity npc : npc) if(npc != null) npc.draw(graphics2d);

View File

@@ -1,20 +1,31 @@
package de.miaurizius.jgame2d.core; package de.miaurizius.jgame2d.core;
import de.miaurizius.jgame2d.core.enums.GameState; import de.miaurizius.jgame2d.core.enums.GameState;
import de.miaurizius.jgame2d.object.HeartObj;
import de.miaurizius.jgame2d.object.SuperObject;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage;
public class UI { public class UI {
GamePanel panel; GamePanel panel;
Graphics2D graphics2d; Graphics2D graphics2d;
Font arial_40, arial_80B; Font arial_40, arial_80B;
BufferedImage heart_full, heart_half, heart_blank;
public String currentDialogue; public String currentDialogue;
public int commandNum = 0;
public UI(GamePanel panel) { public UI(GamePanel panel) {
this.panel = panel; this.panel = panel;
arial_40 = new Font("Arial", Font.PLAIN, 40); arial_40 = new Font("Arial", Font.PLAIN, 40);
arial_80B = new Font("Arial", Font.BOLD, 80); arial_80B = new Font("Arial", Font.BOLD, 80);
// CREATE HUD OBJECT
SuperObject heart = new HeartObj(panel);
heart_full = heart.image;
heart_half = heart.image2;
heart_blank = heart.image3;
} }
public void draw(Graphics2D graphics2d) { public void draw(Graphics2D graphics2d) {
@@ -25,14 +36,45 @@ public class UI {
if(panel.gameState == null) return; if(panel.gameState == null) return;
switch (panel.gameState) { switch (panel.gameState) {
case GameState.PLAY: case GameState.PLAY:
drawPlayerLife();
break; break;
case GameState.PAUSE: case GameState.PAUSE:
drawPlayerLife();
drawPauseScreen(); drawPauseScreen();
break; break;
case GameState.DIALOGUE: case GameState.DIALOGUE:
drawPlayerLife();
drawDialogueScreen(); drawDialogueScreen();
break; break;
case TITLE:
drawTitleScreen();
break;
}
}
public void drawPlayerLife() {
int x = panel.tileSize / 2;
int y = panel.tileSize / 2;
int i = 0;
// DRAW MAX HEART
while(i<panel.player.maxLife/2) {
graphics2d.drawImage(heart_blank, x, y, null);
i++;
x += panel.tileSize;
}
// RESET
x = panel.tileSize / 2;
i = 0;
// DRAW CURRENT LIFE
while(i<panel.player.life) {
graphics2d.drawImage(heart_half, x, y, null);
i++;
if(i < panel.player.life) graphics2d.drawImage(heart_full, x, y, null);
i++;
x += panel.tileSize;
} }
} }
@@ -61,6 +103,45 @@ public class UI {
} }
} }
public void drawTitleScreen() {
graphics2d.setColor(new Color(0, 0, 0));
graphics2d.fillRect(0, 0, panel.screenWidth, panel.screenHeight);
// TITLE NAME
graphics2d.setFont(graphics2d.getFont().deriveFont(Font.BOLD, 96F));
String text = "JGame2D";
int x = getCenteredX(text);
int y = panel.tileSize*3;
// SHADOW
graphics2d.setColor(Color.gray);
graphics2d.drawString(text, x+5, y+5);
// MAIN COLOR
graphics2d.setColor(Color.white);
graphics2d.drawString(text, x, y);
// MENU
graphics2d.setFont(graphics2d.getFont().deriveFont(Font.BOLD, 48F));
text = "NEW GAME";
x = getCenteredX(text);
y += panel.tileSize*4;
graphics2d.drawString(text, x, y);
if(commandNum == 0) graphics2d.drawString(">", x-panel.tileSize, y);
text = "LOAD GAME";
x = getCenteredX(text);
y += panel.tileSize;
graphics2d.drawString(text, x, y);
if(commandNum == 1) graphics2d.drawString(">", x-panel.tileSize, y);
text = "QUIT";
x = getCenteredX(text);
y += panel.tileSize;
graphics2d.drawString(text, x, y);
if(commandNum == 2) graphics2d.drawString(">", x-panel.tileSize, y);
}
public void drawSubWindow(int x, int y, int width, int height) { public void drawSubWindow(int x, int y, int width, int height) {
graphics2d.setColor(new Color(0,0,0,210)); graphics2d.setColor(new Color(0,0,0,210));
graphics2d.fillRoundRect(x, y, width, height, 35, 35); graphics2d.fillRoundRect(x, y, width, height, 35, 35);
@@ -69,7 +150,6 @@ public class UI {
graphics2d.drawRoundRect(x+5, y+5, width-10, height-10, 25, 25); graphics2d.drawRoundRect(x+5, y+5, width-10, height-10, 25, 25);
} }
public int getCenteredX(String text) { public int getCenteredX(String text) {
return panel.screenWidth / 2 - (int) graphics2d.getFontMetrics().getStringBounds(text, graphics2d).getWidth() / 2; return panel.screenWidth / 2 - (int) graphics2d.getFontMetrics().getStringBounds(text, graphics2d).getWidth() / 2;
} }

View File

@@ -2,18 +2,9 @@ package de.miaurizius.jgame2d.core.enums;
public enum Direction { public enum Direction {
UP("up"), UP,
DOWN("down"), DOWN,
LEFT("left"), LEFT,
RIGHT("right"); RIGHT
private final String name;
Direction(String name) {
this.name = name;
}
public String getName() {
return name;
}
} }

View File

@@ -5,5 +5,6 @@ public enum GameState {
PLAY, PLAY,
PAUSE, PAUSE,
DIALOGUE, DIALOGUE,
TITLE,
} }

View File

@@ -0,0 +1,59 @@
package de.miaurizius.jgame2d.core.handlers;
import de.miaurizius.jgame2d.core.GamePanel;
import de.miaurizius.jgame2d.core.enums.Direction;
import de.miaurizius.jgame2d.core.enums.GameState;
import java.awt.*;
public class EventHandler {
GamePanel panel;
Rectangle eventRect;
int eventRectDefaultX, eventRectDefaultY;
public EventHandler(GamePanel panel) {
this.panel = panel;
eventRect = new Rectangle();
eventRect.x = 23;
eventRect.y = 23;
eventRect.width = 2;
eventRect.height = 2;
eventRectDefaultX = eventRect.x;
eventRectDefaultY = eventRect.y;
}
public void checkEvent() {
if(hit(27,16, Direction.RIGHT)) damagePit(GameState.DIALOGUE);
if(hit(23,12, Direction.UP)) healingPool(GameState.DIALOGUE);
}
public boolean hit(int eventCol, int eventRow, Direction reqDirection) {
boolean hit = false;
panel.player.solidArea.x = panel.player.worldX + panel.player.solidArea.x;
panel.player.solidArea.y = panel.player.worldY + panel.player.solidArea.y;
eventRect.x = eventCol*panel.tileSize + eventRect.x;
eventRect.y = eventRow*panel.tileSize + eventRect.y;
if(panel.player.solidArea.intersects(eventRect)) if(reqDirection == null || panel.player.direction == reqDirection) hit = true;
panel.player.solidArea.x = panel.player.solidAreaDefaultX;
panel.player.solidArea.y = panel.player.solidAreaDefaultY;
eventRect.x = eventRectDefaultX;
eventRect.y = eventRectDefaultY;
return hit;
}
public void damagePit(GameState gameState) {
panel.gameState = gameState;
panel.ui.currentDialogue = "You have fallen into a pit!";
panel.player.life -= 1;
}
public void healingPool(GameState gameState) {
if(!panel.keyH.spacePressed) return;
panel.gameState = gameState;
panel.ui.currentDialogue = "You drank the holy water.\nYour life has been recovered!";
panel.player.life = panel.player.maxLife;
}
}

View File

@@ -41,8 +41,32 @@ public class KeyHandler implements KeyListener {
} }
break; break;
case DIALOGUE: case DIALOGUE:
if (code == KeyEvent.VK_SPACE) {
panel.gameState = GameState.PLAY;
}
break;
case TITLE:
switch (code) { switch (code) {
case KeyEvent.VK_SPACE -> panel.gameState = GameState.PLAY; case KeyEvent.VK_UP -> {
if(panel.ui.commandNum != 0) panel.ui.commandNum--;
}
case KeyEvent.VK_DOWN -> {
if(panel.ui.commandNum != 2) panel.ui.commandNum++;
}
case KeyEvent.VK_ENTER -> {
switch (panel.ui.commandNum) {
case 0:
panel.gameState = GameState.PLAY;
panel.playMusic(0);
break;
case 1:
// add later
break;
case 2:
System.exit(0);
break;
}
}
} }
break; break;
} }

View File

@@ -28,6 +28,10 @@ public class Entity {
String[] dialogue = new String[20]; String[] dialogue = new String[20];
int dialogueIndex = 0; int dialogueIndex = 0;
// CHARACTER STATUS
public int maxLife;
public int life;
public Entity(GamePanel panel) { public Entity(GamePanel panel) {
this.panel = panel; this.panel = panel;
} }

View File

@@ -30,7 +30,7 @@ public class OldManNPC extends Entity {
public void setDialogue() { public void setDialogue() {
dialogue[0] = "Hello, lad."; dialogue[0] = "Hello, lad.";
dialogue[1] = "So you've come to this island to \nfind the treasure?"; dialogue[1] = "So you've come to this island to \nfind the treasure?";
dialogue[2] = "I used to be a great wizard but now... \nI'm a bit too old for taking an \nadventure"; dialogue[2] = "I used to be a great wizard but now... \nI'm a bit too old for taking an \nadventure.";
dialogue[3] = "Well, good luck on you."; dialogue[3] = "Well, good luck on you.";
} }

View File

@@ -38,6 +38,10 @@ public class Player extends Entity {
worldY = panel.tileSize * 21; worldY = panel.tileSize * 21;
speed = 4; speed = 4;
direction = Direction.DOWN; direction = Direction.DOWN;
// PLAYER STATUS (1 heart = 2 lives)
maxLife = 6;
life = maxLife;
} }
public void getPlayerImage() { public void getPlayerImage() {
@@ -57,7 +61,7 @@ public class Player extends Entity {
if(keyH.upPressed) direction = Direction.UP; if(keyH.upPressed) direction = Direction.UP;
else if(keyH.downPressed) direction = Direction.DOWN; else if(keyH.downPressed) direction = Direction.DOWN;
else if(keyH.leftPressed) direction = Direction.LEFT; else if(keyH.leftPressed) direction = Direction.LEFT;
else if(keyH.rightPressed) direction = Direction.RIGHT; else direction = Direction.RIGHT;
// CHECK TILE COLLISION // CHECK TILE COLLISION
collisionOn = false; collisionOn = false;
@@ -71,6 +75,11 @@ public class Player extends Entity {
int npcIndex = panel.collisionH.checkEntity(this, panel.npc); int npcIndex = panel.collisionH.checkEntity(this, panel.npc);
interactNPC(npcIndex); interactNPC(npcIndex);
// CHECK EVENT
panel.eventH.checkEvent();
panel.keyH.spacePressed = false;
if(!collisionOn) { if(!collisionOn) {
switch (direction) { switch (direction) {
case UP -> worldY -= speed; case UP -> worldY -= speed;
@@ -99,7 +108,6 @@ public class Player extends Entity {
//if(!panel.keyH.spacePressed) return; //Only uncomment if text should only appear if player hits space //if(!panel.keyH.spacePressed) return; //Only uncomment if text should only appear if player hits space
panel.gameState = GameState.DIALOGUE; panel.gameState = GameState.DIALOGUE;
panel.npc[index].speak(); panel.npc[index].speak();
panel.keyH.spacePressed = false;
} }
public void draw(Graphics2D graphics2d) { public void draw(Graphics2D graphics2d) {

View File

@@ -0,0 +1,28 @@
package de.miaurizius.jgame2d.object;
import de.miaurizius.jgame2d.core.Boot;
import de.miaurizius.jgame2d.core.GamePanel;
import de.miaurizius.jgame2d.core.Utility;
import javax.imageio.ImageIO;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.logging.Level;
public class HeartObj extends SuperObject {
GamePanel panel;
public HeartObj(GamePanel panel) {
this.panel = panel;
name = "heart";
try {
image = Utility.scaleImage(ImageIO.read(new FileInputStream("assets/objects/heart_full.png")), panel.tileSize, panel.tileSize);
image2 = Utility.scaleImage(ImageIO.read(new FileInputStream("assets/objects/heart_half.png")), panel.tileSize, panel.tileSize);
image3 = Utility.scaleImage(ImageIO.read(new FileInputStream("assets/objects/heart_blank.png")), panel.tileSize, panel.tileSize);
} catch(IOException e) {
Boot.logger.log(Level.SEVERE, "Could not load image", e);
}
}
}

View File

@@ -7,7 +7,7 @@ import java.awt.image.BufferedImage;
public class SuperObject { public class SuperObject {
public BufferedImage image; public BufferedImage image, image2, image3;
public String name; public String name;
public boolean collision = false; public boolean collision = false;
public int worldX, worldY; public int worldX, worldY;