2D游戏引擎(五)——添加子画面类

 子画面的主要目的是模拟游戏中能够随时间移动的图形对象,它具有以下属性:

Bitmap*       m_pBitmap;    //位图指针
  RECT          m_rcPosition;   //子画面位置
  POINT         m_ptVelocity;   //速度
  int           m_iZOrder;    //z顺序
  RECT          m_rcBounds;    //边界矩形
  BOUNDSACTION  m_baBoundsAction; //边界动作
  BOOL          m_bHidden;    //可见/隐藏

基于以上属性,子画面(Sprite)类程序清单如下:

//-----------------------------------------------------------------
// Sprite Object
// C++ Header - Sprite.h
//-----------------------------------------------------------------

#pragma once

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include 
 
 
  
  
#include "Bitmap.h"

//-----------------------------------------------------------------
// 自定义数据类型(边界动作)
//-----------------------------------------------------------------
typedef WORD        BOUNDSACTION;
const BOUNDSACTION  BA_STOP   = 0,
                    BA_WRAP   = 1,
                    BA_BOUNCE = 2,
                    BA_DIE    = 3;

//-----------------------------------------------------------------
// Sprite Class
//-----------------------------------------------------------------
class Sprite
{
protected:
  // Member Variables
  Bitmap*       m_pBitmap;		  //位图指针
  RECT          m_rcPosition;	  //子画面位置
  POINT         m_ptVelocity;	  //速度
  int           m_iZOrder;		  //z顺序
  RECT          m_rcBounds;		  //边界矩形
  BOUNDSACTION  m_baBoundsAction; //边界动作
  BOOL          m_bHidden;		  //可见/隐藏

public:
  // Constructor(s)/Destructor
  Sprite(Bitmap* pBitmap);
  Sprite(Bitmap* pBitmap, RECT& rcBounds,
    BOUNDSACTION baBoundsAction = BA_STOP);
  Sprite(Bitmap* pBitmap, POINT ptPosition, POINT ptVelocity, int iZOrder,
    RECT& rcBounds, BOUNDSACTION baBoundsAction = BA_STOP);
  virtual ~Sprite();

  // General Methods
  virtual void  Update();
  void          Draw(HDC hDC);
  BOOL          IsPointInside(int x, int y);

  // 访问方法
  RECT&   GetPosition()             { return m_rcPosition; };
  void    SetPosition(int x, int y);
  void    SetPosition(POINT ptPosition);
  void    SetPosition(RECT& rcPosition)
    { CopyRect(&m_rcPosition, &rcPosition); };
  void    OffsetPosition(int x, int y);
  POINT   GetVelocity()             { return m_ptVelocity; };
  void    SetVelocity(int x, int y);
  void    SetVelocity(POINT ptVelocity);
  BOOL    GetZOrder()               { return m_iZOrder; };
  void    SetZOrder(int iZOrder)    { m_iZOrder = iZOrder; };
  void    SetBounds(RECT& rcBounds) { CopyRect(&m_rcBounds, &rcBounds); };
  void    SetBoundsAction(BOUNDSACTION ba) { m_baBoundsAction = ba; };
  BOOL    IsHidden()                { return m_bHidden; };
  void    SetHidden(BOOL bHidden)   { m_bHidden = bHidden; };
  int     GetWidth()                { return m_pBitmap->GetWidth(); };
  int     GetHeight()               { return m_pBitmap->GetHeight(); };
};

//-----------------------------------------------------------------
// Sprite Inline General Methods
//-----------------------------------------------------------------
inline BOOL Sprite::IsPointInside(int x, int y)
{
  POINT ptPoint;
  ptPoint.x = x;
  ptPoint.y = y;
  return PtInRect(&m_rcPosition, ptPoint);
}

//-----------------------------------------------------------------
// Sprite Inline Accessor Methods
//-----------------------------------------------------------------
inline void Sprite::SetPosition(int x, int y)
{
  OffsetRect(&m_rcPosition, x - m_rcPosition.left, y - m_rcPosition.top);
}

inline void Sprite::SetPosition(POINT ptPosition)
{
  OffsetRect(&m_rcPosition, ptPosition.x - m_rcPosition.left,
    ptPosition.y - m_rcPosition.top);
}

inline void Sprite::OffsetPosition(int x, int y)
{
  OffsetRect(&m_rcPosition, x, y);
}

inline void Sprite::SetVelocity(int x, int y)
{
  m_ptVelocity.x = x;
  m_ptVelocity.y = y;
}

inline void Sprite::SetVelocity(POINT ptVelocity)
{
  m_ptVelocity.x = ptVelocity.x;
  m_ptVelocity.y = ptVelocity.y;
}

  
  

 
 
//-----------------------------------------------------------------
// Sprite Object
// C++ Source - Sprite.cpp
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include "Sprite.h"

//-----------------------------------------------------------------
// Sprite Constructor(s)/Destructor
//-----------------------------------------------------------------
Sprite::Sprite(Bitmap* pBitmap)
{
  //初始化成员变量
  m_pBitmap = pBitmap;
  SetRect(&m_rcPosition, 0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
  m_ptVelocity.x = m_ptVelocity.y = 0;
  m_iZOrder = 0;
  SetRect(&m_rcBounds, 0, 0, 640, 480);
  m_baBoundsAction = BA_STOP;
  m_bHidden = FALSE;
}

Sprite::Sprite(Bitmap* pBitmap, RECT& rcBounds, BOUNDSACTION baBoundsAction)
{
  // 计算一个随机位置
  int iXPos = rand() % (rcBounds.right - rcBounds.left);
  int iYPos = rand() % (rcBounds.bottom - rcBounds.top);

  // 初始化成员变量
  m_pBitmap = pBitmap;
  SetRect(&m_rcPosition, iXPos, iYPos, iXPos + pBitmap->GetWidth(),
    iYPos + pBitmap->GetHeight());
  m_ptVelocity.x = m_ptVelocity.y = 0;
  m_iZOrder = 0;
  CopyRect(&m_rcBounds, &rcBounds);
  m_baBoundsAction = baBoundsAction;
  m_bHidden = FALSE;
}

Sprite::Sprite(Bitmap* pBitmap, POINT ptPosition, POINT ptVelocity, int iZOrder,
    RECT& rcBounds, BOUNDSACTION baBoundsAction)
{
  //初始化成员变量
  m_pBitmap = pBitmap;
  SetRect(&m_rcPosition, ptPosition.x, ptPosition.y,
    ptPosition.x + pBitmap->GetWidth(), ptPosition.y + pBitmap->GetHeight());
  m_ptVelocity = ptVelocity;
  m_iZOrder = iZOrder;
  CopyRect(&m_rcBounds, &rcBounds);
  m_baBoundsAction = baBoundsAction;
  m_bHidden = FALSE;
}

Sprite::~Sprite()
{
}

//-----------------------------------------------------------------
// Sprite General Methods
//-----------------------------------------------------------------
void Sprite::Update()
{
  // 更新位置
  POINT ptNewPosition, ptSpriteSize, ptBoundsSize;
  ptNewPosition.x = m_rcPosition.left + m_ptVelocity.x;
  ptNewPosition.y = m_rcPosition.top + m_ptVelocity.y;
  ptSpriteSize.x = m_rcPosition.right - m_rcPosition.left;
  ptSpriteSize.y = m_rcPosition.bottom - m_rcPosition.top;
  ptBoundsSize.x = m_rcBounds.right - m_rcBounds.left;
  ptBoundsSize.y = m_rcBounds.bottom - m_rcBounds.top;

  // 检查边界动作
  // 环绕
  if (m_baBoundsAction == BA_WRAP)
  {
    if ((ptNewPosition.x + ptSpriteSize.x) < m_rcBounds.left)
      ptNewPosition.x = m_rcBounds.right;
    else if (ptNewPosition.x > m_rcBounds.right)
      ptNewPosition.x = m_rcBounds.left - ptSpriteSize.x;
    if ((ptNewPosition.y + ptSpriteSize.y) < m_rcBounds.top)
      ptNewPosition.y = m_rcBounds.bottom;
    else if (ptNewPosition.y > m_rcBounds.bottom)
      ptNewPosition.y = m_rcBounds.top - ptSpriteSize.y;
  }
  // 弹开
  else if (m_baBoundsAction == BA_BOUNCE)
  {
    BOOL bBounce = FALSE;
    POINT ptNewVelocity = m_ptVelocity;
    if (ptNewPosition.x < m_rcBounds.left)
    {
      bBounce = TRUE;
      ptNewPosition.x = m_rcBounds.left;
      ptNewVelocity.x = -ptNewVelocity.x;
    }
    else if ((ptNewPosition.x + ptSpriteSize.x) > m_rcBounds.right)
    {
      bBounce = TRUE;
      ptNewPosition.x = m_rcBounds.right - ptSpriteSize.x;
      ptNewVelocity.x = -ptNewVelocity.x;
    }
    if (ptNewPosition.y < m_rcBounds.top)
    {
      bBounce = TRUE;
      ptNewPosition.y = m_rcBounds.top;
      ptNewVelocity.y = -ptNewVelocity.y;
    }
    else if ((ptNewPosition.y + ptSpriteSize.y) > m_rcBounds.bottom)
    {
      bBounce = TRUE;
      ptNewPosition.y = m_rcBounds.bottom - ptSpriteSize.y;
      ptNewVelocity.y = -ptNewVelocity.y;
    }
    if (bBounce)
      SetVelocity(ptNewVelocity);
  }
  // 停止(默认)
  else
  {
    if (ptNewPosition.x  < m_rcBounds.left ||
      ptNewPosition.x > (m_rcBounds.right - ptSpriteSize.x))
    {
      ptNewPosition.x = max(m_rcBounds.left, min(ptNewPosition.x,
        m_rcBounds.right - ptSpriteSize.x));
      SetVelocity(0, 0);
    }
    if (ptNewPosition.y  < m_rcBounds.top ||
      ptNewPosition.y > (m_rcBounds.bottom - ptSpriteSize.y))
    {
      ptNewPosition.y = max(m_rcBounds.top, min(ptNewPosition.y,
        m_rcBounds.bottom - ptSpriteSize.y));
      SetVelocity(0, 0);
    }
  }
  SetPosition(ptNewPosition);
}

void Sprite::Draw(HDC hDC)
{
  // 如果没有隐藏,使用子画面
  if (m_pBitmap != NULL && !m_bHidden)
    m_pBitmap->Draw(hDC, m_rcPosition.left, m_rcPosition.top, TRUE);
}

当然附上一个相应的实例程序:创建几个行星子画面,并让它们在游戏屏幕上飞来飞去,分别带有一种边界动作。

程序清单:

 

//-----------------------------------------------------------------
// Planets Application
// C++ Header - Planets.h
//-----------------------------------------------------------------

#pragma once

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include 
 
 
  
  
#include "Resource.h"
#include "GameEngine.h"
#include "Bitmap.h"
#include "Sprite.h"

//-----------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------
HINSTANCE   g_hInstance;
GameEngine* g_pGame;
Bitmap*     g_pGalaxyBitmap;	//背景
Bitmap*     g_pPlanetBitmap[3];	//行星位图
Sprite*     g_pPlanetSprite[3];	//行星子画面
BOOL        g_bDragging;		//拖动标志
int         g_iDragPlanet;		//拖动行星号

  
  

 
 

 

 

//-----------------------------------------------------------------
// Planets Application
// C++ Source - Planets.cpp
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include "Planets.h"

//-----------------------------------------------------------------
// Game Engine Functions
//-----------------------------------------------------------------
BOOL GameInitialize(HINSTANCE hInstance)
{
  // Create the game engine
  g_pGame = new GameEngine(hInstance, TEXT("Planets"),
    TEXT("Planets"), IDI_PLANETS, IDI_PLANETS_SM, 600, 400);
  if (g_pGame == NULL)
    return FALSE;
  
  // Set the frame rate
  g_pGame->SetFrameRate(30);

  // Store the instance handle
  g_hInstance = hInstance;

  return TRUE;
}

void GameStart(HWND hWindow)
{
  // Seed the random number generator
  srand(GetTickCount());

  //创建并加载位图
  HDC hDC = GetDC(hWindow);
  g_pGalaxyBitmap = new Bitmap(hDC, IDB_GALAXY, g_hInstance);
  g_pPlanetBitmap[0] = new Bitmap(hDC, IDB_PLANET1, g_hInstance);
  g_pPlanetBitmap[1] = new Bitmap(hDC, IDB_PLANET2, g_hInstance);
  g_pPlanetBitmap[2] = new Bitmap(hDC, IDB_PLANET3, g_hInstance);

  //创建行星子画面
  RECT rcBounds = { 0, 0, 600, 400 };
  g_pPlanetSprite[0] = new Sprite(g_pPlanetBitmap[0], rcBounds);
  g_pPlanetSprite[1] = new Sprite(g_pPlanetBitmap[1], rcBounds, BA_WRAP);
  g_pPlanetSprite[2] = new Sprite(g_pPlanetBitmap[2], rcBounds, BA_BOUNCE);
  g_pPlanetSprite[0]->SetPosition(0, 0);
  g_pPlanetSprite[0]->SetVelocity(1, 1);
  g_pPlanetSprite[1]->SetVelocity(2, -1);
  g_pPlanetSprite[2]->SetVelocity(3, -2);

  //设置初始拖动信息
  g_bDragging = FALSE;
  g_iDragPlanet = -1;
}

void GameEnd()
{
  // Cleanup the bitmaps
  delete g_pGalaxyBitmap;
  for (int i = 0; i < 3; i++)
    delete g_pPlanetBitmap[i];

  // Cleanup the sprites
  for (i = 0; i < 3; i++)
    delete g_pPlanetSprite[i];

  // Cleanup the game engine
  delete g_pGame;
}

void GameActivate(HWND hWindow)
{
}

void GameDeactivate(HWND hWindow)
{
}

void GamePaint(HDC hDC)
{
  // 绘制星系背景
  g_pGalaxyBitmap->Draw(hDC, 0, 0);

  // 绘制行星子画面
  for (int i = 0; i < 3; i++)
    g_pPlanetSprite[i]->Draw(hDC);
}

void GameCycle()
{
  // 更新行星子画面
  for (int i = 0; i < 3; i++)
    g_pPlanetSprite[i]->Update();

  // Force a repaint to redraw the planets
  InvalidateRect(g_pGame->GetWindow(), NULL, FALSE);
}

void HandleKeys()
{
}

void MouseButtonDown(int x, int y, BOOL bLeft)
{
  //查看是否使用鼠标左键单击了一颗行星
  if (bLeft && !g_bDragging)
  {
    for (int i = 0; i < 3; i++)
      if (g_pPlanetSprite[i]->IsPointInside(x, y))
      {
        // 捕获鼠标
        SetCapture(g_pGame->GetWindow());

        // Set the drag state and the drag planet
        g_bDragging = TRUE;
        g_iDragPlanet = i;

        //开始模拟鼠标移动
        MouseMove(x, y);

        // 不检查其他行星
        break;
      }
  }
}

void MouseButtonUp(int x, int y, BOOL bLeft)
{
  // 释放鼠标
  ReleaseCapture();

  // 停止拖动
  g_bDragging = FALSE;
}

void MouseMove(int x, int y)
{
  if (g_bDragging)
  {
    //将子画面移动到鼠标指针位置
    g_pPlanetSprite[g_iDragPlanet]->SetPosition(
      x - (g_pPlanetBitmap[g_iDragPlanet]->GetWidth() / 2),
      y - (g_pPlanetBitmap[g_iDragPlanet]->GetHeight() / 2));

    // Force a repaint to redraw the planets
    InvalidateRect(g_pGame->GetWindow(), NULL, FALSE);
  }
}

void HandleJoystick(JOYSTATE jsJoystickState)
{
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用方法:将配套的模块与DLL放到运行程序目录一起即可.比如: 用易语言新建立了一个程序,名称为[新程序.e]那么就放到和它一起的目录,添加模块即可. 搜集不宜,闲分多的请绕行. (包内无任何连接广告,纯绿色)压缩包内包括内容如下: --------------------------------以下为EDgame2d 引擎 D2D.ec 模块正式版本包括: 版本号: 1.0.5.15 大小: 628 kb 版本号: 1.0.5.15 大小: 635 kb 版本号: 1.0.6.20 大小: 652 kb 版本号: 1.0.7.20 大小: 660 kb 版本号: 1.0.7.70 大小: 653 kb 版本号: 1.0.8.70 大小: 664 kb 版本号: 1.0_学习版本 大小: 661 kb 版本号: 2.0_坏少爷完美破解(赞助版) 大小: 307 kb(最新) 版本号: 2.0_竹林深处破解(赞助版) 大小: 307 kb(最新) D2D.ec 模块扩展版本包括: 版本号: 1.0 大小: 83 kb 版本号: 1.1 大小: 86 kb 版本号: 1.2 大小: 91 kb D2D.dll 正式版本包括: 版本号: 1.0.0.1 大小: 952 kb 版本号: 1.0.5.15 大小: 824 kb 版本号: 1.0.6.20 大小: 507 kb 版本号: 1.0.7.20 大小: 417 kb 版本号: 1.0.8.70 大小: 417 kb 版本号: 1.0.8.17 大小: 433 kb 版本号: 1.0.8.28 大小: 418 kb 版本号: 1.0.11.25 大小: 427 kb 版本号: 1.0.6.20 大小: 507 kb 版本号: 1.0.0.1 大小: 846 kb 版本号: 1.0.0.1 大小: 847 kb 版本号: 1.0.0.1 大小: 925 kb 版本号: 1.0.0.1 大小: 957 kb 版本号: 1.0.0.1 大小: 961 kb 版本号: 1.1.2.7 大小: 519 kb(最新) bass.dll 正式版本包括: 版本号: 2.3.0.3 大小为: 91 kb ScriptManager.dll 正式版本包括: 版本号: 未知 大小为: 55kb --------------------------------以下为Galaxy2d 引擎 G2D.ec 版本号:4.102 大小为: 109 kb Galaxy2d.dll 版本号: 未知 大小为: 903 kb star.dll 版本号: 未知 大小为: 102 kb --------------------------------以下为Pge2d 引擎 pge32.ec 版本号: 15.316 大小为: 917kb PGE32.dll 版本号: 15.125.12.12 大小为: 1.72M

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值