ClanLib的一个特别突出的方面是它避开传统型应用于许多框架中的回调模型,而引入了"信号和槽"模型。这种模型广泛应用于Boost C++库中,并在QT中得到实现。信号代表具有多个目标的回调函数,又在一些类似的系统中称作"出版者"或者"事件"。信号被连接到一些槽上,它们是回调函数接收器(也称作事件目标或者订户),当信号被"发出"时即被调用。信号具有类型安全的优点,它们避开了在传统型的框架中的不可避免的cast操作。
信号和槽被统一管理。在信号和槽中(或者更准确些说是,作为槽的一部分出现的对象)跟踪所有的连接,并当任何其一被破坏时能够自动地断开信号/槽连接。这能够使用户建立信号/槽连接而不需要花费多大的代价来管理那些连接以及所有包含于其中的对象的生命周期。在行105中,你只要捕获所有的键击("down")事件并确保使用了你自己的inputHandler()(见行168-216)。
105 CL_Slot keypress = CL_Keyboard::sig_key_down().connect(this, &Boxes::inputHandler); |
现在,你将开始初始化程序的音乐部分。首先,你用一个.wav格式的("binary")音乐文件装载一个CL_SoundBuffer,然后准备一个会话句柄以为玩游戏之用。下一步,你应用一个淡入淡出过滤器来异步地调整音量-在五秒(行 108-112)内把音量从零变化到最大音量的百分之六十。
106 CL_SoundBuffer *music = new CL_SoundBuffer("linemusic.ogg"); 107 CL_SoundBuffer_Session session = music->prepare(); 108 CL_FadeFilter *fade = new CL_FadeFilter(0.0f); 109 session.add_filter(fade); 110 session.set_looping(true); 111 session.play(); 112 fade->fade_to_volume(0.6f, 5000); 113 } |
drawBoard()方法绘制线段所在的点画格子图案,如,每个玩家赢得的红色的西红柿和蓝色的矢车菊框出的方格,还有模仿的光标。而最重要的代码行是第165行。CL_Display::flip()交换前后台缓冲区。后台缓冲区是在该帧中你绘制所有图形的地方,而前台缓冲区是显示在屏幕上的内容。
115 void Boxes::drawBoard() 116 { 117 CL_Display::clear(redturn ? CL_Color::red : CL_Color::blue); 118 CL_Display::fill_rect(CL_Rect(border/2, border/2, 119 winsize - border/2, winsize - border/2),CL_Color::black); 120 121 //画方框 122 for (int x = 0; x < boardsize - 1; x++) 123 for (int y = 0; y < boardsize - 1; y++) { 124 if (squares[x][y] == red) { 125 CL_Display::fill_rect(CL_Rect(x * spacing + border,y * spacing + border, x * spacing + border + spacing, 127 y * spacing + border + spacing),CL_Gradient(CL_Color::red, 128 CL_Color::red, CL_Color::tomato, CL_Color::tomato)); 129 redpict->draw(x * spacing + border + spacing / 2, 130 y * spacing + border + spacing / 2); 131 } 132 else if (squares[x][y] == blue) { 133 CL_Display::fill_rect(CL_Rect(x * spacing + border, 134 y * spacing + border,x * spacing + border +spacing, 135 y * spacing + border +spacing),CL_Gradient(CL_Color::blue, 136 CL_Color::blue, CL_Color::cornflowerblue,CL_Color::cornflowerblue)); 137 bluepict->draw(x * spacing + border + spacing / 2,y * spacing + border + spacing / 2); 139 } 140 } 141 142 //画线 143 for (int x = 0; x < boardsize; x++) { 144 for (int y = 0; y < boardsize - 1; y++) { 145 if (ver[x][y]) CL_Display::draw_line(x * spacing + border, 146 y * spacing + border,x * spacing + border, 147 y * spacing + border+ spacing,CL_Color::yellow); 148 if (hor[y][x]) CL_Display::draw_line(y * spacing + border, 149 x * spacing + border,y * spacing + border+ spacing,x * spacing + border,CL_Color::yellow); 151 } 152 } 153 154 //画格子 155 for (int x = 0; x < boardsize; x++) 156 for (int y = 0; y < boardsize; y++) 157 CL_Display::draw_rect(CL_Rect(x * spacing + border, 158 y * spacing + border,x * spacing + border + 2,159 y * spacing + border + 2),CL_Color::white); 160 161 //画光标 162 if (curs.vert) cursimg->draw((curs.x - 1) * spacing + border,int((curs.y - 0.5) * spacing + border)); 163 else cursimg->draw(int((curs.x - 0.5) * spacing + border),(curs.y - 1) * spacing + border); 164 165 CL_Display::flip(); 166 } |
你安装的inputHandler()函数用于观察在行105的按键信号。这个函数负责处理细节问题-把键击变成游戏运动,还有最重要的空格或者回车键-用于指示当前玩家的一个选择(行200-210)。然后,你要检查一下是否已完成了一个"方形"并把控制返回到原来的玩家。
168 void Boxes::inputHandler(const CL_InputEvent &i) 169 { 170 if (redturn) { 171 switch(i.id) { 172 case CL_KEY_LEFT: 173 case CL_KEY_G: 174 if (curs.x > 1) curs.x--; 175 break; 176 case CL_KEY_RIGHT: 177 case CL_KEY_J: 178 if (curs.x < boardsize) curs.x++; 179 break; 180 case CL_KEY_UP: 181 case CL_KEY_Y: 182 if (!curs.vert && curs.y > 1) { 183 curs.y--; 184 curs.vert = !curs.vert; 185 } 186 else if (curs.vert) curs.vert = false; 187 break; 188 case CL_KEY_DOWN: 189 case CL_KEY_H: 190 if (curs.vert && curs.y < boardsize) { 191 curs.y++; 192 curs.vert = !curs.vert; 193 } 194 else if (!curs.vert) curs.vert = true; 195 break; 196 } 197 if (curs.x == boardsize && !curs.vert) curs.x--; 198 if (curs.y == boardsize && curs.vert) curs.vert = false; 199 200 if (i.id == CL_KEY_SPACE || i.id == CL_KEY_ENTER) { 201 if (curs.vert) { 202 if (!ver[curs.x-1][curs.y-1]) { 203 ver[curs.x-1][curs.y-1] = true; 204 if (!findsquares()) redturn = !redturn; 205 } 206 } 207 else { 208 if (!hor[curs.x-1][curs.y-1]) { 209 hor[curs.x-1][curs.y-1] = true; 210 if (!findsquares()) redturn = !redturn; 211 } 212 } 213 } 214 } 215 } |
最后,由endOfGame()方法计算最后的得分。记住游戏还没有结束,直到板子满了为止(见行48)或者某人通过按下ESC键(见行46)退出。最后,你用大约1秒的时间把音量淡出到0。
217 void Boxes::endOfGame() 218 { 219 // 计数得分 220 int redscore, bluescore; 221 redscore = bluescore = 0; 222 for (int x = 0; x < boardsize - 1; x++) 223 for (int y = 0; y < boardsize - 1; y++) { 224 if (squares[x][y] == red) redscore++; 225 else if (squares[x][y] == blue) bluescore++; 226 } 227 228 cout << "Red: " << redscore << "/nBlue: " << bluescore << endl; 229 if (bluescore != redscore) 230 cout << (bluescore > redscore ? "Blue" : "Red") << " player wins/n"; 231 else cout << "It was a tie/n"; 232 233 if (fullup) { 234 fade->fade_to_volume(0.0f, 1000); 235 CL_System::sleep(1000); 236 } 237 } |
 
2/2 首页 上一页 1 2 |