I'm creating a top-down game for my A-level/college computer science project, and I'm trying to implement rain. The game needs to be usable on any platform, so the use of external libraries is out of the question. I currently have the GUI running off Java's Graphics package, and the game is rendered pixel-per-pixel from an array of pixels. The aim would be to have a rain effect that looks something like this http://d2436y6oj07al2.cloudfront.net/spff/previews/vbme0577.jpg. If this is possible, this would be really good. Currently I also have a particle class and particle spawners', which add the blood effect and effect of projectiles "exploding" when they hit a wall.
Is there a way to implement some rain from what I already have? I attempted to implement a Rain class, which spawns particles in a random place within bounds on an area of the screen, to make it look like it was coming from the perspective of the blocks.
Here is the rain i've tried to add (blue particles):
The issue is it moves and looks nothing like the image linked above. Also, here is my Rain class, which is added currently by the player just for testing, but the end game will be to have a "WeatherManager" class that handles all the weather changes and weather spawning (rain, snow etc).
package com.ritcat14.GotYourSix.entity.particle;
import java.util.Random;
import com.ritcat14.GotYourSix.Game;
import com.ritcat14.GotYourSix.entity.Entity;
import com.ritcat14.GotYourSix.graphics.Sprite;
import com.ritcat14.GotYourSix.level.Level;
public class Rain extends Entity {
private int time = 0; //time it is raining for
private int currTime = 0;
private boolean timeOfDay = false; //if it is night or day (false - night, true - day)
private Level level = null;
private Sprite drop = null;
private int amount = 0;
public Rain(int time, boolean timeOfDay, Level level) {
init(level);
this.time = time;
this.timeOfDay = timeOfDay;
this.level = level;
if (timeOfDay) {
drop = new Sprite(1, 0x87F7FF);
} else {
drop = new Sprite(1, 0xEFFBFF);
}
}
public void update() {
currTime++;
if (currTime > time) {
remove();
} else {
Random ran = new Random();
if (time % (ran.nextInt(120) + 1) == 0) {
int x = ran.nextInt(Game.getWindowWidth());
int y = ran.nextInt(Game.getWindowHeight() / 4) + 100;
level.add(new Particle(x, y, 1000, drop));
amount++;
}
}
}
public void setDay(boolean dayTime) {
this.timeOfDay = dayTime;
}
}
Here is my particle class:
package com.ritcat14.GotYourSix.entity.particle;
import java.util.Random;
import com.ritcat14.GotYourSix.entity.Entity;
import com.ritcat14.GotYourSix.entity.mob.Player;
import com.ritcat14.GotYourSix.entity.projectile.Projectile;
import com.ritcat14.GotYourSix.graphics.Screen;
import com.ritcat14.GotYourSix.graphics.Sprite;
public class Particle extends Entity {
private Sprite sprite = null;
private int life = 0;
private int time = 0;
protected double xx = 0, yy = 0, zz = 0;
protected double xa = 0, ya = 0, za = 0;
private Random ran = new Random();
public Particle(int x, int y, int life, Sprite sprite) {
this.x = x;
this.y = y;
this.xx = x;
this.yy = y;
this.life = life + (random.nextInt(50) - 25);
this.sprite = sprite;
this.xa = random.nextGaussian();
this.ya = random.nextGaussian();
this.zz = random.nextFloat() + 2.0;
int col = ran.nextInt(4);
if (sprite != Sprite.particle_blood) {
if (Projectile.weapon == Projectile.Weapon.FIREDCANNON || Projectile.weapon == Projectile.Weapon.FIREDARROW) {
if (col == 0)
this.sprite = new Sprite(2, 0xff000000);
if (col == 1)
this.sprite = new Sprite(2, 0xffF8A800);
if (col == 2)
this.sprite = new Sprite(2, 0xffF8F8C8);
if (col == 3)
this.sprite = new Sprite(2, 0xffF8A800);
} else if (Projectile.weapon == Projectile.Weapon.FIREBALL || Projectile.weapon == Projectile.Weapon.FIREWALL) {
if (col == 0)
this.sprite = new Sprite(2, 0xffF86800);
if (col == 1)
this.sprite = new Sprite(2, 0xffF8A800);
if (col == 2)
this.sprite = new Sprite(2, 0xffF8F8C8);
if (col == 3)
this.sprite = new Sprite(2, 0xffF8D840);
} else if (Projectile.weapon == Projectile.Weapon.ICEDCANNON || Projectile.weapon == Projectile.Weapon.ICEDARROW) {
if (col == 0)
this.sprite = new Sprite(2, 0xff427AFF);
if (col == 1)
this.sprite = new Sprite(2, 0xff607BFF);
if (col == 2)
this.sprite = new Sprite(2, 0xff7C9BFF);
if (col == 3)
this.sprite = new Sprite(2, 0xff000000);
} else if (Projectile.weapon == Projectile.Weapon.ICEBALL || Projectile.weapon == Projectile.Weapon.ICEWALL) {
if (col == 0)
this.sprite = new Sprite(2, 0xff427AFF);
if (col == 1)
this.sprite = new Sprite(2, 0xff607BFF);
if (col == 2)
this.sprite = new Sprite(2, 0xff7C9BFF);
if (col == 3)
this.sprite = new Sprite(2, 0xffD3DEFF);
}
}
}
public void update() {
time++;
if (time >= Integer.MAX_VALUE - 100)
time = 0; //Safety check
if (time > life)
remove();
za -= 0.1;
if (zz < 0) {
zz = 0;
za *= -0.55;
xa *= 0.4;
ya *= 0.4;
}
move(xx + xa, (yy + ya) + (zz + 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;
for (int c = 0; c < 4; c++) {
double xt = (x - c % 2 * 16) / 16;
double yt = (y - c / 2 * 16) / 16;
int ix = (int)Math.ceil(xt);
int iy = (int)Math.ceil(yt);
if (c % 2 == 0)
ix = (int)Math.floor(xt);
if (c / 2 == 0)
iy = (int)Math.floor(yt);
if (level.getTile(ix, iy).solid())
solid = true;
}
return solid;
}
public void render(Screen screen) {
screen.renderSprite((int)xx - 1, (int)yy - (int)zz - 1, sprite, true);
}
}
Any ideas as to how to improve and/or make it appear to "fall" to the ground? I managed this with standard particles, but I can't get my head round how "Rain" would appear to "fall" in a 2D world. Any ideas? Thanks