第一次写俄罗斯方块,完全是按照自己的想法做的。做完了很奇怪。 估计是按照相对坐标来算,好多的分支语句把自己都搞晕了。 所以决定放弃了,贴出来以祭奠。 设计的草稿是这样的
棋子记录状态
棋盘根据棋子状态进行判断和绘制
主要检测:
越界检测:每次左移或者右移时检测(在边界内则移动否则不动)OK
触底检测:每次下降时检测OK,也就是在时钟记录一次时探测。
消行检测:触底触发时检测
旋转检测:能否旋转
检测时首先根据棋子种类再根据棋子状态进行筛选。
全局棋盘只在触底时更新(检测消行后的状态),上部分在数组部分不更新 仅仅根据状态由画刷画出。
触发事件:
触底时触发产生新的方块设置high_pos变量。
已经实现的功能:
越界检测触底检测
旋转检测 旋转检测
代码 这里下载,我想没人愿意去找错误所在的。呵呵相当繁琐。 如果大家有什么想法或者好的设计方法告诉我哈。非常乐意重新写。 我听同学说存储每个图形做比较简单。可以减少分支判断。 哈哈,第二天醒来终于意识到问题了,是数组的坐标系和图形的坐标系混淆了。以及数组和方块的参照系独立的原因。 可以修改了。 现在的问题只剩下旋转的时候会插到墙壁里,应该是个小问题。也是因为单个点记录造成对整体的把握性下降。 所以只能重新用新的方法去设计。 vczh跟我说他以前写过这个代码,我就打算参照他的脚本写的代码用C++写一个。这个脚本还真牛叉:
1unit Bricks 2{ 3 4uses 5{ 6 Game, 7 Sound 8} 9 10layout 11{ 12 13 class Cell 14 { 15 public: 16 var bool Used; 17 var Color Face; 18 var Color Bright; 19 var Color Dark; 20 21 Cell(); 22 }; 23 24 class Block 25 { 26 public: 27 var Color Face; 28 var Color Bright; 29 var Color Dark; 30 var int Cols; 31 var int Rows; 32 var bool Data[][]; 33 34 void Turn(ref int XOffset,ref int YOffset); 35 Block Copy(); 36 }; 37 38 class Bricks:IGame 39 { 40 protected: 41 var string DataPath; 42 var int Size; 43 var int Cols; 44 var int Rows; 45 var int Head; 46 var int Score; 47 var Cell Cells[][]; 48 var Block Storage[]; 49 var int UsedStorage; 50 51 var int CurX; 52 var int CurY; 53 var Block NextBlock; 54 var Block CurBlock; 55 var int LastIndex; 56 57 bool IsBeat(int X,int Y,Block Cur); 58 bool GetCellColor(int Col,int Row,ref Color Face,ref Color Bright,ref Color Dark); 59 void DrawMap(); 60 int GenerateBlock(); 61 void PutBlock(); 62 void Paste(); 63 bool CheckLine(int Row); 64 void Lost(); 65 void OnTimer(); 66 void LoadStorage(); 67 public: 68 Bricks(int Level); 69 void OnKeyDown(int KeyCode); 70 }; 71 72} 73 74unitbox 75{ 76} 77 78script 79{ 80 81Cell::Cell() 82{ 83 Used=false; 84 Face=new Color(0,0,0); 85 Bright=new Color(0,0,0); 86 Dark=new Color(0,0,0); 87} 88 89void Block::Turn(ref int XOffset,ref int YOffset) 90{ 91 var int NewCols; 92 var int NewRows; 93 var bool NewData[][]; 94 var int i; 95 var int j; 96 97 NewCols=Rows; 98 NewRows=Cols; 99 NewData=new bool[NewRows][NewCols]; 100 XOffset=Cols/2-NewCols/2; 101 YOffset=Rows/2-NewRows/2; 102 103 for(i=0;i<NewRows;i+=1) 104 for(j=0;j<NewCols;j+=1) 105 NewData[i][j]=Data[j][NewRows-i-1]; 106 107 Cols=NewCols; 108 Rows=NewRows; 109 Data=NewData; 110} 111 112Block Block::Copy() 113{ 114 var Block b; 115 var int i; 116 var int j; 117 b=new Block; 118 b.Face=Face; 119 b.Bright=Bright; 120 b.Dark=Dark; 121 b.Cols=Cols; 122 b.Rows=Rows; 123 b.Data=new bool[Rows][Cols]; 124 for(i=0;i<Rows;i+=1) 125 for(j=0;j<Cols;j+=1) 126 b.Data[i][j]=Data[i][j]; 127 return b; 128} 129 130bool Bricks::IsBeat(int X,int Y,Block Cur) 131{ 132 var int i; 133 var int j; 134 var int Col; 135 var int Row; 136 for(i=0;i<Cur.Rows;i+=1) 137 for(j=0;j<Cur.Cols;j+=1) 138 if(Cur.Data[i][j]) 139 { 140 Row=Y+i; 141 Col=X+j; 142 if(Col<0||Row<0||Col>=Cols||Row>=Rows) 143 return true; 144 else if(Cells[Row][Col].Used) 145 return true; 146 } 147 return false; 148} 149 150bool Bricks::GetCellColor(int Col,int Row,ref Color Face,ref Color Bright,ref Color Dark) 151{ 152 var Cell c; 153 c=Cells[Row][Col]; 154 if(c.Used) 155 { 156 Face=c.Face; 157 Bright=c.Bright; 158 Dark=c.Dark; 159 return true; 160 } 161 else if((Col>=Cols-NextBlock.Cols)&&(Row<NextBlock.Rows)) 162 { 163 Col-=Cols-NextBlock.Cols; 164 if(NextBlock.Data[Row][Col]) 165 { 166 Face=NextBlock.Face; 167 Bright=NextBlock.Bright; 168 Dark=NextBlock.Dark; 169 return true; 170 } 171 else 172 return false; 173 } 174 else if((Col>=CurX)&&(Col<CurX+CurBlock.Cols)&&(Row>=CurY)&&(Row<CurY+CurBlock.Rows)) 175 { 176 Col-=CurX; 177 Row-=CurY; 178 if(CurBlock.Data[Row][Col]) 179 { 180 Face=CurBlock.Face; 181 Bright=CurBlock.Bright; 182 Dark=CurBlock.Dark; 183 return true; 184 } 185 else 186 return false; 187 } 188 else 189 { 190 return false; 191 } 192} 193 194void Bricks::DrawMap() 195{ 196 var int Col; 197 var int Row; 198 var Color Face; 199 var Color Bright; 200 var Color Dark; 201 var int X1; 202 var int Y1; 203 var int X2; 204 var int Y2; 205 MainBuffer.Clear(new Color(0,0,0)); 206 for(Row=0;Row<Rows;Row+=1) 207 for(Col=0;Col<Cols;Col+=1) 208 { 209 if(GetCellColor(Col,Row,Face,Bright,Dark)) 210 { 211 X1=Col*Size; 212 Y1=Row*Size; 213 X2=X1+Size-1; 214 Y2=Y1+Size-1; 215 MainBuffer.SetPenColor(Face); 216 MainBuffer.SetBrushColor(Face); 217 MainBuffer.Rect(X1,Y1,X2+1,Y2+1); 218 MainBuffer.SetPenColor(Dark); 219 MainBuffer.Line(X2-1,Y1 ,X2-1,Y2 ); 220 MainBuffer.Line(X2 ,Y1 ,X2 ,Y2+1); 221 MainBuffer.Line(X1 ,Y2-1,X2 ,Y2-1); 222 MainBuffer.Line(X1 ,Y2 ,X2+1,Y2 ); 223 MainBuffer.SetPenColor(Bright); 224 MainBuffer.Line(X1 ,Y1 ,X2 ,Y1 ); 225 MainBuffer.Line(X1 ,Y1 ,X1 ,Y2+1); 226 MainBuffer.Line(X1 ,Y1+1,X2-1,Y1+1); 227 MainBuffer.Line(X1+1,Y1 ,X1+1,Y2 ); 228 } 229 } 230 MainBuffer.TextOut(0,0,"vczh积木"); 231 MainBuffer.TextOut(0,25,"Score:"+inttostr(Score)); 232 MainBuffer.TextOut(0,50,"按[ESC]退出"); 233 MainBuffer.TextOut(0,75,"按[ENTER]暂停/继续"); 234 MainBuffer.SetPenColor(new Color(255,255,128)); 235 MainBuffer.Line(0,Head*Size,MainBuffer.GetWidth(),Head*Size); 236 Refresh(); 237} 238 239int Bricks::GenerateBlock() 240{ 241 var int Index; 242 do 243 { 244 Index=Random(UsedStorage); 245 }while(Index==LastIndex); 246 LastIndex=Index; 247 return Index; 248} 249 250void Bricks::PutBlock() 251{ 252 CurBlock=NextBlock; 253 CurX=(Cols-CurBlock.Cols)/2; 254 CurY=Head-CurBlock.Rows; 255 NextBlock=Storage[GenerateBlock()].Copy(); 256} 257 258void Bricks::Paste() 259{ 260 var int i; 261 var int j; 262 var Cell cell; 263 for(i=0;i<CurBlock.Rows;i+=1) 264 for(j=0;j<CurBlock.Cols;j+=1) 265 if(CurBlock.Data[i][j]) 266 { 267 cell=Cells[i+CurY][j+CurX]; 268 cell.Used=true; 269 cell.Face=CurBlock.Face; 270 cell.Bright=CurBlock.Bright; 271 cell.Dark=CurBlock.Dark; 272 } 273} 274 275bool Bricks::CheckLine(int Row) 276{ 277 var int X; 278 var int Y; 279 for(X=0;X<Cols;X+=1) 280 if(!Cells[Row][X].Used) 281 return false; 282 for(Y=Row;Y>0;Y-=1) 283 for(X=0;X<Cols;X+=1) 284 Cells[Y][X]=Cells[Y-1][X]; 285 for(X=0;X<Cols;X+=1) 286 Cells[0][X]=new Cell; 287 return true; 288} 289 290void Bricks::Lost() 291{ 292 var int Col; 293 var int Row; 294 Score=0; 295 for(Row=0;Row<Rows;Row+=1) 296 for(Col=0;Col<Cols;Col+=1) 297 { 298 Cells[Row][Col].Used=false; 299 } 300 PutBlock(); 301 SetInterval(0.5); 302 DrawMap(); 303} 304 305void Bricks::OnTimer() 306{ 307 var int X; 308 var int Y; 309 var Block Cur; 310 var int CurScore; 311 X=CurX; 312 Y=CurY; 313 Cur=CurBlock.Copy(); 314 Y+=1; 315 if(IsBeat(X,Y,Cur)) 316 { 317 if(CurY<Head) 318 Lost(); 319 else 320 { 321 Paste(); 322 CurScore=10; 323 for(Y=CurY;Y<CurY+CurBlock.Rows;Y+=1) 324 if(CheckLine(Y)) 325 { 326 Score+=CurScore; 327 CurScore+=10; 328 } 329 if(Score<1000) 330 SetInterval(0.5); 331 else if(Score<2000) 332 SetInterval(0.333); 333 else if(Score<3000) 334 SetInterval(0.2); 335 else 336 SetInterval(0.1); 337 PutBlock(); 338 } 339 } 340 else 341 { 342 CurX=X; 343 CurY=Y; 344 CurBlock=Cur; 345 } 346 DrawMap(); 347} 348 349void Bricks::LoadStorage() 350{ 351 var DataFile df; 352 var DataBag bag; 353 var DataBag block; 354 var Block Item; 355 var int Count; 356 var int i; 357 var byte r; 358 var byte g; 359 var byte b; 360 var string data; 361 var int Row; 362 var int Col; 363 var int Index; 364 365 df=new DataFile; 366 df.LoadFromFile(DataPath+"Blocks.txt"); 367 bag=df.GetDataBag(); 368 UsedStorage=bag.Field("using").Item(0).GetInt(); 369 if(UsedStorage>=bag.GetFieldCount()) 370 UsedStorage=bag.GetFieldCount()-1; 371 Count=bag.GetFieldCount()-1; 372 Storage=new Block[Count]; 373 for(i=0;i<Count;i+=1) 374 { 375 Item=new Block; 376 Storage[i]=Item; 377 block=bag.Field(i+1); 378 r=block.Field("r").Item(0).GetInt(); 379 g=block.Field("g").Item(0).GetInt(); 380 b=block.Field("b").Item(0).GetInt(); 381 Item.Face=new Color(r,g,b); 382 Item.Bright=Item.Face.MakeOffset(100); 383 Item.Dark=Item.Face.MakeOffset(-100); 384 Item.Cols=block.Field("cols").Item(0).GetInt(); 385 Item.Rows=block.Field("rows").Item(0).GetInt(); 386 Item.Data=new bool[Item.Rows][Item.Cols]; 387 data=block.Field("data").Item(0).GetString(); 388 Index=0; 389 for(Row=0;Row<Item.Rows;Row+=1) 390 for(Col=0;Col<Item.Cols;Col+=1) 391 { 392 Item.Data[Row][Col]=data[Index]=='T'; 393 Index+=1; 394 } 395 } 396} 397 398Bricks::Bricks(int Level) 399{ 400 var int Col; 401 var int Row; 402 //初始化设定 403 DataPath=ExtractFilePath(ExeName())+"Data\\Bricks\\"; 404 base.IGame(); 405 if(Level==0) 406 { 407 Cols=12; 408 Rows=20; 409 } 410 else 411 { 412 Cols=16; 413 Rows=23; 414 } 415 Size=32; 416 Head=4; 417 //构造游戏窗口 418 SetTitle("VL++::JoveScript::Demo::Bricks"); 419 SetSize(Cols*Size,Rows*Size); 420 CreateApplication(); 421 MainBuffer=GetMainBuffer(); 422 MainBuffer.SetTextColor(new Color(255,255,128)); 423 MainBuffer.BuildFont("宋体",20,false,false,false); 424 MainBuffer.Clear(new Color(0,0,0)); 425 Refresh(); 426 //初始化数据 427 Score=0; 428 Cells=new Cell[Rows][Cols]; 429 for(Row=0;Row<Rows;Row+=1) 430 for(Col=0;Col<Cols;Col+=1) 431 Cells[Row][Col]=new Cell; 432 LoadStorage(); 433 if(Level==1)UsedStorage=length(Storage); 434 //启动游戏 435 LastIndex=-1; 436 NextBlock=Storage[GenerateBlock()].Copy(); 437 PutBlock(); 438 SetInterval(0.5); 439 TurnOnTimer(); 440} 441 442void Bricks::OnKeyDown(int KeyCode) 443{ 444 var int XOffset; 445 var int YOffset; 446 var int X; 447 var int Y; 448 var Block Cur; 449 X=CurX; 450 Y=CurY; 451 Cur=CurBlock.Copy(); 452 if(!TimerEnabled&&KeyCode!=13)return; 453 switch(KeyCode) 454 { 455 case 38: 456 Cur.Turn(XOffset,YOffset); 457 X+=XOffset; 458 Y+=YOffset; 459 if(X<0) 460 X=0; 461 else if(X+Cur.Cols>Cols) 462 X=Cols-Cur.Cols; 463 if(!IsBeat(X,Y,Cur)) 464 { 465 CurX=X; 466 CurY=Y; 467 CurBlock=Cur; 468 DrawMap(); 469 } 470 break; 471 case 37: 472 X-=1; 473 if(!IsBeat(X,Y,Cur)) 474 { 475 CurX=X; 476 DrawMap(); 477 } 478 break; 479 case 39: 480 X+=1; 481 if(!IsBeat(X,Y,Cur)) 482 { 483 CurX=X; 484 DrawMap(); 485 } 486 break; 487 case 40: 488 OnTimer(); 489 break; 490 case 13: 491 if(TimerEnabled) 492 TurnOffTimer(); 493 else 494 TurnOnTimer(); 495 } 496} 497 498} 499}
|