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

📄 mapeditview.cpp

📁 经典游戏超级玛丽的C++实现
💻 CPP
字号:
// MapEditView.cpp : implementation of the CMapEditView class
//

#include "stdafx.h"
#include "MapEdit.h"

#include "MapEditDoc.h"
#include "MapEditView.h"
#include "MapWidthDlg.h"
#include "ObjectTypeDlg.h"

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

enum
{ 
	BRICK1, BRICK2, BRICK3, GRASS, CLOUD, HILL, MARK, TUBE, BUILDING,
	GHOST1, GHOST2, GHOST3,
};

enum
{
	SURF_NONE = -1,
	SURF_SOLID,
	SURF_BRICK,
	SURF_COIN,
	SURF_MUSHROOM,
};

const int TILE_W = 32;
const int TILE_H = 32;


CSize GetSize( UINT object )
{
	int w, h;

	switch( object )
	{
	case BRICK1:
	case BRICK2:
	case BRICK3:
	case MARK:
		w = 1;
		h = 1;
		break;

	case GRASS:
		w = 3;
		h = 1;
		break;

	case CLOUD:
	case HILL:
		w = 3;
		h = 2;
		break;

	case TUBE:
		w = 2;
		h = 2;
		break;

	case GHOST1:
		w = h = 1;
		break;

	case GHOST2:
	case GHOST3:
		w = 1;
		h = 2;
		break;

	case BUILDING:
		w = h = 5;
		break;
	}
	
	return CSize(w * TILE_W, h * TILE_H );
}


/////////////////////////////////////////////////////////////////////////////
// CMapEditView

IMPLEMENT_DYNCREATE(CMapEditView, CScrollView)

BEGIN_MESSAGE_MAP(CMapEditView, CScrollView)
	//{{AFX_MSG_MAP(CMapEditView)
	ON_WM_MOUSEMOVE()
	ON_WM_RBUTTONDOWN()
	ON_COMMAND(ID_EDIT_MAPWIDTH, OnEditMapwidth)
	ON_WM_LBUTTONDOWN()
	//}}AFX_MSG_MAP
	ON_COMMAND_RANGE( ID_BRICK1, ID_GHOST3, OnSelectObject )
	ON_UPDATE_COMMAND_UI_RANGE( ID_BRICK1, ID_GHOST3, OnUpdateObject )
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMapEditView construction/destruction

CMapEditView::CMapEditView()
{
	m_object = BRICK1;
	m_tilex = 0;
	m_tiley = 0;

	m_bmTiles.LoadBitmap( IDB_TILES );
	m_bmGhosts[0].LoadBitmap( IDB_GHOST1 );
	m_bmGhosts[1].LoadBitmap( IDB_GHOST2 );
	m_bmGhosts[2].LoadBitmap( IDB_GHOST3 );
}

CMapEditView::~CMapEditView()
{

}

BOOL CMapEditView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CScrollView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMapEditView drawing

void CMapEditView::OnDraw(CDC* pDC)
{
	CMapEditDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CDC dcMem;
	CBitmap bitmap, *pbmOld;
	dcMem.CreateCompatibleDC( pDC );
	bitmap.CreateCompatibleBitmap( pDC, 640, 480 );
	pbmOld = (CBitmap *)dcMem.SelectObject( &bitmap );
	dcMem.FillSolidRect( 0, 0, 640, 480, RGB(107,136,255) );
	
	int planex = GetScrollPosition().x;
	
	// draw tiles
	CDC dcTiles;
	dcTiles.CreateCompatibleDC( pDC );
	CBitmap *pbmOld1 = (CBitmap *)dcTiles.SelectObject( &m_bmTiles );
	int min = planex / TILE_W;
	int max = min + 20;
	int leftx = planex - min * TILE_W;
	int width = pDoc->m_width;
	int height = pDoc->m_height;
	char *tiles = pDoc->m_tiles;
	
	for( int i = 0; i < height; i ++ )
	{
		int destx = 0;
		for( int j = min; j <= max; j ++ )
		{
			int tile = tiles[i * width + j];
			if( tile >= 0 )
			{
				int desty = i * TILE_H;
				int srcx = (tile % 16) * TILE_W;
				int srcy = (tile / 16) * TILE_H;
				int w = TILE_W;
				int h = TILE_H;
				if( j == min )
					srcx += leftx;
				else if( j == max )
					w = leftx;
				
				dcMem.BitBlt( destx, desty, w, h, &dcTiles, srcx, srcy, SRCCOPY );
			}
			if( j == min )
				destx += TILE_W - leftx;
			else
				destx += TILE_W;
		}
	}
	dcTiles.SelectObject( pbmOld1 );
	dcTiles.DeleteDC();
	
	// draw ghosts
	for( i = 0; i < 3; i ++ )
		pDoc->m_ghostlist[i].Draw( &dcMem, &m_bmGhosts[i], planex );


	// draw focus rect
	CBrush *pbrOld = (CBrush *)dcMem.SelectStockObject( NULL_BRUSH );
	RECT rc;
	CSize size = GetSize( m_object );
	rc.left = m_tilex * TILE_W - planex;
	rc.right = rc.left + size.cx;
	rc.top = m_tiley * TILE_H;
	rc.bottom = rc.top + size.cy;
	dcMem.Rectangle( &rc );

	pDC->BitBlt( planex, 0, 640, 480, &dcMem, 0, 0, SRCCOPY );
	dcMem.SelectObject( pbmOld );
	dcMem.SelectObject( pbrOld );
}


void CMapEditView::OnInitialUpdate()
{
	CScrollView::OnInitialUpdate();

	CSize sizeTotal;
	sizeTotal.cx = GetDocument()->m_width * TILE_W;
	sizeTotal.cy = GetDocument()->m_height * TILE_H;
	SetScrollSizes(MM_TEXT, sizeTotal);
}

/////////////////////////////////////////////////////////////////////////////
// CMapEditView diagnostics

#ifdef _DEBUG
void CMapEditView::AssertValid() const
{
	CScrollView::AssertValid();
}

void CMapEditView::Dump(CDumpContext& dc) const
{
	CScrollView::Dump(dc);
}

CMapEditDoc* CMapEditView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMapEditDoc)));
	return (CMapEditDoc*)m_pDocument;
}
#endif //_DEBUG


char CMapEditView::GetTile( int x, int y )
{
	int width = GetDocument()->m_width;
	int height = GetDocument()->m_height;
	if( x >= 0 && x < width &&
		y >= 0 && y < height )
	{
		return GetDocument()->m_tiles[y*width+x];
	}
	return -1;
}

void CMapEditView::SetTile( int x, int y, char tile )
{
	int width = GetDocument()->m_width;
	int height = GetDocument()->m_height;
	if( x >= 0 && x < width &&
		y >= 0 && y < height )
	{
		GetDocument()->m_tiles[y*width+x] = tile;
		GetDocument()->SetModifiedFlag();
	}
}


char CMapEditView::GetSurface( int x, int y )
{
	int width = GetDocument()->m_width;
	int height = GetDocument()->m_height;
	if( x >= 0 && x < width &&
		y >= 0 && y < height )
	{
		return GetDocument()->m_surface[y*width+x];
	}
	return -1;
}


void CMapEditView::SetSurface( int x, int y, char surf )
{
	int width = GetDocument()->m_width;
	int height = GetDocument()->m_height;
	if( x >= 0 && x < width &&
		y >= 0 && y < height )
	{
		GetDocument()->m_surface[y*width+x] = surf;
		GetDocument()->SetModifiedFlag();
	}
}

/////////////////////////////////////////////////////////////////////////////
// CMapEditView message handlers

void CMapEditView::OnSelectObject( UINT nID )
{
	m_object = nID - ID_BRICK1;
}

void CMapEditView::OnUpdateObject( CCmdUI *pCmdUI )
{
	pCmdUI->SetCheck( pCmdUI->m_nID - ID_BRICK1 == m_object );
}

void CMapEditView::OnMouseMove(UINT nFlags, CPoint point)
{
	CClientDC dc(this);
	OnPrepareDC( &dc );
	dc.DPtoLP( &point );

	int tilex = point.x / TILE_W;
	int tiley = point.y / TILE_H;
	if( tilex != m_tilex || tiley != m_tiley )
	{
		m_tilex = tilex;
		m_tiley = tiley;
		Invalidate( FALSE );
	}
	
	CScrollView::OnMouseMove(nFlags, point);
}


void CMapEditView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	int x = m_tilex * TILE_W;
	int y = m_tiley * TILE_H;
	if( m_object == GHOST2 || m_object == GHOST3 )
		y += 16;
	if( m_object == GHOST1 ||
		m_object == GHOST2 ||
		m_object == GHOST3 )
	{
		int i = m_object - GHOST1;
		GetDocument()->m_ghostlist[i].Delete( x, y );
	}
	else
	{
		if( GetSurface( m_tilex, m_tiley ) == SURF_BRICK &&
			GetTile( m_tilex, m_tiley+1 ) == 20 )
			SetTile( m_tilex, m_tiley+1, 0 );

		SetTile( m_tilex, m_tiley, -1 );
		SetSurface( m_tilex, m_tiley, SURF_NONE );
	}

	Invalidate( FALSE );
	
	CScrollView::OnRButtonDown(nFlags, point);
}

void CMapEditView::OnEditMapwidth() 
{
	CMapWidthDlg dlg;
	int &width = GetDocument()->m_width;
	int &height = GetDocument()->m_height;
	BOOL &darken = GetDocument()->m_darken;
	dlg.m_width = width;
	dlg.m_bDarken = darken;
	
	if( dlg.DoModal() == IDOK )
	{
		if( dlg.m_width < width &&
			AfxMessageBox(IDS_WARNING, MB_YESNO) == IDNO )
			return;
		
		if( dlg.m_width != width )
		{
			GetDocument()->Resize( dlg.m_width );
			CSize sizeTotal;
			sizeTotal.cx = width * TILE_W;
			sizeTotal.cy = height * TILE_H;
			SetScrollSizes(MM_TEXT, sizeTotal);
		}
		darken = dlg.m_bDarken;
		GetDocument()->SetModifiedFlag();
	}
}


void CMapEditView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if( nFlags & MK_CONTROL )
	{
		Property();
		return;
	}
	

	int &x = m_tilex;
	int &y = m_tiley;

	switch( m_object )
	{
	case BRICK1:
		if( GetSurface( x, y - 1 ) != SURF_BRICK )
			SetTile( x, y, 0 );
		else
			SetTile( x, y, 20 );

		if( GetTile( x, y + 1 ) == 0 )
			SetTile( x, y + 1, 20 );

		SetSurface( x, y, SURF_BRICK );
		break;

	case BRICK2:
		SetTile( x, y, 1 );
		SetSurface( x, y, SURF_SOLID );
		break;

	case BRICK3:
		SetTile( x, y, 19 );
		SetSurface( x, y, SURF_SOLID );
		break;

	case GRASS:
		SetTile( x, y, 2 );
		SetTile( x + 1, y, 3 );
		SetTile( x + 2, y, 4 );
		break;

	case CLOUD:
		SetTile( x + 1, y, 8 );
		SetTile( x, y + 1, 5 );
		SetTile( x + 1, y + 1, 6 );
		SetTile( x + 2, y + 1, 7 );
		break;

	case HILL:
		SetTile( x + 1, y, 12 );
		SetTile( x, y + 1, 9 );
		SetTile( x + 1, y + 1, 10 );
		SetTile( x + 2, y + 1, 11 );
		break;

	case MARK:		// question mark
		SetTile( x, y, 13 );
		SetSurface( x, y, SURF_COIN );
		break;

	case TUBE:
		SetTile( x, y, 16 );
		SetTile( x + 1, y, 17 );
		SetTile( x, y + 1, 14 );
		SetTile( x + 1, y + 1, 15 );
		
		SetSurface( x, y, SURF_SOLID );
		SetSurface( x + 1, y, SURF_SOLID );
		SetSurface( x, y + 1, SURF_SOLID );
		SetSurface( x + 1, y + 1, SURF_SOLID );
		break;

	case GHOST1:
	case GHOST2:
	case GHOST3:
		{
			int i = m_object - GHOST1;
			int spritex = x * TILE_W;
			int spritey = y * TILE_H;
			if( m_object == GHOST2 || m_object == GHOST3 )
				spritey += 16;
			
			GetDocument()->m_ghostlist[i].Add( spritex, spritey );
			GetDocument()->SetModifiedFlag();
		}
		break;

	case BUILDING:
		SetTile( x + 1, y, 26 );
		SetTile( x + 2, y, 26 );
		SetTile( x + 3, y, 26 );
		SetTile( x + 1, y + 1, 24 );
		SetTile( x + 2, y + 1, 20 );
		SetTile( x + 3, y + 1, 25 );
		SetTile( x, y + 2, 26 );
		SetTile( x + 1, y + 2, 23 );
		SetTile( x + 2, y + 2, 23 );
		SetTile( x + 3, y + 2, 23 );
		SetTile( x + 4, y + 2, 26 );
		SetTile( x, y + 3, 20 );
		SetTile( x + 1, y + 3, 20 );
		SetTile( x + 2, y + 3, 22 );
		SetTile( x + 3, y + 3, 20 );
		SetTile( x + 4, y + 3, 20 );
		SetTile( x, y + 4, 20 );
		SetTile( x + 1, y + 4, 20);
		SetTile( x + 2, y + 4, 21 );
		SetTile( x + 3, y + 4, 20 );
		SetTile( x + 4, y + 4, 20 );
		break;
	}
	Invalidate( FALSE );
	
	CScrollView::OnLButtonDown(nFlags, point);
}



void CMapEditView::Property() 
{
	char tile = GetTile( m_tilex, m_tiley );
	char surf = GetSurface( m_tilex, m_tiley );

	if( tile == 13 )		// question mark
	{
		CObjectTypeDlg dlg;
		dlg.m_nObjectType = GetSurface( m_tilex, m_tiley ) - SURF_COIN;
		if( dlg.DoModal() == IDOK )
		{
			if( dlg.m_bHidden )
				SetTile( m_tilex, m_tiley, -1 );
			SetSurface( m_tilex, m_tiley, dlg.m_nObjectType + SURF_COIN );
		}
	}
	else if( surf == SURF_BRICK )
	{
		CObjectTypeDlg dlg;
		if( surf == SURF_NONE )
			dlg.m_nObjectType = -1;
		else
			dlg.m_nObjectType = surf - SURF_COIN;
		if( dlg.DoModal() == IDOK )
		{
			int object = dlg.m_nObjectType;
			if( object == -1 )
				SetSurface( m_tilex, m_tiley, SURF_NONE );
			else
				SetSurface( m_tilex, m_tiley, object + SURF_COIN );
		}
	}
}

⌨️ 快捷键说明

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