This commit is contained in:
Victor 2018-11-14 23:02:34 +02:00
commit e75944fbe0
5 changed files with 320 additions and 0 deletions

91
src/DrawParticles.java Normal file
View File

@ -0,0 +1,91 @@
/*
* aNNiMON 2011
* For more info visit http://annimon.com/
*/
import java.util.Vector;
import javax.microedition.lcdui.*;
/**
* @author aNNiMON
*/
public class DrawParticles extends Canvas implements Runnable {
private static final int MAX_SNOW = 15;
private int w, h;
private int speed, wind;
private Vector particles;
public DrawParticles() {
setFullScreenMode(true);
w = getWidth();
h = getHeight();
speed = 1;
wind = 0;
Snow.setSpeed(speed);
Snow.setWind(wind);
particles = new Vector();
for (int i = 0; i < 10; i++) {
particles.addElement(new Snow(w, h-10*i, MAX_SNOW*i+MAX_SNOW/3, i+1));
}
new Thread(this).start();
}
public void paint(Graphics g) {
g.setColor(0);//xFF2895B9);
g.fillRect(0, 0, w, h);
// рисуем системы
for (int i = 0; i < particles.size(); i++) {
((ParticleSystem) particles.elementAt(i)).render(g, speed);
}
}
public void run() {
while(true) {
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
protected void sizeChanged(int w, int h) {
this.w = getWidth();
this.h = getHeight();
super.sizeChanged(w, h);
}
protected void keyPressed(int key) {
int ga = getGameAction(key);
switch (ga) {
case UP:
speed++;
if (speed > 30) speed = 30;
Snow.setSpeed(speed);
break;
case DOWN:
speed--;
if (speed < 1) speed = 1;
Snow.setSpeed(speed);
break;
case RIGHT:
wind++;
if (wind > 10) wind = 10;
Snow.setWind(wind);
break;
case LEFT:
wind--;
if (wind < -10) wind = -10;
Snow.setWind(wind);
break;
}
}
protected void keyRepeated(int key) {
keyPressed(key);
}
}

33
src/Main.java Normal file
View File

@ -0,0 +1,33 @@
/*
* aNNiMON 2011
* For more info visit http://annimon.com/
*/
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* @author aNNiMON
*/
public class Main extends MIDlet {
public Display dsp;
public static Main midlet;
public Main() {
midlet = Main.this;
dsp = Display.getDisplay(Main.this);
}
public void startApp() {
DrawParticles dp = new DrawParticles();
dsp.setCurrent(dp);
}
public void pauseApp() {
}
public void destroyApp(boolean ex) {
notifyDestroyed();
}
}

60
src/ParticleSystem.java Normal file
View File

@ -0,0 +1,60 @@
import javax.microedition.lcdui.Graphics;
/*
* aNNiMON 2011
* For more info visit http://annimon.com/
*/
/**
* Базовый класс системы частиц
* @author aNNiMON
*/
public abstract class ParticleSystem {
/* Массив частицы */
protected Point3D[] particles;
protected Rectangle window;
public ParticleSystem(int x, int y, int w, int h, int numOfParticles) {
window = new Rectangle(x, y, w, h);
particles = new Point3D[numOfParticles];
}
/* Отрисовка системы частиц */
public void render(Graphics g, int speed) {
update(); // сначала обновляем частицы
g.clipRect(window.x, window.y, window.w, window.h);
draw(g); // затем только рисуем
}
/* Добавление частицы */
protected Point3D addParticle() {
return resetParticle();
}
/* Сброс свойств частицы */
protected abstract Point3D resetParticle();
/* Обновление свойств частиц */
protected abstract void update();
/* Отрисовка частиц */
protected abstract void draw(Graphics g);
/* Точка в 3D */
protected class Point3D {
float x, y, z;
int color;
}
/* Прямоугольник */
protected class Rectangle {
int x, y, w, h;
public Rectangle(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
}

99
src/Snow.java Normal file
View File

@ -0,0 +1,99 @@
import javax.microedition.lcdui.Graphics;
/*
* aNNiMON 2011
* For more info visit http://annimon.com/
*/
/**
* @author aNNiMON
*/
public class Snow extends ParticleSystem {
/* Скорость падения снега */
private static int speed;
/* Скорость и направление ветра */
private static int wind;
/* Начальный угол отрисовки снежинки */
private static float stAngle = 0;
/* Слой снежинок по Z */
private float zPosition;
public Snow(int w, int h, int numOfParticles, float zPos) {
super(0, 0, w, h, numOfParticles);
if (zPos > 10) zPos = 10;
zPosition = zPos+1;
for (int i = 0; i < particles.length; i++) {
particles[i] = addParticle();
}
}
/* Установка скорости падения снега */
public static void setSpeed(int value) {
speed = value;
}
/* Установка скорости и направления ветра */
public static void setWind(int value) {
wind = value;
}
/* Начальные свойства снежинки */
protected Point3D resetParticle() {
Point3D snow = new Point3D();
snow.x = Util.random(window.x, window.w);
// создаём снежинки за экраном
snow.y = Util.random(window.y, window.h);
snow.z = zPosition;
return snow;
}
protected void update() {
for (int i = 0; i < particles.length; i++) {
particles[i].x = applyWind(particles[i].x); // ветер
particles[i].x += Util.random(-1+Util.sign(wind), 1+Util.sign(wind)); // прочие параметры
particles[i].y = particles[i].y + (speed / particles[i].z) + 0.981f; // скорость + притяжение
if (particles[i].y > window.h) {
if (wind > 0) particles[i].x = Util.random(window.x-wind*10, window.w);
else if (wind < 0) particles[i].x = Util.random(window.x, window.w-wind*10);
else particles[i].x = Util.random(window.x, window.w);
particles[i].y = window.y - Util.random(0, 10);
} else if (particles[i].x > window.w) {
if (wind > 0) particles[i].x = -Util.random(0, 10);
} else if (particles[i].x < window.x) {
if (wind < 0) particles[i].x = window.w+Util.random(0, 10);
}
}
}
protected void draw(Graphics g) {
g.setColor(Util.colorFromBrightness(255 - (int)((zPosition-1) * 12.7f)));
for (int i = 0; i < particles.length; i++) {
int x = (int) particles[i].x;
int y = (int) particles[i].y;
if (zPosition > 6) g.drawLine(x, y, x, y);
else {
int radius = (int) (8 - zPosition);
drawSnow(g, x, y, radius);
}
}
}
private float applyWind(float x) {
return (x + wind/5f);
}
private void drawSnow(Graphics g, int x, int y, int radius) {
if (wind != 0) {
stAngle = stAngle + Util.sign(wind) * 0.0004f*(speed+Math.abs(wind));
if (Math.abs(stAngle) > 90) stAngle = Util.sign(wind);
}
for (float i = stAngle/2; i <= 180; i += 45) {
int cos = (int) (Math.cos(i)*radius);
int sin = (int) (Math.sin(i)*radius);
g.drawLine(x-cos, y-sin, x+cos, y+sin);
}
}
}

37
src/Util.java Normal file
View File

@ -0,0 +1,37 @@
import java.util.Random;
/*
* aNNiMON 2011
* For more info visit http://annimon.com/
*/
/**
*
* @author aNNiMON
*/
public class Util {
private static final Random rnd = new Random();
/**
* Получить цвет ARGB из яркости. Оттенки серого.
* @param value яркость
* @return ARGB цвет
*/
public static int colorFromBrightness(int value) {
return 0xFF000000 | (value << 16) | (value << 8) | (value);
}
/* Получить случайное float значение в промежутке (from; to) */
public static float random(int from, int to) {
return rnd.nextInt(to-from)+from+rnd.nextFloat();
}
/* Возвращает знак числа */
public static int sign(int number) {
if (number > 0) return 1;
else if (number < 0) return -1;
else return 0;
}
}