|
|

楼主 |
发表于 2008-10-2 08:26:00
|
显示全部楼层
Re: 一种新的 get/set 模式
- // Func.cpp
- #include "stdafx.h"
- using namespace inst;
- using namespace inst::i2d;
- using namespace std;
- class CScene;
- class CSprite;
- struct MYSPRITE;
- Bool g_bExit = False;
- Bool g_bMyMsgLoop = True;
- SmartPtr<CGameWnd> g_pWnd;
- Int2 g_Mouse = { 0, 0 };
- SmartPtr<CBuffer> g_pBuf;
- SmartPtr<CScene> g_pScene;
- void Wnd_WndProc(UINT msg,WPARAM wparam,LPARAM lparam);
- void Update(){}
- void Render();
- void OnReset(){}
- void Init();
- void Destroy(){}
- Bool MsgLoop();
- const Int N = 10; // the num of sprites
- const POS SZ = 20; // the size of a block for drawing a sprite
- MYSPRITE *selected; // current selected sprite by the mouse
- COLOR old_color_selected; // store the old colr of the selected sprite
- // Float2 is a typedef of inst::MATRIX<inst::Float,2,1>
- class CSprite:virtual public IDynamic
- {
- INST_DYNAMIC1(L"CSprite");
- public:
- typedef Float2 (* WORLDPOS)(const CSprite *);
- private:
- COLOR m_Color;
- // - - - - - - - - -
- void *m_instWorldPos; // instances
- WORLDPOS m_funcWorldPos;
- public:
- CSprite(){ m_instWorldPos = m_funcWorldPos = null; m_Color = 0xFFFFFFFF; }
- public:
- void put_Color(COLOR color){ m_Color = color; }
- Int get_Color()const{ return m_Color; }
- // - - - - - - - - - - - - - - - - - - - - -
- template <class T> void put_WorldPos(T *inst, Float2 (T:: *func)(const CSprite *))
- {
- m_instWorldPos = reinterpret_cast<void *>(inst);
- m_funcWorldPos = union_cast<WORLDPOS>(func);
- }
- void put_WorldPos(WORLDPOS func)
- {
- m_instWorldPos = null;
- m_funcWorldPos = func;
- }
- Float2 get_WorldPos()const
- {
- if(null==m_funcWorldPos) return Float2();
- if(null==m_instWorldPos) return (*m_funcWorldPos)(this);
- return INST_THISCALLBACK(m_instWorldPos, m_funcWorldPos, Float2, (const CSprite *), (this));
- }
- void Render(Int2 pos, const Int2 *next_pos)
- {
- if(next_pos)
- g_pBuf->DrawLine(pos.x, pos.y, next_pos->x, next_pos->y, 0xFF00FF00);
- g_pBuf->FillRect(POS(pos.x) - SZ/2, POS(pos.y) - SZ/2, SZ, SZ, get_Color());
- g_pBuf->DrawRect(POS(pos.x) - SZ/2, POS(pos.y) - SZ/2, SZ, SZ, ~get_Color());
- }
- };
- class CScene:virtual public IDynamic
- {
- INST_DYNAMIC1(L"CScene");
- public:
- typedef Float2 (* CAMERA)(const CScene *);
- typedef Array< SmartPtr<CSprite> > SpritesList;
- SpritesList m_Sprites;
- private:
- void *m_instCamera; // instance
- CAMERA m_funcCamera;
- public:
- CScene(){ m_instCamera = m_funcCamera = null; }
- public:
- template <class T> void put_Camera(T *inst, Float2 (T:: *func)(const CScene *))
- {
- m_instCamera = reinterpret_cast<void *>(inst);
- m_funcCamera = union_cast<CAMERA>(func);
- }
- void put_Camera(CAMERA func)
- {
- m_instCamera = null;
- m_funcCamera = func;
- }
- Float2 get_Camera()const
- {
- if(null==m_funcCamera) return Float2();
- if(null==m_instCamera) return (*m_funcCamera)(this);
- return INST_THISCALLBACK(m_instCamera, m_funcCamera, Float2, (const CScene *), (this));
- }
- Int2 CalcScreenPos(const CSprite *sprite)
- {
- if(!sprite) return Int2();
- Float2 tmp = sprite->get_WorldPos() - get_Camera();
- return Int2().Set((Int)tmp.x, (Int)tmp.y);
- }
- void RenderAll()
- {
- for(Int32 i = 0; i < m_Sprites.Count() - 1; i++)
- {
- if(m_Sprites.Get(i))
- m_Sprites.Get(i)->Render(CalcScreenPos(m_Sprites.Get(i)), &CalcScreenPos(m_Sprites.Get(i+1)));
- }
- if(m_Sprites.GetEnd())
- m_Sprites.GetEnd()->Render(CalcScreenPos(m_Sprites.GetEnd()), null);
- }
- };
- struct MYSPRITE
- {
- MYSPRITE *Parent;
- SmartPtr<CSprite> Sprite;
- Float2 LocalPos;
- MYSPRITE(){ Parent = null; }
- Float2 WorldPos(const CSprite *sender)
- {
- INST_ASSERT(Is(sender, Sprite));
- Float2 ret = LocalPos;
- MYSPRITE *tmp = Parent;
- while(tmp)
- {
- ret += tmp->LocalPos;
- tmp = tmp->Parent;
- }
- return ret;
- }
- } MySprite[N];
- Float2 Camera(const CScene *sender)
- {
- return Float2();
- }
- void Init()
- {
- g_pWnd = new CGameWnd(L"Test Window");
- g_pWnd->SetCallback(&Wnd_WndProc);
- g_pWnd->Show();
- g_pWnd->Activate();
- CGraphics::CreateGraphics(640,480,g_pWnd->GetHWnd());
- g_pBuf = CGraphics::GetGraphics()->GetBackBuffer();
- g_pScene = new CScene;
- g_pScene->put_Camera(&Camera);
- MySprite[0].Parent = null;
- MySprite[0].LocalPos.Set(g_pBuf->GetW()/3, g_pBuf->GetH()/3);
- for(MYSPRITE *i = MySprite + 1; i < MySprite + N; i++)
- {
- i->LocalPos.Set(SZ*1.5, SZ);
- i->Parent = i - 1;
- }
- for(MYSPRITE *i = MySprite; i < MySprite + N; i++)
- {
- i->Sprite = new CSprite;
- i->Sprite->put_Color(Rgb(255 - Float(i-MySprite) / N * 255, 0, 0));
- i->Sprite->put_WorldPos(i, &MYSPRITE::WorldPos);
- g_pScene->m_Sprites.AddEnd(i->Sprite);
- }
- }
- void Render()
- {
- g_pBuf->FillRect(0,0,g_pBuf->GetW(),g_pBuf->GetH(),Rgb(0,0,0));
- g_pScene->RenderAll();
- CGraphics::GetGraphics()->Present();
- }
- void Wnd_WndProc(UINT msg,WPARAM wparam,LPARAM lparam)
- {
- switch(msg)
- {
- case WM_KEYDOWN:
- if(selected)
- switch(wparam)
- {
- case 'A': selected->LocalPos.x -= SZ*0.33; break;
- case 'D': selected->LocalPos.x += SZ*0.33; break;
- case 'W': selected->LocalPos.y -= SZ*0.33; break;
- case 'S': selected->LocalPos.y += SZ*0.33; break;
- }
- break;
- case WM_LBUTTONDOWN:
- if(selected) selected->Sprite->put_Color( old_color_selected );
- for(MYSPRITE *i = MySprite + N; i >= MySprite ; i--)
- {
- Int2 pos = g_pScene->CalcScreenPos(i->Sprite);
- if( pos.x - SZ/2 <= g_Mouse.x && pos.x + SZ/2 >= g_Mouse.x
- && pos.y - SZ/2 <= g_Mouse.y && pos.y + SZ/2 >= g_Mouse.y)
- {
- selected = i;
- old_color_selected = i->Sprite->get_Color();
- i->Sprite->put_Color(Rgb(0,255,0));
- break;
- }
- }
- break;
- case WM_DESTROY:
- g_bExit=True;
- break;
- case WM_DISPLAYCHANGE:
- CGraphics::GetGraphics()->Reset();
- OnReset();
- break;
- case WM_PAINT:
- if(False==g_bMyMsgLoop) Render();
- break;
- }
- }
- int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
- {
- Init();
- while(1)
- if(MsgLoop()) break;
- Destroy();
- return 0;
- }
- Bool MsgLoop()
- {
- g_bMyMsgLoop = True;
- if(g_bExit) return True;
- ::MSG msg = {0};
- while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- g_Mouse.Set(msg.pt.x, msg.pt.y);
- POS tx=0, ty=0, tw=1, th=1;
- g_pWnd->GetClientPos(null, null, &tw, &th);
- g_pWnd->ClientToScreen(0, 0, &tx, &ty);
- g_Mouse.Add(-tx, -ty);
- g_Mouse.x /= (Float)tw / g_pBuf->GetW();
- g_Mouse.y /= (Float)th / g_pBuf->GetH();
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- Update();
- Render();
- return False;
- }
- /* NOTE to me:
- class ISprite:virtual public IDynamic
- {
- INST_DYNAMIC1(L"ISprite"):
- protected:
- virtual ~CSprite(){}
- public:
- virtual COLOR Color()=0;
- // - - - - - - - - - - - - - - - - - - - - -
- virtual Float2 WorldPos()=0;
- };
- // 把可变属性 Color 按照数学思想(无可变值)只能用 覆盖 表示。
- // 如果函数能够返回函数指针,那么把函数指针属性按照数学思想(覆盖)表示就是:返回函数指针的可覆盖函数,讨论一下这和 普通返回值的可覆盖函数 的关系!
- */
复制代码
|
|