2007年12月21日金曜日

時計の表示

時計を表示します。
package {
import flash.display.Sprite;
import flash.display.Shape;
import flash.text.TextField;

public class ClockSample extends Sprite {
// 表示用スプライト
private var child:Sprite;

/**
* コンストラクタ */
public function ClockSample() {
// 文字盤を作る
makeBoard();

// 時計の針をつくる
makeNeedles();
}
/**
* 文字盤を作る */
private function makeBoard():void {
child = new Sprite();
child.graphics.beginFill(0xFFFFFF);
child.graphics.drawRect(-200, -200, 400, 400);
child.graphics.endFill();
child.x = this.stage.stageWidth / 2;
child.y = this.stage.stageHeight / 2;
this.addChild(child);

var i:int;
for(i=1;i<=12;i++) {
var number:Shape = new Shape();
var angle:Number = Math.PI * i / 6.0;
number.graphics.beginFill(0xCCCCCC);
number.graphics.drawRect(-10,-10,20,20);
number.graphics.endFill();
number.x = (child.width * Math.sin(angle)*0.8) * 0.5;
number.y = (child.height * -Math.cos(angle)*0.8) * 0.5;
child.addChild(number);
}
}
/**
* 針を作る */
private function makeNeedles():void {
child.addChild(new NeedleSec());
child.addChild(new NeedleMin());
child.addChild(new NeedleHour());
}
}
}

import flash.display.Shape;
import flash.events.Event;

/**
* 針の基本クラス */
internal class Needle extends Shape
{
public function Needle(length:uint, width:uint, color:uint) {
this.graphics.beginFill(color);
this.graphics.drawRoundRect(-width, -length, width*2, length, width, width);
this.graphics.endFill();
this.x = 0;
this.y = 0;
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
move();
}
public function onEnterFrame(event:Event):void {
move();
}
public function move():void {}
}
/**
* 時間を指し示す針のクラス */
internal class NeedleHour extends Needle {
public function NeedleHour() {
super(60, 3, 0xFF0000);
}
override public function move():void {
var now:Date = new Date();
this.rotation = (now.hours + now.minutes/60) * 30;
}
}
/**
* 分を指し示す針のクラス */
internal class NeedleMin extends Needle {
public function NeedleMin() {
super(100, 2, 0xFF8000);
}
override public function move():void {
var now:Date = new Date();
this.rotation = now.minutes * 6;
}
}
/**
* 秒を指し示す針のクラス */
internal class NeedleSec extends Needle {
public function NeedleSec() {
super(105, 1, 0x000000);
}
override public function move():void {
var now:Date = new Date();
this.rotation = now.seconds * 6;
}
}

2007年12月8日土曜日

相互作用が働く粒子の運動

相互作用が働く粒子の運動2のJava移植版。アプレットはこちらです。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;

public class HSPAtom extends JApplet implements Runnable, MouseListener {
private Vector<Particle> particles = new Vector<Particle>();
private float h = 0.0f;
private final int NUM_MEMBERS = 12;
private MyPanel panel;
private Random random = new Random();

/**
* アプレットの初期化
*/
public void init() {
panel = new MyPanel();
add(panel, BorderLayout.CENTER);
makeParticles();
addMouseListener(this);

Thread thread = new Thread(this);
thread.start();
}

/**
* スレッド
*/
public void run() {
Rectangle rect = new Rectangle(getSize());
while(true) {
try {
Enumeration<Particle> e = particles.elements();
while(e.hasMoreElements()) {
Particle particle = e.nextElement();
particle.move(particles, rect);
}
panel.repaint();
Thread.sleep(40);
} catch(Exception e) {

}
}
}

/**
* 粒子を全消去し、新たに一定数の粒子を作成する
* 粒子の色も変更される
*/
private void makeParticles() {
h = random.nextFloat();
particles.clear();
Dimension size = getSize();
for(int i=0; i<NUM_MEMBERS; i++) {
Particle particle = new Particle(
random.nextDouble() * size.width,
random.nextDouble() * size.height);
particles.add(particle);
}
}
public void mouseClicked(final MouseEvent event) {
if(javax.swing.SwingUtilities.isRightMouseButton(event)){
// 右クリックの場合 - 粒子を作成し直す
makeParticles();
} else if(javax.swing.SwingUtilities.isLeftMouseButton(event)){
// 左クリックの場合 - 粒子を追加する
Particle particle = new Particle(
event.getX(), event.getY());
particles.add(particle);
}
}
public void mouseEntered(final MouseEvent event) {}
public void mouseExited(final MouseEvent event) {}
public void mousePressed(final MouseEvent event) {}
public void mouseReleased(final MouseEvent event) {}

/**
* オリジナルのパネル
*/
private class MyPanel extends JPanel{
public void paintComponent(final Graphics g) {
Dimension size = getSize();
Graphics2D g2d = (Graphics2D)g;

// 画面の消去
g.setColor(Color.black);
g.fillRect(0, 0, size.width, size.height);

// 粒子の描画
g2d.setColor(Color.getHSBColor(h, 1.0f, 1.0f));
Enumeration<Particle> e = particles.elements();
while(e.hasMoreElements()) {
Particle particle = e.nextElement();
g2d.fill(particle);
}
}
}
/**
* 粒子を表すクラス
* Ellipse2D.Doubleを拡張し、Graphics2Dのfillメソッドを利用できるようにした
*/
private class Particle extends Ellipse2D.Double {
private double veloX, veloY;
private static final int
RADIUS = 5,
PARTY_DIST = 120;
/**
* コンストラクタ
* @param x 粒子の位置(X座標)
* @param y 粒子の位置(Y座標)
*/
private Particle(double x, double y) {
super(x, y, RADIUS * 2, RADIUS * 2);
}
/**
* 速度計算と移動を同時に行う(厳密には別々に行うべき)
* @param party 自分自身を含むすべての粒子が代入されているVector
* @param size 行動範囲の広さ
*/
private void move(final Vector<Particle> party, final Rectangle area) {
double ax = 0.0, ay = 0.0;
Enumeration<Particle> e = party.elements();
while(e.hasMoreElements()) {
Particle target = e.nextElement();
if(!target.equals(this)) {
double
distance = Math.sqrt(
Math.pow(x - target.x, 2)
+ Math.pow(y - target.y, 2)),
theta = Math.atan2(target.y - y, target.x - x),
speed = Math.abs(distance - PARTY_DIST) * (distance - PARTY_DIST) / 5000;

ax += speed * Math.cos(theta);
ay += speed * Math.sin(theta);
}
}
veloX = 0.9 * (veloX + ax);
veloY = 0.9 * (veloY + ay);

this.x = limit(this.x + veloX, area.x + RADIUS, area.x + area.width - RADIUS);
this.y = limit(this.y + veloY, area.y + RADIUS, area.y + area.height - RADIUS);
}
}
/**
* HSPのlimit関数と同じ
*/
private static double limit(final double value, final double min, final double max) {
return Math.max(min, Math.min(value, max));
}
}