1.继续完成飞机大战
1.继续完成back背景类
1.要贴图的话就需要先导入资源文件,选择 解决方案中的资源文件,右键添加->资源->BitMap,找到要添加的位图文件。
1)这里涉及到一个问题,我们需要保证我们的可执行文件能够在我们自己的电脑上运行,也能够在他人的电脑上运行,因此,在添加资源文件时,需要注意资源文件的路径问题(最好修改为相对路径)。
2.设计back类的成员,设计为两个 HBITMAP 成员来保存背景图,并且定义背景的横纵坐标。
3.back类需要有三个成员函数:
1)初始化背景
2)移动背景
3)显示背景
1)初始化背景需要进行加载位图,将加载的背景位图赋值给两个位图句柄;
2)移动背景需要判断背景的y坐标,若y>550,则将y置零(背景位图大小为550x380);
3)显示背景需要创建兼容性dc,再将位图选择进兼容性dc,再复制位图;
#include "Back.h"
CBack::CBack(void)
{
x = 0; // 初始化成员
y = 0;
m_hBmpBackDown = 0;
m_hBmpBackUp = 0;
}
CBack::~CBack(void)
{
::DeleteObject(m_hBmpBackUp); // 删除位图,释放空间
::DeleteObject(m_hBmpBackDown);
}
void CBack::InitBack(HINSTANCE h_ins)
{
m_hBmpBackDown = ::LoadBitmap(h_ins, MAKEINTRESOURCE(IDB_BACK)); // 加载位图
m_hBmpBackUp = ::LoadBitmap(h_ins, MAKEINTRESOURCE(IDB_BACK));
}
void CBack::MoveBack()
{
if(y > 550) // 向下一直移动背景图,x、y为背景图左上角坐标
y = 0;
else
{
y++;
}
}
void CBack::ShowBack(HDC dc)
{
HDC map_dc = ::CreateCompatibleDC(dc); // 创建兼容性dc
::SelectObject(map_dc, m_hBmpBackUp); // 选择 上背景图 句柄
::BitBlt(dc, x, y-550, 280, 550, map_dc, 0, 0, SRCCOPY); // 将 上背景图 拷贝到dc中
::SelectObject(map_dc, m_hBmpBackDown); // 选择 下背景图 句柄
::BitBlt(dc, x, y, 380, 550, map_dc, 0, 0, SRCCOPY); // 将 下背景图 拷贝到dc中
::DeleteDC(map_dc); // 删除兼容性dc
}
4.完成back类之后,需要调用back类来显示背景。
1)在PlaneApp中创建 back类对象;
2)PlaneApp类中重写 OnCreateGame、OnGameShow、OnGameRun以及OnGameKeyDown 四个虚函数;
3)在 OnCreateGame 函数中调用 back 的初始化函数 back.InitBack(m_h_ins) ,参数为GameApp中定义的实例句柄;
4)在 OnCreateGame 函数中设置一个控制背景移动速度的定时器,定时器编号在 CommonInclude 文件中定义为宏:#define BACK_MOVE_TIMER_ID 1
5)在 OnGameShow 函数中先获得dc,再调用 back.ShowBack(dc) 来显示背景;
6)在 OnGameRun 函数中判断输入的消息是否为控制背景移动的定时器 BACK_MOVE_TIMER_ID,若是,则 back.MoveBack();
7)完整的PlaneApp.cpp
#include "PlaneApp.h"
IMPLEMENT(CPlaneApp)
CPlaneApp::CPlaneApp(void)
{
}
CPlaneApp::~CPlaneApp(void)
{
}
void CPlaneApp::OnCreateGame()
{
// 1.初始化背景
back.InitBack(m_h_ins);
// 2.启动定时器
::SetTimer(m_hwnd, BACK_MOVE_TIMER_ID, 100, 0);
}
void CPlaneApp::OnGameShow()
{
HDC dc = GetDC(m_hwnd); // GetDC对应ReleaseDC
back.ShowBack(dc);
::ReleaseDC(m_hwnd, dc);
}
void CPlaneApp::OnGameRun(WPARAM w_param)
{
if(w_param == BACK_MOVE_TIMER_ID)
{
back.MoveBack();
}
this->OnGameShow();
}
void CPlaneApp::OnGameKeyDown(WPARAM w_param)
{
}
2.完成Player类来显示玩家飞机
1.创建一个 Player类,该类不用继承任何其他类。
2.定义该类的成员 HBITMAP m_hBmpPlayer、int m_nGunnerStyle、int x、int y 分别表示飞机的位图句柄、子弹的风格(暂时无用,可以不设置)以及飞机位图的左上角坐标。
3.该类的成员函数与back类类似,有三个:InitPlayer、MovePlayer以及ShowPlayer。
4.在Player的构造函数中,我们让飞机的起始位置在窗口的下部中间位置,可设置 x=160,y=490。
5.InitPlayer 函数用来加载飞机位图。
6.MovePlayer 函数用来移动飞机(即改变飞机左上角的位置)。
7.ShowPlayer 函数用来显示飞机。
Player类的实现
#include "Player.h"
CPlayer::CPlayer(void)
{
m_hBmpPlayer = 0;
m_nGunnerStyle = 0;
x = 160;
y = 490;
}
CPlayer::~CPlayer(void)
{
::DeleteObject(m_hBmpPlayer);
}
void CPlayer::InitPlayer(HINSTANCE hIns)
{
m_hBmpPlayer = ::LoadBitmap(hIns, MAKEINTRESOURCE(IDB_HERO));
}
void CPlayer::MovePlayer(int FX)
{
if(FX == VK_LEFT) // 因为VK_LEFT是宏定义,且其实质上是一个int型的数,FX用来表示接受到的按键消息
{
if(x > 0)
x -= 2;
}
if(FX == VK_RIGHT)
{
if(x < 320)
x += 2;
}
if(FX == VK_DOWN)
{
if(y < 490)
y += 2;
}
if(FX == VK_UP)
{
if(y > 0)
y -= 2;
}
}
void CPlayer::ShowPlayer(HDC dc)
{
HDC map_dc = ::CreateCompatibleDC(dc);
::SelectObject(map_dc, m_hBmpPlayer);
::BitBlt(dc, x, y, 60, 60, map_dc, 0, 0, SRCAND);
::DeleteDC(map_dc);
}
8.显示玩家飞机
1)在PlaneApp中创建player类对象;
2)在 OnCreateGame 函数中初始化玩家飞机,player.InitPlayer(m_h_ins);
3)为玩家飞机移动设置一个定时器,编号为 PLAYER_MOVE_TIMER_ID;
4)在 OnGameShow 函数中调用 player.ShowPlayer(dc) 来显示玩家飞机;
5)在 OnGameRun 函数中判断传入的消息是否是 PLAYER_MOVE_TIMER_ID,若是再判断输入的按键是哪个按键。
6)增加飞机后的PlaneApp实现类如下:
#include "PlaneApp.h"
IMPLEMENT(CPlaneApp)
CPlaneApp::CPlaneApp(void)
{
}
CPlaneApp::~CPlaneApp(void)
{
}
void CPlaneApp::OnCreateGame()
{
// 1.初始化背景
back.InitBack(m_h_ins);
// 2.初始化玩家飞机
player.InitPlayer(m_h_ins);
// 3.启动所有的定时器
::SetTimer(m_hwnd, BACK_MOVE_TIMER_ID, 100, 0);
::SetTimer(m_hwnd, PLAYER_MOVE_TIMER_ID, 1, 0);
}
void CPlaneApp::OnGameShow()
{
HDC dc = GetDC(m_hwnd);
back.ShowBack(dc);
player.ShowPlayer(dc);
::ReleaseDC(m_hwnd, dc);
}
void CPlaneApp::OnGameRun(WPARAM w_param)
{
if(w_param == PLAYER_MOVE_TIMER_ID)
{
if(::GetAsyncKeyState(VK_LEFT))
player.MovePlayer(VK_LEFT);
if(::GetAsyncKeyState(VK_RIGHT))
player.MovePlayer(VK_RIGHT);
if(::GetAsyncKeyState(VK_DOWN))
player.MovePlayer(VK_DOWN);
if(::GetAsyncKeyState(VK_UP))
player.MovePlayer(VK_UP);
}
if(w_param == BACK_MOVE_TIMER_ID)
{
back.MoveBack();
}
this->OnGameShow();
}
void CPlaneApp::OnGameKeyDown(WPARAM w_param)
{}
3.显示飞机子弹
1.与显示背景和玩家飞机几乎完全相同,先创建一个子弹类Gunner,不用继承其他类。
2.公有成员有:子弹位图句柄HBITMAP m_hBmpGunner、子弹的横纵坐标。
3.成员函数也是三个:InitGuuner、MoveGunner、ShowGunner。
4.在Gunner的构造函数中设置句柄为null,横纵坐标为飞机的上面一点。
5.在初始化函数 InitGuuner 中载入图像。
6.暂时不对移动子弹函数进行设计,先让子弹能够显示出来。
7.在显示函数 ShowGunner 中将子弹位图拷贝到dc上。
8.具体实现代码:
#include "Gunner.h"
CGunner::CGunner(void)
{
m_hBmpGunner = 0;
x = 187;
y = 481;
}
CGunner::~CGunner(void)
{
::DeleteObject(m_hBmpGunner);
}
void CGunner:: (HINSTANCE hIns, int new_x, int new_y)
{
m_hBmpGunner = ::LoadBitmap(hIns, MAKEINTRESOURCE(IDB_GUNNER));
}
void CGunner::MoveGunner()
{
}
void CGunner::ShowGunner(HDC dc)
{
HDC map_dc = ::CreateCompatibleDC(dc);
::SelectObject(map_dc, m_hBmpGunner);
::BitBlt(dc, x, y, 6, 9, map_dc, 0, 0, SRCCOPY);
::DeleteDC(map_dc);
}
4.下一步我们需要将子弹进行自主移动。
--------------------------------未完待续---------------------------