package de.miaurizius.jgame2d.core; import de.miaurizius.jgame2d.core.enums.GameState; import de.miaurizius.jgame2d.core.handlers.*; import de.miaurizius.jgame2d.entity.Entity; import de.miaurizius.jgame2d.entity.Player; import de.miaurizius.jgame2d.tile.TileManager; import javax.sound.sampled.Clip; import javax.swing.*; import java.awt.*; import java.util.ArrayList; import java.util.Comparator; import java.util.logging.Level; public class GamePanel extends JPanel implements Runnable { // SCREEN SETTINGS final int originalTileSize = 16; //16x16 tile final int scale = 3; public final int maxScreenCol = 16; public final int tileSize = originalTileSize * scale; //48x48 tile public final int maxScreenRow = 12; public final int screenWidth = tileSize * maxScreenCol; // 768 pixels public final int screenHeight = tileSize * maxScreenRow; // 576 pixels // WORLD SETTINGS public final int maxWorldCol = 50; public final int maxWorldRow = 50; public final String currentMap = "testmap2"; //FPS final int FPS = 60; int fpsMeasure; // SYSTEM public TileManager tileM = new TileManager(this); public KeyHandler keyH = new KeyHandler(this); public CollisionHandler collisionH = new CollisionHandler(this); public AssetSetter assetSetter = new AssetSetter(this); public UI ui = new UI(this); public EventHandler eventH = new EventHandler(this); Sound se = new Sound(); Sound music = new Sound(); Thread gameThread; // ENTITY AND OBJECT public Player player = new Player(this, keyH); public Entity[] obj = new Entity[10]; public Entity[] npc = new Entity[10]; public Entity[] monster = new Entity[20]; ArrayList entityList = new ArrayList<>(); // GAME STATE public GameState gameState; public GamePanel() { this.setPreferredSize(new Dimension(screenWidth, screenHeight)); this.setBackground(Color.black); this.setDoubleBuffered(true); this.addKeyListener(keyH); this.setFocusable(true); } // GAME THREAD / CORE public void startGameThread() { gameThread = new Thread(this); gameThread.start(); } @Override public void run() { double drawInterval = (double) 1000000000 / FPS; double delta = 0; double lastTime = System.nanoTime(); long currentTime; long timer = 0; int drawCount = 0; while(gameThread != null) { currentTime = System.nanoTime(); delta += (currentTime - lastTime) / drawInterval; timer += (long) (currentTime - lastTime); lastTime = currentTime; if(delta >= 1) { update(); repaint(); delta--; drawCount++; } if(timer >= 1000000000) { fpsMeasure = drawCount; drawCount = 0; timer = 0; } } } // FRAME GENERATION public void update() { switch(gameState) { case PLAY: player.update(); for(Entity entity : npc) if(entity != null) entity.update(); for(int i = 0; i < monster.length; i++) { Entity m = monster[i]; if(m != null) { if(m.alive && !m.dying) m.update(); if(!m.alive) monster[i] = null; } } break; case PAUSE: break; } } public void paintComponent(Graphics graphics) { super.paintComponent(graphics); Graphics2D graphics2d = (Graphics2D) graphics; // DEBUG long drawStart; drawStart = System.nanoTime(); // TITLE SCREEN if(gameState == GameState.TITLE) { ui.draw(graphics2d); return; } // GAME tileM.draw(graphics2d); // ENTITY RENDER SYSTEM entityList.add(player); for(Entity entity : npc) if(entity != null) entityList.add(entity); for(Entity entity : obj) if(entity != null) entityList.add(entity); for(Entity entity : monster) if(entity != null) entityList.add(entity); entityList.sort(Comparator.comparingInt(o -> o.worldY)); for(Entity entity : entityList) entity.draw(graphics2d); entityList.clear(); ui.draw(graphics2d); long drawEnd = System.nanoTime(); long passed = drawEnd - drawStart; // DEBUG if(keyH.debug) { int start = 350; graphics2d.setColor(Color.white); graphics2d.drawString("Draw Time: " + passed, 10, start); graphics2d.drawString("FPS: " + fpsMeasure, 10, start+tileSize); graphics2d.drawString("Invincible: " + player.invincibleCount, 10, start+tileSize*2); graphics2d.drawString("X, Y: " + player.worldX+", "+player.worldY, 10, start+tileSize*3); graphics2d.drawString("Col, Row: " + (player.worldX+player.solidArea.x)/tileSize+", "+(player.worldY+player.solidArea.y)/tileSize, 10, start+tileSize*4); Boot.logger.log(Level.FINE, "Draw Time: " + passed); } // END graphics.dispose(); } // MUSIC public void playMusic(int i) { Clip c = se.clips[i]; if(c.isRunning()) c.stop(); c.setFramePosition(0); c.start(); c.loop(Clip.LOOP_CONTINUOUSLY); } public void stopMusic() { music.stop(); } public void playSE(int i) { Clip c = se.clips[i]; if(c.isRunning()) c.stop(); c.setFramePosition(0); c.start(); } // SETTING THINGS UP public void setupGame() { assetSetter.setObject(); assetSetter.setNPC(); assetSetter.setMonster(); gameState = GameState.TITLE; } }