commit fd45f6aa7429522db6ca4fb10445fddccc76eefe Author: Voomra Date: Mon Aug 26 22:35:42 2024 +0300 import code diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28827b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# JetBrains +.idea/ +out/ +*.iml \ No newline at end of file diff --git a/res/bossdeath.wav b/res/bossdeath.wav new file mode 100644 index 0000000..3e56567 Binary files /dev/null and b/res/bossdeath.wav differ diff --git a/res/craft.wav b/res/craft.wav new file mode 100644 index 0000000..eb7da65 Binary files /dev/null and b/res/craft.wav differ diff --git a/res/death.wav b/res/death.wav new file mode 100644 index 0000000..100db7e Binary files /dev/null and b/res/death.wav differ diff --git a/res/icons.png b/res/icons.png new file mode 100644 index 0000000..a1b223c Binary files /dev/null and b/res/icons.png differ diff --git a/res/icons2.png b/res/icons2.png new file mode 100644 index 0000000..9d14900 Binary files /dev/null and b/res/icons2.png differ diff --git a/res/monsterhurt.wav b/res/monsterhurt.wav new file mode 100644 index 0000000..c2474ce Binary files /dev/null and b/res/monsterhurt.wav differ diff --git a/res/pickup.wav b/res/pickup.wav new file mode 100644 index 0000000..126f1b9 Binary files /dev/null and b/res/pickup.wav differ diff --git a/res/playerhurt.wav b/res/playerhurt.wav new file mode 100644 index 0000000..0d09a18 Binary files /dev/null and b/res/playerhurt.wav differ diff --git a/res/test.wav b/res/test.wav new file mode 100644 index 0000000..056f66d Binary files /dev/null and b/res/test.wav differ diff --git a/src/com/mojang/ld22/Game.java b/src/com/mojang/ld22/Game.java new file mode 100644 index 0000000..e9fdd2d --- /dev/null +++ b/src/com/mojang/ld22/Game.java @@ -0,0 +1,354 @@ +package com.mojang.ld22; + +import java.awt.BorderLayout; +import java.awt.Canvas; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.image.BufferStrategy; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.io.IOException; +import java.util.Random; + +import javax.imageio.ImageIO; +import javax.swing.JFrame; + +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.gfx.SpriteSheet; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; +import com.mojang.ld22.screen.DeadMenu; +import com.mojang.ld22.screen.LevelTransitionMenu; +import com.mojang.ld22.screen.Menu; +import com.mojang.ld22.screen.TitleMenu; +import com.mojang.ld22.screen.WonMenu; + +public class Game extends Canvas implements Runnable { + private static final long serialVersionUID = 1L; + private Random random = new Random(); + public static final String NAME = "Minicraft"; + public static final int HEIGHT = 120; + public static final int WIDTH = 160; + private static final int SCALE = 3; + + private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); + private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + private boolean running = false; + private Screen screen; + private Screen lightScreen; + private InputHandler input = new InputHandler(this); + + private int[] colors = new int[256]; + private int tickCount = 0; + public int gameTime = 0; + + private Level level; + private Level[] levels = new Level[5]; + private int currentLevel = 3; + public Player player; + + public Menu menu; + private int playerDeadTime; + private int pendingLevelChange; + private int wonTimer = 0; + public boolean hasWon = false; + + public void setMenu(Menu menu) { + this.menu = menu; + if (menu != null) menu.init(this, input); + } + + public void start() { + running = true; + new Thread(this).start(); + } + + public void stop() { + running = false; + } + + public void resetGame() { + playerDeadTime = 0; + wonTimer = 0; + gameTime = 0; + hasWon = false; + + levels = new Level[5]; + currentLevel = 3; + + levels[4] = new Level(128, 128, 1, null); + levels[3] = new Level(128, 128, 0, levels[4]); + levels[2] = new Level(128, 128, -1, levels[3]); + levels[1] = new Level(128, 128, -2, levels[2]); + levels[0] = new Level(128, 128, -3, levels[1]); + + level = levels[currentLevel]; + player = new Player(this, input); + player.findStartPos(level); + + level.add(player); + + for (int i = 0; i < 5; i++) { + levels[i].trySpawn(5000); + } + } + + private void init() { + int pp = 0; + for (int r = 0; r < 6; r++) { + for (int g = 0; g < 6; g++) { + for (int b = 0; b < 6; b++) { + int rr = (r * 255 / 5); + int gg = (g * 255 / 5); + int bb = (b * 255 / 5); + int mid = (rr * 30 + gg * 59 + bb * 11) / 100; + + int r1 = ((rr + mid * 1) / 2) * 230 / 255 + 10; + int g1 = ((gg + mid * 1) / 2) * 230 / 255 + 10; + int b1 = ((bb + mid * 1) / 2) * 230 / 255 + 10; + colors[pp++] = r1 << 16 | g1 << 8 | b1; + + } + } + } + try { + screen = new Screen(WIDTH, HEIGHT, new SpriteSheet(ImageIO.read(Game.class.getResourceAsStream("/icons.png")))); + lightScreen = new Screen(WIDTH, HEIGHT, new SpriteSheet(ImageIO.read(Game.class.getResourceAsStream("/icons.png")))); + } catch (IOException e) { + e.printStackTrace(); + } + + resetGame(); + setMenu(new TitleMenu()); + } + + public void run() { + long lastTime = System.nanoTime(); + double unprocessed = 0; + double nsPerTick = 1000000000.0 / 60; + int frames = 0; + int ticks = 0; + long lastTimer1 = System.currentTimeMillis(); + + init(); + + while (running) { + long now = System.nanoTime(); + unprocessed += (now - lastTime) / nsPerTick; + lastTime = now; + boolean shouldRender = true; + while (unprocessed >= 1) { + ticks++; + tick(); + unprocessed -= 1; + shouldRender = true; + } + + try { + Thread.sleep(2); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (shouldRender) { + frames++; + render(); + } + + if (System.currentTimeMillis() - lastTimer1 > 1000) { + lastTimer1 += 1000; + System.out.println(ticks + " ticks, " + frames + " fps"); + frames = 0; + ticks = 0; + } + } + } + + public void tick() { + tickCount++; + if (!hasFocus()) { + input.releaseAll(); + } else { + if (!player.removed && !hasWon) gameTime++; + + input.tick(); + if (menu != null) { + menu.tick(); + } else { + if (player.removed) { + playerDeadTime++; + if (playerDeadTime > 60) { + setMenu(new DeadMenu()); + } + } else { + if (pendingLevelChange != 0) { + setMenu(new LevelTransitionMenu(pendingLevelChange)); + pendingLevelChange = 0; + } + } + if (wonTimer > 0) { + if (--wonTimer == 0) { + setMenu(new WonMenu()); + } + } + level.tick(); + Tile.tickCount++; + } + } + } + + public void changeLevel(int dir) { + level.remove(player); + currentLevel += dir; + level = levels[currentLevel]; + player.x = (player.x >> 4) * 16 + 8; + player.y = (player.y >> 4) * 16 + 8; + level.add(player); + + } + + public void render() { + BufferStrategy bs = getBufferStrategy(); + if (bs == null) { + createBufferStrategy(3); + requestFocus(); + return; + } + + int xScroll = player.x - screen.w / 2; + int yScroll = player.y - (screen.h - 8) / 2; + if (xScroll < 16) xScroll = 16; + if (yScroll < 16) yScroll = 16; + if (xScroll > level.w * 16 - screen.w - 16) xScroll = level.w * 16 - screen.w - 16; + if (yScroll > level.h * 16 - screen.h - 16) yScroll = level.h * 16 - screen.h - 16; + if (currentLevel > 3) { + int col = Color.get(20, 20, 121, 121); + for (int y = 0; y < 14; y++) + for (int x = 0; x < 24; x++) { + screen.render(x * 8 - ((xScroll / 4) & 7), y * 8 - ((yScroll / 4) & 7), 0, col, 0); + } + } + + level.renderBackground(screen, xScroll, yScroll); + level.renderSprites(screen, xScroll, yScroll); + + if (currentLevel < 3) { + lightScreen.clear(0); + level.renderLight(lightScreen, xScroll, yScroll); + screen.overlay(lightScreen, xScroll, yScroll); + } + + renderGui(); + + if (!hasFocus()) renderFocusNagger(); + + for (int y = 0; y < screen.h; y++) { + for (int x = 0; x < screen.w; x++) { + int cc = screen.pixels[x + y * screen.w]; + if (cc < 255) pixels[x + y * WIDTH] = colors[cc]; + } + } + + Graphics g = bs.getDrawGraphics(); + g.fillRect(0, 0, getWidth(), getHeight()); + + int ww = WIDTH * 3; + int hh = HEIGHT * 3; + int xo = (getWidth() - ww) / 2; + int yo = (getHeight() - hh) / 2; + g.drawImage(image, xo, yo, ww, hh, null); + g.dispose(); + bs.show(); + } + + private void renderGui() { + for (int y = 0; y < 2; y++) { + for (int x = 0; x < 20; x++) { + screen.render(x * 8, screen.h - 16 + y * 8, 0 + 12 * 32, Color.get(000, 000, 000, 000), 0); + } + } + + for (int i = 0; i < 10; i++) { + if (i < player.health) + screen.render(i * 8, screen.h - 16, 0 + 12 * 32, Color.get(000, 200, 500, 533), 0); + else + screen.render(i * 8, screen.h - 16, 0 + 12 * 32, Color.get(000, 100, 000, 000), 0); + + if (player.staminaRechargeDelay > 0) { + if (player.staminaRechargeDelay / 4 % 2 == 0) + screen.render(i * 8, screen.h - 8, 1 + 12 * 32, Color.get(000, 555, 000, 000), 0); + else + screen.render(i * 8, screen.h - 8, 1 + 12 * 32, Color.get(000, 110, 000, 000), 0); + } else { + if (i < player.stamina) + screen.render(i * 8, screen.h - 8, 1 + 12 * 32, Color.get(000, 220, 550, 553), 0); + else + screen.render(i * 8, screen.h - 8, 1 + 12 * 32, Color.get(000, 110, 000, 000), 0); + } + } + if (player.activeItem != null) { + player.activeItem.renderInventory(screen, 10 * 8, screen.h - 16); + } + + if (menu != null) { + menu.render(screen); + } + } + + private void renderFocusNagger() { + String msg = "Click to focus!"; + int xx = (WIDTH - msg.length() * 8) / 2; + int yy = (HEIGHT - 8) / 2; + int w = msg.length(); + int h = 1; + + screen.render(xx - 8, yy - 8, 0 + 13 * 32, Color.get(-1, 1, 5, 445), 0); + screen.render(xx + w * 8, yy - 8, 0 + 13 * 32, Color.get(-1, 1, 5, 445), 1); + screen.render(xx - 8, yy + 8, 0 + 13 * 32, Color.get(-1, 1, 5, 445), 2); + screen.render(xx + w * 8, yy + 8, 0 + 13 * 32, Color.get(-1, 1, 5, 445), 3); + for (int x = 0; x < w; x++) { + screen.render(xx + x * 8, yy - 8, 1 + 13 * 32, Color.get(-1, 1, 5, 445), 0); + screen.render(xx + x * 8, yy + 8, 1 + 13 * 32, Color.get(-1, 1, 5, 445), 2); + } + for (int y = 0; y < h; y++) { + screen.render(xx - 8, yy + y * 8, 2 + 13 * 32, Color.get(-1, 1, 5, 445), 0); + screen.render(xx + w * 8, yy + y * 8, 2 + 13 * 32, Color.get(-1, 1, 5, 445), 1); + } + + if ((tickCount / 20) % 2 == 0) { + Font.draw(msg, screen, xx, yy, Color.get(5, 333, 333, 333)); + } else { + Font.draw(msg, screen, xx, yy, Color.get(5, 555, 555, 555)); + } + } + + public void scheduleLevelChange(int dir) { + pendingLevelChange = dir; + } + + public static void main(String[] args) { + Game game = new Game(); + game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE)); + game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE)); + game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE)); + + JFrame frame = new JFrame(Game.NAME); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLayout(new BorderLayout()); + frame.add(game, BorderLayout.CENTER); + frame.pack(); + frame.setResizable(false); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + + game.start(); + } + + public void won() { + wonTimer = 60 * 3; + hasWon = true; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/GameApplet.java b/src/com/mojang/ld22/GameApplet.java new file mode 100644 index 0000000..2c81002 --- /dev/null +++ b/src/com/mojang/ld22/GameApplet.java @@ -0,0 +1,23 @@ +package com.mojang.ld22; + +import java.applet.Applet; +import java.awt.BorderLayout; + +public class GameApplet extends Applet { + private static final long serialVersionUID = 1L; + + private Game game = new Game(); + + public void init() { + setLayout(new BorderLayout()); + add(game, BorderLayout.CENTER); + } + + public void start() { + game.start(); + } + + public void stop() { + game.stop(); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/InputHandler.java b/src/com/mojang/ld22/InputHandler.java new file mode 100644 index 0000000..9682ff2 --- /dev/null +++ b/src/com/mojang/ld22/InputHandler.java @@ -0,0 +1,98 @@ +package com.mojang.ld22; + +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.ArrayList; +import java.util.List; + +public class InputHandler implements KeyListener { + public class Key { + public int presses, absorbs; + public boolean down, clicked; + + public Key() { + keys.add(this); + } + + public void toggle(boolean pressed) { + if (pressed != down) { + down = pressed; + } + if (pressed) { + presses++; + } + } + + public void tick() { + if (absorbs < presses) { + absorbs++; + clicked = true; + } else { + clicked = false; + } + } + } + + public List keys = new ArrayList(); + + public Key up = new Key(); + public Key down = new Key(); + public Key left = new Key(); + public Key right = new Key(); + public Key attack = new Key(); + public Key menu = new Key(); + + public void releaseAll() { + for (int i = 0; i < keys.size(); i++) { + keys.get(i).down = false; + } + } + + public void tick() { + for (int i = 0; i < keys.size(); i++) { + keys.get(i).tick(); + } + } + + public InputHandler(Game game) { + game.addKeyListener(this); + } + + public void keyPressed(KeyEvent ke) { + toggle(ke, true); + } + + public void keyReleased(KeyEvent ke) { + toggle(ke, false); + } + + private void toggle(KeyEvent ke, boolean pressed) { + if (ke.getKeyCode() == KeyEvent.VK_NUMPAD8) up.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_NUMPAD2) down.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_NUMPAD4) left.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_NUMPAD6) right.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_W) up.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_S) down.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_A) left.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_D) right.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_UP) up.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_DOWN) down.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_LEFT) left.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_RIGHT) right.toggle(pressed); + + if (ke.getKeyCode() == KeyEvent.VK_TAB) menu.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_ALT) menu.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_ALT_GRAPH) menu.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_SPACE) attack.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_CONTROL) attack.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_NUMPAD0) attack.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_INSERT) attack.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_ENTER) menu.toggle(pressed); + + if (ke.getKeyCode() == KeyEvent.VK_X) menu.toggle(pressed); + if (ke.getKeyCode() == KeyEvent.VK_C) attack.toggle(pressed); + } + + public void keyTyped(KeyEvent ke) { + } +} diff --git a/src/com/mojang/ld22/crafting/Crafting.java b/src/com/mojang/ld22/crafting/Crafting.java new file mode 100644 index 0000000..deda785 --- /dev/null +++ b/src/com/mojang/ld22/crafting/Crafting.java @@ -0,0 +1,69 @@ +package com.mojang.ld22.crafting; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.ld22.entity.Anvil; +import com.mojang.ld22.entity.Chest; +import com.mojang.ld22.entity.Furnace; +import com.mojang.ld22.entity.Oven; +import com.mojang.ld22.entity.Lantern; +import com.mojang.ld22.entity.Workbench; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; + +public class Crafting { + public static final List anvilRecipes = new ArrayList(); + public static final List ovenRecipes = new ArrayList(); + public static final List furnaceRecipes = new ArrayList(); + public static final List workbenchRecipes = new ArrayList(); + + static { + try { + workbenchRecipes.add(new FurnitureRecipe(Lantern.class).addCost(Resource.wood, 5).addCost(Resource.slime, 10).addCost(Resource.glass, 4)); + + workbenchRecipes.add(new FurnitureRecipe(Oven.class).addCost(Resource.stone, 15)); + workbenchRecipes.add(new FurnitureRecipe(Furnace.class).addCost(Resource.stone, 20)); + workbenchRecipes.add(new FurnitureRecipe(Workbench.class).addCost(Resource.wood, 20)); + workbenchRecipes.add(new FurnitureRecipe(Chest.class).addCost(Resource.wood, 20)); + workbenchRecipes.add(new FurnitureRecipe(Anvil.class).addCost(Resource.ironIngot, 5)); + + workbenchRecipes.add(new ToolRecipe(ToolType.sword, 0).addCost(Resource.wood, 5)); + workbenchRecipes.add(new ToolRecipe(ToolType.axe, 0).addCost(Resource.wood, 5)); + workbenchRecipes.add(new ToolRecipe(ToolType.hoe, 0).addCost(Resource.wood, 5)); + workbenchRecipes.add(new ToolRecipe(ToolType.pickaxe, 0).addCost(Resource.wood, 5)); + workbenchRecipes.add(new ToolRecipe(ToolType.shovel, 0).addCost(Resource.wood, 5)); + workbenchRecipes.add(new ToolRecipe(ToolType.sword, 1).addCost(Resource.wood, 5).addCost(Resource.stone, 5)); + workbenchRecipes.add(new ToolRecipe(ToolType.axe, 1).addCost(Resource.wood, 5).addCost(Resource.stone, 5)); + workbenchRecipes.add(new ToolRecipe(ToolType.hoe, 1).addCost(Resource.wood, 5).addCost(Resource.stone, 5)); + workbenchRecipes.add(new ToolRecipe(ToolType.pickaxe, 1).addCost(Resource.wood, 5).addCost(Resource.stone, 5)); + workbenchRecipes.add(new ToolRecipe(ToolType.shovel, 1).addCost(Resource.wood, 5).addCost(Resource.stone, 5)); + + anvilRecipes.add(new ToolRecipe(ToolType.sword, 2).addCost(Resource.wood, 5).addCost(Resource.ironIngot, 5)); + anvilRecipes.add(new ToolRecipe(ToolType.axe, 2).addCost(Resource.wood, 5).addCost(Resource.ironIngot, 5)); + anvilRecipes.add(new ToolRecipe(ToolType.hoe, 2).addCost(Resource.wood, 5).addCost(Resource.ironIngot, 5)); + anvilRecipes.add(new ToolRecipe(ToolType.pickaxe, 2).addCost(Resource.wood, 5).addCost(Resource.ironIngot, 5)); + anvilRecipes.add(new ToolRecipe(ToolType.shovel, 2).addCost(Resource.wood, 5).addCost(Resource.ironIngot, 5)); + + anvilRecipes.add(new ToolRecipe(ToolType.sword, 3).addCost(Resource.wood, 5).addCost(Resource.goldIngot, 5)); + anvilRecipes.add(new ToolRecipe(ToolType.axe, 3).addCost(Resource.wood, 5).addCost(Resource.goldIngot, 5)); + anvilRecipes.add(new ToolRecipe(ToolType.hoe, 3).addCost(Resource.wood, 5).addCost(Resource.goldIngot, 5)); + anvilRecipes.add(new ToolRecipe(ToolType.pickaxe, 3).addCost(Resource.wood, 5).addCost(Resource.goldIngot, 5)); + anvilRecipes.add(new ToolRecipe(ToolType.shovel, 3).addCost(Resource.wood, 5).addCost(Resource.goldIngot, 5)); + + anvilRecipes.add(new ToolRecipe(ToolType.sword, 4).addCost(Resource.wood, 5).addCost(Resource.gem, 50)); + anvilRecipes.add(new ToolRecipe(ToolType.axe, 4).addCost(Resource.wood, 5).addCost(Resource.gem, 50)); + anvilRecipes.add(new ToolRecipe(ToolType.hoe, 4).addCost(Resource.wood, 5).addCost(Resource.gem, 50)); + anvilRecipes.add(new ToolRecipe(ToolType.pickaxe, 4).addCost(Resource.wood, 5).addCost(Resource.gem, 50)); + anvilRecipes.add(new ToolRecipe(ToolType.shovel, 4).addCost(Resource.wood, 5).addCost(Resource.gem, 50)); + + furnaceRecipes.add(new ResourceRecipe(Resource.ironIngot).addCost(Resource.ironOre, 4).addCost(Resource.coal, 1)); + furnaceRecipes.add(new ResourceRecipe(Resource.goldIngot).addCost(Resource.goldOre, 4).addCost(Resource.coal, 1)); + furnaceRecipes.add(new ResourceRecipe(Resource.glass).addCost(Resource.sand, 4).addCost(Resource.coal, 1)); + + ovenRecipes.add(new ResourceRecipe(Resource.bread).addCost(Resource.wheat, 4)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/crafting/FurnitureRecipe.java b/src/com/mojang/ld22/crafting/FurnitureRecipe.java new file mode 100644 index 0000000..ebe19e6 --- /dev/null +++ b/src/com/mojang/ld22/crafting/FurnitureRecipe.java @@ -0,0 +1,22 @@ +package com.mojang.ld22.crafting; + +import com.mojang.ld22.entity.Furniture; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.item.FurnitureItem; + +public class FurnitureRecipe extends Recipe { + private Class clazz; + + public FurnitureRecipe(Class clazz) throws InstantiationException, IllegalAccessException { + super(new FurnitureItem(clazz.newInstance())); + this.clazz = clazz; + } + + public void craft(Player player) { + try { + player.inventory.add(0, new FurnitureItem(clazz.newInstance())); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/com/mojang/ld22/crafting/Recipe.java b/src/com/mojang/ld22/crafting/Recipe.java new file mode 100644 index 0000000..a325130 --- /dev/null +++ b/src/com/mojang/ld22/crafting/Recipe.java @@ -0,0 +1,60 @@ +package com.mojang.ld22.crafting; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.screen.ListItem; + +public abstract class Recipe implements ListItem { + public List costs = new ArrayList(); + public boolean canCraft = false; + public Item resultTemplate; + + public Recipe(Item resultTemplate) { + this.resultTemplate = resultTemplate; + } + + public Recipe addCost(Resource resource, int count) { + costs.add(new ResourceItem(resource, count)); + return this; + } + + public void checkCanCraft(Player player) { + for (int i = 0; i < costs.size(); i++) { + Item item = costs.get(i); + if (item instanceof ResourceItem) { + ResourceItem ri = (ResourceItem) item; + if (!player.inventory.hasResources(ri.resource, ri.count)) { + canCraft = false; + return; + } + } + } + canCraft = true; + } + + public void renderInventory(Screen screen, int x, int y) { + screen.render(x, y, resultTemplate.getSprite(), resultTemplate.getColor(), 0); + int textColor = canCraft ? Color.get(-1, 555, 555, 555) : Color.get(-1, 222, 222, 222); + Font.draw(resultTemplate.getName(), screen, x + 8, y, textColor); + } + + public abstract void craft(Player player); + + public void deductCost(Player player) { + for (int i = 0; i < costs.size(); i++) { + Item item = costs.get(i); + if (item instanceof ResourceItem) { + ResourceItem ri = (ResourceItem) item; + player.inventory.removeResource(ri.resource, ri.count); + } + } + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/crafting/ResourceRecipe.java b/src/com/mojang/ld22/crafting/ResourceRecipe.java new file mode 100644 index 0000000..bc7661c --- /dev/null +++ b/src/com/mojang/ld22/crafting/ResourceRecipe.java @@ -0,0 +1,21 @@ +package com.mojang.ld22.crafting; + +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.resource.Resource; + +public class ResourceRecipe extends Recipe { + private Resource resource; + + public ResourceRecipe(Resource resource) { + super(new ResourceItem(resource, 1)); + this.resource = resource; + } + + public void craft(Player player) { + player.inventory.add(0, new ResourceItem(resource, 1)); + } +} diff --git a/src/com/mojang/ld22/crafting/ToolRecipe.java b/src/com/mojang/ld22/crafting/ToolRecipe.java new file mode 100644 index 0000000..00510c2 --- /dev/null +++ b/src/com/mojang/ld22/crafting/ToolRecipe.java @@ -0,0 +1,20 @@ +package com.mojang.ld22.crafting; + +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; + +public class ToolRecipe extends Recipe { + private ToolType type; + private int level; + + public ToolRecipe(ToolType type, int level) { + super(new ToolItem(type, level)); + this.type = type; + this.level = level; + } + + public void craft(Player player) { + player.inventory.add(0, new ToolItem(type, level)); + } +} diff --git a/src/com/mojang/ld22/entity/AirWizard.java b/src/com/mojang/ld22/entity/AirWizard.java new file mode 100644 index 0000000..42d2f8b --- /dev/null +++ b/src/com/mojang/ld22/entity/AirWizard.java @@ -0,0 +1,158 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.sound.Sound; + +public class AirWizard extends Mob { + private int xa, ya; + private int randomWalkTime = 0; + private int attackDelay = 0; + private int attackTime = 0; + private int attackType = 0; + + public AirWizard() { + x = random.nextInt(64 * 16); + y = random.nextInt(64 * 16); + health = maxHealth = 2000; + } + + public void tick() { + super.tick(); + + if (attackDelay > 0) { + dir = (attackDelay - 45) / 4 % 4; + dir = (dir * 2 % 4) + (dir / 2); + if (attackDelay < 45) { + dir = 0; + } + attackDelay--; + if (attackDelay == 0) { + attackType = 0; + if (health < 1000) attackType = 1; + if (health < 200) attackType = 2; + attackTime = 60 * 2; + } + return; + } + + if (attackTime > 0) { + attackTime--; + double dir = attackTime * 0.25 * (attackTime % 2 * 2 - 1); + double speed = (0.7) + attackType * 0.2; + level.add(new Spark(this, Math.cos(dir) * speed, Math.sin(dir) * speed)); + return; + } + + if (level.player != null && randomWalkTime == 0) { + int xd = level.player.x - x; + int yd = level.player.y - y; + if (xd * xd + yd * yd < 32 * 32) { + xa = 0; + ya = 0; + if (xd < 0) xa = +1; + if (xd > 0) xa = -1; + if (yd < 0) ya = +1; + if (yd > 0) ya = -1; + } else if (xd * xd + yd * yd > 80 * 80) { + xa = 0; + ya = 0; + if (xd < 0) xa = -1; + if (xd > 0) xa = +1; + if (yd < 0) ya = -1; + if (yd > 0) ya = +1; + } + } + + int speed = (tickTime % 4) == 0 ? 0 : 1; + if (!move(xa * speed, ya * speed) || random.nextInt(100) == 0) { + randomWalkTime = 30; + xa = (random.nextInt(3) - 1); + ya = (random.nextInt(3) - 1); + } + if (randomWalkTime > 0) { + randomWalkTime--; + if (level.player != null && randomWalkTime == 0) { + int xd = level.player.x - x; + int yd = level.player.y - y; + if (random.nextInt(4) == 0 && xd * xd + yd * yd < 50 * 50) { + if (attackDelay == 0 && attackTime == 0) { + attackDelay = 60 * 2; + } + } + } + } + } + + protected void doHurt(int damage, int attackDir) { + super.doHurt(damage, attackDir); + if (attackDelay == 0 && attackTime == 0) { + attackDelay = 60 * 2; + } + } + + public void render(Screen screen) { + int xt = 8; + int yt = 14; + + int flip1 = (walkDist >> 3) & 1; + int flip2 = (walkDist >> 3) & 1; + + if (dir == 1) { + xt += 2; + } + if (dir > 1) { + + flip1 = 0; + flip2 = ((walkDist >> 4) & 1); + if (dir == 2) { + flip1 = 1; + } + xt += 4 + ((walkDist >> 3) & 1) * 2; + } + + int xo = x - 8; + int yo = y - 11; + + int col1 = Color.get(-1, 100, 500, 555); + int col2 = Color.get(-1, 100, 500, 532); + if (health < 200) { + if (tickTime / 3 % 2 == 0) { + col1 = Color.get(-1, 500, 100, 555); + col2 = Color.get(-1, 500, 100, 532); + } + } else if (health < 1000) { + if (tickTime / 5 % 4 == 0) { + col1 = Color.get(-1, 500, 100, 555); + col2 = Color.get(-1, 500, 100, 532); + } + } + if (hurtTime > 0) { + col1 = Color.get(-1, 555, 555, 555); + col2 = Color.get(-1, 555, 555, 555); + } + + screen.render(xo + 8 * flip1, yo + 0, xt + yt * 32, col1, flip1); + screen.render(xo + 8 - 8 * flip1, yo + 0, xt + 1 + yt * 32, col1, flip1); + screen.render(xo + 8 * flip2, yo + 8, xt + (yt + 1) * 32, col2, flip2); + screen.render(xo + 8 - 8 * flip2, yo + 8, xt + 1 + (yt + 1) * 32, col2, flip2); + } + + protected void touchedBy(Entity entity) { + if (entity instanceof Player) { + entity.hurt(this, 3, dir); + } + } + + protected void die() { + super.die(); + if (level.player != null) { + level.player.score += 1000; + level.player.gameWon(); + } + Sound.bossdeath.play(); + } + +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Anvil.java b/src/com/mojang/ld22/entity/Anvil.java new file mode 100644 index 0000000..5ed22b4 --- /dev/null +++ b/src/com/mojang/ld22/entity/Anvil.java @@ -0,0 +1,20 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.crafting.Crafting; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.screen.CraftingMenu; + +public class Anvil extends Furniture { + public Anvil() { + super("Anvil"); + col = Color.get(-1, 000, 111, 222); + sprite = 0; + xr = 3; + yr = 2; + } + + public boolean use(Player player, int attackDir) { + player.game.setMenu(new CraftingMenu(Crafting.anvilRecipes, player)); + return true; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Chest.java b/src/com/mojang/ld22/entity/Chest.java new file mode 100644 index 0000000..7e4146c --- /dev/null +++ b/src/com/mojang/ld22/entity/Chest.java @@ -0,0 +1,19 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.screen.ContainerMenu; + +public class Chest extends Furniture { + public Inventory inventory = new Inventory(); + + public Chest() { + super("Chest"); + col = Color.get(-1, 110, 331, 552); + sprite = 1; + } + + public boolean use(Player player, int attackDir) { + player.game.setMenu(new ContainerMenu(player, "Chest", inventory)); + return true; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Entity.java b/src/com/mojang/ld22/entity/Entity.java new file mode 100644 index 0000000..34dd41e --- /dev/null +++ b/src/com/mojang/ld22/entity/Entity.java @@ -0,0 +1,134 @@ +package com.mojang.ld22.entity; + +import java.util.List; +import java.util.Random; + +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; + +public class Entity { + protected final Random random = new Random(); + public int x, y; + public int xr = 6; + public int yr = 6; + public boolean removed; + public Level level; + + public void render(Screen screen) { + } + + public void tick() { + } + + public void remove() { + removed = true; + } + + public final void init(Level level) { + this.level = level; + } + + public boolean intersects(int x0, int y0, int x1, int y1) { + return !(x + xr < x0 || y + yr < y0 || x - xr > x1 || y - yr > y1); + } + + public boolean blocks(Entity e) { + return false; + } + + public void hurt(Mob mob, int dmg, int attackDir) { + } + + public void hurt(Tile tile, int x, int y, int dmg) { + } + + public boolean move(int xa, int ya) { + if (xa != 0 || ya != 0) { + boolean stopped = true; + if (xa != 0 && move2(xa, 0)) stopped = false; + if (ya != 0 && move2(0, ya)) stopped = false; + if (!stopped) { + int xt = x >> 4; + int yt = y >> 4; + level.getTile(xt, yt).steppedOn(level, xt, yt, this); + } + return !stopped; + } + return true; + } + + protected boolean move2(int xa, int ya) { + if (xa != 0 && ya != 0) throw new IllegalArgumentException("Move2 can only move along one axis at a time!"); + + int xto0 = ((x) - xr) >> 4; + int yto0 = ((y) - yr) >> 4; + int xto1 = ((x) + xr) >> 4; + int yto1 = ((y) + yr) >> 4; + + int xt0 = ((x + xa) - xr) >> 4; + int yt0 = ((y + ya) - yr) >> 4; + int xt1 = ((x + xa) + xr) >> 4; + int yt1 = ((y + ya) + yr) >> 4; + boolean blocked = false; + for (int yt = yt0; yt <= yt1; yt++) + for (int xt = xt0; xt <= xt1; xt++) { + if (xt >= xto0 && xt <= xto1 && yt >= yto0 && yt <= yto1) continue; + level.getTile(xt, yt).bumpedInto(level, xt, yt, this); + if (!level.getTile(xt, yt).mayPass(level, xt, yt, this)) { + blocked = true; + return false; + } + } + if (blocked) return false; + + List wasInside = level.getEntities(x - xr, y - yr, x + xr, y + yr); + List isInside = level.getEntities(x + xa - xr, y + ya - yr, x + xa + xr, y + ya + yr); + for (int i = 0; i < isInside.size(); i++) { + Entity e = isInside.get(i); + if (e == this) continue; + + e.touchedBy(this); + } + isInside.removeAll(wasInside); + for (int i = 0; i < isInside.size(); i++) { + Entity e = isInside.get(i); + if (e == this) continue; + + if (e.blocks(this)) { + return false; + } + } + + x += xa; + y += ya; + return true; + } + + protected void touchedBy(Entity entity) { + } + + public boolean isBlockableBy(Mob mob) { + return true; + } + + public void touchItem(ItemEntity itemEntity) { + } + + public boolean canSwim() { + return false; + } + + public boolean interact(Player player, Item item, int attackDir) { + return item.interact(player, this, attackDir); + } + + public boolean use(Player player, int attackDir) { + return false; + } + + public int getLightRadius() { + return 0; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Furnace.java b/src/com/mojang/ld22/entity/Furnace.java new file mode 100644 index 0000000..b95aed1 --- /dev/null +++ b/src/com/mojang/ld22/entity/Furnace.java @@ -0,0 +1,20 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.crafting.Crafting; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.screen.CraftingMenu; + +public class Furnace extends Furniture { + public Furnace() { + super("Furnace"); + col = Color.get(-1, 000, 222, 333); + sprite = 3; + xr = 3; + yr = 2; + } + + public boolean use(Player player, int attackDir) { + player.game.setMenu(new CraftingMenu(Crafting.furnaceRecipes, player)); + return true; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Furniture.java b/src/com/mojang/ld22/entity/Furniture.java new file mode 100644 index 0000000..ae3256b --- /dev/null +++ b/src/com/mojang/ld22/entity/Furniture.java @@ -0,0 +1,58 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.FurnitureItem; +import com.mojang.ld22.item.PowerGloveItem; + +public class Furniture extends Entity { + private int pushTime = 0; + private int pushDir = -1; + public int col, sprite; + public String name; + private Player shouldTake; + + public Furniture(String name) { + this.name = name; + xr = 3; + yr = 3; + } + + public void tick() { + if (shouldTake != null) { + if (shouldTake.activeItem instanceof PowerGloveItem) { + remove(); + shouldTake.inventory.add(0, shouldTake.activeItem); + shouldTake.activeItem = new FurnitureItem(this); + } + shouldTake = null; + } + if (pushDir == 0) move(0, +1); + if (pushDir == 1) move(0, -1); + if (pushDir == 2) move(-1, 0); + if (pushDir == 3) move(+1, 0); + pushDir = -1; + if (pushTime > 0) pushTime--; + } + + public void render(Screen screen) { + screen.render(x - 8, y - 8 - 4, sprite * 2 + 8 * 32, col, 0); + screen.render(x - 0, y - 8 - 4, sprite * 2 + 8 * 32 + 1, col, 0); + screen.render(x - 8, y - 0 - 4, sprite * 2 + 8 * 32 + 32, col, 0); + screen.render(x - 0, y - 0 - 4, sprite * 2 + 8 * 32 + 33, col, 0); + } + + public boolean blocks(Entity e) { + return true; + } + + protected void touchedBy(Entity entity) { + if (entity instanceof Player && pushTime == 0) { + pushDir = ((Player) entity).dir; + pushTime = 10; + } + } + + public void take(Player player) { + shouldTake = player; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Inventory.java b/src/com/mojang/ld22/entity/Inventory.java new file mode 100644 index 0000000..19d79a6 --- /dev/null +++ b/src/com/mojang/ld22/entity/Inventory.java @@ -0,0 +1,69 @@ +package com.mojang.ld22.entity; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.resource.Resource; + +public class Inventory { + public List items = new ArrayList(); + + public void add(Item item) { + add(items.size(), item); + } + + public void add(int slot, Item item) { + if (item instanceof ResourceItem) { + ResourceItem toTake = (ResourceItem) item; + ResourceItem has = findResource(toTake.resource); + if (has == null) { + items.add(slot, toTake); + } else { + has.count += toTake.count; + } + } else { + items.add(slot, item); + } + } + + private ResourceItem findResource(Resource resource) { + for (int i = 0; i < items.size(); i++) { + if (items.get(i) instanceof ResourceItem) { + ResourceItem has = (ResourceItem) items.get(i); + if (has.resource == resource) return has; + } + } + return null; + } + + public boolean hasResources(Resource r, int count) { + ResourceItem ri = findResource(r); + if (ri == null) return false; + return ri.count >= count; + } + + public boolean removeResource(Resource r, int count) { + ResourceItem ri = findResource(r); + if (ri == null) return false; + if (ri.count < count) return false; + ri.count -= count; + if (ri.count <= 0) items.remove(ri); + return true; + } + + public int count(Item item) { + if (item instanceof ResourceItem) { + ResourceItem ri = findResource(((ResourceItem)item).resource); + if (ri!=null) return ri.count; + } else { + int count = 0; + for (int i=0; i= lifeTime) { + remove(); + return; + } + xx += xa; + yy += ya; + zz += za; + if (zz < 0) { + zz = 0; + za *= -0.5; + xa *= 0.6; + ya *= 0.6; + } + za -= 0.15; + int ox = x; + int oy = y; + int nx = (int) xx; + int ny = (int) yy; + int expectedx = nx - x; + int expectedy = ny - y; + move(nx - x, ny - y); + int gotx = x - ox; + int goty = y - oy; + xx += gotx - expectedx; + yy += goty - expectedy; + + if (hurtTime > 0) hurtTime--; + } + + public boolean isBlockableBy(Mob mob) { + return false; + } + + public void render(Screen screen) { + if (time >= lifeTime - 6 * 20) { + if (time / 6 % 2 == 0) return; + } + screen.render(x - 4, y - 4, item.getSprite(), Color.get(-1, 0, 0, 0), 0); + screen.render(x - 4, y - 4 - (int) (zz), item.getSprite(), item.getColor(), 0); + } + + protected void touchedBy(Entity entity) { + if (time > 30) entity.touchItem(this); + } + + public void take(Player player) { + Sound.pickup.play(); + player.score++; + item.onTake(this); + remove(); + } +} diff --git a/src/com/mojang/ld22/entity/Lantern.java b/src/com/mojang/ld22/entity/Lantern.java new file mode 100644 index 0000000..27a3702 --- /dev/null +++ b/src/com/mojang/ld22/entity/Lantern.java @@ -0,0 +1,17 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.gfx.Color; + +public class Lantern extends Furniture { + public Lantern() { + super("Lantern"); + col = Color.get(-1, 000, 111, 555); + sprite = 5; + xr = 3; + yr = 2; + } + + public int getLightRadius() { + return 8; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Mob.java b/src/com/mojang/ld22/entity/Mob.java new file mode 100644 index 0000000..1db8e32 --- /dev/null +++ b/src/com/mojang/ld22/entity/Mob.java @@ -0,0 +1,140 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.entity.particle.TextParticle; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; +import com.mojang.ld22.sound.Sound; + +public class Mob extends Entity { + protected int walkDist = 0; + protected int dir = 0; + public int hurtTime = 0; + protected int xKnockback, yKnockback; + public int maxHealth = 10; + public int health = maxHealth; + public int swimTimer = 0; + public int tickTime = 0; + + public Mob() { + x = y = 8; + xr = 4; + yr = 3; + } + + public void tick() { + tickTime++; + if (level.getTile(x >> 4, y >> 4) == Tile.lava) { + hurt(this, 4, dir ^ 1); + } + + if (health <= 0) { + die(); + } + if (hurtTime > 0) hurtTime--; + } + + protected void die() { + remove(); + } + + public boolean move(int xa, int ya) { + if (isSwimming()) { + if (swimTimer++ % 2 == 0) return true; + } + if (xKnockback < 0) { + move2(-1, 0); + xKnockback++; + } + if (xKnockback > 0) { + move2(1, 0); + xKnockback--; + } + if (yKnockback < 0) { + move2(0, -1); + yKnockback++; + } + if (yKnockback > 0) { + move2(0, 1); + yKnockback--; + } + if (hurtTime > 0) return true; + if (xa != 0 || ya != 0) { + walkDist++; + if (xa < 0) dir = 2; + if (xa > 0) dir = 3; + if (ya < 0) dir = 1; + if (ya > 0) dir = 0; + } + return super.move(xa, ya); + } + + protected boolean isSwimming() { + Tile tile = level.getTile(x >> 4, y >> 4); + return tile == Tile.water || tile == Tile.lava; + } + + public boolean blocks(Entity e) { + return e.isBlockableBy(this); + } + + public void hurt(Tile tile, int x, int y, int damage) { + int attackDir = dir ^ 1; + doHurt(damage, attackDir); + } + + public void hurt(Mob mob, int damage, int attackDir) { + doHurt(damage, attackDir); + } + + public void heal(int heal) { + if (hurtTime > 0) return; + + level.add(new TextParticle("" + heal, x, y, Color.get(-1, 50, 50, 50))); + health += heal; + if (health > maxHealth) health = maxHealth; + } + + protected void doHurt(int damage, int attackDir) { + if (hurtTime > 0) return; + + if (level.player != null) { + int xd = level.player.x - x; + int yd = level.player.y - y; + if (xd * xd + yd * yd < 80 * 80) { + Sound.monsterHurt.play(); + } + } + level.add(new TextParticle("" + damage, x, y, Color.get(-1, 500, 500, 500))); + health -= damage; + if (attackDir == 0) yKnockback = +6; + if (attackDir == 1) yKnockback = -6; + if (attackDir == 2) xKnockback = -6; + if (attackDir == 3) xKnockback = +6; + hurtTime = 10; + } + + public boolean findStartPos(Level level) { + int x = random.nextInt(level.w); + int y = random.nextInt(level.h); + int xx = x * 16 + 8; + int yy = y * 16 + 8; + + if (level.player != null) { + int xd = level.player.x - xx; + int yd = level.player.y - yy; + if (xd * xd + yd * yd < 80 * 80) return false; + } + + int r = level.monsterDensity * 16; + if (level.getEntities(xx - r, yy - r, xx + r, yy + r).size() > 0) return false; + + if (level.getTile(x, y).mayPass(level, x, y, this)) { + this.x = xx; + this.y = yy; + return true; + } + + return false; + } +} diff --git a/src/com/mojang/ld22/entity/Oven.java b/src/com/mojang/ld22/entity/Oven.java new file mode 100644 index 0000000..6ab8410 --- /dev/null +++ b/src/com/mojang/ld22/entity/Oven.java @@ -0,0 +1,20 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.crafting.Crafting; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.screen.CraftingMenu; + +public class Oven extends Furniture { + public Oven() { + super("Oven"); + col = Color.get(-1, 000, 332, 442); + sprite = 2; + xr = 3; + yr = 2; + } + + public boolean use(Player player, int attackDir) { + player.game.setMenu(new CraftingMenu(Crafting.ovenRecipes, player)); + return true; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Player.java b/src/com/mojang/ld22/entity/Player.java new file mode 100644 index 0000000..5865b78 --- /dev/null +++ b/src/com/mojang/ld22/entity/Player.java @@ -0,0 +1,395 @@ +package com.mojang.ld22.entity; + +import java.util.List; + +import com.mojang.ld22.Game; +import com.mojang.ld22.InputHandler; +import com.mojang.ld22.entity.particle.TextParticle; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.FurnitureItem; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.PowerGloveItem; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; +import com.mojang.ld22.screen.InventoryMenu; +import com.mojang.ld22.sound.Sound; + +public class Player extends Mob { + private InputHandler input; + private int attackTime, attackDir; + + public Game game; + public Inventory inventory = new Inventory(); + public Item attackItem; + public Item activeItem; + public int stamina; + public int staminaRecharge; + public int staminaRechargeDelay; + public int score; + public int maxStamina = 10; + private int onStairDelay; + public int invulnerableTime = 0; + + public Player(Game game, InputHandler input) { + this.game = game; + this.input = input; + x = 24; + y = 24; + stamina = maxStamina; + + inventory.add(new FurnitureItem(new Workbench())); + inventory.add(new PowerGloveItem()); + } + + public void tick() { + super.tick(); + + if (invulnerableTime > 0) invulnerableTime--; + Tile onTile = level.getTile(x >> 4, y >> 4); + if (onTile == Tile.stairsDown || onTile == Tile.stairsUp) { + if (onStairDelay == 0) { + changeLevel((onTile == Tile.stairsUp) ? 1 : -1); + onStairDelay = 10; + return; + } + onStairDelay = 10; + } else { + if (onStairDelay > 0) onStairDelay--; + } + + if (stamina <= 0 && staminaRechargeDelay == 0 && staminaRecharge == 0) { + staminaRechargeDelay = 40; + } + + if (staminaRechargeDelay > 0) { + staminaRechargeDelay--; + } + + if (staminaRechargeDelay == 0) { + staminaRecharge++; + if (isSwimming()) { + staminaRecharge = 0; + } + while (staminaRecharge > 10) { + staminaRecharge -= 10; + if (stamina < maxStamina) stamina++; + } + } + + int xa = 0; + int ya = 0; + if (input.up.down) ya--; + if (input.down.down) ya++; + if (input.left.down) xa--; + if (input.right.down) xa++; + if (isSwimming() && tickTime % 60 == 0) { + if (stamina > 0) { + stamina--; + } else { + hurt(this, 1, dir ^ 1); + } + } + + if (staminaRechargeDelay % 2 == 0) { + move(xa, ya); + } + + if (input.attack.clicked) { + if (stamina == 0) { + + } else { + stamina--; + staminaRecharge = 0; + attack(); + } + } + if (input.menu.clicked) { + if (!use()) { + game.setMenu(new InventoryMenu(this)); + } + } + if (attackTime > 0) attackTime--; + + } + + private boolean use() { + int yo = -2; + if (dir == 0 && use(x - 8, y + 4 + yo, x + 8, y + 12 + yo)) return true; + if (dir == 1 && use(x - 8, y - 12 + yo, x + 8, y - 4 + yo)) return true; + if (dir == 3 && use(x + 4, y - 8 + yo, x + 12, y + 8 + yo)) return true; + if (dir == 2 && use(x - 12, y - 8 + yo, x - 4, y + 8 + yo)) return true; + + int xt = x >> 4; + int yt = (y + yo) >> 4; + int r = 12; + if (attackDir == 0) yt = (y + r + yo) >> 4; + if (attackDir == 1) yt = (y - r + yo) >> 4; + if (attackDir == 2) xt = (x - r) >> 4; + if (attackDir == 3) xt = (x + r) >> 4; + + if (xt >= 0 && yt >= 0 && xt < level.w && yt < level.h) { + if (level.getTile(xt, yt).use(level, xt, yt, this, attackDir)) return true; + } + + return false; + } + + private void attack() { + walkDist += 8; + attackDir = dir; + attackItem = activeItem; + boolean done = false; + + if (activeItem != null) { + attackTime = 10; + int yo = -2; + int range = 12; + if (dir == 0 && interact(x - 8, y + 4 + yo, x + 8, y + range + yo)) done = true; + if (dir == 1 && interact(x - 8, y - range + yo, x + 8, y - 4 + yo)) done = true; + if (dir == 3 && interact(x + 4, y - 8 + yo, x + range, y + 8 + yo)) done = true; + if (dir == 2 && interact(x - range, y - 8 + yo, x - 4, y + 8 + yo)) done = true; + if (done) return; + + int xt = x >> 4; + int yt = (y + yo) >> 4; + int r = 12; + if (attackDir == 0) yt = (y + r + yo) >> 4; + if (attackDir == 1) yt = (y - r + yo) >> 4; + if (attackDir == 2) xt = (x - r) >> 4; + if (attackDir == 3) xt = (x + r) >> 4; + + if (xt >= 0 && yt >= 0 && xt < level.w && yt < level.h) { + if (activeItem.interactOn(level.getTile(xt, yt), level, xt, yt, this, attackDir)) { + done = true; + } else { + if (level.getTile(xt, yt).interact(level, xt, yt, this, activeItem, attackDir)) { + done = true; + } + } + if (activeItem.isDepleted()) { + activeItem = null; + } + } + } + + if (done) return; + + if (activeItem == null || activeItem.canAttack()) { + attackTime = 5; + int yo = -2; + int range = 20; + if (dir == 0) hurt(x - 8, y + 4 + yo, x + 8, y + range + yo); + if (dir == 1) hurt(x - 8, y - range + yo, x + 8, y - 4 + yo); + if (dir == 3) hurt(x + 4, y - 8 + yo, x + range, y + 8 + yo); + if (dir == 2) hurt(x - range, y - 8 + yo, x - 4, y + 8 + yo); + + int xt = x >> 4; + int yt = (y + yo) >> 4; + int r = 12; + if (attackDir == 0) yt = (y + r + yo) >> 4; + if (attackDir == 1) yt = (y - r + yo) >> 4; + if (attackDir == 2) xt = (x - r) >> 4; + if (attackDir == 3) xt = (x + r) >> 4; + + if (xt >= 0 && yt >= 0 && xt < level.w && yt < level.h) { + level.getTile(xt, yt).hurt(level, xt, yt, this, random.nextInt(3) + 1, attackDir); + } + } + + } + + private boolean use(int x0, int y0, int x1, int y1) { + List entities = level.getEntities(x0, y0, x1, y1); + for (int i = 0; i < entities.size(); i++) { + Entity e = entities.get(i); + if (e != this) if (e.use(this, attackDir)) return true; + } + return false; + } + + private boolean interact(int x0, int y0, int x1, int y1) { + List entities = level.getEntities(x0, y0, x1, y1); + for (int i = 0; i < entities.size(); i++) { + Entity e = entities.get(i); + if (e != this) if (e.interact(this, activeItem, attackDir)) return true; + } + return false; + } + + private void hurt(int x0, int y0, int x1, int y1) { + List entities = level.getEntities(x0, y0, x1, y1); + for (int i = 0; i < entities.size(); i++) { + Entity e = entities.get(i); + if (e != this) e.hurt(this, getAttackDamage(e), attackDir); + } + } + + private int getAttackDamage(Entity e) { + int dmg = random.nextInt(3) + 1; + if (attackItem != null) { + dmg += attackItem.getAttackDamageBonus(e); + } + return dmg; + } + + public void render(Screen screen) { + int xt = 0; + int yt = 14; + + int flip1 = (walkDist >> 3) & 1; + int flip2 = (walkDist >> 3) & 1; + + if (dir == 1) { + xt += 2; + } + if (dir > 1) { + flip1 = 0; + flip2 = ((walkDist >> 4) & 1); + if (dir == 2) { + flip1 = 1; + } + xt += 4 + ((walkDist >> 3) & 1) * 2; + } + + int xo = x - 8; + int yo = y - 11; + if (isSwimming()) { + yo += 4; + int waterColor = Color.get(-1, -1, 115, 335); + if (tickTime / 8 % 2 == 0) { + waterColor = Color.get(-1, 335, 5, 115); + } + screen.render(xo + 0, yo + 3, 5 + 13 * 32, waterColor, 0); + screen.render(xo + 8, yo + 3, 5 + 13 * 32, waterColor, 1); + } + + if (attackTime > 0 && attackDir == 1) { + screen.render(xo + 0, yo - 4, 6 + 13 * 32, Color.get(-1, 555, 555, 555), 0); + screen.render(xo + 8, yo - 4, 6 + 13 * 32, Color.get(-1, 555, 555, 555), 1); + if (attackItem != null) { + attackItem.renderIcon(screen, xo + 4, yo - 4); + } + } + int col = Color.get(-1, 100, 220, 532); + if (hurtTime > 0) { + col = Color.get(-1, 555, 555, 555); + } + + if (activeItem instanceof FurnitureItem) { + yt += 2; + } + screen.render(xo + 8 * flip1, yo + 0, xt + yt * 32, col, flip1); + screen.render(xo + 8 - 8 * flip1, yo + 0, xt + 1 + yt * 32, col, flip1); + if (!isSwimming()) { + screen.render(xo + 8 * flip2, yo + 8, xt + (yt + 1) * 32, col, flip2); + screen.render(xo + 8 - 8 * flip2, yo + 8, xt + 1 + (yt + 1) * 32, col, flip2); + } + + if (attackTime > 0 && attackDir == 2) { + screen.render(xo - 4, yo, 7 + 13 * 32, Color.get(-1, 555, 555, 555), 1); + screen.render(xo - 4, yo + 8, 7 + 13 * 32, Color.get(-1, 555, 555, 555), 3); + if (attackItem != null) { + attackItem.renderIcon(screen, xo - 4, yo + 4); + } + } + if (attackTime > 0 && attackDir == 3) { + screen.render(xo + 8 + 4, yo, 7 + 13 * 32, Color.get(-1, 555, 555, 555), 0); + screen.render(xo + 8 + 4, yo + 8, 7 + 13 * 32, Color.get(-1, 555, 555, 555), 2); + if (attackItem != null) { + attackItem.renderIcon(screen, xo + 8 + 4, yo + 4); + } + } + if (attackTime > 0 && attackDir == 0) { + screen.render(xo + 0, yo + 8 + 4, 6 + 13 * 32, Color.get(-1, 555, 555, 555), 2); + screen.render(xo + 8, yo + 8 + 4, 6 + 13 * 32, Color.get(-1, 555, 555, 555), 3); + if (attackItem != null) { + attackItem.renderIcon(screen, xo + 4, yo + 8 + 4); + } + } + + if (activeItem instanceof FurnitureItem) { + Furniture furniture = ((FurnitureItem) activeItem).furniture; + furniture.x = x; + furniture.y = yo; + furniture.render(screen); + + } + } + + public void touchItem(ItemEntity itemEntity) { + itemEntity.take(this); + inventory.add(itemEntity.item); + } + + public boolean canSwim() { + return true; + } + + public boolean findStartPos(Level level) { + while (true) { + int x = random.nextInt(level.w); + int y = random.nextInt(level.h); + if (level.getTile(x, y) == Tile.grass) { + this.x = x * 16 + 8; + this.y = y * 16 + 8; + return true; + } + } + } + + public boolean payStamina(int cost) { + if (cost > stamina) return false; + stamina -= cost; + return true; + } + + public void changeLevel(int dir) { + game.scheduleLevelChange(dir); + } + + public int getLightRadius() { + int r = 2; + if (activeItem != null) { + if (activeItem instanceof FurnitureItem) { + int rr = ((FurnitureItem) activeItem).furniture.getLightRadius(); + if (rr > r) r = rr; + } + } + return r; + } + + protected void die() { + super.die(); + Sound.playerDeath.play(); + } + + protected void touchedBy(Entity entity) { + if (!(entity instanceof Player)) { + entity.touchedBy(this); + } + } + + protected void doHurt(int damage, int attackDir) { + if (hurtTime > 0 || invulnerableTime > 0) return; + + Sound.playerHurt.play(); + level.add(new TextParticle("" + damage, x, y, Color.get(-1, 504, 504, 504))); + health -= damage; + if (attackDir == 0) yKnockback = +6; + if (attackDir == 1) yKnockback = -6; + if (attackDir == 2) xKnockback = -6; + if (attackDir == 3) xKnockback = +6; + hurtTime = 10; + invulnerableTime = 30; + } + + public void gameWon() { + level.player.invulnerableTime = 60 * 5; + game.won(); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Slime.java b/src/com/mojang/ld22/entity/Slime.java new file mode 100644 index 0000000..926f0ff --- /dev/null +++ b/src/com/mojang/ld22/entity/Slime.java @@ -0,0 +1,97 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.resource.Resource; + +public class Slime extends Mob { + private int xa, ya; + private int jumpTime = 0; + private int lvl; + + public Slime(int lvl) { + this.lvl = lvl; + x = random.nextInt(64 * 16); + y = random.nextInt(64 * 16); + health = maxHealth = lvl * lvl * 5; + } + + public void tick() { + super.tick(); + + int speed = 1; + if (!move(xa * speed, ya * speed) || random.nextInt(40) == 0) { + if (jumpTime <= -10) { + xa = (random.nextInt(3) - 1); + ya = (random.nextInt(3) - 1); + + if (level.player != null) { + int xd = level.player.x - x; + int yd = level.player.y - y; + if (xd * xd + yd * yd < 50 * 50) { + if (xd < 0) xa = -1; + if (xd > 0) xa = +1; + if (yd < 0) ya = -1; + if (yd > 0) ya = +1; + } + + } + + if (xa != 0 || ya != 0) jumpTime = 10; + } + } + + jumpTime--; + if (jumpTime == 0) { + xa = ya = 0; + } + } + + protected void die() { + super.die(); + + int count = random.nextInt(2) + 1; + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.slime), x + random.nextInt(11) - 5, y + random.nextInt(11) - 5)); + } + + if (level.player != null) { + level.player.score += 25*lvl; + } + + } + + public void render(Screen screen) { + int xt = 0; + int yt = 18; + + int xo = x - 8; + int yo = y - 11; + + if (jumpTime > 0) { + xt += 2; + yo -= 4; + } + + int col = Color.get(-1, 10, 252, 555); + if (lvl == 2) col = Color.get(-1, 100, 522, 555); + if (lvl == 3) col = Color.get(-1, 111, 444, 555); + if (lvl == 4) col = Color.get(-1, 000, 111, 224); + + if (hurtTime > 0) { + col = Color.get(-1, 555, 555, 555); + } + + screen.render(xo + 0, yo + 0, xt + yt * 32, col, 0); + screen.render(xo + 8, yo + 0, xt + 1 + yt * 32, col, 0); + screen.render(xo + 0, yo + 8, xt + (yt + 1) * 32, col, 0); + screen.render(xo + 8, yo + 8, xt + 1 + (yt + 1) * 32, col, 0); + } + + protected void touchedBy(Entity entity) { + if (entity instanceof Player) { + entity.hurt(this, lvl, dir); + } + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Spark.java b/src/com/mojang/ld22/entity/Spark.java new file mode 100644 index 0000000..41ab255 --- /dev/null +++ b/src/com/mojang/ld22/entity/Spark.java @@ -0,0 +1,62 @@ +package com.mojang.ld22.entity; + +import java.util.List; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; + +public class Spark extends Entity { + private int lifeTime; + public double xa, ya; + public double xx, yy; + private int time; + private AirWizard owner; + + public Spark(AirWizard owner, double xa, double ya) { + this.owner = owner; + xx = this.x = owner.x; + yy = this.y = owner.y; + xr = 0; + yr = 0; + + this.xa = xa; + this.ya = ya; + + lifeTime = 60 * 10 + random.nextInt(30); + } + + public void tick() { + time++; + if (time >= lifeTime) { + remove(); + return; + } + xx += xa; + yy += ya; + x = (int) xx; + y = (int) yy; + List toHit = level.getEntities(x, y, x, y); + for (int i = 0; i < toHit.size(); i++) { + Entity e = toHit.get(i); + if (e instanceof Mob && !(e instanceof AirWizard)) { + e.hurt(owner, 1, ((Mob) e).dir ^ 1); + } + } + } + + public boolean isBlockableBy(Mob mob) { + return false; + } + + public void render(Screen screen) { + if (time >= lifeTime - 6 * 20) { + if (time / 6 % 2 == 0) return; + } + + int xt = 8; + int yt = 13; + + screen.render(x - 4, y - 4 - 2, xt + yt * 32, Color.get(-1, 555, 555, 555), random.nextInt(4)); + screen.render(x - 4, y - 4 + 2, xt + yt * 32, Color.get(-1, 000, 000, 000), random.nextInt(4)); + } +} diff --git a/src/com/mojang/ld22/entity/Workbench.java b/src/com/mojang/ld22/entity/Workbench.java new file mode 100644 index 0000000..ca3d51d --- /dev/null +++ b/src/com/mojang/ld22/entity/Workbench.java @@ -0,0 +1,20 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.crafting.Crafting; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.screen.CraftingMenu; + +public class Workbench extends Furniture { + public Workbench() { + super("Workbench"); + col = Color.get(-1, 100, 321, 431); + sprite = 4; + xr = 3; + yr = 2; + } + + public boolean use(Player player, int attackDir) { + player.game.setMenu(new CraftingMenu(Crafting.workbenchRecipes, player)); + return true; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/Zombie.java b/src/com/mojang/ld22/entity/Zombie.java new file mode 100644 index 0000000..d3e0bad --- /dev/null +++ b/src/com/mojang/ld22/entity/Zombie.java @@ -0,0 +1,103 @@ +package com.mojang.ld22.entity; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.resource.Resource; + +public class Zombie extends Mob { + private int xa, ya; + private int lvl; + private int randomWalkTime = 0; + + public Zombie(int lvl) { + this.lvl = lvl; + x = random.nextInt(64 * 16); + y = random.nextInt(64 * 16); + health = maxHealth = lvl * lvl * 10; + + } + + public void tick() { + super.tick(); + + if (level.player != null && randomWalkTime == 0) { + int xd = level.player.x - x; + int yd = level.player.y - y; + if (xd * xd + yd * yd < 50 * 50) { + xa = 0; + ya = 0; + if (xd < 0) xa = -1; + if (xd > 0) xa = +1; + if (yd < 0) ya = -1; + if (yd > 0) ya = +1; + } + } + + int speed = tickTime & 1; + if (!move(xa * speed, ya * speed) || random.nextInt(200) == 0) { + randomWalkTime = 60; + xa = (random.nextInt(3) - 1) * random.nextInt(2); + ya = (random.nextInt(3) - 1) * random.nextInt(2); + } + if (randomWalkTime > 0) randomWalkTime--; + } + + public void render(Screen screen) { + int xt = 0; + int yt = 14; + + int flip1 = (walkDist >> 3) & 1; + int flip2 = (walkDist >> 3) & 1; + + if (dir == 1) { + xt += 2; + } + if (dir > 1) { + + flip1 = 0; + flip2 = ((walkDist >> 4) & 1); + if (dir == 2) { + flip1 = 1; + } + xt += 4 + ((walkDist >> 3) & 1) * 2; + } + + int xo = x - 8; + int yo = y - 11; + + int col = Color.get(-1, 10, 252, 050); + if (lvl == 2) col = Color.get(-1, 100, 522, 050); + if (lvl == 3) col = Color.get(-1, 111, 444, 050); + if (lvl == 4) col = Color.get(-1, 000, 111, 020); + if (hurtTime > 0) { + col = Color.get(-1, 555, 555, 555); + } + + screen.render(xo + 8 * flip1, yo + 0, xt + yt * 32, col, flip1); + screen.render(xo + 8 - 8 * flip1, yo + 0, xt + 1 + yt * 32, col, flip1); + screen.render(xo + 8 * flip2, yo + 8, xt + (yt + 1) * 32, col, flip2); + screen.render(xo + 8 - 8 * flip2, yo + 8, xt + 1 + (yt + 1) * 32, col, flip2); + } + + protected void touchedBy(Entity entity) { + if (entity instanceof Player) { + entity.hurt(this, lvl + 1, dir); + } + } + + protected void die() { + super.die(); + + int count = random.nextInt(2) + 1; + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.cloth), x + random.nextInt(11) - 5, y + random.nextInt(11) - 5)); + } + + if (level.player != null) { + level.player.score += 50 * lvl; + } + + } + +} \ No newline at end of file diff --git a/src/com/mojang/ld22/entity/particle/Particle.java b/src/com/mojang/ld22/entity/particle/Particle.java new file mode 100644 index 0000000..17cb7c2 --- /dev/null +++ b/src/com/mojang/ld22/entity/particle/Particle.java @@ -0,0 +1,11 @@ +package com.mojang.ld22.entity.particle; + +import com.mojang.ld22.entity.Entity; + +public class Particle extends Entity { + public Particle() { + } + + public void tick() { + } +} diff --git a/src/com/mojang/ld22/entity/particle/SmashParticle.java b/src/com/mojang/ld22/entity/particle/SmashParticle.java new file mode 100644 index 0000000..30b6a30 --- /dev/null +++ b/src/com/mojang/ld22/entity/particle/SmashParticle.java @@ -0,0 +1,31 @@ +package com.mojang.ld22.entity.particle; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.sound.Sound; + +public class SmashParticle extends Entity { + private int time = 0; + + public SmashParticle(int x, int y) { + this.x = x; + this.y = y; + Sound.monsterHurt.play(); + } + + public void tick() { + time++; + if (time > 10) { + remove(); + } + } + + public void render(Screen screen) { + int col = Color.get(-1, 555, 555, 555); + screen.render(x - 8, y - 8, 5 + 12 * 32, col, 2); + screen.render(x - 0, y - 8, 5 + 12 * 32, col, 3); + screen.render(x - 8, y - 0, 5 + 12 * 32, col, 0); + screen.render(x - 0, y - 0, 5 + 12 * 32, col, 1); + } +} diff --git a/src/com/mojang/ld22/entity/particle/TextParticle.java b/src/com/mojang/ld22/entity/particle/TextParticle.java new file mode 100644 index 0000000..2127edd --- /dev/null +++ b/src/com/mojang/ld22/entity/particle/TextParticle.java @@ -0,0 +1,53 @@ +package com.mojang.ld22.entity.particle; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; + +public class TextParticle extends Entity { + private String msg; + private int col; + private int time = 0; + public double xa, ya, za; + public double xx, yy, zz; + + public TextParticle(String msg, int x, int y, int col) { + this.msg = msg; + this.x = x; + this.y = y; + this.col = col; + xx = x; + yy = y; + zz = 2; + xa = random.nextGaussian() * 0.3; + ya = random.nextGaussian() * 0.2; + za = random.nextFloat() * 0.7 + 2; + } + + public void tick() { + time++; + if (time > 60) { + remove(); + } + xx += xa; + yy += ya; + zz += za; + if (zz < 0) { + zz = 0; + za *= -0.5; + xa *= 0.6; + ya *= 0.6; + } + za -= 0.15; + x = (int) xx; + y = (int) yy; + } + + public void render(Screen screen) { +// Font.draw(msg, screen, x - msg.length() * 4, y, Color.get(-1, 0, 0, 0)); + Font.draw(msg, screen, x - msg.length() * 4 + 1, y - (int) (zz) + 1, Color.get(-1, 0, 0, 0)); + Font.draw(msg, screen, x - msg.length() * 4, y - (int) (zz), col); + } + +} diff --git a/src/com/mojang/ld22/gfx/Color.java b/src/com/mojang/ld22/gfx/Color.java new file mode 100644 index 0000000..56c7f25 --- /dev/null +++ b/src/com/mojang/ld22/gfx/Color.java @@ -0,0 +1,17 @@ +package com.mojang.ld22.gfx; + +public class Color { + + public static int get(int a, int b, int c, int d) { + return (get(d) << 24) + (get(c) << 16) + (get(b) << 8) + (get(a)); + } + + public static int get(int d) { + if (d < 0) return 255; + int r = d / 100 % 10; + int g = d / 10 % 10; + int b = d % 10; + return r * 36 + g * 6 + b; + } + +} \ No newline at end of file diff --git a/src/com/mojang/ld22/gfx/Font.java b/src/com/mojang/ld22/gfx/Font.java new file mode 100644 index 0000000..5f117f6 --- /dev/null +++ b/src/com/mojang/ld22/gfx/Font.java @@ -0,0 +1,46 @@ +package com.mojang.ld22.gfx; + +public class Font { + private static String chars = "" + // + "ABCDEFGHIJKLMNOPQRSTUVWXYZ " + // + "0123456789.,!?'\"-+=/\\%()<>:; " + // + ""; + + public static void draw(String msg, Screen screen, int x, int y, int col) { + msg = msg.toUpperCase(); + for (int i = 0; i < msg.length(); i++) { + int ix = chars.indexOf(msg.charAt(i)); + if (ix >= 0) { + screen.render(x + i * 8, y, ix + 30 * 32, col, 0); + } + } + } + + public static void renderFrame(Screen screen, String title, int x0, int y0, int x1, int y1) { + for (int y = y0; y <= y1; y++) { + for (int x = x0; x <= x1; x++) { + if (x == x0 && y == y0) + screen.render(x * 8, y * 8, 0 + 13 * 32, Color.get(-1, 1, 5, 445), 0); + else if (x == x1 && y == y0) + screen.render(x * 8, y * 8, 0 + 13 * 32, Color.get(-1, 1, 5, 445), 1); + else if (x == x0 && y == y1) + screen.render(x * 8, y * 8, 0 + 13 * 32, Color.get(-1, 1, 5, 445), 2); + else if (x == x1 && y == y1) + screen.render(x * 8, y * 8, 0 + 13 * 32, Color.get(-1, 1, 5, 445), 3); + else if (y == y0) + screen.render(x * 8, y * 8, 1 + 13 * 32, Color.get(-1, 1, 5, 445), 0); + else if (y == y1) + screen.render(x * 8, y * 8, 1 + 13 * 32, Color.get(-1, 1, 5, 445), 2); + else if (x == x0) + screen.render(x * 8, y * 8, 2 + 13 * 32, Color.get(-1, 1, 5, 445), 0); + else if (x == x1) + screen.render(x * 8, y * 8, 2 + 13 * 32, Color.get(-1, 1, 5, 445), 1); + else + screen.render(x * 8, y * 8, 2 + 13 * 32, Color.get(5, 5, 5, 5), 1); + } + } + + draw(title, screen, x0 * 8 + 8, y0 * 8, Color.get(5, 5, 5, 550)); + + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/gfx/Screen.java b/src/com/mojang/ld22/gfx/Screen.java new file mode 100644 index 0000000..cbe6901 --- /dev/null +++ b/src/com/mojang/ld22/gfx/Screen.java @@ -0,0 +1,122 @@ +package com.mojang.ld22.gfx; + +public class Screen { + /* + * public static final int MAP_WIDTH = 64; // Must be 2^x public static final int MAP_WIDTH_MASK = MAP_WIDTH - 1; + * + * public int[] tiles = new int[MAP_WIDTH * MAP_WIDTH]; public int[] colors = new int[MAP_WIDTH * MAP_WIDTH]; public int[] databits = new int[MAP_WIDTH * MAP_WIDTH]; + */ + public int xOffset; + public int yOffset; + + public static final int BIT_MIRROR_X = 0x01; + public static final int BIT_MIRROR_Y = 0x02; + + public final int w, h; + public int[] pixels; + + private SpriteSheet sheet; + + public Screen(int w, int h, SpriteSheet sheet) { + this.sheet = sheet; + this.w = w; + this.h = h; + + pixels = new int[w * h]; + + // Random random = new Random(); + + /* + * for (int i = 0; i < MAP_WIDTH * MAP_WIDTH; i++) { colors[i] = Color.get(00, 40, 50, 40); tiles[i] = 0; + * + * if (random.nextInt(40) == 0) { tiles[i] = 32; colors[i] = Color.get(111, 40, 222, 333); databits[i] = random.nextInt(2); } else if (random.nextInt(40) == 0) { tiles[i] = 33; colors[i] = Color.get(20, 40, 30, 550); } else { tiles[i] = random.nextInt(4); databits[i] = random.nextInt(4); + * + * } } + * + * Font.setMap("Testing the 0341879123", this, 0, 0, Color.get(0, 555, 555, 555)); + */ + } + + public void clear(int color) { + for (int i = 0; i < pixels.length; i++) + pixels[i] = color; + } + + /* + * public void renderBackground() { for (int yt = yScroll >> 3; yt <= (yScroll + h) >> 3; yt++) { int yp = yt * 8 - yScroll; for (int xt = xScroll >> 3; xt <= (xScroll + w) >> 3; xt++) { int xp = xt * 8 - xScroll; int ti = (xt & (MAP_WIDTH_MASK)) + (yt & (MAP_WIDTH_MASK)) * MAP_WIDTH; render(xp, yp, tiles[ti], colors[ti], databits[ti]); } } + * + * for (int i = 0; i < sprites.size(); i++) { Sprite s = sprites.get(i); render(s.x, s.y, s.img, s.col, s.bits); } sprites.clear(); } + */ + + public void render(int xp, int yp, int tile, int colors, int bits) { + xp -= xOffset; + yp -= yOffset; + boolean mirrorX = (bits & BIT_MIRROR_X) > 0; + boolean mirrorY = (bits & BIT_MIRROR_Y) > 0; + + int xTile = tile % 32; + int yTile = tile / 32; + int toffs = xTile * 8 + yTile * 8 * sheet.width; + + for (int y = 0; y < 8; y++) { + int ys = y; + if (mirrorY) ys = 7 - y; + if (y + yp < 0 || y + yp >= h) continue; + for (int x = 0; x < 8; x++) { + if (x + xp < 0 || x + xp >= w) continue; + + int xs = x; + if (mirrorX) xs = 7 - x; + int col = (colors >> (sheet.pixels[xs + ys * sheet.width + toffs] * 8)) & 255; + if (col < 255) pixels[(x + xp) + (y + yp) * w] = col; + } + } + } + + public void setOffset(int xOffset, int yOffset) { + this.xOffset = xOffset; + this.yOffset = yOffset; + } + + private int[] dither = new int[] { 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5, }; + + public void overlay(Screen screen2, int xa, int ya) { + int[] oPixels = screen2.pixels; + int i = 0; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + if (oPixels[i] / 10 <= dither[((x + xa) & 3) + ((y + ya) & 3) * 4]) pixels[i] = 0; + i++; + } + + } + } + + public void renderLight(int x, int y, int r) { + x -= xOffset; + y -= yOffset; + int x0 = x - r; + int x1 = x + r; + int y0 = y - r; + int y1 = y + r; + + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 > w) x1 = w; + if (y1 > h) y1 = h; + // System.out.println(x0 + ", " + x1 + " -> " + y0 + ", " + y1); + for (int yy = y0; yy < y1; yy++) { + int yd = yy - y; + yd = yd * yd; + for (int xx = x0; xx < x1; xx++) { + int xd = xx - x; + int dist = xd * xd + yd; + // System.out.println(dist); + if (dist <= r * r) { + int br = 255 - dist * 255 / (r * r); + if (pixels[xx + yy * w] < br) pixels[xx + yy * w] = br; + } + } + } + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/gfx/Sprite.java b/src/com/mojang/ld22/gfx/Sprite.java new file mode 100644 index 0000000..02ce33f --- /dev/null +++ b/src/com/mojang/ld22/gfx/Sprite.java @@ -0,0 +1,16 @@ +package com.mojang.ld22.gfx; + +public class Sprite { + public int x, y; + public int img; + public int col; + public int bits; + + public Sprite(int x, int y, int img, int col, int bits) { + this.x = x; + this.y = y; + this.img = img; + this.col = col; + this.bits = bits; + } +} diff --git a/src/com/mojang/ld22/gfx/SpriteSheet.java b/src/com/mojang/ld22/gfx/SpriteSheet.java new file mode 100644 index 0000000..b72ebd9 --- /dev/null +++ b/src/com/mojang/ld22/gfx/SpriteSheet.java @@ -0,0 +1,17 @@ +package com.mojang.ld22.gfx; + +import java.awt.image.BufferedImage; + +public class SpriteSheet { + public int width, height; + public int[] pixels; + + public SpriteSheet(BufferedImage image) { + width = image.getWidth(); + height = image.getHeight(); + pixels = image.getRGB(0, 0, width, height, null, 0, width); + for (int i = 0; i < pixels.length; i++) { + pixels[i] = (pixels[i] & 0xff) / 64; + } + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/item/FurnitureItem.java b/src/com/mojang/ld22/item/FurnitureItem.java new file mode 100644 index 0000000..fc9d196 --- /dev/null +++ b/src/com/mojang/ld22/item/FurnitureItem.java @@ -0,0 +1,62 @@ +package com.mojang.ld22.item; + +import com.mojang.ld22.entity.Furniture; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; + +public class FurnitureItem extends Item { + public Furniture furniture; + public boolean placed = false; + + public FurnitureItem(Furniture furniture) { + this.furniture = furniture; + } + + public int getColor() { + return furniture.col; + } + + public int getSprite() { + return furniture.sprite + 10 * 32; + } + + public void renderIcon(Screen screen, int x, int y) { + screen.render(x, y, getSprite(), getColor(), 0); + } + + public void renderInventory(Screen screen, int x, int y) { + screen.render(x, y, getSprite(), getColor(), 0); + Font.draw(furniture.name, screen, x + 8, y, Color.get(-1, 555, 555, 555)); + } + + public void onTake(ItemEntity itemEntity) { + } + + public boolean canAttack() { + return false; + } + + public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, int attackDir) { + if (tile.mayPass(level, xt, yt, furniture)) { + furniture.x = xt * 16 + 8; + furniture.y = yt * 16 + 8; + level.add(furniture); + placed = true; + return true; + } + return false; + } + + public boolean isDepleted() { + return placed; + } + + public String getName() { + return furniture.name; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/item/Item.java b/src/com/mojang/ld22/item/Item.java new file mode 100644 index 0000000..e51fd1b --- /dev/null +++ b/src/com/mojang/ld22/item/Item.java @@ -0,0 +1,56 @@ +package com.mojang.ld22.item; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; +import com.mojang.ld22.screen.ListItem; + +public class Item implements ListItem { + public int getColor() { + return 0; + } + + public int getSprite() { + return 0; + } + + public void onTake(ItemEntity itemEntity) { + } + + public void renderInventory(Screen screen, int x, int y) { + } + + public boolean interact(Player player, Entity entity, int attackDir) { + return false; + } + + public void renderIcon(Screen screen, int x, int y) { + } + + public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, int attackDir) { + return false; + } + + public boolean isDepleted() { + return false; + } + + public boolean canAttack() { + return false; + } + + public int getAttackDamageBonus(Entity e) { + return 0; + } + + public String getName() { + return ""; + } + + public boolean matches(Item item) { + return item.getClass() == getClass(); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/item/PowerGloveItem.java b/src/com/mojang/ld22/item/PowerGloveItem.java new file mode 100644 index 0000000..b820af2 --- /dev/null +++ b/src/com/mojang/ld22/item/PowerGloveItem.java @@ -0,0 +1,40 @@ +package com.mojang.ld22.item; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.Furniture; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; + +public class PowerGloveItem extends Item { + public int getColor() { + return Color.get(-1, 100, 320, 430); + } + + public int getSprite() { + return 7 + 4 * 32; + } + + public void renderIcon(Screen screen, int x, int y) { + screen.render(x, y, getSprite(), getColor(), 0); + } + + public void renderInventory(Screen screen, int x, int y) { + screen.render(x, y, getSprite(), getColor(), 0); + Font.draw(getName(), screen, x + 8, y, Color.get(-1, 555, 555, 555)); + } + + public String getName() { + return "Pow glove"; + } + + public boolean interact(Player player, Entity entity, int attackDir) { + if (entity instanceof Furniture) { + Furniture f = (Furniture) entity; + f.take(player); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/item/ResourceItem.java b/src/com/mojang/ld22/item/ResourceItem.java new file mode 100644 index 0000000..d8f32cf --- /dev/null +++ b/src/com/mojang/ld22/item/ResourceItem.java @@ -0,0 +1,64 @@ +package com.mojang.ld22.item; + +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; + +public class ResourceItem extends Item { + public Resource resource; + public int count = 1; + + public ResourceItem(Resource resource) { + this.resource = resource; + } + + public ResourceItem(Resource resource, int count) { + this.resource = resource; + this.count = count; + } + + public int getColor() { + return resource.color; + } + + public int getSprite() { + return resource.sprite; + } + + public void renderIcon(Screen screen, int x, int y) { + screen.render(x, y, resource.sprite, resource.color, 0); + } + + public void renderInventory(Screen screen, int x, int y) { + screen.render(x, y, resource.sprite, resource.color, 0); + Font.draw(resource.name, screen, x + 32, y, Color.get(-1, 555, 555, 555)); + int cc = count; + if (cc > 999) cc = 999; + Font.draw("" + cc, screen, x + 8, y, Color.get(-1, 444, 444, 444)); + } + + public String getName() { + return resource.name; + } + + public void onTake(ItemEntity itemEntity) { + } + + public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, int attackDir) { + if (resource.interactOn(tile, level, xt, yt, player, attackDir)) { + count--; + return true; + } + return false; + } + + public boolean isDepleted() { + return count <= 0; + } + +} \ No newline at end of file diff --git a/src/com/mojang/ld22/item/ToolItem.java b/src/com/mojang/ld22/item/ToolItem.java new file mode 100644 index 0000000..5772ab9 --- /dev/null +++ b/src/com/mojang/ld22/item/ToolItem.java @@ -0,0 +1,82 @@ +package com.mojang.ld22.item; + +import java.util.Random; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; + +public class ToolItem extends Item { + private Random random = new Random(); + + public static final int MAX_LEVEL = 5; + public static final String[] LEVEL_NAMES = { // + "Wood", "Rock", "Iron", "Gold", "Gem"// + }; + + public static final int[] LEVEL_COLORS = {// + Color.get(-1, 100, 321, 431),// + Color.get(-1, 100, 321, 111),// + Color.get(-1, 100, 321, 555),// + Color.get(-1, 100, 321, 550),// + Color.get(-1, 100, 321, 055),// + }; + + public ToolType type; + public int level = 0; + + public ToolItem(ToolType type, int level) { + this.type = type; + this.level = level; + } + + public int getColor() { + return LEVEL_COLORS[level]; + } + + public int getSprite() { + return type.sprite + 5 * 32; + } + + public void renderIcon(Screen screen, int x, int y) { + screen.render(x, y, getSprite(), getColor(), 0); + } + + public void renderInventory(Screen screen, int x, int y) { + screen.render(x, y, getSprite(), getColor(), 0); + Font.draw(getName(), screen, x + 8, y, Color.get(-1, 555, 555, 555)); + } + + public String getName() { + return LEVEL_NAMES[level] + " " + type.name; + } + + public void onTake(ItemEntity itemEntity) { + } + + public boolean canAttack() { + return true; + } + + public int getAttackDamageBonus(Entity e) { + if (type == ToolType.axe) { + return (level + 1) * 2 + random.nextInt(4); + } + if (type == ToolType.sword) { + return (level + 1) * 3 + random.nextInt(2 + level * level * 2); + } + return 1; + } + + public boolean matches(Item item) { + if (item instanceof ToolItem) { + ToolItem other = (ToolItem) item; + if (other.type != type) return false; + if (other.level != level) return false; + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/item/ToolType.java b/src/com/mojang/ld22/item/ToolType.java new file mode 100644 index 0000000..21771ba --- /dev/null +++ b/src/com/mojang/ld22/item/ToolType.java @@ -0,0 +1,17 @@ +package com.mojang.ld22.item; + +public class ToolType { + public static ToolType shovel = new ToolType("Shvl", 0); + public static ToolType hoe = new ToolType("Hoe", 1); + public static ToolType sword = new ToolType("Swrd", 2); + public static ToolType pickaxe = new ToolType("Pick", 3); + public static ToolType axe = new ToolType("Axe", 4); + + public final String name; + public final int sprite; + + private ToolType(String name, int sprite) { + this.name = name; + this.sprite = sprite; + } +} diff --git a/src/com/mojang/ld22/item/resource/FoodResource.java b/src/com/mojang/ld22/item/resource/FoodResource.java new file mode 100644 index 0000000..5044e4c --- /dev/null +++ b/src/com/mojang/ld22/item/resource/FoodResource.java @@ -0,0 +1,24 @@ +package com.mojang.ld22.item.resource; + +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; + +public class FoodResource extends Resource { + private int heal; + private int staminaCost; + + public FoodResource(String name, int sprite, int color, int heal, int staminaCost) { + super(name, sprite, color); + this.heal = heal; + this.staminaCost = staminaCost; + } + + public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, int attackDir) { + if (player.health < player.maxHealth && player.payStamina(staminaCost)) { + player.heal(heal); + return true; + } + return false; + } +} diff --git a/src/com/mojang/ld22/item/resource/PlantableResource.java b/src/com/mojang/ld22/item/resource/PlantableResource.java new file mode 100644 index 0000000..d1944e4 --- /dev/null +++ b/src/com/mojang/ld22/item/resource/PlantableResource.java @@ -0,0 +1,31 @@ +package com.mojang.ld22.item.resource; + +import java.util.Arrays; +import java.util.List; + +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; + +public class PlantableResource extends Resource { + private List sourceTiles; + private Tile targetTile; + + public PlantableResource(String name, int sprite, int color, Tile targetTile, Tile... sourceTiles1) { + this(name, sprite, color, targetTile, Arrays.asList(sourceTiles1)); + } + + public PlantableResource(String name, int sprite, int color, Tile targetTile, List sourceTiles) { + super(name, sprite, color); + this.sourceTiles = sourceTiles; + this.targetTile = targetTile; + } + + public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, int attackDir) { + if (sourceTiles.contains(tile)) { + level.setTile(xt, yt, targetTile, 0); + return true; + } + return false; + } +} diff --git a/src/com/mojang/ld22/item/resource/Resource.java b/src/com/mojang/ld22/item/resource/Resource.java new file mode 100644 index 0000000..eb3d8c0 --- /dev/null +++ b/src/com/mojang/ld22/item/resource/Resource.java @@ -0,0 +1,47 @@ +package com.mojang.ld22.item.resource; + +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.level.tile.Tile; + +public class Resource { + public static Resource wood = new Resource("Wood", 1 + 4 * 32, Color.get(-1, 200, 531, 430)); + public static Resource stone = new Resource("Stone", 2 + 4 * 32, Color.get(-1, 111, 333, 555)); + public static Resource flower = new PlantableResource("Flower", 0 + 4 * 32, Color.get(-1, 10, 444, 330), Tile.flower, Tile.grass); + public static Resource acorn = new PlantableResource("Acorn", 3 + 4 * 32, Color.get(-1, 100, 531, 320), Tile.treeSapling, Tile.grass); + public static Resource dirt = new PlantableResource("Dirt", 2 + 4 * 32, Color.get(-1, 100, 322, 432), Tile.dirt, Tile.hole, Tile.water, Tile.lava); + public static Resource sand = new PlantableResource("Sand", 2 + 4 * 32, Color.get(-1, 110, 440, 550), Tile.sand, Tile.grass, Tile.dirt); + public static Resource cactusFlower = new PlantableResource("Cactus", 4 + 4 * 32, Color.get(-1, 10, 40, 50), Tile.cactusSapling, Tile.sand); + public static Resource seeds = new PlantableResource("Seeds", 5 + 4 * 32, Color.get(-1, 10, 40, 50), Tile.wheat, Tile.farmland); + public static Resource wheat = new Resource("Wheat", 6 + 4 * 32, Color.get(-1, 110, 330, 550)); + public static Resource bread = new FoodResource("Bread", 8 + 4 * 32, Color.get(-1, 110, 330, 550), 2, 5); + public static Resource apple = new FoodResource("Apple", 9 + 4 * 32, Color.get(-1, 100, 300, 500), 1, 5); + + public static Resource coal = new Resource("COAL", 10 + 4 * 32, Color.get(-1, 000, 111, 111)); + public static Resource ironOre = new Resource("I.ORE", 10 + 4 * 32, Color.get(-1, 100, 322, 544)); + public static Resource goldOre = new Resource("G.ORE", 10 + 4 * 32, Color.get(-1, 110, 440, 553)); + public static Resource ironIngot = new Resource("IRON", 11 + 4 * 32, Color.get(-1, 100, 322, 544)); + public static Resource goldIngot = new Resource("GOLD", 11 + 4 * 32, Color.get(-1, 110, 330, 553)); + + public static Resource slime = new Resource("SLIME", 10 + 4 * 32, Color.get(-1, 10, 30, 50)); + public static Resource glass = new Resource("glass", 12 + 4 * 32, Color.get(-1, 555, 555, 555)); + public static Resource cloth = new Resource("cloth", 1 + 4 * 32, Color.get(-1, 25, 252, 141)); + public static Resource cloud = new PlantableResource("cloud", 2 + 4 * 32, Color.get(-1, 222, 555, 444), Tile.cloud, Tile.infiniteFall); + public static Resource gem = new Resource("gem", 13 + 4 * 32, Color.get(-1, 101, 404, 545)); + + public final String name; + public final int sprite; + public final int color; + + public Resource(String name, int sprite, int color) { + if (name.length() > 6) throw new RuntimeException("Name cannot be longer than six characters!"); + this.name = name; + this.sprite = sprite; + this.color = color; + } + + public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, int attackDir) { + return false; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/level/Level.java b/src/com/mojang/ld22/level/Level.java new file mode 100644 index 0000000..8c4669e --- /dev/null +++ b/src/com/mojang/ld22/level/Level.java @@ -0,0 +1,309 @@ +package com.mojang.ld22.level; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Random; + +import com.mojang.ld22.entity.AirWizard; +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.entity.Slime; +import com.mojang.ld22.entity.Zombie; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.levelgen.LevelGen; +import com.mojang.ld22.level.tile.Tile; + +public class Level { + private Random random = new Random(); + + public int w, h; + + public byte[] tiles; + public byte[] data; + public List[] entitiesInTiles; + + public int grassColor = 141; + public int dirtColor = 322; + public int sandColor = 550; + private int depth; + public int monsterDensity = 8; + + public List entities = new ArrayList(); + private Comparator spriteSorter = new Comparator() { + public int compare(Entity e0, Entity e1) { + if (e1.y < e0.y) return +1; + if (e1.y > e0.y) return -1; + return 0; + } + + }; + + @SuppressWarnings("unchecked") + public Level(int w, int h, int level, Level parentLevel) { + if (level < 0) { + dirtColor = 222; + } + this.depth = level; + this.w = w; + this.h = h; + byte[][] maps; + + if (level == 1) { + dirtColor = 444; + } + if (level == 0) + maps = LevelGen.createAndValidateTopMap(w, h); + else if (level < 0) { + maps = LevelGen.createAndValidateUndergroundMap(w, h, -level); + monsterDensity = 4; + } else { + maps = LevelGen.createAndValidateSkyMap(w, h); // Sky level + monsterDensity = 4; + } + + tiles = maps[0]; + data = maps[1]; + + if (parentLevel != null) { + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) { + if (parentLevel.getTile(x, y) == Tile.stairsDown) { + + setTile(x, y, Tile.stairsUp, 0); + if (level == 0) { + setTile(x - 1, y, Tile.hardRock, 0); + setTile(x + 1, y, Tile.hardRock, 0); + setTile(x, y - 1, Tile.hardRock, 0); + setTile(x, y + 1, Tile.hardRock, 0); + setTile(x - 1, y - 1, Tile.hardRock, 0); + setTile(x - 1, y + 1, Tile.hardRock, 0); + setTile(x + 1, y - 1, Tile.hardRock, 0); + setTile(x + 1, y + 1, Tile.hardRock, 0); + } else { + setTile(x - 1, y, Tile.dirt, 0); + setTile(x + 1, y, Tile.dirt, 0); + setTile(x, y - 1, Tile.dirt, 0); + setTile(x, y + 1, Tile.dirt, 0); + setTile(x - 1, y - 1, Tile.dirt, 0); + setTile(x - 1, y + 1, Tile.dirt, 0); + setTile(x + 1, y - 1, Tile.dirt, 0); + setTile(x + 1, y + 1, Tile.dirt, 0); + } + } + + } + } + + entitiesInTiles = new ArrayList[w * h]; + for (int i = 0; i < w * h; i++) { + entitiesInTiles[i] = new ArrayList(); + } + + if (level==1) { + AirWizard aw = new AirWizard(); + aw.x = w*8; + aw.y = h*8; + add(aw); + } + } + + public void renderBackground(Screen screen, int xScroll, int yScroll) { + int xo = xScroll >> 4; + int yo = yScroll >> 4; + int w = (screen.w + 15) >> 4; + int h = (screen.h + 15) >> 4; + screen.setOffset(xScroll, yScroll); + for (int y = yo; y <= h + yo; y++) { + for (int x = xo; x <= w + xo; x++) { + getTile(x, y).render(screen, this, x, y); + } + } + screen.setOffset(0, 0); + } + + private List rowSprites = new ArrayList(); + + public Player player; + + public void renderSprites(Screen screen, int xScroll, int yScroll) { + int xo = xScroll >> 4; + int yo = yScroll >> 4; + int w = (screen.w + 15) >> 4; + int h = (screen.h + 15) >> 4; + + screen.setOffset(xScroll, yScroll); + for (int y = yo; y <= h + yo; y++) { + for (int x = xo; x <= w + xo; x++) { + if (x < 0 || y < 0 || x >= this.w || y >= this.h) continue; + rowSprites.addAll(entitiesInTiles[x + y * this.w]); + } + if (rowSprites.size() > 0) { + sortAndRender(screen, rowSprites); + } + rowSprites.clear(); + } + screen.setOffset(0, 0); + } + + public void renderLight(Screen screen, int xScroll, int yScroll) { + 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 = 4; + 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; + List entities = entitiesInTiles[x + y * this.w]; + for (int i = 0; i < entities.size(); i++) { + Entity e = entities.get(i); + // e.render(screen); + int lr = e.getLightRadius(); + if (lr > 0) screen.renderLight(e.x - 1, e.y - 4, lr * 8); + } + int lr = getTile(x, y).getLightRadius(this, x, y); + if (lr > 0) screen.renderLight(x * 16 + 8, y * 16 + 8, lr * 8); + } + } + screen.setOffset(0, 0); + } + + // private void renderLight(Screen screen, int x, int y, int r) { + // screen.renderLight(x, y, r); + // } + + private void sortAndRender(Screen screen, List list) { + Collections.sort(list, spriteSorter); + for (int i = 0; i < list.size(); i++) { + list.get(i).render(screen); + } + } + + public Tile getTile(int x, int y) { + if (x < 0 || y < 0 || x >= w || y >= h) return Tile.rock; + return Tile.tiles[tiles[x + y * w]]; + } + + public void setTile(int x, int y, Tile t, int dataVal) { + if (x < 0 || y < 0 || x >= w || y >= h) return; + tiles[x + y * w] = t.id; + data[x + y * w] = (byte) dataVal; + } + + public int getData(int x, int y) { + if (x < 0 || y < 0 || x >= w || y >= h) return 0; + return data[x + y * w] & 0xff; + } + + public void setData(int x, int y, int val) { + if (x < 0 || y < 0 || x >= w || y >= h) return; + data[x + y * w] = (byte) val; + } + + public void add(Entity entity) { + if (entity instanceof Player) { + player = (Player) entity; + } + entity.removed = false; + entities.add(entity); + entity.init(this); + + insertEntity(entity.x >> 4, entity.y >> 4, entity); + } + + public void remove(Entity e) { + entities.remove(e); + int xto = e.x >> 4; + int yto = e.y >> 4; + removeEntity(xto, yto, e); + } + + private void insertEntity(int x, int y, Entity e) { + if (x < 0 || y < 0 || x >= w || y >= h) return; + entitiesInTiles[x + y * w].add(e); + } + + private void removeEntity(int x, int y, Entity e) { + if (x < 0 || y < 0 || x >= w || y >= h) return; + entitiesInTiles[x + y * w].remove(e); + } + + public void trySpawn(int count) { + for (int i = 0; i < count; i++) { + Mob mob; + + int minLevel = 1; + int maxLevel = 1; + if (depth < 0) { + maxLevel = (-depth) + 1; + } + if (depth > 0) { + minLevel = maxLevel = 4; + } + + int lvl = random.nextInt(maxLevel - minLevel + 1) + minLevel; + if (random.nextInt(2) == 0) + mob = new Slime(lvl); + else + mob = new Zombie(lvl); + + if (mob.findStartPos(this)) { + this.add(mob); + } + } + } + + public void tick() { + trySpawn(1); + + for (int i = 0; i < w * h / 50; i++) { + int xt = random.nextInt(w); + int yt = random.nextInt(w); + getTile(xt, yt).tick(this, xt, yt); + } + for (int i = 0; i < entities.size(); i++) { + Entity e = entities.get(i); + int xto = e.x >> 4; + int yto = e.y >> 4; + + e.tick(); + + if (e.removed) { + entities.remove(i--); + removeEntity(xto, yto, e); + } else { + int xt = e.x >> 4; + int yt = e.y >> 4; + + if (xto != xt || yto != yt) { + removeEntity(xto, yto, e); + insertEntity(xt, yt, e); + } + } + } + } + + public List getEntities(int x0, int y0, int x1, int y1) { + List result = new ArrayList(); + int xt0 = (x0 >> 4) - 1; + int yt0 = (y0 >> 4) - 1; + int xt1 = (x1 >> 4) + 1; + int yt1 = (y1 >> 4) + 1; + for (int y = yt0; y <= yt1; y++) { + for (int x = xt0; x <= xt1; x++) { + if (x < 0 || y < 0 || x >= w || y >= h) continue; + List entities = entitiesInTiles[x + y * this.w]; + for (int i = 0; i < entities.size(); i++) { + Entity e = entities.get(i); + if (e.intersects(x0, y0, x1, y1)) result.add(e); + } + } + } + return result; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/level/levelgen/LevelGen.java b/src/com/mojang/ld22/level/levelgen/LevelGen.java new file mode 100644 index 0000000..8044e99 --- /dev/null +++ b/src/com/mojang/ld22/level/levelgen/LevelGen.java @@ -0,0 +1,437 @@ +package com.mojang.ld22.level.levelgen; + +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.util.Random; + +import javax.swing.ImageIcon; +import javax.swing.JOptionPane; + +import com.mojang.ld22.level.tile.Tile; + +public class LevelGen { + private static final Random random = new Random(); + public double[] values; + private int w, h; + + public LevelGen(int w, int h, int featureSize) { + this.w = w; + this.h = h; + + values = new double[w * h]; + + for (int y = 0; y < w; y += featureSize) { + for (int x = 0; x < w; x += featureSize) { + setSample(x, y, random.nextFloat() * 2 - 1); + } + } + + int stepSize = featureSize; + double scale = 1.0 / w; + double scaleMod = 1; + do { + int halfStep = stepSize / 2; + for (int y = 0; y < w; y += stepSize) { + for (int x = 0; x < w; x += stepSize) { + double a = sample(x, y); + double b = sample(x + stepSize, y); + double c = sample(x, y + stepSize); + double d = sample(x + stepSize, y + stepSize); + + double e = (a + b + c + d) / 4.0 + (random.nextFloat() * 2 - 1) * stepSize * scale; + setSample(x + halfStep, y + halfStep, e); + } + } + for (int y = 0; y < w; y += stepSize) { + for (int x = 0; x < w; x += stepSize) { + double a = sample(x, y); + double b = sample(x + stepSize, y); + double c = sample(x, y + stepSize); + double d = sample(x + halfStep, y + halfStep); + double e = sample(x + halfStep, y - halfStep); + double f = sample(x - halfStep, y + halfStep); + + double H = (a + b + d + e) / 4.0 + (random.nextFloat() * 2 - 1) * stepSize * scale * 0.5; + double g = (a + c + d + f) / 4.0 + (random.nextFloat() * 2 - 1) * stepSize * scale * 0.5; + setSample(x + halfStep, y, H); + setSample(x, y + halfStep, g); + } + } + stepSize /= 2; + scale *= (scaleMod + 0.8); + scaleMod *= 0.3; + } while (stepSize > 1); + } + + private double sample(int x, int y) { + return values[(x & (w - 1)) + (y & (h - 1)) * w]; + } + + private void setSample(int x, int y, double value) { + values[(x & (w - 1)) + (y & (h - 1)) * w] = value; + } + + public static byte[][] createAndValidateTopMap(int w, int h) { + int attempt = 0; + do { + byte[][] result = createTopMap(w, h); + + int[] count = new int[256]; + + for (int i = 0; i < w * h; i++) { + count[result[0][i] & 0xff]++; + } + if (count[Tile.rock.id & 0xff] < 100) continue; + if (count[Tile.sand.id & 0xff] < 100) continue; + if (count[Tile.grass.id & 0xff] < 100) continue; + if (count[Tile.tree.id & 0xff] < 100) continue; + if (count[Tile.stairsDown.id & 0xff] < 2) continue; + + return result; + + } while (true); + } + + public static byte[][] createAndValidateUndergroundMap(int w, int h, int depth) { + int attempt = 0; + do { + byte[][] result = createUndergroundMap(w, h, depth); + + int[] count = new int[256]; + + for (int i = 0; i < w * h; i++) { + count[result[0][i] & 0xff]++; + } + if (count[Tile.rock.id & 0xff] < 100) continue; + if (count[Tile.dirt.id & 0xff] < 100) continue; + if (count[(Tile.ironOre.id & 0xff) + depth - 1] < 20) continue; + if (depth < 3) if (count[Tile.stairsDown.id & 0xff] < 2) continue; + + return result; + + } while (true); + } + + public static byte[][] createAndValidateSkyMap(int w, int h) { + int attempt = 0; + do { + byte[][] result = createSkyMap(w, h); + + int[] count = new int[256]; + + for (int i = 0; i < w * h; i++) { + count[result[0][i] & 0xff]++; + } + if (count[Tile.cloud.id & 0xff] < 2000) continue; + if (count[Tile.stairsDown.id & 0xff] < 2) continue; + + return result; + + } while (true); + } + + private static byte[][] createTopMap(int w, int h) { + LevelGen mnoise1 = new LevelGen(w, h, 16); + LevelGen mnoise2 = new LevelGen(w, h, 16); + LevelGen mnoise3 = new LevelGen(w, h, 16); + + LevelGen noise1 = new LevelGen(w, h, 32); + LevelGen noise2 = new LevelGen(w, h, 32); + + byte[] map = new byte[w * h]; + byte[] data = new byte[w * h]; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int i = x + y * w; + + double val = Math.abs(noise1.values[i] - noise2.values[i]) * 3 - 2; + double mval = Math.abs(mnoise1.values[i] - mnoise2.values[i]); + mval = Math.abs(mval - mnoise3.values[i]) * 3 - 2; + + double xd = x / (w - 1.0) * 2 - 1; + double yd = y / (h - 1.0) * 2 - 1; + if (xd < 0) xd = -xd; + if (yd < 0) yd = -yd; + double dist = xd >= yd ? xd : yd; + dist = dist * dist * dist * dist; + dist = dist * dist * dist * dist; + val = val + 1 - dist * 20; + + if (val < -0.5) { + map[i] = Tile.water.id; + } else if (val > 0.5 && mval < -1.5) { + map[i] = Tile.rock.id; + } else { + map[i] = Tile.grass.id; + } + } + } + + for (int i = 0; i < w * h / 2800; i++) { + int xs = random.nextInt(w); + int ys = random.nextInt(h); + for (int k = 0; k < 10; k++) { + int x = xs + random.nextInt(21) - 10; + int y = ys + random.nextInt(21) - 10; + for (int j = 0; j < 100; j++) { + int xo = x + random.nextInt(5) - random.nextInt(5); + int yo = y + random.nextInt(5) - random.nextInt(5); + for (int yy = yo - 1; yy <= yo + 1; yy++) + for (int xx = xo - 1; xx <= xo + 1; xx++) + if (xx >= 0 && yy >= 0 && xx < w && yy < h) { + if (map[xx + yy * w] == Tile.grass.id) { + map[xx + yy * w] = Tile.sand.id; + } + } + } + } + } + + /* + * for (int i = 0; i < w * h / 2800; i++) { int xs = random.nextInt(w); int ys = random.nextInt(h); for (int k = 0; k < 10; k++) { int x = xs + random.nextInt(21) - 10; int y = ys + random.nextInt(21) - 10; for (int j = 0; j < 100; j++) { int xo = x + random.nextInt(5) - random.nextInt(5); int yo = y + random.nextInt(5) - random.nextInt(5); for (int yy = yo - 1; yy <= yo + 1; yy++) for (int xx = xo - 1; xx <= xo + 1; xx++) if (xx >= 0 && yy >= 0 && xx < w && yy < h) { if (map[xx + yy * w] == Tile.grass.id) { map[xx + yy * w] = Tile.dirt.id; } } } } } + */ + + for (int i = 0; i < w * h / 400; i++) { + int x = random.nextInt(w); + int y = random.nextInt(h); + for (int j = 0; j < 200; j++) { + int xx = x + random.nextInt(15) - random.nextInt(15); + int yy = y + random.nextInt(15) - random.nextInt(15); + if (xx >= 0 && yy >= 0 && xx < w && yy < h) { + if (map[xx + yy * w] == Tile.grass.id) { + map[xx + yy * w] = Tile.tree.id; + } + } + } + } + + for (int i = 0; i < w * h / 400; i++) { + int x = random.nextInt(w); + int y = random.nextInt(h); + int col = random.nextInt(4); + for (int j = 0; j < 30; j++) { + int xx = x + random.nextInt(5) - random.nextInt(5); + int yy = y + random.nextInt(5) - random.nextInt(5); + if (xx >= 0 && yy >= 0 && xx < w && yy < h) { + if (map[xx + yy * w] == Tile.grass.id) { + map[xx + yy * w] = Tile.flower.id; + data[xx + yy * w] = (byte) (col + random.nextInt(4) * 16); + } + } + } + } + + for (int i = 0; i < w * h / 100; i++) { + int xx = random.nextInt(w); + int yy = random.nextInt(h); + if (xx >= 0 && yy >= 0 && xx < w && yy < h) { + if (map[xx + yy * w] == Tile.sand.id) { + map[xx + yy * w] = Tile.cactus.id; + } + } + } + + int count = 0; + stairsLoop: for (int i = 0; i < w * h / 100; i++) { + int x = random.nextInt(w - 2) + 1; + int y = random.nextInt(h - 2) + 1; + + for (int yy = y - 1; yy <= y + 1; yy++) + for (int xx = x - 1; xx <= x + 1; xx++) { + if (map[xx + yy * w] != Tile.rock.id) continue stairsLoop; + } + + map[x + y * w] = Tile.stairsDown.id; + count++; + if (count == 4) break; + } + + return new byte[][] { map, data }; + } + + private static byte[][] createUndergroundMap(int w, int h, int depth) { + LevelGen mnoise1 = new LevelGen(w, h, 16); + LevelGen mnoise2 = new LevelGen(w, h, 16); + LevelGen mnoise3 = new LevelGen(w, h, 16); + + LevelGen nnoise1 = new LevelGen(w, h, 16); + LevelGen nnoise2 = new LevelGen(w, h, 16); + LevelGen nnoise3 = new LevelGen(w, h, 16); + + LevelGen wnoise1 = new LevelGen(w, h, 16); + LevelGen wnoise2 = new LevelGen(w, h, 16); + LevelGen wnoise3 = new LevelGen(w, h, 16); + + LevelGen noise1 = new LevelGen(w, h, 32); + LevelGen noise2 = new LevelGen(w, h, 32); + + byte[] map = new byte[w * h]; + byte[] data = new byte[w * h]; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int i = x + y * w; + + double val = Math.abs(noise1.values[i] - noise2.values[i]) * 3 - 2; + + double mval = Math.abs(mnoise1.values[i] - mnoise2.values[i]); + mval = Math.abs(mval - mnoise3.values[i]) * 3 - 2; + + double nval = Math.abs(nnoise1.values[i] - nnoise2.values[i]); + nval = Math.abs(nval - nnoise3.values[i]) * 3 - 2; + + double wval = Math.abs(wnoise1.values[i] - wnoise2.values[i]); + wval = Math.abs(nval - wnoise3.values[i]) * 3 - 2; + + double xd = x / (w - 1.0) * 2 - 1; + double yd = y / (h - 1.0) * 2 - 1; + if (xd < 0) xd = -xd; + if (yd < 0) yd = -yd; + double dist = xd >= yd ? xd : yd; + dist = dist * dist * dist * dist; + dist = dist * dist * dist * dist; + val = val + 1 - dist * 20; + + if (val > -2 && wval < -2.0 + (depth) / 2 * 3) { + if (depth > 2) + map[i] = Tile.lava.id; + else + map[i] = Tile.water.id; + } else if (val > -2 && (mval < -1.7 || nval < -1.4)) { + map[i] = Tile.dirt.id; + } else { + map[i] = Tile.rock.id; + } + } + } + + { + int r = 2; + for (int i = 0; i < w * h / 400; i++) { + int x = random.nextInt(w); + int y = random.nextInt(h); + for (int j = 0; j < 30; j++) { + int xx = x + random.nextInt(5) - random.nextInt(5); + int yy = y + random.nextInt(5) - random.nextInt(5); + if (xx >= r && yy >= r && xx < w - r && yy < h - r) { + if (map[xx + yy * w] == Tile.rock.id) { + map[xx + yy * w] = (byte) ((Tile.ironOre.id & 0xff) + depth - 1); + } + } + } + } + } + + if (depth < 3) { + int count = 0; + stairsLoop: for (int i = 0; i < w * h / 100; i++) { + int x = random.nextInt(w - 20) + 10; + int y = random.nextInt(h - 20) + 10; + + for (int yy = y - 1; yy <= y + 1; yy++) + for (int xx = x - 1; xx <= x + 1; xx++) { + if (map[xx + yy * w] != Tile.rock.id) continue stairsLoop; + } + + map[x + y * w] = Tile.stairsDown.id; + count++; + if (count == 4) break; + } + } + + return new byte[][] { map, data }; + } + + private static byte[][] createSkyMap(int w, int h) { + LevelGen noise1 = new LevelGen(w, h, 8); + LevelGen noise2 = new LevelGen(w, h, 8); + + byte[] map = new byte[w * h]; + byte[] data = new byte[w * h]; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int i = x + y * w; + + double val = Math.abs(noise1.values[i] - noise2.values[i]) * 3 - 2; + + double xd = x / (w - 1.0) * 2 - 1; + double yd = y / (h - 1.0) * 2 - 1; + if (xd < 0) xd = -xd; + if (yd < 0) yd = -yd; + double dist = xd >= yd ? xd : yd; + dist = dist * dist * dist * dist; + dist = dist * dist * dist * dist; + val = -val * 1 - 2.2; + val = val + 1 - dist * 20; + + if (val < -0.25) { + map[i] = Tile.infiniteFall.id; + } else { + map[i] = Tile.cloud.id; + } + } + } + + stairsLoop: for (int i = 0; i < w * h / 50; i++) { + int x = random.nextInt(w - 2) + 1; + int y = random.nextInt(h - 2) + 1; + + for (int yy = y - 1; yy <= y + 1; yy++) + for (int xx = x - 1; xx <= x + 1; xx++) { + if (map[xx + yy * w] != Tile.cloud.id) continue stairsLoop; + } + + map[x + y * w] = Tile.cloudCactus.id; + } + + int count = 0; + stairsLoop: for (int i = 0; i < w * h; i++) { + int x = random.nextInt(w - 2) + 1; + int y = random.nextInt(h - 2) + 1; + + for (int yy = y - 1; yy <= y + 1; yy++) + for (int xx = x - 1; xx <= x + 1; xx++) { + if (map[xx + yy * w] != Tile.cloud.id) continue stairsLoop; + } + + map[x + y * w] = Tile.stairsDown.id; + count++; + if (count == 2) break; + } + + return new byte[][] { map, data }; + } + + public static void main(String[] args) { + int d = 0; + while (true) { + int w = 128; + int h = 128; + + byte[] map = LevelGen.createAndValidateTopMap(w, h)[0]; + // byte[] map = LevelGen.createAndValidateUndergroundMap(w, h, (d++ % 3) + 1)[0]; + // byte[] map = LevelGen.createAndValidateSkyMap(w, h)[0]; + + BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + int[] pixels = new int[w * h]; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int i = x + y * w; + + if (map[i] == Tile.water.id) pixels[i] = 0x000080; + if (map[i] == Tile.grass.id) pixels[i] = 0x208020; + if (map[i] == Tile.rock.id) pixels[i] = 0xa0a0a0; + if (map[i] == Tile.dirt.id) pixels[i] = 0x604040; + if (map[i] == Tile.sand.id) pixels[i] = 0xa0a040; + if (map[i] == Tile.tree.id) pixels[i] = 0x003000; + if (map[i] == Tile.lava.id) pixels[i] = 0xff2020; + if (map[i] == Tile.cloud.id) pixels[i] = 0xa0a0a0; + if (map[i] == Tile.stairsDown.id) pixels[i] = 0xffffff; + if (map[i] == Tile.stairsUp.id) pixels[i] = 0xffffff; + if (map[i] == Tile.cloudCactus.id) pixels[i] = 0xff00ff; + } + } + img.setRGB(0, 0, w, h, pixels, 0, w); + JOptionPane.showMessageDialog(null, null, "Another", JOptionPane.YES_NO_OPTION, new ImageIcon(img.getScaledInstance(w * 4, h * 4, Image.SCALE_AREA_AVERAGING))); + } + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/level/tile/CactusTile.java b/src/com/mojang/ld22/level/tile/CactusTile.java new file mode 100644 index 0000000..f058997 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/CactusTile.java @@ -0,0 +1,55 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.particle.SmashParticle; +import com.mojang.ld22.entity.particle.TextParticle; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class CactusTile extends Tile { + public CactusTile(int id) { + super(id); + connectsToSand = true; + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(20, 40, 50, level.sandColor); + screen.render(x * 16 + 0, y * 16 + 0, 8 + 2 * 32, col, 0); + screen.render(x * 16 + 8, y * 16 + 0, 9 + 2 * 32, col, 0); + screen.render(x * 16 + 0, y * 16 + 8, 8 + 3 * 32, col, 0); + screen.render(x * 16 + 8, y * 16 + 8, 9 + 3 * 32, col, 0); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return false; + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + int damage = level.getData(x, y) + dmg; + level.add(new SmashParticle(x * 16 + 8, y * 16 + 8)); + level.add(new TextParticle("" + dmg, x * 16 + 8, y * 16 + 8, Color.get(-1, 500, 500, 500))); + if (damage >= 10) { + int count = random.nextInt(2) + 1; + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.cactusFlower), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + level.setTile(x, y, Tile.sand, 0); + } else { + level.setData(x, y, damage); + } + } + + public void bumpedInto(Level level, int x, int y, Entity entity) { + entity.hurt(this, x, y, 1); + } + + public void tick(Level level, int xt, int yt) { + int damage = level.getData(xt, yt); + if (damage > 0) level.setData(xt, yt, damage - 1); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/level/tile/CloudCactusTile.java b/src/com/mojang/ld22/level/tile/CloudCactusTile.java new file mode 100644 index 0000000..e4b9936 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/CloudCactusTile.java @@ -0,0 +1,70 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.AirWizard; +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.entity.particle.SmashParticle; +import com.mojang.ld22.entity.particle.TextParticle; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.level.Level; + +public class CloudCactusTile extends Tile { + public CloudCactusTile(int id) { + super(id); + } + + public void render(Screen screen, Level level, int x, int y) { + int color = Color.get(444, 111, 333, 555); + screen.render(x * 16 + 0, y * 16 + 0, 17 + 1 * 32, color, 0); + screen.render(x * 16 + 8, y * 16 + 0, 18 + 1 * 32, color, 0); + screen.render(x * 16 + 0, y * 16 + 8, 17 + 2 * 32, color, 0); + screen.render(x * 16 + 8, y * 16 + 8, 18 + 2 * 32, color, 0); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + if (e instanceof AirWizard) return true; + return false; + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + hurt(level, x, y, 0); + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.pickaxe) { + if (player.payStamina(6 - tool.level)) { + hurt(level, xt, yt, 1); + return true; + } + } + } + return false; + } + + public void hurt(Level level, int x, int y, int dmg) { + int damage = level.getData(x, y) + 1; + level.add(new SmashParticle(x * 16 + 8, y * 16 + 8)); + level.add(new TextParticle("" + dmg, x * 16 + 8, y * 16 + 8, Color.get(-1, 500, 500, 500))); + if (dmg > 0) { + if (damage >= 10) { + level.setTile(x, y, Tile.cloud, 0); + } else { + level.setData(x, y, damage); + } + } + } + + public void bumpedInto(Level level, int x, int y, Entity entity) { + if (entity instanceof AirWizard) return; + entity.hurt(this, x, y, 3); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/level/tile/CloudTile.java b/src/com/mojang/ld22/level/tile/CloudTile.java new file mode 100644 index 0000000..d3490c1 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/CloudTile.java @@ -0,0 +1,90 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class CloudTile extends Tile { + public CloudTile(int id) { + super(id); + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(444, 444, 555, 555); + int transitionColor = Color.get(333, 444, 555, -1); + + boolean u = level.getTile(x, y - 1) == Tile.infiniteFall; + boolean d = level.getTile(x, y + 1) == Tile.infiniteFall; + boolean l = level.getTile(x - 1, y) == Tile.infiniteFall; + boolean r = level.getTile(x + 1, y) == Tile.infiniteFall; + + boolean ul = level.getTile(x - 1, y - 1) == Tile.infiniteFall; + boolean dl = level.getTile(x - 1, y + 1) == Tile.infiniteFall; + boolean ur = level.getTile(x + 1, y - 1) == Tile.infiniteFall; + boolean dr = level.getTile(x + 1, y + 1) == Tile.infiniteFall; + + if (!u && !l) { + if (!ul) + screen.render(x * 16 + 0, y * 16 + 0, 17, col, 0); + else + screen.render(x * 16 + 0, y * 16 + 0, 7 + 0 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 0, y * 16 + 0, (l ? 6 : 5) + (u ? 2 : 1) * 32, transitionColor, 3); + + if (!u && !r) { + if (!ur) + screen.render(x * 16 + 8, y * 16 + 0, 18, col, 0); + else + screen.render(x * 16 + 8, y * 16 + 0, 8 + 0 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 8, y * 16 + 0, (r ? 4 : 5) + (u ? 2 : 1) * 32, transitionColor, 3); + + if (!d && !l) { + if (!dl) + screen.render(x * 16 + 0, y * 16 + 8, 20, col, 0); + else + screen.render(x * 16 + 0, y * 16 + 8, 7 + 1 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 0, y * 16 + 8, (l ? 6 : 5) + (d ? 0 : 1) * 32, transitionColor, 3); + if (!d && !r) { + if (!dr) + screen.render(x * 16 + 8, y * 16 + 8, 19, col, 0); + else + screen.render(x * 16 + 8, y * 16 + 8, 8 + 1 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 8, y * 16 + 8, (r ? 4 : 5) + (d ? 0 : 1) * 32, transitionColor, 3); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return true; + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.shovel) { + if (player.payStamina(5)) { + // level.setTile(xt, yt, Tile.infiniteFall, 0); + int count = random.nextInt(2) + 1; + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.cloud), xt * 16 + random.nextInt(10) + 3, yt * 16 + random.nextInt(10) + 3)); + } + return true; + } + } + } + return false; + } + + /* + * public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { if (item instanceof ToolItem) { ToolItem tool = (ToolItem) item; if (tool.type == ToolType.pickaxe) { if (player.payStamina(4 - tool.level)) { hurt(level, xt, yt, random.nextInt(10) + (tool.level) * 5 + 10); return true; } } } return false; } + */ +} diff --git a/src/com/mojang/ld22/level/tile/DirtTile.java b/src/com/mojang/ld22/level/tile/DirtTile.java new file mode 100644 index 0000000..323c75f --- /dev/null +++ b/src/com/mojang/ld22/level/tile/DirtTile.java @@ -0,0 +1,49 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.sound.Sound; + +public class DirtTile extends Tile { + public DirtTile(int id) { + super(id); + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(level.dirtColor, level.dirtColor, level.dirtColor - 111, level.dirtColor - 111); + screen.render(x * 16 + 0, y * 16 + 0, 0, col, 0); + screen.render(x * 16 + 8, y * 16 + 0, 1, col, 0); + screen.render(x * 16 + 0, y * 16 + 8, 2, col, 0); + screen.render(x * 16 + 8, y * 16 + 8, 3, col, 0); + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.shovel) { + if (player.payStamina(4 - tool.level)) { + level.setTile(xt, yt, Tile.hole, 0); + level.add(new ItemEntity(new ResourceItem(Resource.dirt), xt * 16 + random.nextInt(10) + 3, yt * 16 + random.nextInt(10) + 3)); + Sound.monsterHurt.play(); + return true; + } + } + if (tool.type == ToolType.hoe) { + if (player.payStamina(4 - tool.level)) { + level.setTile(xt, yt, Tile.farmland, 0); + Sound.monsterHurt.play(); + return true; + } + } + } + return false; + } +} diff --git a/src/com/mojang/ld22/level/tile/FarmTile.java b/src/com/mojang/ld22/level/tile/FarmTile.java new file mode 100644 index 0000000..dcd5fcc --- /dev/null +++ b/src/com/mojang/ld22/level/tile/FarmTile.java @@ -0,0 +1,48 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.level.Level; + +public class FarmTile extends Tile { + public FarmTile(int id) { + super(id); + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(level.dirtColor - 121, level.dirtColor - 11, level.dirtColor, level.dirtColor + 111); + screen.render(x * 16 + 0, y * 16 + 0, 2 + 32, col, 1); + screen.render(x * 16 + 8, y * 16 + 0, 2 + 32, col, 0); + screen.render(x * 16 + 0, y * 16 + 8, 2 + 32, col, 0); + screen.render(x * 16 + 8, y * 16 + 8, 2 + 32, col, 1); + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.shovel) { + if (player.payStamina(4 - tool.level)) { + level.setTile(xt, yt, Tile.dirt, 0); + return true; + } + } + } + return false; + } + + public void tick(Level level, int xt, int yt) { + int age = level.getData(xt, yt); + if (age < 5) level.setData(xt, yt, age + 1); + } + + public void steppedOn(Level level, int xt, int yt, Entity entity) { + if (random.nextInt(60) != 0) return; + if (level.getData(xt, yt) < 5) return; + level.setTile(xt, yt, Tile.dirt, 0); + } +} diff --git a/src/com/mojang/ld22/level/tile/FlowerTile.java b/src/com/mojang/ld22/level/tile/FlowerTile.java new file mode 100644 index 0000000..93f2c9f --- /dev/null +++ b/src/com/mojang/ld22/level/tile/FlowerTile.java @@ -0,0 +1,57 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class FlowerTile extends GrassTile { + public FlowerTile(int id) { + super(id); + tiles[id] = this; + connectsToGrass = true; + } + + public void render(Screen screen, Level level, int x, int y) { + super.render(screen, level, x, y); + + int data = level.getData(x, y); + int shape = (data / 16) % 2; + int flowerCol = Color.get(10, level.grassColor, 555, 440); + + if (shape == 0) screen.render(x * 16 + 0, y * 16 + 0, 1 + 1 * 32, flowerCol, 0); + if (shape == 1) screen.render(x * 16 + 8, y * 16 + 0, 1 + 1 * 32, flowerCol, 0); + if (shape == 1) screen.render(x * 16 + 0, y * 16 + 8, 1 + 1 * 32, flowerCol, 0); + if (shape == 0) screen.render(x * 16 + 8, y * 16 + 8, 1 + 1 * 32, flowerCol, 0); + } + + public boolean interact(Level level, int x, int y, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.shovel) { + if (player.payStamina(4 - tool.level)) { + level.add(new ItemEntity(new ResourceItem(Resource.flower), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + level.add(new ItemEntity(new ResourceItem(Resource.flower), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + level.setTile(x, y, Tile.grass, 0); + return true; + } + } + } + return false; + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + int count = random.nextInt(2) + 1; + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.flower), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + level.setTile(x, y, Tile.grass, 0); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/level/tile/GrassTile.java b/src/com/mojang/ld22/level/tile/GrassTile.java new file mode 100644 index 0000000..70d2f74 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/GrassTile.java @@ -0,0 +1,94 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; +import com.mojang.ld22.sound.Sound; + +public class GrassTile extends Tile { + public GrassTile(int id) { + super(id); + connectsToGrass = true; + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(level.grassColor, level.grassColor, level.grassColor + 111, level.grassColor + 111); + int transitionColor = Color.get(level.grassColor - 111, level.grassColor, level.grassColor + 111, level.dirtColor); + + boolean u = !level.getTile(x, y - 1).connectsToGrass; + boolean d = !level.getTile(x, y + 1).connectsToGrass; + boolean l = !level.getTile(x - 1, y).connectsToGrass; + boolean r = !level.getTile(x + 1, y).connectsToGrass; + + if (!u && !l) { + screen.render(x * 16 + 0, y * 16 + 0, 0, col, 0); + } else + screen.render(x * 16 + 0, y * 16 + 0, (l ? 11 : 12) + (u ? 0 : 1) * 32, transitionColor, 0); + + if (!u && !r) { + screen.render(x * 16 + 8, y * 16 + 0, 1, col, 0); + } else + screen.render(x * 16 + 8, y * 16 + 0, (r ? 13 : 12) + (u ? 0 : 1) * 32, transitionColor, 0); + + if (!d && !l) { + screen.render(x * 16 + 0, y * 16 + 8, 2, col, 0); + } else + screen.render(x * 16 + 0, y * 16 + 8, (l ? 11 : 12) + (d ? 2 : 1) * 32, transitionColor, 0); + if (!d && !r) { + screen.render(x * 16 + 8, y * 16 + 8, 3, col, 0); + } else + screen.render(x * 16 + 8, y * 16 + 8, (r ? 13 : 12) + (d ? 2 : 1) * 32, transitionColor, 0); + } + + public void tick(Level level, int xt, int yt) { + if (random.nextInt(40) != 0) return; + + int xn = xt; + int yn = yt; + + if (random.nextBoolean()) + xn += random.nextInt(2) * 2 - 1; + else + yn += random.nextInt(2) * 2 - 1; + + if (level.getTile(xn, yn) == Tile.dirt) { + level.setTile(xn, yn, this, 0); + } + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.shovel) { + if (player.payStamina(4 - tool.level)) { + level.setTile(xt, yt, Tile.dirt, 0); + Sound.monsterHurt.play(); + if (random.nextInt(5) == 0) { + level.add(new ItemEntity(new ResourceItem(Resource.seeds), xt * 16 + random.nextInt(10) + 3, yt * 16 + random.nextInt(10) + 3)); + return true; + } + } + } + if (tool.type == ToolType.hoe) { + if (player.payStamina(4 - tool.level)) { + Sound.monsterHurt.play(); + if (random.nextInt(5) == 0) { + level.add(new ItemEntity(new ResourceItem(Resource.seeds), xt * 16 + random.nextInt(10) + 3, yt * 16 + random.nextInt(10) + 3)); + return true; + } + level.setTile(xt, yt, Tile.farmland, 0); + return true; + } + } + } + return false; + + } +} diff --git a/src/com/mojang/ld22/level/tile/HardRockTile.java b/src/com/mojang/ld22/level/tile/HardRockTile.java new file mode 100644 index 0000000..e6cf1be --- /dev/null +++ b/src/com/mojang/ld22/level/tile/HardRockTile.java @@ -0,0 +1,113 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.entity.particle.SmashParticle; +import com.mojang.ld22.entity.particle.TextParticle; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class HardRockTile extends Tile { + public HardRockTile(int id) { + super(id); + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(334, 334, 223, 223); + int transitionColor = Color.get(001, 334, 445, level.dirtColor); + + boolean u = level.getTile(x, y - 1) != this; + boolean d = level.getTile(x, y + 1) != this; + boolean l = level.getTile(x - 1, y) != this; + boolean r = level.getTile(x + 1, y) != this; + + boolean ul = level.getTile(x - 1, y - 1) != this; + boolean dl = level.getTile(x - 1, y + 1) != this; + boolean ur = level.getTile(x + 1, y - 1) != this; + boolean dr = level.getTile(x + 1, y + 1) != this; + + if (!u && !l) { + if (!ul) + screen.render(x * 16 + 0, y * 16 + 0, 0, col, 0); + else + screen.render(x * 16 + 0, y * 16 + 0, 7 + 0 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 0, y * 16 + 0, (l ? 6 : 5) + (u ? 2 : 1) * 32, transitionColor, 3); + + if (!u && !r) { + if (!ur) + screen.render(x * 16 + 8, y * 16 + 0, 1, col, 0); + else + screen.render(x * 16 + 8, y * 16 + 0, 8 + 0 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 8, y * 16 + 0, (r ? 4 : 5) + (u ? 2 : 1) * 32, transitionColor, 3); + + if (!d && !l) { + if (!dl) + screen.render(x * 16 + 0, y * 16 + 8, 2, col, 0); + else + screen.render(x * 16 + 0, y * 16 + 8, 7 + 1 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 0, y * 16 + 8, (l ? 6 : 5) + (d ? 0 : 1) * 32, transitionColor, 3); + if (!d && !r) { + if (!dr) + screen.render(x * 16 + 8, y * 16 + 8, 3, col, 0); + else + screen.render(x * 16 + 8, y * 16 + 8, 8 + 1 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 8, y * 16 + 8, (r ? 4 : 5) + (d ? 0 : 1) * 32, transitionColor, 3); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return false; + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + hurt(level, x, y, 0); + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.pickaxe && tool.level == 4) { + if (player.payStamina(4 - tool.level)) { + hurt(level, xt, yt, random.nextInt(10) + (tool.level) * 5 + 10); + return true; + } + } + } + return false; + } + + public void hurt(Level level, int x, int y, int dmg) { + int damage = level.getData(x, y) + dmg; + level.add(new SmashParticle(x * 16 + 8, y * 16 + 8)); + level.add(new TextParticle("" + dmg, x * 16 + 8, y * 16 + 8, Color.get(-1, 500, 500, 500))); + if (damage >= 200) { + int count = random.nextInt(4) + 1; + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.stone), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + count = random.nextInt(2); + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.coal), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + level.setTile(x, y, Tile.dirt, 0); + } else { + level.setData(x, y, damage); + } + } + + public void tick(Level level, int xt, int yt) { + int damage = level.getData(xt, yt); + if (damage > 0) level.setData(xt, yt, damage - 1); + } +} diff --git a/src/com/mojang/ld22/level/tile/HoleTile.java b/src/com/mojang/ld22/level/tile/HoleTile.java new file mode 100644 index 0000000..719e904 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/HoleTile.java @@ -0,0 +1,55 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.Level; + +public class HoleTile extends Tile { + public HoleTile(int id) { + super(id); + connectsToSand = true; + connectsToWater = true; + connectsToLava= true; + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(111, 111, 110, 110); + int transitionColor1 = Color.get(3, 111, level.dirtColor - 111, level.dirtColor); + int transitionColor2 = Color.get(3, 111, level.sandColor - 110, level.sandColor); + + boolean u = !level.getTile(x, y - 1).connectsToLiquid(); + boolean d = !level.getTile(x, y + 1).connectsToLiquid(); + boolean l = !level.getTile(x - 1, y).connectsToLiquid(); + boolean r = !level.getTile(x + 1, y).connectsToLiquid(); + + boolean su = u && level.getTile(x, y - 1).connectsToSand; + boolean sd = d && level.getTile(x, y + 1).connectsToSand; + boolean sl = l && level.getTile(x - 1, y).connectsToSand; + boolean sr = r && level.getTile(x + 1, y).connectsToSand; + + if (!u && !l) { + screen.render(x * 16 + 0, y * 16 + 0, 0, col, 0); + } else + screen.render(x * 16 + 0, y * 16 + 0, (l ? 14 : 15) + (u ? 0 : 1) * 32, (su || sl) ? transitionColor2 : transitionColor1, 0); + + if (!u && !r) { + screen.render(x * 16 + 8, y * 16 + 0, 1, col, 0); + } else + screen.render(x * 16 + 8, y * 16 + 0, (r ? 16 : 15) + (u ? 0 : 1) * 32, (su || sr) ? transitionColor2 : transitionColor1, 0); + + if (!d && !l) { + screen.render(x * 16 + 0, y * 16 + 8, 2, col, 0); + } else + screen.render(x * 16 + 0, y * 16 + 8, (l ? 14 : 15) + (d ? 2 : 1) * 32, (sd || sl) ? transitionColor2 : transitionColor1, 0); + if (!d && !r) { + screen.render(x * 16 + 8, y * 16 + 8, 3, col, 0); + } else + screen.render(x * 16 + 8, y * 16 + 8, (r ? 16 : 15) + (d ? 2 : 1) * 32, (sd || sr) ? transitionColor2 : transitionColor1, 0); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return e.canSwim(); + } + +} diff --git a/src/com/mojang/ld22/level/tile/InfiniteFallTile.java b/src/com/mojang/ld22/level/tile/InfiniteFallTile.java new file mode 100644 index 0000000..92cc6ff --- /dev/null +++ b/src/com/mojang/ld22/level/tile/InfiniteFallTile.java @@ -0,0 +1,23 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.AirWizard; +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.Level; + +public class InfiniteFallTile extends Tile { + public InfiniteFallTile(int id) { + super(id); + } + + public void render(Screen screen, Level level, int x, int y) { + } + + public void tick(Level level, int xt, int yt) { + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + if (e instanceof AirWizard) return true; + return false; + } +} diff --git a/src/com/mojang/ld22/level/tile/LavaTile.java b/src/com/mojang/ld22/level/tile/LavaTile.java new file mode 100644 index 0000000..c1c434c --- /dev/null +++ b/src/com/mojang/ld22/level/tile/LavaTile.java @@ -0,0 +1,76 @@ +package com.mojang.ld22.level.tile; + +import java.util.Random; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.Level; + +public class LavaTile extends Tile { + public LavaTile(int id) { + super(id); + connectsToSand = true; + connectsToLava = true; + } + + private Random wRandom = new Random(); + + public void render(Screen screen, Level level, int x, int y) { + wRandom.setSeed((tickCount + (x / 2 - y) * 4311) / 10 * 54687121l + x * 3271612l + y * 3412987161l); + int col = Color.get(500, 500, 520, 550); + int transitionColor1 = Color.get(3, 500, level.dirtColor - 111, level.dirtColor); + int transitionColor2 = Color.get(3, 500, level.sandColor - 110, level.sandColor); + + boolean u = !level.getTile(x, y - 1).connectsToLava; + boolean d = !level.getTile(x, y + 1).connectsToLava; + boolean l = !level.getTile(x - 1, y).connectsToLava; + boolean r = !level.getTile(x + 1, y).connectsToLava; + + boolean su = u && level.getTile(x, y - 1).connectsToSand; + boolean sd = d && level.getTile(x, y + 1).connectsToSand; + boolean sl = l && level.getTile(x - 1, y).connectsToSand; + boolean sr = r && level.getTile(x + 1, y).connectsToSand; + + if (!u && !l) { + screen.render(x * 16 + 0, y * 16 + 0, wRandom.nextInt(4), col, wRandom.nextInt(4)); + } else + screen.render(x * 16 + 0, y * 16 + 0, (l ? 14 : 15) + (u ? 0 : 1) * 32, (su || sl) ? transitionColor2 : transitionColor1, 0); + + if (!u && !r) { + screen.render(x * 16 + 8, y * 16 + 0, wRandom.nextInt(4), col, wRandom.nextInt(4)); + } else + screen.render(x * 16 + 8, y * 16 + 0, (r ? 16 : 15) + (u ? 0 : 1) * 32, (su || sr) ? transitionColor2 : transitionColor1, 0); + + if (!d && !l) { + screen.render(x * 16 + 0, y * 16 + 8, wRandom.nextInt(4), col, wRandom.nextInt(4)); + } else + screen.render(x * 16 + 0, y * 16 + 8, (l ? 14 : 15) + (d ? 2 : 1) * 32, (sd || sl) ? transitionColor2 : transitionColor1, 0); + if (!d && !r) { + screen.render(x * 16 + 8, y * 16 + 8, wRandom.nextInt(4), col, wRandom.nextInt(4)); + } else + screen.render(x * 16 + 8, y * 16 + 8, (r ? 16 : 15) + (d ? 2 : 1) * 32, (sd || sr) ? transitionColor2 : transitionColor1, 0); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return e.canSwim(); + } + + public void tick(Level level, int xt, int yt) { + int xn = xt; + int yn = yt; + + if (random.nextBoolean()) + xn += random.nextInt(2) * 2 - 1; + else + yn += random.nextInt(2) * 2 - 1; + + if (level.getTile(xn, yn) == Tile.hole) { + level.setTile(xn, yn, this, 0); + } + } + + public int getLightRadius(Level level, int x, int y) { + return 6; + } +} diff --git a/src/com/mojang/ld22/level/tile/OreTile.java b/src/com/mojang/ld22/level/tile/OreTile.java new file mode 100644 index 0000000..30c8db0 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/OreTile.java @@ -0,0 +1,78 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.entity.particle.SmashParticle; +import com.mojang.ld22.entity.particle.TextParticle; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class OreTile extends Tile { + private Resource toDrop; + private int color; + + public OreTile(int id, Resource toDrop) { + super(id); + this.toDrop = toDrop; + this.color = toDrop.color & 0xffff00; + } + + public void render(Screen screen, Level level, int x, int y) { + color = (toDrop.color & 0xffffff00) + Color.get(level.dirtColor); + screen.render(x * 16 + 0, y * 16 + 0, 17 + 1 * 32, color, 0); + screen.render(x * 16 + 8, y * 16 + 0, 18 + 1 * 32, color, 0); + screen.render(x * 16 + 0, y * 16 + 8, 17 + 2 * 32, color, 0); + screen.render(x * 16 + 8, y * 16 + 8, 18 + 2 * 32, color, 0); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return false; + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + hurt(level, x, y, 0); + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.pickaxe) { + if (player.payStamina(6 - tool.level)) { + hurt(level, xt, yt, 1); + return true; + } + } + } + return false; + } + + public void hurt(Level level, int x, int y, int dmg) { + int damage = level.getData(x, y) + 1; + level.add(new SmashParticle(x * 16 + 8, y * 16 + 8)); + level.add(new TextParticle("" + dmg, x * 16 + 8, y * 16 + 8, Color.get(-1, 500, 500, 500))); + if (dmg > 0) { + int count = random.nextInt(2); + if (damage >= random.nextInt(10) + 3) { + level.setTile(x, y, Tile.dirt, 0); + count += 2; + } else { + level.setData(x, y, damage); + } + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(toDrop), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + } + } + + public void bumpedInto(Level level, int x, int y, Entity entity) { + entity.hurt(this, x, y, 3); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/level/tile/RockTile.java b/src/com/mojang/ld22/level/tile/RockTile.java new file mode 100644 index 0000000..bf3165b --- /dev/null +++ b/src/com/mojang/ld22/level/tile/RockTile.java @@ -0,0 +1,113 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.entity.particle.SmashParticle; +import com.mojang.ld22.entity.particle.TextParticle; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class RockTile extends Tile { + public RockTile(int id) { + super(id); + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(444, 444, 333, 333); + int transitionColor = Color.get(111, 444, 555, level.dirtColor); + + boolean u = level.getTile(x, y - 1) != this; + boolean d = level.getTile(x, y + 1) != this; + boolean l = level.getTile(x - 1, y) != this; + boolean r = level.getTile(x + 1, y) != this; + + boolean ul = level.getTile(x - 1, y - 1) != this; + boolean dl = level.getTile(x - 1, y + 1) != this; + boolean ur = level.getTile(x + 1, y - 1) != this; + boolean dr = level.getTile(x + 1, y + 1) != this; + + if (!u && !l) { + if (!ul) + screen.render(x * 16 + 0, y * 16 + 0, 0, col, 0); + else + screen.render(x * 16 + 0, y * 16 + 0, 7 + 0 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 0, y * 16 + 0, (l ? 6 : 5) + (u ? 2 : 1) * 32, transitionColor, 3); + + if (!u && !r) { + if (!ur) + screen.render(x * 16 + 8, y * 16 + 0, 1, col, 0); + else + screen.render(x * 16 + 8, y * 16 + 0, 8 + 0 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 8, y * 16 + 0, (r ? 4 : 5) + (u ? 2 : 1) * 32, transitionColor, 3); + + if (!d && !l) { + if (!dl) + screen.render(x * 16 + 0, y * 16 + 8, 2, col, 0); + else + screen.render(x * 16 + 0, y * 16 + 8, 7 + 1 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 0, y * 16 + 8, (l ? 6 : 5) + (d ? 0 : 1) * 32, transitionColor, 3); + if (!d && !r) { + if (!dr) + screen.render(x * 16 + 8, y * 16 + 8, 3, col, 0); + else + screen.render(x * 16 + 8, y * 16 + 8, 8 + 1 * 32, transitionColor, 3); + } else + screen.render(x * 16 + 8, y * 16 + 8, (r ? 4 : 5) + (d ? 0 : 1) * 32, transitionColor, 3); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return false; + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + hurt(level, x, y, dmg); + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.pickaxe) { + if (player.payStamina(4 - tool.level)) { + hurt(level, xt, yt, random.nextInt(10) + (tool.level) * 5 + 10); + return true; + } + } + } + return false; + } + + public void hurt(Level level, int x, int y, int dmg) { + int damage = level.getData(x, y) + dmg; + level.add(new SmashParticle(x * 16 + 8, y * 16 + 8)); + level.add(new TextParticle("" + dmg, x * 16 + 8, y * 16 + 8, Color.get(-1, 500, 500, 500))); + if (damage >= 50) { + int count = random.nextInt(4) + 1; + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.stone), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + count = random.nextInt(2); + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.coal), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + level.setTile(x, y, Tile.dirt, 0); + } else { + level.setData(x, y, damage); + } + } + + public void tick(Level level, int xt, int yt) { + int damage = level.getData(xt, yt); + if (damage > 0) level.setData(xt, yt, damage - 1); + } +} diff --git a/src/com/mojang/ld22/level/tile/SandTile.java b/src/com/mojang/ld22/level/tile/SandTile.java new file mode 100644 index 0000000..db84e1c --- /dev/null +++ b/src/com/mojang/ld22/level/tile/SandTile.java @@ -0,0 +1,84 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class SandTile extends Tile { + public SandTile(int id) { + super(id); + connectsToSand = true; + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(level.sandColor + 2, level.sandColor, level.sandColor - 110, level.sandColor - 110); + int transitionColor = Color.get(level.sandColor - 110, level.sandColor, level.sandColor - 110, level.dirtColor); + + boolean u = !level.getTile(x, y - 1).connectsToSand; + boolean d = !level.getTile(x, y + 1).connectsToSand; + boolean l = !level.getTile(x - 1, y).connectsToSand; + boolean r = !level.getTile(x + 1, y).connectsToSand; + + boolean steppedOn = level.getData(x, y) > 0; + + if (!u && !l) { + if (!steppedOn) + screen.render(x * 16 + 0, y * 16 + 0, 0, col, 0); + else + screen.render(x * 16 + 0, y * 16 + 0, 3 + 1 * 32, col, 0); + } else + screen.render(x * 16 + 0, y * 16 + 0, (l ? 11 : 12) + (u ? 0 : 1) * 32, transitionColor, 0); + + if (!u && !r) { + screen.render(x * 16 + 8, y * 16 + 0, 1, col, 0); + } else + screen.render(x * 16 + 8, y * 16 + 0, (r ? 13 : 12) + (u ? 0 : 1) * 32, transitionColor, 0); + + if (!d && !l) { + screen.render(x * 16 + 0, y * 16 + 8, 2, col, 0); + } else + screen.render(x * 16 + 0, y * 16 + 8, (l ? 11 : 12) + (d ? 2 : 1) * 32, transitionColor, 0); + if (!d && !r) { + if (!steppedOn) + screen.render(x * 16 + 8, y * 16 + 8, 3, col, 0); + else + screen.render(x * 16 + 8, y * 16 + 8, 3 + 1 * 32, col, 0); + + } else + screen.render(x * 16 + 8, y * 16 + 8, (r ? 13 : 12) + (d ? 2 : 1) * 32, transitionColor, 0); + } + + public void tick(Level level, int x, int y) { + int d = level.getData(x, y); + if (d > 0) level.setData(x, y, d - 1); + } + + public void steppedOn(Level level, int x, int y, Entity entity) { + if (entity instanceof Mob) { + level.setData(x, y, 10); + } + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.shovel) { + if (player.payStamina(4 - tool.level)) { + level.setTile(xt, yt, Tile.dirt, 0); + level.add(new ItemEntity(new ResourceItem(Resource.sand), xt * 16 + random.nextInt(10) + 3, yt * 16 + random.nextInt(10) + 3)); + return true; + } + } + } + return false; + } +} diff --git a/src/com/mojang/ld22/level/tile/SaplingTile.java b/src/com/mojang/ld22/level/tile/SaplingTile.java new file mode 100644 index 0000000..1e2b88b --- /dev/null +++ b/src/com/mojang/ld22/level/tile/SaplingTile.java @@ -0,0 +1,40 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.Level; + +public class SaplingTile extends Tile { + private Tile onType; + private Tile growsTo; + + public SaplingTile(int id, Tile onType, Tile growsTo) { + super(id); + this.onType = onType; + this.growsTo = growsTo; + connectsToSand = onType.connectsToSand; + connectsToGrass = onType.connectsToGrass; + connectsToWater = onType.connectsToWater; + connectsToLava = onType.connectsToLava; + } + + public void render(Screen screen, Level level, int x, int y) { + onType.render(screen, level, x, y); + int col = Color.get(10, 40, 50, -1); + screen.render(x * 16 + 4, y * 16 + 4, 11 + 3 * 32, col, 0); + } + + public void tick(Level level, int x, int y) { + int age = level.getData(x, y) + 1; + if (age > 100) { + level.setTile(x, y, growsTo, 0); + } else { + level.setData(x, y, age); + } + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + level.setTile(x, y, onType, 0); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/level/tile/StairsTile.java b/src/com/mojang/ld22/level/tile/StairsTile.java new file mode 100644 index 0000000..e11dd99 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/StairsTile.java @@ -0,0 +1,24 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.Level; + +public class StairsTile extends Tile { + private boolean leadsUp; + + public StairsTile(int id, boolean leadsUp) { + super(id); + this.leadsUp = leadsUp; + } + + public void render(Screen screen, Level level, int x, int y) { + int color = Color.get(level.dirtColor, 000, 333, 444); + int xt = 0; + if (leadsUp) xt = 2; + screen.render(x * 16 + 0, y * 16 + 0, xt + 2 * 32, color, 0); + screen.render(x * 16 + 8, y * 16 + 0, xt + 1 + 2 * 32, color, 0); + screen.render(x * 16 + 0, y * 16 + 8, xt + 3 * 32, color, 0); + screen.render(x * 16 + 8, y * 16 + 8, xt + 1 + 3 * 32, color, 0); + } +} diff --git a/src/com/mojang/ld22/level/tile/StoneTile.java b/src/com/mojang/ld22/level/tile/StoneTile.java new file mode 100644 index 0000000..cb30d38 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/StoneTile.java @@ -0,0 +1,27 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.Level; + +public class StoneTile extends Tile { + public StoneTile(int id) { + super(id); + } + + public void render(Screen screen, Level level, int x, int y) { + int rc1 = 111; + int rc2 = 333; + int rc3 = 555; + screen.render(x * 16 + 0, y * 16 + 0, 32, Color.get(rc1, level.dirtColor, rc2, rc3), 0); + screen.render(x * 16 + 8, y * 16 + 0, 32, Color.get(rc1, level.dirtColor, rc2, rc3), 0); + screen.render(x * 16 + 0, y * 16 + 8, 32, Color.get(rc1, level.dirtColor, rc2, rc3), 0); + screen.render(x * 16 + 8, y * 16 + 8, 32, Color.get(rc1, level.dirtColor, rc2, rc3), 0); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return false; + } + +} diff --git a/src/com/mojang/ld22/level/tile/Tile.java b/src/com/mojang/ld22/level/tile/Tile.java new file mode 100644 index 0000000..b1adc9d --- /dev/null +++ b/src/com/mojang/ld22/level/tile/Tile.java @@ -0,0 +1,89 @@ +package com.mojang.ld22.level.tile; + +import java.util.Random; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class Tile { + public static int tickCount = 0; + protected Random random = new Random(); + + public static Tile[] tiles = new Tile[256]; + public static Tile grass = new GrassTile(0); + public static Tile rock = new RockTile(1); + public static Tile water = new WaterTile(2); + public static Tile flower = new FlowerTile(3); + public static Tile tree = new TreeTile(4); + public static Tile dirt = new DirtTile(5); + public static Tile sand = new SandTile(6); + public static Tile cactus = new CactusTile(7); + public static Tile hole = new HoleTile(8); + public static Tile treeSapling = new SaplingTile(9, grass, tree); + public static Tile cactusSapling = new SaplingTile(10, sand, cactus); + public static Tile farmland = new FarmTile(11); + public static Tile wheat = new WheatTile(12); + public static Tile lava = new LavaTile(13); + public static Tile stairsDown = new StairsTile(14, false); + public static Tile stairsUp = new StairsTile(15, true); + public static Tile infiniteFall = new InfiniteFallTile(16); + public static Tile cloud = new CloudTile(17); + public static Tile hardRock = new HardRockTile(18); + public static Tile ironOre = new OreTile(19, Resource.ironOre); + public static Tile goldOre = new OreTile(20, Resource.goldOre); + public static Tile gemOre = new OreTile(21, Resource.gem); + public static Tile cloudCactus = new CloudCactusTile(22); + + public final byte id; + + public boolean connectsToGrass = false; + public boolean connectsToSand = false; + public boolean connectsToLava = false; + public boolean connectsToWater = false; + + public Tile(int id) { + this.id = (byte) id; + if (tiles[id] != null) throw new RuntimeException("Duplicate tile ids!"); + tiles[id] = this; + } + + public void render(Screen screen, Level level, int x, int y) { + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return true; + } + + public int getLightRadius(Level level, int x, int y) { + return 0; + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + } + + public void bumpedInto(Level level, int xt, int yt, Entity entity) { + } + + public void tick(Level level, int xt, int yt) { + } + + public void steppedOn(Level level, int xt, int yt, Entity entity) { + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + return false; + } + + public boolean use(Level level, int xt, int yt, Player player, int attackDir) { + return false; + } + + public boolean connectsToLiquid() { + return connectsToWater || connectsToLava; + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/level/tile/TreeTile.java b/src/com/mojang/ld22/level/tile/TreeTile.java new file mode 100644 index 0000000..9eb5b26 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/TreeTile.java @@ -0,0 +1,110 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.entity.particle.SmashParticle; +import com.mojang.ld22.entity.particle.TextParticle; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class TreeTile extends Tile { + public TreeTile(int id) { + super(id); + connectsToGrass = true; + } + + public void render(Screen screen, Level level, int x, int y) { + int col = Color.get(10, 30, 151, level.grassColor); + int barkCol1 = Color.get(10, 30, 430, level.grassColor); + int barkCol2 = Color.get(10, 30, 320, level.grassColor); + + boolean u = level.getTile(x, y - 1) == this; + boolean l = level.getTile(x - 1, y) == this; + boolean r = level.getTile(x + 1, y) == this; + boolean d = level.getTile(x, y + 1) == this; + boolean ul = level.getTile(x - 1, y - 1) == this; + boolean ur = level.getTile(x + 1, y - 1) == this; + boolean dl = level.getTile(x - 1, y + 1) == this; + boolean dr = level.getTile(x + 1, y + 1) == this; + + if (u && ul && l) { + screen.render(x * 16 + 0, y * 16 + 0, 10 + 1 * 32, col, 0); + } else { + screen.render(x * 16 + 0, y * 16 + 0, 9 + 0 * 32, col, 0); + } + if (u && ur && r) { + screen.render(x * 16 + 8, y * 16 + 0, 10 + 2 * 32, barkCol2, 0); + } else { + screen.render(x * 16 + 8, y * 16 + 0, 10 + 0 * 32, col, 0); + } + if (d && dl && l) { + screen.render(x * 16 + 0, y * 16 + 8, 10 + 2 * 32, barkCol2, 0); + } else { + screen.render(x * 16 + 0, y * 16 + 8, 9 + 1 * 32, barkCol1, 0); + } + if (d && dr && r) { + screen.render(x * 16 + 8, y * 16 + 8, 10 + 1 * 32, col, 0); + } else { + screen.render(x * 16 + 8, y * 16 + 8, 10 + 3 * 32, barkCol2, 0); + } + } + + public void tick(Level level, int xt, int yt) { + int damage = level.getData(xt, yt); + if (damage > 0) level.setData(xt, yt, damage - 1); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return false; + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + hurt(level, x, y, dmg); + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.axe) { + if (player.payStamina(4 - tool.level)) { + hurt(level, xt, yt, random.nextInt(10) + (tool.level) * 5 + 10); + return true; + } + } + } + return false; + } + + private void hurt(Level level, int x, int y, int dmg) { + { + int count = random.nextInt(10) == 0 ? 1 : 0; + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.apple), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + } + int damage = level.getData(x, y) + dmg; + level.add(new SmashParticle(x * 16 + 8, y * 16 + 8)); + level.add(new TextParticle("" + dmg, x * 16 + 8, y * 16 + 8, Color.get(-1, 500, 500, 500))); + if (damage >= 20) { + int count = random.nextInt(2) + 1; + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.wood), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + count = random.nextInt(random.nextInt(4) + 1); + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.acorn), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + level.setTile(x, y, Tile.grass, 0); + } else { + level.setData(x, y, damage); + } + } +} diff --git a/src/com/mojang/ld22/level/tile/WaterTile.java b/src/com/mojang/ld22/level/tile/WaterTile.java new file mode 100644 index 0000000..33c0927 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/WaterTile.java @@ -0,0 +1,72 @@ +package com.mojang.ld22.level.tile; + +import java.util.Random; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.level.Level; + +public class WaterTile extends Tile { + public WaterTile(int id) { + super(id); + connectsToSand = true; + connectsToWater = true; + } + + private Random wRandom = new Random(); + + public void render(Screen screen, Level level, int x, int y) { + wRandom.setSeed((tickCount + (x / 2 - y) * 4311) / 10 * 54687121l + x * 3271612l + y * 3412987161l); + int col = Color.get(005, 005, 115, 115); + int transitionColor1 = Color.get(3, 005, level.dirtColor - 111, level.dirtColor); + int transitionColor2 = Color.get(3, 005, level.sandColor - 110, level.sandColor); + + boolean u = !level.getTile(x, y - 1).connectsToWater; + boolean d = !level.getTile(x, y + 1).connectsToWater; + boolean l = !level.getTile(x - 1, y).connectsToWater; + boolean r = !level.getTile(x + 1, y).connectsToWater; + + boolean su = u && level.getTile(x, y - 1).connectsToSand; + boolean sd = d && level.getTile(x, y + 1).connectsToSand; + boolean sl = l && level.getTile(x - 1, y).connectsToSand; + boolean sr = r && level.getTile(x + 1, y).connectsToSand; + + if (!u && !l) { + screen.render(x * 16 + 0, y * 16 + 0, wRandom.nextInt(4), col, wRandom.nextInt(4)); + } else + screen.render(x * 16 + 0, y * 16 + 0, (l ? 14 : 15) + (u ? 0 : 1) * 32, (su || sl) ? transitionColor2 : transitionColor1, 0); + + if (!u && !r) { + screen.render(x * 16 + 8, y * 16 + 0, wRandom.nextInt(4), col, wRandom.nextInt(4)); + } else + screen.render(x * 16 + 8, y * 16 + 0, (r ? 16 : 15) + (u ? 0 : 1) * 32, (su || sr) ? transitionColor2 : transitionColor1, 0); + + if (!d && !l) { + screen.render(x * 16 + 0, y * 16 + 8, wRandom.nextInt(4), col, wRandom.nextInt(4)); + } else + screen.render(x * 16 + 0, y * 16 + 8, (l ? 14 : 15) + (d ? 2 : 1) * 32, (sd || sl) ? transitionColor2 : transitionColor1, 0); + if (!d && !r) { + screen.render(x * 16 + 8, y * 16 + 8, wRandom.nextInt(4), col, wRandom.nextInt(4)); + } else + screen.render(x * 16 + 8, y * 16 + 8, (r ? 16 : 15) + (d ? 2 : 1) * 32, (sd || sr) ? transitionColor2 : transitionColor1, 0); + } + + public boolean mayPass(Level level, int x, int y, Entity e) { + return e.canSwim(); + } + + public void tick(Level level, int xt, int yt) { + int xn = xt; + int yn = yt; + + if (random.nextBoolean()) + xn += random.nextInt(2) * 2 - 1; + else + yn += random.nextInt(2) * 2 - 1; + + if (level.getTile(xn, yn) == Tile.hole) { + level.setTile(xn, yn, this, 0); + } + } +} diff --git a/src/com/mojang/ld22/level/tile/WheatTile.java b/src/com/mojang/ld22/level/tile/WheatTile.java new file mode 100644 index 0000000..10710b9 --- /dev/null +++ b/src/com/mojang/ld22/level/tile/WheatTile.java @@ -0,0 +1,90 @@ +package com.mojang.ld22.level.tile; + +import com.mojang.ld22.entity.Entity; +import com.mojang.ld22.entity.ItemEntity; +import com.mojang.ld22.entity.Mob; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.item.ToolItem; +import com.mojang.ld22.item.ToolType; +import com.mojang.ld22.item.resource.Resource; +import com.mojang.ld22.level.Level; + +public class WheatTile extends Tile { + public WheatTile(int id) { + super(id); + } + + public void render(Screen screen, Level level, int x, int y) { + int age = level.getData(x, y); + int col = Color.get(level.dirtColor - 121, level.dirtColor - 11, level.dirtColor, 50); + int icon = age / 10; + if (icon >= 3) { + col = Color.get(level.dirtColor - 121, level.dirtColor - 11, 50 + (icon) * 100, 40 + (icon - 3) * 2 * 100); + if (age == 50) { + col = Color.get(0, 0, 50 + (icon) * 100, 40 + (icon - 3) * 2 * 100); + } + icon = 3; + } + + screen.render(x * 16 + 0, y * 16 + 0, 4 + 3 * 32 + icon, col, 0); + screen.render(x * 16 + 8, y * 16 + 0, 4 + 3 * 32 + icon, col, 0); + screen.render(x * 16 + 0, y * 16 + 8, 4 + 3 * 32 + icon, col, 1); + screen.render(x * 16 + 8, y * 16 + 8, 4 + 3 * 32 + icon, col, 1); + } + + public void tick(Level level, int xt, int yt) { + if (random.nextInt(2) == 0) return; + + int age = level.getData(xt, yt); + if (age < 50) level.setData(xt, yt, age + 1); + } + + public boolean interact(Level level, int xt, int yt, Player player, Item item, int attackDir) { + if (item instanceof ToolItem) { + ToolItem tool = (ToolItem) item; + if (tool.type == ToolType.shovel) { + if (player.payStamina(4 - tool.level)) { + level.setTile(xt, yt, Tile.dirt, 0); + return true; + } + } + } + return false; + } + + public void steppedOn(Level level, int xt, int yt, Entity entity) { + if (random.nextInt(60) != 0) return; + if (level.getData(xt, yt) < 2) return; + harvest(level, xt, yt); + } + + public void hurt(Level level, int x, int y, Mob source, int dmg, int attackDir) { + + harvest(level, x, y); + } + + private void harvest(Level level, int x, int y) { + int age = level.getData(x, y); + + int count = random.nextInt(2); + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.seeds), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + + count = 0; + if (age == 50) { + count = random.nextInt(3) + 2; + } else if (age >= 40) { + count = random.nextInt(2) + 1; + } + for (int i = 0; i < count; i++) { + level.add(new ItemEntity(new ResourceItem(Resource.wheat), x * 16 + random.nextInt(10) + 3, y * 16 + random.nextInt(10) + 3)); + } + + level.setTile(x, y, Tile.dirt, 0); + } +} diff --git a/src/com/mojang/ld22/screen/AboutMenu.java b/src/com/mojang/ld22/screen/AboutMenu.java new file mode 100644 index 0000000..0cf7d7c --- /dev/null +++ b/src/com/mojang/ld22/screen/AboutMenu.java @@ -0,0 +1,32 @@ +package com.mojang.ld22.screen; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; + +public class AboutMenu extends Menu { + private Menu parent; + + public AboutMenu(Menu parent) { + this.parent = parent; + } + + public void tick() { + if (input.attack.clicked || input.menu.clicked) { + game.setMenu(parent); + } + } + + public void render(Screen screen) { + screen.clear(0); + + Font.draw("About Minicraft", screen, 2 * 8 + 4, 1 * 8, Color.get(0, 555, 555, 555)); + Font.draw("Minicraft was made", screen, 0 * 8 + 4, 3 * 8, Color.get(0, 333, 333, 333)); + Font.draw("by Markus Persson", screen, 0 * 8 + 4, 4 * 8, Color.get(0, 333, 333, 333)); + Font.draw("For the 22'nd ludum", screen, 0 * 8 + 4, 5 * 8, Color.get(0, 333, 333, 333)); + Font.draw("dare competition in", screen, 0 * 8 + 4, 6 * 8, Color.get(0, 333, 333, 333)); + Font.draw("december 2011.", screen, 0 * 8 + 4, 7 * 8, Color.get(0, 333, 333, 333)); + Font.draw("it is dedicated to", screen, 0 * 8 + 4, 9 * 8, Color.get(0, 333, 333, 333)); + Font.draw("my father. <3", screen, 0 * 8 + 4, 10 * 8, Color.get(0, 333, 333, 333)); + } +} diff --git a/src/com/mojang/ld22/screen/ContainerMenu.java b/src/com/mojang/ld22/screen/ContainerMenu.java new file mode 100644 index 0000000..7d4a064 --- /dev/null +++ b/src/com/mojang/ld22/screen/ContainerMenu.java @@ -0,0 +1,67 @@ +package com.mojang.ld22.screen; + +import com.mojang.ld22.entity.Inventory; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; + +public class ContainerMenu extends Menu { + private Player player; + private Inventory container; + private int selected = 0; + private String title; + private int oSelected; + private int window = 0; + + public ContainerMenu(Player player, String title, Inventory container) { + this.player = player; + this.title = title; + this.container = container; + } + + public void tick() { + if (input.menu.clicked) game.setMenu(null); + + if (input.left.clicked) { + window = 0; + int tmp = selected; + selected = oSelected; + oSelected = tmp; + } + if (input.right.clicked) { + window = 1; + int tmp = selected; + selected = oSelected; + oSelected = tmp; + } + + Inventory i = window == 1 ? player.inventory : container; + Inventory i2 = window == 0 ? player.inventory : container; + + int len = i.items.size(); + if (selected < 0) selected = 0; + if (selected >= len) selected = len - 1; + + if (input.up.clicked) selected--; + if (input.down.clicked) selected++; + + if (len == 0) selected = 0; + if (selected < 0) selected += len; + if (selected >= len) selected -= len; + + if (input.attack.clicked && len > 0) { + i2.add(oSelected, i.items.remove(selected)); + if (selected >= i.items.size()) selected = i.items.size() - 1; + } + } + + public void render(Screen screen) { + if (window == 1) screen.setOffset(6 * 8, 0); + Font.renderFrame(screen, title, 1, 1, 12, 11); + renderItemList(screen, 1, 1, 12, 11, container.items, window == 0 ? selected : -oSelected - 1); + + Font.renderFrame(screen, "inventory", 13, 1, 13 + 11, 11); + renderItemList(screen, 13, 1, 13 + 11, 11, player.inventory.items, window == 1 ? selected : -oSelected - 1); + screen.setOffset(0, 0); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/screen/CraftingMenu.java b/src/com/mojang/ld22/screen/CraftingMenu.java new file mode 100644 index 0000000..0f52f6d --- /dev/null +++ b/src/com/mojang/ld22/screen/CraftingMenu.java @@ -0,0 +1,98 @@ +package com.mojang.ld22.screen; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import com.mojang.ld22.crafting.Recipe; +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; +import com.mojang.ld22.item.ResourceItem; +import com.mojang.ld22.sound.Sound; + +public class CraftingMenu extends Menu { + private Player player; + private int selected = 0; + + private List recipes; + + public CraftingMenu(List recipes, Player player) { + this.recipes = new ArrayList(recipes); + this.player = player; + + for (int i = 0; i < recipes.size(); i++) { + this.recipes.get(i).checkCanCraft(player); + } + + Collections.sort(this.recipes, new Comparator() { + public int compare(Recipe r1, Recipe r2) { + if (r1.canCraft && !r2.canCraft) return -1; + if (!r1.canCraft && r2.canCraft) return 1; + return 0; + } + }); + } + + public void tick() { + if (input.menu.clicked) game.setMenu(null); + + if (input.up.clicked) selected--; + if (input.down.clicked) selected++; + + int len = recipes.size(); + if (len == 0) selected = 0; + if (selected < 0) selected += len; + if (selected >= len) selected -= len; + + if (input.attack.clicked && len > 0) { + Recipe r = recipes.get(selected); + r.checkCanCraft(player); + if (r.canCraft) { + r.deductCost(player); + r.craft(player); + Sound.craft.play(); + } + for (int i = 0; i < recipes.size(); i++) { + recipes.get(i).checkCanCraft(player); + } + } + } + + public void render(Screen screen) { + Font.renderFrame(screen, "Have", 12, 1, 19, 3); + Font.renderFrame(screen, "Cost", 12, 4, 19, 11); + Font.renderFrame(screen, "Crafting", 0, 1, 11, 11); + renderItemList(screen, 0, 1, 11, 11, recipes, selected); + + if (recipes.size() > 0) { + Recipe recipe = recipes.get(selected); + int hasResultItems = player.inventory.count(recipe.resultTemplate); + int xo = 13 * 8; + screen.render(xo, 2 * 8, recipe.resultTemplate.getSprite(), recipe.resultTemplate.getColor(), 0); + Font.draw("" + hasResultItems, screen, xo + 8, 2 * 8, Color.get(-1, 555, 555, 555)); + + List costs = recipe.costs; + for (int i = 0; i < costs.size(); i++) { + Item item = costs.get(i); + int yo = (5 + i) * 8; + screen.render(xo, yo, item.getSprite(), item.getColor(), 0); + int requiredAmt = 1; + if (item instanceof ResourceItem) { + requiredAmt = ((ResourceItem) item).count; + } + int has = player.inventory.count(item); + int color = Color.get(-1, 555, 555, 555); + if (has < requiredAmt) { + color = Color.get(-1, 222, 222, 222); + } + if (has > 99) has = 99; + Font.draw("" + requiredAmt + "/" + has, screen, xo + 8, yo, color); + } + } + // renderItemList(screen, 12, 4, 19, 11, recipes.get(selected).costs, -1); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/screen/DeadMenu.java b/src/com/mojang/ld22/screen/DeadMenu.java new file mode 100644 index 0000000..f14c65d --- /dev/null +++ b/src/com/mojang/ld22/screen/DeadMenu.java @@ -0,0 +1,43 @@ +package com.mojang.ld22.screen; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; + +public class DeadMenu extends Menu { + private int inputDelay = 60; + + public DeadMenu() { + } + + public void tick() { + if (inputDelay > 0) + inputDelay--; + else if (input.attack.clicked || input.menu.clicked) { + game.setMenu(new TitleMenu()); + } + } + + public void render(Screen screen) { + Font.renderFrame(screen, "", 1, 3, 18, 9); + Font.draw("You died! Aww!", screen, 2 * 8, 4 * 8, Color.get(-1, 555, 555, 555)); + + int seconds = game.gameTime / 60; + int minutes = seconds / 60; + int hours = minutes / 60; + minutes %= 60; + seconds %= 60; + + String timeString = ""; + if (hours > 0) { + timeString = hours + "h" + (minutes < 10 ? "0" : "") + minutes + "m"; + } else { + timeString = minutes + "m " + (seconds < 10 ? "0" : "") + seconds + "s"; + } + Font.draw("Time:", screen, 2 * 8, 5 * 8, Color.get(-1, 555, 555, 555)); + Font.draw(timeString, screen, (2 + 5) * 8, 5 * 8, Color.get(-1, 550, 550, 550)); + Font.draw("Score:", screen, 2 * 8, 6 * 8, Color.get(-1, 555, 555, 555)); + Font.draw("" + game.player.score, screen, (2 + 6) * 8, 6 * 8, Color.get(-1, 550, 550, 550)); + Font.draw("Press C to lose", screen, 2 * 8, 8 * 8, Color.get(-1, 333, 333, 333)); + } +} diff --git a/src/com/mojang/ld22/screen/InstructionsMenu.java b/src/com/mojang/ld22/screen/InstructionsMenu.java new file mode 100644 index 0000000..85ae711 --- /dev/null +++ b/src/com/mojang/ld22/screen/InstructionsMenu.java @@ -0,0 +1,36 @@ +package com.mojang.ld22.screen; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; + +public class InstructionsMenu extends Menu { + private Menu parent; + + public InstructionsMenu(Menu parent) { + this.parent = parent; + } + + public void tick() { + if (input.attack.clicked || input.menu.clicked) { + game.setMenu(parent); + } + } + + public void render(Screen screen) { + screen.clear(0); + + Font.draw("HOW TO PLAY", screen, 4 * 8 + 4, 1 * 8, Color.get(0, 555, 555, 555)); + Font.draw("Move your character", screen, 0 * 8 + 4, 3 * 8, Color.get(0, 333, 333, 333)); + Font.draw("with the arrow keys", screen, 0 * 8 + 4, 4 * 8, Color.get(0, 333, 333, 333)); + Font.draw("press C to attack", screen, 0 * 8 + 4, 5 * 8, Color.get(0, 333, 333, 333)); + Font.draw("and X to open the", screen, 0 * 8 + 4, 6 * 8, Color.get(0, 333, 333, 333)); + Font.draw("inventory and to", screen, 0 * 8 + 4, 7 * 8, Color.get(0, 333, 333, 333)); + Font.draw("use items.", screen, 0 * 8 + 4, 8 * 8, Color.get(0, 333, 333, 333)); + Font.draw("Select an item in", screen, 0 * 8 + 4, 9 * 8, Color.get(0, 333, 333, 333)); + Font.draw("the inventory to", screen, 0 * 8 + 4, 10 * 8, Color.get(0, 333, 333, 333)); + Font.draw("equip it.", screen, 0 * 8 + 4, 11 * 8, Color.get(0, 333, 333, 333)); + Font.draw("Kill the air wizard", screen, 0 * 8 + 4, 12 * 8, Color.get(0, 333, 333, 333)); + Font.draw("to win the game!", screen, 0 * 8 + 4, 13 * 8, Color.get(0, 333, 333, 333)); + } +} diff --git a/src/com/mojang/ld22/screen/InventoryMenu.java b/src/com/mojang/ld22/screen/InventoryMenu.java new file mode 100644 index 0000000..210b6d7 --- /dev/null +++ b/src/com/mojang/ld22/screen/InventoryMenu.java @@ -0,0 +1,43 @@ +package com.mojang.ld22.screen; + +import com.mojang.ld22.entity.Player; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.item.Item; + +public class InventoryMenu extends Menu { + private Player player; + private int selected = 0; + + public InventoryMenu(Player player) { + this.player = player; + + if (player.activeItem != null) { + player.inventory.items.add(0, player.activeItem); + player.activeItem = null; + } + } + + public void tick() { + if (input.menu.clicked) game.setMenu(null); + + if (input.up.clicked) selected--; + if (input.down.clicked) selected++; + + int len = player.inventory.items.size(); + if (len == 0) selected = 0; + if (selected < 0) selected += len; + if (selected >= len) selected -= len; + + if (input.attack.clicked && len > 0) { + Item item = player.inventory.items.remove(selected); + player.activeItem = item; + game.setMenu(null); + } + } + + public void render(Screen screen) { + Font.renderFrame(screen, "inventory", 1, 1, 12, 11); + renderItemList(screen, 1, 1, 12, 11, player.inventory.items, selected); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/screen/LevelTransitionMenu.java b/src/com/mojang/ld22/screen/LevelTransitionMenu.java new file mode 100644 index 0000000..ff97c0e --- /dev/null +++ b/src/com/mojang/ld22/screen/LevelTransitionMenu.java @@ -0,0 +1,32 @@ +package com.mojang.ld22.screen; + +import com.mojang.ld22.gfx.Screen; + +public class LevelTransitionMenu extends Menu { + private int dir; + private int time = 0; + + public LevelTransitionMenu(int dir) { + this.dir = dir; + } + + public void tick() { + time += 2; + if (time == 30) game.changeLevel(dir); + if (time == 60) game.setMenu(null); + } + + public void render(Screen screen) { + for (int x = 0; x < 20; x++) { + for (int y = 0; y < 15; y++) { + int dd = (y + x % 2 * 2 + x / 3) - time; + if (dd < 0 && dd > -30) { + if (dir > 0) + screen.render(x * 8, y * 8, 0, 0, 0); + else + screen.render(x * 8, screen.h - y * 8 - 8, 0, 0, 0); + } + } + } + } +} diff --git a/src/com/mojang/ld22/screen/ListItem.java b/src/com/mojang/ld22/screen/ListItem.java new file mode 100644 index 0000000..aa629a4 --- /dev/null +++ b/src/com/mojang/ld22/screen/ListItem.java @@ -0,0 +1,7 @@ +package com.mojang.ld22.screen; + +import com.mojang.ld22.gfx.Screen; + +public interface ListItem { + void renderInventory(Screen screen, int i, int j); +} diff --git a/src/com/mojang/ld22/screen/Menu.java b/src/com/mojang/ld22/screen/Menu.java new file mode 100644 index 0000000..d3e3cbb --- /dev/null +++ b/src/com/mojang/ld22/screen/Menu.java @@ -0,0 +1,51 @@ +package com.mojang.ld22.screen; + +import java.util.List; + +import com.mojang.ld22.Game; +import com.mojang.ld22.InputHandler; +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; + +public class Menu { + protected Game game; + protected InputHandler input; + + public void init(Game game, InputHandler input) { + this.input = input; + this.game = game; + } + + public void tick() { + } + + public void render(Screen screen) { + } + + public void renderItemList(Screen screen, int xo, int yo, int x1, int y1, List listItems, int selected) { + boolean renderCursor = true; + if (selected < 0) { + selected = -selected - 1; + renderCursor = false; + } + int w = x1 - xo; + int h = y1 - yo - 1; + int i0 = 0; + int i1 = listItems.size(); + if (i1 > h) i1 = h; + int io = selected - h / 2; + if (io > listItems.size() - h) io = listItems.size() - h; + if (io < 0) io = 0; + + for (int i = i0; i < i1; i++) { + listItems.get(i + io).renderInventory(screen, (1 + xo) * 8, (i + 1 + yo) * 8); + } + + if (renderCursor) { + int yy = selected + 1 - io + yo; + Font.draw(">", screen, (xo + 0) * 8, yy * 8, Color.get(5, 555, 555, 555)); + Font.draw("<", screen, (xo + w) * 8, yy * 8, Color.get(5, 555, 555, 555)); + } + } +} diff --git a/src/com/mojang/ld22/screen/TitleMenu.java b/src/com/mojang/ld22/screen/TitleMenu.java new file mode 100644 index 0000000..7afebb8 --- /dev/null +++ b/src/com/mojang/ld22/screen/TitleMenu.java @@ -0,0 +1,61 @@ +package com.mojang.ld22.screen; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; +import com.mojang.ld22.sound.Sound; + +public class TitleMenu extends Menu { + private int selected = 0; + + private static final String[] options = { "Start game", "How to play", "About" }; + + public TitleMenu() { + } + + public void tick() { + if (input.up.clicked) selected--; + if (input.down.clicked) selected++; + + int len = options.length; + if (selected < 0) selected += len; + if (selected >= len) selected -= len; + + if (input.attack.clicked || input.menu.clicked) { + if (selected == 0) { + Sound.test.play(); + game.resetGame(); + game.setMenu(null); + } + if (selected == 1) game.setMenu(new InstructionsMenu(this)); + if (selected == 2) game.setMenu(new AboutMenu(this)); + } + } + + public void render(Screen screen) { + screen.clear(0); + + int h = 2; + int w = 13; + int titleColor = Color.get(0, 010, 131, 551); + int xo = (screen.w - w * 8) / 2; + int yo = 24; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + screen.render(xo + x * 8, yo + y * 8, x + (y + 6) * 32, titleColor, 0); + } + } + + for (int i = 0; i < 3; i++) { + String msg = options[i]; + int col = Color.get(0, 222, 222, 222); + if (i == selected) { + msg = "> " + msg + " <"; + col = Color.get(0, 555, 555, 555); + } + Font.draw(msg, screen, (screen.w - msg.length() * 8) / 2, (8 + i) * 8, col); + } + + Font.draw("(Arrow keys,X and C)", screen, 0, screen.h - 8, Color.get(0, 111, 111, 111)); + } +} \ No newline at end of file diff --git a/src/com/mojang/ld22/screen/WonMenu.java b/src/com/mojang/ld22/screen/WonMenu.java new file mode 100644 index 0000000..79a55ea --- /dev/null +++ b/src/com/mojang/ld22/screen/WonMenu.java @@ -0,0 +1,43 @@ +package com.mojang.ld22.screen; + +import com.mojang.ld22.gfx.Color; +import com.mojang.ld22.gfx.Font; +import com.mojang.ld22.gfx.Screen; + +public class WonMenu extends Menu { + private int inputDelay = 60; + + public WonMenu() { + } + + public void tick() { + if (inputDelay > 0) + inputDelay--; + else if (input.attack.clicked || input.menu.clicked) { + game.setMenu(new TitleMenu()); + } + } + + public void render(Screen screen) { + Font.renderFrame(screen, "", 1, 3, 18, 9); + Font.draw("You won! Yay!", screen, 2 * 8, 4 * 8, Color.get(-1, 555, 555, 555)); + + int seconds = game.gameTime / 60; + int minutes = seconds / 60; + int hours = minutes / 60; + minutes %= 60; + seconds %= 60; + + String timeString = ""; + if (hours > 0) { + timeString = hours + "h" + (minutes < 10 ? "0" : "") + minutes + "m"; + } else { + timeString = minutes + "m " + (seconds < 10 ? "0" : "") + seconds + "s"; + } + Font.draw("Time:", screen, 2 * 8, 5 * 8, Color.get(-1, 555, 555, 555)); + Font.draw(timeString, screen, (2 + 5) * 8, 5 * 8, Color.get(-1, 550, 550, 550)); + Font.draw("Score:", screen, 2 * 8, 6 * 8, Color.get(-1, 555, 555, 555)); + Font.draw("" + game.player.score, screen, (2 + 6) * 8, 6 * 8, Color.get(-1, 550, 550, 550)); + Font.draw("Press C to win", screen, 2 * 8, 8 * 8, Color.get(-1, 333, 333, 333)); + } +} diff --git a/src/com/mojang/ld22/sound/Sound.java b/src/com/mojang/ld22/sound/Sound.java new file mode 100644 index 0000000..147fe5c --- /dev/null +++ b/src/com/mojang/ld22/sound/Sound.java @@ -0,0 +1,36 @@ +package com.mojang.ld22.sound; + +import java.applet.Applet; +import java.applet.AudioClip; + +public class Sound { + public static final Sound playerHurt = new Sound("/playerhurt.wav"); + public static final Sound playerDeath = new Sound("/death.wav"); + public static final Sound monsterHurt = new Sound("/monsterhurt.wav"); + public static final Sound test = new Sound("/test.wav"); + public static final Sound pickup = new Sound("/pickup.wav"); + public static final Sound bossdeath = new Sound("/bossdeath.wav"); + public static final Sound craft = new Sound("/craft.wav"); + + private AudioClip clip; + + private Sound(String name) { + try { + clip = Applet.newAudioClip(Sound.class.getResource(name)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void play() { + try { + new Thread() { + public void run() { + clip.play(); + } + }.start(); + } catch (Throwable e) { + e.printStackTrace(); + } + } +} \ No newline at end of file