Problem with Tetris game I am making

Blitz3D Forums/Blitz3D Beginners Area/Problem with Tetris game I am making

Rainking(Posted 2003) [#1]
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]


Tricky(Posted 2003) [#2]
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...


jhocking(Posted 2003) [#3]
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.


Bremer(Posted 2003) [#4]
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.


Rainking(Posted 2003) [#5]
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.


Rainking(Posted 2003) [#6]
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]


robleong(Posted 2003) [#7]
Daniel,

If this is your first game on Blitz, I look forward to seeing more!!

Keep it up - great job!

Robert.


Rainking(Posted 2003) [#8]
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.


robleong(Posted 2003) [#9]
You should consider posting it in the showcase section of BlitzCoder... - it will be well received there!


Rainking(Posted 2003) [#10]
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.


robleong(Posted 2003) [#11]
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.


Rainking(Posted 2003) [#12]
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.


Rainking(Posted 2003) [#13]
The latest version can be found here, for anyone who is interested:

http://members.fortunecity.com/rainking2/BlockDropV0.71.zip


Rainking(Posted 2003) [#14]
If you have any problems downloading go here:

http://members.fortunecity.com/rainking2/

And click download BlockDrop


robleong(Posted 2003) [#15]
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...


Rainking(Posted 2003) [#16]
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.


robleong(Posted 2003) [#17]
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...


Rainking(Posted 2003) [#18]
See what you mean now.

Fixed it in Version 0.73.

Thanks for the help :)


Rainking(Posted 2003) [#19]
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


Rottbott(Posted 2003) [#20]
Rainking. Hmmm. Maiden BB?


Rainking(Posted 2003) [#21]
Yes.

Who be you? :)


Rottbott(Posted 2003) [#22]
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 :)


Rainking(Posted 2003) [#23]
What Blitz stuff have/are you working on at the moment?


Rottbott(Posted 2003) [#24]
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' :-)


Rainking(Posted 2003) [#25]
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.


Rottbott(Posted 2003) [#26]
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..)


Rainking(Posted 2003) [#27]
Okay going to fire you a PM on the Iron Maiden BB with the details.

Catch up with you there.