`
yuanlanjun
  • 浏览: 1181658 次
文章分类
社区版块
存档分类
最新评论

DirectX游戏编程入门——第二部分(游戏编程工具箱) —— Bomb Catcher 伪游戏

 
阅读更多

本系列文章由 net_assassin 整理编写,转载请注明出处。

http://blog.csdn.net/net_assassin/article/category/1100363


作者:net_assassin 邮箱: net_assassin@hotmail.com 期待着与志同道合的朋友们相互交流


前面讲到了如何从键盘和鼠标获取输入,这一章我们利用前面学到知识制作我们的游戏来演示到目前为止我们所学的一切。

这个游戏要求用户在屏幕底部移动一个篮筐,抓住从顶部随机落下的。


重点:我们将 Windows 、 DirectX 和 游戏源代码分开存放在不同文件中。

MyWindows.cpp 所有Windows代码,包括WinMain 和 WinProc

MyDirectX.h DirectX变量和函数定义

MyDirectX.cpp DirectX变量和函数实现

MyGame.cpp 游戏的源代码

要成为专业程序员,代码重用是关键。不能一次一次重写代码并指望每一次都能把工作做好。

到目前为止我们所创建的源代码文件提供了一个可极大减少编写Windows/DirectX游戏所需工作量的游戏框架。

效果图:


贴代码:

MyWindows.cpp

#include "MyDirectX.h"
using namespace std;
bool gameover = false;

/**
 ** Windows event handler
 **/
LRESULT WINAPI WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            gameover = true;
            PostQuitMessage(0);
            return 0;
    }
    return DefWindowProc( hWnd, msg, wParam, lParam );
}

/**
 ** Windows entry point
 **/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //initialize window settings
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX); 
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = (WNDPROC)WinProc;
    wc.cbClsExtra	 = 0;
    wc.cbWndExtra	 = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = NULL;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = APPTITLE.c_str();
    wc.hIconSm       = NULL;
    RegisterClassEx(&wc);

    //create a new window
    HWND window = CreateWindow( APPTITLE.c_str(), APPTITLE.c_str(),
       WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
       SCREENW, SCREENH, NULL, NULL, hInstance, NULL);
    if (window == 0) return 0;

    //display the window
    ShowWindow(window, nCmdShow);
    UpdateWindow(window);
	
	//initialize the game
    if (!Game_Init(window)) return 0;

    // main message loop
	MSG message;
	while (!gameover)
    {
        if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) 
	    {
		    TranslateMessage(&message);
		    DispatchMessage(&message);
	    }

        //process game loop 
        Game_Run(window);
    }

    //shutdown
    Game_End();
	return message.wParam;
}

MyDirectX.h

#pragma once

//header files
#define WIN32_EXTRA_LEAN
#define DIRECTINPUT_VERSION 0x0800
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dinput.h>
#include <xinput.h>
#include <ctime>
#include <iostream>
#include <iomanip>
using namespace std;

//libraries
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"gdi32.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"dinput8.lib")
#pragma comment(lib,"xinput.lib")

//program values
extern const string APPTITLE;
extern const int SCREENW;
extern const int SCREENH;
extern bool gameover;

//Direct3D objects
extern LPDIRECT3D9 d3d; 
extern LPDIRECT3DDEVICE9 d3ddev; 
extern LPDIRECT3DSURFACE9 backbuffer;

//Direct3D functions
bool Direct3D_Init(HWND hwnd, int width, int height, bool fullscreen);
void Direct3D_Shutdown();
LPDIRECT3DSURFACE9 LoadSurface(string filename);
void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source);

//DirectInput objects, devices, and states
extern LPDIRECTINPUT8 dinput;
extern LPDIRECTINPUTDEVICE8 dimouse;
extern LPDIRECTINPUTDEVICE8 dikeyboard;
extern DIMOUSESTATE mouse_state;
extern XINPUT_GAMEPAD controllers[4];

//DirectInput functions
bool DirectInput_Init(HWND);
void DirectInput_Update();
void DirectInput_Shutdown();
int Key_Down(int);
int Mouse_Button(int);
int Mouse_X();
int Mouse_Y();
void XInput_Vibrate(int contNum = 0, int amount = 65535);
bool XInput_Controller_Found();

//game functions
bool Game_Init(HWND window);
void Game_Run(HWND window);
void Game_End();

MyDirectX.cpp

#include "MyDirectX.h"
#include <iostream>
using namespace std;

//Direct3D variables
LPDIRECT3D9 d3d = NULL; 
LPDIRECT3DDEVICE9 d3ddev = NULL; 
LPDIRECT3DSURFACE9 backbuffer = NULL;

//DirectInput variables
LPDIRECTINPUT8 dinput = NULL;
LPDIRECTINPUTDEVICE8 dimouse = NULL;
LPDIRECTINPUTDEVICE8 dikeyboard = NULL;
DIMOUSESTATE mouse_state;
char keys[256];
XINPUT_GAMEPAD controllers[4];

/**
 ** Direct3D initialization
 **/
bool Direct3D_Init(HWND window, int width, int height, bool fullscreen)
{
    //initialize Direct3D
    d3d = Direct3DCreate9(D3D_SDK_VERSION);
    if (!d3d) return false;

    //set Direct3D presentation parameters
    D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = (!fullscreen);
    d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferCount = 1;
    d3dpp.BackBufferWidth = width;
    d3dpp.BackBufferHeight = height;
    d3dpp.hDeviceWindow = window;

    //create Direct3D device
    d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);

    if (!d3ddev) return false;

    //get a pointer to the back buffer surface
    d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);

    return true;
}

/**
 ** Direct3D shutdown
 **/
void Direct3D_Shutdown()
{
    if (d3ddev) d3ddev->Release();
    if (d3d) d3d->Release();
}

/**
 ** Draws a surface to the screen using StretchRect
 **/
void DrawSurface(LPDIRECT3DSURFACE9 dest, float x, float y, LPDIRECT3DSURFACE9 source)
{
    //get width/height from source surface
    D3DSURFACE_DESC desc;
    source->GetDesc(&desc);

    //create rects for drawing
    RECT source_rect = {0, 0, (long)desc.Width, (long)desc.Height };
    RECT dest_rect = { (long)x, (long)y, (long)x+desc.Width, (long)y+desc.Height};
    
    //draw the source surface onto the dest
    d3ddev->StretchRect(source, &source_rect, dest, &dest_rect, D3DTEXF_NONE);

}

/**
 ** Loads a bitmap file into a surface
 **/
LPDIRECT3DSURFACE9 LoadSurface(string filename)
{
    LPDIRECT3DSURFACE9 image = NULL;
    
    //get width and height from bitmap file
    D3DXIMAGE_INFO info;
    HRESULT result = D3DXGetImageInfoFromFile(filename.c_str(), &info);
    if (result != D3D_OK)
        return NULL;

    //create surface
    result = d3ddev->CreateOffscreenPlainSurface(
        info.Width,         //width of the surface
        info.Height,        //height of the surface
        D3DFMT_X8R8G8B8,    //surface format
        D3DPOOL_DEFAULT,    //memory pool to use
        &image,             //pointer to the surface
        NULL);              //reserved (always NULL)

    if (result != D3D_OK) return NULL;

    //load surface from file into newly created surface
    result = D3DXLoadSurfaceFromFile(
        image,                  //destination surface
        NULL,                   //destination palette
        NULL,                   //destination rectangle
        filename.c_str(),       //source filename
        NULL,                   //source rectangle
        D3DX_DEFAULT,           //controls how image is filtered
        D3DCOLOR_XRGB(0,0,0),   //for transparency (0 for none)
        NULL);                  //source image info (usually NULL)

    //make sure file was loaded okay
    if (result != D3D_OK) return NULL;

    return image;
}

/**
 ** DirectInput initialization
 **/
bool DirectInput_Init(HWND hwnd)
{
    //initialize DirectInput object
    HRESULT result = DirectInput8Create(
        GetModuleHandle(NULL), 
        DIRECTINPUT_VERSION, 
        IID_IDirectInput8,
        (void**)&dinput,
        NULL);

    //initialize the keyboard
    dinput->CreateDevice(GUID_SysKeyboard, &dikeyboard, NULL);
    dikeyboard->SetDataFormat(&c_dfDIKeyboard);
    dikeyboard->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
    dikeyboard->Acquire();

    //initialize the mouse
    dinput->CreateDevice(GUID_SysMouse, &dimouse, NULL);
    dimouse->SetDataFormat(&c_dfDIMouse);
    dimouse->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
    dimouse->Acquire();
    d3ddev->ShowCursor(false);

    return true;
}

/**
 ** DirectInput update
 **/
void DirectInput_Update()
{
    //update mouse
    dimouse->GetDeviceState(sizeof(mouse_state), (LPVOID)&mouse_state);

    //update keyboard
    dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys);

    //update controllers
    for (int i=0; i< 4; i++ )
    {
        ZeroMemory( &controllers[i], sizeof(XINPUT_STATE) );

        //get the state of the controller
        XINPUT_STATE state;
        DWORD result = XInputGetState( i, &state );

        //store state in global controllers array
        if (result == 0) controllers[i] = state.Gamepad;
    }

}

/**
 ** Return mouse x movement
 **/
int Mouse_X()
{
    return mouse_state.lX;
}

/**
 ** Return mouse y movement
 **/
int Mouse_Y()
{
    return mouse_state.lY;
}

/**
 ** Return mouse button state
 **/
int Mouse_Button(int button)
{
    return mouse_state.rgbButtons[button] & 0x80;
}

/**
 ** Return key press state
 **/
int Key_Down(int key)
{
    return (keys[key] & 0x80);
}

/**
 ** DirectInput shutdown
 **/
void DirectInput_Shutdown()
{
    if (dikeyboard) 
    {
        dikeyboard->Unacquire();
        dikeyboard->Release();
        dikeyboard = NULL;
    }
    if (dimouse) 
    {
        dimouse->Unacquire();
        dimouse->Release();
        dimouse = NULL;
    }
}

/**
 ** Returns true if controller is plugged in
 **/
bool XInput_Controller_Found()
{
    XINPUT_CAPABILITIES caps;
    ZeroMemory(&caps, sizeof(XINPUT_CAPABILITIES));
    XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps);
    if (caps.Type != 0) return false;
    
    return true;
}

/**
 ** Vibrates the controller
 **/
void XInput_Vibrate(int contNum, int amount)
{
    XINPUT_VIBRATION vibration;
    ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) );
    vibration.wLeftMotorSpeed = amount;
    vibration.wRightMotorSpeed = amount; 
    XInputSetState( contNum, &vibration );
}

MyGame.cpp

#include "MyDirectX.h"
using namespace std;

const string APPTITLE = "Bomb Catcher Game";
const int SCREENW = 1024;
const int SCREENH = 768;

LPDIRECT3DSURFACE9 bomb_surf = NULL;
LPDIRECT3DSURFACE9 bucket_surf = NULL;

struct BOMB
{
    float x,y;

    void reset()
    {
        x = (float)(rand() % (SCREENW-128));
        y = 0;
    }
};

BOMB bomb;

struct BUCKET
{
    float x,y;
};

BUCKET bucket;

int score = 0;
int vibrating = 0;


/**
 ** Game initialization
 **/
bool Game_Init(HWND window)
{
    Direct3D_Init(window, SCREENW, SCREENH, false);

    DirectInput_Init(window);

    bomb_surf = LoadSurface("bomb.bmp");
    if (!bomb_surf) {
        MessageBox(window, "Error loading bomb","Error",0);
        return false;
    }

    bucket_surf = LoadSurface("bucket.bmp");
    if (!bucket_surf) {
        MessageBox(window, "Error loading bucket","Error",0);
        return false;
    }


    //position the bomb
    srand( (unsigned int)time(NULL) );
    bomb.reset();

    //position the bucket
    bucket.x = 500;
    bucket.y = 630;


    return true;
}

void Game_Run(HWND window)
{
    //make sure the Direct3D device is valid
    if (!d3ddev) return;

    //update input devices
    DirectInput_Update();

    //move the bomb down the screen
    bomb.y += 2.0f;

    //see if bomb hit the floor
    if (bomb.y > SCREENH) 
    {
        MessageBox(0,"Oh no, the bomb exploded!!","YOU STINK",0);
        gameover = true;
    }

    //move the bucket with the mouse
    int mx = Mouse_X();
    if (mx < 0) bucket.x -= 6.0f;
    else if (mx > 0) bucket.x += 6.0f;
    
    //move the bucket with the keyboard
    if (Key_Down(DIK_LEFT)) bucket.x -= 6.0f;
    else if (Key_Down(DIK_RIGHT)) bucket.x += 6.0f;

    //move the bucket with the controller
    if (XInput_Controller_Found())
    {
        //left analog thumb stick
        if (controllers[0].sThumbLX < -5000) 
            bucket.x -= 6.0f;
        else if (controllers[0].sThumbLX > 5000) 
            bucket.x += 6.0f;

        //left and right triggers
        if (controllers[0].bLeftTrigger > 128) 
            bucket.x -= 6.0f;
        else if (controllers[0].bRightTrigger > 128) 
            bucket.x += 6.0f;

        //left and right D-PAD
        if (controllers[0].wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) 
            bucket.x -= 6.0f;
        else if (controllers[0].wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER)
            bucket.x += 6.0f;

        //left and right shoulders
        if (controllers[0].wButtons & XINPUT_GAMEPAD_DPAD_LEFT) 
            bucket.x -= 6.0f;
        else if (controllers[0].wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
            bucket.x += 6.0f;
    }

    //update vibration
    if (vibrating > 0)
    {
        vibrating++;
        if (vibrating > 20)
        {
            XInput_Vibrate(0, 0);
            vibrating = 0;
        }
    } 


    //keep bucket inside the screen
    if (bucket.x < 0) bucket.x = 0;
    if (bucket.x > SCREENW-128) bucket.x = SCREENW-128;

    //see if bucket caught the bomb
    int cx = bomb.x + 64;
    int cy = bomb.y + 64;
    if (cx > bucket.x && cx < bucket.x+128 && cy > bucket.y && cy < bucket.y+128)
    {
        //update and display score
        score++;
        char s[255];
        sprintf(s, "%s [SCORE %d]", APPTITLE.c_str(), score);
        SetWindowText(window, s);

        //vibrate the controller
        XInput_Vibrate(0, 65000);
        vibrating = 1;

        //restart bomb
        bomb.reset();
    }

    //clear the backbuffer
    d3ddev->ColorFill(backbuffer, NULL, D3DCOLOR_XRGB(0,0,0));

    //start rendering
    if (d3ddev->BeginScene())
    {

        //draw the bomb
        DrawSurface(backbuffer, bomb.x, bomb.y, bomb_surf);

        //draw the bucket
        DrawSurface(backbuffer, bucket.x, bucket.y, bucket_surf);
     
        //stop rendering
        d3ddev->EndScene();
        d3ddev->Present(NULL, NULL, NULL, NULL);
    }

    //escape key exits
    if (Key_Down(DIK_ESCAPE)) 
        gameover = true;

    //controller Back button also exits
    if (controllers[0].wButtons & XINPUT_GAMEPAD_BACK)
        gameover = true;


}

void Game_End()
{
    if (bomb_surf) bomb_surf->Release();
    if (bucket_surf) bucket_surf->Release();
    DirectInput_Shutdown();
    Direct3D_Shutdown();
}


分享到:
评论

相关推荐

    Bomb Catcher 小游戏

    Bomb Cather 入门小游戏!!!使用DirexctX库,使用前必须安装并配置号DirectX库。微软官方有免费下载。。

    bomb——mp3——音效文件

    用于制作unity游戏或者其他开发时的添加音效,是一个爆炸的音效,MP3格式的文件,导入很快,声音清晰,可以自行进行音频长度的裁剪

    BOMB游戏

    一个用C语言写的小游戏源码

    C# 扫雷游戏源码Bomb-非常适合初学者学习

    C# 扫雷游戏源码Bomb-非常适合初学者学习,C# 扫雷游戏源码Bomb-非常适合初学者学习,C# 扫雷游戏源码Bomb-非常适合初学者学习,重要的事情说三遍

    bomblab实验

    请使用IDA Pro工具,反汇编bomb.exe 并调试该程序。 bomb.exe将要求你输入多个密码,只有输入正确的密码,才能继续执行程序,否则将“爆炸”。 利用IDA Pro的反汇编、调试功能,你应该可以破解该炸弹! bomb.exe ...

    系统级编程 Lab6-BInary Bomb.zip_Binary Bomb_lab06_系统级编程

    通过使用IDA pro7 来解决系统级编程实验 BInary Bomb

    bomblab实验报告.doc

    &lt;2&gt;实验内容包含 2 个文件 bomb(可执行文件)和 bomb.c(c 源文件)。 使用 gdb 工具反汇编出汇编代码,结合 c 语言文件找到每个关卡的入口函数。 分析汇编代码,找到在每个 phase 程序段中,引导程序跳转到 ...

    CMU_lab1_bomblab

    cmu 的课程计算机系统导论(《深入理解计算机系统》)里的lab1——bomblab拆解二进制炸弹的一个版本

    csapp binarybomb实验报告

    本资源是CSAPP配套实验二进制炸弹binarybomb的实验报告。 使用c32asm进行反编译,查看汇编代码比较方便 编译调试工具使用gdb, 常用命令:disassemb 查看当前函数的汇编代码 x/ 0x4061a2 查看内存 b 函数名 在函数...

    bomblab汇编代码

    bomblab反汇编代码.CMU大学的计算机实验课程。

    工具::bomb:工具

    :bomb: 工具v2021.4.103 错误显而易见:trade_mark:-MATRIX NodeJs LTS版本要求 &gt;=12.13.0 建立在NodeJ上 v14.15.4 必须使用async和await关键字。 仅支持最新的LTS变体。 安装NodeJ: ://nodejs.org/en/download/...

    bomb18答案

    bomb的答案,第18个的答案在里面,部分可以有其他答案

    Timebomb

    Timebomb

    bomblab.zip

    计算机系统结构的经典教程《深入理解计算机系统(CS:APP)》CMU镇校之课中bomblab实验的参考解答,欢迎大家下载

    bomb.zip

    bomb.zip

    unity 实现Bomb支付

    本资源为unity接Bomb支付SDK,实现支付功能,可用于自己开发的项目中。资源中包含源代码,字需要将ID改为自己在Bomb中申请的ID即可实现。

    CSAPP实验bomb炸弹破解

    CSAPP实验bomb拆炸弹实验,这个实验总体蛮有趣的。里面有详细的代码、破解过程和报告。

    CSAPP BombLab实验解决源码(亲测有效!!!)

    "Bomb实验" 是与CSAPP教材相关的一项编程实验。它是一种反汇编和逆向工程任务,旨在教授如何分析和解决复杂的程序问题。Bomb实验的目标是解开一系列的"炸弹",每个炸弹都有不同的解锁方法,需要分析程序的汇编代码,...

    bomb lab writeup

    bomblab writeup

    bomb18的详细解析

    里面有关于bomb18的所有解析及其分析,还有一些长哟给你指令

Global site tag (gtag.js) - Google Analytics