⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 marsdoc.cpp

📁 MARS加密解密
💻 CPP
字号:
// MarsDoc.cpp : implementation of the CMarsDoc class
//
//	本程序是《疯狂的火星虫—面向对象状态机实践指南》的演示程序
//
//	版权所有 (C) 2004 王咏武
//	http://www.contextfree.net/wangyw/
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <math.h>
#include "Mars.h"

#include "MarsDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMarsDoc

IMPLEMENT_DYNCREATE(CMarsDoc, CDocument)

BEGIN_MESSAGE_MAP(CMarsDoc, CDocument)
	//{{AFX_MSG_MAP(CMarsDoc)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMarsDoc construction/destruction

CMarsDoc::CMarsDoc()
{
	// TODO: add one-time construction code here
    srand(GetTickCount());
}

CMarsDoc::~CMarsDoc()
{
    for (int i = 0; i < m_Bugs.size(); i ++)
        delete m_Bugs[i].m_pBug;
}

BOOL CMarsDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)

    // 初始创建10个火星虫
    for (int i = 0; i < 10; i ++)
        AddNewBug();

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CMarsDoc serialization

void CMarsDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
        int size = m_Bugs.size();
        ar << size;
        
        for (int i = 0; i < size; i ++)
        {
            m_Bugs[i].Serialize(ar);
        }
	}
	else
	{
		// TODO: add loading code here
        int size;
        ar >> size;

        int i;
        // 从文件装载时,先删除原来的火星虫
        for (i = 0; i < m_Bugs.size(); i ++)
        {
            m_Bugs[i].m_pBug->Invalidate();
            delete m_Bugs[i].m_pBug;
        }
        m_Bugs.erase(m_Bugs.begin(), m_Bugs.end());

        for (i = 0; i < size; i ++)
        {
            SBugInfo bug_info(new CMarsBug(0, 0, 0));
            bug_info.Serialize(ar);
            m_Bugs.push_back(bug_info);
        }
    }
}

/////////////////////////////////////////////////////////////////////////////
// CMarsDoc diagnostics

#ifdef _DEBUG
void CMarsDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CMarsDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMarsDoc commands

void CMarsDoc::OnDraw(CDC* pDC)
{
    for (int i = 0; i < m_Bugs.size(); i ++)
        m_Bugs[i].m_pBug->OnDraw(pDC);
}

void CMarsDoc::OnTimer()
{
    vector<SBugInfo>::iterator it;
    for (it = m_Bugs.begin(); it < m_Bugs.end(); it ++)
        if (it->m_bRemove)
        {
            it->m_pBug->Invalidate();
            delete it->m_pBug;
            m_Bugs.erase(it);
            break;
        }

    // 根据距离确定给每个火星虫发送的消息
    for (int i = 0; i < m_Bugs.size(); i ++)
        for (int j = i + 1; j < m_Bugs.size(); j ++)
        {
            int distance = GetDistance(m_Bugs[i].m_pBug, m_Bugs[j].m_pBug);

            if (distance < m_Bugs[i].m_iDistance)
            {
                if (distance <= CMarsBug::DISTANCE_CAN_ATTACK)
                    m_Bugs[i].m_Event = CMarsBug::EVENT_CAN_ATTACK;
                else if (distance <= CMarsBug::DISTANCE_CAN_SEE)
                    m_Bugs[i].m_Event = CMarsBug::EVENT_CAN_SEE;
                else
                    m_Bugs[i].m_Event = CMarsBug::EVENT_IDLE;
                m_Bugs[i].m_iDistance = distance;
                m_Bugs[i].m_pEnemy = m_Bugs[j].m_pBug;
            }

            if (distance < m_Bugs[j].m_iDistance)
            {
                if (distance <= CMarsBug::DISTANCE_CAN_ATTACK)
                    m_Bugs[j].m_Event = CMarsBug::EVENT_CAN_ATTACK;
                else if (distance <= CMarsBug::DISTANCE_CAN_SEE)
                    m_Bugs[j].m_Event = CMarsBug::EVENT_CAN_SEE;
                else
                    m_Bugs[j].m_Event = CMarsBug::EVENT_IDLE;
                m_Bugs[j].m_iDistance = distance;
                m_Bugs[j].m_pEnemy = m_Bugs[i].m_pBug;
            }
        }

    for (int k = 0; k < m_Bugs.size(); k ++)
    {
        m_Bugs[k].m_pBug->Invalidate();
        m_Bugs[k].m_pBug->SendEvent(m_Bugs[k].m_Event, 0, (DWORD)m_Bugs[k].m_pEnemy);
        m_Bugs[k].m_pBug->Invalidate();
        m_Bugs[k].Init();
    }
}

void CMarsDoc::Escape(CMarsBug * pBug, CMarsBug * pBugFrom)
{
    int distance = GetDistance(pBug, pBugFrom);

    int x = pBug->GetX();
    int xFrom = pBugFrom->GetX();
    if (distance)
        x -= (xFrom - x) * CMarsBug::ESCAPE_STEP / distance;
    else
        x -= CMarsBug::ESCAPE_STEP;
    int y = pBug->GetY();
    int yFrom = pBugFrom->GetY();
    if (distance)
        y -= (yFrom - y) * CMarsBug::ESCAPE_STEP / distance;
    else
        y -= CMarsBug::ESCAPE_STEP;

    BorderCheck(x, y);
    pBug->SetX(x);
    pBug->SetY(y);
}

void CMarsDoc::Chase(CMarsBug * pBug, CMarsBug * pBugFrom)
{
    int distance = GetDistance(pBug, pBugFrom);

    int x = pBug->GetX();
    int xFrom = pBugFrom->GetX();
    if (distance)
        x += (xFrom - x) * CMarsBug::CHASE_STEP / distance;
    int y = pBug->GetY();
    int yFrom = pBugFrom->GetY();
    if (distance)
        y += (yFrom - y) * CMarsBug::CHASE_STEP / distance;

    BorderCheck(x, y);
    pBug->SetX(x);
    pBug->SetY(y);
}

void CMarsDoc::Walk(CMarsBug * pBug)
{
    int x = pBug->GetX();
    x += rand() * CMarsBug::WALK_STEP / RAND_MAX - CMarsBug::WALK_STEP / 2;
    int y = pBug->GetY();
    y += rand() * CMarsBug::WALK_STEP / RAND_MAX - CMarsBug::WALK_STEP / 2;

    BorderCheck(x, y);
    pBug->SetX(x);
    pBug->SetY(y);
}

int CMarsDoc::GetDistance(CMarsBug *pBug1, CMarsBug *pBug2)
{
    double cx = pBug1->GetX() - pBug2->GetX();
    double cy = pBug1->GetY() - pBug2->GetY();
    return sqrt(cx * cx + cy * cy);
}

void CMarsDoc::AddNewBug()
{
    int x = rand() * m_iWidth / RAND_MAX;
    int y = rand() * m_iHeight / RAND_MAX;
    m_Bugs.push_back(SBugInfo(new CMarsBug(x, y,
        RGB(rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX))));
}

void CMarsDoc::Remove(CMarsBug * pBug)
{
    vector<SBugInfo>::iterator i;
    for (i = m_Bugs.begin(); i < m_Bugs.end(); i ++)
        if (i->m_pBug == pBug)
        {
            i->m_bRemove = TRUE;
            break;
        }
}

void CMarsDoc::Spawn(int x, int y)
{
    m_Bugs.push_back(SBugInfo(new CMarsBug(x, y, RGB(rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX))));
}

void CMarsDoc::BorderCheck(int & x, int & y)
{
    if (x < CMarsBug::RADIUS)
        x = CMarsBug::RADIUS;
    else if (x > m_iWidth - CMarsBug::RADIUS)
        x = m_iWidth - CMarsBug::RADIUS;

    if (y < CMarsBug::RADIUS)
        y = CMarsBug::RADIUS;
    else if (y > m_iHeight - CMarsBug::RADIUS)
        y = m_iHeight - CMarsBug::RADIUS;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -