diff --git a/src/main/java/minicraft/core/Game.java b/src/main/java/minicraft/core/Game.java index 0ad4826..390c414 100644 --- a/src/main/java/minicraft/core/Game.java +++ b/src/main/java/minicraft/core/Game.java @@ -133,7 +133,6 @@ private static String getWittyComment() { // Main functions public static void main(String[] args) { - // Crash report log Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { throwable.printStackTrace(); diff --git a/src/main/java/minicraft/core/Initializer.java b/src/main/java/minicraft/core/Initializer.java index b76f0e0..542866c 100644 --- a/src/main/java/minicraft/core/Initializer.java +++ b/src/main/java/minicraft/core/Initializer.java @@ -104,7 +104,7 @@ static void run(Core discordCore) { // Refresh the screen now = System.nanoTime(); - if (now >= lastRender + 1E9D / maxFPS / 1.05) { + if (now >= lastRender + 1E9D / maxFPS / 1.01) { frames++; lastRender = System.nanoTime(); Renderer.render(); @@ -197,23 +197,30 @@ public void windowClosing(WindowEvent e) { @SuppressWarnings("serial") private static class LogoSplashCanvas extends JPanel { - private final Image logo; - { + private static final Image LOGO; + static { try { - logo = ImageIO.read(Objects.requireNonNull(Initializer.class.getResourceAsStream("/resources/title.png"))); + LOGO = ImageIO.read(Objects.requireNonNull(Initializer.class.getResourceAsStream("/resources/title.png"))); } catch (IOException exception) { throw new RuntimeException(exception); } } + private static final Color[] COLORS = new Color[256]; + static { + for (int i = 0; i < COLORS.length; i++) { + COLORS[i] = new Color(0, 0, 0, i); + } + } + private int transparency = 255; private boolean display = false; private boolean inAnimation = false; private boolean interruptWhenAnimated = false; - - public LogoSplashCanvas() { - setBackground(Color.BLACK); - } + + public LogoSplashCanvas() { + setBackground(Color.BLACK); + } public final Thread renderer = new Thread(() -> { do { @@ -225,18 +232,18 @@ public LogoSplashCanvas() { @Override public void paintComponent(Graphics graphics) { super.paintComponent(graphics); - - int lx = (getWidth() / 2) - logo.getWidth(frame); - int ly = (getHeight() / 2) - (logo.getHeight(frame) + 12); - int lw = logo.getWidth(frame) * 2; - int lh = logo.getHeight(frame) * 2; + + int lx = (getWidth() / 2) - LOGO.getWidth(frame); + int ly = (getHeight() / 2) - (LOGO.getHeight(frame) + 12); + int lw = LOGO.getWidth(frame) * 2; + int lh = LOGO.getHeight(frame) * 2; if (transparency < 255) { - graphics.drawImage(logo, lx, ly, lw, lh, frame); + graphics.drawImage(LOGO, lx, ly, lw, lh, frame); } - + if (transparency > 0) { - graphics.setColor(new Color(0, 0, 0, transparency)); + graphics.setColor(COLORS[transparency]); graphics.fillRect(0, 0, graphics.getClipBounds().width, graphics.getClipBounds().height); } diff --git a/src/main/java/minicraft/core/Renderer.java b/src/main/java/minicraft/core/Renderer.java index cc86776..2517d26 100644 --- a/src/main/java/minicraft/core/Renderer.java +++ b/src/main/java/minicraft/core/Renderer.java @@ -1,7 +1,9 @@ package minicraft.core; import java.awt.Canvas; +import java.awt.Dimension; import java.awt.Graphics; +import java.awt.Insets; import java.awt.image.BufferStrategy; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; @@ -164,17 +166,21 @@ public static void render() { Graphics graphics = bufferStrategy.getDrawGraphics(); // Gets the graphics in which java draws the picture graphics.fillRect(0, 0, canvas.getWidth(), canvas.getHeight()); // draws a rect to fill the whole window (to cover last?) - // Scale the pixels. - int windowWidth = getWindowSize().width; - int windowHeight = getWindowSize().height; + Dimension windowSize = getWindowSize(); - // Gets the image offset. - int xo = (canvas.getWidth() - windowWidth) / 2 + canvas.getParent().getInsets().left; - int yo = (canvas.getHeight() - windowHeight) / 2 + canvas.getParent().getInsets().top; - graphics.drawImage(image, xo, yo, windowWidth, windowHeight, null); // Draws the image on the window - graphics.dispose(); // Releases any system items that are using this method. (so we don't have crappy framerates) + // Calculate image offset + Insets insets = canvas.getParent().getInsets(); + int xo = (canvas.getWidth() - windowSize.width) / 2 + insets.left; + int yo = (canvas.getHeight() - windowSize.height) / 2 + insets.top; - bufferStrategy.show(); // Makes the picture visible. (probably) + // Draw the image on the window + graphics.drawImage(image, xo, yo, windowSize.width, windowSize.height, null); + + // Dispose graphics to free up system resources + graphics.dispose(); + + // Show the buffered image + bufferStrategy.show(); } private static void renderLevel() { @@ -194,10 +200,12 @@ private static void renderLevel() { if (yScroll > ((level.h << 4) - Screen.h)) yScroll = ((level.h << 4) - Screen.h); // ...bottom border. if (currentLevel > 3) { // If the current level is higher than 3 (which only the sky level (and dungeon) is) + int xShifted = (xScroll >> 2) & 7; + int yShifted = (yScroll >> 2) & 7; for (int y = 0; y < 37; y++) { for (int x = 0; x < 55; x++) { // Creates the background for the sky (and dungeon) level: - screen.render((x << 3) - ((xScroll >> 2) & 7), (y << 3) - ((yScroll >> 2) & 7), 3 + (23 << 5), 0, 1); + screen.render((x << 3) - xShifted, (y << 3) - yShifted, 3 + (23 << 5), 0, 1); } } } @@ -254,7 +262,7 @@ private static void renderGui() { // Renders the box Font.drawBox(screen, (Screen.w) / 2 - 32 - tool.arrowOffset, (Screen.h - 8) - 13, 3, 1); - if (isMode("Creative") || arrowsCount >= 10000) { + if (isMode("Creative") || arrowsCount >= 999) { Font.draw(" x" + "∞", screen, 184 - tool.arrowOffset, Screen.h - 24); } else { Font.draw(" x" + arrowsCount, screen, 180 - tool.arrowOffset, Screen.h - 24); @@ -342,41 +350,38 @@ private static void renderGui() { /// This renders the potions overlay if (player.showPotionEffects && !player.potionEffects.isEmpty()) { - Map.Entry [] effects = player.potionEffects.entrySet().toArray(new Map.Entry[0]); - - String title = "(" + input.getMapping("potionEffects") + " to hide)"; - - PotionType potionType; - Sprite potionIcon = new Sprite(0, 7, 0); - - for (int i = 0; i < effects.length; i++) { - int x = (Screen.w - 118) / 2 + (Screen.w - 8) / 3 - 8; // the width of the box - int y = (HEIGHT - 8) / 2 + (Screen.h - 8) / 36 - 130; // the height of the box - potionType = effects[i].getKey(); - - // Renders the GUI box - Font.drawBox(screen, x, y, 16, effects.length); - } - - for (int effectIndex = 0; effectIndex < effects.length; effectIndex++) { - potionType = effects[effectIndex].getKey(); - int potionTime = effects[effectIndex].getValue() / Updater.normalSpeed; - - potionIcon.color = potionType.displayColor; - - int minutes = potionTime / 60; - int seconds = potionTime % 60; - - // Title background - for (int j = 0; j < title.length(); j++) { - screen.render(311 + (j << 3) - 1, 9, 3 + (21 << 5), 0, 3); - } - Font.draw(title, screen, 310, 9, Color.YELLOW); - - Font.draw(potionType + " ", screen, 300 , 17 + effectIndex * Font.textHeight(), potionType.displayColor); - Font.draw("(" + minutes + ":" + (seconds < 10? "0" + seconds:seconds) + ")", screen, 373 , 17 + effectIndex * Font.textHeight(), potionType.displayColor); - potionIcon.render(screen, 290, 17 + effectIndex * Font.textHeight()); - } + Map.Entry[] effects = player.potionEffects.entrySet().toArray(new Map.Entry[0]); + String title = "(" + input.getMapping("potionEffects") + " to hide)"; + + Sprite potionIcon = new Sprite(0, 7, 0); + + int x = (Screen.w - 118) / 2 + (Screen.w - 8) / 3 - 8; // the width of the box + int y = (HEIGHT - 8) / 2 + (Screen.h - 8) / 36 - 130; // the height of the box + + int titleLen = title.length(); + + // Renders the GUI box + Font.drawBox(screen, x, y, 16, effects.length); + + for (int effectIndex = 0; effectIndex < effects.length; effectIndex++) { + PotionType potionType = effects[effectIndex].getKey(); + int potionTime = effects[effectIndex].getValue() / Updater.normalSpeed; + + potionIcon.color = potionType.displayColor; + + int minutes = potionTime / 60; + int seconds = potionTime % 60; + + Font.draw(potionType + " ", screen, 300 , 17 + effectIndex * Font.textHeight(), Color.GRAY); + Font.draw("(" + minutes + ":" + (seconds < 10? "0" + seconds:seconds) + ")", screen, 373 , 17 + effectIndex * Font.textHeight(), Color.YELLOW); + potionIcon.render(screen, 290, 17 + effectIndex * Font.textHeight()); + } + + // Title background + for (int j = 0; j < titleLen; j++) { + screen.render(311 + (j << 3) - 1, 9, 3 + (21 << 5), 0, 3); + } + Font.draw(title, screen, 310, 9, Color.YELLOW); } // This is the status icons, like health hearts, stamina bolts, hunger "burger", and armor points. diff --git a/src/main/java/minicraft/core/io/Settings.java b/src/main/java/minicraft/core/io/Settings.java index e7dd52e..427f3c4 100644 --- a/src/main/java/minicraft/core/io/Settings.java +++ b/src/main/java/minicraft/core/io/Settings.java @@ -33,7 +33,7 @@ public class Settings { options.put("cheats", new BooleanEntry("Cheats", true)); - options.put("size", new ArrayEntry<>("World Size", 256, 512, 1024)); + options.put("size", new ArrayEntry<>("World Size", 256, 512)); options.get("size").setSelection(0); options.put("theme", new ArrayEntry<>("World Theme", "Normal", "Forest", "Desert", "Plain", "Hell", "Snow")); @@ -61,7 +61,7 @@ public class Settings { options.get("textures").setSelection(0); // Video options - options.put("fps", new RangeEntry("Max FPS", 16, 300, getRefreshRate())); + options.put("fps", new RangeEntry("Max FPS", 30, 300, getRefreshRate())); options.put("vsync", new BooleanEntry("V.Sync", false)); options.put("bossbar", new ArrayEntry<>("Bossbar type", "On screen", "On entity", "Percent")); diff --git a/src/main/java/minicraft/entity/ItemEntity.java b/src/main/java/minicraft/entity/ItemEntity.java index abb24ce..9b21fe5 100644 --- a/src/main/java/minicraft/entity/ItemEntity.java +++ b/src/main/java/minicraft/entity/ItemEntity.java @@ -157,20 +157,28 @@ public boolean isSolid() { @Override public void render(Screen screen) { + int xo = 0; + int yo = 0; + + if (this.getLightRadius() > 0) { + xo = 5; + yo = 8; + } + /* This first part is for the blinking effect */ if (time >= lifeTime - 6 * 20 && !item.equals(Items.get("AlAzif"))) { if (time / 6 % 2 == 0) return; } + if (Settings.getBoolean("shadows")) { - item.sprite.render(screen, x - 5, y - 8, 4, -1, Color.BLACK); // item shadow uses black color + item.sprite.render(screen, x - xo, y - yo, 4, -1, Color.BLACK); // item shadow uses black color } - item.sprite.render(screen, x - 5, y - 8 - (int)(zz)); + item.sprite.render(screen, x - xo, y - yo - (int)(zz)); } @Override protected void touchedBy(Entity entity) { - if (entity instanceof EyeQueen || entity instanceof Fireball) { for (int i = 0; i < 1 + random.nextInt(2); i++) { int randX = random.nextInt(16); diff --git a/src/main/java/minicraft/graphic/Font.java b/src/main/java/minicraft/graphic/Font.java index 4d15f19..50fb808 100644 --- a/src/main/java/minicraft/graphic/Font.java +++ b/src/main/java/minicraft/graphic/Font.java @@ -113,13 +113,14 @@ public static void drawBackground(String msg, Screen screen, int x, int y) { public static void drawBackground(String msg, Screen screen, int x, int y, int whiteTint) { int xx = x; + + int len = msg.length(); - for (int i = 0; i < msg.length(); i++) { + for (int i = 0; i < len; i++) { // render the black background screen.render(xx, y, 12 + (24 << 5), 0, 3); int ix = chars.indexOf(msg.charAt(i)); xx += msg.charAt(i) == ' ' ? 8 : ix >= 0 ? Font.charsAdvance[ix] : 8; - } draw(msg, screen, x, y, whiteTint); } @@ -128,8 +129,9 @@ public static int textWidth(String text) { if (text == null) return 0; int width = 0; + int len = text.length(); - for (int i = 0; i < text.length(); ++i) { + for (int i = 0; i < len; ++i) { char chr = text.charAt(i); if (chr == Color.COLOR_CHAR) { diff --git a/src/main/java/minicraft/item/StackableItem.java b/src/main/java/minicraft/item/StackableItem.java index 9ce0732..ce633fa 100644 --- a/src/main/java/minicraft/item/StackableItem.java +++ b/src/main/java/minicraft/item/StackableItem.java @@ -79,12 +79,6 @@ protected static ArrayList getAllInstances() { items.add(new StackableItem("Gear", new Sprite(15, 4, 0))); items.add(new StackableItem("Spring", new Sprite(16, 3, 0))); items.add(new StackableItem("Flint", new Sprite(8, 3, 0))); - items.add(new StackableItem("Protection I", new Sprite(2, 8, 0))); - items.add(new StackableItem("Protection II", new Sprite(2, 8, 0))); - items.add(new StackableItem("Protection III", new Sprite(2, 8, 0))); - items.add(new StackableItem("Sharp I", new Sprite(2, 8, 0))); - items.add(new StackableItem("Sharp II", new Sprite(2, 8, 0))); - items.add(new StackableItem("Sharp III", new Sprite(2, 8, 0))); // Essences // items.add(new StackableItem("Cordyceps essence", new Sprite(1, 7, 0))); diff --git a/src/main/java/minicraft/level/Level.java b/src/main/java/minicraft/level/Level.java index 83c1947..d9974e9 100644 --- a/src/main/java/minicraft/level/Level.java +++ b/src/main/java/minicraft/level/Level.java @@ -607,8 +607,11 @@ public void renderLight(Screen screen, int xScroll, int yScroll, int brightness) screen.setOffset(xScroll, yScroll); int r = 8; + + int xBound = w + xo + r; + int yBound = h + yo + r; - List entities = getEntitiesInTiles(xo - r, yo - r, w + xo + r, h + yo + r); + List entities = getEntitiesInTiles(xo - r, yo - r, xBound, yBound); for (Entity entity: entities) { int lightRadius = entity.getLightRadius(); if (lightRadius > 0) { @@ -616,8 +619,8 @@ public void renderLight(Screen screen, int xScroll, int yScroll, int brightness) } } - for (int y = yo - r; y <= h + yo + r; y++) { - for (int x = xo - r; x <= w + xo + r; x++) { + for (int y = yo - r; y <= yBound; y++) { + for (int x = xo - r; x <= xBound; x++) { if (x < 0 || y < 0 || x >= this.w || y >= this.h) { continue; } @@ -629,42 +632,6 @@ public void renderLight(Screen screen, int xScroll, int yScroll, int brightness) screen.setOffset(0, 0); } - public void renderLight(Screen screen, int xScroll, int yScroll, int brightness, int additionalRadius) { - int xo = xScroll >> 4; - int yo = yScroll >> 4; - - int w = (Screen.w + 15) >> 4; - int h = (Screen.h + 15) >> 4; - - screen.setOffset(xScroll, yScroll); - - int r = 8; - - List entities = getEntitiesInTiles(xo - r, yo - r, w + xo + r, h + yo + r); - for (Entity entity: entities) { - int lightRadius = entity.getLightRadius(); - if (lightRadius > 0) { - lightRadius += additionalRadius; - screen.renderLight(entity.x - 1, entity.y - 4, lightRadius * brightness, 51); - } - } - - for (int y = yo - r; y <= h + yo + r; y++) { - for (int x = xo - r; x <= w + xo + r; x++) { - if (x < 0 || y < 0 || x >= this.w || y >= this.h) { - continue; - } - - int lightRadius = getTile(x, y).getLightRadius(this, x, y); - if (lightRadius > 0) { - lightRadius += additionalRadius; - screen.renderLight((x << 4) + 8, (y << 4) + 8, lightRadius * brightness, 0); - } - } - } - screen.setOffset(0, 0); - } - private void sortAndRender(Screen screen, List list) { list.sort(spriteSorter); for (Entity entity : list) { @@ -763,17 +730,22 @@ private void trySpawn() { if (spawnSkipChance > 0 && random.nextInt(spawnSkipChance) != 0) { return; // hopefully will make mobs spawn a lot slower. } + + boolean peaceful = Settings.get("diff").equals("Peaceful"); boolean spawned = false; for (int i = 0; i < 15 && !spawned; i++) { int minLevel = 1; int maxLevel = 1; + int lvl = 0; if (depth < 0) maxLevel = (-depth) + ((Math.random() > 0.75 && -depth != 4) ? 1 : 0); if (depth > 0) minLevel = maxLevel = 4; - - int lvl = random.nextInt(maxLevel - minLevel + 1) + minLevel; + + if (!peaceful) { + lvl = random.nextInt(maxLevel - minLevel + 1) + minLevel; + } int spawnChance = random.nextInt(100); int nx = (random.nextInt(w) << 4) + 8; int ny = (random.nextInt(h) << 4) + 8; @@ -781,7 +753,7 @@ private void trySpawn() { // System.out.println("trySpawn on level " + depth + " of lvl " + lvl + " mob w/rand " + random + " at tile " + nx + "," + ny); // spawns the enemy mobs; first part prevents enemy mob spawn on surface and the sky on first day, more or less. - if (!Settings.get("diff").equals("Peaceful")) { + if (!peaceful) { if ((depth != 1 && depth != 2) && EnemyMob.checkStartPos(this, nx, ny)) { if (depth == 0 && Updater.getTime() == Updater.Time.Night && !Game.player.isNiceNight) { EnemyMob[] mobs = {new Zombie(lvl), new Skeleton(lvl), new Creeper(lvl)}; @@ -863,16 +835,18 @@ private void trySpawn() { add((new Phyg()), nx, ny); add((new Sheepuff()), nx, ny); } else { // Spawns hostile sky mobs. - if (spawnChance <= 40) { - add((new Slime(lvl)), nx, ny); - } else if (spawnChance <= 75) { - add((new Zombie(lvl)), nx, ny); - } else if (spawnChance >= 85) { - add((new OldGolem(lvl)), nx, ny); - } else if (spawnChance >= 82) { - add((new Skeleton(lvl)), nx, ny); - } else { - add((new Creeper(lvl)), nx, ny); + if (!peaceful) { + if (spawnChance <= 40) { + add((new Slime(lvl)), nx, ny); + } else if (spawnChance <= 75) { + add((new Zombie(lvl)), nx, ny); + } else if (spawnChance >= 85) { + add((new OldGolem(lvl)), nx, ny); + } else if (spawnChance >= 82) { + add((new Skeleton(lvl)), nx, ny); + } else { + add((new Creeper(lvl)), nx, ny); + } } } spawned = true;