SDL_Engine游戏引擎制作 3-Window 游戏窗口

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

猜你喜欢

转载自blog.csdn.net/bull521/article/details/79694866