Created
June 18, 2014 14:04
-
-
Save jimgong92/3a17eb7b04b00444ca02 to your computer and use it in GitHub Desktop.
Aerial View Game - In Development
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.graphics; | |
public class AnimatedSprite extends Sprite { | |
private int animate_step = 0; | |
private int animate_speed = 32; | |
private int frame_length = animate_speed >> 2; | |
private boolean animate = false; | |
//direction = column (N - 0, E - 1, S - 2, W - 3) | |
//animation step = row | |
public AnimatedSprite(int size, int x, int y, SpriteSheet sheet) { | |
super(size, x, y, sheet); | |
} | |
public void update(int direction) { | |
if (animate_step++ >= 2100) animate_step = 0; | |
//Update direction | |
x = direction * SIZE; | |
//If supposed to be animating, | |
if (animate) y = ((animate_step % animate_speed)/ frame_length) * SIZE; | |
else y = 0; | |
load(); | |
} | |
public void animateControl(boolean moving) { | |
animate = moving; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.mob; | |
import java.util.List; | |
import com.jimgong.rain.entity.valuebar.Hitpoints; | |
import com.jimgong.rain.graphics.AnimatedSprite; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.SpriteSheet; | |
public class Chaser extends Mob { | |
private int time = 0; | |
private AnimatedSprite animSprite; | |
private int xa, ya; | |
//chases within 10 tile radius | |
private int chaseRadius = 10 << 4; | |
public Chaser(int x, int y) { | |
this.x = x << 4; | |
this.y = y << 4; | |
animSprite = new AnimatedSprite(16, 0, 0, SpriteSheet.charmander); | |
sprite = animSprite; | |
hp = new Hitpoints(16, x, y); | |
} | |
//chase player | |
private void chase() { | |
xa = 0; ya = 0; | |
List<Player> players = level.getPlayersInRadius(this, chaseRadius); | |
if (players.size() > 0) { | |
Player player = players.get(0); | |
if (x < player.getX()) xa++; | |
if (x > player.getX()) xa--; | |
if (y < player.getY()) ya++; | |
if (y > player.getY()) ya--; | |
} | |
} | |
private void attack() { | |
List<Player> attackRadius = level.getPlayersInRadius(this, 8); | |
for (int i = 0; i < attackRadius.size(); i++) { | |
attackRadius.get(i).getHitpoints().setPoints(1); | |
} | |
} | |
public void update() { | |
if (time++ > 210000) time = 0; | |
chase(); | |
if (xa != 0 || ya != 0) moving = true; | |
else moving = false; | |
if (moving) { | |
if (ya < 0) dir = NORTH; | |
if (ya > 0) dir = SOUTH; | |
if (xa < 0) dir = WEST; | |
if (xa > 0) dir = EAST; | |
move(xa, ya); | |
} | |
animSprite.update(dir); | |
animSprite.animateControl(moving); | |
if (!hp.isDead()) hp.update(x + Hitpoints.X_OFFSET, y + Hitpoints.Y_OFFSET); | |
else remove(); | |
if (time >= 10) { | |
attack(); | |
time = 0; | |
} | |
} | |
public void render(Screen screen) { | |
//Center sprite | |
int xx = x - sprite.SIZE / 2; | |
int yy = y - sprite.SIZE / 2; | |
screen.renderMob(xx, yy, this); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.mob; | |
import com.jimgong.rain.entity.valuebar.Hitpoints; | |
import com.jimgong.rain.graphics.AnimatedSprite; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.SpriteSheet; | |
public class Dummy extends Mob { | |
private int animate_step = 0; | |
private int animate_speed = 30; | |
private AnimatedSprite sprite; | |
//x & y are starting coordinates | |
public Dummy(int x, int y) { | |
//Shift left by 4 (x16) to adjust for tile size | |
this.x = x << 4; | |
this.y = y << 4; | |
sprite = new AnimatedSprite(16, 0, 0, SpriteSheet.charmander); | |
hp = new Hitpoints(16, x, y); | |
} | |
public void update() { | |
//Note direction sprite is supposed to move | |
int xa = 0, ya = 0; | |
//Update animation, prevent crashing | |
if (animate_step++ >= 2100) animate_step = 0; | |
//at every animate_speed interval, randomly generate a new direction and if moving | |
if (animate_step % animate_speed == 0) { | |
dir = random.nextInt(4); | |
//1 in 3 chance to not move | |
if (random.nextInt(3) == 2) moving = false; | |
else moving = true; | |
} | |
if (moving) { | |
if (dir == NORTH) ya--; | |
if (dir == SOUTH) ya++; | |
if (dir == WEST) xa--; | |
if (dir == EAST) xa++; | |
move(xa, ya); | |
} | |
sprite.update(dir); | |
sprite.animateControl(moving); | |
if (!hp.isDead()) hp.update(x + Hitpoints.X_OFFSET, y + Hitpoints.Y_OFFSET); | |
else remove(); | |
} | |
public void render(Screen screen) { | |
//Center sprite | |
int xx = x - sprite.SIZE / 2; | |
int yy = y - sprite.SIZE / 2; | |
screen.renderMob(xx, yy, sprite, 0); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity; | |
import java.util.Random; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.level.Level; | |
public abstract class Entity { | |
protected int x, y; //Location of particular entity | |
protected boolean removed = false; | |
protected Level level; | |
protected final Random random = new Random(); | |
public void update() { | |
} | |
public void render(Screen screen) { | |
} | |
public void remove() { | |
//Removes entity from level | |
removed = true; | |
} | |
public int getX() { | |
return x; | |
} | |
public int getY() { | |
return y; | |
} | |
public boolean isRemoved() { | |
return removed; | |
} | |
public void init(Level level) { | |
this.level = level; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level.tile; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
public class FlowerTile extends Tile { | |
public FlowerTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain; | |
import java.awt.Canvas; | |
import java.awt.Color; | |
import java.awt.Dimension; | |
import java.awt.Font; | |
import java.awt.Graphics; | |
import java.awt.image.BufferStrategy; | |
import java.awt.image.BufferedImage; | |
import java.awt.image.DataBufferInt; | |
import javax.swing.JFrame; | |
import com.jimgong.rain.entity.mob.Player; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
import com.jimgong.rain.input.Keyboard; | |
import com.jimgong.rain.input.Mouse; | |
import com.jimgong.rain.level.Level; | |
import com.jimgong.rain.level.TileCoordinate; | |
// | |
public class Game extends Canvas implements Runnable { | |
private static final long serialVersionUID = 1L; | |
//Screen Resolution 16 x 9 ratio | |
private static int width = 300; | |
private static int height = width / 16 * 9; //168 | |
private static int scale = 3; | |
public static String title = "Rain"; | |
private Thread gameThread; | |
private JFrame frame; | |
private Keyboard key; | |
private Level level; | |
private Player player; | |
private boolean running = false; | |
private Screen screen; | |
private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); | |
private int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData(); | |
public Game() { | |
Dimension size = new Dimension(width * scale, height * scale); | |
setPreferredSize(size); | |
screen = new Screen(width, height); | |
frame = new JFrame(); | |
key = new Keyboard(); | |
//level = new RandomLevel(64, 64); | |
level = Level.spawn; | |
TileCoordinate playerSpawn = new TileCoordinate(19,30); | |
player = new Player(playerSpawn.x(), playerSpawn.y(), key); | |
level.add(player); | |
addKeyListener(key); | |
Mouse mouse = new Mouse(); | |
addMouseListener(mouse); | |
addMouseMotionListener(mouse); | |
} | |
public static int getWindowWidth() { | |
return width * scale; | |
} | |
public static int getWindowHeight() { | |
return height * scale; | |
} | |
public synchronized void start() { | |
running = true; | |
gameThread = new Thread(this, "Display"); | |
gameThread.start(); | |
} | |
//Method to stop the applet | |
public synchronized void stop() { | |
running = false; | |
try { | |
gameThread.join(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
} | |
//Run method | |
public void run() { | |
//Store time | |
long lastTime = System.nanoTime(); | |
long timer = System.currentTimeMillis(); | |
final double ns = 1000000000.0 / 60.0; | |
double delta = 0; //Accumulator | |
int frames = 0; | |
int updates = 0; | |
requestFocus(); | |
while (running) { | |
long now = System.nanoTime(); | |
delta += (now - lastTime) / ns; | |
lastTime = now; //Update lastTime | |
while (delta >= 1) { | |
update(); //Restrict to 60fps | |
updates++; | |
delta--; | |
} | |
render(); | |
frames++; | |
if (System.currentTimeMillis() - timer > 1000) { | |
timer += 1000; | |
frame.setTitle(title + " | " + updates + " ups " + frames + " fps"); //display fps in window title | |
updates = 0; frames = 0; | |
} | |
} | |
} | |
public void update() { | |
key.update(); | |
level.update(); | |
} | |
public void render() { | |
BufferStrategy bs = getBufferStrategy(); | |
if (bs == null) { //If no buffer strategy on canvas | |
createBufferStrategy(3); //3 is number of buffers | |
return; | |
} | |
screen.clear(); | |
//Center player | |
int xScroll = player.getX() - screen.width / 2; | |
int yScroll = player.getY() - screen.height / 2; | |
level.render(xScroll, yScroll, screen); | |
for (int i = 0; i < pixels.length; i++) { | |
pixels[i] = screen.pixels[i]; | |
} | |
Graphics g = bs.getDrawGraphics(); | |
g.drawImage(image, 0, 0, getWidth(), getHeight(), null); | |
g.setColor(Color.WHITE); | |
g.setFont(new Font("Verdana", 0, 20)); | |
g.drawString("Button: " + Mouse.getButton(), 20, 20); | |
g.drawString("X: " + player.getX() + ", Y: " + player.getY(), 350, 300); | |
g.dispose(); | |
bs.show(); | |
} | |
/** Main Method */ | |
public static void main(String[] args) { | |
Game game = new Game(); | |
game.frame.setResizable(false); | |
game.frame.setTitle(Game.title); | |
game.frame.add(game); | |
game.frame.pack(); | |
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
game.frame.setLocationRelativeTo(null); | |
game.frame.setVisible(true); | |
game.start(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Grass tile has no collision, so no need to override solid method | |
package com.jimgong.rain.level.tile; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
public class GrassTile extends Tile{ | |
public GrassTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.valuebar; | |
public class Hitpoints extends ValueBar { | |
public static final int HITPOINTS_COLOR = 0xFFFF0000; | |
public static final int EMPTY_COLOR = 0xFFFF8080; | |
public static final int X_OFFSET = 9; | |
public static final int Y_OFFSET = -8; | |
//x & y visibility coordinates relative to the Mob to whom it belongs | |
//HP bar visible to the right of the player | |
public Hitpoints (int hitpoints, int x, int y) { | |
//2 pixels wide, offset by 2 pixels from player | |
super(hitpoints, x + X_OFFSET, y + Y_OFFSET, HITPOINTS_COLOR, EMPTY_COLOR); | |
point_color = HITPOINTS_COLOR; | |
empty_color = EMPTY_COLOR; | |
} | |
public boolean isDead() { | |
if (points <= 0) return true; | |
else return false; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.input; | |
import java.awt.event.KeyEvent; | |
import java.awt.event.KeyListener; | |
public class Keyboard implements KeyListener { | |
//Array for keystroke states | |
private boolean[] keys = new boolean[120]; | |
public boolean up, down, left, right; | |
public boolean space; | |
public boolean shift; | |
public void update() { | |
up = keys[KeyEvent.VK_UP] || keys[KeyEvent.VK_W]; | |
down = keys[KeyEvent.VK_DOWN] || keys[KeyEvent.VK_S]; | |
left = keys[KeyEvent.VK_LEFT] || keys[KeyEvent.VK_A]; | |
right = keys[KeyEvent.VK_RIGHT] || keys[KeyEvent.VK_D]; | |
space = keys[KeyEvent.VK_SPACE]; | |
shift = keys[KeyEvent.VK_SHIFT]; | |
for (int i = 0; i < keys.length; i++) { | |
if (keys[i]) { | |
System.out.println("KEY: " + i); | |
} | |
} | |
} | |
@Override | |
public void keyPressed(KeyEvent e) { | |
keys[e.getKeyCode()] = true; | |
} | |
@Override | |
public void keyReleased(KeyEvent e) { | |
keys[e.getKeyCode()] = false; | |
} | |
@Override | |
public void keyTyped(KeyEvent e) { | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Random; | |
import com.jimgong.rain.entity.Entity; | |
import com.jimgong.rain.entity.mob.Chaser; | |
import com.jimgong.rain.entity.mob.Mob; | |
import com.jimgong.rain.entity.mob.Player; | |
import com.jimgong.rain.entity.particle.Particle; | |
import com.jimgong.rain.entity.projectile.Projectile; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.level.tile.Tile; | |
public class Level { | |
protected int width, height; | |
protected int[] tilesInt; //For rand levels | |
protected int[] tiles; | |
protected final Random random = new Random(); | |
protected int time = 0; | |
//Array of all entities to have on the level | |
private List<Entity> entities = new ArrayList<Entity>(); | |
private List<Projectile> projectiles = new ArrayList<Projectile>(); | |
private List<Particle> particles = new ArrayList<Particle>(); | |
private List<Mob> nonPlayerMobs = new ArrayList<Mob>(); | |
private List<Player> players = new ArrayList<Player>(); | |
public static Level spawn = new SpawnLevel("/levels/spawn.png"); | |
//Random level | |
public Level(int width, int height) { | |
this.width = width; | |
this.height = height; | |
tilesInt = new int[width * height]; | |
generateLevel(); | |
} | |
//Custom level | |
public Level(String path) { | |
loadLevel(path); | |
generateLevel(); | |
} | |
protected void generateLevel() { | |
} | |
protected void loadLevel(String path) { | |
} | |
public void update() { | |
//time based events | |
if (time++ > 2100) time = 0; | |
//spawn new chaser mob every half second | |
if (time % 30 == 0) { | |
if (nonPlayerMobs.size() < 20) add(new Chaser(random.nextInt(3) + 15, random.nextInt(10) + 10)); | |
} | |
for (int i = 0; i < entities.size(); i++) { | |
entities.get(i).update(); | |
} | |
for (int i = 0; i < projectiles.size(); i++) { | |
projectiles.get(i).update(); | |
} | |
for (int i = 0; i < particles.size(); i++) { | |
particles.get(i).update(); | |
} | |
for (int i = 0; i < nonPlayerMobs.size(); i++) { | |
nonPlayerMobs.get(i).update(); | |
} | |
for (int i = 0; i < players.size(); i++) { | |
players.get(i).update(); | |
} | |
remove(); | |
} | |
private void remove() { | |
for (int i = 0; i < entities.size(); i++) { | |
if (entities.get(i).isRemoved()) entities.remove(i); | |
} | |
for (int i = 0; i < projectiles.size(); i++) { | |
if (projectiles.get(i).isRemoved()) projectiles.remove(i); | |
} | |
for (int i = 0; i < particles.size(); i++) { | |
if (particles.get(i).isRemoved()) particles.remove(i); | |
} | |
for (int i = 0; i < nonPlayerMobs.size(); i++) { | |
if (nonPlayerMobs.get(i).isRemoved()) nonPlayerMobs.remove(i); | |
} | |
for (int i = 0; i < players.size(); i++) { | |
if (players.get(i).isRemoved()) players.remove(i); | |
} | |
} | |
public List<Projectile> getProjectiles() { | |
return projectiles; | |
} | |
//The offsets adjust for the unrendered (pink) area of the sprite | |
public boolean tileCollision(int x, int y, int size, int xOffset, int yOffset) { | |
boolean solid = false; | |
//Corner precision | |
for (int corner = 0; corner < 4; corner++) { | |
int xt = (x - corner % 2 * size + xOffset) >> 4; | |
int yt = (y - corner / 2 * size + yOffset) >> 4; | |
if (getTile((int) xt,(int) yt).solid()) solid = true; | |
} | |
return solid; | |
} | |
//Scroll indicates coordinate of player | |
public void render(int xScroll, int yScroll, Screen screen) { | |
screen.setOffset(xScroll, yScroll); | |
//Set cornerpins | |
int x0 = xScroll >> 4; //same as xScroll / 16, shifting bit 4 places to right | |
//Aggregates pixels into tiles, 16 is size of a tile to render an extra tile for offsetting | |
int x1 = (xScroll + screen.width + 16) >> 4; | |
int y0 = yScroll >> 4; | |
int y1 = (yScroll + screen.height + 16) >> 4; | |
for (int y = y0; y < y1; y++) { | |
for (int x = x0; x < x1; x++) { | |
getTile(x, y).render(x, y, screen); | |
} | |
} | |
//Render entities | |
for (int i = 0; i < entities.size(); i++) { | |
entities.get(i).render(screen); | |
} | |
//Render projectiles | |
for (int i = 0; i < projectiles.size(); i++) { | |
projectiles.get(i).render(screen); | |
} | |
//Render particles | |
for (int i = 0; i < particles.size(); i++) { | |
particles.get(i).render(screen); | |
} | |
//Render non-player mobs | |
for (int i = 0; i < nonPlayerMobs.size(); i++) { | |
nonPlayerMobs.get(i).render(screen); | |
} | |
//Render players | |
for (int i = 0; i < players.size(); i++) { | |
players.get(i).render(screen); | |
} | |
} | |
public void add(Entity e) { | |
e.init(this); | |
if (e instanceof Particle) { | |
particles.add((Particle)e); | |
} | |
else if (e instanceof Projectile) { | |
projectiles.add((Projectile)e); | |
} | |
else if (e instanceof Player) { | |
players.add((Player)e); | |
} | |
else if (e instanceof Mob) { | |
nonPlayerMobs.add((Mob)e); | |
} | |
else entities.add(e); | |
} | |
public List<Player> getPlayers() { | |
return players; | |
} | |
public Player getPlayerAt(int index) { | |
return players.get(index); | |
} | |
public Player getClientPlayer() { | |
return players.get(0); | |
} | |
public List<Mob> getMobs() { | |
return nonPlayerMobs; | |
} | |
//Returns entities within a certain radius | |
public List<Entity> getEntitiesInRadius (Entity e, int radius) { | |
List<Entity> result = new ArrayList<Entity>(); | |
//x and y coordinates of e | |
int ex = e.getX(), ey = e.getY(); | |
for (int i = 0; i < entities.size(); i++) { | |
Entity entity = entities.get(i); | |
int x = entity.getX(); | |
int y = entity.getY(); | |
double distance = Math.sqrt((x-ex)*(x-ex) + (y-ey)*(y-ey)); | |
//if entity is within radius, add | |
if (radius >= distance) { | |
result.add(entity); | |
} | |
} | |
return result; | |
} | |
//Returns mobs within a certain radius | |
public List<Mob> getMobsInRadius (Entity e, int radius) { | |
List<Mob> result = new ArrayList<Mob>(); | |
//x and y coordinates of e | |
int ex = e.getX(), ey = e.getY(); | |
for (int i = 0; i < nonPlayerMobs.size(); i++) { | |
Mob mob = nonPlayerMobs.get(i); | |
int x = mob.getX(); | |
int y = mob.getY(); | |
double distance = Math.sqrt((x-ex)*(x-ex) + (y-ey)*(y-ey)); | |
//if entity is within radius, add | |
if (radius >= distance) { | |
result.add(mob); | |
} | |
} | |
return result; | |
} | |
//Returns mobs within a certain radius for a given coordinate | |
public List<Mob> getMobsInRadius (int ex, int ey, int radius) { | |
List<Mob> result = new ArrayList<Mob>(); | |
for (int i = 0; i < nonPlayerMobs.size(); i++) { | |
Mob mob = nonPlayerMobs.get(i); | |
int x = mob.getX(); | |
int y = mob.getY(); | |
double distance = Math.sqrt((x-ex)*(x-ex) + (y-ey)*(y-ey)); | |
//if entity is within radius, add | |
if (radius >= distance) { | |
result.add(mob); | |
} | |
} | |
return result; | |
} | |
//Returns player entities within a certain radius | |
public List<Player> getPlayersInRadius (Entity e, int radius) { | |
List<Player> result = new ArrayList<Player>(); | |
//x and y coordinates of e | |
int ex = e.getX(), ey = e.getY(); | |
for (int i = 0; i < players.size(); i++) { | |
Player player = players.get(i); | |
int x = player.getX(); | |
int y = player.getY(); | |
double distance = Math.sqrt((x-ex)*(x-ex) + (y-ey)*(y-ey)); | |
//if entity is within radius, add | |
if (radius >= distance) { | |
result.add(player); | |
} | |
} | |
return result; | |
} | |
public Tile getTile(int x, int y) { | |
if (x < 0 || y < 0 || x >= width || y >= height) return Tile.voidTile; | |
if (tiles[x + y * width] == Tile.col_spawn_floor) return Tile.spawn_floor; | |
if (tiles[x + y * width] == Tile.col_spawn_flower) return Tile.spawn_flower; | |
if (tiles[x + y * width] == Tile.col_spawn_grass) return Tile.spawn_grass; | |
if (tiles[x + y * width] == Tile.col_spawn_rock) return Tile.spawn_rock; | |
if (tiles[x + y * width] == Tile.col_spawn_wall) return Tile.spawn_wall; | |
if (tiles[x + y * width] == Tile.col_spawn_water) return Tile.spawn_water; | |
return Tile.voidTile; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.valuebar; | |
public class Mana extends ValueBar{ | |
public static final int MANA_COLOR = 0xFF0000FF; | |
public static final int EMPTY_COLOR = 0xFF8080FF; | |
public static final int X_OFFSET = 11; | |
public static final int Y_OFFSET = -8; | |
//x & y visibility coordinates relative to the Mob to whom it belongs | |
//HP bar visible to the right of the player | |
public Mana (int manaPoints, int x, int y) { | |
//2 pixels wide, offset by 2 pixels from player | |
super(manaPoints, x + X_OFFSET, y + Y_OFFSET, MANA_COLOR, EMPTY_COLOR); | |
point_color = MANA_COLOR; | |
empty_color = EMPTY_COLOR; | |
} | |
public boolean isEmpty() { | |
if (points <= 0) return true; | |
else return false; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.mob; | |
import com.jimgong.rain.entity.Entity; | |
import com.jimgong.rain.entity.particle.Particle; | |
import com.jimgong.rain.entity.projectile.Projectile; | |
import com.jimgong.rain.entity.projectile.WizardProjectile; | |
import com.jimgong.rain.entity.spawner.ParticleSpawner; | |
import com.jimgong.rain.entity.valuebar.Hitpoints; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
public abstract class Mob extends Entity { | |
protected static final int NORTH = 0; | |
protected static final int EAST = 1; | |
protected static final int SOUTH = 2; | |
protected static final int WEST = 3; | |
protected Sprite sprite; | |
protected int dir = 0; //Entity's direction 0-N, 1-E, 2-S, 3-W | |
protected boolean moving = false; | |
protected Hitpoints hp; | |
//xa,ya denote where the player is moving on the x and y axis | |
public void move(int xa, int ya) { | |
//if trying to move on two axis | |
if (xa != 0 && ya != 0) { | |
//separate movement so collision on one axis is not a mutual relationship | |
move(xa, 0); | |
move(0,ya); | |
return; | |
} | |
if (xa > 0) dir = EAST; //Going right | |
if (xa < 0) dir = WEST; //Going left | |
if (ya > 0) dir = SOUTH; //Going down | |
if (ya < 0) dir = NORTH; //Going up | |
if (!collision(xa, ya)) { | |
//xa = -1, 0, 1 passed as arguments (moving left, staying still, moving right) | |
x += xa; | |
y += ya; | |
} | |
} | |
public void update() { | |
} | |
protected void shoot(int x, int y, double dir) { | |
//dir *= 180 / Math.PI; | |
Projectile p = new WizardProjectile(x, y, dir); | |
level.add(p); | |
} | |
private boolean collision(int xa, int ya) { | |
boolean solid = false; | |
//Corner precision | |
for (int corner = 0; corner < 4; corner++) { | |
int xt = ((x + xa) + corner % 2 * 14 - 8 ) >> 4; | |
int yt = ((y + ya) + corner % 2 / 10 + (ya * 4 + 3)) >> 4; | |
if (level.getTile(xt, yt).solid()) solid = true; | |
} | |
return solid; | |
} | |
public abstract void render(Screen screen); | |
public Sprite getSprite() { | |
return sprite; | |
} | |
public Hitpoints getHitpoints() { | |
return hp; | |
} | |
public boolean isRemoved() { | |
if (removed) level.add(new ParticleSpawner(x, y, 60, 50, level)); | |
return removed; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.input; | |
import java.awt.event.MouseEvent; | |
import java.awt.event.MouseListener; | |
import java.awt.event.MouseMotionListener; | |
public class Mouse implements MouseListener, MouseMotionListener { | |
//static because we can only have one mouse | |
private static int mouseX = -1, mouseY = -1; | |
private static int mouseB = -1; | |
public static int getX() { | |
return mouseX; | |
} | |
public static int getY() { | |
return mouseY; | |
} | |
public static int getButton() { | |
return mouseB; | |
} | |
@Override | |
public void mouseDragged(MouseEvent e) { | |
mouseX = e.getX(); | |
mouseY = e.getY(); | |
} | |
@Override | |
public void mouseMoved(MouseEvent e) { | |
mouseX = e.getX(); | |
mouseY = e.getY(); | |
} | |
@Override | |
public void mouseClicked(MouseEvent e) { | |
} | |
@Override | |
public void mouseEntered(MouseEvent e) { | |
} | |
@Override | |
public void mouseExited(MouseEvent e) { | |
} | |
@Override | |
public void mousePressed(MouseEvent e) { | |
mouseB = e.getButton(); | |
} | |
@Override | |
public void mouseReleased(MouseEvent e) { | |
mouseB = -1; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.particle; | |
import com.jimgong.rain.entity.Entity; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
public class Particle extends Entity { | |
private Sprite sprite; | |
//Duration (called "life" in Cherno's videos) indicates how long particles last | |
protected int duration; | |
private int time = 0; | |
//Actual x and y locations | |
//zed models gravity | |
protected double xx, yy, zz; | |
//Amount of pixels particle moves in the x and y axes | |
protected double xa, ya, za; | |
public Particle(int x, int y, int duration) { | |
this.x = x; | |
this.y = y; | |
this.xx = x; | |
this.yy = y; | |
this.duration = duration + (random.nextInt(duration) - duration / 2); | |
sprite = Sprite.particle_normal; | |
//Gives a random number between - and 1, but gives a normal distribution | |
//more likely for number to be around 0 than -1 or 1 | |
this.xa = random.nextGaussian(); | |
this.ya = random.nextGaussian(); | |
this.zz = random.nextFloat() + 5; | |
} | |
public void update() { | |
time++; | |
if (time >= 2100) time = 0; | |
if (time > duration) remove(); | |
za -= 0.1; | |
if(zz < 0) { | |
zz = 0; | |
za *= -0.6; | |
xa *= 0.4; | |
ya *= 0.4; | |
} | |
move((xx + xa), (yy + ya) + (za)); | |
} | |
private void move(double x, double y) { | |
if (collision(x, y)) { | |
this.xa *= -0.5; | |
this.ya *= -0.5; | |
this.za *= -0.5; | |
} | |
this.xx += xa; | |
this.yy += ya; | |
this.zz += za; | |
} | |
public boolean collision(double x, double y) { | |
boolean solid = false; | |
/* | |
* Corner precision | |
* If corner % 2 == 0, checking left side | |
* If corner / 2 == 0, checking top side | |
*/ | |
for (int corner = 0; corner < 4; corner++) { | |
double xt = (x - corner % 2 * 16) / 16; | |
double yt = (y - corner / 2 * 16) / 16; | |
int ix = (int) Math.ceil(xt); //Math.ceil rounds up before casting | |
int iy = (int) Math.ceil(yt); | |
if (corner % 2 == 0) ix = (int)xt; | |
if (corner / 2 == 0) iy = (int)yt; | |
if (level.getTile(ix, iy).solid()) solid = true; | |
} | |
return solid; | |
} | |
public void render(Screen screen) { | |
screen.renderSprite((int) xx, (int) yy, sprite, true); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.spawner; | |
import com.jimgong.rain.entity.particle.Particle; | |
import com.jimgong.rain.entity.spawner.Spawner.Type; | |
import com.jimgong.rain.level.Level; | |
public class ParticleSpawner extends Spawner { | |
private int duration; | |
public ParticleSpawner(int x, int y, int duration, int amount, Level level) { | |
super(x, y, Type.PARTICLE, amount, level); | |
this.duration = duration; | |
for (int i = 0; i < amount; i++) { | |
level.add(new Particle(x, y, duration)); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.mob; | |
import java.util.ArrayList; | |
import java.util.List; | |
import com.jimgong.rain.Game; | |
import com.jimgong.rain.entity.projectile.Projectile; | |
import com.jimgong.rain.entity.projectile.WizardProjectile; | |
import com.jimgong.rain.entity.valuebar.Hitpoints; | |
import com.jimgong.rain.entity.valuebar.Mana; | |
import com.jimgong.rain.graphics.AnimatedSprite; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.SpriteSheet; | |
import com.jimgong.rain.input.Keyboard; | |
import com.jimgong.rain.input.Mouse; | |
public class Player extends Mob { | |
private Keyboard input; | |
private int animate_step = 0; | |
private AnimatedSprite sprite; | |
private Mana mana; | |
private int manaRegenRate = -2; | |
public static final int RUN_SPEED = 3; | |
public static final int WALK_SPEED = 1; | |
private int movespeed = WALK_SPEED; | |
public Player(Keyboard input) { | |
this.input = input; | |
sprite = new AnimatedSprite(16, 0, 0, SpriteSheet.player); | |
} | |
//Constructor to be used if player spawns at new coordinate | |
public Player (int x, int y, Keyboard input) { | |
this.x = x; | |
this.y = y; | |
this.input = input; | |
sprite = new AnimatedSprite(16, 0, 0, SpriteSheet.player); | |
//instantiate hitpoints and mana | |
hp = new Hitpoints(16, x, y); | |
mana = new Mana(16, x, y); | |
} | |
public void update() { | |
//Note direction player is supposed to move | |
int xa = 0, ya = 0; | |
//Update animation, prevent crashing | |
if (animate_step++ >= 2100) animate_step = 0; | |
if (input.up) ya--; | |
if (input.down) ya++; | |
if (input.left) xa--; | |
if (input.right) xa++; | |
if (input.space) movespeed = RUN_SPEED; | |
else movespeed = WALK_SPEED; | |
if (xa != 0 || ya != 0) { | |
for (int i = 0; i < movespeed; i++) { | |
move(xa, ya); | |
moving = true; | |
} | |
} | |
else moving = false; | |
clear(); | |
//shoot at max speed of once every 10 frames | |
updateShooting(); | |
sprite.update(dir); | |
sprite.animateControl(moving); | |
//Hitpoints and mana update | |
if (!hp.isDead()) hp.update(x + Hitpoints.X_OFFSET, y + Hitpoints.Y_OFFSET); | |
else remove(); | |
mana.update(x + Mana.X_OFFSET, y + Mana.Y_OFFSET); | |
if (animate_step % 60 == 0) { | |
//regen mana | |
if (mana.getPoints() - mana.getCapacity() <= manaRegenRate) mana.setPoints(manaRegenRate); | |
else if (mana.getPoints() < mana.getCapacity()) mana.setPoints(-1); | |
} | |
} | |
private void clear() { | |
for (int i = 0; i < level.getProjectiles().size(); i++) { | |
Projectile p = level.getProjectiles().get(i); | |
if (p.isRemoved()) { | |
level.getProjectiles().remove(i); | |
} | |
} | |
} | |
//Shoot if clicking left mouse button | |
private void updateShooting() { | |
//if out of mana, stop shooting | |
if (mana.isEmpty()) return; | |
if (Mouse.getButton() == 1 && animate_step % WizardProjectile.FIRE_RATE == 0) { | |
double dx = Mouse.getX() - Game.getWindowWidth() / 2; | |
double dy = Mouse.getY() - Game.getWindowHeight() / 2; | |
double dir = Math.atan2(dy, dx); | |
shoot(x, y, dir); | |
//mana shoot | |
mana.setPoints(1); | |
} | |
} | |
public void render(Screen screen) { | |
//Center player | |
int xx = x - sprite.SIZE / 2; | |
int yy = y - sprite.SIZE / 2; | |
screen.renderMob(xx, yy, sprite, 0); | |
if (input.shift) { | |
//render hp and mana bars | |
hp.render(screen); | |
mana.render(screen); | |
List<Mob> hpToggle = level.getMobsInRadius(this, Game.getWindowWidth()); | |
for (int i = 0; i < hpToggle.size(); i++) { | |
hpToggle.get(i).getHitpoints().render(screen); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.projectile; | |
import java.util.Random; | |
import com.jimgong.rain.entity.Entity; | |
import com.jimgong.rain.graphics.Sprite; | |
public abstract class Projectile extends Entity { | |
//where projectile spawns | |
protected final int xOrigin, yOrigin; | |
protected double angle; | |
protected Sprite sprite; | |
protected double x, y; | |
protected final Random random = new Random(); | |
//vector | |
protected double nx, ny; | |
//Distance projectile has traveled from origin | |
protected double distance; | |
//speed, range, damage | |
protected double speed, range, damage; | |
public Projectile(int x, int y, double dir) { | |
xOrigin = x; | |
yOrigin = y; | |
angle = dir; | |
this.x = x; | |
this.y = y; | |
} | |
protected void move() { | |
} | |
public Sprite getSprite() { | |
return sprite; | |
} | |
public int getSpriteSize() { | |
return sprite.SIZE; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level; | |
import java.util.Random; | |
public class RandomLevel extends Level { | |
private static final Random random = new Random(); | |
public RandomLevel(int width, int height) { | |
super(width, height); | |
} | |
@Override | |
protected void generateLevel() { | |
for (int y = 0; y < height; y++) { | |
for (int x = 0; x < width; x++) { | |
tilesInt[x + y * width] = random.nextInt(4); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level.tile; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
public class RockTile extends Tile { | |
public RockTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
public boolean solid() { | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.graphics; | |
import java.util.Random; | |
import com.jimgong.rain.entity.mob.Chaser; | |
import com.jimgong.rain.entity.mob.Mob; | |
import com.jimgong.rain.entity.projectile.Projectile; | |
import com.jimgong.rain.level.tile.Tile; | |
public class Screen { | |
public int width, height; | |
public int[] pixels; | |
public final int MAP_SIZE = 64; | |
public final int MAP_SIZE_MASK = MAP_SIZE - 1; | |
public int[] tiles = new int[MAP_SIZE * MAP_SIZE]; | |
public int xOffset, yOffset; | |
private Random random = new Random(); | |
public Screen(int width, int height) { | |
this.width = width; | |
this.height = height; | |
pixels = new int[width * height]; //50400 pixels total for 300x168 | |
for (int i = 0; i < tiles.length; i++) { | |
tiles[i] = random.nextInt(0xFFFFFF); | |
} | |
} | |
public void clear() { | |
for (int i = 0; i < pixels.length; i++) { | |
pixels[i] = 0; | |
} | |
} | |
public void renderSprite(int xp, int yp, Sprite sprite, boolean fixed) { | |
//Offsets it so it renders at the area the map currently is | |
if (fixed) { | |
xp -= xOffset; | |
yp -= yOffset; | |
} | |
for (int y = 0; y < sprite.getHeight(); y++) { | |
int ya = y + yp; | |
for (int x = 0; x < sprite.getWidth(); x++) { | |
int xa = x + xp; | |
if (xa < 0 || xa >= width || ya < 0 || ya >= height) continue; | |
pixels[xa + ya * width] = sprite.pixels[x + y * sprite.getWidth()]; | |
} | |
} | |
} | |
/* | |
* Render individual tiles | |
* xa/ya are the absolute position of the tile | |
* x/y are the pixels being rendered | |
* xp/yp are the offsets | |
*/ | |
public void renderTile(int xp, int yp, Tile tile) { | |
xp -= xOffset; | |
yp -= yOffset; | |
for (int y = 0; y < tile.sprite.SIZE; y++) { | |
int ya = y + yp; | |
for (int x = 0; x < tile.sprite.SIZE; x++) { | |
int xa = x + xp; | |
/*Prevent program from rendering entire map | |
* at once; just show immediate screen area | |
*/ | |
if (xa < -tile.sprite.SIZE || xa >= width || ya < 0 || ya >= height) break; | |
if (xa < 0) xa = 0; | |
pixels[xa + ya * width] = tile.sprite.pixels[x + y * tile.sprite.SIZE]; | |
//pixel on screen getting rendered; pixel on sprite getting rendered | |
} | |
} | |
} | |
//Render projectiles | |
public void renderProjectile(int xp, int yp, Projectile p) { | |
xp -= xOffset; | |
yp -= yOffset; | |
for (int y = 0; y < p.getSpriteSize(); y++) { | |
int ya = y + yp; | |
for (int x = 0; x < p.getSpriteSize(); x++) { | |
int xa = x + xp; | |
/*Prevent program from rendering entire map | |
* at once; just show immediate screen area | |
*/ | |
if (xa < -p.getSpriteSize() || xa >= width || ya < 0 || ya >= height) break; | |
if (xa < 0) xa = 0; | |
int col = p.getSprite().pixels[x + y * p.getSpriteSize()]; | |
if (col != 0xFFFF00FF) pixels[xa + ya * width] = col; | |
} | |
} | |
} | |
public void renderMob(int xp, int yp, Mob mob) { | |
xp -= xOffset; | |
yp -= yOffset; | |
for (int y = 0; y < mob.getSprite().SIZE; y++) { | |
int ya = y + yp; | |
for (int x = 0; x < mob.getSprite().SIZE; x++) { | |
int xa = x + xp; | |
/*Prevent program from rendering entire map | |
* at once; just show immediate screen area | |
*/ | |
if (xa < -(mob.getSprite().SIZE) || xa >= width || ya < 0 || ya >= height) break; | |
if (xa < 0) xa = 0; | |
//Prevent the pink pixels in spritesheet from being rendered | |
int col = mob.getSprite().pixels[x + y * mob.getSprite().SIZE]; | |
//Change color of chasers | |
if (mob instanceof Chaser && col == 0xffe02828) col = 0xff054bff; | |
if (col != 0xFFFF00FF) | |
pixels[xa + ya * width] = col; | |
} | |
} | |
} | |
public void renderMob(int xp, int yp, Sprite sprite, int flip) { | |
xp -= xOffset; | |
yp -= yOffset; | |
for (int y = 0; y < sprite.SIZE; y++) { | |
int ya = y + yp; | |
int ys = y; | |
if (flip == 2 || flip == 3) ys = 15 - y; | |
for (int x = 0; x < sprite.SIZE; x++) { | |
int xa = x + xp; | |
/*Prevent program from rendering entire map | |
* at once; just show immediate screen area | |
*/ | |
int xs = x; | |
if (flip == 1 || flip == 3) xs = 15 - x; | |
if (xa < -sprite.SIZE || xa >= width || ya < 0 || ya >= height) break; | |
if (xa < 0) xa = 0; | |
//Prevent the pink pixels in spritesheet from being rendered | |
int col = sprite.pixels[xs + ys * sprite.SIZE]; | |
if (col != 0xFFFF00FF) | |
pixels[xa + ya * width] = col; | |
} | |
} | |
} | |
//set Offset | |
public void setOffset(int xOffset, int yOffset) { | |
this.xOffset = xOffset; | |
this.yOffset = yOffset; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.spawner; | |
import com.jimgong.rain.entity.Entity; | |
import com.jimgong.rain.entity.particle.Particle; | |
import com.jimgong.rain.level.Level; | |
public class Spawner extends Entity { | |
public enum Type { | |
MOB, PARTICLE | |
} | |
private Type type; | |
public Spawner (int x, int y, Type type, int amount, Level level) { | |
init(level); | |
this.x = x; | |
this.y = y; | |
this.type = type; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level.tile.spawn_level; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
import com.jimgong.rain.level.tile.Tile; | |
public class SpawnFloorTile extends Tile { | |
public SpawnFloorTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level.tile.spawn_level; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
import com.jimgong.rain.level.tile.Tile; | |
public class SpawnFlowerTile extends Tile{ | |
public SpawnFlowerTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level.tile.spawn_level; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
import com.jimgong.rain.level.tile.Tile; | |
public class SpawnGrassTile extends Tile { | |
public SpawnGrassTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level; | |
import java.awt.image.BufferedImage; | |
import java.io.IOException; | |
import javax.imageio.ImageIO; | |
import com.jimgong.rain.entity.mob.Chaser; | |
import com.jimgong.rain.entity.mob.Dummy; | |
public class SpawnLevel extends Level{ | |
public SpawnLevel (String path) { | |
super(path); | |
} | |
protected void loadLevel(String path) { | |
try { | |
BufferedImage image = ImageIO.read(SpawnLevel.class.getResource(path)); | |
width = image.getWidth(); | |
height = image.getHeight(); | |
tiles = new int[width * height]; | |
image.getRGB(0, 0, width, height, tiles, 0 , width); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
System.out.println("Exception! Could not load level file!"); | |
} | |
//load dummies in 5 random locations | |
for (int i = 0; i < 1; i++) { | |
add(new Chaser(19, 25)); | |
add(new Dummy(19, 25)); | |
} | |
} | |
//Grass = 0xFF00FF00 | |
//Flower = 0xFFFFFF00 | |
//Rock = 0xFF7F7F00 | |
protected void generateLevel() { | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level.tile.spawn_level; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
import com.jimgong.rain.level.tile.Tile; | |
public class SpawnRockTile extends Tile { | |
public SpawnRockTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
public boolean solid() { | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level.tile.spawn_level; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
import com.jimgong.rain.level.tile.Tile; | |
public class SpawnWallTile extends Tile { | |
public SpawnWallTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
public boolean solid() { | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level.tile.spawn_level; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
import com.jimgong.rain.level.tile.Tile; | |
public class SpawnWaterTile extends Tile{ | |
public SpawnWaterTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.graphics; | |
import com.jimgong.rain.entity.valuebar.Hitpoints; | |
import com.jimgong.rain.entity.valuebar.ValueBar; | |
public class Sprite { | |
//Size of the particular sprite | |
public final int SIZE; | |
//width and height | |
private int width, height; | |
//Coordinates of sprite | |
protected int x, y; | |
public int[] pixels; | |
private SpriteSheet sheet; | |
public static Sprite grass = new Sprite(16, 0, 1, SpriteSheet.tiles); | |
public static Sprite flower = new Sprite(16, 1, 1, SpriteSheet.tiles); | |
public static Sprite rock = new Sprite(16, 2, 1, SpriteSheet.tiles); | |
public static Sprite voidSprite = new Sprite(16, 16, 0x1B87E0); | |
//Spawn level sprites | |
public static Sprite spawn_grass = new Sprite(16, 0, 0, SpriteSheet.spawn_level); | |
public static Sprite spawn_flower = new Sprite(16, 0, 1, SpriteSheet.spawn_level); | |
public static Sprite spawn_rock = new Sprite(16, 0, 2, SpriteSheet.spawn_level); | |
public static Sprite spawn_wall = new Sprite(16, 1, 0, SpriteSheet.spawn_level); | |
public static Sprite spawn_floor = new Sprite(16, 1, 1, SpriteSheet.spawn_level); | |
public static Sprite spawn_water = new Sprite(16, 2, 0, SpriteSheet.spawn_level); | |
//Projectile Sprites | |
public static Sprite projectile_wizard = new Sprite(16, 0, 2, SpriteSheet.projectile_wizard); | |
//Particle sprites | |
public static Sprite particle_normal = new Sprite(1, 1, 0xCC3130); | |
public Sprite(int size, int x, int y, SpriteSheet sheet) { | |
SIZE = size; | |
this.width = SIZE; | |
this.height = SIZE; | |
pixels = new int[SIZE * SIZE]; | |
//Set location of target sprite in sprite sheet | |
this.x = x * size; | |
this.y = y * size; | |
this.sheet = sheet; | |
load(); | |
} | |
public Sprite(int width, int height, int color) { | |
SIZE = width * height; | |
this.width = width; | |
this.height = height; | |
pixels = new int[SIZE * SIZE]; | |
setColor(color); | |
} | |
//for Bar sprites | |
//emptyValue designates amount of points empty from capacity | |
public Sprite(int width, int height, int fillColor, int emptyColor, int emptyValue) { | |
SIZE = width * height; | |
this.width = width; | |
this.height = height; | |
pixels = new int[SIZE]; | |
setColor(fillColor, emptyColor, emptyValue * ValueBar.BAR_WIDTH); | |
} | |
private void setColor(int color) { | |
for (int i = 0; i < SIZE; i++) { | |
pixels[i] = color; | |
} | |
} | |
//for Bar sprites | |
private void setColor(int fillColor, int emptyColor, int limit) { | |
//top pixels empty | |
for (int i = 0; i < limit; i++) { | |
pixels[i] = emptyColor; | |
} | |
//bottom pixels filled | |
for (int i = limit; i < SIZE; i++) { | |
pixels[i] = fillColor; | |
} | |
} | |
public int getWidth() { | |
return width; | |
} | |
public int getHeight() { | |
return height; | |
} | |
//Access spritesheet pixels and find right sprite | |
protected void load() { | |
for (int y = 0; y < SIZE; y++) { | |
for (int x = 0; x < SIZE; x++) { | |
//Extract single sprite from sprite sheet | |
pixels[x + y * SIZE] = sheet.pixels[(x + this.x) + (y + this.y) * sheet.SIZE]; | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.graphics; | |
import java.awt.image.BufferedImage; | |
import java.io.IOException; | |
import javax.imageio.ImageIO; | |
public class SpriteSheet { | |
/** Specify path */ | |
private String path; | |
public final int SIZE; | |
public final int WIDTH, HEIGHT; | |
public int[] pixels; | |
//Tiles spritesheet | |
public static SpriteSheet tiles = new SpriteSheet("/textures/sheets/spritesheet.png", 256); | |
public static SpriteSheet spawn_level = new SpriteSheet("/textures/sheets/spawn_level.png", 48); | |
//Player spritesheet | |
public static SpriteSheet player = new SpriteSheet("/textures/sheets/player.png", 64); | |
//Projectiles | |
public static SpriteSheet projectile_wizard = new SpriteSheet("/textures/sheets/projectiles/wizard.png", 48); | |
//Charmander - used for Dummy NPC | |
public static SpriteSheet charmander = new SpriteSheet("/textures/sheets/charmander.png", 64); | |
/**Constructor*/ | |
public SpriteSheet(String path, int size) { | |
this.path = path; | |
SIZE = size; | |
WIDTH = SIZE; | |
HEIGHT = SIZE; | |
pixels = new int[SIZE * SIZE]; | |
load(); | |
} | |
/** Load spritesheet */ | |
private void load() { | |
//Create new buffered image object and set it equal to image of path | |
try { | |
BufferedImage image = ImageIO.read(SpriteSheet.class.getResource(path)); | |
int w = image.getWidth(); | |
int h = image.getHeight(); | |
//Translate loaded image into pixels | |
image.getRGB(0, 0, w, h, pixels, 0, w); | |
} | |
catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Each tile should have a position and a sprite | |
* Say whether it is collidable (i.e. something can pass through it) | |
*/ | |
package com.jimgong.rain.level.tile; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
import com.jimgong.rain.level.tile.spawn_level.SpawnFloorTile; | |
import com.jimgong.rain.level.tile.spawn_level.SpawnFlowerTile; | |
import com.jimgong.rain.level.tile.spawn_level.SpawnGrassTile; | |
import com.jimgong.rain.level.tile.spawn_level.SpawnRockTile; | |
import com.jimgong.rain.level.tile.spawn_level.SpawnWallTile; | |
import com.jimgong.rain.level.tile.spawn_level.SpawnWaterTile; | |
public class Tile { | |
public int x, y; | |
public Sprite sprite; | |
public static Tile grass = new GrassTile(Sprite.grass); | |
public static Tile flower = new FlowerTile(Sprite.flower); | |
public static Tile rock = new RockTile(Sprite.rock); | |
public static Tile voidTile = new VoidTile(Sprite.voidSprite); | |
//Spawn level tiles | |
public static Tile spawn_grass = new SpawnGrassTile(Sprite.spawn_grass); | |
public static Tile spawn_flower = new SpawnFlowerTile(Sprite.spawn_flower); | |
public static Tile spawn_rock = new SpawnRockTile(Sprite.spawn_rock); | |
public static Tile spawn_wall = new SpawnWallTile(Sprite.spawn_wall); | |
public static Tile spawn_floor = new SpawnFloorTile(Sprite.spawn_floor); | |
public static Tile spawn_water = new SpawnWaterTile(Sprite.spawn_water); | |
//color recognition | |
public static final int col_spawn_grass = 0xFF00FF00; | |
public static final int col_spawn_flower = 0xFFFFFF00; | |
public static final int col_spawn_rock = 0xFFFF0000; | |
public static final int col_spawn_wall = 0xFF808080; | |
public static final int col_spawn_floor = 0xFF7F3300; | |
public static final int col_spawn_water = 0xFF0000FF; | |
//Constructor | |
public Tile(Sprite sprite) { | |
this.sprite = sprite; | |
} | |
public void render(int x, int y, Screen screen) { | |
} | |
//Whether collidable | |
public boolean solid() { | |
return false; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level; | |
public class TileCoordinate { | |
private int x, y; | |
private final int TILE_SIZE = 16; | |
public TileCoordinate(int x, int y) { | |
this.x = x * TILE_SIZE; | |
this.y = y * TILE_SIZE; | |
} | |
public int x() { | |
return x; | |
} | |
public int y() { | |
return y; | |
} | |
public int[] xy() { | |
return new int[] {x,y}; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.valuebar; | |
import com.jimgong.rain.entity.Entity; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
public class ValueBar extends Entity { | |
protected int capacity; | |
protected int points; | |
protected Sprite sprite; | |
protected int point_color; | |
protected int empty_color; | |
public final static int BAR_WIDTH = 1; | |
//Construct full value bar (loaded to capacity) | |
//x & y designate visibility coordinates | |
public ValueBar(int capacity, int x, int y, int point_color, int empty_color) { | |
this.capacity = capacity; | |
this.points = capacity; | |
this.x = x; | |
this.y = y; | |
sprite = new Sprite(BAR_WIDTH, capacity, point_color, empty_color, 0); | |
} | |
public void update(int x, int y) { | |
sprite = new Sprite(BAR_WIDTH, capacity, point_color, empty_color, capacity - points); | |
this.x = x; | |
this.y = y; | |
} | |
public int getCapacity() { | |
return capacity; | |
} | |
public int getPoints() { | |
return points; | |
} | |
//positive value = damage, negative value = heal | |
public void setPoints(int value) { | |
points -= value; | |
} | |
public void render(Screen screen) { | |
screen.renderSprite(x, y, sprite, true); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.level.tile; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
public class VoidTile extends Tile{ | |
public VoidTile(Sprite sprite) { | |
super(sprite); | |
} | |
public void render(int x, int y, Screen screen) { | |
screen.renderTile(x << 4, y << 4, this); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.jimgong.rain.entity.projectile; | |
import java.util.List; | |
import com.jimgong.rain.entity.mob.Mob; | |
import com.jimgong.rain.entity.spawner.ParticleSpawner; | |
import com.jimgong.rain.graphics.Screen; | |
import com.jimgong.rain.graphics.Sprite; | |
public class WizardProjectile extends Projectile{ | |
public static final int FIRE_RATE = 6; //10 per second at 60fps | |
public WizardProjectile(int x, int y, double dir) { | |
super(x, y, dir); | |
//varying range | |
range = 150; | |
speed = 3; | |
damage = 2; | |
sprite = Sprite.projectile_wizard; | |
nx = speed * Math.cos(angle); | |
ny = speed * Math.sin(angle); | |
} | |
public void update() { | |
if (level.tileCollision((int)(x + nx), (int)(y + ny), 8, 4, 4)) { | |
level.add(new ParticleSpawner((int)x, (int)y, 60, 50, level)); | |
remove(); | |
} | |
else move(); | |
List<Mob> hitbox = level.getMobsInRadius((int)x, (int)y, 8); | |
for (int i = 0; i < hitbox.size(); i++) { | |
hitbox.get(i).getHitpoints().setPoints((int)damage); | |
} | |
} | |
protected void move() { | |
x += nx; | |
y += ny; | |
if (getDistance() > range) remove(); | |
} | |
private double getDistance() { | |
double dist = 0; | |
dist = Math.sqrt((xOrigin - x) * (xOrigin - x) + (yOrigin - y) * (yOrigin - y)); | |
return dist; | |
} | |
public void render(Screen screen) { | |
//x y render projectile relative to character | |
screen.renderProjectile((int)x - 8, (int)y - 8, this); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment