Programming II Report#6

 ProgramingII Report#5 <- TOP


課題内容

~ 目次 ~

  1. 1-1. 入力ソース
  2. 1-2. 実行結果
  3. 感想

1.

1-1.入力ソース


import java.applet.*;
import java.awt.*;
import java.awt.event.*;
  
 public class Caveman extends Applet implements Runnable, MouseListener, KeyListener{
      Thread t;          
      Image buffer;
      Graphics bufferg;

     Font normal = new Font("SansSerif", Font.BOLD, 16); // フォントのオブジェクトを生成
     Font small = new Font("Serif", Font.PLAIN, 12);
     Font big = new Font("Serif", Font.BOLD, 36);
     Font stress = new Font("SansSerif",Font.BOLD, 20);
     
     boolean start = false;            // ゲームスタートしたかどうか
     boolean col = false;              // 衝突したかどうか
     boolean over= false;              // ゲームオーバーしたかどうか
     Block b = new Block();            // ブロック生成
     Jiki j[] = new Jiki[5];           // 自機を宣言
     int score = 0;                    // 点数、及び開始からの時間 
     int top = 20;                     // 上下の幅
     int bottom;
     int margin = 5;                   // タイトル画面での枠幅
     int x[] = { 20, 15, 10, 5, 0 };   // 各自機の初期座標
     int y[] = { 40, 35, 40, 45, 50 };
     int highscore = 0;                // ハイスコアを保存
     int winWidth, winHeight;          // ウインドウの幅と高さ
     public void init() {
             
             setFont(normal); // フォントを設定
             
             // 自機を生成
             for(int a = 0; a < 5; a++){
                     j[a] = new Jiki(x[a],y[a]);
             }
             addMouseListener(this);
             addKeyListener(this);
             requestFocus();
             
             // スレッドを開始
             t = new Thread(this);
             t.start();
              
             // アプレットサイズの取得
             Dimension d = getSize();
             winWidth = d.width;
             winHeight = d.height;
             bottom = winHeight - 75;
             
             // バッファを作成
             buffer = createImage(winWidth, winHeight);
     }
     
     public void run(){
             try{
                     while(true) {
                             
                             // ゲーム中で、衝突してない状態
                             if(start && !col){
                                             
                                             // 自機の現在の座標を記録
                                             for(int a = 0; a < 4; a++){
                                                     j[a].log_y = j[a].y;
                                             }
                                             
                                             // 後続の自機に座標を伝える
                                             for(int a = 0; a < 4; a++){
                                                     j[a+1].y = j[a].log_y;
                                             }
                                             
                                             j[0].move(); // 先頭の自機を動かす
                                     
                                             // ブロックを生成するかどうか
                                             if(b.time > 9){
                                                     b.newBlock = true;
                                                     b.time = 0;
                                             }
                                             // ブロックを生成する処理
                                             if(b.newBlock){
                                                     if(b.num == 255){ b.num = 0; }
                                                     b.x[b.num] = 190;
                                                     b.y[b.num] = b.topLimit + (int)(Math.random() * b.bottomLimit);
                                                     b.num++;
                                                     b.newBlock = false;
                                             }
                                             
                                             b.time++;    // ブロックを生成してからの時間を更新
                                             score++;     // スコアを更新
                                             
                                             // ブロックの移動
                                             for(int a = 0; a < b.num; a++){
                                                     b.x[a] -= 5;
                                             }
                                             
                                             // 地面と天井を動かす処理
                                             if(score % 10 == 0){
                                                     if(score > 100 && score < 500 || score > 700 && score < 900){
                                                             top++;
                                                             bottom--;
                                                            b.topLimit++;
                                                            b.bottomLimit--;
                                                    }
                                            }
                            
                                    
                                            // 衝突を判定
                                            if(b.num < 9){ // 最初に描画されたブロックが画面端に届いてない場合
                                                    for(int a = 0; a < b.num; a++){
                                                    
                                                            // ブロックとの衝突を判定
                                                            if(( j[0].x+5 >= b.x[a]  && j[0].x <= b.x[a] + b.width) 
                                                                            && (j[0].y+5 >= b.y[a]  && j[0].y <= b.y[a] + b.height)){
                                                                    col = true;
                                                            }
                                                            
                                                            // 天井、地面との衝突を判定
                                                            else if( j[0].y <= top-1 || j[0].y + 5 >= bottom+1){
                                                                    col = true;
                                                            }
                                                    }
                                            }else{ // 最初に描画されたブロックが画面端に届いた場合
                                                    for(int a = b.num-8; a < b.num; a++){
                                                    
                                                            // ブロックとの衝突を判定
                                                            if(( j[0].x+5 >= b.x[a] && j[0].x <= b.x[a] + b.width) 
                                                                            && (j[0].y+5 >= b.y[a] && j[0].y <= b.y[a] + b.height)){
                                                                    col = true;
                                                            }
                                                            
                                                            // 天井、地面との衝突を判定
                                                            else if( j[0].y <= top-1 || j[0].y + 5 >= bottom+1){
                                                                    col = true;
                                                            }
                                                    }
                                            }
                                    }
                            
                            repaint();         // 再描画
                            Thread.sleep(100); // ウィンドウを更新する前に休止
                    }
            }
            catch(Exception e){
            }
    }
    
    public void update(Graphics g){
            paint(g);
    }
    
    public void paint(Graphics g){
            
            // バッファのグラフィックコンテキストを取得
            if(bufferg == null){
                    bufferg = buffer.getGraphics();
            }
            
            // タイトル画面での描画
            if(!start){
                    
                    // 全体を塗りつぶす
                    bufferg.setColor(Color.black);
                    bufferg.fillRect(0, 0, winWidth, winHeight);
                    
                    // 枠内を描画
                    bufferg.setColor(Color.blue);
                    bufferg.fillRect(margin ,margin ,winWidth - (margin*2), winHeight - (margin*2));
                    
                    // タイトル等の文字を描画
                    bufferg.setColor(Color.white);
                    bufferg.setFont(big);
                    bufferg.drawString("Caveman", 20, 50);

                    bufferg.setFont(small);
                    bufferg.drawString("UP/click!", 40, 80);
                    bufferg.drawString("Doun/newtral", 40, 100);                    
                                       
                    bufferg.setFont(normal);
                    bufferg.drawString("HISCORE: " + highscore, 40, 160);
                    bufferg.drawString("SCORE  : " + score, 40, 130);
                    
                    bufferg.setFont(stress);
                    bufferg.drawString("Click to Start!", 40, 200);
            
            }else{
            
                    // ゲーム中の描画
                    if(!over){
                    
                            // 全体を塗りつぶす
                            bufferg.setColor(Color.black);
                            bufferg.fillRect(0, 0, winWidth, winHeight);
                            
                            // 自機を描画
                            bufferg.setColor(Color.blue);
                            for(int a = 0; a < 5; a++){
                            bufferg.fillRect(j[a].x, j[a].y, 5, 5);                            }
                    
                            // ブロックの描画
                            bufferg.setColor(Color.green);
                            if(b.num < 9){
                                    for(int a = 0; a < b.num; a++){
                                            bufferg.fillRect(b.x[a], b.y[a], b.width, b.height);
                                    }
                            }else{
                                    for(int a = b.num-8; a < b.num; a++){
                                            bufferg.fillRect(b.x[a], b.y[a], b.width, b.height);
                                    }
                            }
                            
                            // 天井と壁を描画
                            bufferg.setColor(Color.green);
                            bufferg.fillRect(0, 0, 200, top);
                            bufferg.fillRect(0, bottom, winWidth, 200);
                            bufferg.setColor(Color.green);
                            bufferg.drawLine(0, top, winWidth, top);
                            bufferg.drawLine(0, bottom, winWidth, bottom);
                            
                            // スコアを描画
                            bufferg.setFont(normal);
                            bufferg.setColor(Color.white);
                            bufferg.drawString("SCORE: " + score, 50, 190);
                            bufferg.drawString("Click: UP" , 50, 210);
                    }
            
                    // ゲームオーバー時の描画
                    if(col){
                    
                            // ゲームオーバー時の各文字列を描画
                            bufferg.setFont(normal);
                            bufferg.setColor(Color.red);
                            bufferg.drawString("GAME OVER" , 50, 100);
                            highscore = Math.max(highscore,score);
                            bufferg.drawString("HIGHSCORE: " + highscore, 40, 140);
                            bufferg.setColor(Color.white);
                            bufferg.drawString("Push enter key", 30, 230);
                            
                            // ゲームオーバー
                            over = true;
                    }
            }
            // ウインドウを更新
            g.drawImage(buffer, 0, 0, this);
            
    }
    
    public void mouseClicked(MouseEvent ev){
            
            // ゲームスタート
            if(!start){
                    start = true;
                    score = 0;
            }
    }
    
    public void mouseEntered(MouseEvent ev){
    }
    
    public void mouseExited(MouseEvent ev){
    }
    
    public void mousePressed(MouseEvent ev){
            
            // 自機を上昇させる
            if(!over){
                    for(int a = 0; a < 5; a++){
                            j[a].up = true;
                            j[a].time = 1;
                    }
            }
    }
    
    public void mouseReleased(MouseEvent me){
            
            // 自機を下降させる
            if(!over){
                    for(int a = 0; a < 5; a++){
                            j[a].up = false;
                            j[a].time = 1;
                    }
            }               
    }
    
    public void keyPressed(KeyEvent ke){
    }
    
    public void keyReleased(KeyEvent ke) {
            
            // 押したキーの値を取得
            int key = ke.getKeyCode();
 
            // ゲームオーバー時の処理
            if(over){
                    switch(key){
                    case KeyEvent.VK_ENTER:
                            col = false;
                            over = false;
                            top = 20; bottom = 175;
                            
                            // 自機の再初期化
                            for(int a = 0; a < 5; a++){
                                    j[a].jikiInit();
                            }
                            // ブロックの再初期化
                            b.blockInit();
                            start = false;
                            break;
                    }
            }
    }
    
    public void keyTyped(KeyEvent ke) {
    }
   
    // プレイヤーが操作する物体のクラス
    class Jiki{
    
            int x, y;             // 現在の座標
            int log_x, log_y;     // 座標のログ
            int time;             // 上昇、下降してからの経過時間
            int x_first, y_first; // 座標の初期値
            float gravity;        // 天井と壁への引力
            boolean up;           // マウスがクリックされてるかどうか
            int vy_up, vy_down;   // 上昇、下降時の速度
            
            Jiki(int x, int y){          // コンストラクタ
                    this.x = x; this.y = y;
                    time = 1;
                    gravity = 0.5f;
                    x_first = x; y_first = y;
                    log_x = 0; log_y = 0;
                    up = false;
                    vy_up = 0; vy_down = 0;
                    gravity = 0.5f;
            }
            
            // マウスがクリックされてるかどうかで上昇、下降のどちらかを行う
            void move(){
                    if(!up){
                            y += ((int)(time * time * gravity / 4)) + vy_up + 1;
                            vy_down = (int)(time * gravity);
                    }else if(up){
                            y -= ((int)(time * time * gravity / 4)) - vy_down - 1;
                            vy_up = -(int)(time * gravity);
                    }
                    
                    // 上昇、下降してからの時間を更新
                    j[0].time++;
            }
            
            // ゲームをリスタートする場合に再初期化する
            void jikiInit(){
                    x = x_first; y = y_first;
                    log_x = 0; log_y = 0;
                    time = 1;
                    up = false;
                    vy_up = 0; vy_down = 0;
            }
    }
 
    // 前面から押し寄せてくるブロックのクラス
    class Block {
            
            int x[] = new int[256];    // ブロックの座標
            int y[] = new int[256];
            int width, height;         // ブロックの幅と高さ
            int topLimit, bottomLimit; // ブロックが出現する高さの上限と下限
            int time;                  // ブロックが出現する時間の間隔
            int num;                   // 生成されたブロックの個数
            boolean newBlock;          // ブロックを新たに出現させるかどうか
            
            Block(){                          // コンストラクタ
                    for(int a = 0; a < 256; a++){
                            x[a] = 0; y[a] = 0;
                    }
                    width = 5; height = 30;
                    topLimit = 20; bottomLimit = 125;
                    time = 0; num = 0;
                    newBlock = false;
            }
    
            // ゲームをリスタートする場合に再初期化する
            public void blockInit(){
                    for(int a = 0; a < num; a++){
                            x[a] = 0; y[a] = 0;
                    }
                    topLimit = 20; bottomLimit = 125;
                    time = 0; num = 0;
                    newBlock = false;
            }
    }
 }
動作はコメント行で書かれている通りである。
1-2. 実行結果





別画面で表示実行結果
2. 感想
ゲームを作るのはとても難しいんだなと思いました。
自分はファミコンをしたことがありますが、あんなの簡単にできるだろ!!と思っていましたが、とっても難しいと思いました。
そして、何を考察するかに悩んでいたところに、昔にはやったCavemanというゲームがありそれを考察することにしました。