SDL编写程序的第一步先是初始化SDL,然后就是创建窗口。然后就是创建基于本窗口的渲染器(Renderer 姑且称为渲染器吧)。SDL中的窗口为SDL_Window,是一个结构体,与之对应的有各种与窗口处理相关的函数,比如窗口创建和销毁函数,最大化或最小化窗口等等。下面先简单地说一下常用的几个函数。
1.SDL_Init() 初始化SDL库。这个函数一定要在使用大多数SDL函数前被调用。(类似的有SDL_InitSubSystem 初始化子系统)
2.SDL_CreateWindow函数。在特定的位置,尺寸以及标识(flags)创建一个窗口。
3.SDL_DestroyWindow。销毁创建的窗口 与SDL_CreateWindow对应使用。
4.SDL_Quit()。清除全部初始化的子系统,与SDL_Init功能相反。
5.SDL__GetTicks()。获取从SDL库初始化到现在经过的毫秒,返回值为Uin32(Unsigned int)
6.SDL_PollEvent()。从事件队列中拉取事件。
SDL_Window以及对应的一部分操作函数封装成Window类。
Window.h
#ifndef __Window_H__
#define __Window_H__
#include "SDL.h"
#include "Object.h"
NS_SDL_BEGIN
class Surface;
class Renderer;
class Size;
class Window:public Object
{
private:
SDL_Window*_window;
//窗口坐标和大小
SDL_Point _position;
int _width;
int _height;
public:
Window();
~Window();
static Window*create(const char*title,int x,int y,int width,int height,Uint32 flags);
bool init(const char*title,int x,int y,int width,int height,Uint32 flags);
//更新
int updateWindowSurface();
//获得窗口的surface
Surface*getWindowSurface();
//显示窗口
void showWindow();
//隐藏窗口
void hideWindow();
//获得窗口大小
Size getWindowSize()const;
//获得窗口真实大小
Size getRealWindowSize()const;
//更新窗口位置并返回
SDL_Point getWindowPosition();
//Renderer作为友元
friend class Renderer;
};
NS_SDL_END
#endif
Window.cpp
#include "Window.h"
//#include "Surface.h"
#include "Size.h"
NS_SDL_BEGIN
Window::Window()
{
_window = NULL;
}
Window::~Window()
{
SDL_DestroyWindow(_window);
_window = nullptr;
}
bool Window::init(const char*title,int x,int y,int width,int height,Uint32 flags)
{
_window = SDL_CreateWindow(title,x,y,width,height,flags);
//initlize
_position.x = x;
_position.y = y;
_width = width;
_height = height;
return true;
}
Window*Window::create(const char*title,int x,int y,int width,int height,Uint32 flags)
{
Window* window = new Window();
if(window && window->init(title,x,y,width,height,flags))
window->autorelease();
else
SDL_SAFE_DELETE(window);
return window;
}
int Window::updateWindowSurface()
{
if(_window)
return SDL_UpdateWindowSurface(_window);
return -1;
}
Surface* Window::getWindowSurface()
{
/* if(_window)
return Surface::create(SDL_GetWindowSurface(_window));*/
return NULL;
}
void Window::showWindow()
{
SDL_ShowWindow(_window);
}
void Window::hideWindow()
{
SDL_HideWindow(_window);
}
Size Window::getWindowSize()const
{
return Size(_width,_height);
}
Size Window::getRealWindowSize()const
{
int w = 0;
int h = 0;
SDL_GetWindowSize(_window,&w,&h);
return Size((float)w,(float)h);
}
SDL_Point Window::getWindowPosition()
{
if(_window)
SDL_GetWindowPosition(_window,&_position.x,&_position.y);
return _position;
}
NS_SDL_END
当前还没有实现Surface,不过对目前来说不影响。接下来就是更新main.cpp文件了(注意要在SDL_Engine中添加Window.h等头文件)
main.cpp
#include <iostream>
#include "SDL_Engine.h"
#include "SDL.h"
#include "vld.h"
USING_NS_SDL;
using namespace std;
//更新
void update(float dt);
//事件处理
void handleEvents();
bool g_bRunning = true;
int main(int argc,char** argv)
{
float secondsPerFrame = 1.f/60.f;
float time = 0.f;
Uint32 nextTick = 0u;
Uint32 lastTick = 0u;
int currentFrame = 0;
//初始化全部子系统
SDL_Init(SDL_INIT_EVERYTHING);
//创建窗口
Window* window = Window::create("SDL_Engine test",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,800,480,SDL_WINDOW_SHOWN);
window->retain();
//游戏循环
while (g_bRunning)
{
Uint32 currentTick = SDL_GetTicks();
if(currentTick >= nextTick)
{
//帧率固定为方便调试
float dt = secondsPerFrame;
time += (currentTick - lastTick) / 1000.f;
lastTick = currentTick;
nextTick = lastTick + (Uint32)(secondsPerFrame * 1000);
//显示当前帧数
if (time >= 1.f)
{
time -= 1.f;
printf("%d\n",currentFrame);
currentFrame = 0;
}
else
currentFrame++;
//TODO
update(dt);
}
handleEvents();
PoolManager::getInstance()->getCurReleasePool()->clear();
}
window->release();
PoolManager::purge();
_CrtDumpMemoryLeaks();
return 0;
}
void update(float dt)
{
}
void handleEvents()
{
SDL_Event event = {};
//对事件进行轮询
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT: g_bRunning = false; break;
}
}
}
注意main函数和一般的c/c++的main函数是有区别的。#define main SDL_main。
对于SDL的main函数,是必须要为(int argc, char *argv[])或者(int argc,char** argv)的,两者并没有实质的区别。
main函数中,先创建了一个窗口,之后判断窗口是否创建成功,然后进入游戏循环,进行FPS(Frame Per Second)控制,现在的update函数是空函数,以后会添加一些绘图函数或者逻辑控制。handleEvents函数则是对SDL的事件进行接收并处理,如果没有事件处理的话,新建出来的窗口是无法操作的,即无法进行最小化,窗口移动等。handleEvents()函数目前也仅仅添加了一个退出功能。
可以看到,控制台显示的是FPS(一般稳定在60左右),右边的那个白色窗口则是我们以后的游戏窗口了。
本节代码:链接:https://pan.baidu.com/s/10oCETHrNuwkmm69TbvNVAA 密码:mtu1