├── 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 |
--------------------------------------------------------------------------------