第一次寫俄羅斯方塊,完全是按照自己的想法做的。做完了很奇怪。 估計是按照相對坐標來算,好多的分支語句把自己都搞暈了。 所以決定放棄了,貼出來以祭奠。 設計的草稿是這樣的
棋子記錄狀態
棋盤根據棋子狀態進行判斷和繪制
主要檢測:
越界檢測:每次左移或者右移時檢測(在邊界內則移動否則不動)OK
觸底檢測:每次下降時檢測OK,也就是在時鐘記錄一次時探測。
消行檢測:觸底觸發時檢測
旋轉檢測:能否旋轉
檢測時首先根據棋子種類再根據棋子狀態進行篩選。
全局棋盤只在觸底時更新(檢測消行后的狀態),上部分在數組部分不更新 僅僅根據狀態由畫刷畫出。
觸發事件:
觸底時觸發產生新的方塊設置high_pos變量。
已經實現的功能:
越界檢測觸底檢測
旋轉檢測 旋轉檢測
代碼 這里下載,我想沒人愿意去找錯誤所在的。呵呵相當繁瑣。 如果大家有什么想法或者好的設計方法告訴我哈。非常樂意重新寫。 我聽同學說存儲每個圖形做比較簡單。可以減少分支判斷。 哈哈,第二天醒來終于意識到問題了,是數組的坐標系和圖形的坐標系混淆了。以及數組和方塊的參照系獨立的原因。 可以修改了。 現在的問題只剩下旋轉的時候會插到墻壁里,應該是個小問題。也是因為單個點記錄造成對整體的把握性下降。 所以只能重新用新的方法去設計。 vczh跟我說他以前寫過這個代碼,我就打算參照他的腳本寫的代碼用C++寫一個。這個腳本還真牛叉:
  1 unit Bricks 2  { 3 4 uses 5  { 6 Game, 7 Sound 8 } 9 10 layout 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 74 unitbox 75  { 76 } 77 78 script 79  { 80 81 Cell::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 89 void 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 112 Block 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 130 bool 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 150 bool 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 194 void 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 239 int 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 250 void Bricks::PutBlock() 251  { 252 CurBlock=NextBlock; 253 CurX=(Cols-CurBlock.Cols)/2; 254 CurY=Head-CurBlock.Rows; 255 NextBlock=Storage[GenerateBlock()].Copy(); 256 } 257 258 void 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 275 bool 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 290 void 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 305 void 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 349 void 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 398 Bricks::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 442 void 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 }
|