// screen.h
#ifndef SCREEN_H
#define SCREEN_H
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
#include <string>
#include <vector>
#include "shape.h"
#include "writetxt.h"
#include "coloradd.h"
#include <unordered_map>
#include "dynamicproperty.h"
#include <map>
#include <cmath>
typedef DynamicProperty DynProp; //定义动态属性类的别名
class Sprite; // 前向声明
extern std::map<std::string,std::string> named_shapes;
class Screen {
public:
std::unordered_map<std::string,DynamicProperty> property; //动态属性字典
Screen(const std::string& title = "C++ Sprites Library", int width = -1, int height =-1);
~Screen();
Screen& title(std::string s); //设定窗口标题
Screen& setup(int width,int height); //设定窗口宽高
std::string title(); //获取窗口标题
Screen& clear(); //清空屏幕
Screen& update(); // 手动刷新屏幕
bool update_mode(); //返回刷新模式,为真表示是自动刷新模式,为假则表示要手动刷新屏幕
bool tracer() ; //同上
Screen& update_mode(bool auto_update); // 设置自动/手动刷新模式
Screen& tracer(bool auto_update); // 同上,设置自动/手动刷新模式,因为Python turtle中有这个命令,它的本意是是否要追踪海龟的动作进行屏幕的刷新)
Screen& delay(unsigned int ms); // 设置全局延迟(毫秒)
unsigned int delay() const; // 获取当前延迟
void mainloop(); // 让程序进入主循环,保持窗口打开
void done(); // 同上,作为mainloop的别名
int width() const { return m_width; } //返回窗口宽度
int height() const { return m_height; } //返回窗口高度
std::string bgcolor(); //返回背景颜色
Screen& bgcolor(SDL_Color color); //设定背景颜色
Screen& bgcolor(int); //设定背景颜色,填一个整数表示的是色相 0-360
Screen& bgcolor(Uint8,Uint8,Uint8,Uint8=0); //设定背景颜色,四个整数分别表示RGBA
Screen& bgcolor(std::string color); //设定背景颜色
Screen& fill(SDL_Color color); //设定背景颜色
Screen& fill(Uint8,Uint8=0,Uint8=0,Uint8=0); //设定背景颜色
Screen& fill(std::string color); //设定背景颜色
//以下renderer方法不公开
SDL_Renderer* renderer() const { return m_renderer; } //返回渲染层
//以下canvas方法不公开
SDL_Texture* canvas() const { return m_canvas; } //返回画布(绘画的纹理)
//以下cmspriteslist向量不公开
std::vector<Sprite*> cmspriteslist; //普通角色列表 ,
//以下bgspriteslist向量不公开
std::vector<Sprite*> bgspriteslist; //角色可作为背景(在cmspriteslist中的角色前先渲染)
bool exitonclick(); //单击窗口关闭按钮会返回false ,可用于在循环中单击窗口关闭按钮退出循环
Screen& wait(float seconds); // 等待指定秒数(非阻塞),期间刷新画面和处理事件
Uint32 get_ticks() const; // 获取当前时间(毫秒)
SDL_Texture* loadbackground(const std::string imgpath); //加载纹理 ,先变成表面,然后从表面创建纹理,最后翻释放表面
SDL_Texture* addbackground(const std::string imgpath); //加载纹理 ,先变成表面,然后从表面创建纹理,最后翻释放表面
SDL_Texture* addbg(const std::string imgpath); //加载纹理 ,先变成表面,然后从表面创建纹理,最后翻释放表面
Screen& removebackground(const std::string imgpath); //移除背景
Screen& removebg(const std::string imgpath); //称除背景
Screen& bgpic(const std::string imgpath); //设定背景图片
Screen& next_bg(); //下一个背景
Screen& nextbg(); //下一个背景
Screen& next_background();//下一个背景
Screen& pre_bg();//上一个背景
Screen& prebg(); //上一个背景
Screen& pre_background(); //上一个背景
Screen& set_background(int index); //通过设定 bgtexturelist里的索引 指定纹理来设定背景
Screen& set_background(const std::string imgpath); //通过获取bgtexturedict里的纹理来设定背景
//以下3个方法不公开
void set_world_coordinate(); //设置为世界坐标系, m_is_world_coordinate 为真,则为世界坐标系,否则屏幕坐标系
void set_screen_coordinate(); //设置为屏幕坐标系
int get_coordinate(); //返回1表示当前为世界坐标系,返回-1表示当前为屏幕坐标系
Screen& xy_grid(int step); //在屏幕上绘制坐标格子,和坐标系无关
Screen& xygrid(int step); //在屏幕上绘制坐标格子,和坐标系无关
int xy_grid(); //返回坐标格子边长
int xygrid(); //返回坐标格子边长
void setpixel(int x,int y,Color color); //在x,y坐标设置像素值,即打一个点
void setpixel(int x,int y,SDL_Color color);//在x,y坐标设置像素值,即打一个点
//以下_setpixel方法不公开
void _setpixel(int x,int y,SDL_Color color);
Color getpixel(int x,int y,bool painting=false); //得到x,y坐标的像素值 ,默认为假表示取最终渲染的
std::string inputbox(std::string title, std::string prompt); //输入框
int messagebox(std::string title,std::string prompt,unsigned flags=SDL_MESSAGEBOX_INFORMATION); //消息输出框
/*
SDL_MESSAGEBOX_ERROR = 0x00000010, < error dialog 16
SDL_MESSAGEBOX_WARNING = 0x00000020, < warning dialog ,32
SDL_MESSAGEBOX_INFORMATION = 0x00000040, < informational dialog > 64
*/
//以下fillpolygon方法不公开,
Screen& fillpolygon(std::vector<Point> points,std::vector<SDL_Color> colors); // fillpolygon采用屏幕坐标系,传入参数需要转换 to_screen_xy ,两个向量size要一样才会画
bool savepng(const std::string& filename, bool painting=false); //截屏命令,这是截取整个窗口,filename为存储图像的文件名,painting表示是否把角色本身也截进去
bool savepng(const std::string& filename, SDL_Rect rect, bool painting=false); //截屏命令,截取矩形区域,filename为存储图像的文件名,rect表示要截取的矩形区域(默认世界坐标系),painting表示是否把角色本身也截进去
//以下的saveRenderToPNG方法不公开
bool saveRenderToPNG(const std::string& filename, const SDL_Rect& rect, bool painting=false); //无论哪个坐标系,这里的rect用的都是SDL2的屏幕坐标系
bool saveRenderToPNG(const std::string& filename, bool painting=false); //默认整个窗口截屏
private:
int m_gridstep; //格子边长 ,如果小于等于0,则不显示格子
int m_coordinate_type; //是否是世界坐标系,默认为1,为-1表示屏幕坐标系
bool m_is_updating; //是否正在刷新中
SDL_Color _bgcolour; //背景颜色
int m_width, m_height;
SDL_Window* m_window;
SDL_Renderer* m_renderer;
SDL_Texture* m_canvas; //画布
bool m_auto_update; //是否自动刷新
unsigned int m_delay; //全局延迟(毫秒)
void _bgcolor(Uint8,Uint8,Uint8,Uint8);
//角色管理接口
void addSprite(Sprite* sprite); // 向列表添加角色,刚开始所有创建的角色都会自动加入cmspriteslist
// bool out_cmspriteslist(Sprite* sprite); // 从普通角色列表中移除
// bool out_bgspriteslist(Sprite* sprite); //从背景角色列表中移除
bool is_updating();
TextRenderer& getTextRenderer() { return textRenderer; }
void destroy();
friend class Sprite; // 允许 Sprite 访问 renderer
//std::string curbgpath;
SDL_Texture* m_curbgtexture; //当前背景图片纹理
std::map<std::string,SDL_Texture*> bgtexturedict; //图片路径到纹理指针的映射
std::vector<SDL_Texture*> bgtexturelist; //背景纹理列表
int cur_bg_texture_index; //当前背景纹理索引,为-1表示没有背景纹理
void ResizeCanvas(int new_width, int new_height);
void _create_renderer_and_canvas();
TextRenderer textRenderer; // 文本渲染器
void _drawGrid( int m_gridstep);
bool m_cmlist_sort_flag ; // 标记是否cmspriteslist需要重新排序
bool m_bglist_sort_flag ; // 标记是否cmspriteslist需要重新排序
void set_m_cmlist_sort_flag(bool);
void set_m_bglist_sort_flag(bool);
};
// 添加全局变量的外部声明
extern Screen* g_screen;
#endif // SCREEN_H