Home>戻る

〜第三章 簡単なアニメーション〜


ボールが動いています。今回はこれを作ってみましょう。

まず、ボールの情報をいろいろ定義する必要があります。
今回は、ボールがグルグル回るというプログラムを作るので、それらに必要な変数の分だけ宣言をしましょう。
ボールの画像、現在の位置、速さ、大きさ、移動方向です。
   Image ball_image;//ボールイメージ
   float ball_px,ball_py;//ボール座標
   float ball_speed;//ボールの速度
   int ball_size;//ボールの一辺のサイズ(ドット)
   int ball_dir;//ボールの移動方向(上=1,下=2,左=3,右=4)
ここでボールの座標、速度はfloat型で宣言しています。
float型では、細かい動きをすることが出来るので使用しています。(後に詳しく解説)
画像を表示する時は、整数の位置で指定するのでint型でキャストして使います。
      //ボール表示
      bufferg.drawImage(ball_image,(int)ball_px,(int)ball_py,this);

表示させるのはこの部分だけですので、次にボールを動かす処理を考えてみましょう。
      ball_px += FrameTime * ball_speed;
この部分ではボールを右へ動かしています。
FrameTimeという変数は、1フレームあたりの秒数です。
1フレームとは、ゲームループの1ループ分を表します。
つまり、
         //ここがゲームループ
         while(true){
            action();//処理
            input_key();//キー入力
            repaint();//再描画

            //ちょっと休憩(0.01秒)
            Thread.sleep(10);
         }
この場合だと、action();、input_key();、repaint();、Thread.sleep(10); の4つの処理で1フレームで、それらの処理時間の合計がフレーム時間(FrameTime)です。
1フレームが0.1秒だとすると、1秒間で10ループ処理されるということです。

ではこの場合。
      ball_px += FrameTime * ball_speed;
仮にFrameTimeは0.2(秒)とします。
そしてball_speedは10としましょう。
ボールは0.2×10で2ドット移動します。これは1フレームで2ドット移動するということです。
では1秒間に何ドット移動するのでしょうか?
0.2秒で1フレームだから、1秒で5フレームです。
そしてボールは1フレームで2ドット移動するから5フレームだと10ドット移動します。
これはball_speedの値そのものです。
ball_speedが20だとすると、1秒間で20ドット移動する事になります。
FrameTimeの使い方が分かりましたでしょうか? これからアニメーションや移動の処理で使っていきます。

ちなみにこのようにFrameTimeを使用したやり方を「変動フレーム」といいます。
距離=時間×速度という計算を用いているので、ゲームが滑らかになります。
対するのは固定フレームです。こちらは処理に時間がかかった場合に、もたつきや処理落ちしてしまいます。
私は変動フレームで組む方法をとっています。まぁ入門がそっちだったので^^;

では完成されたプログラムを公開します。


Rpg03.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// RPG03 第三章 簡単なアニメーション
// 2004/07/10

import java.awt.*;
import java.applet.*;

public class Rpg03 extends Applet implements Runnable{
   Image buffer;//イメージバッファ
   Graphics bufferg;//バックバッファ

   float FrameTime;//1フレームあたりの時間(秒)
   long waitTime;//現在時刻保存用

   Image ball_image;//ボールイメージ
   float ball_px,ball_py;//ボール座標
   float ball_speed;//ボールの速度
   int ball_size;//ボールの一辺のサイズ(ドット)
   int ball_dir;//ボールの移動方向(上=1,下=2,左=3,右=4)

   //初期化
   public void init(){
      Thread t;
      MediaTracker mediaT = new MediaTracker(this);

      //ボール画像ロード
      ball_image = getImage(getDocumentBase(),"chara13.gif");
      mediaT.addImage(ball_image,0);

      //ロード待ち
      try{
         mediaT.waitForAll();
      }catch(InterruptedException e){}

      //ボールの初期座標
      ball_px = 20.0f;
      ball_py = 20.0f;
      
      ball_speed = 50;//ボールの速度。1秒で50ドット。
      ball_size = 32;//ボールの一辺のサイズ(ドット)
      ball_dir = 4;//最初は右に動く
      
      //現在時刻保存
      waitTime=System.currentTimeMillis();

      //スレッドを開始する
      t = new Thread(this);
      t.start();

      //バッファを作成する
      Dimension d = getSize();
      buffer = createImage(d.width,d.height);
   }

   //実行
   public void run(){
      try{
         //ここがゲームループ
         while(true){
            //1フレーム時間計算(秒)
            FrameTime = ( System.currentTimeMillis()-waitTime ) /1000.0f;
            waitTime = System.currentTimeMillis();

            action();//処理
            repaint();//描画

            //ちょっと休憩(0.01秒)
            Thread.sleep(10);
         }
      }
      catch(Exception e){
      }
   }
   
   //描画更新
   public void update(Graphics g){
      paint(g);
   }

   //描画
   public void paint(Graphics g){
      //バッファのグラフィックコンテキストを取得する
      if(bufferg == null){
         bufferg = buffer.getGraphics();
      }
      
      //バッファを描画する
      Dimension d = getSize();
      bufferg.setColor(Color.white);
      bufferg.fillRect(0,0,d.width,d.height);

      //ボール表示
      bufferg.drawImage(ball_image,(int)ball_px,(int)ball_py,this);

      //フォント
      bufferg.setColor(Color.black);
      bufferg.drawString("動いてるよー。現在の座標は(" +(int)ball_px+ "," +(int)ball_py+ ")。",20,20);
      //ウインドウを更新する
      g.drawImage(buffer,0,0,this);
   }


   //処理
   public void action(){
      Dimension d = getSize();

      //ボールをグルグル移動させる
      switch(ball_dir){
      //上
      case 1:
         ball_py -= FrameTime * ball_speed;
         //上端まで来ると、方向を右に変える
         if(ball_py < 0){
            ball_py = 0;
            ball_dir = 4;
         }
         break;
      //下
      case 2:
         ball_py += FrameTime * ball_speed;
         //下端まで来ると、方向を左に変える
         if(ball_py > d.height-ball_size){
            ball_py = d.height-ball_size;
            ball_dir = 3;
         }
         break;
      //左
      case 3:
         ball_px -= FrameTime * ball_speed;
         //左端まで来ると、方向を上に変える
         if(ball_px < 0){
            ball_px = 0;
            ball_dir = 1;
         }
         break;
      //右
      case 4:
         ball_px += FrameTime * ball_speed;
         //右端まで来ると、方向を下に変える
         if(ball_px > d.width-ball_size){
            ball_px = d.width-ball_size;
            ball_dir = 2;
         }
         break;
      }
   }
}