16 июл. 2008 г.

Dots Applet

Ещё один бесполезный апплет =)



Смотреть

Исходный код подкатом.


Исходный код:

package org.tosamoepalevo.dotsapplet;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import java.util.ArrayList;
import java.util.Random;

/**
* Так как апплет очень простенький, всё сделано в одном классе
*/
public class Main extends JApplet implements Runnable, MouseListener, MouseMotionListener {
private static final int DESIRED_FPS = 25;
private static final int SIZE_WIDTH = 400;
private static final int SIZE_HEIGHT = 300;
private static final Color COLOR_BACKGROUND = new Color(0, 0, 0);
private static final Color COLOR_FOREGROUND = new Color(250, 250, 250);
private static final Color COLOR_MESSAGE = new Color(32, 32, 32, 90);
private static final Color COLOR_RESTART_BUTTON_BACKGROUND = new Color(255, 255, 255, 90);
private static final Color COLOR_RESTART_BUTTON_FOREGROUND = new Color(127, 127, 127, 90);
private static final Font FONT_TEXT = new Font("Arial", Font.PLAIN, 10);
private static final Font FONT_MESSAGE = new Font("Gerogia", Font.BOLD, 20);

//параметры точек
private static final int MAX_VALUE = 1024;
private static final int MIN_VALUE = 100;
private static final int DECREASE_COUNT = 2;
private static final int SCALE = 2;
private static final int RANDOM_DECREASE = 20;

private boolean stopFlag = false;
//двойная буферизация
private Image dbImage;
private Graphics g;

private long lastTime;
private Thread thread;
//массив значений
private int[][] dots;
//массив состояний
private boolean[][] flags;
private Random random;

//кнопка рестарта
private int restartButtonXPos = -20;
private int restartButtonYPos = -20;
private int restartButtonSize = 20;

//сообщение Click.. при старте
private boolean showMessage;
//надписи
private java.util.List<String> textArray;

public Main() {
setSize(SIZE_WIDTH, SIZE_HEIGHT);
}

public void init() {
super.init();
random = new Random();
//создаём массив значений для точек
dots = new int[SIZE_WIDTH / SCALE][SIZE_HEIGHT / SCALE];
//и массив, определяющий, задета точка или нет
flags = new boolean[SIZE_WIDTH / SCALE][SIZE_HEIGHT / SCALE];
//задаём лист слов
textArray = new ArrayList<String>();
textArray.add("ТОСАМОЕПАЛЕВО");
textArray.add("pixels..");
//загружаем слова из параметров апплета
for (int i = 0; i < 10; i++) {
if (getParameter("string_" + i) != null) {
textArray.add(getParameter("string_" + i));
}
}
//чтобы сообщение Click.. показать при старте
showMessage = true;
//заполняем массивы рандомными значениями и рисуем одно из слов
resetDotsArray();
resetFlagsArray();
stopFlag = false;
//добавляем листенеры
this.addMouseListener(this);
this.addMouseMotionListener(this);
thread = new Thread(this);
//запускаем главный поток
thread.start();
}

public void stop() {
stopFlag = true;
System.gc();
}

public void destroy() {
stopFlag = true;
System.gc();
}

public void run() {
while (!stopFlag) {
lastTime = System.currentTimeMillis() + 1000 / DESIRED_FPS;
processDots();
repaint();
do {
try {
Thread.sleep(5);
} catch (InterruptedException ex) {
// do nothing
}
} while (System.currentTimeMillis() < lastTime);
}
}

/**
* Заполняет массив точек случайными значениями и рисует одно из слов
*/
private void resetDotsArray() {
for (int i = 0; i < dots.length; i++) {
for (int j = 0; j < dots[i].length; j++) {
dots[i][j] = random.nextInt(MAX_VALUE);
}
}
//рисуем слово
int xDis = 10 + random.nextInt(100);
int yDis = 10 + random.nextInt(100);
int[][] pixselArray = stringToPixelArray(textArray.get(random.nextInt(textArray.size())));
for (int i = 0; i < pixselArray.length; i++) {
for (int j = 0; j < pixselArray[i].length; j++) {
try {
if (pixselArray[i][j] > 32) {
dots[i + xDis][j + yDis] = pixselArray[i][j] * 50;
}
} catch (IndexOutOfBoundsException e) {
//do nothing if screen border reached
}
}
}
}

/**
* Возвращает массив значений точек, соответствующий заданному тексту
*/
private int[][] stringToPixelArray(String text) {
int width = 100;
int height = 15;
int[][] result = new int[width][height];
//рисуем текст на картинке
Image image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics gr = image.getGraphics();
gr.setFont(FONT_TEXT);
gr.setColor(Color.BLACK);
gr.fillRect(0, 0, width, height);
gr.setColor(Color.WHITE);
gr.drawString(text, 1, 11);
//используем pixelgrabber для преобразования картинки в массив пикселей
int[] pixels = new int[width * height];
PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width);
try {
pixelGrabber.grabPixels();
} catch (InterruptedException e) {
e.printStackTrace();
}
ColorModel colorModel = pixelGrabber.getColorModel();
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//берём среднее значение по трём компонентам в каждой точке
result[i][j] = (colorModel.getRed(pixels[i + j * width]) + colorModel.getGreen(pixels[i + j * width]) + colorModel.getBlue(pixels[i + j * width])) / 3;
}
}
return result;
}

/**
* Все точки становятся не затронутыми
*/
private void resetFlagsArray() {
for (int i = 0; i < flags.length; i++) {
for (int j = 0; j < flags[i].length; j++) {
flags[i][j] = false;
}
}
}

/**
* Тут значения для каждой точки уменьшаются в соответствии с getDecrease
*/
private void processDots() {
for (int i = 0; i < dots.length; i++) {
for (int j = 0; j < dots[i].length; j++) {
dots[i][j] = dots[i][j] - getDecrease(i, j);
}
}
}

/**
* Возвращает значение от 0 до 255
*/
private int getColorValue(int value) {
int result = value;
if (result < 0) {
result = 0;
} else if (result > 255) {
result = 255;
}
return result;
}

/**
* Если значение какой-либо из окружающих точек становится меньше MIN_VALUE,
* текущая точка помечается как затронутая и её значение начинает уменьшаться (см. isDecreased(int x, int y))
*/
private int getDecrease(int x, int y) {
int result = 0;
boolean isDecr = false;
if (flags[x][y]) {
result += (DECREASE_COUNT + random.nextInt(RANDOM_DECREASE)); // + some random here =)
isDecr = true;
}
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
if (isDecreased(x + i, y + j)) {
isDecr = true;
result += DECREASE_COUNT;
}
}
}
if (isDecr) {
flags[x][y] = true;
}
return result;
}

/**
* Проверяет, нужно ли уменьшать значение точки
*/
private boolean isDecreased(int x, int y) {
boolean result = false;
try {
if (flags[x][y] && dots[x][y] < MIN_VALUE) {
result = true;
}
} catch (IndexOutOfBoundsException e) {
//if out of bounds just return false
}
return result;
}

/**
* Для двойной буферизации
*/
public void paint(Graphics g) {
update(g);
}

/**
* Рисуем всё на картинке, которую потом рисуем на канвасе
*/
public void update(Graphics graphics) {
if (dbImage == null) {
dbImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
g = dbImage.getGraphics();
} else {
g.setColor(COLOR_BACKGROUND);
g.fillRect(0, 0, getWidth(), getHeight());
}
//рисуем точки
for (int i = 0; i < dots.length; i++) {
for (int j = 0; j < dots[i].length; j++) {
int value = getColorValue(dots[i][j]);
if (flags[i][j]) {
g.setColor(new Color(value, value, value));
} else {
g.setColor(COLOR_FOREGROUND);
}
g.fillRect(i * SCALE, j * SCALE, SCALE, SCALE);
}
}
//рисуем сообщение
if(showMessage){
g.setColor(COLOR_MESSAGE);
g.setFont(FONT_MESSAGE);
g.drawString("Click..", 50, 70);
}
//рисуем кнопку перезапуска
g.setColor(COLOR_RESTART_BUTTON_BACKGROUND);
g.fillRect(restartButtonXPos, restartButtonYPos, restartButtonSize, restartButtonSize);
g.setColor(COLOR_RESTART_BUTTON_FOREGROUND);
g.drawRect(restartButtonXPos, restartButtonYPos, restartButtonSize, restartButtonSize);
//двойной буфер
graphics.drawImage(dbImage, 0, 0, this);

}

public void mouseClicked(MouseEvent e) {

}

public void mousePressed(MouseEvent e) {

}

public void mouseReleased(MouseEvent e) {
//если попали в кнопку рестарта
if (e.getX() > restartButtonXPos &&
e.getX() < restartButtonXPos + restartButtonSize &&
e.getY() > restartButtonYPos &&
e.getY() < restartButtonYPos + restartButtonSize) {
resetDotsArray();
resetFlagsArray();
} else {
try {
//точку, в которую попали, помечаем как затронутую - её значение начинает уменьшатся
flags[e.getX() / SCALE][e.getY() / SCALE] = true;
} catch (IndexOutOfBoundsException ex) {
//nothing
}
}
}

public void mouseEntered(MouseEvent e) {
//показываем кнопку рестарта, если указатель над апплетом
restartButtonXPos = 5;
restartButtonYPos = 5;
//убираем сообщение Click..
showMessage = false;
}

public void mouseExited(MouseEvent e) {
//когда указатель мышки покинул пределы апплета, прячем кнопку рестарта за экран
restartButtonXPos = -20;
restartButtonYPos = -20;
}

public void mouseDragged(MouseEvent e) {
mouseReleased(e);
}

public void mouseMoved(MouseEvent e) {

}
}


Исходники обработаны с помощью blogsource

Комментариев нет: