Problem with Tetris game I am making
Blitz3D Forums/Blitz3D Beginners Area/Problem with Tetris game I am making
| ||
I am making a Tetris like game in order to learn Blitz Basic - this is my first real attempt so please forgive the n00b code. I have got quite a long way (although my code is very messy). I am having problems with my shapes - they are made up of 4 cubes with 1 as the parent entity. If a non-parent cube hits a wall then it goes behind another one of the cubes. If I put collision detection on the actual cubes to prevent this, it has strange effects on my shape as it moves. Take a look - you'll quickly see what I mean. Any suggestions on how to fix this most appreciated. Also suggestions on better ways to do things would be useful. Thanks, here's my code: [CODE] ;;;;;;;;;;;;;;;;;;;; ; ; ; Main starts here ; ; ; ;;;;;;;;;;;;;;;;;;;; Graphics3D 800,600 SetBuffer BackBuffer() Camera = CreateCamera() CameraViewport Camera,0,0,GraphicsWidth(),GraphicsHeight() Light = CreateLight() Dim Block(4) Block(1) = InitGame() SeedRnd = MilliSecs() ShapeType = Rnd(7) Block(2) = NewShape(ShapeType,2) Block(3) = NewShape(ShapeType,3) Block(4) = NewShape(ShapeType,4) Timer = CreateTimer(5) Dim Grid(11,20) While Not KeyHit(1) Frames = WaitTimer(Timer) For k = 1 To Frames x = 0 y = -2 StopCollision = 0 Collision = 0 LCollision = 0 RCollision = 0 For c = 1 To 4 If EntityCollided(Block(c),1) Collision = 1 If CollisionNX(Block(c),1) > 0 LCollision = 1 End If If CollisionNX(Block(c),1) < 0 RCollision = 1 End If If CollisionNY(Block(c),1) = 1 StopCollision = 1 End If End If Next If KeyHit(203) If LCollision = 0 x = -2 End If End If If KeyHit(205) If RCollision = 0 x = 2 End If End If ;If KeyHit(200) ; TurnEntity Block(1),0,0,90 ; For a = 1 To 4 ; TurnBack = 0 ; If EntityCollided(Block(a),1) ; TurnBack = 1 ; End If ; If TurnBack = 1 ; TurnEntity Block(1),0,0,-90 ; End If ; Next ;End If If StopCollision = 1 For a = 1 To 4 If Not a = 1 AdjX = EntityX(Block(1)) + EntityX(Block(a)) AdjY = EntityY(Block(1)) + EntityY(Block(a)) Else AdjX = EntityX(Block(1)) AdjY = EntityY(Block(1)) End If ValX = AdjX/2 + 6 ValY = AdjY/2 + 10 Grid(ValX,ValY) = PlaceBlock() PositionEntity Grid(ValX,ValY),AdjX,AdjY,30 EntityType Grid(ValX,ValY),1 Next FreeEntity Block(1) For r = 1 To 20 Full = 1 For c = 1 To 11 If Grid(c,r) = 0 Full = 0 End If Next If Full = 1 For c = 1 To 11 FreeEntity Grid(c,r) Grid(c,r) = 0 Next For s = r + 1 To 20 For c = 1 To 11 If Not Grid(c,s) = 0 TranslateEntity Grid(c,s),0,-2,0 Grid(c,s-1) = Grid(c,s) Grid(c,s) = 0 End If Next Next End If Next Block(1) = NewBlock() ShapeType = Rnd(7) Block(2) = NewShape(ShapeType,2) Block(3) = NewShape(ShapeType,3) Block(4) = NewShape(ShapeType,4) Else TranslateEntity Block(1),x,y,0 End If UpdateWorld Next RenderWorld ; o = 10 ; q = 10 ; ; For r = 1 To 20 ; ; For c = 1 To 11 ; ; If Grid(c,r) = 0 ; ; Text p,q,"0" ; ; Else ; ; Text p,q,"X" ; ; End If ; ; p = p + 10 ; ; Next ; ; q = q + 10 ; ; p = 10 ; ; Next Flip Wend ;;;;;;;;;;;;;;;;;;;; ; ; ; Main ends here ; ; ; ;;;;;;;;;;;;;;;;;;;; Function InitGame() For a = 0 To 20 Step 2 x = -10 + a BottomWall = CreateCube() PositionEntity BottomWall,x,-20,30 EntityType BottomWall,1 Next For a = 0 To 40 Step 2 y = 20 - a LeftWall = CreateCube() PositionEntity LeftWall,-12,y,30 EntityType LeftWall,1 RightWall = CreateCube() PositionEntity RightWall,12,y,30 EntityType RightWall,1 Next aBlock = NewBlock() Return aBlock End Function Function NewShape(ShapeType,BlockNo) aBlock = CreateCube(Block(1)) EntityRadius aBlock,0.5 EntityType aBlock,2 EntityColor aBlock,100,100,100 Select ShapeType Case 1 Select BlockNo Case 2 PositionEntity aBlock,0,2,0 Case 3 PositionEntity aBlock,0,4,0 Case 4 PositionEntity aBlock,0,6,0 End Select Case 2 Select BlockNo Case 2 PositionEntity aBlock,2,0,0 Case 3 PositionEntity aBlock,0,2,0 Case 4 PositionEntity aBlock,0,4,0 End Select Case 3 Select BlockNo Case 2 PositionEntity aBlock,-2,0,0 Case 3 PositionEntity aBlock,0,2,0 Case 4 PositionEntity aBlock,0,4,0 End Select Case 4 Select BlockNo Case 2 PositionEntity aBlock,0,2,0 Case 3 PositionEntity aBlock,0,4,0 Case 4 PositionEntity aBlock,2,2,0 End Select Case 5 Select BlockNo Case 2 PositionEntity aBlock,0,2,0 Case 3 PositionEntity aBlock,2,2,0 Case 4 PositionEntity aBlock,2,0,0 End Select Case 6 Select BlockNo Case 2 PositionEntity aBlock,2,0,0 Case 3 PositionEntity aBlock,2,2,0 Case 4 PositionEntity aBlock,4,2,0 End Select Case 7 Select BlockNo Case 2 PositionEntity aBlock,0,2,0 Case 3 PositionEntity aBlock,-2,2,0 Case 4 PositionEntity aBlock,2,0,0 End Select End Select Collisions 2,1,1,1 Return aBlock End Function Function NewBlock() aBlock = CreateCube() EntityRadius aBlock,0.5 PositionEntity aBlock,0,22,30 EntityType aBlock,2 EntityColor aBlock,150,100,100 Return aBlock End Function Function PlaceBlock() aBlock = CreateCube() EntityRadius aBlock,0.5 EntityType aBlock,1 EntityColor aBlock,100,100,100 Return aBlock End Function [/CODE] |
| ||
I'd love to sort this out for you, but that will need time... I first need to install Blitz on my new PC, and then try the entire code... Bugfixing other people's code is not really my forte... |
| ||
I wouldn't use the built-in collision detection for this. Blitz's collision detection is great for what it is designed for, semi-realistic in an arbitrary level, but Tetris is neither realistic nor arbitrary. What I would do is check manually, by comparing block positions and the wall, before moving if the shape is already abutting the wall, in which case I won't move it. Along the same lines I would represent the blocks at the bottom of the level in an array and check that array before moving the shape down. If the shape has landed on blocks then add the shape to the array. |
| ||
In the Tetris game that I completed a few weeks ago, I have the entire playfiled stored in a 2 dimensional array Playfield(x,y) and before I move the blocks I check to see if the piece can't move any further or if it has reached the left or right wall. If it can't move anymore I place the block into the array. I have a rutine that checks the entire array for filled lines and if there is any they are deleted and everything is moved down. The current block is not part of the array until it can't move anymore. Until then it is moved seperately on top of the playfield. I hope that helps. |
| ||
Thanks for the help guys. I am already storing stationary blocks in an array that scans for full lines. It clears if there is a full line and moves the rest of the array down. So I should be able to use this for the collision detection too. Thanks again. |
| ||
Okay, it seems to be working now. For anyone who's interested here is the code I came up with. Cursors move and rotate. Any suggestions on improvements so far welcome. [CODE] ;;;;;;;;;;;;;;;;;;;; ; ; ; Main starts here ; ; ; ;;;;;;;;;;;;;;;;;;;; Dim Grid(11,20) ; Cube,Gridx,Gridy,Left,Right,Down,Rotate,Realx,Realy Dim Block(4,9) Timer = InitGame() While Not KeyHit(1) Frames = WaitTimer(Timer) For k = 1 To Frames MoveShape() UpdateWorld Next RenderWorld Flip Wend ;;;;;;;;;;;;;;;;;;;; ; ; ; Main ends here ; ; ; ;;;;;;;;;;;;;;;;;;;; Function InitGame() Graphics3D 800,600 SetBuffer BackBuffer() Camera = CreateCamera() CameraViewport Camera,0,0,GraphicsWidth(),GraphicsHeight() Light = CreateLight() For a = 0 To 20 Step 2 x = -10 + a BottomWall = CreateCube() PositionEntity BottomWall,x,-20,30 Next For a = 0 To 40 Step 2 y = 20 - a LeftWall = CreateCube() PositionEntity LeftWall,-12,y,30 RightWall = CreateCube() PositionEntity RightWall,12,y,30 Next NewShape() Timer = CreateTimer(5) Return Timer End Function Function NewShape() SeedRnd = MilliSecs() ShapeType = Rnd(1,7) For a = 1 To 4 Block(a,1) = NewBlock(ShapeType,a) Next End Function Function NewBlock(ShapeType,BlockNo) If BlockNo = 1 aBlock = CreateCube() PositionEntity aBlock,0,22,30 EntityColor aBlock,150,100,100 Else aBlock = CreateCube(Block(1,1)) EntityColor aBlock,100,100,100 Select ShapeType Case 1 Select BlockNo Case 2 PositionEntity aBlock,0,2,0 Case 3 PositionEntity aBlock,0,4,0 Case 4 PositionEntity aBlock,0,6,0 End Select Case 2 Select BlockNo Case 2 PositionEntity aBlock,2,0,0 Case 3 PositionEntity aBlock,0,2,0 Case 4 PositionEntity aBlock,0,4,0 End Select Case 3 Select BlockNo Case 2 PositionEntity aBlock,-2,0,0 Case 3 PositionEntity aBlock,0,2,0 Case 4 PositionEntity aBlock,0,4,0 End Select Case 4 Select BlockNo Case 2 PositionEntity aBlock,0,2,0 Case 3 PositionEntity aBlock,0,4,0 Case 4 PositionEntity aBlock,2,2,0 End Select Case 5 Select BlockNo Case 2 PositionEntity aBlock,0,2,0 Case 3 PositionEntity aBlock,2,2,0 Case 4 PositionEntity aBlock,2,0,0 End Select Case 6 Select BlockNo Case 2 PositionEntity aBlock,2,0,0 Case 3 PositionEntity aBlock,2,2,0 Case 4 PositionEntity aBlock,4,2,0 End Select Case 7 Select BlockNo Case 2 PositionEntity aBlock,0,2,0 Case 3 PositionEntity aBlock,-2,2,0 Case 4 PositionEntity aBlock,2,0,0 End Select End Select End If Return aBlock End Function Function MoveShape() LBlocked = 0 RBlocked = 0 DBlocked = 0 ;Rotate If KeyHit(200) TurnEntity Block(1,1),0,0,90 TurnBack = 0 For a = 1 To 4 TranslateToGrid(a) CheckRotate(a) If Block(a,7) = 1 TurnBack = 1 End If Next If TurnBack = 1 TurnEntity Block(1,1),0,0,-90 End If End If ;CheckMovement For a = 1 To 4 TranslateToGrid(a) CheckMovement(a) If Block(a,4) = 1 LBlocked = 1 End If If Block(a,5) = 1 RBlocked = 1 End If If Block(a,6) = 1 DBlocked = 1 End If Next x=0 y=-2 If KeyHit(203) If Not LBlocked = 1 x = -2 End If End If If KeyHit(205) If Not RBlocked = 1 x = 2 End If End If If DBlocked = 1 MoveToGrid() CheckFull() NewShape() Else TranslateEntity Block(1,1),x,y,0 End If End Function Function TranslateToGrid(BlockNo) x = EntityX(Block(BlockNo,1),True) y = EntityY(Block(BlockNo,1),True) a = x/2 + 6 b = y/2 + 10 Block(BlockNo,2) = a Block(BlockNo,3) = b Block(BlockNo,8) = x Block(BlockNo,9) = y End Function Function CheckMovement(BlockNo) Blockx = Block(BlockNo,2) Blocky = Block(BlockNo,3) For a = 4 To 6 Block(BlockNo,a) = 0 Next ;CheckLeft If Blockx = 1 Block(BlockNo,4) = 1 Else If Blocky <= 20 If Not Grid(Blockx-1,Blocky-1) = 0 Block(BlockNo,4) = 1 End If End If End If ;CheckRight If Blockx = 11 Block(BlockNo,5) = 1 Else If Blocky <= 20 If Not Grid(Blockx+1,Blocky-1) = 0 Block(BlockNo,5) = 1 End If End If End If ;CheckDown If Blocky = 1 Block(BlockNo,6) = 1 Else If Blocky <= 21 If Not Grid(Blockx,Blocky-1) = 0 Block(BlockNo,6) = 1 End If End If End If End Function Function MoveToGrid() For a = 1 To 4 If Not Block(a,3) > 20 Grid( Block(a,2),Block(a,3) ) = CreateCube() PositionEntity Grid( Block(a,2),Block(a,3) ),Block(a,8),Block(a,9),30 EntityColor Grid( Block(a,2),Block(a,3) ),100,100,100 Else GameOver() End If Next FreeEntity Block(1,1) End Function Function CheckFull() For r = 1 To 20 Full = 1 For c = 1 To 11 If Grid(c,r) = 0 Full = 0 End If Next If Full = 1 For c = 1 To 11 FreeEntity Grid(c,r) Grid(c,r) = 0 Next For s = r + 1 To 20 For c = 1 To 11 If Not Grid(c,s) = 0 TranslateEntity Grid(c,s),0,-2,0 Grid(c,s-1) = Grid(c,s) Grid(c,s) = 0 End If Next Next CheckFull() End If Next End Function Function GameOver() ClearWorld Stop End Function Function CheckRotate(BlockNo) Blockx = Block(BlockNo,2) Blocky = Block(BlockNo,3) Block(BlockNo,7) = 0 If Blockx < 1 Or Blockx > 11 Or Blocky < 2 Block(BlockNo,7) = 1 End If If Blocky < 20 If Not Grid(Blockx,Blocky) = 0 Block(BlockNo,7) = 1 End If End If End Function [/CODE] |
| ||
Daniel, If this is your first game on Blitz, I look forward to seeing more!! Keep it up - great job! Robert. |
| ||
Thanks Robert, I'm still working on it but it's shaping up quite well now. I've added colours to the blocks and also it now shows the next shape. Just need to add a score counter and also levels and it should be just about there. |
| ||
You should consider posting it in the showcase section of BlitzCoder... - it will be well received there! |
| ||
I don't think it's quite good enough for that, apart from to show how easy it is to make your first game perhaps. |
| ||
It certainly is "good enough" for BlitzCoder!! Just touch it up a little to include a score maybe, and paste it there. If you don't think it's complete enough, you could put a version number < 1 on it, and alter it later. Anyway, cheers, and keep up the great programming. |
| ||
I've now added a score. Want to make an intro screen and varying levels of difficulty now. Once I've finished tweaking I'll put it up. |
| ||
The latest version can be found here, for anyone who is interested: http://members.fortunecity.com/rainking2/BlockDropV0.71.zip |
| ||
If you have any problems downloading go here: http://members.fortunecity.com/rainking2/ And click download BlockDrop |
| ||
Looks good, Daniel! One small bug - if you score a high score from level 2 upwards, your high score disappears when you restart the game at level 1... |
| ||
Thanks Rob. I think the problem you are experiencing is because it doesn't save the high score if you close the game and open it again. I'll be fixing this by writing it to a file in a future version. Also I have plans to add a full-screen option, a pause function, and of course better graphics etc. |
| ||
Daniel, I'm not talking about restarting the game by double-clicking the .exe file. Consider rechecking your high-score code as I think there is a bug... |
| ||
See what you mean now. Fixed it in Version 0.73. Thanks for the help :) |
| ||
Version 0.75 is up at http://members.fortunecity.com/rainking2/ Here's the change log from 0.71: Change Log 0.75 (20 May 2003) Slowed the down movement of the blocks by half 0.74 (20 May 2003) Added Pause Function (Use P key to pause and unpause) 0.73 (19 May 2003) Fixed High Score bug 0.72 (19 May 2003) Cleaned up the level-up scoring |
| ||
Rainking. Hmmm. Maiden BB? |
| ||
Yes. Who be you? :) |
| ||
Hi :) I'm Rottbott over there as well, I just don't post very much. Ah well it's good to know at least someone on these forums has music taste :) |
| ||
What Blitz stuff have/are you working on at the moment? |
| ||
At the moment, a rather silly MMORPG called Another Life, and a multiplayer take-over-the-universe type strategy game called Galactic Empire Conquest II :) Screenshots: Another Life: GEC2: My programming is okay, but my graphics skills are... let's just say 'unique' :-) |
| ||
What happened to Galactic Empire Conquest I? ;) I am designing a MMORPG myself at the moment, but I'm still deciding whether to use Blitz3d for it or a prebuilt C++ engine since there are lots of good ones out there. I'm a little more at home with C++ to be honest but my BASIC skills are coming back to me slowly since I picked up Blitz3D again. Maybe you would like to collaborate on the project? So far I have myself and 2 artists, 1 doing concept art and one who is a graphic designer. I still have alot of game design to do, and then concept art etc before the coding starts. |
| ||
Having "Game Name II" makes it sound cooler. There was a game called F-22 Lightning II a few years ago, and one of the mags that reviewed it pointed out that there had never been an F-22 Lightning :-) Wait till you see the names for the ships and weapons in it, they'll sound rather familiar to you... Anyway, I'd like to work with you on your game, it'd be a luxury to have some other buggers to do some art for a change. I suggest using Blitz3D though 'cos I don't have enough C++ experience to tackle something like that yet (although I'd get the hang of it quite fast I suppose..) |
| ||
Okay going to fire you a PM on the Iron Maiden BB with the details. Catch up with you there. |