├── README.md ├── Rain ├── .classpath ├── .gitignore ├── .project ├── .settings │ └── org.eclipse.jdt.core.prefs ├── Sprites.aep ├── res │ ├── data │ │ └── screen.bin │ ├── fonts │ │ └── arial.png │ ├── levels │ │ ├── level.png │ │ └── spawn.png │ └── textures │ │ ├── home.png │ │ ├── playerback.png │ │ ├── playerfront.png │ │ ├── playerleft.png │ │ ├── playerright.png │ │ ├── sheets │ │ ├── king_cherno.png │ │ ├── player.png │ │ ├── player_sheet.png │ │ ├── projectiles │ │ │ └── wizard.png │ │ ├── spawn_level.png │ │ ├── spawn_lvl.png │ │ ├── spritesheet.png │ │ └── trig.png │ │ └── spritesheet.png └── src │ └── com │ └── thecherno │ └── rain │ ├── Game.java │ ├── entity │ ├── Entity.java │ ├── mob │ │ ├── Chaser.java │ │ ├── Dummy.java │ │ ├── Mob.java │ │ ├── Player.java │ │ ├── Shooter.java │ │ └── Star.java │ ├── particle │ │ └── Particle.java │ ├── projectile │ │ ├── Projectile.java │ │ └── WizardProjectile.java │ └── spawner │ │ ├── ParticleSpawner.java │ │ └── Spawner.java │ ├── events │ ├── Event.java │ ├── EventDispatcher.java │ ├── EventHandler.java │ ├── EventListener.java │ └── types │ │ ├── MouseButtonEvent.java │ │ ├── MouseMovedEvent.java │ │ ├── MousePressedEvent.java │ │ └── MouseReleasedEvent.java │ ├── graphics │ ├── AnimatedSprite.java │ ├── Font.java │ ├── Screen.java │ ├── Sprite.java │ ├── SpriteSheet.java │ ├── layers │ │ └── Layer.java │ └── ui │ │ ├── UIActionListener.java │ │ ├── UIButton.java │ │ ├── UIButtonListener.java │ │ ├── UIComponent.java │ │ ├── UILabel.java │ │ ├── UIManager.java │ │ ├── UIPanel.java │ │ └── UIProgressBar.java │ ├── input │ ├── Keyboard.java │ └── Mouse.java │ ├── level │ ├── Level.java │ ├── Node.java │ ├── RandomLevel.java │ ├── SpawnLevel.java │ ├── TileCoordinate.java │ └── tile │ │ ├── FlowerTile.java │ │ ├── GrassTile.java │ │ ├── RockTile.java │ │ ├── Tile.java │ │ ├── VoidTile.java │ │ └── spawn_level │ │ ├── SpawnFloorTile.java │ │ ├── SpawnGrassTile.java │ │ ├── SpawnHedgeTile.java │ │ ├── SpawnWallTile.java │ │ └── SpawnWaterTile.java │ ├── net │ ├── Client.java │ └── player │ │ └── NetPlayer.java │ └── util │ ├── BinaryWriter.java │ ├── Debug.java │ ├── ImageUtils.java │ ├── MathUtils.java │ └── Vector2i.java ├── RainCloud-Serialization ├── .classpath ├── .project ├── .settings │ └── org.eclipse.jdt.core.prefs └── src │ └── com │ └── thecherno │ └── raincloud │ └── serialization │ ├── ContainerType.java │ ├── RCArray.java │ ├── RCBase.java │ ├── RCDatabase.java │ ├── RCField.java │ ├── RCObject.java │ ├── RCString.java │ ├── SerializationUtils.java │ └── Type.java └── RainServer ├── .classpath ├── .gitignore ├── .project ├── .settings └── org.eclipse.jdt.core.prefs └── src └── com └── thecherno └── rainserver ├── RainServer.java ├── Server.java └── ServerClient.java /README.md: -------------------------------------------------------------------------------- 1 | Game Programming 2 | ================ 3 | 4 | Welcome to the official Game Programming repository! This is the source code from a YouTube series you can find here: https://www.youtube.com/playlist?list=PLlrATfBNZ98eOOCk2fOFg7Qg5yoQfFAdf 5 | -------------------------------------------------------------------------------- /Rain/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Rain/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | .class -------------------------------------------------------------------------------- /Rain/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Rain 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /Rain/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /Rain/Sprites.aep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/Sprites.aep -------------------------------------------------------------------------------- /Rain/res/data/screen.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/data/screen.bin -------------------------------------------------------------------------------- /Rain/res/fonts/arial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/fonts/arial.png -------------------------------------------------------------------------------- /Rain/res/levels/level.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/levels/level.png -------------------------------------------------------------------------------- /Rain/res/levels/spawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/levels/spawn.png -------------------------------------------------------------------------------- /Rain/res/textures/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/home.png -------------------------------------------------------------------------------- /Rain/res/textures/playerback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/playerback.png -------------------------------------------------------------------------------- /Rain/res/textures/playerfront.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/playerfront.png -------------------------------------------------------------------------------- /Rain/res/textures/playerleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/playerleft.png -------------------------------------------------------------------------------- /Rain/res/textures/playerright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/playerright.png -------------------------------------------------------------------------------- /Rain/res/textures/sheets/king_cherno.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/sheets/king_cherno.png -------------------------------------------------------------------------------- /Rain/res/textures/sheets/player.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/sheets/player.png -------------------------------------------------------------------------------- /Rain/res/textures/sheets/player_sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/sheets/player_sheet.png -------------------------------------------------------------------------------- /Rain/res/textures/sheets/projectiles/wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/sheets/projectiles/wizard.png -------------------------------------------------------------------------------- /Rain/res/textures/sheets/spawn_level.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/sheets/spawn_level.png -------------------------------------------------------------------------------- /Rain/res/textures/sheets/spawn_lvl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/sheets/spawn_lvl.png -------------------------------------------------------------------------------- /Rain/res/textures/sheets/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/sheets/spritesheet.png -------------------------------------------------------------------------------- /Rain/res/textures/sheets/trig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/sheets/trig.png -------------------------------------------------------------------------------- /Rain/res/textures/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/res/textures/spritesheet.png -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/Game.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain; 2 | 3 | import java.awt.Canvas; 4 | import java.awt.Color; 5 | import java.awt.Dimension; 6 | import java.awt.Graphics; 7 | import java.awt.image.BufferStrategy; 8 | import java.awt.image.BufferedImage; 9 | import java.awt.image.DataBufferInt; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | import javax.swing.JFrame; 14 | 15 | import com.thecherno.rain.entity.mob.Player; 16 | import com.thecherno.rain.events.Event; 17 | import com.thecherno.rain.events.EventListener; 18 | import com.thecherno.rain.graphics.Screen; 19 | import com.thecherno.rain.graphics.layers.Layer; 20 | import com.thecherno.rain.graphics.ui.UIManager; 21 | import com.thecherno.rain.input.Keyboard; 22 | import com.thecherno.rain.input.Mouse; 23 | import com.thecherno.rain.level.Level; 24 | import com.thecherno.rain.level.TileCoordinate; 25 | import com.thecherno.rain.net.Client; 26 | import com.thecherno.rain.net.player.NetPlayer; 27 | import com.thecherno.raincloud.serialization.RCDatabase; 28 | import com.thecherno.raincloud.serialization.RCField; 29 | import com.thecherno.raincloud.serialization.RCObject; 30 | 31 | public class Game extends Canvas implements Runnable, EventListener { 32 | private static final long serialVersionUID = 1L; 33 | 34 | private static int width = 300 - 80; 35 | private static int height = 168; 36 | private static int scale = 3; 37 | public static String title = "Rain"; 38 | 39 | private Thread thread; 40 | private JFrame frame; 41 | private Keyboard key; 42 | private Level level; 43 | private Player player; 44 | private boolean running = false; 45 | 46 | private static UIManager uiManager; 47 | 48 | private Screen screen; 49 | private BufferedImage image; 50 | private int[] pixels; 51 | 52 | private List layerStack = new ArrayList(); 53 | 54 | public Game() { 55 | setSize(); 56 | 57 | screen = new Screen(width, height); 58 | uiManager = new UIManager(); 59 | frame = new JFrame(); 60 | key = new Keyboard(); 61 | 62 | // TODO: Connect to server here! 63 | Client client = new Client("localhost", 8192); 64 | if (!client.connect()) { 65 | // TODO: We didn't connect 66 | } 67 | 68 | RCDatabase db = RCDatabase.DeserializeFromFile("res/data/screen.bin"); 69 | // client.send(db); 70 | 71 | level = Level.spawn; 72 | addLayer(level); 73 | TileCoordinate playerSpawn = new TileCoordinate(19, 42); 74 | player = new Player("Cherno", playerSpawn.x(), playerSpawn.y(), key); 75 | level.add(player); 76 | level.addPlayer(new NetPlayer()); 77 | addKeyListener(key); 78 | 79 | Mouse mouse = new Mouse(this); 80 | addMouseListener(mouse); 81 | addMouseMotionListener(mouse); 82 | 83 | save(); 84 | } 85 | 86 | private void setSize() { 87 | RCDatabase db = RCDatabase.DeserializeFromFile("res/data/screen.bin"); 88 | if (db != null) { 89 | RCObject obj = db.findObject("Resolution"); 90 | width = obj.findField("width").getInt(); 91 | height = obj.findField("height").getInt(); 92 | scale = obj.findField("scale").getInt(); 93 | } 94 | 95 | Dimension size = new Dimension(width * scale + 80 * 3, height * scale); 96 | setPreferredSize(size); 97 | 98 | image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 99 | pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); 100 | } 101 | 102 | private void save() { 103 | RCDatabase db = new RCDatabase("Screen"); 104 | 105 | RCObject obj = new RCObject("Resolution"); 106 | obj.addField(RCField.Integer("width", width)); 107 | obj.addField(RCField.Integer("height", height)); 108 | obj.addField(RCField.Integer("scale", scale)); 109 | db.addObject(obj); 110 | 111 | db.serializeToFile("res/data/screen.bin"); 112 | } 113 | 114 | public static int getWindowWidth() { 115 | return width * scale; 116 | } 117 | 118 | public static int getWindowHeight() { 119 | return height * scale; 120 | } 121 | 122 | public static UIManager getUIManager() { 123 | return uiManager; 124 | } 125 | 126 | public void addLayer(Layer layer) { 127 | layerStack.add(layer); 128 | } 129 | 130 | public synchronized void start() { 131 | running = true; 132 | thread = new Thread(this, "Display"); 133 | thread.start(); 134 | } 135 | 136 | public synchronized void stop() { 137 | running = false; 138 | try { 139 | thread.join(); 140 | } catch (InterruptedException e) { 141 | e.printStackTrace(); 142 | } 143 | } 144 | 145 | public void run() { 146 | long lastTime = System.nanoTime(); 147 | long timer = System.currentTimeMillis(); 148 | final double ns = 1000000000.0 / 60.0; 149 | double delta = 0; 150 | int frames = 0; 151 | int updates = 0; 152 | requestFocus(); 153 | while (running) { 154 | long now = System.nanoTime(); 155 | delta += (now - lastTime) / ns; 156 | lastTime = now; 157 | while (delta >= 1) { 158 | update(); 159 | updates++; 160 | delta--; 161 | } 162 | render(); 163 | frames++; 164 | 165 | if (System.currentTimeMillis() - timer > 1000) { 166 | timer += 1000; 167 | System.out.println(updates + " ups, " + frames + " fps"); 168 | frame.setTitle(title + " | " + updates + " ups, " + frames + " fps"); 169 | updates = 0; 170 | frames = 0; 171 | } 172 | } 173 | stop(); 174 | } 175 | 176 | public void onEvent(Event event) { 177 | for (int i = layerStack.size() - 1; i >= 0; i--) { 178 | layerStack.get(i).onEvent(event); 179 | } 180 | } 181 | 182 | public void update() { 183 | key.update(); 184 | uiManager.update(); 185 | 186 | // Update layers here 187 | for (int i = 0; i < layerStack.size(); i++) { 188 | layerStack.get(i).update(); 189 | } 190 | } 191 | 192 | public void render() { 193 | BufferStrategy bs = getBufferStrategy(); 194 | if (bs == null) { 195 | createBufferStrategy(3); 196 | return; 197 | } 198 | 199 | screen.clear(); 200 | int xScroll = player.getX() - screen.width / 2; 201 | int yScroll = player.getY() - screen.height / 2; 202 | level.setScroll(xScroll, yScroll); 203 | 204 | // Render layers here 205 | for (int i = 0; i < layerStack.size(); i++) { 206 | layerStack.get(i).render(screen); 207 | } 208 | 209 | // font.render(50, 50, -3, "Hey what's up\nguys, My name is\nThe Cherno!", screen); 210 | // screen.renderSheet(40, 40, SpriteSheet.player_down, false); 211 | for (int i = 0; i < pixels.length; i++) { 212 | pixels[i] = screen.pixels[i]; 213 | } 214 | Graphics g = bs.getDrawGraphics(); 215 | g.setColor(new Color(0xff00ff)); 216 | g.fillRect(0, 0, getWidth(), getHeight()); 217 | g.drawImage(image, 0, 0, width * scale, height * scale, null); 218 | uiManager.render(g); 219 | // g.fillRect(Mouse.getX() - 32, Mouse.getY() - 32, 64, 64); 220 | // if (Mouse.getButton() != -1) g.drawString("Button: " + Mouse.getButton(), 80, 80); 221 | g.dispose(); 222 | bs.show(); 223 | } 224 | 225 | public static void main(String[] args) { 226 | Game game = new Game(); 227 | game.frame.setResizable(false); 228 | game.frame.setTitle(Game.title); 229 | game.frame.add(game); 230 | game.frame.pack(); 231 | game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 232 | game.frame.setLocationRelativeTo(null); 233 | game.frame.setVisible(true); 234 | 235 | game.start(); 236 | } 237 | 238 | } 239 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/Entity.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity; 2 | 3 | import java.util.Random; 4 | 5 | import com.thecherno.rain.graphics.Screen; 6 | import com.thecherno.rain.graphics.Sprite; 7 | import com.thecherno.rain.level.Level; 8 | 9 | public class Entity { 10 | 11 | protected int x, y; 12 | protected Sprite sprite; 13 | private boolean removed = false; 14 | protected Level level; 15 | protected final Random random = new Random(); 16 | 17 | public Entity() { 18 | } 19 | 20 | public Entity(int x, int y, Sprite sprite) { 21 | this.x = x; 22 | this.y = y; 23 | this.sprite = sprite; 24 | } 25 | 26 | public void update() { 27 | } 28 | 29 | public void render(Screen screen) { 30 | if (sprite != null) screen.renderSprite(x, y, sprite, true); 31 | } 32 | 33 | public void remove() { 34 | //Remove from level 35 | removed = true; 36 | } 37 | 38 | public int getX() { 39 | return x; 40 | } 41 | 42 | public int getY() { 43 | return y; 44 | } 45 | 46 | public Sprite getSprite() { 47 | return sprite; 48 | } 49 | 50 | public boolean isRemoved() { 51 | return removed; 52 | } 53 | 54 | public void init(Level level) { 55 | this.level = level; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/mob/Chaser.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.mob; 2 | 3 | import java.util.List; 4 | 5 | import com.thecherno.rain.graphics.AnimatedSprite; 6 | import com.thecherno.rain.graphics.Screen; 7 | import com.thecherno.rain.graphics.Sprite; 8 | import com.thecherno.rain.graphics.SpriteSheet; 9 | 10 | public class Chaser extends Mob { 11 | 12 | private AnimatedSprite down = new AnimatedSprite(SpriteSheet.dummy_down, 32, 32, 3); 13 | private AnimatedSprite up = new AnimatedSprite(SpriteSheet.dummy_up, 32, 32, 3); 14 | private AnimatedSprite left = new AnimatedSprite(SpriteSheet.dummy_left, 32, 32, 3); 15 | private AnimatedSprite right = new AnimatedSprite(SpriteSheet.dummy_right, 32, 32, 3); 16 | 17 | private AnimatedSprite animSprite = down; 18 | 19 | private int xa = 0; 20 | private int ya = 0; 21 | 22 | public Chaser(int x, int y) { 23 | this.x = x << 4; 24 | this.y = y << 4; 25 | sprite = Sprite.dummy; 26 | } 27 | 28 | private void move() { 29 | xa = 0; 30 | ya = 0; 31 | List players = level.getPlayers(this, 50); 32 | if (players.size() > 0) { 33 | Mob player = players.get(0); 34 | if (x < player.getX()) xa++; 35 | if (x > player.getX()) xa--; 36 | if (y < player.getY()) ya++; 37 | if (y > player.getY()) ya--; 38 | } 39 | if (xa != 0 || ya != 0) { 40 | move(xa, ya); 41 | walking = true; 42 | } else { 43 | walking = false; 44 | } 45 | } 46 | 47 | public void update() { 48 | move(); 49 | if (walking) animSprite.update(); 50 | else animSprite.setFrame(0); 51 | if (ya < 0) { 52 | animSprite = up; 53 | dir = Direction.UP; 54 | } else if (ya > 0) { 55 | animSprite = down; 56 | dir = Direction.DOWN; 57 | } 58 | if (xa < 0) { 59 | animSprite = left; 60 | dir = Direction.LEFT; 61 | } else if (xa > 0) { 62 | animSprite = right; 63 | dir = Direction.RIGHT; 64 | } 65 | } 66 | 67 | public void render(Screen screen) { 68 | sprite = animSprite.getSprite(); 69 | screen.renderMob(x - 16, y - 16, this); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/mob/Dummy.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.mob; 2 | 3 | import com.thecherno.rain.graphics.AnimatedSprite; 4 | import com.thecherno.rain.graphics.Screen; 5 | import com.thecherno.rain.graphics.Sprite; 6 | import com.thecherno.rain.graphics.SpriteSheet; 7 | 8 | public class Dummy extends Mob { 9 | 10 | private AnimatedSprite down = new AnimatedSprite(SpriteSheet.dummy_down, 32, 32, 3); 11 | private AnimatedSprite up = new AnimatedSprite(SpriteSheet.dummy_up, 32, 32, 3); 12 | private AnimatedSprite left = new AnimatedSprite(SpriteSheet.dummy_left, 32, 32, 3); 13 | private AnimatedSprite right = new AnimatedSprite(SpriteSheet.dummy_right, 32, 32, 3); 14 | 15 | private AnimatedSprite animSprite = down; 16 | 17 | private int time = 0; 18 | private int xa = 0; 19 | private int ya = 0; 20 | 21 | public Dummy(int x, int y) { 22 | this.x = x << 4; 23 | this.y = y << 4; 24 | sprite = Sprite.dummy; 25 | } 26 | 27 | public void update() { 28 | time++; 29 | if (time % (random.nextInt(50) + 30) == 0) { 30 | xa = random.nextInt(3) - 1; 31 | ya = random.nextInt(3) - 1; 32 | if (random.nextInt(4) == 0) { 33 | xa = 0; 34 | ya = 0; 35 | } 36 | } 37 | if (walking) animSprite.update(); 38 | else animSprite.setFrame(0); 39 | if (ya < 0) { 40 | animSprite = up; 41 | dir = Direction.UP; 42 | } else if (ya > 0) { 43 | animSprite = down; 44 | dir = Direction.DOWN; 45 | } 46 | if (xa < 0) { 47 | animSprite = left; 48 | dir = Direction.LEFT; 49 | } else if (xa > 0) { 50 | animSprite = right; 51 | dir = Direction.RIGHT; 52 | } 53 | if (xa != 0 || ya != 0) { 54 | //move(xa, ya); 55 | walking = true; 56 | } else { 57 | walking = false; 58 | } 59 | } 60 | 61 | public void render(Screen screen) { 62 | sprite = animSprite.getSprite(); 63 | screen.renderMob(x, y, sprite, 0); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/mob/Mob.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.mob; 2 | 3 | import com.thecherno.rain.entity.Entity; 4 | import com.thecherno.rain.entity.projectile.Projectile; 5 | import com.thecherno.rain.entity.projectile.WizardProjectile; 6 | import com.thecherno.rain.graphics.Screen; 7 | 8 | public abstract class Mob extends Entity { 9 | 10 | protected boolean moving = false; 11 | protected boolean walking = false; 12 | 13 | protected int health; 14 | 15 | protected enum Direction { 16 | UP, DOWN, LEFT, RIGHT 17 | } 18 | 19 | protected Direction dir; 20 | 21 | public void move(double xa, double ya) { 22 | if (xa != 0 && ya != 0) { 23 | move(xa, 0); 24 | move(0, ya); 25 | return; 26 | } 27 | 28 | if (xa > 0) dir = Direction.RIGHT; 29 | if (xa < 0) dir = Direction.LEFT; 30 | if (ya > 0) dir = Direction.DOWN; 31 | if (ya < 0) dir = Direction.UP; 32 | 33 | for (int x = 0; x < Math.abs(xa); x++) { 34 | if (!collision(abs(xa), ya)) { 35 | this.x += abs(xa); 36 | } 37 | } 38 | 39 | for (int y = 0; y < Math.abs(ya); y++) { 40 | if (!collision(xa, abs(ya))) { 41 | this.y += abs(ya); 42 | } 43 | } 44 | } 45 | 46 | private int abs(double value) { 47 | if (value < 0) return -1; 48 | return 1; 49 | } 50 | 51 | public abstract void update(); 52 | 53 | public abstract void render(Screen screen); 54 | 55 | protected void shoot(int x, int y, double dir) { 56 | Projectile p = new WizardProjectile(x, y, dir); 57 | level.add(p); 58 | } 59 | 60 | private boolean collision(double xa, double ya) { 61 | boolean solid = false; 62 | for (int c = 0; c < 4; c++) { 63 | double xt = ((x + xa) - c % 2 * 15) / 16; 64 | double yt = ((y + ya) - c / 2 * 15) / 16; 65 | int ix = (int) Math.ceil(xt); 66 | int iy = (int) Math.ceil(yt); 67 | if (c % 2 == 0) ix = (int) Math.floor(xt); 68 | if (c / 2 == 0) iy = (int) Math.floor(yt); 69 | if (level.getTile(ix, iy).solid()) solid = true; 70 | } 71 | return solid; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/mob/Player.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.mob; 2 | 3 | import java.awt.Font; 4 | import java.awt.event.MouseEvent; 5 | import java.awt.image.BufferedImage; 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | import javax.imageio.ImageIO; 10 | 11 | import com.thecherno.rain.Game; 12 | import com.thecherno.rain.entity.projectile.Projectile; 13 | import com.thecherno.rain.entity.projectile.WizardProjectile; 14 | import com.thecherno.rain.events.Event; 15 | import com.thecherno.rain.events.EventDispatcher; 16 | import com.thecherno.rain.events.EventListener; 17 | import com.thecherno.rain.events.types.MousePressedEvent; 18 | import com.thecherno.rain.events.types.MouseReleasedEvent; 19 | import com.thecherno.rain.graphics.AnimatedSprite; 20 | import com.thecherno.rain.graphics.Screen; 21 | import com.thecherno.rain.graphics.Sprite; 22 | import com.thecherno.rain.graphics.SpriteSheet; 23 | import com.thecherno.rain.graphics.ui.UIActionListener; 24 | import com.thecherno.rain.graphics.ui.UIButton; 25 | import com.thecherno.rain.graphics.ui.UIButtonListener; 26 | import com.thecherno.rain.graphics.ui.UILabel; 27 | import com.thecherno.rain.graphics.ui.UIManager; 28 | import com.thecherno.rain.graphics.ui.UIPanel; 29 | import com.thecherno.rain.graphics.ui.UIProgressBar; 30 | import com.thecherno.rain.input.Keyboard; 31 | import com.thecherno.rain.input.Mouse; 32 | import com.thecherno.rain.util.ImageUtils; 33 | import com.thecherno.rain.util.Vector2i; 34 | 35 | public class Player extends Mob implements EventListener { 36 | 37 | private String name; 38 | private Keyboard input; 39 | private Sprite sprite; 40 | private boolean walking = false; 41 | 42 | private AnimatedSprite down = new AnimatedSprite(SpriteSheet.player_down, 32, 32, 3); 43 | private AnimatedSprite up = new AnimatedSprite(SpriteSheet.player_up, 32, 32, 3); 44 | private AnimatedSprite left = new AnimatedSprite(SpriteSheet.player_left, 32, 32, 3); 45 | private AnimatedSprite right = new AnimatedSprite(SpriteSheet.player_right, 32, 32, 3); 46 | 47 | private AnimatedSprite animSprite = down; 48 | 49 | private int fireRate = 0; 50 | 51 | private UIManager ui; 52 | private UIProgressBar uiHealthBar; 53 | private UIButton button; 54 | 55 | private BufferedImage image; 56 | 57 | private boolean shooting = false; 58 | 59 | @Deprecated 60 | public Player(String name, Keyboard input) { 61 | this.name = name; 62 | this.input = input; 63 | sprite = Sprite.player_forward; 64 | } 65 | 66 | public Player(String name, int x, int y, Keyboard input) { 67 | this.name = name; 68 | this.x = x; 69 | this.y = y; 70 | this.input = input; 71 | sprite = Sprite.player_forward; 72 | fireRate = WizardProjectile.FIRE_RATE; 73 | 74 | ui = Game.getUIManager(); 75 | UIPanel panel = (UIPanel) new UIPanel(new Vector2i((300 - 80) * 3, 0), new Vector2i(80 * 3, 168 * 3)).setColor(0x4f4f4f); 76 | ui.addPanel(panel); 77 | UILabel nameLabel = new UILabel(new Vector2i(40, 200), name); 78 | nameLabel.setColor(0xbbbbbb); 79 | nameLabel.setFont(new Font("Verdana", Font.PLAIN, 24)); 80 | nameLabel.dropShadow = true; 81 | panel.addComponent(nameLabel); 82 | 83 | uiHealthBar = new UIProgressBar(new Vector2i(10, 215), new Vector2i(80 * 3 - 20, 20)); 84 | uiHealthBar.setColor(0x6a6a6a); 85 | uiHealthBar.setForegroundColor(0xee3030); 86 | panel.addComponent(uiHealthBar); 87 | 88 | UILabel hpLabel = new UILabel(new Vector2i(uiHealthBar.position).add(new Vector2i(2, 16)), "HP"); 89 | hpLabel.setColor(0xffffff); 90 | hpLabel.setFont(new Font("Verdana", Font.PLAIN, 18)); 91 | panel.addComponent(hpLabel); 92 | // Player default attributes 93 | health = 100; 94 | 95 | button = new UIButton(new Vector2i(10, 260), new Vector2i(100, 30), new UIActionListener() { 96 | public void perform() { 97 | System.out.println("Action Performed!"); 98 | } 99 | }); 100 | button.setText("Hello"); 101 | panel.addComponent(button); 102 | 103 | try { 104 | image = ImageIO.read(new File("res/textures/home.png")); 105 | System.out.println(image.getType()); 106 | } catch (IOException e) { 107 | e.printStackTrace(); 108 | } 109 | 110 | UIButton imageButton = new UIButton(new Vector2i(10, 360), image, new UIActionListener() { 111 | public void perform() { 112 | System.exit(0); 113 | } 114 | }); 115 | imageButton.setButtonListener(new UIButtonListener() { 116 | public void entered(UIButton button) { 117 | button.setImage(ImageUtils.changeBrightness(image, -50)); 118 | } 119 | 120 | public void exited(UIButton button) { 121 | button.setImage(image); 122 | } 123 | 124 | public void pressed(UIButton button) { 125 | button.setImage(ImageUtils.changeBrightness(image, 50)); 126 | } 127 | 128 | public void released(UIButton button) { 129 | button.setImage(image); 130 | } 131 | }); 132 | panel.addComponent(imageButton); 133 | } 134 | 135 | public String getName() { 136 | return name; 137 | } 138 | 139 | public void onEvent(Event event) { 140 | EventDispatcher dispatcher = new EventDispatcher(event); 141 | dispatcher.dispatch(Event.Type.MOUSE_PRESSED, (Event e) -> onMousePressed((MousePressedEvent) e)); 142 | dispatcher.dispatch(Event.Type.MOUSE_RELEASED, (Event e) -> onMouseReleased((MouseReleasedEvent) e)); 143 | } 144 | 145 | public void update() { 146 | if (walking) animSprite.update(); 147 | else animSprite.setFrame(0); 148 | if (fireRate > 0) fireRate--; 149 | int xa = 0, ya = 0; 150 | if (input.up) { 151 | animSprite = up; 152 | ya -= 2; 153 | } else if (input.down) { 154 | animSprite = down; 155 | ya += 2; 156 | } 157 | if (input.left) { 158 | animSprite = left; 159 | xa -= 2; 160 | } else if (input.right) { 161 | animSprite = right; 162 | xa += 2; 163 | } 164 | if (xa != 0 || ya != 0) { 165 | move(xa, ya); 166 | walking = true; 167 | } else { 168 | walking = false; 169 | } 170 | clear(); 171 | updateShooting(); 172 | 173 | uiHealthBar.setProgress(health / 100.0); 174 | } 175 | 176 | private void updateShooting() { 177 | if (!shooting || fireRate > 0) 178 | return; 179 | 180 | double dx = Mouse.getX() - Game.getWindowWidth() / 2; 181 | double dy = Mouse.getY() - Game.getWindowHeight() / 2; 182 | double dir = Math.atan2(dy, dx); 183 | shoot(x, y, dir); 184 | fireRate = WizardProjectile.FIRE_RATE; 185 | } 186 | 187 | public boolean onMousePressed(MousePressedEvent e) { 188 | if (Mouse.getX() > 660) 189 | return false; 190 | 191 | if (e.getButton() == MouseEvent.BUTTON1) { 192 | shooting = true; 193 | return true; 194 | } 195 | return false; 196 | } 197 | 198 | public boolean onMouseReleased(MouseReleasedEvent e) { 199 | if (e.getButton() == MouseEvent.BUTTON1) { 200 | shooting = false; 201 | return true; 202 | } 203 | return false; 204 | } 205 | 206 | private void clear() { 207 | for (int i = 0; i < level.getProjectiles().size(); i++) { 208 | Projectile p = level.getProjectiles().get(i); 209 | if (p.isRemoved()) level.getProjectiles().remove(i); 210 | } 211 | } 212 | 213 | public void render(Screen screen) { 214 | int flip = 0; 215 | sprite = animSprite.getSprite(); 216 | screen.renderMob(x - 16, y - 16, sprite, flip); 217 | } 218 | 219 | } 220 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/mob/Shooter.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.mob; 2 | 3 | import java.util.List; 4 | 5 | import com.thecherno.rain.entity.Entity; 6 | import com.thecherno.rain.graphics.AnimatedSprite; 7 | import com.thecherno.rain.graphics.Screen; 8 | import com.thecherno.rain.graphics.Sprite; 9 | import com.thecherno.rain.graphics.SpriteSheet; 10 | import com.thecherno.rain.util.Vector2i; 11 | 12 | public class Shooter extends Mob { 13 | 14 | private AnimatedSprite down = new AnimatedSprite(SpriteSheet.dummy_down, 32, 32, 3); 15 | private AnimatedSprite up = new AnimatedSprite(SpriteSheet.dummy_up, 32, 32, 3); 16 | private AnimatedSprite left = new AnimatedSprite(SpriteSheet.dummy_left, 32, 32, 3); 17 | private AnimatedSprite right = new AnimatedSprite(SpriteSheet.dummy_right, 32, 32, 3); 18 | 19 | private AnimatedSprite animSprite = down; 20 | private int time = 0; 21 | private int xa = 0, ya = 0; 22 | 23 | private Entity rand = null; 24 | 25 | public Shooter(int x, int y) { 26 | this.x = x << 4; 27 | this.y = y << 4; 28 | sprite = Sprite.dummy; 29 | } 30 | 31 | public void update() { 32 | time++; 33 | if (time % (random.nextInt(50) + 30) == 0) { 34 | xa = random.nextInt(3) - 1; 35 | ya = random.nextInt(3) - 1; 36 | if (random.nextInt(4) == 0) { 37 | xa = 0; 38 | ya = 0; 39 | } 40 | } 41 | if (walking) animSprite.update(); 42 | else animSprite.setFrame(0); 43 | if (ya < 0) { 44 | animSprite = up; 45 | dir = Direction.UP; 46 | } else if (ya > 0) { 47 | animSprite = down; 48 | dir = Direction.DOWN; 49 | } 50 | if (xa < 0) { 51 | animSprite = left; 52 | dir = Direction.LEFT; 53 | } else if (xa > 0) { 54 | animSprite = right; 55 | dir = Direction.RIGHT; 56 | } 57 | if (xa != 0 || ya != 0) { 58 | //move(xa, ya); 59 | walking = true; 60 | } else { 61 | walking = false; 62 | } 63 | 64 | shootRandom(); 65 | 66 | } 67 | 68 | private void shootRandom() { 69 | List entities = level.getEntities(this, 500); 70 | entities.add(level.getClientPlayer()); 71 | if (time % (30 + random.nextInt(91)) == 0) { 72 | int index = random.nextInt(entities.size()); 73 | rand = entities.get(index); 74 | } 75 | 76 | if (rand != null) { 77 | double dx = rand.getX() - x; 78 | double dy = rand.getY() - y; 79 | double dir = Math.atan2(dy, dx); 80 | shoot(x, y, dir); 81 | } 82 | } 83 | 84 | private void shootClosest() { 85 | List entities = level.getEntities(this, 500); 86 | entities.add(level.getClientPlayer()); 87 | 88 | double min = 0; 89 | Entity closest = null; 90 | for (int i = 0; i < entities.size(); i++) { 91 | Entity e = entities.get(i); 92 | double distance = Vector2i.getDistance(new Vector2i(x, y), new Vector2i(e.getX(), e.getY())); 93 | if (i == 0 || distance < min) { 94 | min = distance; 95 | closest = e; 96 | } 97 | } 98 | 99 | if (closest != null) { 100 | double dx = closest.getX() - x; 101 | double dy = closest.getY() - y; 102 | double dir = Math.atan2(dy, dx); 103 | shoot(x, y, dir); 104 | } 105 | } 106 | 107 | public void render(Screen screen) { 108 | sprite = animSprite.getSprite(); 109 | screen.renderMob(x - 16, y - 16, this); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/mob/Star.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.mob; 2 | 3 | import java.util.List; 4 | 5 | import com.thecherno.rain.graphics.AnimatedSprite; 6 | import com.thecherno.rain.graphics.Screen; 7 | import com.thecherno.rain.graphics.Sprite; 8 | import com.thecherno.rain.graphics.SpriteSheet; 9 | import com.thecherno.rain.level.Node; 10 | import com.thecherno.rain.util.Vector2i; 11 | 12 | public class Star extends Mob { 13 | private AnimatedSprite down = new AnimatedSprite(SpriteSheet.dummy_down, 32, 32, 3); 14 | private AnimatedSprite up = new AnimatedSprite(SpriteSheet.dummy_up, 32, 32, 3); 15 | private AnimatedSprite left = new AnimatedSprite(SpriteSheet.dummy_left, 32, 32, 3); 16 | private AnimatedSprite right = new AnimatedSprite(SpriteSheet.dummy_right, 32, 32, 3); 17 | 18 | private AnimatedSprite animSprite = down; 19 | 20 | private int xa = 0; 21 | private int ya = 0; 22 | private List path = null; 23 | private int time = 0; 24 | 25 | public Star(int x, int y) { 26 | this.x = x << 4; 27 | this.y = y << 4; 28 | sprite = Sprite.dummy; 29 | } 30 | 31 | private void move() { 32 | xa = 0; 33 | ya = 0; 34 | int px = level.getPlayerAt(0).getX(); 35 | int py = level.getPlayerAt(0).getY(); 36 | Vector2i start = new Vector2i(getX() >> 4, getY() >> 4); 37 | Vector2i destination = new Vector2i(px >> 4, py >> 4); 38 | if (time % 3 == 0) path = level.findPath(start, destination); 39 | if (path != null) { 40 | if (path.size() > 0) { 41 | Vector2i vec = path.get(path.size() - 1).tile; 42 | if (x < vec.getX() << 4) xa++; 43 | if (x > vec.getX() << 4) xa--; 44 | if (y < vec.getY() << 4) ya++; 45 | if (y > vec.getY() << 4) ya--; 46 | } 47 | } 48 | if (xa != 0 || ya != 0) { 49 | move(xa, ya); 50 | walking = true; 51 | } else { 52 | walking = false; 53 | } 54 | } 55 | 56 | public void update() { 57 | time++; 58 | move(); 59 | if (walking) animSprite.update(); 60 | else animSprite.setFrame(0); 61 | if (ya < 0) { 62 | animSprite = up; 63 | dir = Direction.UP; 64 | } else if (ya > 0) { 65 | animSprite = down; 66 | dir = Direction.DOWN; 67 | } 68 | if (xa < 0) { 69 | animSprite = left; 70 | dir = Direction.LEFT; 71 | } else if (xa > 0) { 72 | animSprite = right; 73 | dir = Direction.RIGHT; 74 | } 75 | } 76 | 77 | public void render(Screen screen) { 78 | sprite = animSprite.getSprite(); 79 | screen.renderMob(x - 16, y - 16, this); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/particle/Particle.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.particle; 2 | 3 | import com.thecherno.rain.entity.Entity; 4 | import com.thecherno.rain.graphics.Screen; 5 | import com.thecherno.rain.graphics.Sprite; 6 | 7 | public class Particle extends Entity { 8 | 9 | private Sprite sprite; 10 | 11 | private int life; 12 | private int time = 0; 13 | 14 | protected double xx, yy, zz; 15 | protected double xa, ya, za; 16 | 17 | public Particle(int x, int y, int life) { 18 | this.x = x; 19 | this.y = y; 20 | this.xx = x; 21 | this.yy = y; 22 | this.life = life + (random.nextInt(20) - 10); 23 | sprite = Sprite.particle_normal; 24 | 25 | this.xa = random.nextGaussian(); 26 | this.ya = random.nextGaussian(); 27 | this.zz = random.nextFloat() + 2.0; 28 | } 29 | 30 | public void update() { 31 | time++; 32 | if (time >= 7400) time = 0; 33 | if (time > life) remove(); 34 | za -= 0.1; 35 | 36 | if (zz < 0) { 37 | zz = 0; 38 | za *= -0.55; 39 | xa *= 0.4; 40 | ya *= 0.4; 41 | } 42 | 43 | move(xx + xa, (yy + ya) + (zz + za)); 44 | } 45 | 46 | private void move(double x, double y) { 47 | if (collision(x, y)) { 48 | this.xa *= -0.5; 49 | this.ya *= -0.5; 50 | this.za *= -0.5; 51 | } 52 | this.xx += xa; 53 | this.yy += ya; 54 | this.zz += za; 55 | } 56 | 57 | public boolean collision(double x, double y) { 58 | boolean solid = false; 59 | for (int c = 0; c < 4; c++) { 60 | double xt = (x - c % 2 * 16) / 16; 61 | double yt = (y - c / 2 * 16) / 16; 62 | int ix = (int) Math.ceil(xt); 63 | int iy = (int) Math.ceil(yt); 64 | if (c % 2 == 0) ix = (int) Math.floor(xt); 65 | if (c / 2 == 0) iy = (int) Math.floor(yt); 66 | if (level.getTile(ix, iy).solid()) solid = true; 67 | } 68 | return solid; 69 | } 70 | 71 | public void render(Screen screen) { 72 | screen.renderSprite((int) xx - 1, (int) yy - (int) zz - 1, sprite, true); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/projectile/Projectile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.projectile; 2 | 3 | import java.util.Random; 4 | 5 | import com.thecherno.rain.entity.Entity; 6 | import com.thecherno.rain.graphics.Sprite; 7 | 8 | public abstract class Projectile extends Entity { 9 | 10 | protected final int xOrigin, yOrigin; 11 | protected double angle; 12 | protected Sprite sprite; 13 | protected double x, y; 14 | protected double nx, ny; 15 | protected double distance; 16 | protected double speed, range, damage; 17 | 18 | protected final Random random = new Random(); 19 | 20 | public Projectile(int x, int y, double dir) { 21 | xOrigin = x; 22 | yOrigin = y; 23 | angle = dir; 24 | this.x = x; 25 | this.y = y; 26 | } 27 | 28 | public Sprite getSprite() { 29 | return sprite; 30 | } 31 | 32 | public int getSpriteSize() { 33 | return sprite.SIZE; 34 | } 35 | 36 | protected void move() { 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/projectile/WizardProjectile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.projectile; 2 | 3 | import com.thecherno.rain.entity.spawner.ParticleSpawner; 4 | import com.thecherno.rain.graphics.Screen; 5 | import com.thecherno.rain.graphics.Sprite; 6 | 7 | public class WizardProjectile extends Projectile { 8 | 9 | public static final int FIRE_RATE = 10; // Higher is slower! 10 | 11 | public WizardProjectile(int x, int y, double dir) { 12 | super(x, y, dir); 13 | range = 200; 14 | speed = 4; 15 | damage = 20; 16 | sprite = Sprite.rotate(Sprite.projectile_arrow, angle); 17 | nx = speed * Math.cos(angle); 18 | ny = speed * Math.sin(angle); 19 | } 20 | 21 | private int time = 0; 22 | 23 | public void update() { 24 | if (level.tileCollision((int) (x + nx), (int) (y + ny), 7, 5, 4)) { 25 | level.add(new ParticleSpawner((int) x, (int) y, 44, 50, level)); 26 | remove(); 27 | } 28 | time++; 29 | if (time % 2 == 0) { 30 | sprite = Sprite.rotate(sprite, Math.PI / 20.0); 31 | } 32 | 33 | move(); 34 | } 35 | 36 | protected void move() { 37 | x += nx; 38 | y += ny; 39 | if (distance() > range) remove(); 40 | } 41 | 42 | private double distance() { 43 | double dist = 0; 44 | dist = Math.sqrt(Math.abs((xOrigin - x) * (xOrigin - x) + (yOrigin - y) * (yOrigin - y))); 45 | return dist; 46 | } 47 | 48 | public void render(Screen screen) { 49 | screen.renderProjectile((int) x - 12, (int) y - 2, this); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/spawner/ParticleSpawner.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.spawner; 2 | 3 | import com.thecherno.rain.entity.particle.Particle; 4 | import com.thecherno.rain.level.Level; 5 | 6 | public class ParticleSpawner extends Spawner { 7 | 8 | private int life; 9 | 10 | public ParticleSpawner(int x, int y, int life, int amount, Level level) { 11 | super(x, y, Type.PARTICLE, amount, level); 12 | this.life = life; 13 | for (int i = 0; i < amount; i++) { 14 | level.add(new Particle(x, y, life)); 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/entity/spawner/Spawner.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.entity.spawner; 2 | 3 | import com.thecherno.rain.entity.Entity; 4 | import com.thecherno.rain.level.Level; 5 | 6 | public abstract class Spawner extends Entity { 7 | 8 | public enum Type { 9 | MOB, PARTICLE; 10 | } 11 | 12 | protected Type type; 13 | 14 | public Spawner(int x, int y, Type type, int amount, Level level) { 15 | init(level); 16 | this.x = x; 17 | this.y = y; 18 | this.type = type; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/events/Event.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.events; 2 | 3 | public class Event { 4 | 5 | public enum Type { 6 | MOUSE_PRESSED, 7 | MOUSE_RELEASED, 8 | MOUSE_MOVED 9 | } 10 | 11 | private Type type; 12 | boolean handled; 13 | 14 | protected Event(Type type) { 15 | this.type = type; 16 | } 17 | 18 | public Type getType() { 19 | return type; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/events/EventDispatcher.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.events; 2 | 3 | public class EventDispatcher { 4 | 5 | private Event event; 6 | 7 | public EventDispatcher(Event event) { 8 | this.event = event; 9 | } 10 | 11 | public void dispatch(Event.Type type, EventHandler handler) { 12 | if (event.handled) 13 | return; 14 | 15 | if (event.getType() == type) 16 | event.handled = handler.onEvent(event); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/events/EventHandler.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.events; 2 | 3 | public interface EventHandler { 4 | 5 | public boolean onEvent(Event event); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/events/EventListener.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.events; 2 | 3 | public interface EventListener { 4 | 5 | public void onEvent(Event event); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/events/types/MouseButtonEvent.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.events.types; 2 | 3 | import com.thecherno.rain.events.Event; 4 | 5 | public class MouseButtonEvent extends Event { 6 | 7 | protected int button; 8 | protected int x, y; 9 | 10 | protected MouseButtonEvent(int button, int x, int y, Type type) { 11 | super(type); 12 | this.button = button; 13 | this.x = x; 14 | this.y = y; 15 | } 16 | 17 | public int getButton() { 18 | return button; 19 | } 20 | 21 | public int getX() { 22 | return x; 23 | } 24 | 25 | public int getY() { 26 | return y; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/events/types/MouseMovedEvent.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.events.types; 2 | 3 | import com.thecherno.rain.events.Event; 4 | 5 | public class MouseMovedEvent extends Event { 6 | 7 | private int x, y; 8 | private boolean dragged; 9 | 10 | public MouseMovedEvent(int x, int y, boolean dragged) { 11 | super(Event.Type.MOUSE_MOVED); 12 | this.x = x; 13 | this.y = y; 14 | this.dragged = dragged; 15 | } 16 | 17 | public int getX() { 18 | return x; 19 | } 20 | 21 | public int getY() { 22 | return y; 23 | } 24 | 25 | public boolean getDragged() { 26 | return dragged; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/events/types/MousePressedEvent.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.events.types; 2 | 3 | import com.thecherno.rain.events.Event; 4 | 5 | public class MousePressedEvent extends MouseButtonEvent { 6 | 7 | public MousePressedEvent(int button, int x, int y) { 8 | super(button, x, y, Event.Type.MOUSE_PRESSED); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/events/types/MouseReleasedEvent.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.events.types; 2 | 3 | import com.thecherno.rain.events.Event; 4 | 5 | public class MouseReleasedEvent extends MouseButtonEvent { 6 | 7 | public MouseReleasedEvent(int button, int x, int y) { 8 | super(button, x, y, Event.Type.MOUSE_RELEASED); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/AnimatedSprite.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics; 2 | 3 | public class AnimatedSprite extends Sprite { 4 | 5 | private int frame = 0; 6 | private Sprite sprite; 7 | private int rate = 5; 8 | private int time = 0; 9 | private int length = -1; 10 | 11 | public AnimatedSprite(SpriteSheet sheet, int width, int height, int length) { 12 | super(sheet, width, height); 13 | this.length = length; 14 | sprite = sheet.getSprites()[0]; 15 | if (length > sheet.getSprites().length) System.err.println("Error! Length of animation is too long!"); 16 | } 17 | 18 | public void update() { 19 | time++; 20 | if (time % rate == 0) { 21 | if (frame >= length - 1) frame = 0; 22 | else frame++; 23 | sprite = sheet.getSprites()[frame]; 24 | } 25 | } 26 | 27 | public Sprite getSprite() { 28 | return sprite; 29 | } 30 | 31 | public void setFrameRate(int frames) { 32 | rate = frames; 33 | } 34 | 35 | public void setFrame(int index) { 36 | if (index > sheet.getSprites().length - 1) { 37 | System.err.println("Index out of bounds in " + this); 38 | return; 39 | } 40 | sprite = sheet.getSprites()[index]; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/Font.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheCherno/GameProgramming/d6046db84deff9e7559a0626d6464caf8b97ca31/Rain/src/com/thecherno/rain/graphics/Font.java -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/Screen.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics; 2 | 3 | import java.util.Random; 4 | 5 | import com.thecherno.rain.entity.mob.Chaser; 6 | import com.thecherno.rain.entity.mob.Mob; 7 | import com.thecherno.rain.entity.mob.Star; 8 | import com.thecherno.rain.entity.projectile.Projectile; 9 | import com.thecherno.rain.level.tile.Tile; 10 | 11 | public class Screen { 12 | 13 | public int width, height; 14 | public int[] pixels; 15 | public final int MAP_SIZE = 64; 16 | public final int MAP_SIZE_MASK = MAP_SIZE - 1; 17 | public int xOffset, yOffset; 18 | public int[] tiles = new int[MAP_SIZE * MAP_SIZE]; 19 | private Random random = new Random(); 20 | 21 | private final int ALPHA_COL = 0xffff00ff; 22 | 23 | public Screen(int width, int height) { 24 | this.width = width; 25 | this.height = height; 26 | pixels = new int[width * height]; // 0 - 50,399 = 50,400 27 | 28 | for (int i = 0; i < MAP_SIZE * MAP_SIZE; i++) { 29 | tiles[i] = random.nextInt(0xffffff); 30 | tiles[0] = 0; 31 | } 32 | 33 | } 34 | 35 | public void clear() { 36 | for (int i = 0; i < pixels.length; i++) { 37 | pixels[i] = 0; 38 | } 39 | } 40 | 41 | public void renderSheet(int xp, int yp, SpriteSheet sheet, boolean fixed) { 42 | if (fixed) { 43 | xp -= xOffset; 44 | yp -= yOffset; 45 | } 46 | for (int y = 0; y < sheet.SPRITE_HEIGHT; y++) { 47 | int ya = y + yp; 48 | for (int x = 0; x < sheet.SPRITE_WIDTH; x++) { 49 | int xa = x + xp; 50 | if (xa < 0 || xa >= width || ya < 0 || ya >= height) continue; 51 | pixels[xa + ya * width] = sheet.pixels[x + y * sheet.SPRITE_WIDTH]; 52 | } 53 | } 54 | } 55 | 56 | public void renderTextCharacter(int xp, int yp, Sprite sprite, int color, boolean fixed) { 57 | if (fixed) { 58 | xp -= xOffset; 59 | yp -= yOffset; 60 | } 61 | for (int y = 0; y < sprite.getHeight(); y++) { 62 | int ya = y + yp; 63 | for (int x = 0; x < sprite.getWidth(); x++) { 64 | int xa = x + xp; 65 | if (xa < 0 || xa >= width || ya < 0 || ya >= height) continue; 66 | int col = sprite.pixels[x + y * sprite.getWidth()]; 67 | if (col != ALPHA_COL && col != 0xff7f007f) pixels[xa + ya * width] = color; 68 | } 69 | } 70 | } 71 | 72 | public void renderSprite(int xp, int yp, Sprite sprite, boolean fixed) { 73 | if (fixed) { 74 | xp -= xOffset; 75 | yp -= yOffset; 76 | } 77 | for (int y = 0; y < sprite.getHeight(); y++) { 78 | int ya = y + yp; 79 | for (int x = 0; x < sprite.getWidth(); x++) { 80 | int xa = x + xp; 81 | if (xa < 0 || xa >= width || ya < 0 || ya >= height) continue; 82 | int col = sprite.pixels[x + y * sprite.getWidth()]; 83 | if (col != ALPHA_COL && col != 0xff7f007f) pixels[xa + ya * width] = col; 84 | } 85 | } 86 | } 87 | 88 | public void renderTile(int xp, int yp, Tile tile) { 89 | xp -= xOffset; 90 | yp -= yOffset; 91 | for (int y = 0; y < tile.sprite.SIZE; y++) { 92 | int ya = y + yp; 93 | for (int x = 0; x < tile.sprite.SIZE; x++) { 94 | int xa = x + xp; 95 | if (xa < -tile.sprite.SIZE || xa >= width || ya < 0 || ya >= height) break; 96 | if (xa < 0) xa = 0; 97 | pixels[xa + ya * width] = tile.sprite.pixels[x + y * tile.sprite.SIZE]; 98 | } 99 | } 100 | } 101 | 102 | public void renderProjectile(int xp, int yp, Projectile p) { 103 | xp -= xOffset; 104 | yp -= yOffset; 105 | for (int y = 0; y < p.getSpriteSize(); y++) { 106 | int ya = y + yp; 107 | for (int x = 0; x < p.getSpriteSize(); x++) { 108 | int xa = x + xp; 109 | if (xa < -p.getSpriteSize() || xa >= width || ya < 0 || ya >= height) break; 110 | if (xa < 0) xa = 0; 111 | int col = p.getSprite().pixels[x + y * p.getSprite().SIZE]; 112 | if (col != ALPHA_COL) pixels[xa + ya * width] = col; 113 | } 114 | } 115 | } 116 | 117 | public void renderMob(int xp, int yp, Mob mob) { 118 | xp -= xOffset; 119 | yp -= yOffset; 120 | for (int y = 0; y < 32; y++) { 121 | int ya = y + yp; 122 | int ys = y; 123 | for (int x = 0; x < 32; x++) { 124 | int xa = x + xp; 125 | int xs = x; 126 | if (xa < -32 || xa >= width || ya < 0 || ya >= height) break; 127 | if (xa < 0) xa = 0; 128 | int col = mob.getSprite().pixels[xs + ys * 32]; 129 | if ((mob instanceof Chaser) && col == 0xff472BBF) col = 0xffBA0015; 130 | if ((mob instanceof Star) && col == 0xff472BBF) col = 0xffE8E83A; 131 | if (col != ALPHA_COL) pixels[xa + ya * width] = col; 132 | } 133 | } 134 | } 135 | 136 | public void renderMob(int xp, int yp, Sprite sprite, int flip) { 137 | xp -= xOffset; 138 | yp -= yOffset; 139 | for (int y = 0; y < 32; y++) { 140 | int ya = y + yp; 141 | int ys = y; 142 | if (flip == 2 || flip == 3) ys = 31 - y; 143 | for (int x = 0; x < 32; x++) { 144 | int xa = x + xp; 145 | int xs = x; 146 | if (flip == 1 || flip == 3) xs = 31 - x; 147 | if (xa < -32 || xa >= width || ya < 0 || ya >= height) break; 148 | if (xa < 0) xa = 0; 149 | int col = sprite.pixels[xs + ys * 32]; 150 | if (col != ALPHA_COL) pixels[xa + ya * width] = col; 151 | } 152 | } 153 | } 154 | 155 | public void drawRect(int xp, int yp, int width, int height, int color, boolean fixed) { 156 | if (fixed) { 157 | xp -= xOffset; 158 | yp -= yOffset; 159 | } 160 | for (int x = xp; x < xp + width; x++) { 161 | if (x < 0 | x >= this.width || yp >= this.height) continue; 162 | if (yp > 0) pixels[x + yp * this.width] = color; 163 | if (yp + height >= this.height) continue; 164 | if (yp + height > 0) pixels[x + (yp + height) * this.width] = color; 165 | } 166 | for (int y = yp; y <= yp + height; y++) { 167 | if (xp >= this.width || y < 0 || y >= this.height) continue; 168 | if (xp > 0) pixels[xp + y * this.width] = color; 169 | if (xp + width >= this.width) continue; 170 | if (xp + width > 0) pixels[(xp + width) + y * this.width] = color; 171 | } 172 | } 173 | 174 | public void fillRect(int xp, int yp, int width, int height, int color, boolean fixed) { 175 | if (fixed) { 176 | xp -= xOffset; 177 | yp -= yOffset; 178 | } 179 | 180 | for (int y = 0; y < height; y++) { 181 | int yo = yp + y; 182 | if (yo < 0 || yo >= this.height) 183 | continue; 184 | for (int x = 0; x < width; x++) { 185 | int xo = xp + x; 186 | if (xo < 0 || xo >= this.width) 187 | continue; 188 | pixels[xo + yo * this.width] = color; 189 | } 190 | } 191 | } 192 | 193 | public void setOffset(int xOffset, int yOffset) { 194 | this.xOffset = xOffset; 195 | this.yOffset = yOffset; 196 | } 197 | 198 | } 199 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/Sprite.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics; 2 | 3 | public class Sprite { 4 | 5 | public final int SIZE; 6 | private int x, y; 7 | private int width, height; 8 | public int[] pixels; 9 | protected SpriteSheet sheet; 10 | 11 | public static Sprite grass = new Sprite(16, 0, 5, SpriteSheet.tiles); 12 | public static Sprite flower = new Sprite(16, 1, 0, SpriteSheet.tiles); 13 | public static Sprite rock = new Sprite(16, 2, 0, SpriteSheet.tiles); 14 | public static Sprite voidSprite = new Sprite(16, 0x1B87E0); 15 | 16 | //Spawn Level Sprites here: 17 | public static Sprite spawn_grass = new Sprite(16, 0, 0, SpriteSheet.spawn_level); 18 | public static Sprite spawn_hedge = new Sprite(16, 1, 0, SpriteSheet.spawn_level); 19 | public static Sprite spawn_water = new Sprite(16, 2, 0, SpriteSheet.spawn_level); 20 | public static Sprite spawn_wall1 = new Sprite(16, 0, 1, SpriteSheet.spawn_level); 21 | public static Sprite spawn_wall2 = new Sprite(16, 0, 2, SpriteSheet.spawn_level); 22 | public static Sprite spawn_floor = new Sprite(16, 1, 1, SpriteSheet.spawn_level); 23 | 24 | //Player Sprites here: 25 | public static Sprite player_forward = new Sprite(32, 0, 5, SpriteSheet.tiles); 26 | public static Sprite player_back = new Sprite(32, 2, 5, SpriteSheet.tiles); 27 | public static Sprite player_side = new Sprite(32, 1, 5, SpriteSheet.tiles); 28 | 29 | public static Sprite player_forward_1 = new Sprite(32, 0, 6, SpriteSheet.tiles); 30 | public static Sprite player_forward_2 = new Sprite(32, 0, 7, SpriteSheet.tiles); 31 | 32 | public static Sprite player_side_1 = new Sprite(32, 1, 6, SpriteSheet.tiles); 33 | public static Sprite player_side_2 = new Sprite(32, 1, 7, SpriteSheet.tiles); 34 | 35 | public static Sprite player_back_1 = new Sprite(32, 2, 6, SpriteSheet.tiles); 36 | public static Sprite player_back_2 = new Sprite(32, 2, 7, SpriteSheet.tiles); 37 | 38 | public static Sprite dummy = new Sprite(32, 0, 0, SpriteSheet.dummy_down); 39 | 40 | //Projectile Sprites here: 41 | public static Sprite projectile_wizard = new Sprite(16, 0, 0, SpriteSheet.projectile_wizard); 42 | public static Sprite projectile_arrow = new Sprite(16, 1, 0, SpriteSheet.projectile_wizard); 43 | 44 | // Particles 45 | public static Sprite particle_normal = new Sprite(3, 0xAAAAAA); 46 | public static Sprite square = new Sprite(2, 0xFF0000); 47 | 48 | protected Sprite(SpriteSheet sheet, int width, int height) { 49 | SIZE = (width == height) ? width : -1; 50 | this.width = width; 51 | this.height = height; 52 | this.sheet = sheet; 53 | } 54 | 55 | public Sprite(int size, int x, int y, SpriteSheet sheet) { 56 | SIZE = size; 57 | this.width = size; 58 | this.height = size; 59 | pixels = new int[SIZE * SIZE]; 60 | this.x = x * size; 61 | this.y = y * size; 62 | this.sheet = sheet; 63 | load(); 64 | } 65 | 66 | public Sprite(int width, int height, int colour) { 67 | SIZE = -1; 68 | this.width = width; 69 | this.height = height; 70 | pixels = new int[width * height]; 71 | setColour(colour); 72 | } 73 | 74 | public Sprite(int size, int colour) { 75 | SIZE = size; 76 | this.width = size; 77 | this.height = size; 78 | pixels = new int[SIZE * SIZE]; 79 | setColour(colour); 80 | } 81 | 82 | public Sprite(int[] pixels, int width, int height) { 83 | SIZE = (width == height) ? width : -1; 84 | this.width = width; 85 | this.height = height; 86 | this.pixels = new int[pixels.length]; 87 | for (int i = 0; i < pixels.length; i++) { 88 | this.pixels[i] = pixels[i]; 89 | } 90 | } 91 | 92 | public static Sprite rotate(Sprite sprite, double angle) { 93 | return new Sprite(rotate(sprite.pixels, sprite.width, sprite.height, angle), sprite.width, sprite.height); 94 | } 95 | 96 | private static int[] rotate(int[] pixels, int width, int height, double angle) { 97 | int[] result = new int[width * height]; 98 | 99 | double nx_x = rot_x(-angle, 1.0, 0.0); 100 | double nx_y = rot_y(-angle, 1.0, 0.0); 101 | double ny_x = rot_x(-angle, 0.0, 1.0); 102 | double ny_y = rot_y(-angle, 0.0, 1.0); 103 | 104 | double x0 = rot_x(-angle, -width / 2.0, -height / 2.0) + width / 2.0; 105 | double y0 = rot_y(-angle, -width / 2.0, -height / 2.0) + height / 2.0; 106 | 107 | for (int y = 0; y < height; y++) { 108 | double x1 = x0; 109 | double y1 = y0; 110 | for (int x = 0; x < width; x++) { 111 | int xx = (int) x1; 112 | int yy = (int) y1; 113 | int col = 0; 114 | if (xx < 0 || xx >= width || yy < 0 || yy >= height) col = 0xffff00ff; 115 | else col = pixels[xx + yy * width]; 116 | result[x + y * width] = col; 117 | x1 += nx_x; 118 | y1 += nx_y; 119 | } 120 | x0 += ny_x; 121 | y0 += ny_y; 122 | } 123 | 124 | return result; 125 | } 126 | 127 | private static double rot_x(double angle, double x, double y) { 128 | double cos = Math.cos(angle - Math.PI / 2); 129 | double sin = Math.sin(angle - Math.PI / 2); 130 | return x * cos + y * -sin; 131 | } 132 | 133 | private static double rot_y(double angle, double x, double y) { 134 | double cos = Math.cos(angle - Math.PI / 2); 135 | double sin = Math.sin(angle - Math.PI / 2); 136 | return x * sin + y * cos; 137 | } 138 | 139 | 140 | public static Sprite[] split(SpriteSheet sheet) { 141 | int amount = (sheet.getWidth() * sheet.getHeight()) / (sheet.SPRITE_WIDTH * sheet.SPRITE_HEIGHT); 142 | Sprite[] sprites = new Sprite[amount]; 143 | int current = 0; 144 | int[] pixels = new int[sheet.SPRITE_WIDTH * sheet.SPRITE_HEIGHT]; 145 | for (int yp = 0; yp < sheet.getHeight() / sheet.SPRITE_HEIGHT; yp++) { 146 | for (int xp = 0; xp < sheet.getWidth() / sheet.SPRITE_WIDTH; xp++) { 147 | 148 | for (int y = 0; y < sheet.SPRITE_HEIGHT; y++) { 149 | for (int x = 0; x < sheet.SPRITE_WIDTH; x++) { 150 | int xo = x + xp * sheet.SPRITE_WIDTH; 151 | int yo = y + yp * sheet.SPRITE_HEIGHT; 152 | pixels[x + y * sheet.SPRITE_WIDTH] = sheet.getPixels()[xo + yo * sheet.getWidth()]; 153 | } 154 | } 155 | 156 | sprites[current++] = new Sprite(pixels, sheet.SPRITE_WIDTH, sheet.SPRITE_HEIGHT); 157 | } 158 | } 159 | 160 | return sprites; 161 | } 162 | 163 | public Sprite(int[] pixels, int size) { 164 | SIZE = width = height = size; 165 | this.pixels = pixels; 166 | } 167 | 168 | private void setColour(int colour) { 169 | for (int i = 0; i < width * height; i++) { 170 | pixels[i] = colour; 171 | } 172 | } 173 | 174 | public int getWidth() { 175 | return width; 176 | } 177 | 178 | public int getHeight() { 179 | return height; 180 | } 181 | 182 | private void load() { 183 | for (int y = 0; y < height; y++) { 184 | for (int x = 0; x < width; x++) { 185 | pixels[x + y * width] = sheet.pixels[(x + this.x) + (y + this.y) * sheet.SPRITE_WIDTH]; 186 | } 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/SpriteSheet.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.IOException; 5 | 6 | import javax.imageio.ImageIO; 7 | 8 | public class SpriteSheet { 9 | 10 | private String path; 11 | public final int SIZE; 12 | public final int SPRITE_WIDTH, SPRITE_HEIGHT; 13 | private int width, height; 14 | public int[] pixels; 15 | 16 | public static SpriteSheet tiles = new SpriteSheet("/textures/sheets/spritesheet.png", 256); 17 | public static SpriteSheet spawn_level = new SpriteSheet("/textures/sheets/spawn_lvl.png", 48); 18 | public static SpriteSheet projectile_wizard = new SpriteSheet("/textures/sheets/projectiles/wizard.png", 48); 19 | 20 | public static SpriteSheet player = new SpriteSheet("/textures/sheets/player_sheet.png", 128, 96); 21 | public static SpriteSheet player_down = new SpriteSheet(player, 0, 0, 1, 3, 32); 22 | public static SpriteSheet player_up = new SpriteSheet(player, 1, 0, 1, 3, 32); 23 | public static SpriteSheet player_left = new SpriteSheet(player, 2, 0, 1, 3, 32); 24 | public static SpriteSheet player_right = new SpriteSheet(player, 3, 0, 1, 3, 32); 25 | 26 | public static SpriteSheet dummy = new SpriteSheet("/textures/sheets/king_cherno.png", 128, 96); 27 | public static SpriteSheet dummy_down = new SpriteSheet(dummy, 0, 0, 1, 3, 32); 28 | public static SpriteSheet dummy_up = new SpriteSheet(dummy, 1, 0, 1, 3, 32); 29 | public static SpriteSheet dummy_left = new SpriteSheet(dummy, 2, 0, 1, 3, 32); 30 | public static SpriteSheet dummy_right = new SpriteSheet(dummy, 3, 0, 1, 3, 32); 31 | 32 | private Sprite[] sprites; 33 | 34 | public SpriteSheet(SpriteSheet sheet, int x, int y, int width, int height, int spriteSize) { 35 | int xx = x * spriteSize; 36 | int yy = y * spriteSize; 37 | int w = width * spriteSize; 38 | int h = height * spriteSize; 39 | if (width == height) SIZE = width; 40 | else SIZE = -1; 41 | SPRITE_WIDTH = w; 42 | SPRITE_HEIGHT = h; 43 | pixels = new int[w * h]; 44 | for (int y0 = 0; y0 < h; y0++) { 45 | int yp = yy + y0; 46 | for (int x0 = 0; x0 < w; x0++) { 47 | int xp = xx + x0; 48 | pixels[x0 + y0 * w] = sheet.pixels[xp + yp * sheet.SPRITE_WIDTH]; 49 | } 50 | } 51 | int frame = 0; 52 | sprites = new Sprite[width * height]; 53 | for (int ya = 0; ya < height; ya++) { 54 | for (int xa = 0; xa < width; xa++) { 55 | int[] spritePixels = new int[spriteSize * spriteSize]; 56 | for (int y0 = 0; y0 < spriteSize; y0++) { 57 | for (int x0 = 0; x0 < spriteSize; x0++) { 58 | spritePixels[x0 + y0 * spriteSize] = pixels[(x0 + xa * spriteSize) + (y0 + ya * spriteSize) * SPRITE_WIDTH]; 59 | } 60 | } 61 | Sprite sprite = new Sprite(spritePixels, spriteSize, spriteSize); 62 | sprites[frame++] = sprite; 63 | } 64 | } 65 | } 66 | 67 | public SpriteSheet(String path, int size) { 68 | this.path = path; 69 | SIZE = size; 70 | SPRITE_WIDTH = size; 71 | SPRITE_HEIGHT = size; 72 | load(); 73 | } 74 | 75 | public SpriteSheet(String path, int width, int height) { 76 | this.path = path; 77 | SIZE = -1; 78 | SPRITE_WIDTH = width; 79 | SPRITE_HEIGHT = height; 80 | pixels = new int[SPRITE_WIDTH * SPRITE_HEIGHT]; 81 | load(); 82 | } 83 | 84 | public Sprite[] getSprites() { 85 | return sprites; 86 | } 87 | 88 | public int getWidth() { 89 | return width; 90 | } 91 | 92 | public int getHeight() { 93 | return height; 94 | } 95 | 96 | public int[] getPixels() { 97 | return pixels; 98 | } 99 | 100 | private void load() { 101 | try { 102 | System.out.print("Trying to load: " + path + "..."); 103 | BufferedImage image = ImageIO.read(SpriteSheet.class.getResource(path)); 104 | System.out.println(" succeeded!"); 105 | width = image.getWidth(); 106 | height = image.getHeight(); 107 | pixels = new int[width * height]; 108 | image.getRGB(0, 0, width, height, pixels, 0, width); 109 | } catch (IOException e) { 110 | e.printStackTrace(); 111 | } catch (Exception e) { 112 | System.err.println(" failed!"); 113 | } 114 | 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/layers/Layer.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics.layers; 2 | 3 | import com.thecherno.rain.events.Event; 4 | import com.thecherno.rain.events.EventListener; 5 | import com.thecherno.rain.graphics.Screen; 6 | 7 | public class Layer implements EventListener { 8 | 9 | public void onEvent(Event event) { 10 | } 11 | 12 | public void update() { 13 | } 14 | 15 | public void render(Screen screen) { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/ui/UIActionListener.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics.ui; 2 | 3 | public interface UIActionListener { 4 | 5 | public void perform(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/ui/UIButton.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics.ui; 2 | 3 | import java.awt.Graphics; 4 | import java.awt.Image; 5 | import java.awt.Point; 6 | import java.awt.Rectangle; 7 | import java.awt.event.MouseEvent; 8 | import java.awt.image.BufferedImage; 9 | 10 | import com.thecherno.rain.input.Mouse; 11 | import com.thecherno.rain.util.Vector2i; 12 | 13 | public class UIButton extends UIComponent { 14 | 15 | public UILabel label; 16 | private UIButtonListener buttonListener; 17 | private UIActionListener actionListener; 18 | 19 | private Image image; 20 | 21 | private boolean inside = false; 22 | private boolean pressed = false; 23 | private boolean ignorePressed = false; 24 | private boolean ignoreAction = false; 25 | 26 | public UIButton(Vector2i position, Vector2i size, UIActionListener actionListener) { 27 | super(position, size); 28 | this.actionListener = actionListener; 29 | Vector2i lp = new Vector2i(position); 30 | lp.x += 4; 31 | lp.y += size.y - 2; 32 | label = new UILabel(lp, ""); 33 | label.setColor(0x444444); 34 | label.active = false; 35 | init(); 36 | } 37 | 38 | public UIButton(Vector2i position, BufferedImage image, UIActionListener actionListener) { 39 | super(position, new Vector2i(image.getWidth(), image.getHeight())); 40 | this.actionListener = actionListener; 41 | setImage(image); 42 | init(); 43 | } 44 | 45 | private void init() { 46 | setColor(0xaaaaaa); 47 | buttonListener = new UIButtonListener(); 48 | } 49 | 50 | void init(UIPanel panel) { 51 | super.init(panel); 52 | if (label != null) 53 | panel.addComponent(label); 54 | } 55 | 56 | public void setButtonListener(UIButtonListener buttonListener) { 57 | this.buttonListener = buttonListener; 58 | } 59 | 60 | public void setImage(Image image) { 61 | this.image = image; 62 | } 63 | 64 | public void setText(String text) { 65 | if (text == "") 66 | label.active = false; 67 | else 68 | label.text = text; 69 | } 70 | 71 | public void performAction() { 72 | actionListener.perform(); 73 | } 74 | 75 | public void ignoreNextPress() { 76 | ignoreAction = true; 77 | } 78 | 79 | public void update() { 80 | Rectangle rect = new Rectangle(getAbsolutePosition().x, getAbsolutePosition().y, size.x, size.y); 81 | boolean leftMouseButtonDown = Mouse.getButton() == MouseEvent.BUTTON1; 82 | if (rect.contains(new Point(Mouse.getX(), Mouse.getY()))) { 83 | if (!inside) { 84 | if (leftMouseButtonDown) 85 | ignorePressed = true; 86 | else 87 | ignorePressed = false; 88 | buttonListener.entered(this); 89 | } 90 | inside = true; 91 | 92 | if (!pressed && !ignorePressed && leftMouseButtonDown) { 93 | buttonListener.pressed(this); 94 | pressed = true; 95 | } else if (Mouse.getButton() == MouseEvent.NOBUTTON) { 96 | if (pressed) { 97 | buttonListener.released(this); 98 | if (!ignoreAction) 99 | actionListener.perform(); 100 | else 101 | ignoreAction = false; 102 | pressed = false; 103 | } 104 | ignorePressed = false; 105 | } 106 | } else { 107 | if (inside) { 108 | buttonListener.exited(this); 109 | pressed = false; 110 | } 111 | inside = false; 112 | } 113 | } 114 | 115 | public void render(Graphics g) { 116 | int x = position.x + offset.x; 117 | int y = position.y + offset.y; 118 | if (image != null) { 119 | g.drawImage(image, x, y, null); 120 | } else { 121 | g.setColor(color); 122 | g.fillRect(x, y, size.x, size.y); 123 | 124 | if (label != null) 125 | label.render(g); 126 | } 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/ui/UIButtonListener.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics.ui; 2 | 3 | public class UIButtonListener { 4 | 5 | public void entered(UIButton button) { 6 | button.setColor(0xcdcdcd); 7 | } 8 | 9 | public void exited(UIButton button) { 10 | button.setColor(0xaaaaaa); 11 | } 12 | 13 | public void pressed(UIButton button) { 14 | button.setColor(0xcc2222); 15 | } 16 | 17 | public void released(UIButton button) { 18 | button.setColor(0xcdcdcd); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/ui/UIComponent.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics.ui; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | 6 | import com.thecherno.rain.util.Vector2i; 7 | 8 | public class UIComponent { 9 | 10 | public Vector2i position, size; 11 | protected Vector2i offset; 12 | public Color color; 13 | protected UIPanel panel; 14 | 15 | public boolean active = true; 16 | 17 | public UIComponent(Vector2i position) { 18 | this.position = position; 19 | offset = new Vector2i(); 20 | } 21 | 22 | public UIComponent(Vector2i position, Vector2i size) { 23 | this.position = position; 24 | this.size = size; 25 | offset = new Vector2i(); 26 | } 27 | 28 | void init(UIPanel panel) { 29 | this.panel = panel; 30 | } 31 | 32 | public UIComponent setColor(int color) { 33 | this.color = new Color(color); 34 | return this; 35 | } 36 | 37 | public void update() { 38 | } 39 | 40 | public void render(Graphics g) { 41 | } 42 | 43 | public Vector2i getAbsolutePosition() { 44 | return new Vector2i(position).add(offset); 45 | } 46 | 47 | void setOffset(Vector2i offset) { 48 | this.offset = offset; 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/ui/UILabel.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics.ui; 2 | 3 | import java.awt.Color; 4 | import java.awt.Font; 5 | import java.awt.Graphics; 6 | 7 | import com.thecherno.rain.util.Vector2i; 8 | 9 | public class UILabel extends UIComponent { 10 | 11 | public String text; 12 | private Font font; 13 | public boolean dropShadow = false; 14 | public int dropShadowOffset = 2; 15 | 16 | public UILabel(Vector2i position, String text) { 17 | super(position); 18 | font = new Font("Helvetica", Font.PLAIN, 32); 19 | this.text = text; 20 | color = new Color(0xff00ff); 21 | } 22 | 23 | public UILabel setFont(Font font) { 24 | this.font = font; 25 | return this; 26 | } 27 | 28 | public void render(Graphics g) { 29 | if (dropShadow) { 30 | g.setFont(font); 31 | g.setColor(Color.BLACK); 32 | g.drawString(text, position.x + offset.x + dropShadowOffset, position.y + offset.y + dropShadowOffset); 33 | } 34 | 35 | g.setColor(color); 36 | g.setFont(font); 37 | g.drawString(text, position.x + offset.x, position.y + offset.y); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/ui/UIManager.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics.ui; 2 | 3 | import java.awt.Graphics; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class UIManager { 8 | 9 | private List panels = new ArrayList(); 10 | 11 | public UIManager() { 12 | 13 | } 14 | 15 | public void addPanel(UIPanel panel) { 16 | panels.add(panel); 17 | } 18 | 19 | public void update() { 20 | for (UIPanel panel : panels) { 21 | panel.update(); 22 | } 23 | } 24 | 25 | public void render(Graphics g) { 26 | for (UIPanel panel : panels) { 27 | panel.render(g); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/ui/UIPanel.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics.ui; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import com.thecherno.rain.util.Vector2i; 9 | 10 | public class UIPanel extends UIComponent { 11 | 12 | private List components = new ArrayList(); 13 | private Vector2i size; 14 | 15 | public UIPanel(Vector2i position, Vector2i size) { 16 | super(position); 17 | this.position = position; 18 | this.size = size; 19 | color = new Color(0xcacaca); 20 | } 21 | 22 | public void addComponent(UIComponent component) { 23 | component.init(this); 24 | components.add(component); 25 | } 26 | 27 | public void update() { 28 | for (UIComponent component : components) { 29 | component.setOffset(position); 30 | component.update(); 31 | } 32 | } 33 | 34 | public void render(Graphics g) { 35 | g.setColor(color); 36 | g.fillRect(position.x, position.y, size.x, size.y); 37 | for (UIComponent component : components) { 38 | component.render(g); 39 | } 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/graphics/ui/UIProgressBar.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.graphics.ui; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | 6 | import org.w3c.dom.ranges.RangeException; 7 | 8 | import com.thecherno.rain.util.Vector2i; 9 | 10 | public class UIProgressBar extends UIComponent { 11 | 12 | private double progress; // 0.0 - 1.0 13 | 14 | private Color foregroundColor; 15 | 16 | public UIProgressBar(Vector2i position, Vector2i size) { 17 | super(position); 18 | this.size = size; 19 | 20 | foregroundColor = new Color(0xff00ff); 21 | } 22 | 23 | public void setProgress(double progress) { 24 | if (progress < 0.0 || progress > 1.0) throw new RangeException(RangeException.BAD_BOUNDARYPOINTS_ERR, "Progress must be between 0.0 and 1.0!"); 25 | 26 | this.progress = progress; 27 | } 28 | 29 | public void setForegroundColor(int color) { 30 | this.foregroundColor = new Color(color); 31 | } 32 | 33 | public double getProgress() { 34 | return progress; 35 | } 36 | 37 | public void update() { 38 | } 39 | 40 | public void render(Graphics g) { 41 | g.setColor(color); 42 | g.fillRect(position.x + offset.x, position.y + offset.y, size.x, size.y); 43 | 44 | g.setColor(foregroundColor); 45 | g.fillRect(position.x + offset.x, position.y + offset.y, (int) (progress * size.x), size.y); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/input/Keyboard.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.input; 2 | 3 | import java.awt.event.KeyEvent; 4 | import java.awt.event.KeyListener; 5 | 6 | public class Keyboard implements KeyListener { 7 | 8 | private boolean[] keys = new boolean[120]; 9 | public boolean up, down, left, right; 10 | 11 | public void update() { 12 | up = keys[KeyEvent.VK_UP] || keys[KeyEvent.VK_W]; 13 | down = keys[KeyEvent.VK_DOWN] || keys[KeyEvent.VK_S]; 14 | left = keys[KeyEvent.VK_LEFT] || keys[KeyEvent.VK_A]; 15 | right = keys[KeyEvent.VK_RIGHT] || keys[KeyEvent.VK_D]; 16 | } 17 | 18 | public void keyPressed(KeyEvent e) { 19 | keys[e.getKeyCode()] = true; 20 | } 21 | 22 | public void keyReleased(KeyEvent e) { 23 | keys[e.getKeyCode()] = false; 24 | } 25 | 26 | public void keyTyped(KeyEvent e) { 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/input/Mouse.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.input; 2 | 3 | import java.awt.event.MouseEvent; 4 | import java.awt.event.MouseListener; 5 | import java.awt.event.MouseMotionListener; 6 | 7 | import com.thecherno.rain.events.EventListener; 8 | import com.thecherno.rain.events.types.MouseMovedEvent; 9 | import com.thecherno.rain.events.types.MousePressedEvent; 10 | import com.thecherno.rain.events.types.MouseReleasedEvent; 11 | 12 | public class Mouse implements MouseListener, MouseMotionListener { 13 | 14 | private static int mouseX = -1; 15 | private static int mouseY = -1; 16 | private static int mouseB = -1; 17 | 18 | private EventListener eventListener; 19 | 20 | public Mouse(EventListener listener) { 21 | eventListener = listener; 22 | } 23 | 24 | public static int getX() { 25 | return mouseX; 26 | } 27 | 28 | public static int getY() { 29 | return mouseY; 30 | } 31 | 32 | public static int getButton() { 33 | return mouseB; 34 | } 35 | 36 | public void mouseDragged(MouseEvent e) { 37 | mouseX = e.getX(); 38 | mouseY = e.getY(); 39 | 40 | MouseMovedEvent event = new MouseMovedEvent(e.getX(), e.getY(), true); 41 | eventListener.onEvent(event); 42 | } 43 | 44 | public void mouseMoved(MouseEvent e) { 45 | mouseX = e.getX(); 46 | mouseY = e.getY(); 47 | 48 | MouseMovedEvent event = new MouseMovedEvent(e.getX(), e.getY(), false); 49 | eventListener.onEvent(event); 50 | } 51 | 52 | public void mouseClicked(MouseEvent e) { 53 | } 54 | 55 | public void mouseEntered(MouseEvent e) { 56 | } 57 | 58 | public void mouseExited(MouseEvent e) { 59 | } 60 | 61 | public void mousePressed(MouseEvent e) { 62 | mouseB = e.getButton(); 63 | 64 | MousePressedEvent event = new MousePressedEvent(e.getButton(), e.getX(), e.getY()); 65 | eventListener.onEvent(event); 66 | } 67 | 68 | public void mouseReleased(MouseEvent e) { 69 | mouseB = MouseEvent.NOBUTTON; 70 | 71 | MouseReleasedEvent event = new MouseReleasedEvent(e.getButton(), e.getX(), e.getY()); 72 | eventListener.onEvent(event); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/Level.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level; 2 | 3 | import java.util.ArrayList 4 | ; 5 | import java.util.Collections; 6 | import java.util.Comparator; 7 | import java.util.List; 8 | 9 | import com.thecherno.rain.entity.Entity; 10 | import com.thecherno.rain.entity.mob.Mob; 11 | import com.thecherno.rain.entity.mob.Player; 12 | import com.thecherno.rain.entity.particle.Particle; 13 | import com.thecherno.rain.entity.projectile.Projectile; 14 | import com.thecherno.rain.events.Event; 15 | import com.thecherno.rain.graphics.Screen; 16 | import com.thecherno.rain.graphics.layers.Layer; 17 | import com.thecherno.rain.level.tile.Tile; 18 | import com.thecherno.rain.util.Vector2i; 19 | 20 | public class Level extends Layer { 21 | 22 | protected int width, height; 23 | protected int[] tilesInt; 24 | protected int[] tiles; 25 | protected int tile_size; 26 | 27 | private int xScroll, yScroll; 28 | 29 | private List entities = new ArrayList(); 30 | private List projectiles = new ArrayList(); 31 | private List particles = new ArrayList(); 32 | 33 | public List players = new ArrayList(); 34 | 35 | private Comparator nodeSorter = new Comparator() { 36 | public int compare(Node n0, Node n1) { 37 | if (n1.fCost < n0.fCost) return +1; 38 | if (n1.fCost > n0.fCost) return -1; 39 | return 0; 40 | } 41 | }; 42 | 43 | public static Level spawn = new SpawnLevel("/levels/spawn.png"); 44 | 45 | public Level(int width, int height) { 46 | this.width = width; 47 | this.height = height; 48 | tilesInt = new int[width * height]; 49 | generateLevel(); 50 | } 51 | 52 | public Level(String path) { 53 | loadLevel(path); 54 | generateLevel(); 55 | } 56 | 57 | protected void generateLevel() { 58 | for (int y = 0; y < 64; y++) { 59 | for (int x = 0; x < 64; x++) { 60 | getTile(x, y); 61 | } 62 | } 63 | tile_size = 16; 64 | } 65 | 66 | protected void loadLevel(String path) { 67 | } 68 | 69 | public void update() { 70 | for (int i = 0; i < entities.size(); i++) { 71 | entities.get(i).update(); 72 | } 73 | for (int i = 0; i < projectiles.size(); i++) { 74 | projectiles.get(i).update(); 75 | } 76 | for (int i = 0; i < particles.size(); i++) { 77 | particles.get(i).update(); 78 | } 79 | for (int i = 0; i < players.size(); i++) { 80 | players.get(i).update(); 81 | } 82 | remove(); 83 | } 84 | 85 | public void onEvent(Event event) { 86 | getClientPlayer().onEvent(event); 87 | } 88 | 89 | private void remove() { 90 | for (int i = 0; i < entities.size(); i++) { 91 | if (entities.get(i).isRemoved()) entities.remove(i); 92 | } 93 | for (int i = 0; i < projectiles.size(); i++) { 94 | if (projectiles.get(i).isRemoved()) projectiles.remove(i); 95 | } 96 | for (int i = 0; i < particles.size(); i++) { 97 | if (particles.get(i).isRemoved()) particles.remove(i); 98 | } 99 | for (int i = 0; i < players.size(); i++) { 100 | if (players.get(i).isRemoved()) players.remove(i); 101 | } 102 | } 103 | 104 | public List getProjectiles() { 105 | return projectiles; 106 | } 107 | 108 | private void time() { 109 | } 110 | 111 | public boolean tileCollision(int x, int y, int size, int xOffset, int yOffset) { 112 | boolean solid = false; 113 | for (int c = 0; c < 4; c++) { 114 | int xt = (x - c % 2 * size + xOffset) >> 4; 115 | int yt = (y - c / 2 * size + yOffset) >> 4; 116 | if (getTile(xt, yt).solid()) solid = true; 117 | } 118 | return solid; 119 | } 120 | 121 | public void setScroll(int xScroll, int yScroll) { 122 | this.xScroll = xScroll; 123 | this.yScroll = yScroll; 124 | } 125 | 126 | public void render(Screen screen) { 127 | screen.setOffset(xScroll, yScroll); 128 | int x0 = xScroll >> 4; 129 | int x1 = (xScroll + screen.width + 16) >> 4; 130 | int y0 = yScroll >> 4; 131 | int y1 = (yScroll + screen.height + 16) >> 4; 132 | for (int y = y0; y < y1; y++) { 133 | for (int x = x0; x < x1; x++) { 134 | getTile(x, y).render(x, y, screen); 135 | } 136 | } 137 | for (int i = 0; i < entities.size(); i++) { 138 | entities.get(i).render(screen); 139 | } 140 | for (int i = 0; i < projectiles.size(); i++) { 141 | projectiles.get(i).render(screen); 142 | } 143 | for (int i = 0; i < particles.size(); i++) { 144 | particles.get(i).render(screen); 145 | } 146 | for (int i = 0; i < players.size(); i++) { 147 | players.get(i).render(screen); 148 | } 149 | 150 | 151 | } 152 | 153 | public void add(Entity e) { 154 | e.init(this); 155 | if (e instanceof Particle) { 156 | particles.add((Particle) e); 157 | } else if (e instanceof Projectile) { 158 | projectiles.add((Projectile) e); 159 | } else if (e instanceof Player) { 160 | players.add((Player) e); 161 | } else { 162 | entities.add(e); 163 | } 164 | } 165 | 166 | public void addPlayer(Mob player) { 167 | player.init(this); 168 | players.add(player); 169 | } 170 | 171 | public List getPlayers() { 172 | return players; 173 | } 174 | 175 | public Mob getPlayerAt(int index) { 176 | return players.get(index); 177 | } 178 | 179 | public Player getClientPlayer() { 180 | return (Player) players.get(0); 181 | } 182 | 183 | public List findPath(Vector2i start, Vector2i goal) { 184 | List openList = new ArrayList(); 185 | List closedList = new ArrayList(); 186 | Node current = new Node(start, null, 0, getDistance(start, goal)); 187 | openList.add(current); 188 | while (openList.size() > 0) { 189 | Collections.sort(openList, nodeSorter); 190 | current = openList.get(0); 191 | if (current.tile.equals(goal)) { 192 | List path = new ArrayList(); 193 | while (current.parent != null) { 194 | path.add(current); 195 | current = current.parent; 196 | } 197 | openList.clear(); 198 | closedList.clear(); 199 | return path; 200 | } 201 | openList.remove(current); 202 | closedList.add(current); 203 | for (int i = 0; i < 9; i++) { 204 | if (i == 4) continue; 205 | int x = current.tile.getX(); 206 | int y = current.tile.getY(); 207 | int xi = (i % 3) - 1; 208 | int yi = (i / 3) - 1; 209 | Tile at = getTile(x + xi, y + yi); 210 | if (at == null) continue; 211 | if (at.solid()) continue; 212 | Vector2i a = new Vector2i(x + xi, y + yi); 213 | double gCost = current.gCost + (getDistance(current.tile, a) == 1 ? 1 : 0.95); 214 | double hCost = getDistance(a, goal); 215 | Node node = new Node(a, current, gCost, hCost); 216 | if (vecInList(closedList, a) && gCost >= node.gCost) continue; 217 | if (!vecInList(openList, a) || gCost < node.gCost) openList.add(node); 218 | } 219 | } 220 | closedList.clear(); 221 | return null; 222 | } 223 | 224 | private boolean vecInList(List list, Vector2i vector) { 225 | for (Node n : list) { 226 | if (n.tile.equals(vector)) return true; 227 | } 228 | return false; 229 | } 230 | 231 | private double getDistance(Vector2i tile, Vector2i goal) { 232 | double dx = tile.getX() - goal.getX(); 233 | double dy = tile.getY() - goal.getY(); 234 | return Math.sqrt(dx * dx + dy * dy); 235 | } 236 | 237 | public List getEntities(Entity e, int radius) { 238 | List result = new ArrayList(); 239 | int ex = e.getX(); 240 | int ey = e.getY(); 241 | for (int i = 0; i < entities.size(); i++) { 242 | Entity entity = entities.get(i); 243 | if (entity.equals(e)) continue; 244 | int x = entity.getX(); 245 | int y = entity.getY(); 246 | int dx = Math.abs(x - ex); 247 | int dy = Math.abs(y - ey); 248 | double distance = Math.sqrt((dx * dx) + (dy * dy)); 249 | if (distance <= radius) result.add(entity); 250 | } 251 | return result; 252 | } 253 | 254 | public List getPlayers(Entity e, int radius) { 255 | List result = new ArrayList(); 256 | int ex = e.getX(); 257 | int ey = e.getY(); 258 | for (int i = 0; i < players.size(); i++) { 259 | Mob player = players.get(i); 260 | int x = player.getX(); 261 | int y = player.getY(); 262 | int dx = Math.abs(x - ex); 263 | int dy = Math.abs(y - ey); 264 | double distance = Math.sqrt((dx * dx) + (dy * dy)); 265 | if (distance <= radius) result.add(player); 266 | } 267 | return result; 268 | } 269 | 270 | // Grass = 0xFF00FF00 271 | // Flower = 0xFFFFFF00 272 | // Rock = 0xFF7F7F00 273 | public Tile getTile(int x, int y) { 274 | if (x < 0 || y < 0 || x >= width || y >= height) return Tile.voidTile; 275 | if (tiles[x + y * width] == Tile.col_spawn_floor) return Tile.spawn_floor; 276 | if (tiles[x + y * width] == Tile.col_spawn_grass) return Tile.spawn_grass; 277 | if (tiles[x + y * width] == Tile.col_spawn_hedge) return Tile.spawn_hedge; 278 | if (tiles[x + y * width] == Tile.col_spawn_wall1) return Tile.spawn_wall1; 279 | if (tiles[x + y * width] == Tile.col_spawn_wall2) return Tile.spawn_wall2; 280 | if (tiles[x + y * width] == Tile.col_spawn_water) return Tile.spawn_water; 281 | return Tile.voidTile; 282 | } 283 | 284 | } 285 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/Node.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level; 2 | 3 | import com.thecherno.rain.util.Vector2i; 4 | 5 | public class Node { 6 | 7 | public Vector2i tile; 8 | public Node parent; 9 | public double fCost, gCost, hCost; 10 | 11 | public Node(Vector2i tile, Node parent, double gCost, double hCost) { 12 | this.tile = tile; 13 | this.parent = parent; 14 | this.gCost = gCost; 15 | this.hCost = hCost; 16 | this.fCost = this.gCost + this.hCost; 17 | } 18 | } -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/RandomLevel.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level; 2 | 3 | import java.util.Random; 4 | 5 | public class RandomLevel extends Level { 6 | 7 | private static final Random random = new Random(); 8 | 9 | public RandomLevel(int width, int height) { 10 | super(width, height); 11 | } 12 | 13 | protected void generateLevel() { 14 | for (int y = 0; y < height; y++) { 15 | for (int x = 0; x < width; x++) { 16 | tilesInt[x + y * width] = random.nextInt(4); 17 | } 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/SpawnLevel.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.IOException; 5 | 6 | import javax.imageio.ImageIO; 7 | 8 | import com.thecherno.rain.entity.mob.Dummy; 9 | import com.thecherno.rain.entity.mob.Player; 10 | import com.thecherno.rain.entity.mob.Shooter; 11 | 12 | public class SpawnLevel extends Level { 13 | 14 | public SpawnLevel(String path) { 15 | super(path); 16 | } 17 | 18 | protected void loadLevel(String path) { 19 | try { 20 | BufferedImage image = ImageIO.read(SpawnLevel.class.getResource(path)); 21 | int w = width = image.getWidth(); 22 | int h = height = image.getHeight(); 23 | tiles = new int[w * h]; 24 | image.getRGB(0, 0, w, h, tiles, 0, w); 25 | } catch (IOException e) { 26 | e.printStackTrace(); 27 | System.out.println("Exception! Could not load level file!"); 28 | } 29 | //add(new Chaser(20, 55)); 30 | //add(new Star(17, 35)); 31 | add(new Shooter(20, 48)); 32 | add(new Shooter(20, 55)); 33 | add(new Dummy(15, 53)); 34 | 35 | for (int i = 0; i < 5; i++) { 36 | //add(new Dummy(20, 55)); 37 | } 38 | } 39 | 40 | protected void generateLevel() { 41 | for (int y = 0; y < 64; y++) { 42 | for (int x = 0; x < 64; x++) { 43 | getTile(x, y); 44 | } 45 | } 46 | tile_size = 16; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/TileCoordinate.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level; 2 | 3 | public class TileCoordinate { 4 | 5 | private int x, y; 6 | private final int TILE_SIZE = 16; 7 | 8 | public TileCoordinate(int x, int y) { 9 | this.x = x * TILE_SIZE; 10 | this.y = y * TILE_SIZE; 11 | } 12 | 13 | public int x() { 14 | return x; 15 | } 16 | 17 | public int y() { 18 | return y; 19 | } 20 | 21 | public int[] xy() { 22 | int[] r = new int[2]; 23 | r[0] = x; 24 | r[1] = y; 25 | return r; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/FlowerTile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | 6 | public class FlowerTile extends Tile { 7 | 8 | public FlowerTile(Sprite sprite) { 9 | super(sprite); 10 | } 11 | 12 | public void render(int x, int y, Screen screen) { 13 | screen.renderTile(x << 4, y << 4, this); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/GrassTile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | 6 | public class GrassTile extends Tile { 7 | 8 | public GrassTile(Sprite sprite) { 9 | super(sprite); 10 | } 11 | 12 | public void render(int x, int y, Screen screen) { 13 | screen.renderTile(x << 4, y << 4, this); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/RockTile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | 6 | public class RockTile extends Tile { 7 | 8 | public RockTile(Sprite sprite) { 9 | super(sprite); 10 | } 11 | 12 | public void render(int x, int y, Screen screen) { 13 | screen.renderTile(x << 4, y << 4, this); 14 | } 15 | 16 | public boolean solid() { 17 | return true; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/Tile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | import com.thecherno.rain.level.tile.spawn_level.SpawnFloorTile; 6 | import com.thecherno.rain.level.tile.spawn_level.SpawnGrassTile; 7 | import com.thecherno.rain.level.tile.spawn_level.SpawnHedgeTile; 8 | import com.thecherno.rain.level.tile.spawn_level.SpawnWallTile; 9 | import com.thecherno.rain.level.tile.spawn_level.SpawnWaterTile; 10 | 11 | public class Tile { 12 | 13 | public Sprite sprite; 14 | 15 | public static Tile grass = new GrassTile(Sprite.grass); 16 | public static Tile flower = new FlowerTile(Sprite.flower); 17 | public static Tile rock = new RockTile(Sprite.rock); 18 | public static Tile voidTile = new VoidTile(Sprite.voidSprite); 19 | 20 | public static Tile spawn_grass = new SpawnGrassTile(Sprite.spawn_grass); 21 | public static Tile spawn_hedge = new SpawnHedgeTile(Sprite.spawn_hedge); 22 | public static Tile spawn_water = new SpawnWaterTile(Sprite.spawn_water); 23 | public static Tile spawn_wall1 = new SpawnWallTile(Sprite.spawn_wall1); 24 | public static Tile spawn_wall2 = new SpawnWallTile(Sprite.spawn_wall2); 25 | public static Tile spawn_floor = new SpawnFloorTile(Sprite.spawn_floor); 26 | 27 | public static final int col_spawn_grass = 0xff00ff00; 28 | public static final int col_spawn_hedge = 0; //unused 29 | public static final int col_spawn_water = 0; //unused 30 | public static final int col_spawn_wall1 = 0xff808080; 31 | public static final int col_spawn_wall2 = 0xff303030; 32 | public static final int col_spawn_floor = 0xff724715; 33 | public static final int col_spawn = 0xff38EEFF; 34 | 35 | public Tile(Sprite sprite) { 36 | this.sprite = sprite; 37 | } 38 | 39 | public void render(int x, int y, Screen screen) { 40 | } 41 | 42 | public boolean solid() { 43 | return false; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/VoidTile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | 6 | public class VoidTile extends Tile { 7 | 8 | public VoidTile(Sprite sprite) { 9 | super(sprite); 10 | } 11 | 12 | public void render(int x, int y, Screen screen) { 13 | screen.renderTile(x << 4, y << 4, this); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/spawn_level/SpawnFloorTile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile.spawn_level; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | import com.thecherno.rain.level.tile.Tile; 6 | 7 | public class SpawnFloorTile extends Tile { 8 | 9 | public SpawnFloorTile(Sprite sprite) { 10 | super(sprite); 11 | } 12 | 13 | public void render(int x, int y, Screen screen) { 14 | screen.renderTile(x << 4, y << 4, this); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/spawn_level/SpawnGrassTile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile.spawn_level; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | import com.thecherno.rain.level.tile.Tile; 6 | 7 | public class SpawnGrassTile extends Tile { 8 | 9 | public SpawnGrassTile(Sprite sprite) { 10 | super(sprite); 11 | } 12 | 13 | public void render(int x, int y, Screen screen) { 14 | screen.renderTile(x << 4, y << 4, this); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/spawn_level/SpawnHedgeTile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile.spawn_level; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | import com.thecherno.rain.level.tile.Tile; 6 | 7 | public class SpawnHedgeTile extends Tile { 8 | 9 | public SpawnHedgeTile(Sprite sprite) { 10 | super(sprite); 11 | } 12 | 13 | public void render(int x, int y, Screen screen) { 14 | screen.renderTile(x << 4, y << 4, this); 15 | } 16 | 17 | public boolean solid() { 18 | return true; 19 | } 20 | 21 | public boolean breakable() { 22 | return true; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/spawn_level/SpawnWallTile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile.spawn_level; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | import com.thecherno.rain.level.tile.Tile; 6 | 7 | public class SpawnWallTile extends Tile { 8 | 9 | public SpawnWallTile(Sprite sprite) { 10 | super(sprite); 11 | } 12 | 13 | public void render(int x, int y, Screen screen) { 14 | screen.renderTile(x << 4, y << 4, this); 15 | } 16 | 17 | public boolean solid() { 18 | return true; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/level/tile/spawn_level/SpawnWaterTile.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.level.tile.spawn_level; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | import com.thecherno.rain.graphics.Sprite; 5 | import com.thecherno.rain.level.tile.Tile; 6 | 7 | public class SpawnWaterTile extends Tile { 8 | 9 | public SpawnWaterTile(Sprite sprite) { 10 | super(sprite); 11 | } 12 | public void render(int x, int y, Screen screen) { 13 | screen.renderTile(x << 4, y << 4, this); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/net/Client.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.net; 2 | 3 | import java.io.IOException; 4 | import java.net.DatagramPacket; 5 | import java.net.DatagramSocket; 6 | import java.net.InetAddress; 7 | import java.net.SocketException; 8 | import java.net.UnknownHostException; 9 | import java.util.function.BinaryOperator; 10 | 11 | import com.thecherno.rain.util.BinaryWriter; 12 | import com.thecherno.raincloud.serialization.RCDatabase; 13 | 14 | public class Client { 15 | 16 | private final static byte[] PACKET_HEADER = new byte[] { 0x40, 0x40 }; 17 | private final static byte PACKET_TYPE_CONNECT = 0x01; 18 | 19 | public enum Error { 20 | NONE, INVALID_HOST, SOCKET_EXCEPTION 21 | } 22 | 23 | private String ipAddress; 24 | private int port; 25 | private Error errorCode = Error.NONE; 26 | 27 | private InetAddress serverAddress; 28 | private DatagramSocket socket; 29 | 30 | /** 31 | * 32 | * @param host 33 | * Eg. 192.168.1.1:5000 34 | */ 35 | public Client(String host) { 36 | String[] parts = host.split(":"); 37 | if (parts.length != 2) { 38 | errorCode = Error.INVALID_HOST; 39 | return; 40 | } 41 | ipAddress = parts[0]; 42 | try { 43 | port = Integer.parseInt(parts[1]); 44 | } catch (NumberFormatException e) { 45 | errorCode = Error.INVALID_HOST; 46 | return; 47 | } 48 | } 49 | 50 | /** 51 | * 52 | * @param host 53 | * Eg. 192.168.1.1 54 | * @param port 55 | * Eg. 5000 56 | */ 57 | public Client(String host, int port) { 58 | this.ipAddress = host; 59 | this.port = port; 60 | } 61 | 62 | public boolean connect() { 63 | try { 64 | serverAddress = InetAddress.getByName(ipAddress); 65 | } catch (UnknownHostException e) { 66 | e.printStackTrace(); 67 | errorCode = Error.INVALID_HOST; 68 | return false; 69 | } 70 | 71 | try { 72 | socket = new DatagramSocket(); 73 | } catch (SocketException e) { 74 | e.printStackTrace(); 75 | errorCode = Error.SOCKET_EXCEPTION; 76 | return false; 77 | } 78 | sendConnectionPacket(); 79 | // Wait for server to reply 80 | return true; 81 | } 82 | 83 | private void sendConnectionPacket() { 84 | BinaryWriter writer = new BinaryWriter(); 85 | writer.write(PACKET_HEADER); 86 | writer.write(PACKET_TYPE_CONNECT); 87 | send(writer.getBuffer()); 88 | } 89 | 90 | public void send(byte[] data) { 91 | assert(socket.isConnected()); 92 | DatagramPacket packet = new DatagramPacket(data, data.length, serverAddress, port); 93 | try { 94 | socket.send(packet); 95 | } catch (IOException e) { 96 | e.printStackTrace(); 97 | } 98 | } 99 | 100 | public void send(RCDatabase database) { 101 | byte[] data = new byte[database.getSize()]; 102 | database.getBytes(data, 0); 103 | send(data); 104 | } 105 | 106 | public Error getErrorCode() { 107 | return errorCode; 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/net/player/NetPlayer.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.net.player; 2 | 3 | import com.thecherno.rain.entity.mob.Mob; 4 | import com.thecherno.rain.graphics.Screen; 5 | 6 | public class NetPlayer extends Mob { 7 | 8 | public NetPlayer() { 9 | x = 22 * 16; 10 | y = 42 * 16; 11 | } 12 | 13 | public void update() { 14 | 15 | } 16 | 17 | public void render(Screen screen) { 18 | screen.fillRect(x, y, 32, 32, 0x2030cc, true); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/util/BinaryWriter.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.util; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class BinaryWriter { 8 | 9 | private List buffer; 10 | 11 | public BinaryWriter() { 12 | buffer = new ArrayList(); 13 | } 14 | 15 | public BinaryWriter(int size) { 16 | buffer = new ArrayList(size); 17 | } 18 | 19 | public byte[] getBuffer() { 20 | Byte[] array = new Byte[buffer.size()]; 21 | buffer.toArray(array); 22 | byte[] result = new byte[buffer.size()]; 23 | for (int i = 0; i < result.length; i++) 24 | result[i] = array[i]; 25 | return result; 26 | } 27 | 28 | public void write(byte data) { 29 | buffer.add(data); 30 | } 31 | 32 | public void write(byte[] data) { 33 | for (int i = 0; i < data.length; i++) 34 | buffer.add(data[i]); 35 | } 36 | 37 | public void write(int data) { 38 | byte[] b = ByteBuffer.allocate(4).putInt(data).array(); 39 | write(b); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/util/Debug.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.util; 2 | 3 | import com.thecherno.rain.graphics.Screen; 4 | 5 | public class Debug { 6 | 7 | private Debug() { 8 | } 9 | 10 | public static void drawRect(Screen screen, int x, int y, int width, int height, boolean fixed) { 11 | drawRect(screen, x, y, width, height, 0xff0000, fixed); 12 | } 13 | 14 | public static void drawRect(Screen screen, int x, int y, int width, int height, int col, boolean fixed) { 15 | screen.drawRect(x, y, width, height, col, fixed); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/util/ImageUtils.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.util; 2 | 3 | import static com.thecherno.rain.util.MathUtils.clamp; 4 | 5 | import java.awt.image.BufferedImage; 6 | import java.awt.image.DataBufferByte; 7 | import java.awt.image.DataBufferInt; 8 | 9 | public class ImageUtils { 10 | 11 | private ImageUtils() { 12 | } 13 | 14 | /** 15 | * Returns a NEW image! 16 | */ 17 | public static BufferedImage changeBrightness(BufferedImage original, int amount) { 18 | BufferedImage result = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_ARGB); 19 | byte[] pixels = ((DataBufferByte)original.getRaster().getDataBuffer()).getData(); 20 | int[] resultPixels = ((DataBufferInt)result.getRaster().getDataBuffer()).getData(); 21 | 22 | int offset = 0; 23 | for (int yy = 0; yy < original.getHeight(); yy++) { 24 | for (int xx = 0; xx < original.getWidth(); xx++) { 25 | int a = Byte.toUnsignedInt(pixels[offset++]); 26 | int b = Byte.toUnsignedInt(pixels[offset++]); 27 | int g = Byte.toUnsignedInt(pixels[offset++]); 28 | int r = Byte.toUnsignedInt(pixels[offset++]); 29 | 30 | r = clamp(r + amount, 0, 255); 31 | g = clamp(g + amount, 0, 255); 32 | b = clamp(b + amount, 0, 255); 33 | 34 | resultPixels[xx + yy * result.getWidth()] = a << 24 | r << 16 | g << 8 | b; 35 | } 36 | } 37 | return result; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/util/MathUtils.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.util; 2 | 3 | public class MathUtils { 4 | 5 | private MathUtils() { 6 | } 7 | 8 | public static int min(int value, int min) { 9 | return value < min ? min : value; 10 | } 11 | 12 | public static int max(int value, int max) { 13 | return value > max ? max : value; 14 | } 15 | 16 | public static int clamp(int value, int min, int max) { 17 | if (value < min) 18 | return min; 19 | if (value > max) 20 | return max; 21 | return value; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Rain/src/com/thecherno/rain/util/Vector2i.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rain.util; 2 | 3 | public class Vector2i { 4 | 5 | public int x, y; 6 | 7 | public Vector2i() { 8 | set(0, 0); 9 | } 10 | 11 | public Vector2i(Vector2i vector) { 12 | set(vector.x, vector.y); 13 | } 14 | 15 | public Vector2i(int x, int y) { 16 | set(x, y); 17 | } 18 | 19 | public void set(int x, int y) { 20 | this.x = x; 21 | this.y = y; 22 | } 23 | 24 | public int getX() { 25 | return x; 26 | } 27 | 28 | public int getY() { 29 | return y; 30 | } 31 | 32 | public Vector2i add(Vector2i vector) { 33 | this.x += vector.x; 34 | this.y += vector.y; 35 | return this; 36 | } 37 | 38 | public Vector2i add(int value) { 39 | this.x += value; 40 | this.y += value; 41 | return this; 42 | } 43 | 44 | public Vector2i subtract(Vector2i vector) { 45 | this.x -= vector.x; 46 | this.y -= vector.y; 47 | return this; 48 | } 49 | 50 | public Vector2i setX(int x) { 51 | this.x = x; 52 | return this; 53 | } 54 | 55 | public Vector2i setY(int y) { 56 | this.y = y; 57 | return this; 58 | } 59 | 60 | public static double getDistance(Vector2i v0, Vector2i v1) { 61 | double x = v0.getX() - v1.getX(); 62 | double y = v0.getY() - v1.getY(); 63 | return Math.sqrt(x * x + y * y); 64 | } 65 | 66 | public boolean equals(Object object) { 67 | if (!(object instanceof Vector2i)) return false; 68 | Vector2i vec = (Vector2i) object; 69 | if (vec.getX() == this.getX() && vec.getY() == this.getY()) return true; 70 | return false; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /RainCloud-Serialization/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /RainCloud-Serialization/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | RainCloud-Serialization 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /RainCloud-Serialization/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/ContainerType.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | public class ContainerType { 4 | 5 | public static final byte UNKNOWN = 0; 6 | public static final byte FIELD = 1; 7 | public static final byte ARRAY = 2; 8 | public static final byte STRING = 3; 9 | public static final byte OBJECT = 4; 10 | public static final byte DATABASE = 5; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCArray.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | public class RCArray extends RCBase { 8 | 9 | public static final byte CONTAINER_TYPE = ContainerType.ARRAY; 10 | public byte type; 11 | public int count; 12 | public byte[] data; 13 | 14 | private short[] shortData; 15 | private char[] charData; 16 | private int[] intData; 17 | private long[] longData; 18 | private float[] floatData; 19 | private double[] doubleData; 20 | private boolean[] booleanData; 21 | 22 | private RCArray() { 23 | size += 1 + 1 + 4; 24 | } 25 | 26 | private void updateSize() { 27 | size += getDataSize(); 28 | } 29 | 30 | public int getBytes(byte[] dest, int pointer) { 31 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 32 | pointer = writeBytes(dest, pointer, nameLength); 33 | pointer = writeBytes(dest, pointer, name); 34 | pointer = writeBytes(dest, pointer, size); 35 | pointer = writeBytes(dest, pointer, type); 36 | pointer = writeBytes(dest, pointer, count); 37 | 38 | switch(type) { 39 | case Type.BYTE: 40 | pointer = writeBytes(dest, pointer, data); 41 | break; 42 | case Type.SHORT: 43 | pointer = writeBytes(dest, pointer, shortData); 44 | break; 45 | case Type.CHAR: 46 | pointer = writeBytes(dest, pointer, charData); 47 | break; 48 | case Type.INTEGER: 49 | pointer = writeBytes(dest, pointer, intData); 50 | break; 51 | case Type.LONG: 52 | pointer = writeBytes(dest, pointer, longData); 53 | break; 54 | case Type.FLOAT: 55 | pointer = writeBytes(dest, pointer, floatData); 56 | break; 57 | case Type.DOUBLE: 58 | pointer = writeBytes(dest, pointer, doubleData); 59 | break; 60 | case Type.BOOLEAN: 61 | pointer = writeBytes(dest, pointer, booleanData); 62 | break; 63 | } 64 | return pointer; 65 | } 66 | 67 | public int getSize() { 68 | return size; 69 | } 70 | 71 | public int getDataSize() { 72 | switch(type) { 73 | case Type.BYTE: return data.length * Type.getSize(Type.BYTE); 74 | case Type.SHORT: return shortData.length * Type.getSize(Type.SHORT); 75 | case Type.CHAR: return charData.length * Type.getSize(Type.CHAR); 76 | case Type.INTEGER: return intData.length * Type.getSize(Type.INTEGER); 77 | case Type.LONG: return longData.length * Type.getSize(Type.LONG); 78 | case Type.FLOAT: return floatData.length * Type.getSize(Type.FLOAT); 79 | case Type.DOUBLE: return doubleData.length * Type.getSize(Type.DOUBLE); 80 | case Type.BOOLEAN: return booleanData.length * Type.getSize(Type.BOOLEAN); 81 | } 82 | return 0; 83 | } 84 | 85 | public static RCArray Byte(String name, byte[] data) { 86 | RCArray array = new RCArray(); 87 | array.setName(name); 88 | array.type = Type.BYTE; 89 | array.count = data.length; 90 | array.data = data; 91 | array.updateSize(); 92 | return array; 93 | } 94 | 95 | public static RCArray Short(String name, short[] data) { 96 | RCArray array = new RCArray(); 97 | array.setName(name); 98 | array.type = Type.SHORT; 99 | array.count = data.length; 100 | array.shortData = data; 101 | array.updateSize(); 102 | return array; 103 | } 104 | 105 | public static RCArray Char(String name, char[] data) { 106 | RCArray array = new RCArray(); 107 | array.setName(name); 108 | array.type = Type.CHAR; 109 | array.count = data.length; 110 | array.charData = data; 111 | array.updateSize(); 112 | return array; 113 | } 114 | 115 | public static RCArray Integer(String name, int[] data) { 116 | RCArray array = new RCArray(); 117 | array.setName(name); 118 | array.type = Type.INTEGER; 119 | array.count = data.length; 120 | array.intData = data; 121 | array.updateSize(); 122 | return array; 123 | } 124 | 125 | public static RCArray Long(String name, long[] data) { 126 | RCArray array = new RCArray(); 127 | array.setName(name); 128 | array.type = Type.LONG; 129 | array.count = data.length; 130 | array.longData = data; 131 | array.updateSize(); 132 | return array; 133 | } 134 | 135 | public static RCArray Float(String name, float[] data) { 136 | RCArray array = new RCArray(); 137 | array.setName(name); 138 | array.type = Type.FLOAT; 139 | array.count = data.length; 140 | array.floatData = data; 141 | array.updateSize(); 142 | return array; 143 | } 144 | 145 | public static RCArray Double(String name, double[] data) { 146 | RCArray array = new RCArray(); 147 | array.setName(name); 148 | array.type = Type.DOUBLE; 149 | array.count = data.length; 150 | array.doubleData = data; 151 | array.updateSize(); 152 | return array; 153 | } 154 | 155 | public static RCArray Boolean(String name, boolean[] data) { 156 | RCArray array = new RCArray(); 157 | array.setName(name); 158 | array.type = Type.BOOLEAN; 159 | array.count = data.length; 160 | array.booleanData = data; 161 | array.updateSize(); 162 | return array; 163 | } 164 | 165 | public static RCArray Deserialize(byte[] data, int pointer) { 166 | byte containerType = data[pointer++]; 167 | assert(containerType == CONTAINER_TYPE); 168 | 169 | RCArray result = new RCArray(); 170 | result.nameLength = readShort(data, pointer); 171 | pointer += 2; 172 | result.name = readString(data, pointer, result.nameLength).getBytes(); 173 | pointer += result.nameLength; 174 | 175 | result.size = readInt(data, pointer); 176 | pointer += 4; 177 | 178 | result.type = data[pointer++]; 179 | 180 | result.count = readInt(data, pointer); 181 | pointer += 4; 182 | 183 | switch(result.type) { 184 | case Type.BYTE: 185 | result.data = new byte[result.count]; 186 | readBytes(data, pointer, result.data); 187 | break; 188 | case Type.SHORT: 189 | result.shortData = new short[result.count]; 190 | readShorts(data, pointer, result.shortData); 191 | break; 192 | case Type.CHAR: 193 | result.charData = new char[result.count]; 194 | readChars(data, pointer, result.charData); 195 | break; 196 | case Type.INTEGER: 197 | result.intData = new int[result.count]; 198 | readInts(data, pointer, result.intData); 199 | break; 200 | case Type.LONG: 201 | result.longData = new long[result.count]; 202 | readLongs(data, pointer, result.longData); 203 | break; 204 | case Type.FLOAT: 205 | result.floatData = new float[result.count]; 206 | readFloats(data, pointer, result.floatData); 207 | break; 208 | case Type.DOUBLE: 209 | result.doubleData = new double[result.count]; 210 | readDoubles(data, pointer, result.doubleData); 211 | break; 212 | case Type.BOOLEAN: 213 | result.booleanData = new boolean[result.count]; 214 | readBooleans(data, pointer, result.booleanData); 215 | break; 216 | } 217 | 218 | pointer += result.count * Type.getSize(result.type); 219 | 220 | return result; 221 | } 222 | 223 | } 224 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCBase.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | public abstract class RCBase { 4 | 5 | protected short nameLength; 6 | protected byte[] name; 7 | 8 | protected int size = 2 + 4; 9 | 10 | public String getName() { 11 | return new String(name, 0, nameLength); 12 | } 13 | 14 | public void setName(String name) { 15 | assert(name.length() < Short.MAX_VALUE); 16 | 17 | if (this.name != null) 18 | size -= this.name.length; 19 | 20 | nameLength = (short)name.length(); 21 | this.name = name.getBytes(); 22 | size += nameLength; 23 | } 24 | 25 | public abstract int getSize(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCDatabase.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | import java.io.BufferedInputStream; 6 | import java.io.BufferedOutputStream; 7 | import java.io.FileInputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class RCDatabase extends RCBase { 14 | 15 | public static final byte[] HEADER = "RCDB".getBytes(); 16 | public static final short VERSION = 0x0100; 17 | public static final byte CONTAINER_TYPE = ContainerType.DATABASE; 18 | private short objectCount; 19 | public List objects = new ArrayList(); 20 | 21 | private RCDatabase() { 22 | } 23 | 24 | public RCDatabase(String name) { 25 | setName(name); 26 | 27 | size += HEADER.length + 2 + 1 + 2; 28 | } 29 | 30 | public void addObject(RCObject object) { 31 | objects.add(object); 32 | size += object.getSize(); 33 | 34 | objectCount = (short)objects.size(); 35 | } 36 | 37 | public int getSize() { 38 | return size; 39 | } 40 | 41 | public int getBytes(byte[] dest, int pointer) { 42 | pointer = writeBytes(dest, pointer, HEADER); 43 | pointer = writeBytes(dest, pointer, VERSION); 44 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 45 | pointer = writeBytes(dest, pointer, nameLength); 46 | pointer = writeBytes(dest, pointer, name); 47 | pointer = writeBytes(dest, pointer, size); 48 | 49 | pointer = writeBytes(dest, pointer, objectCount); 50 | for (RCObject object : objects) 51 | pointer = object.getBytes(dest, pointer); 52 | 53 | return pointer; 54 | } 55 | 56 | public static RCDatabase Deserialize(byte[] data) { 57 | int pointer = 0; 58 | //assert(readString(data, pointer, HEADER.length).equals(HEADER)); 59 | pointer += HEADER.length; 60 | 61 | if (readShort(data, pointer) != VERSION) { 62 | System.err.println("Invalid RCDB version!"); 63 | return null; 64 | } 65 | pointer += 2; 66 | 67 | byte containerType = readByte(data, pointer++); 68 | assert(containerType == CONTAINER_TYPE); 69 | 70 | RCDatabase result = new RCDatabase(); 71 | result.nameLength = readShort(data, pointer); 72 | pointer += 2; 73 | result.name = readString(data, pointer, result.nameLength).getBytes(); 74 | pointer += result.nameLength; 75 | 76 | result.size = readInt(data, pointer); 77 | pointer += 4; 78 | 79 | result.objectCount = readShort(data, pointer); 80 | pointer += 2; 81 | 82 | for (int i = 0; i < result.objectCount; i++) { 83 | RCObject object = RCObject.Deserialize(data, pointer); 84 | result.objects.add(object); 85 | pointer += object.getSize(); 86 | } 87 | 88 | return result; 89 | } 90 | 91 | public RCObject findObject(String name) { 92 | for (RCObject object : objects) { 93 | if (object.getName().equals(name)) 94 | return object; 95 | } 96 | return null; 97 | } 98 | 99 | public static RCDatabase DeserializeFromFile(String path) { 100 | byte[] buffer = null; 101 | try { 102 | BufferedInputStream stream = new BufferedInputStream(new FileInputStream(path)); 103 | buffer = new byte[stream.available()]; 104 | stream.read(buffer); 105 | stream.close(); 106 | } catch (IOException e) { 107 | return null; 108 | } 109 | 110 | return Deserialize(buffer); 111 | } 112 | 113 | public void serializeToFile(String path) { 114 | byte[] data = new byte[getSize()]; 115 | getBytes(data, 0); 116 | try { 117 | BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(path)); 118 | stream.write(data); 119 | stream.close(); 120 | } catch (IOException e) { 121 | e.printStackTrace(); 122 | } 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCField.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | public class RCField extends RCBase { 6 | 7 | public static final byte CONTAINER_TYPE = ContainerType.FIELD; 8 | public byte type; 9 | public byte[] data; 10 | 11 | private RCField() { 12 | } 13 | 14 | public byte getByte() { 15 | return data[0]; 16 | } 17 | 18 | public short getShort() { 19 | return readShort(data, 0); 20 | } 21 | 22 | public char getChar() { 23 | return readChar(data, 0); 24 | } 25 | 26 | public int getInt() { 27 | return readInt(data, 0); 28 | } 29 | 30 | public long getLong() { 31 | return readLong(data, 0); 32 | } 33 | 34 | public double getDouble() { 35 | return readDouble(data, 0); 36 | } 37 | 38 | public float getFloat() { 39 | return readFloat(data, 0); 40 | } 41 | 42 | public boolean getBoolean() { 43 | return readBoolean(data, 0); 44 | } 45 | 46 | public int getBytes(byte[] dest, int pointer) { 47 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 48 | pointer = writeBytes(dest, pointer, nameLength); 49 | pointer = writeBytes(dest, pointer, name); 50 | pointer = writeBytes(dest, pointer, type); 51 | pointer = writeBytes(dest, pointer, data); 52 | return pointer; 53 | } 54 | 55 | public int getSize() { 56 | assert(data.length == Type.getSize(type)); 57 | return 1 + 2 + name.length + 1 + data.length; 58 | } 59 | 60 | public static RCField Byte(String name, byte value) { 61 | RCField field = new RCField(); 62 | field.setName(name); 63 | field.type = Type.BYTE; 64 | field.data = new byte[Type.getSize(Type.BYTE)]; 65 | writeBytes(field.data, 0, value); 66 | return field; 67 | } 68 | 69 | public static RCField Short(String name, short value) { 70 | RCField field = new RCField(); 71 | field.setName(name); 72 | field.type = Type.SHORT; 73 | field.data = new byte[Type.getSize(Type.SHORT)]; 74 | writeBytes(field.data, 0, value); 75 | return field; 76 | } 77 | 78 | public static RCField Char(String name, char value) { 79 | RCField field = new RCField(); 80 | field.setName(name); 81 | field.type = Type.CHAR; 82 | field.data = new byte[Type.getSize(Type.CHAR)]; 83 | writeBytes(field.data, 0, value); 84 | return field; 85 | } 86 | 87 | public static RCField Integer(String name, int value) { 88 | RCField field = new RCField(); 89 | field.setName(name); 90 | field.type = Type.INTEGER; 91 | field.data = new byte[Type.getSize(Type.INTEGER)]; 92 | writeBytes(field.data, 0, value); 93 | return field; 94 | } 95 | 96 | public static RCField Long(String name, long value) { 97 | RCField field = new RCField(); 98 | field.setName(name); 99 | field.type = Type.LONG; 100 | field.data = new byte[Type.getSize(Type.LONG)]; 101 | writeBytes(field.data, 0, value); 102 | return field; 103 | } 104 | 105 | public static RCField Float(String name, float value) { 106 | RCField field = new RCField(); 107 | field.setName(name); 108 | field.type = Type.FLOAT; 109 | field.data = new byte[Type.getSize(Type.FLOAT)]; 110 | writeBytes(field.data, 0, value); 111 | return field; 112 | } 113 | 114 | public static RCField Double(String name, double value) { 115 | RCField field = new RCField(); 116 | field.setName(name); 117 | field.type = Type.DOUBLE; 118 | field.data = new byte[Type.getSize(Type.DOUBLE)]; 119 | writeBytes(field.data, 0, value); 120 | return field; 121 | } 122 | 123 | public static RCField Boolean(String name, boolean value) { 124 | RCField field = new RCField(); 125 | field.setName(name); 126 | field.type = Type.BOOLEAN; 127 | field.data = new byte[Type.getSize(Type.BOOLEAN)]; 128 | writeBytes(field.data, 0, value); 129 | return field; 130 | } 131 | 132 | public static RCField Deserialize(byte[] data, int pointer) { 133 | byte containerType = data[pointer++]; 134 | assert(containerType == CONTAINER_TYPE); 135 | 136 | RCField result = new RCField(); 137 | result.nameLength = readShort(data, pointer); 138 | pointer += 2; 139 | result.name = readString(data, pointer, result.nameLength).getBytes(); 140 | pointer += result.nameLength; 141 | 142 | result.type = data[pointer++]; 143 | 144 | result.data = new byte[Type.getSize(result.type)]; 145 | readBytes(data, pointer, result.data); 146 | pointer += Type.getSize(result.type); 147 | return result; 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCObject.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class RCObject extends RCBase { 9 | 10 | public static final byte CONTAINER_TYPE = ContainerType.OBJECT; 11 | private short fieldCount; 12 | public List fields = new ArrayList(); 13 | private short stringCount; 14 | public List strings = new ArrayList(); 15 | private short arrayCount; 16 | public List arrays = new ArrayList(); 17 | 18 | private RCObject() { 19 | } 20 | 21 | public RCObject(String name) { 22 | size += 1 + 2 + 2 + 2; 23 | setName(name); 24 | } 25 | 26 | public void addField(RCField field) { 27 | fields.add(field); 28 | size += field.getSize(); 29 | 30 | fieldCount = (short)fields.size(); 31 | } 32 | 33 | public void addString(RCString string) { 34 | strings.add(string); 35 | size += string.getSize(); 36 | 37 | stringCount = (short)strings.size(); 38 | } 39 | 40 | public void addArray(RCArray array) { 41 | arrays.add(array); 42 | size += array.getSize(); 43 | 44 | arrayCount = (short)arrays.size(); 45 | } 46 | 47 | public int getSize() { 48 | return size; 49 | } 50 | 51 | public RCField findField(String name) { 52 | for (RCField field : fields) { 53 | if (field.getName().equals(name)) 54 | return field; 55 | } 56 | return null; 57 | } 58 | 59 | public RCString findString(String name) { 60 | for (RCString string : strings) { 61 | if (string.getName().equals(name)) 62 | return string; 63 | } 64 | return null; 65 | } 66 | 67 | public RCArray findArray(String name) { 68 | for (RCArray array : arrays) { 69 | if (array.getName().equals(name)) 70 | return array; 71 | } 72 | return null; 73 | } 74 | 75 | public int getBytes(byte[] dest, int pointer) { 76 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 77 | pointer = writeBytes(dest, pointer, nameLength); 78 | pointer = writeBytes(dest, pointer, name); 79 | pointer = writeBytes(dest, pointer, size); 80 | 81 | pointer = writeBytes(dest, pointer, fieldCount); 82 | for (RCField field : fields) 83 | pointer = field.getBytes(dest, pointer); 84 | 85 | pointer = writeBytes(dest, pointer, stringCount); 86 | for (RCString string : strings) 87 | pointer = string.getBytes(dest, pointer); 88 | 89 | pointer = writeBytes(dest, pointer, arrayCount); 90 | for (RCArray array : arrays) 91 | pointer = array.getBytes(dest, pointer); 92 | 93 | return pointer; 94 | } 95 | 96 | public static RCObject Deserialize(byte[] data, int pointer) { 97 | byte containerType = data[pointer++]; 98 | assert(containerType == CONTAINER_TYPE); 99 | 100 | RCObject result = new RCObject(); 101 | result.nameLength = readShort(data, pointer); 102 | pointer += 2; 103 | result.name = readString(data, pointer, result.nameLength).getBytes(); 104 | pointer += result.nameLength; 105 | 106 | result.size = readInt(data, pointer); 107 | pointer += 4; 108 | 109 | // Early-out: pointer += result.size - sizeOffset - result.nameLength; 110 | 111 | result.fieldCount = readShort(data, pointer); 112 | pointer += 2; 113 | 114 | for (int i = 0; i < result.fieldCount; i++) { 115 | RCField field = RCField.Deserialize(data, pointer); 116 | result.fields.add(field); 117 | pointer += field.getSize(); 118 | } 119 | 120 | result.stringCount = readShort(data, pointer); 121 | pointer += 2; 122 | 123 | for (int i = 0; i < result.stringCount; i++) { 124 | RCString string = RCString.Deserialize(data, pointer); 125 | result.strings.add(string); 126 | pointer += string.getSize(); 127 | } 128 | 129 | result.arrayCount = readShort(data, pointer); 130 | pointer += 2; 131 | 132 | for (int i = 0; i < result.arrayCount; i++) { 133 | RCArray array = RCArray.Deserialize(data, pointer); 134 | result.arrays.add(array); 135 | pointer += array.getSize(); 136 | } 137 | 138 | return result; 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/RCString.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import static com.thecherno.raincloud.serialization.SerializationUtils.*; 4 | 5 | public class RCString extends RCBase { 6 | 7 | public static final byte CONTAINER_TYPE = ContainerType.STRING; 8 | public int count; 9 | private char[] characters; 10 | 11 | private RCString() { 12 | size += 1 + 4; 13 | } 14 | 15 | public String getString() { 16 | return new String(characters); 17 | } 18 | 19 | private void updateSize() { 20 | size += getDataSize(); 21 | } 22 | 23 | public int getBytes(byte[] dest, int pointer) { 24 | pointer = writeBytes(dest, pointer, CONTAINER_TYPE); 25 | pointer = writeBytes(dest, pointer, nameLength); 26 | pointer = writeBytes(dest, pointer, name); 27 | pointer = writeBytes(dest, pointer, size); 28 | pointer = writeBytes(dest, pointer, count); 29 | pointer = writeBytes(dest, pointer, characters); 30 | return pointer; 31 | } 32 | 33 | public int getSize() { 34 | return size; 35 | } 36 | 37 | public int getDataSize() { 38 | return characters.length * Type.getSize(Type.CHAR); 39 | } 40 | 41 | public static RCString Create(String name, String data) { 42 | RCString string = new RCString(); 43 | string.setName(name); 44 | string.count = data.length(); 45 | string.characters = data.toCharArray(); 46 | string.updateSize(); 47 | return string; 48 | } 49 | 50 | public static RCString Deserialize(byte[] data, int pointer) { 51 | byte containerType = data[pointer++]; 52 | assert(containerType == CONTAINER_TYPE); 53 | 54 | RCString result = new RCString(); 55 | result.nameLength = readShort(data, pointer); 56 | pointer += 2; 57 | result.name = readString(data, pointer, result.nameLength).getBytes(); 58 | pointer += result.nameLength; 59 | 60 | result.size = readInt(data, pointer); 61 | pointer += 4; 62 | 63 | result.count = readInt(data, pointer); 64 | pointer += 4; 65 | 66 | result.characters = new char[result.count]; 67 | readChars(data, pointer, result.characters); 68 | 69 | pointer += result.count * Type.getSize(Type.CHAR); 70 | return result; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/SerializationUtils.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | public class SerializationUtils { 6 | 7 | public static int writeBytes(byte[] dest, int pointer, byte[] src) { 8 | assert(dest.length >= pointer + src.length); 9 | for (int i = 0; i < src.length; i++) 10 | dest[pointer++] = src[i]; 11 | return pointer; 12 | } 13 | 14 | public static int writeBytes(byte[] dest, int pointer, char[] src) { 15 | assert(dest.length > pointer + src.length); 16 | for (int i = 0; i < src.length; i++) 17 | pointer = writeBytes(dest, pointer, src[i]); 18 | return pointer; 19 | } 20 | 21 | public static int writeBytes(byte[] dest, int pointer, short[] src) { 22 | assert(dest.length > pointer + src.length); 23 | for (int i = 0; i < src.length; i++) 24 | pointer = writeBytes(dest, pointer, src[i]); 25 | return pointer; 26 | } 27 | 28 | public static int writeBytes(byte[] dest, int pointer, int[] src) { 29 | assert(dest.length > pointer + src.length); 30 | for (int i = 0; i < src.length; i++) 31 | pointer = writeBytes(dest, pointer, src[i]); 32 | return pointer; 33 | } 34 | 35 | public static int writeBytes(byte[] dest, int pointer, long[] src) { 36 | assert(dest.length > pointer + src.length); 37 | for (int i = 0; i < src.length; i++) 38 | pointer = writeBytes(dest, pointer, src[i]); 39 | return pointer; 40 | } 41 | 42 | public static int writeBytes(byte[] dest, int pointer, float[] src) { 43 | assert(dest.length > pointer + src.length); 44 | for (int i = 0; i < src.length; i++) 45 | pointer = writeBytes(dest, pointer, src[i]); 46 | return pointer; 47 | } 48 | 49 | public static int writeBytes(byte[] dest, int pointer, double[] src) { 50 | assert(dest.length > pointer + src.length); 51 | for (int i = 0; i < src.length; i++) 52 | pointer = writeBytes(dest, pointer, src[i]); 53 | return pointer; 54 | } 55 | 56 | public static int writeBytes(byte[] dest, int pointer, boolean[] src) { 57 | assert(dest.length > pointer + src.length); 58 | for (int i = 0; i < src.length; i++) 59 | pointer = writeBytes(dest, pointer, src[i]); 60 | return pointer; 61 | } 62 | 63 | public static int writeBytes(byte[] dest, int pointer, byte value) { 64 | assert(dest.length > pointer + Type.getSize(Type.BYTE)); 65 | dest[pointer++] = value; 66 | return pointer; 67 | } 68 | 69 | public static int writeBytes(byte[] dest, int pointer, short value) { 70 | assert(dest.length > pointer + Type.getSize(Type.SHORT)); 71 | dest[pointer++] = (byte)((value >> 8) & 0xff); 72 | dest[pointer++] = (byte)((value >> 0) & 0xff); 73 | return pointer; 74 | } 75 | 76 | public static int writeBytes(byte[] dest, int pointer, char value) { 77 | assert(dest.length > pointer + Type.getSize(Type.CHAR)); 78 | dest[pointer++] = (byte)((value >> 8) & 0xff); 79 | dest[pointer++] = (byte)((value >> 0) & 0xff); 80 | return pointer; 81 | } 82 | 83 | public static int writeBytes(byte[] dest, int pointer, int value) { 84 | assert(dest.length >= pointer + Type.getSize(Type.INTEGER)); 85 | dest[pointer++] = (byte)((value >> 24) & 0xff); 86 | dest[pointer++] = (byte)((value >> 16) & 0xff); 87 | dest[pointer++] = (byte)((value >> 8) & 0xff); 88 | dest[pointer++] = (byte)((value >> 0) & 0xff); 89 | return pointer; 90 | } 91 | 92 | public static int writeBytes(byte[] dest, int pointer, long value) { 93 | assert(dest.length > pointer + Type.getSize(Type.LONG)); 94 | dest[pointer++] = (byte)((value >> 56) & 0xff); 95 | dest[pointer++] = (byte)((value >> 48) & 0xff); 96 | dest[pointer++] = (byte)((value >> 40) & 0xff); 97 | dest[pointer++] = (byte)((value >> 32) & 0xff); 98 | dest[pointer++] = (byte)((value >> 24) & 0xff); 99 | dest[pointer++] = (byte)((value >> 16) & 0xff); 100 | dest[pointer++] = (byte)((value >> 8) & 0xff); 101 | dest[pointer++] = (byte)((value >> 0) & 0xff); 102 | return pointer; 103 | } 104 | 105 | public static int writeBytes(byte[] dest, int pointer, float value) { 106 | assert(dest.length > pointer + Type.getSize(Type.FLOAT)); 107 | int data = Float.floatToIntBits(value); 108 | return writeBytes(dest, pointer, data); 109 | } 110 | 111 | public static int writeBytes(byte[] dest, int pointer, double value) { 112 | assert(dest.length > pointer + Type.getSize(Type.DOUBLE)); 113 | long data = Double.doubleToLongBits(value); 114 | return writeBytes(dest, pointer, data); 115 | } 116 | 117 | public static int writeBytes(byte[] dest, int pointer, boolean value) { 118 | assert(dest.length > pointer + Type.getSize(Type.BOOLEAN)); 119 | dest[pointer++] = (byte)(value ? 1 : 0); 120 | return pointer; 121 | } 122 | 123 | public static int writeBytes(byte[] dest, int pointer, String string) { 124 | pointer = writeBytes(dest, pointer, (short) string.length()); 125 | return writeBytes(dest, pointer, string.getBytes()); 126 | } 127 | 128 | public static byte readByte(byte[] src, int pointer) { 129 | return src[pointer]; 130 | } 131 | 132 | public static void readBytes(byte[] src, int pointer, byte[] dest) { 133 | for (int i = 0; i < dest.length; i++) 134 | dest[i] = src[pointer + i]; 135 | } 136 | 137 | public static void readShorts(byte[] src, int pointer, short[] dest) { 138 | for (int i = 0; i < dest.length; i++) { 139 | dest[i] = readShort(src, pointer); 140 | pointer += Type.getSize(Type.SHORT); 141 | } 142 | } 143 | 144 | public static void readChars(byte[] src, int pointer, char[] dest) { 145 | for (int i = 0; i < dest.length; i++) { 146 | dest[i] = readChar(src, pointer); 147 | pointer += Type.getSize(Type.CHAR); 148 | } 149 | } 150 | 151 | public static void readInts(byte[] src, int pointer, int[] dest) { 152 | for (int i = 0; i < dest.length; i++) { 153 | dest[i] = readInt(src, pointer); 154 | pointer += Type.getSize(Type.INTEGER); 155 | } 156 | } 157 | 158 | public static void readLongs(byte[] src, int pointer, long[] dest) { 159 | for (int i = 0; i < dest.length; i++) { 160 | dest[i] = readLong(src, pointer); 161 | pointer += Type.getSize(Type.LONG); 162 | } 163 | } 164 | 165 | public static void readFloats(byte[] src, int pointer, float[] dest) { 166 | for (int i = 0; i < dest.length; i++) { 167 | dest[i] = readFloat(src, pointer); 168 | pointer += Type.getSize(Type.FLOAT); 169 | } 170 | } 171 | 172 | public static void readDoubles(byte[] src, int pointer, double[] dest) { 173 | for (int i = 0; i < dest.length; i++) { 174 | dest[i] = readDouble(src, pointer); 175 | pointer += Type.getSize(Type.DOUBLE); 176 | } 177 | } 178 | 179 | public static void readBooleans(byte[] src, int pointer, boolean[] dest) { 180 | for (int i = 0; i < dest.length; i++) { 181 | dest[i] = readBoolean(src, pointer); 182 | pointer += Type.getSize(Type.BOOLEAN); 183 | } 184 | } 185 | public static short readShort(byte[] src, int pointer) { 186 | return ByteBuffer.wrap(src, pointer, 2).getShort(); 187 | } 188 | 189 | public static char readChar(byte[] src, int pointer) { 190 | return ByteBuffer.wrap(src, pointer, 2).getChar(); 191 | } 192 | 193 | public static int readInt(byte[] src, int pointer) { 194 | return ByteBuffer.wrap(src, pointer, 4).getInt(); 195 | } 196 | 197 | public static long readLong(byte[] src, int pointer) { 198 | return ByteBuffer.wrap(src, pointer, 8).getLong(); 199 | } 200 | 201 | public static float readFloat(byte[] src, int pointer) { 202 | return Float.intBitsToFloat(readInt(src, pointer)); 203 | } 204 | 205 | public static double readDouble(byte[] src, int pointer) { 206 | return Double.longBitsToDouble(readLong(src, pointer)); 207 | } 208 | 209 | public static boolean readBoolean(byte[] src, int pointer) { 210 | assert(src[pointer] == 0 || src[pointer] == 1); 211 | return src[pointer] != 0; 212 | } 213 | 214 | public static String readString(byte[] src, int pointer, int length) { 215 | return new String(src, pointer, length); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /RainCloud-Serialization/src/com/thecherno/raincloud/serialization/Type.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.raincloud.serialization; 2 | 3 | public class Type { 4 | 5 | public static final byte UNKNOWN = 0; 6 | public static final byte BYTE = 1; 7 | public static final byte SHORT = 2; 8 | public static final byte CHAR = 3; 9 | public static final byte INTEGER = 4; 10 | public static final byte LONG = 5; 11 | public static final byte FLOAT = 6; 12 | public static final byte DOUBLE = 7; 13 | public static final byte BOOLEAN = 8; 14 | 15 | public static int getSize(byte type) { 16 | switch (type) { 17 | case BYTE: return 1; 18 | case SHORT: return 2; 19 | case CHAR: return 2; 20 | case INTEGER: return 4; 21 | case LONG: return 8; 22 | case FLOAT: return 4; 23 | case DOUBLE: return 8; 24 | case BOOLEAN: return 1; 25 | } 26 | assert(false); 27 | return 0; 28 | } 29 | 30 | public static String typeToString(byte type) { 31 | switch (type) { 32 | case UNKNOWN: return "Unknown"; 33 | case BYTE: return "Byte"; 34 | case SHORT: return "Short"; 35 | case CHAR: return "Char"; 36 | case INTEGER: return "Integer"; 37 | case LONG: return "Long"; 38 | case FLOAT: return "Float"; 39 | case DOUBLE: return "Double"; 40 | case BOOLEAN: return "Boolean"; 41 | } 42 | return "Invalid"; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /RainServer/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RainServer/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | -------------------------------------------------------------------------------- /RainServer/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | RainServer 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /RainServer/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /RainServer/src/com/thecherno/rainserver/RainServer.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rainserver; 2 | 3 | import java.net.InetAddress; 4 | import java.net.UnknownHostException; 5 | 6 | public class RainServer { 7 | 8 | public static void main(String[] args) { 9 | Server server = new Server(8192); 10 | server.start(); 11 | 12 | InetAddress address = null; 13 | try { 14 | address = InetAddress.getByName("192.168.1.10"); 15 | } catch (UnknownHostException e) { 16 | e.printStackTrace(); 17 | } 18 | int port = 8192; 19 | server.send(new byte[] { 0, 1, 2 }, address, port); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /RainServer/src/com/thecherno/rainserver/Server.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rainserver; 2 | 3 | import java.io.IOException; 4 | import java.net.DatagramPacket; 5 | import java.net.DatagramSocket; 6 | import java.net.InetAddress; 7 | import java.net.SocketException; 8 | import java.net.SocketTimeoutException; 9 | import java.util.Arrays; 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | import com.thecherno.raincloud.serialization.RCDatabase; 14 | import com.thecherno.raincloud.serialization.RCField; 15 | import com.thecherno.raincloud.serialization.RCObject; 16 | import com.thecherno.raincloud.serialization.Type; 17 | 18 | public class Server { 19 | 20 | private int port; 21 | private Thread listenThread; 22 | private boolean listening = false; 23 | private DatagramSocket socket; 24 | 25 | private final int MAX_PACKET_SIZE = 1024; 26 | private byte[] receivedDataBuffer = new byte[MAX_PACKET_SIZE * 10]; 27 | 28 | private Set clients = new HashSet(); 29 | 30 | public Server(int port) { 31 | this.port = port; 32 | } 33 | 34 | public void start() { 35 | try { 36 | socket = new DatagramSocket(port); 37 | } catch (SocketException e) { 38 | e.printStackTrace(); 39 | return; 40 | } 41 | 42 | System.out.println("Started server on port 8192..."); 43 | 44 | listening = true; 45 | 46 | listenThread = new Thread(() -> listen(), "RainCloudServer-ListenThread"); 47 | listenThread.start(); 48 | System.out.println("Server is listening..."); 49 | } 50 | 51 | private void listen() { 52 | while (listening) { 53 | DatagramPacket packet = new DatagramPacket(receivedDataBuffer, MAX_PACKET_SIZE); 54 | try { 55 | socket.receive(packet); 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | process(packet); 60 | } 61 | } 62 | 63 | private void process(DatagramPacket packet) { 64 | byte[] data = packet.getData(); 65 | InetAddress address = packet.getAddress(); 66 | int port = packet.getPort(); 67 | dump(packet); 68 | 69 | if (new String(data, 0, 4).equals("RCDB")) { 70 | RCDatabase database = RCDatabase.Deserialize(data); 71 | process(database); 72 | } else if (data[0] == 0x40 && data[1] == 0x40) { 73 | switch (data[2]) { 74 | case 0x01: 75 | clients.add(new ServerClient(packet.getAddress(), packet.getPort())); 76 | break; 77 | case 2: 78 | // Ping packet 79 | break; 80 | case 3: 81 | // Login attempt packet 82 | break; 83 | } 84 | } 85 | } 86 | 87 | private void process(RCDatabase database) { 88 | System.out.println("Received database!"); 89 | dump(database); 90 | } 91 | 92 | public void send(byte[] data, InetAddress address, int port) { 93 | assert(socket.isConnected()); 94 | DatagramPacket packet = new DatagramPacket(data, data.length, address, port); 95 | try { 96 | socket.send(packet); 97 | } catch (IOException e) { 98 | e.printStackTrace(); 99 | } 100 | 101 | } 102 | 103 | private void dump(DatagramPacket packet) { 104 | byte[] data = packet.getData(); 105 | InetAddress address = packet.getAddress(); 106 | int port = packet.getPort(); 107 | 108 | System.out.println("----------------------------------------"); 109 | System.out.println("PACKET:"); 110 | System.out.println("\t" + address.getHostAddress() + ":" + port); 111 | System.out.println(); 112 | System.out.println("\tContents:"); 113 | System.out.print("\t\t"); 114 | 115 | for (int i = 0; i < packet.getLength(); i++) { 116 | System.out.printf("%x ", data[i]); 117 | if ((i + 1) % 16 == 0) 118 | System.out.print("\n\t\t"); 119 | } 120 | 121 | System.out.println(); 122 | System.out.println("----------------------------------------"); 123 | } 124 | 125 | private void dump(RCDatabase database) { 126 | System.out.println("----------------------------------------"); 127 | System.out.println(" RCDatabase "); 128 | System.out.println("----------------------------------------"); 129 | System.out.println("Name: " + database.getName()); 130 | System.out.println("Size: " + database.getSize()); 131 | System.out.println("Object Count: " + database.objects.size()); 132 | System.out.println(); 133 | for (RCObject object : database.objects) { 134 | System.out.println("\tObject:"); 135 | System.out.println("\tName: " + object.getName()); 136 | System.out.println("\tSize: " + object.getSize()); 137 | System.out.println("\tField Count: " + object.fields.size()); 138 | for (RCField field : object.fields) { 139 | System.out.println("\t\tField:"); 140 | System.out.println("\t\tName: " + field.getName()); 141 | System.out.println("\t\tSize: " + field.getSize()); 142 | String data = ""; 143 | switch (field.type) { 144 | case Type.BYTE: 145 | data += field.getByte(); 146 | break; 147 | case Type.SHORT: 148 | data += field.getShort(); 149 | break; 150 | case Type.CHAR: 151 | data += field.getChar(); 152 | break; 153 | case Type.INTEGER: 154 | data += field.getInt(); 155 | break; 156 | case Type.LONG: 157 | data += field.getLong(); 158 | break; 159 | case Type.FLOAT: 160 | data += field.getFloat(); 161 | break; 162 | case Type.DOUBLE: 163 | data += field.getDouble(); 164 | break; 165 | case Type.BOOLEAN: 166 | data += field.getBoolean(); 167 | break; 168 | } 169 | System.out.println("\t\tData: " + data); 170 | System.out.println(); 171 | } 172 | System.out.println(); 173 | } 174 | System.out.println("----------------------------------------"); 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /RainServer/src/com/thecherno/rainserver/ServerClient.java: -------------------------------------------------------------------------------- 1 | package com.thecherno.rainserver; 2 | 3 | import java.net.InetAddress; 4 | 5 | public class ServerClient { 6 | 7 | public int userID; 8 | public InetAddress address; 9 | public int port; 10 | public boolean status = false; // is connected 11 | 12 | private static int userIDCounter = 1; 13 | 14 | public ServerClient(InetAddress address, int port) { 15 | userID = userIDCounter++; 16 | this.address = address; 17 | this.port = port; 18 | status = true; 19 | } 20 | 21 | public int hashCode() { 22 | return userID; 23 | } 24 | 25 | 26 | } 27 | --------------------------------------------------------------------------------