プロ2 > 資料 > 第6章
第6回:アニメーションとゲーム
目標
- アニメーションの原理が理解できる.
- タイマーが利用できる.
5.1 アニメーションの原理
- アニメーション(animation:動画)の原理は「少しずつ変化する絵を短い時間間隔で次々に見せる」ことである.コンピュータでは「少しずつ変化する絵を生成し,短い時間間隔で次々に表示する」ことで実現できる.これを実時間アニメーション(real-time animation)と呼ぶ.
- javax.swing.Timerオブジェクトを用いると,一定の時間間隔である動作を繰り返し実行することが可能である.オブジェクトの開始はstart()メソッドを用いる.
new javax.swing.Timer(50,動作).start();
- 動作として渡すオブジェクトはActionListenerインタフェースを実装するオブジェクトのactionPerformed()メソッドとして記述する.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class Sample61 extends JPanel {
ArrayList<Figure> figs = new ArrayList<Figure>();
Circle c1 = new Circle(Color.BLUE, 100, 100, 30);
Text t1 = new Text(20, 40, "?", new Font("serif", Font.BOLD, 36));
public Sample61() {
setOpaque(false);
figs.add(t1);
figs.add(c1);
final long tm0 = System.currentTimeMillis();
new javax.swing.Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
double tm = 0.001 * (System.currentTimeMillis() - tm0);
t1.setText(String.format("%4.2f", tm));
c1.moveTo(20 + (int) (tm * 100) % 250, 100);
repaint();
}
}).start();
}
public void paintComponent(Graphics g) {
for (Figure f : figs) {
f.draw(g);
}
}
public static void main(String[] args) {
JFrame app = new JFrame();
app.add(new Sample61());
app.setSize(400, 300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
interface Figure {
public void draw(Graphics g);
}
static class Circle implements Figure {
Color col;
int xpos, ypos, rad;
public Circle(Color c, int x, int y, int r) {
col = c;
xpos = x;
ypos = y;
rad = r;
}
public boolean hit(int x, int y) {
return (xpos - x) * (xpos - x) + (ypos - y) * (ypos - y) <= rad
* rad;
}
public void setColor(Color c) {
col = c;
}
public void moveTo(int x, int y) {
xpos = x;
ypos = y;
}
public void draw(Graphics g) {
g.setColor(col);
g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2);
}
}
static class Text implements Figure {
int xpos, ypos;
String txt;
Font fn;
public Text(int x, int y, String t, Font f) {
xpos = x;
ypos = y;
txt = t;
fn = f;
}
public void setText(String t) {
txt = t;
}
public void draw(Graphics g) {
g.setColor(Color.BLACK);
g.setFont(fn);
g.drawString(txt, xpos, ypos);
}
}
}
6.2 人間の情報処理能力とゲーム
- 移動する青い円GameCircleを5個生成する.ybaseは原点のy座標で100に設定される.
- 時計をtmに設定する.40秒経つとゲームが終了する.
- 円が移動するまでの時間をランダムにtmcに設定する.
- tmcで設定した時間が過ぎると(tm>=tmcになると),移動させる円をランダムに選択し,赤にして移動開始する.tmcには次の円が移動するまでの時間をランダムに設定する.
- GameCircleはstart()メソッドにより,mcountが20に設定され,移動を開始する.
- proceed()メソッドでmcountが0より大きい場合に,1ずつ減少するようになっている.mcountが10になると跳ね返るようになっている.原点にもどるとmcountは0になり,円の色は青になり,停止する.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class Ex62def extends JPanel {
ArrayList<Figure> figs = new ArrayList<Figure>();
Font fn = new Font("Serif", Font.BOLD, 36);
Text t1 = new Text(20, 30, "Click when red", fn);
Text t2 = new Text(20, 60, "0", fn);
GameCircle[] a = new GameCircle[5];
int count;
public Ex62def() {
setOpaque(false);
figs.add(t1);
figs.add(t2);
for (int i = 0; i < 5; ++i) {
a[i] = new GameCircle(Color.BLUE, 50 + 50 * i, 100, 20);
figs.add(a[i]);
}
count = 0;
final long tm0 = System.currentTimeMillis();
new javax.swing.Timer(30, new ActionListener() {
double tmc = 10.0 + 3.0 * Math.random();
double tm = 0.0;
public void actionPerformed(ActionEvent evt) {
if (tm >= 40.0) {
return;
}
tm = 0.001 * (System.currentTimeMillis() - tm0);
if (tm >= tmc) {
tmc = tm + (40.0 - tm) * 0.1 * Math.random();
int i = (int) (a.length * Math.random());
if (a[i].getColor() != Color.RED) {
a[i].setColor(Color.RED);
a[i].start();
}
}
for (GameCircle c1 : a) {
c1.proceed();
}
t1.setText(String.format("%2.2f", 40.0 - tm));
repaint();
}
}).start();
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
for (GameCircle c1 : a) {
if (c1.getColor() == Color.RED
&& c1.hit(evt.getX(), evt.getY())) {
c1.setColor(Color.BLUE);
++count;
t2.setText(String.format("%d", count));
}
}
}
});
}
public void paintComponent(Graphics g) {
for (Figure f : figs) {
f.draw(g);
}
}
public static void main(String[] args) {
JFrame app = new JFrame();
app.add(new Ex62def());
app.setSize(400, 300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
interface Figure {
public void draw(Graphics g);
}
static class Circle implements Figure {
Color col;
int xpos, ypos, rad;
public Circle(Color c, int x, int y, int r) {
col = c;
xpos = x;
ypos = y;
rad = r;
}
public boolean hit(int x, int y) {
return (xpos - x) * (xpos - x) + (ypos - y) * (ypos - y) <= rad
* rad;
}
public void setColor(Color c) {
col = c;
}
public void moveTo(int x, int y) {
xpos = x;
ypos = y;
}
public void draw(Graphics g) {
g.setColor(col);
g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2);
}
}
static class GameCircle extends Circle {
int ybase, mcount;
public GameCircle(Color c, int x, int y, int r) {
super(c, x, y, r);
ybase = y;
mcount = 0;
}
public Color getColor() {
return col;
}
public void start() {
mcount = 20;
}
public void proceed() {
if (mcount <= 0) {
return;
}
mcount -= 1;
ypos = ybase + 100 - Math.abs(mcount - 10) * 10;
if (mcount == 0) {
col = Color.BLUE;
}
}
}
static class Text implements Figure {
int xpos, ypos;
String txt;
Font fn;
public Text(int x, int y, String t, Font f) {
xpos = x;
ypos = y;
txt = t;
fn = f;
}
public void setText(String t) {
txt = t;
}
public void draw(Graphics g) {
g.setColor(Color.BLACK);
g.setFont(fn);
g.drawString(txt, xpos, ypos);
}
}
}
ykitamura@kwansei.ac.jp