電腦遊戲製作開發設計論壇 首頁 電腦遊戲製作開發設計論壇
任何可以在PC上跑的遊戲都可以討論,主要以遊戲之製作開發為主軸,希望讓台灣的遊戲人有個討論、交流、教學、經驗傳承的園地
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入 

Google
【基本遊戲技術】2D角色上、下、左、右移動
前往頁面 1, 2, 3  下一頁
 
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式演算法
上一篇主題 :: 下一篇主題  
發表人 內容
zwshen
對這略感興趣的新人


註冊時間: 2008-03-11
文章: 22
來自: Taiwan
0.00 果凍幣

發表發表於: 2008-3-14, PM 8:49 星期五    文章主題: 【基本遊戲技術】2D角色上、下、左、右移動 引言回覆

原始碼及執行檔下載 http://zwshen0603.googlepages.com/Movement.zip

這個範例主要是示範2D角色的上、下、左、右移動,使用HGE 1.8引擎,
有兩個基本技術為:

1. 當玩家按下上、下、左、右鍵,將更新角色座標及移動方向
2. 示範如何利用切割後 sprite 圖檔,來組成角色的移動畫面


這裡大概介紹第2個技術如何做,sprite 是一張已經畫有八個角色的png檔
(參考下圖);每個角色都提供四個方向、每個方向各有三個動作,
所以一個角色共有24張小圖,每張小圖都是高32寬24的大小,按動作上、右、
下、左由上到下排好。在這個程式範例中,只用到左上的一個角色。



要達到四方向的移動動畫,要考慮角色的兩個屬性:方向 步伐

方向決定貼圖來源的 Y 值,以第一個角色為例:
1. UP 方向要從圖檔 Y = 0 開始切
2. RIGHT 方向要從圖檔 Y = 32 開始切
3. DOWN 方向要從圖檔 Y = 32*2 開始切
4. RIGHT 方向要從圖檔 Y = 32*3 開始切

步伐只有0, 1, 2 三步)決定貼圖來源的 X 值,同樣以第一個角色為例:
1. 步伐 0 要從圖檔 X = 0 開始切
2. 步伐 1 要從圖檔 X = 24 開始切
3. 步伐 2 要從圖檔 X = 24*2 開始切
(步伐只有0, 1, 2 三步)

取得 X, Y 值之後,就能從sprite圖檔上切出適當的一小塊圖,並繪製到畫面上。

下列為完整程式碼:
代碼:


/**
 * 2D 角色的東、西、南、北四方向移動
 *
 * Author: zwshen (zwshen0603@gmail.com)
 * Date: 2008/03/14
 * Engine: HGE V1.8 2d graphics engine
 */

#include "hge/hge.h"

// 畫面寬度、高度
const int WIDTH = 640, HEIGHT= 480;

// hge 引擎 - 為一個全域變數
HGE *g_hge = 0;

// 移動方向的常數列舉
enum Direction {
   UP = 0, RIGHT, DOWN, LEFT
};

// 遊戲角色(char)類別
class Char {
private:
   float m_xpos, m_ypos;
   int m_width;
   int m_height;
   int m_step;
   float m_speed;
   Direction m_dir;
   hgeQuad sprite;

private:

   void updatePos() {
      // 更新角色座標
      sprite.v[0].x=m_xpos;
      sprite.v[0].y=m_ypos;

      sprite.v[1].x=m_xpos+m_width;
      sprite.v[1].y=m_ypos;

      sprite.v[2].x=m_xpos+m_width;
      sprite.v[2].y=m_ypos+m_height;

      sprite.v[3].x=m_xpos;
      sprite.v[3].y=m_ypos+m_height;
   }

   void updateSprite() {
      // 更新材質來源 - 以方向及步伐來決定
      
      int x = m_step * 24;
      int y = m_dir * 32;

      sprite.v[0].tx = x/288.0;
      sprite.v[0].ty = y/256.0;

      sprite.v[1].tx = (x+m_width)/288.0;
      sprite.v[1].ty = y/256.0;

      sprite.v[2].tx = (x+m_width)/288.0;
      sprite.v[2].ty = (y+m_height)/256.0;

      sprite.v[3].tx = x/288.0;
      sprite.v[3].ty = (y+m_height)/256.0;
   }

public:

   Char() {
      m_dir = RIGHT; // 預設方向為右邊
      m_step = 0; // 步伐
      m_speed = 100; // 速度
      m_xpos = 200; // 角色x座標
      m_ypos = 200; // 角色y座標
      m_height = 32; // 角色高度
      m_width = 24; // 角色寬度
   }

   void shutdown() {
      // 釋放圖片資源
      if (sprite.tex)
         g_hge->Texture_Free(sprite.tex);
   }

   void walk(Direction dir) {
      float dt = g_hge->Timer_GetDelta();
      float dx=0, dy=0;
      if (dir==UP)
         dy -= m_speed*dt;
      if (dir==DOWN)
         dy += m_speed*dt;
      if (dir==RIGHT)
         dx += m_speed*dt;
      if (dir==LEFT)
         dx -= m_speed*dt;

      if (m_dir==dir) {
         // 同一個方向,則更新步伐
         m_step = (m_step+1)%3;
      } else {
         // 換新方向,步伐歸零
         m_dir = dir;
         m_step = 0;
      }

      m_xpos += dx;
      m_ypos += dy;
      // 檢查是否超出範圍
      if (m_xpos < 0)
         m_xpos = 0;
      if (m_xpos> WIDTH-m_width)
         m_xpos =WIDTH-m_width;
      if (m_ypos < 0)
         m_ypos = 0;
      if (m_ypos> HEIGHT-m_height)
         m_ypos =HEIGHT-m_height;

      update(); // 更新角色
   }

   void update() {
      updatePos();
      updateSprite();
   }
   bool init() {
      sprite.tex = g_hge->Texture_Load("blondeboys.png");
      if (!sprite.tex)
         return false; // 載入圖檔失敗

      sprite.blend=BLEND_ALPHAADD | BLEND_COLORMUL | BLEND_ZWRITE;
      for (int i=0; i<4; i++) {
         sprite.v[i].z=0.1f;
         sprite.v[i].col=0xFFFFFFFF;// no effect
      }

      update();
      return true;
   }
   void render() {
      g_hge->Gfx_RenderQuad(&sprite);
   }
};

bool FrameFunc();
bool RenderFunc();

// 遊戲主流程(Game Loop)類別
class GameLoop {
public:
   static GameLoop *theGameLoop;
private:
   Char m_Player; // 遊戲角色

   // 遊戲資源初始化
   void init() {
      g_hge->System_SetState(HGE_FRAMEFUNC, FrameFunc);
      g_hge->System_SetState(HGE_RENDERFUNC, RenderFunc);
      g_hge->System_SetState(HGE_TITLE, "2D角色移動範例");
      g_hge->System_SetState(HGE_WINDOWED, true);
      g_hge->System_SetState(HGE_USESOUND, false);
      g_hge->System_SetState(HGE_SCREENWIDTH, WIDTH);
      g_hge->System_SetState(HGE_SCREENHEIGHT, HEIGHT);
      g_hge->System_SetState(HGE_SCREENBPP, 32);
   }

public:
   GameLoop() {
      g_hge = hgeCreate(HGE_VERSION);
      init();
   }
   ~GameLoop() {
      // 釋放資源
      m_Player.shutdown();
      g_hge->System_Shutdown();
      g_hge->Release();
   }
   void start() {

      // 進入HGE 遊戲迴圈
      if (g_hge->System_Initiate()) {
         // 初始player資源
         if (m_Player.init() == false) {
            // 初始失敗,則就結束遊戲
            MessageBox(NULL, "init Player fail.", "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
            return;
         }
         g_hge->System_Start();
      } else {
         MessageBox(NULL, g_hge->System_GetErrorMessage(), "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
      }
   }

   void keydown(Direction key) {
      // 通知player做「走路」的動作
      m_Player.walk(key);
   }

   // 繪製每一張frame畫面
   void render_frame() {
      g_hge->Gfx_BeginScene();
      g_hge->Gfx_Clear(0);
      m_Player.render(); // 通知player做繪製動作
      g_hge->Gfx_EndScene();
   }
};

bool FrameFunc() {
   if (g_hge->Input_GetKeyState(HGEK_ESCAPE))
      return true;

   /***
    *  判斷是否按上、下、左、右按鍵,並轉交給GameLoop做進一步處理
    */
   if (g_hge->Input_GetKeyState(HGEK_LEFT))
      GameLoop::theGameLoop->keydown(LEFT);
   if (g_hge->Input_GetKeyState(HGEK_RIGHT))
      GameLoop::theGameLoop->keydown(RIGHT);
   if (g_hge->Input_GetKeyState(HGEK_UP))
      GameLoop::theGameLoop->keydown(UP);
   if (g_hge->Input_GetKeyState(HGEK_DOWN))
      GameLoop::theGameLoop->keydown(DOWN);
   return false;
}

bool RenderFunc() {
   GameLoop::theGameLoop->render_frame();
   return false;
}

GameLoop* GameLoop::theGameLoop = new GameLoop();

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {

   // 遊戲迴圈 開始運作
   GameLoop::theGameLoop->start();

   // 釋放遊戲相關資源
   delete GameLoop::theGameLoop;
   return 0;
}

回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
chuangyao
稍嫌羞澀的路人


註冊時間: 2008-03-26
文章: 2

0.00 果凍幣

發表發表於: 2008-3-26, AM 11:22 星期三    文章主題: 引言回覆

感謝大大的教導
還在熟悉了解中^^
回頂端
檢視會員個人資料 發送私人訊息
Okerofujin
略有貢獻的成員


註冊時間: 2007-10-19
文章: 71

-40.53 果凍幣

發表發表於: 2008-4-18, PM 6:20 星期五    文章主題: 引言回覆

問題

Okerofujin 在 2018-7-5, PM 11:48 星期四 作了第 1 次修改
回頂端
檢視會員個人資料 發送私人訊息
zwshen
對這略感興趣的新人


註冊時間: 2008-03-11
文章: 22
來自: Taiwan
0.00 果凍幣

發表發表於: 2008-4-18, PM 6:42 星期五    文章主題: 引言回覆

HPkon 寫到:
抱歉!!!
就是在下用Dev-C++編譯main.cpp這個檔案時發生很多錯誤
但是在下不知道該怎麼解決

另外想請問一下
樓主大人你是用什麼編譯程式編譯main.cpp這個檔案的



我是用 eclipse + CDT 的開發環境,C++ 編譯器是 MinGW32。

這個程式有使用 HGE 2D引擎,不知道你有沒有裝 HGE 呢?

或是你將你的錯誤訊息貼上來,比較好知道問題所在,謝謝。
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
Okerofujin
略有貢獻的成員


註冊時間: 2007-10-19
文章: 71

-40.53 果凍幣

發表發表於: 2008-4-18, PM 8:11 星期五    文章主題: 引言回覆

問題

Okerofujin 在 2018-7-5, PM 11:49 星期四 作了第 1 次修改
回頂端
檢視會員個人資料 發送私人訊息
zwshen
對這略感興趣的新人


註冊時間: 2008-03-11
文章: 22
來自: Taiwan
0.00 果凍幣

發表發表於: 2008-4-18, PM 8:53 星期五    文章主題: 引言回覆

看你貼的錯誤訊息,可以知道是 hge 沒有裝好,你可以參考 hge 的官方文件,有提到如何設定 Dev-C++ 的環境。

連結如下:
http://hge.relishgames.com/doc/index.html?setup_devcpp.html

大概步驟是:
1. 加入 hge 的 include 及 library 的目錄
2. 加入 hge 的 linked library

只要是新開的project ,都需要這樣設定。

Good Lucky Very Happy
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
Okerofujin
略有貢獻的成員


註冊時間: 2007-10-19
文章: 71

-40.53 果凍幣

發表發表於: 2008-4-18, PM 9:02 星期五    文章主題: 引言回覆

問題

Okerofujin 在 2018-7-5, PM 11:49 星期四 作了第 1 次修改
回頂端
檢視會員個人資料 發送私人訊息
zwshen
對這略感興趣的新人


註冊時間: 2008-03-11
文章: 22
來自: Taiwan
0.00 果凍幣

發表發表於: 2008-4-18, PM 9:08 星期五    文章主題: 引言回覆

HPkon 寫到:
新的專案開好之後是把main.cpp檔加入在新開的專案理就能執行了嗎???

可是...
在下還是不能執行耶!!!


不只是這樣子。而是新開的專案,都需要設定hge 的環境,才能正常編譯跟執行。

前一篇回文中有教學文件的link ,你可以參考那文件,再去設定你的專案。

要注意的,是每個人存放 hge 的路徑不一樣,就再依自已的情況設定好吧。
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
Okerofujin
略有貢獻的成員


註冊時間: 2007-10-19
文章: 71

-40.53 果凍幣

發表發表於: 2008-4-18, PM 9:18 星期五    文章主題: 引言回覆

問題

Okerofujin 在 2018-7-5, PM 11:49 星期四 作了第 1 次修改
回頂端
檢視會員個人資料 發送私人訊息
zwshen
對這略感興趣的新人


註冊時間: 2008-03-11
文章: 22
來自: Taiwan
0.00 果凍幣

發表發表於: 2008-4-18, PM 9:24 星期五    文章主題: 引言回覆

引言回覆:
在下是下載hge181
可是hge181\lib\gcc裡只有libhge.a這個檔案
並沒有hge.a這個檔案


那沒有關係,我是 1.80 版,也只有 libhge.a 一個檔,也就夠了。

教學文件是用 1.5 版,所以情況有點不同,但是不傷大雅。
Very Happy
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
Okerofujin
略有貢獻的成員


註冊時間: 2007-10-19
文章: 71

-40.53 果凍幣

發表發表於: 2008-4-18, PM 9:27 星期五    文章主題: 引言回覆

問題

Okerofujin 在 2018-7-5, PM 11:49 星期四 作了第 1 次修改
回頂端
檢視會員個人資料 發送私人訊息
zwshen
對這略感興趣的新人


註冊時間: 2008-03-11
文章: 22
來自: Taiwan
0.00 果凍幣

發表發表於: 2008-4-18, PM 9:32 星期五    文章主題: 引言回覆

HPkon 寫到:

大人抱歉!!!
問一下...
專案開好hge環境也設定好之後
只要把那個main.cpp的檔案加入專案裡就行了嗎???


是的,只要這樣就能正常編譯了。不過提醒一下,那張角色圖檔也要放在專案裡,要不然一執行就會當掉。

說話我剛也升級到 1.81 版...XD

另外,如果你想要進一步練習,可以做個 2D 射擊遊戲,不需要有捲動的場景,就像任天堂的小蜜蜂、或是太空侵略者等。雖然我這個範例是用 RPG 的圖檔,但是要練習遊戲,先從飛機射擊 或是 board game (如撲克牌、俄羅斯方塊、小精靈) 做,會比較容易做出成品,也比較有成就感。


zwshen 在 2008-4-18, PM 9:39 星期五 作了第 1 次修改
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
Okerofujin
略有貢獻的成員


註冊時間: 2007-10-19
文章: 71

-40.53 果凍幣

發表發表於: 2008-4-18, PM 9:35 星期五    文章主題: 引言回覆

問題

Okerofujin 在 2018-7-5, PM 11:49 星期四 作了第 1 次修改
回頂端
檢視會員個人資料 發送私人訊息
zwshen
對這略感興趣的新人


註冊時間: 2008-03-11
文章: 22
來自: Taiwan
0.00 果凍幣

發表發表於: 2008-4-18, PM 9:41 星期五    文章主題: 引言回覆

HPkon 寫到:

嗚...
在下都有放進去耶!!!
可是還是無法編譯
這到底是為什麼???
heg的環境在下有設好啊!!!
可是編譯時#include "hge/hge.h"發生錯誤!!!
這該怎麼辦呢???


可能就是多了 "hge/hge.h" 的 hge 路徑,你可以試試直接用 #include <hge.h>。
回頂端
檢視會員個人資料 發送私人訊息 參觀發表人的個人網站
Okerofujin
略有貢獻的成員


註冊時間: 2007-10-19
文章: 71

-40.53 果凍幣

發表發表於: 2008-4-18, PM 9:43 星期五    文章主題: 引言回覆

問題

Okerofujin 在 2018-7-5, PM 11:49 星期四 作了第 1 次修改
回頂端
檢視會員個人資料 發送私人訊息
從之前的文章開始顯示:   
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式演算法 所有的時間均為 台灣時間 (GMT + 8 小時)
前往頁面 1, 2, 3  下一頁
1頁(共3頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
可以 在這個版面附加檔案
可以 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作