SDL 实现五子棋 GUI (二)
来源:互联网 发布:网络舆论 社会影响 编辑:程序博客网 时间:2024/05/18 00:16
好了, 经过之前简单的介绍, 我们就开始做一个 SDL 下的五子棋 GUI 吧!
首先还是做一些简单的介绍(关于什么是 SDL, 上一篇已经给出官方网站):
在 SDL 中, 制作的思路就是创建出 GUI 所需要的各个组件(图层), 在呈现的时候从最下面的一层一次"贴"到屏幕上面, 用户就能看到一个完整的 GUI 界面了. 同时使用主循环和相应的函数接收消息并作出响应, 每次循环和一些操作之后都要更新界面.
由于 SDL 的原始语言是 C 语言, 在 C++ 中时候之前可以对其进行封装, 这样有利于以后的调用以及异常处理. 封装过程不再累述, 给出 SDL 教程地址, 有兴趣的人可以自行前往学习:
再别流年的技术实验室, http://www.cppblog.com/lf426/category/6107.html?Show=All
Lazy Foo' Productions, http://lazyfoo.net/SDL_tutorials/index.php
我的程序中使用的基本框架也来自于教程, 后来为了加强功能又添加了一些成员函数以及修改了部分细节和异常处理过程.
那么...我们开始 PS 素材吧!
在这里要说一下, 作者是 PS 小白, 一个简单的 GUI 素材用了一整晚的时间, 参考了一些 PS 图文教程, 不会画画确实比较困难.
注: 本文只给出了 GUI 的实现部分, 不包括程序的 AI 和功能性逻辑结构. 及在目前的 GUI 中, 不能判断玩家是否胜利, 在同一个格子上也可以下两次及以上的棋. 在下一篇日志中我将给出一个可能的加入 AI 借口以后的代码. 至于 AI 怎么实现, 网上文献很多, 就不再讨论了(其实是自己的 AI 很渣, 羞愧).
注2: 要在 windows 下配置编译环境, 可以参考教程, 我会给出在 windows 下通过 Code::Blocks 配置的一篇简单文章.
以下是 GUI 类的定义:
以下是 SDLFONT 类的定义:
首先还是做一些简单的介绍(关于什么是 SDL, 上一篇已经给出官方网站):
在 SDL 中, 制作的思路就是创建出 GUI 所需要的各个组件(图层), 在呈现的时候从最下面的一层一次"贴"到屏幕上面, 用户就能看到一个完整的 GUI 界面了. 同时使用主循环和相应的函数接收消息并作出响应, 每次循环和一些操作之后都要更新界面.
由于 SDL 的原始语言是 C 语言, 在 C++ 中时候之前可以对其进行封装, 这样有利于以后的调用以及异常处理. 封装过程不再累述, 给出 SDL 教程地址, 有兴趣的人可以自行前往学习:
再别流年的技术实验室, http://www.cppblog.com/lf426/category/6107.html?Show=All
Lazy Foo' Productions, http://lazyfoo.net/SDL_tutorials/index.php
我的程序中使用的基本框架也来自于教程, 后来为了加强功能又添加了一些成员函数以及修改了部分细节和异常处理过程.
那么...我们开始 PS 素材吧!
在这里要说一下, 作者是 PS 小白, 一个简单的 GUI 素材用了一整晚的时间, 参考了一些 PS 图文教程, 不会画画确实比较困难.
首先, 我们需要准备一张棋板:
这里使用的是 560x560 像素, PS 网格间距 35 像素, 下载了个边框画笔.
之后我们 PS 一下程序的主界面, 800x600 像素:
其中棋盘左上角坐标(可以下子的区域为棋盘)为 (55, 55), 棋盘为 490x490 尺寸, 一个格子 35 像素. 特别地, 在 SDL 中坐标原点在窗体内部左上角, x 轴水平向右, y 轴竖直向下. 那些坐标信息以后会用到.
还缺什么呢? 棋子! 于是 PS 出这俩货
其中的高光弄得很郁闷, 毫无绘画功底, 更不懂高光.
现在基本齐全了, 不过...每下一盘棋以后还要关闭程序再运行? 好吧, 我们再弄出个 Start/Restart 按钮.
正常时候
鼠标经过
按下
现在素材就准备好了. 在面对枯燥的(我倒觉得蛮有意思)代码之前, 给出一张样品图
注: 本文只给出了 GUI 的实现部分, 不包括程序的 AI 和功能性逻辑结构. 及在目前的 GUI 中, 不能判断玩家是否胜利, 在同一个格子上也可以下两次及以上的棋. 在下一篇日志中我将给出一个可能的加入 AI 借口以后的代码. 至于 AI 怎么实现, 网上文献很多, 就不再讨论了(其实是自己的 AI 很渣, 羞愧).
注2: 要在 windows 下配置编译环境, 可以参考教程, 我会给出在 windows 下通过 Code::Blocks 配置的一篇简单文章.
然后开始写代码, 在这里我先给出界面实现的代码, 然后附带给出个各类的定义. 至于这些类怎么来的, 具体实现是什么, 代码量不小, 改写自教程. 完整的源代码及图片我打包以后放在下载里面, 免费下载学习哈(不知道要不要注册). 给出的文件中, /bin/release 下是一个已经编译好的版本.
void SDLGUI::startGame(){ //constant value const int SCREEN_WIDTH = 800; const int SCREEN_HEIGHT = 600; const int BIT_DEPTH = 32; const Uint32 FLAG = SDL_DOUBLEBUF | SDL_HWSURFACE; const int BOARD_Top = 55;//pixel const int BOARD_Left = 55;//pixel const int BOARD_WIDTH = 490; const int BOARD_HEIGHT = 490; const int PIXEL_PER_GRID = 35; const int BUTTON_X = 605; const int BUTTON_Y = 510; const int BLACK_ICON_X = 600; const int BLACK_ICON_Y = 180; const int WHITE_ICON_X = 600; const int WHITE_ICON_Y = 240; const int TEXT_BLACK_X = 660; const int TEXT_BLACK_Y = 177; const int TEXT_WHITE_X = 660; const int TEXT_WHITE_Y = 237; #ifdef __windows__ SDL_putenv("SDL_VIDEODRIVER=directx"); #endif #ifdef __linux__ SDL_putenv("SDL_VIDEODRIVER=dga"); #endif bool isQuit = false; bool isBlackTurn = true; // Alternate each round int row = 0; int col = 0; ScreenSurface screen(SCREEN_WIDTH, SCREEN_HEIGHT, BIT_DEPTH, FLAG, "MySDL"); PictureSurface backSurface("board.jpg", screen); PictureSurface blackStone("black.png", screen, true); PictureSurface whiteStone("white.png", screen, true); ButtonPlus button("button.png", "button_over.png", "button_press.png", screen, true); TextSurface txtBlackStone(int2string(0), screen, "verdana.ttf", 30, 0x00, 0x00, 0x00); TextSurface txtWhiteStone(int2string(0), screen, "verdana.ttf", 30, 0x00, 0x00, 0x00); //set back ground image backSurface.blit(); //set start button button.setBtnRegion(BUTTON_X, BUTTON_Y); button.blitOut(); //set stone counter icon and text blackStone.blit(BLACK_ICON_X, BLACK_ICON_Y); whiteStone.blit(WHITE_ICON_X, WHITE_ICON_Y); txtBlackStone.blit(TEXT_BLACK_X, TEXT_BLACK_Y); txtWhiteStone.blit(TEXT_WHITE_X, TEXT_WHITE_Y); screen.flip(); while (!isQuit){ //press ESC or click X to quit SDL_Event gameEvent; while(SDL_PollEvent(&gameEvent) != 0){ if (gameEvent.type == SDL_QUIT){ isQuit = true; } if (gameEvent.type == SDL_KEYUP){ if (gameEvent.key.keysym.sym == SDLK_ESCAPE){ isQuit = true; } } //lay down a stone if (gameEvent.type == SDL_MOUSEBUTTONDOWN){ if (gameEvent.button.y >= BOARD_Top && gameEvent.button.y <= BOARD_Top + BOARD_HEIGHT && gameEvent.button.x >= BOARD_Left && gameEvent.button.x <= BOARD_Left + BOARD_WIDTH){ row = (gameEvent.button.y - BOARD_Top) / PIXEL_PER_GRID; col = (gameEvent.button.x - BOARD_Left) / PIXEL_PER_GRID; //if the mouse position exceeds row+0.5 if ((gameEvent.button.y - BOARD_Top) % PIXEL_PER_GRID > (PIXEL_PER_GRID / 2)){ row++; } //if the mouse position exceeds col+0.5 GRID if ((gameEvent.button.x - BOARD_Left) % PIXEL_PER_GRID > (PIXEL_PER_GRID / 2)){ col++; } //lay down a stone if (isBlackTurn){ isBlackTurn = !isBlackTurn; blackStone.blit(BOARD_Left + col * PIXEL_PER_GRID - PIXEL_PER_GRID / 2, BOARD_Top + row * PIXEL_PER_GRID - PIXEL_PER_GRID / 2); //API BOARD board.counter_black txtBlackStone.setMessage(int2string(string2int(txtBlackStone.getMessage()) + 1)); backSurface.blit(TEXT_BLACK_X, TEXT_BLACK_Y, TEXT_BLACK_X, TEXT_BLACK_Y, txtBlackStone.getWidth(), txtBlackStone.getHeight()); txtBlackStone.blit(TEXT_BLACK_X, TEXT_BLACK_Y); } else{ //white player's turn isBlackTurn = !isBlackTurn; whiteStone.blit(BOARD_Left + col * PIXEL_PER_GRID - PIXEL_PER_GRID / 2, BOARD_Top + row * PIXEL_PER_GRID - PIXEL_PER_GRID / 2); //API BOARD board.counter_white txtWhiteStone.setMessage(int2string(string2int(txtWhiteStone.getMessage()) + 1)); backSurface.blit(TEXT_WHITE_X, TEXT_WHITE_Y, TEXT_WHITE_X, TEXT_WHITE_Y, txtWhiteStone.getWidth(), txtWhiteStone.getHeight()); txtWhiteStone.blit(TEXT_WHITE_X, TEXT_WHITE_Y); } }//if in board }//if mouse down //change button's look if (button.mouseOver(gameEvent) == true){ button.blitOver(); } else if (button.mouseDown(gameEvent) == true){ button.blitDown(); } else{ button.blitOut(); } //if game start btn is pressed if (button.effectiveClick(gameEvent) == true){ //reset the game backSurface.blit(); button.blitOut(); txtBlackStone.setMessage("0"); txtWhiteStone.setMessage("0"); //set stone counter icon and text blackStone.blit(BLACK_ICON_X, BLACK_ICON_Y); whiteStone.blit(WHITE_ICON_X, WHITE_ICON_Y); txtBlackStone.blit(TEXT_BLACK_X, TEXT_BLACK_Y); txtWhiteStone.blit(TEXT_WHITE_X, TEXT_WHITE_Y); } screen.flip(); }//while SDL_Delay(10); }//main loop return;}
以下是 GUI 类的定义:
#include "main.h"#include "surfaceClass.h"#include "buttonClass.h"#include "sdlFont.h"#ifndef SDLGUI_H#define SDLGUI_Hclass SDLGUI{ private: std::string int2string(int n); int string2int(std::string str); public: void startGame();};#endif
以下是 Surface 类的定义:
/**This file defines the GUI of game wuzi.And all code are based on SDL library.Classes are designed based on Long Fei's tutorialhttp://www.cppblog.com/lf426/*/#include"main.h"#ifdef __windows__//sdlFont.h include chinese rendering functions#include "sdlFont.h"#endif#ifndef SURFACECLASS_H#define SURFACECLASS_H//===============================//class ScreenSurface//===============================class ScreenSurface{ private: static int counter_screen;//ensure there is only one screen surface each progress int width; int height; int bitDepth; Uint32 flags; SDL_Surface* pScreen; std::string windowCaption; public: ScreenSurface(std::string caption=""); ScreenSurface(int w, int h, int dep=8, Uint32 f=0, std::string caption=""); ~ScreenSurface(); SDL_Surface* getPointer() const; void flip() const;//flip to dispaly on the screen void fillColor(Uint8 r=0x0, Uint8 g=0x0, Uint8 b=0x0) const; int getWeight() const{return width;} int getHeight() const{return height;} int getBitDepth() const{return bitDepth;} Uint32 getFlags() const{return flags;}};//===============================//class BaseSurface//===============================class BaseSurface{ private: // protected: SDL_Surface* pScreen; SDL_Surface* pSurface; BaseSurface(); public: BaseSurface(const BaseSurface& copy); virtual ~BaseSurface(); BaseSurface& operator=(const BaseSurface& copy); //surface's pointer SDL_Surface* getPointer() const; //blit surface to screen void blit() const; void blit(int any_num) const;// blit the whole source to destination void blit(int atDstX, int atDstY) const; void blit(int atDstX, int atDstY, int fromSrcX, int fromSrcY, int width, int height, int deltaX=0, int deltaY=0) const; //blit surface to other surface void blit(const BaseSurface& dstSurface) const; void blit(const BaseSurface& dstSurface, int any_num) const;// blit the whole source to destination void blit(const BaseSurface& dstSurface, int atDstX, int atDstY) const; void blit(const BaseSurface& dstSurface, int atDstX, int atDstY, int fromSrcX, int fromSrcY, int width, int height, int deltaX=2, int deltaY=2) const; //set transparent color void colorKey(Uint8 r, Uint8 g, Uint8 b, Uint32 flag=SDL_SRCCOLORKEY); int getWidth() const{return pSurface->w;} int getHeight() const{return pSurface->h;}};//====================================//class PictureSurface//====================================class PictureSurface: public BaseSurface{ private: std::string fileName; public: PictureSurface(std::string file_name, const ScreenSurface& screen, bool alpha = false);};//==================================================//class TextSurface, derived from class DisplaySurface//==================================================class TextSurface: public BaseSurface{ private: static int counter_textSurface; // release or QuitTTF lib when equals 0 std::string message; //the text to show std::string TTF_fileName; //the file name of .ttf int TTF_size; //font size Uint8 r, g, b; //font color public: TextSurface(const std::string& _message, const ScreenSurface& screen, const std::string& ttf_fileName, int ttf_size=12, Uint8 _r=0xFF, Uint8 _g=0xFF, Uint8 _b=0xFF); TextSurface(const TextSurface& copy); ~TextSurface(); //text tools void toBlended(); //render text in blended mode void toSolid(); //render text in solid mode void toShaded(Uint8 _r, Uint8 _g, Uint8 _b); //render text in shaded mode, //(_r, _g, _b) is the color of shade void setColor(Uint8 _r, Uint8 _g, Uint8 _b); //set font color void setSize(int ttf_size); //set font size void setFont(const std::string& ttf_fileName); //set font void setMessage(const std::string& _message); std::string getMessage();};#endif
以下是 SDLFONT 类的定义:
/**This file defines the class and functions tomake it possible use Chinese in SDL.Refers to http://fribidi.freedesktop.org/wikifribidi_char_sets_utf8.cSDL Tutorial written by Long Fei http://www.cppblog.com/lf426/*/#include "main.h"#include "iconv.h"#ifndef SDLFONT_H#define SDLFONT_H//returns the Unicode of each character in strstd::vector<Uint16> getUnicode(const std::string& str);//function UTF8toUNICODEint utf8toUnicode(Uint16* unicode, unsigned char* utf8, int len);//font rendering functionsSDL_Surface* chsTTF_RenderString_Blended(TTF_Font* font, const std::string& str, SDL_Color fg);SDL_Surface* chsTTF_RenderString_Solid(TTF_Font* font, const std::string& str, SDL_Color fg);SDL_Surface* chsTTF_RenderString_Shaded(TTF_Font* font, const std::string& str, SDL_Color fg, SDL_Color bg);#endif
以下是 BUTTON 类的定义:
/**This file defines the button class.Original source:Long Fei ( lf426 ), E-mail: zbln426@163.comLaboratory of ZaiBieLiunNianhttp://www.cppblog.com/lf426/modified by Shadow*/#include "surfaceClass.h"#ifndef BUTTONCLASS_H#define BUTTONCLASS_Hclass BaseButton{ private: // protected: int atX; //the left-top location of the button, int atY; //and is also the valid press region int offset; //used in the button skin blit() int w; //button width int h; //button height //Mouse state bool inBox; //mouse pointer is in the btn region bool clickDown; //mouse click down bool clickUp; //release mouse public: BaseButton(); virtual ~BaseButton(); void setBtnRegion(int at_x, int at_y, int _offset = 0); //set valid press region of the button virtual void colorKey(Uint8 r, Uint8 g, Uint8 b) = 0; //set the transparent color of the button image virtual void blitOut() const = 0; //blit picture when mouse is out of button virtual void blitOver() const = 0; //blit picture when mouse moves over the button virtual void blitDown() const = 0; //blit picture when press the button virtual void addText(const TextSurface& out_text, //attach the text const TextSurface& over_text) = 0; //to the btn surface bool mouseOver(const SDL_Event& gameEvent) const; bool mouseDown(const SDL_Event& gameEvent) const; bool mouseUp(const SDL_Event& gameEvent) const; //release the mouse in the btn region bool mouseUpOutside(const SDL_Event& gameEvent) const; //release the mouse outside the region bool effectiveClick(const SDL_Event& game_event); //check if click is valid, also is the main API of button class};class Button: public BaseButton{ private: // protected: BaseSurface outImg; BaseSurface overImg; public: Button(const std::string& outImg_fileName, const std::string& overImg_fileName, const ScreenSurface& screen, bool alpha = false); Button(const BaseSurface& out_img, const BaseSurface& over_img); Button(const std::string buttonText, const ScreenSurface& screen, Uint8 out_r = 0xFF, Uint8 out_g = 0xFF, Uint8 out_b = 0xFF, Uint8 on_r = 0, Uint8 on_g = 0, Uint8 on_b = 0xFF, int ttf_size = 28, const std::string& ttf_fileName = "./verdana.ttf"); virtual ~Button(); virtual void colorKey(Uint8 r = 0, Uint8 g = 0xFF, Uint8 b = 0xFF); virtual void blitOut() const; virtual void blitOver() const; virtual void blitDown() const; virtual void addText(const TextSurface& out_text, const TextSurface& over_text);};class ButtonPlus: public Button{ private: BaseSurface downImg; public: ButtonPlus(const std::string& outImg_fileName, const std::string& overImg_fileName, const std::string& downImg_fileName, const ScreenSurface& screen, bool alpha = false); ButtonPlus(const BaseSurface& out_img, const BaseSurface& over_img, const BaseSurface& down_img); virtual void colorKey(Uint8 r = 0, Uint8 g = 0xFF, Uint8 b = 0xFF); virtual void blitDown() const; virtual void addText(const TextSurface& out_text, const TextSurface& over_text);};class SpriteButton: public BaseButton{ private: PictureSurface spriteSheet; int outX; int outY; int overX; int overY; int downX; int downY; public: SpriteButton(const std::string& spriteSheet_fileName, const ScreenSurface& screen, int button_w, int button_h, int out_x, int out_y, int over_x, int over_y, int down_x, int down_y); virtual void colorKey(Uint8 r = 0, Uint8 g = 0xFF, Uint8 b = 0xFF); virtual void blitOut() const; virtual void blitOver() const; virtual void blitDown() const; virtual void addText(const TextSurface& out_text, const TextSurface& over_text);};#endif
- SDL 实现五子棋 GUI (二)
- SDL 实现五子棋 GUI (一)
- SDL 实现五子棋 GUI (三)
- SDL 实现五子棋 GUI (四) Code::Blocks 的配置
- 用javascript实现五子棋(二)
- 五子棋网络版JAVA实现(二)
- vc配合sdl编写五子棋游戏
- Android实现五子棋游戏(二) 人机对战实现
- pythonAI五子棋(二)
- Unity3D学习(2)——GUI五子棋
- SDL资料(二) 配置
- SDL学习(二)
- 【SDL】SDL学习笔记二 定时器
- Digital Oscilloscope GUI base on SDL.
- GUI(二)
- 五子棋设计与实现
- VB.net实现五子棋
- 五子棋算法实现
- inline 函数的使用小结之一
- 递归算法颠倒栈中的元素
- 单链表
- hdu 1514-Free Candies
- ZOJ-3633-Alice's present
- SDL 实现五子棋 GUI (二)
- Android开发中的一个小功能 清空搜索框的文字
- 2012 百度实习生笔试(1)
- windows xp 下配置PHP开发环境(apache2.2.22+mysql5.5.27+php5.2.8)
- 关于java.lang.ClassNotFoundException: org.hibernate.Session 异常的原因分析
- MapKit缩放和CAKeyframeAnimation类使用!
- PHP中读取文件的几个方法
- job client与jobStracker
- 2012 百度实习生笔试(2)