<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Java究竟怎么玩?

      天地程序已定棋,人間大數(shù)待變局

        博客園  :: 首頁  :: 新隨筆  :: 聯(lián)系 :: 訂閱 訂閱  :: 管理

      書接前文,事表上回。話說上回書提到“畫面閃爍問題和角色動(dòng)作的變更”是目前我們所面臨的兩大難點(diǎn)之一,本次,將就解決畫面閃爍的前提條件——角色動(dòng)作變更,也即“動(dòng)畫”進(jìn)行較為深入的分析。

      大家都很清楚的知道,所謂的動(dòng)畫,并不是一個(gè)“會(huì)動(dòng)的畫”,而是一組“連續(xù)變動(dòng)的畫”,就好比Flash制作時(shí)的需要憑借“楨”調(diào)節(jié)畫面運(yùn)動(dòng),在Java游戲開發(fā)中一樣要通過類似的方式來控制畫面。

      要實(shí)現(xiàn)這點(diǎn),首先我們需要一組連續(xù)的圖像。

      如下圖:

       

      日常生活中,我們很少會(huì)不知道自己應(yīng)該邁左腳還是邁右腳,但對計(jì)算機(jī)而言,這是我們必須明確提示給他的條件。所以,我們還需要一個(gè)變量充當(dāng)“計(jì)步器”,以明確下步狀態(tài)。

        private int count;

          而要想實(shí)現(xiàn)動(dòng)畫,最重要的一點(diǎn),就是畫面的連續(xù),即多步操作的處理,為此我們使用到了Java中的Thread,也即線程。

        private Thread threadAnime;

       

       Java中,目前不支持如C#式的函數(shù)直接被線程調(diào)用方式。Java要實(shí)現(xiàn)線程,必需要通過繼承Thread類或?qū)崿F(xiàn)Runnable接口。

       

        我們以Thread類的繼承為例:

       

         //內(nèi)部類,用于處理計(jì)步動(dòng)作。

          private class AnimationThread extends Thread {

              public void run() {

                  while (true) {

                      // count計(jì)步

                      if (count == 0) {

                          count = 1;

                      } else if (count == 1) {

                          count = 0;

                      }

                      // 重繪畫面。

                      repaint();

                     

                      // 300毫秒改變一次動(dòng)作。

                      try {

                          Thread.sleep(300);

                      } catch (InterruptedException e) {

                          e.printStackTrace();

                      }

                  }

              }

          }

       

      所謂的繼承,也可以簡單的理解為COPY下所繼承類的全部方法,而這里我們重寫了run()方法,沒有改變其他。也就是說,我們將以自己的方式運(yùn)行AnimationThread這個(gè)類。

         另外,在處理drawRole方法時(shí),我們將其內(nèi)部變更如下:

              //count作為圖像的偏移數(shù)值

        g.drawImage(roleImage, x*CS, y*CS, x*CS+CS, y*CS+CS,

                      count*CS, 0, CS+count*CS, CS, this);

       

        推導(dǎo)公式如下圖:

             

       

        最后,我們在MyPanel構(gòu)建之初即啟動(dòng)線程,令線程的相關(guān)操作活性化。

       

         //實(shí)例化內(nèi)部線程AnimationThread

              threadAnime = new Thread(new AnimationThread());

              //啟動(dòng)線程

              threadAnime.start();

       

      MyPanel代碼如下:

       

      package org.loon.chair.example3;

       

      import java.awt.Dimension;

      import java.awt.Graphics;

      import java.awt.Image;

      import java.awt.event.KeyEvent;

      import java.awt.event.KeyListener;

       

      import javax.swing.ImageIcon;

      import javax.swing.JPanel;

       

      /**

       * Example3中自定義面板,用于描繪底層地圖。

       *

       * @author chenpeng

       *

       * Loon Framework in Game

       *

       * PS:請注意,此處與前例不同,新增鍵盤事件監(jiān)聽

       */

      public class MyPanel extends JPanel implements  KeyListener {

       

          //窗體的寬與高

          private static final int WIDTH = 480;

          private static final int HEIGHT = 480;

       

          //設(shè)定背景方格默認(rèn)行數(shù)

          private static final int ROW = 15;

          //設(shè)定背景方格默認(rèn)列數(shù)

          private static final int COL = 15;

         

          //單個(gè)圖像大小,我默認(rèn)采用32x32圖形,可根據(jù)需要調(diào)整比例。

          //當(dāng)時(shí),始終應(yīng)和窗體大小比例協(xié)調(diào);比如32x32的圖片,如何

          //一行設(shè)置15個(gè),那么就是480,也就是本例子默認(rèn)的窗體大小,

          //當(dāng)然,我們也可以根據(jù)ROW*CS,COl*CS在初始化時(shí)自動(dòng)調(diào)整

          //窗體大小,以后的例子中會(huì)用到類似情況。總之一句話,編程

          //[為目的而存在的],所有的方法,大家都可任意嘗試和使用。

          private static final int CS = 32;

       

          //設(shè)定地圖,通常在rpg類型游戲開發(fā)中,以[二維數(shù)組]對象為

          //基礎(chǔ)進(jìn)行地圖處理,用以描繪出X坐標(biāo)和Y坐標(biāo)。實(shí)際上,即令

          //再華麗的RPG類游戲,都是從這些簡單的X,Y坐標(biāo)開始的。

          //PS:所謂[數(shù)組],大家可以簡單的理解為即數(shù)據(jù)的集合,一維數(shù)組

          //僅包含X軸,而二維是由X,Y兩個(gè)軸組成的,XY的交織點(diǎn),即為

          //一條數(shù)據(jù)。

          private int[][] map = {

              {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

              {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

              {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

              {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

              {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

              {1,0,0,0,0,1,1,1,1,1,0,0,0,0,1},

              {1,0,0,0,0,1,0,0,0,1,0,0,0,0,1},

              {1,0,0,0,0,1,0,0,0,1,0,0,0,0,1},

              {1,0,0,0,0,1,0,0,0,1,0,0,0,0,1},

              {1,0,0,0,0,1,1,0,1,1,0,0,0,0,1},

              {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

              {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

              {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

              {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

              {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};

       

          //設(shè)定顯示圖像對象

          private Image floorImage;

          private Image wallImage;

          //角色

          private Image roleImage;

       

          //角色坐標(biāo)

          private int x, y;

          

          //增加計(jì)步器

          private int count;

       

          //此處我們添加一組常數(shù),用以區(qū)別左右上下按鍵的觸發(fā),

          //之所以采用數(shù)字進(jìn)行區(qū)別,原因大家都很清楚^^,數(shù)字

          //運(yùn)算效率高嘛~

          private static final int LEFT = 0;

          private static final int RIGHT = 1;

          private static final int UP = 2;

          private static final int DOWN = 3;

          private Thread threadAnime;

          public MyPanel() {

              //設(shè)定初始構(gòu)造時(shí)面板大小

              setPreferredSize(new Dimension(WIDTH, HEIGHT));

       

              //于初始化時(shí)載入圖形

              loadImage();

             

              //初始化角色所在位置,由于本例行列皆為15,估xy的極限數(shù)值也皆為15

              //即由15x15的方格圖像,組成了角色的可見活動(dòng)區(qū)域。

              x = 8;

              y = 8;

       

              //在面板構(gòu)建時(shí)賦予計(jì)步器初值

              count = 0;

             

              //設(shè)定焦點(diǎn)在本窗體并付與監(jiān)聽對象

              setFocusable(true);

              addKeyListener(this);

             

              //實(shí)例化內(nèi)部線程AnimationThread

              threadAnime = new Thread(new AnimationThread());

              //啟動(dòng)線程

              threadAnime.start();

          }

       

          //描繪窗體,此處在默認(rèn)JPanel基礎(chǔ)上構(gòu)建底層地圖.

          public void paintComponent(Graphics g) {

              super.paintComponent(g);

       

              //畫出地圖

              drawMap(g);

             

              //畫出人物

              drawRole(g);

          }

       

          /**

           * 載入圖像

           *

           */

          private void loadImage() {

              //獲得當(dāng)前類對應(yīng)的相對位置image文件夾下的地板圖像

             

              ImageIcon icon = new ImageIcon(getClass().getResource("image/floor.gif"));

              //將地板圖像實(shí)例付與floorImage

              floorImage = icon.getImage();

              //獲得當(dāng)前類對應(yīng)的相對位置image文件夾下的墻體圖像

              icon = new ImageIcon(getClass().getResource("image/wall.gif"));

              //將墻體圖像實(shí)例付與wallImage

              wallImage = icon.getImage();

             

              icon = new ImageIcon(getClass().getResource("image/hero.gif"));

              roleImage = icon.getImage();

          }

         

         

          /**

           * 繪制角色

           */

          private void drawRole(Graphics g) {

              //count作為圖像的偏移數(shù)值

              g.drawImage(roleImage, x*CS, y*CS, x*CS+CS, y*CS+CS,

                      count*CS, 0, CS+count*CS, CS, this);

          }

         

          private void drawMap(Graphics g) {

              //Java或任何游戲開發(fā)中,算法都是最重要的一步,本例盡使用

              //簡單的雙層for循環(huán)進(jìn)行地圖描繪,

              for (int x = 0; x < ROW; x++) {

                  for (int j = 0; j < COL; j++) {

                     

                      // switch作為java中的轉(zhuǎn)換器,用于執(zhí)行和()中數(shù)值相等

                      // case操作。請注意,在case操作中如果不以break退出

                      // 執(zhí)行;switch函數(shù)將持續(xù)運(yùn)算到最后一個(gè)case為止。

                      switch (map[x][j]) {

                         

                          case 0 : //map的標(biāo)記為0時(shí)畫出地板

                              //在指定位置[描繪]出我們所加載的圖形,以下同

                              g.drawImage(floorImage, j * CS, x * CS, this);

                              break;

                    

                          case 1 : //map的標(biāo)記為1時(shí)畫出城墻

                              g.drawImage(wallImage, j * CS, x * CS, this);

                              break;

                           //我們可以依次類推出無數(shù)的背景組合,如定義椅子為2、寶座為3

                           //很容易即可勾勒出一張背景地圖。  

                    

                          default: //當(dāng)所有case值皆不匹配時(shí),將執(zhí)行此操作。

                              break;

                      }

                  }

              }

          }

       

          public void keyPressed(KeyEvent e) {

             //獲得按鍵編號

              int keyCode = e.getKeyCode();

             

              //通過轉(zhuǎn)換器匹配事件

              switch (keyCode) {

                  //當(dāng)觸發(fā)Left時(shí)

                  case KeyEvent.VK_LEFT :

                      //進(jìn)行left操作,僅符合move()[規(guī)范]時(shí)執(zhí)行,以下相同

                      move(LEFT);

                      break;

                  //當(dāng)觸發(fā)Right時(shí)     

                  case KeyEvent.VK_RIGHT :

                 

                      move(RIGHT);

                      break;

                  //當(dāng)觸發(fā)Up時(shí)   

                  case KeyEvent.VK_UP :

                     

                      move(UP);

                      break;

                  //當(dāng)觸發(fā)Down時(shí)   

                  case KeyEvent.VK_DOWN :

                    

                      move(DOWN);

                      break;

              }

       

              // 重新繪制窗體圖像

              // PS:在此例程中,僅進(jìn)行了角色的簡單移動(dòng)處理

              // ,關(guān)于避免閃爍及限制活動(dòng)區(qū)域問題,請見后續(xù)

              // 案例。

             

              repaint();

          }

         

          /**

           * 用于判定是否允許移動(dòng)的發(fā)生,被move()函數(shù)調(diào)用

           * @param x

           * @param y

           * @return

           */

          private boolean isAllow(int x, int y) {

              // (x,y)交點(diǎn)進(jìn)行數(shù)據(jù)判定,我們都知道,

              // 在本例中我僅以0作為地板的參數(shù),1作為

              // 墻的參數(shù),由于我們的主角是[人類],而

              // 不是[幽靈],所以當(dāng)他要[撞墻]時(shí),我們

              // 當(dāng)然不會(huì)允許,至少,是我講到劇情的觸發(fā)

              // 以前……

              if (map[y][x] == 1) {

              // 不允許移動(dòng)時(shí),返回[]  

                  return false;

              }

             

              // 允許移動(dòng)時(shí)時(shí),返回[]

              return true;

          }

         

          /**

           * 判斷移動(dòng)事件,關(guān)聯(lián)isAllow()函數(shù)

           * @param event

           */

          private void move(int event) {

              //以轉(zhuǎn)換器判斷相關(guān)事件,僅執(zhí)行符合[規(guī)范]的操作。

              switch (event) {

                  case LEFT:

                      //依次判定事件

                      if (isAllow(x-1, y)) x--;

                      break;

                  case RIGHT:

                      if (isAllow(x+1, y)) x++;

                      break;

                  case UP:

                      if (isAllow(x, y-1)) y--;

                      break;

                  case DOWN:

                      if (isAllow(x, y+1)) y++;

                      break;

                  default:

                      break;

              }

          }

       

          /**

           * 暫無釋放鍵盤事件

           */

          public void keyReleased(KeyEvent e) {

          }

       

          /**

           * 暫無字符輸入事件

           */

          public void keyTyped(KeyEvent e) {

          }

         

         

          //內(nèi)部類,用于處理計(jì)步動(dòng)作。

          private class AnimationThread extends Thread {

              public void run() {

                  while (true) {

                      // count計(jì)步

                      if (count == 0) {

                          count = 1;

                      } else if (count == 1) {

                          count = 0;

                      }

                      // 重繪畫面。

                      repaint();

                     

                      // 300毫秒改變一次動(dòng)作。

                      try {

                          Thread.sleep(300);

                      } catch (InterruptedException e) {

                          e.printStackTrace();

                      }

                  }

              }

          }

      }

       

      如何?只是簡單的基點(diǎn)變更,角色已經(jīng)開始走動(dòng)了。

       

      但是,這種單純的左右走動(dòng)效果實(shí)在不好,并非我們所期望般“華麗”,只能算是邯鄲學(xué)步罷了,下一回,我們將講解較為華麗的走動(dòng)“一步蓮華”。

      什么時(shí)候才下班啊……555555555~~~

       
      posted on 2007-07-17 08:06  cping  閱讀(336)  評論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 中国熟妇毛多多裸交视频| 欧美人成精品网站播放| 亚洲熟少妇一区二区三区| 精品国产成人三级在线观看| 久久99国产精品尤物| 国产精品天干天干综合网| 亚洲国产午夜精品福利| 熟女系列丰满熟妇AV| 国产成人综合网亚洲第一| 日韩高清国产中文字幕| 国产精品一区二区 尿失禁| 国产精品一区中文字幕| 国产成人精品亚洲午夜麻豆| 久久这里只有精品免费首页| 免费无码一区无码东京热| 人妻精品久久无码区| 国产美女自慰在线观看| 国产资源精品中文字幕| 国产亚洲另类无码专区| 国产精品高潮无码毛片| 晋宁县| 亚洲国产精品高清线久久| 成人午夜免费一区二区三区| 亚洲精品国产字幕久久麻豆| 亚洲熟女乱色综合亚洲图片| 国产国产午夜福利视频| 国产精品久久久久9999高清| 国产激情一区二区三区四区| 国产精品天干天干综合网| 大肉大捧一进一出好爽视频动漫| 国产午夜亚洲精品福利| 国产日韩av二区三区| 赫章县| 国产一区国产精品自拍| 国产精品国产三级国快看| 在线高清免费不卡全码| 国产精品黄大片在线播放| 欧美精品一区二区三区中文字幕| 日韩激情无码av一区二区| 国产亚洲一级特黄大片在线| 国产精品任我爽爆在线播放6080|