多语言展示
当前在线:1799今日阅读:195今日分享:14

如何在MFC对话框中使用SDL2

MFC是开发windows桌面程序不二之选,舍弃MFC转向Win32开发或者使用其他第三库开发桌面程序无疑增加开发周期,说不定到最后还要推倒重来。笔者先前将SDL2游戏引擎移植到win32窗口中,采用win32 SDK实现。实际很多工程基于MFC开发,MFC与SDL图形引擎结合,将更易实现更花哨的效果,同时也不减MFC带来的便利,本文实现之。0如何将SDL2.0游戏引擎显示到Win32窗口中
方法/步骤
1

新建MFC应用程序,工程名称为MFCSDL

2

本例使用基于对话框的程序,注意勾选“基于对话框”

3

在MFCSDLDlg.h中添加SDL library 头文件和库文件应用,并定义所需变量。#include '../SDL2-2.0.3/include/sdl.h'#pragma comment(lib, '../SDL2-2.0.3/lib/x86/SDL2.lib')#define WINDOW_W    640#define WINDOW_H    480#define NUM_SPRITES 100#define MAX_SPEED   1static SDL_Window* window;static SDL_Renderer *renderer;static SDL_Texture * sprite;static int window_w, window_h;static int sprite_w, sprite_h;static SDL_Rect *positions, *velocities;

4

添加WM_KICKIDLE消息,该消息为微软保留消息,不公开,用它可以避免自己再重载实现消息循环。具体过程如下:1. 在 MFCSDLdlg.h文件加入afx_msg LRESULT OnKickIdle(WPARAM wParam, LPARAM lParam); 2. 在MFCSDLDlg.cpp中加入消息映射BEGIN_MESSAGE_MAP(CMFCSDLDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_MESSAGE(WM_KICKIDLE,OnKickIdle) ON_WM_CLOSE()END_MESSAGE_MAP()3.添加OnKickIdle消息实现。LRESULT CMFCSDLDlg::OnKickIdle(WPARAM wParam, LPARAM lParam){ SDL_Event event; int done = 0;    while (!done) {        /* Check for events */        while (SDL_PollEvent(&event)) {            switch (event.type) {            case SDL_WINDOWEVENT:                switch (event.window.event) {                case SDL_WINDOWEVENT_EXPOSED:                    SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);                    SDL_RenderClear(renderer);                    break;                }                break;            case SDL_QUIT:                done = 1;                break;            default:                break;            }        }        MoveSprites(renderer, sprite);    } return 0;   //一定要返回0}

5

在OnInitDialog函数中加入初始化代码。 BOOL CMFCSDLDlg::OnInitDialog(){ CDialogEx::OnInitDialog(); // 設定此對話方塊的圖示。當應用程式的主視窗不是對話方塊時, // 框架會自動從事此作業 SetIcon(m_hIcon, TRUE); // 設定大圖示 SetIcon(m_hIcon, FALSE); // 設定小圖示 // TODO: 在此加入額外的初始設定 window = SDL_CreateWindowFrom(m_hWnd); SDL_SetWindowTitle(window, 'SDL Native Window Test'); renderer = SDL_CreateRenderer(window, -1, 0); SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);    SDL_RenderClear(renderer); sprite = LoadSprite(renderer, 'icon.bmp'); SDL_GetWindowSize(window, &window_w, &window_h);    SDL_QueryTexture(sprite, NULL, NULL, &sprite_w, &sprite_h);    positions = (SDL_Rect *) SDL_malloc(NUM_SPRITES * sizeof(SDL_Rect));    velocities = (SDL_Rect *) SDL_malloc(NUM_SPRITES * sizeof(SDL_Rect));    if (!positions || !velocities) {        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 'Out of memory!\n');       // quit(2);    }    srand(time(NULL));    for (int i = 0; i < NUM_SPRITES; ++i) {        positions[i].x = rand() % (window_w - sprite_w);        positions[i].y = rand() % (window_h - sprite_h);        positions[i].w = sprite_w;        positions[i].h = sprite_h;        velocities[i].x = 0;        velocities[i].y = 0;        while (!velocities[i].x && !velocities[i].y) {            velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;            velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;        }    } return TRUE;  // 傳回 TRUE,除非您對控制項設定焦點}

6

在MFCSDLDlg.cpp中,添加LoadSprite函数,注意是static 全局函数,放在所有函数最上方。其作用是加载一个图片精灵,本例使用一个笑脸图片。static SDL_Texture *LoadSprite(SDL_Renderer *renderer, char *file){    SDL_Surface *temp;    SDL_Texture *sprite;    /* Load the sprite image */    temp = SDL_LoadBMP(file);    if (temp == NULL) {        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 'Couldn't load %s: %s', file, SDL_GetError());        return 0;    }    /* Set transparent pixel as the pixel at (0,0) */    if (temp->format->palette) {        SDL_SetColorKey(temp, 1, *(Uint8 *) temp->pixels);    }    /* Create textures from the image */    sprite = SDL_CreateTextureFromSurface(renderer, temp);    if (!sprite) {        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 'Couldn't create texture: %s\n', SDL_GetError());        SDL_FreeSurface(temp);        return 0;    }    SDL_FreeSurface(temp);    /* We're ready to roll. :) */    return sprite;}

7

在LoadSprite后添加MoveSprites函数,其作用是将精灵循环移动,实现动态效果。static voidMoveSprites(SDL_Renderer * renderer, SDL_Texture * sprite){ if(renderer==NULL||sprite==NULL) return;    int sprite_w, sprite_h;    int i;    SDL_Rect viewport;    SDL_Rect *position, *velocity;    /* Query the sizes */    SDL_RenderGetViewport(renderer, &viewport);    SDL_QueryTexture(sprite, NULL, NULL, &sprite_w, &sprite_h);    /* Draw a gray background */    SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);    SDL_RenderClear(renderer);    /* Move the sprite, bounce at the wall, and draw */    for (i = 0; i < NUM_SPRITES; ++i) {        position = &positions[i];        velocity = &velocities[i];        position->x += velocity->x;        if ((position->x < 0) || (position->x >= (viewport.w - sprite_w))) {            velocity->x = -velocity->x;            position->x += velocity->x;        }        position->y += velocity->y;        if ((position->y < 0) || (position->y >= (viewport.h - sprite_h))) {            velocity->y = -velocity->y;            position->y += velocity->y;        }        /* Blit the sprite onto the screen */        SDL_RenderCopy(renderer, sprite, NULL, position);    }    /* Update the screen! */    SDL_RenderPresent(renderer);}

8

以上完成,按F7编译,将icon.bmp文件拷贝到程序执行文件加下,运行程序,可看到如图效果。如果对读者有所帮助,请投一篇,thanks.

推荐信息