基于Pierre Dellacherie的俄罗斯方块-04背景和操作-02

基于Pierre Dellacherie的俄罗斯方块-04背景和操作-02

  1. 完善剩下的上下左右的操作

  2. 设置定时器

  3. 消除bug

#pragma once
#include "CBlock.h"
#include "CBackGround.h"
#include <wtypes.h>


class CTetris
{
public:
	CTetris();
	~CTetris();
public:
	//初始化
	void InitGame();
	//显示
	void ShowGame(HDC hdc);

	//显示背景
	void DrawALlBack(HDC hdc);
	//显示大背景下的图形
	void DrawMaxLeft(HDC hdc); 
	//显示小背景下的图形
	void DrawMinRight(HDC hdc);

	//操作小方块
	// 旋转 rotate
	void BlockRotate();
	// 下
	int BlockDown();
	// 左
	void BlockLeft();
	// 右
	void BlockRight();

private:
	//是否可以移动
	bool IsCanMove();
	//结束
	bool IsGameOver();

	CBlock m_cBlock;
	CBackGround m_cBackGround;

	size_t m_nRow;	//小方块的行
	size_t m_nCol;	//小方块的列

	int m_nScore = 0;
};


#include "CTetris.h"

CTetris::CTetris()
{

}

CTetris::~CTetris()
{

}

void CTetris::InitGame()
{
	//初始化小方块
	m_cBlock.RandCreateBlock();
	m_cBlock.RandCreateBlock();

	//初始化背景
	m_cBackGround.InitBackGround();

	m_nRow = 0;
	m_nCol = COL / 2 - 2;

	//把小方块写进大的背景中
	m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);

}

//显示
void CTetris::ShowGame(HDC hdc)
{
	//显示背景
	DrawALlBack(hdc);
	//显示大背景下的图形
	DrawMaxLeft(hdc);
	//显示小背景下的图形
	DrawMinRight(hdc);
}

void CTetris::DrawALlBack(HDC hdc)
{
	//COL* WIDTH, ROW* HEIGHT
	HGDIOBJ hPenNull = GetStockObject(NULL_PEN);
	HGDIOBJ hBrushGray = GetStockObject(GRAY_BRUSH);

	SelectObject(hdc, hPenNull);
	SelectObject(hdc, hBrushGray);

	//Rectangle(hdc, 0, 0, COL * WIDTH, ROW * HEIGHT);

	Rectangle(hdc, WIDTH, WIDTH * 4, (COL - 1) * WIDTH, ROW * HEIGHT);
	//Rectangle(hdc, 0, 0, COL * WIDTH, ROW * HEIGHT);

	Rectangle(hdc, (COL + 1) * WIDTH, WIDTH * 4, (COL + 9) * WIDTH, ROW * HEIGHT);

	DeleteObject(hBrushGray);
	DeleteObject(hPenNull);

}

//画大背景下的小方块和固定方块

void CTetris::DrawMaxLeft(HDC hdc)
{
	HGDIOBJ hPenBlaCk = GetStockObject(BLACK_PEN);
	HGDIOBJ hBrushWhite = GetStockObject(WHITE_BRUSH);

	SelectObject(hdc, hPenBlaCk);
	SelectObject(hdc, hBrushWhite);


	//获取背景数据
	BACKGROUND BcakGround = m_cBackGround.GetBackGround();
	for (size_t y = 0; y < ROW; y++)
	{
		for (size_t x = 0; x < COL; x++)
		{
			if (BcakGround[y][x] != BLOCK_SPACE && BcakGround[y][x] != BLOCK_WAll)
			{
				//画每一个小方块
				Rectangle(hdc, x * WIDTH, y * HEIGHT, x * WIDTH + WIDTH, y * HEIGHT + HEIGHT);
			}
		}
	}


	DeleteObject(hBrushWhite);
	DeleteObject(hPenBlaCk);
}

void CTetris::DrawMinRight(HDC hdc)
{
	HGDIOBJ hPenBlaCk = GetStockObject(BLACK_PEN);
	HGDIOBJ hBrushWhite = GetStockObject(WHITE_BRUSH);

	SelectObject(hdc, hPenBlaCk);
	SelectObject(hdc, hBrushWhite);


	//画右边的下一个方块
	BLOCKDATE BlockDate = m_cBlock.GetNextBlock();

	for (size_t y = 0; y < BLOCK_ROW; y++)
	{
		for (size_t x = 0; x < BLOCK_COL; x++)
		{
			if (BlockDate[y][x] == BLOCK_MOVE)
			{
				//画每一个小方块
				Rectangle(hdc, (COL + 3 + x) * WIDTH, (y + 6) * HEIGHT, (COL + 3 + x) * WIDTH + WIDTH, (y + 6) * HEIGHT + HEIGHT);
			}
		}
	}


	DeleteObject(hBrushWhite);
	DeleteObject(hPenBlaCk);
}

void CTetris::BlockRotate()
{
	m_cBackGround.ClearBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE);

	//record
	size_t nIndex = m_cBlock.GetShape();

	m_cBlock.RotateBlock();
	//判断可不可以  Rotate
	if (!IsCanMove())
	{
		m_cBlock.SetShape(nIndex);
	}

	m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);

}

int CTetris::BlockDown()
{
	m_cBackGround.ClearBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE);
	m_nRow++;

	//判断可不可以移动
	if (!IsCanMove())
	{
		m_nRow--;
		m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_FIXED);

		//消行 0-4
		m_cBackGround.RemoveRows();

		//有没有结束
		if (IsGameOver())
		{
			return -1;
		}
		m_cBlock.RandCreateBlock();

		m_nRow = 0;
		m_nCol = COL / 2 - 2;

	}
	m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);

	return 0;
}

void CTetris::BlockLeft()
{
	m_cBackGround.ClearBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE);
	m_nCol--;
	//判断可不可以移动
	if (!IsCanMove())
	{
		m_nCol++;

	}

	m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);
}

void CTetris::BlockRight()
{
	m_cBackGround.ClearBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE);
	m_nCol++;
	//判断可不可以移动
	if (!IsCanMove())
	{
		m_nCol--;

	}

	m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);

}

bool CTetris::IsCanMove()
{
	//获取背景数据
	BACKGROUND BcakGround = m_cBackGround.GetBackGround();

	//画右边的下一个方块
	BLOCKDATE BlockDate = m_cBlock.GetCurrentBlock();

	for (size_t y = 0; y < BLOCK_ROW; y++)
	{
		for (size_t x = 0; x < BLOCK_COL; x++)
		{
			if (BlockDate[y][x] == BLOCK_MOVE && (BcakGround[y + m_nRow][x + m_nCol] == BLOCK_WAll || BcakGround[y + m_nRow][x + m_nCol] == BLOCK_FIXED))
			{
				return false;
			}
		}
	}
	return true;
}

bool CTetris::IsGameOver()
{
	//获取背景数据
	BACKGROUND BcakGround = m_cBackGround.GetBackGround();

	for (size_t x = 1; x < COL -1 ; x++)
	{
		if (BcakGround[3][x] == BLOCK_FIXED)
		{
			return true;
		}
	}

	return false;
}


// Project1.cpp : 定义应用程序的入口点。
//

#include "framework.h"
#include "Project1.h"
#include "resource.h"
#include "CBlock.h"
#include "CTetris.h"


#define BLOCK_DOWN_TIMER 1
#define BLOCK_AI_TIMER	2
#define BLOCK_DOWN_SPEED 500


#define MAX_LOADSTRING 100

// 全局变量:


CTetris* pTetris = nullptr;
HINSTANCE hInst;                                // 当前实例
WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名

// 此代码模块中包含的函数的前向声明:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPWSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	// TODO: 在此处放置代码。
	//srand((unsigned)time(NULL));



	// 初始化全局字符串
	LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadStringW(hInstance, IDC_PROJECT1, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// 执行应用程序初始化:
	if (!InitInstance(hInstance, nCmdShow))
	{
		return FALSE;
	}

	HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PROJECT1));

	MSG msg;

	// 主消息循环:
	while (GetMessage(&msg, nullptr, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int)msg.wParam;
}



//
//  函数: MyRegisterClass()
//
//  目标: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEXW wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInstance;
	wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PROJECT1));
	wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PROJECT1);
	wcex.lpszClassName = szWindowClass;
	wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassExW(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目标: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	hInst = hInstance; // 将实例句柄存储在全局变量中

	HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
		600, 300, (COL + 11) * WIDTH, (ROW + 2) * HEIGHT, nullptr, nullptr, hInstance, nullptr);

	if (!hWnd)
	{
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目标: 处理主窗口的消息。
//
//  WM_COMMAND  - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY  - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_TIMER:
	{
		switch (wParam)
		{
		case BLOCK_DOWN_TIMER:
		{
			if (pTetris)
			{
				if (pTetris->BlockDown() == -1)
				{
					PostQuitMessage(0);
				}
			}
			InvalidateRect(hWnd, NULL, TRUE);
			return 0;
		}
		break;

		case BLOCK_AI_TIMER:
		{
			return 0;

		}
		break;
		}
	}
	break;
	case WM_KEYDOWN:
	{
		int wmId = LOWORD(wParam);
		switch (wmId)
		{
		case VK_UP:
		{

			if (pTetris)
			{
				pTetris->BlockRotate();
			}
			InvalidateRect(hWnd, NULL, TRUE);
		}
		break;
		case VK_DOWN:
		{

			if (pTetris)
			{
				if (pTetris->BlockDown() == -1)
				{
					PostQuitMessage(0);
				}
			}
			InvalidateRect(hWnd, NULL, TRUE);
		}
		break;
		case VK_LEFT:
		{
			if (pTetris)
			{
				pTetris->BlockLeft();
			}
			InvalidateRect(hWnd, NULL, TRUE);
		}
		break;
		case VK_RIGHT:
		{

			if (pTetris)
			{
				pTetris->BlockRight();
			}
			InvalidateRect(hWnd, NULL, TRUE);
		}
		break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
	}
	break;
	case WM_COMMAND:
	{
		int wmId = LOWORD(wParam);
		// 分析菜单选择:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		case MENU_START:
		{
			if (pTetris)
			{
				delete pTetris;
				pTetris = nullptr;
			}
			pTetris = new CTetris();
			if (pTetris)
			{
				pTetris->InitGame();
				SetTimer(hWnd, BLOCK_DOWN_TIMER, BLOCK_DOWN_SPEED, NULL);

			}
			InvalidateRect(hWnd, NULL, TRUE);
		}
		break;
		case MENU_PAUSE:
		{
			MessageBox(0, "MENU_PAUSE", "Menu", MB_OKCANCEL);
		}
		break;
		case MENU_EXIT:
		{
			DestroyWindow(hWnd);
			break;
		}
		break;
		case MENU_AI:
		{
			MessageBox(0, "MENU_AI", "Menu", MB_OK);
		}
		break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
	}
	break;
	case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);
		// TODO: 在此处添加使用 hdc 的任何绘图代码...
		if (pTetris)
		{
			pTetris->ShowGame(hdc);
		}
		EndPaint(hWnd, &ps);
	}
	break;
	case WM_DESTROY:
	{
		KillTimer(hWnd, BLOCK_DOWN_TIMER);
		KillTimer(hWnd, BLOCK_AI_TIMER);
		PostQuitMessage(0);

	}
	break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值