//main.cpp
#include <iostream>
#include <SDL2/SDL.h>
#include "sdl_initiator.hpp"
#include "sdl_error.hpp"
#include "sdl_window.hpp"
#include "sdl_surface.hpp"
#include "sdl_renderer.hpp"
#include "sdl_texture.hpp"
#include <SDL2/SDL_timer.h>
#include <thread>
#include "sdl_timer.hpp"
using namespace std;
//加载图片为纹理,并设置透明色
SDL_Texture* LoadBMPTexture(SDL_Renderer* renderer
, char const* filename
, Uint8 key_r, Uint8 key_g, Uint8 key_b)
{
sdl2::BitmapSurface bmp(filename);
if(!bmp)
{
return nullptr;
}
bmp.EnableColorKey(key_r, key_g, key_b, 0);
return sdl2::Texture(renderer, bmp._surface).Release();
}
//加载图片为纹理,不透明,不混色
SDL_Texture* LoadBMPTexture(SDL_Renderer* renderer
, char const* filename)
{
sdl2::BitmapSurface bmp(filename);
if(!bmp)
{
return nullptr;
}
return sdl2::Texture(renderer, bmp._surface).Release();
}
//加载图片为纹理,并设置透明色和混色
SDL_Texture* LoadBMPTexture(SDL_Renderer* renderer
, char const* filename
, Uint8 key_r, Uint8 key_g, Uint8 key_b
, Uint8 alpha_mod
, SDL_BlendMode blend_mode = SDL_BLENDMODE_BLEND)
{
sdl2::BitmapSurface bmp(filename);
if(!bmp)
{
return nullptr;
}
bmp.EnableColorKey(key_r, key_g, key_b, 0);
bmp.SetAlphaMod(alpha_mod);
bmp.SetBlendMode(blend_mode);
return sdl2::Texture(renderer, bmp._surface).Release();
}
int main(int argc, char* argv[])
{
sdl2::Initiator::Instance().Init(SDL_INIT_VIDEO
| SDL_INIT_AUDIO
| SDL_INIT_EVENTS
| SDL_INIT_TIMER);
if(!sdl2::Initiator::Instance())//重载转换符
{
cerr << "初始化就出错,没得玩了!"
<< sdl2::last_error() << endl;
}
//创建并居中显示宽640,高480的游戏窗口
sdl2::Window wnd("hello sdl"
, sdl2::WindowPosition()
, 640, 480
//去除原来的全屏标志
, sdl2::WindowFlags());
if(!wnd)
{
cerr << sdl2::last_error() << endl;
return -1;
}
//准备窗口的渲染器
sdl2::Renderer renderer(wnd._window);
if(!renderer)
{
cerr << sdl2::last_error() << endl;
return -1;
}
//重要!修改缩放质量配置
sdl2::RendererDriver::HintScaleQuality();
//重要!设置虚拟大小
renderer.SetLogicalSize(640, 480);
//准备背景图(不需要透明和混色)
sdl2::Texture bkgnd(LoadBMPTexture(renderer._renderer, "bkgnd.bmp"));
if(!bkgnd)
{
cerr << sdl2::last_error() << endl;
return -1;
}
//准备小马图,透明色为白色
sdl2::Texture horse(LoadBMPTexture(renderer._renderer
, "sdl.bmp"
, 0xff, 0xff, 0xff));
if(!horse)
{
cerr << sdl2::last_error() << endl;
return -1;
}
//准备白云图纹理,透明色为红色,不透明度188(0~255)
sdl2::Texture cloud(LoadBMPTexture(renderer._renderer
, "cloud.bmp"
, 0xff, 0, 0, 188));
if(!cloud)
{
cerr << sdl2::last_error() << endl;
return -1;
}
//定时器
sdl2::Timer timer;
//小马的宽度
int w = 0;
horse.GetSize(&w, nullptr);
//小马的起始位置,靠左侧站立
SDL_Rect horse_rect{-w, 65, 468, 350};
//事件循环
bool Q = false;
while(!Q)//一直循环,直到Q为真
{
SDL_Event event;
//会将队列中拖出的event数据存储到event中
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
Q = true;
break;
case SDL_KEYDOWN:
//即timer为空
if(event.key.keysym.sym == SDLK_t && !timer)//按键 ctrl + t,
{
int const horse_run_timer_code = 1;
timer.Start(500, horse_run_timer_code);
}
break;
case SDL_USEREVENT: //定时事件(用户自定义事件)
if(event.user.code == 1)
{
if(horse_rect.x <= 640)
horse_rect.x += 15;
else //出最右边了
timer.Stop();
}
break;
}
}//内循环
/*外循环:贴骏马图*/
//贴背景->窗口
renderer.CopyFrom(bkgnd._texture);
//贴第一朵白云
SDL_Rect cloud_rect_1{200, 20, 156, 78};
renderer.CopyFrom(cloud._texture, nullptr, &cloud_rect_1);
//贴第二朵白云
SDL_Rect cloud_rect_2{340, 6, 156, 78};
renderer.CopyFrom(cloud._texture, nullptr, &cloud_rect_2);
//贴骏马
// SDL_Rect dst_rect{86, 65, 468, 350};
renderer.CopyFrom(horse._texture, nullptr, &horse_rect);
renderer.Present();
sdl2::Timer::Delay(1);//防止cpu占用率太高
// Q = true; //开发过程中,为方便程序退出,暂时这样
}//外循环
return 0;
}
//sdl_timer.hpp
#ifndef SDL_TIMER_HPP_INCLUDED
#define SDL_TIMER_HPP_INCLUDED
namespace sdl2
{
struct Timer
{
Timer()
: _timer_id(0)
, _interval(0)
, _event_code(0)
, _user_data(nullptr)
{
}
~Timer()
{
if(_timer_id != 0)
{
SDL_RemoveTimer(_timer_id);
}
}
//顺便封装SDL_Delay(),静态方法
static void Delay(Uint32 ms)
{
SDL_Delay(ms);
}
bool Start(Uint32 interval
, Sint32 event_code = 0
, void* data = nullptr)
{
if(_timer_id != 0)//已经创建过了
return false;
this->_user_data = data;
this->_interval = interval;
this->_event_code = event_code;
//添加定时器
_timer_id = SDL_AddTimer(interval
, &Timer::Callback//回调
//回调函数中需要创建一个SDL_Event,需要
//用到this的数据,所以需要把this传递过去
, this); //定时器用户数据固定为this
return (_timer_id != 0);
}
//结束(移除)内部定时器
void Stop()
{
if(_timer_id != 0)
{
SDL_RemoveTimer(_timer_id);
_timer_id = 0;
}
}
explicit operator bool() const
{
return _timer_id != 0;
}
private:
static Uint32 Callback(Uint32 interval, void* param)
{
Timer* self = static_cast <Timer*> (param);
if(!self)
return 0;
SDL_Event event;
event.type = SDL_USEREVENT;
event.user.code = self->_event_code; //事件二级分类
//注意:事件的data被征用
//总是被用于记录定时器对象
event.user.data1 = self;
//data2才是用户自定义事件数据(可有可无)
event.user.data2 = self->_user_data;
if(1 != SDL_PushEvent(&event))
{
self->_timer_id = 0;
return 0; //添加事件失败,结束定时
}
return interval;
}
private:
SDL_TimerID _timer_id;
Uint32 _interval;
Sint32 _event_code;
void* _user_data;
};
}//sdl2
#endif // SDL_TIMER_HPP_INCLUDED