Making a grid and reading through it

BlitzMax Forums/BlitzMax Beginners Area/Making a grid and reading through it

I'm trying to make a simple thing yet I'm getting error

4x4 Grid into an Array so basicly UCell[4,4]
		For Local i:Int = 0 To VCell
			For Local i2:Int = 0 To HCell
				If UCell[i,i2]=1 Then
					DrawRect XCell, YCell, Cell_Size, Cell_Size
				EndIf
			Next
		Next


I'm trying to go through all of them and only draw a rectangle for those with a value of 1 all the other must have a value of 0 by default...

At work, so no BMax, but try
		For Local i:Int = 0 To VCell-1
			For Local i2:Int = 0 To HCell-1
				If UCell[i,i2]=1 Then
					DrawRect XCell, YCell, Cell_Size, Cell_Size
				EndIf
			Next
		Next


I can't see anything wrong with that piece of code at all.

Basicly, I'm trying to make a modified version of tetris as a practice to improve my sloppy programming skills. But I'm trying to figure out the basic logic and I came up with GRIDS.

This is a code to test my Block Type which would be all the blocks in the game. It's a prototype...

Const Cell_Size:Int=12
Graphics 800,600

Global Test1:TBlock=New TBlock
Test1.Create(10,10,0)

Repeat


Test1.Update()
Test1.Draw()
Flip; Cls

Until KeyHit(KEY_ESCAPE)
End

Type TBlock
	Field XCell:Int
	Field YCell:Int

	Field Category:Int
	Field Rotation:Int
	
	Field HCell:Int=4
	Field VCell:Int=4
	Field UCell:Int[HCell,VCell]
	
	Method Create(xstart,ystart,catstart)
		XCell=xstart
		YCell=ystart
		Category=catstart
		
		Select Category
			Case 0
				' Normal L
				UCell[1,2]=1
				UCell[2,2]=1
				UCell[3,2]=1
				UCell[3,1]=1
			Case 1
				' Line |
				
			Case 2
			
			
		End Select
	End Method
	
	Method Update()
		
	End Method
	
	Method Draw()
		For Local i:Int = 0 To VCell
			For Local i2:Int = 0 To HCell
				If UCell[i,i2]=1 Then
					DrawRect XCell, YCell, Cell_Size, Cell_Size
				EndIf
			Next
		Next
	End Method
End Type


EDITED

So basicly
4x4
[0][0][0][0]
[0][0][0][0]
[0][0][0][0]
[0][0][0][0]

0 doesn draw
1 draws on of the figure's cube

So let's say an L
[0][0][0][1]
[1][1][1][1]
[0][0][0][0]
[0][0][0][0]

I am making a Tetris game and found it to be more difficult than you might think.

Perturbatio's code shoud fix the error. You haven't specified what it is but I guess it is array index out of bounds. If you make an array of size 4, then the indexes are [0] [1] [2] and [3]. [4] is not a valid index. Yet in your for loop i/i2 goes 0, 1, 2, 3 and 4. Either put VCell-1 or use for local i:int = 0 until VCell, which goes up to but not including VCell and the same changes for HCell. (Personally I'd use x and y rather than i and i2 but it makes no difference).

Though it can be done with arrays, it is actually easier for each "block" or "shape" to have a list of 4 points/coordinates rather than a 4x4 array. If you make a TPoint type with int fields x and y, and give each shape an array of 4 TPoints. The T shape for instance would be (-1, 0) (0, 0) (1, 0) (0, 1), with (0, 0) being the centre square. Implemented as points[i].x = -1; points[i].y = 0; etc

The list of points methods makes rotating easier and you might want to investigate it. But it is possible using arrays.

Last night I was playing a simple game on my phone similar to tetris which you might find easier to implement. It will give you the chance to sort out program design and finishing a game but avoid some of the more complex problems with a tetris game. (Sorry if I am insulting your intelligence, but I am currently making a tetris game and finding it difficult and I would consider myself an Intermediate, or at least above beginner, programmer).

The game is called QuadraPop and you can see a screenshot here

If you are interested I can describe the game for you.

Apollonius, either do what Perturbatio said or change "to" to "until"

Hi Apollonios. I just did a quick test to see if I could help out. I came up with this.

SuperStrict

Graphics 260, 500

Global LeftLArrWidth:Int = 3
Global leftLArrHeight:Int = 3

Global LeftLXOff:Int = 120
Global LeftLYOff:Int = 0

Global LXTemp:Int[4], LYTEmp:Int[4]

Global CreateLeftL:Int = 0
Global LeftLCreated:Int = 0

Global loopCount:Int = 0

Global LeftLTimer:Int = MilliSecs() 
Global CHeckAheadTImer:Int = MilliSecs() 

Global TimerSpeed:Int = 600

Global ReadDefData:Int = 0
Global RotL:Int = 0
Global RotCount:Int = 0

Global CanMoveLeft:Int = 1
Global CanMoveRight:Int = 1
Global LLCanRotate:Int = 1


Global ArrData:Int[20]

Global LeftL:Int[LeftLArrWidth, LeftLArrHeight]


Const GAMEARRAYWIDTH:Int = 13
Const GAMEARRAYHEIGHT:Int = 25

Global GameArray:Int[GAMEARRAYWIDTH, GAMEARRAYHEIGHT]

While not KeyHit(KEY_ESCAPE) 
	Cls
		DrawLine 0, 60, 260, 60
		
		CheckAhead() 
		
		For Local x:Int = 0 Until GAMEARRAYWIDTH
			For Local Y:Int = 0 Until GAMEARRAYHEIGHT
				If GameArray[x, y]= 1
					DrawRect x * 20, y * 20, 20, 20
					Else
					
				End If
			Next
		Next
		
		
		If LeftLCreated = 1
			If MilliSecs() > LeftLTimer + TimerSpeed
				LeftLYOff:+20
			'	If MilliSecs() > CHeckAheadTImer + 500
					 
				LeftLTimer = MilliSecs() 
			'	EndIf
			End If
			
			If KeyHit(KEY_EQUALS) 
				TimerSpeed:-200
			EndIf
			
			If KeyHit(KEY_MINUS) 
				TimerSpeed:+200
			End If
		End If
		
		
		If LeftLCreated = 1
			For Local x:Int = 0 Until 3
				For Local y:Int = 0 Until 3
					If LeftL[x, y]= 1
					
						DrawRect LeftLXOff + x * 20, LeftLYOff + Y * 20, 20, 20
							Select loopCount
								Case 0
									LXTemp[0]= LeftLXOff + x * 20
									LYTEmp[0]= LeftLYOff + Y * 20
								Case 1
									LXTemp[1]= LeftLXOff + x * 20
									LYTEmp[1]= LeftLYOff + Y * 20
								Case 2
									LXTemp[2]= LeftLXOff + x * 20
									LYTEmp[2]= LeftLYOff + Y * 20
								Case 3
									LXTemp[3]= LeftLXOff + x * 20
									LYTEmp[3]= LeftLYOff + Y * 20
							End Select
							loopCount:+1
					End If
					If loopCount > 3 Then loopCount = 0
				Next
			Next
		EndIf
		
		If KeyHit(KEY_SPACE) and LeftLCreated = 0
			RestoreData LeftL1
			For Local y:Int = 0 Until 3
				For Local x:Int = 0 Until 3
					ReadData ArrData[0]
					LeftL[x, y]= ArrData[0]
				Next
			Next
			LeftLCreated = 1
		End If
		
		If LeftLCReated = 1
			MoveRotate() 
		EndIf
		
		Local tx1:Int, tx2:Int, tx3:Int, tx4:Int
		Local ty1:Int, ty2:Int, ty3:Int, ty4:Int
		
		DrawText "tx1= " + LXTemp[0], 0, 0
		DrawText "ty1= " + LYTEmp[0], 80, 0
		DrawText "tx2= " + LXTemp[1], 0, 15
		DrawText "ty2= " + LYTEmp[1], 80, 15
		DrawText "tx3= " + LXTemp[2], 0, 25
		DrawText "ty3= " + LYTEmp[2], 80, 25
		DrawText "tx4= " + LXTemp[3], 0, 35
		DrawText "ty4= " + LYTEmp[3], 80, 35
		DrawText "LoopCount= " + loopCount, 0, 45
		DrawText "LeftlCReated= " + LeftLCreated, 0, 55
	Flip
Wend

Function CheckAhead() 

	If LYTEmp[0]>= 500 - 20 or LYTEmp[1]>= 500 - 20 or LYTEmp[2]>= 500 - 20 or LYTEmp[3]>= 500 - 20
		GameArray[LXTemp[0]/ 20, LYTEmp[0]/ 20]= 1
		GameArray[LXTemp[1]/ 20, LYTEmp[1]/ 20]= 1
		GameArray[LXTemp[2]/ 20, LYTEmp[2]/ 20]= 1
		GameArray[LXTemp[3]/ 20, LYTEmp[3]/ 20]= 1
		
		For Local iter:Int = 0 Until 4
			LXTemp[iter]= 0
			LYTEmp[iter]= 0
		Next
		LeftLXOff = 120
		LeftLYOff = 0
	'	LeftLCreated = 0
	End If
	
	If GameArray[LXTemp[0]/ 20, LYTEmp[0]/ 20 + 1]= 1 or GameArray[LXTemp[1]/ 20, LYTEmp[1]/ 20 + 1]= 1 or ..
		GameArray[LXTemp[2]/ 20, LYTEmp[2]/ 20 + 1]= 1 or GameArray[LXTemp[3]/ 20, LYTEmp[3]/ 20 + 1]= 1
		
		GameArray[LXTemp[0]/ 20, LYTEmp[0]/ 20]= 1
		GameArray[LXTemp[1]/ 20, LYTEmp[1]/ 20]= 1
		GameArray[LXTemp[2]/ 20, LYTEmp[2]/ 20]= 1
		GameArray[LXTemp[3]/ 20, LYTEmp[3]/ 20]= 1		

		For Local iter:Int = 0 Until 4
			LXTemp[iter]= 0
			LYTEmp[iter]= 0
		Next
		LeftLXOff = 120
		LeftLYOff = 0
	EndIf
			
End Function


Function MoveRotate() 
	
	If KeyHit(KEY_UP) and not KeyHit(KEY_DOWN) and LLCanRotate = 1
		ReadDefData = 1
		RotCount:+1
		RotL = 1
		If RotCount > 3 Then RotCount = 0
	ElseIf KeyHit(KEY_DOWN) and not KeyHit(KEY_UP) LLCanRotate = 1
		ReadDefData = 1
		RotCount:-1
		RotL = 1
		If RotCount < 0 Then RotCount = 3
	End If	
	
	
	
	If KeyHit(KEY_LEFT) and not KeyHit(KEY_RIGHT) 
		LeftLXOff:-20
 		If GameArray[LXTemp[0]/ 20 - 1, LYTEmp[0]/ 20]= 1 or GameArray[LXTemp[1]/ 20 - 1, LYTEmp[1]/ 20]= 1 or ..
			GameArray[LXTemp[2]/ 20 - 1, LYTEmp[2]/ 20]= 1 or GameArray[LXTemp[3]/ 20 - 1, LYTEmp[3]/ 20]= 1
		Else

		EndIf
		If LeftLXOff <= 0 Then LeftLXOff = 0
	EndIf
	
	If KeyHit(KEY_RIGHT) and not KeyHit(KEY_LEFT) 
		LeftLXOff:+20
 		If GameArray[LXTemp[0]/ 20 + 1, LYTEmp[0]/ 20]= 1 or GameArray[LXTemp[1]/ 20 + 1, LYTEmp[1]/ 20]= 1 or ..
			GameArray[LXTemp[2]/ 20 + 1, LYTEmp[2]/ 20]= 1 or GameArray[LXTemp[3]/ 20 + 1, LYTEmp[3]/ 20]= 1
		Else

		EndIf
		If LeftLXOff >= 500 Then LeftLXOff = 500
	End If
	
	If RotL = 1
		Select RotCount
			Case 0
				If ReadDefData = 1
					RestoreData LeftL1
					ReadDefData = 0
				End If
				For Local y:Int = 0 Until 3
					For Local x:Int = 0 Until 3
						ReadData ArrData[0]
						LeftL[x, y]= ArrData[0]
					Next
				Next
				RotL = 0
				ReadDefData = 0
			Case 1
				If ReadDefData = 1
					RestoreData LeftL2
					ReadDefData = 0
				End If
				For Local y:Int = 0 Until 3
					For Local x:Int = 0 Until 3
						ReadData ArrData[1]
						LeftL[x, y]= ArrData[1]
					Next
				Next
				RotL = 0
				ReadDefData = 0
			Case 2
				If ReadDefData = 1
					RestoreData LeftL3
					ReadDefData = 0
				End If
				For Local y:Int = 0 Until 3
					For Local x:Int = 0 Until 3
						ReadData ArrData[2]
						LeftL[x, y]= ArrData[2]
					Next
				Next
				RotL = 0
				ReadDefData = 0
			Case 3
				If ReadDefData = 1
					RestoreData LeftL4
					ReadDefData = 0
				End If
				For Local y:Int = 0 Until 3
					For Local x:Int = 0 Until 3
						ReadData ArrData[3]
						LeftL[x, y]= ArrData[3]
					Next
				Next
				RotL = 0
				ReadDefData = 0
		End Select
	End If
End Function

'#Region 
#LeftL1
DefData 0, 1, 0
DefData 0, 1, 0
DefData 1, 1, 0

#LeftL2
DefData 1, 0, 0
DefData 1, 1, 1
DefData 0, 0, 0

#LeftL3
DefData 0, 1, 1
DefData 0, 1, 0
DefData 0, 1, 0

#leftL4
DefData 0, 0, 0
DefData 1, 1, 1
DefData 0, 0, 1
'#End Region 


Press the + or - key to increase or decrease fall speed. There's no bounds checking for left and right but there is collidable stackable collision checking.

Hope you find it usefull. :)

[edit] Press space bar to drop first shape. There's only one shape. You should get an idea of how it's done though. Don't know if this is the way Tetris is made but it's all I could think of at the time. :)

Amon I can't get your code to work, and it is not easy to understand.

I understand your TPoint Concept. The TPoint and the Array idea seem quite similar to me though. I prefer working on the tetris idea, however my tetris won't be as simple as the normal tetris even though the normal tetris is not as easy as I though it would be.

As for my programming level, I'd be the in the clas of Monkey Programmer, sometimes I know, sometimes I don't and sometimes I just forgot. Reference is my guru~!

Oh and I almost forgot you know how the blocks go down cell by cell, would you use a global grid for the game board where the blocks are drawn or theres no need for this..

I'll figure it out eventually @__@


Amon: that's a nice piece of code u got there :o

here it is your code correcterd:
Const Cell_Size:Int=12
Graphics 800,600

Global Test1:TBlock=New TBlock
Test1.Create(10,10,0)

Repeat


Test1.Update()
Test1.Draw()
Flip; Cls

Until KeyHit(KEY_ESCAPE)
End

Type TBlock
	Field XCell:Int
	Field YCell:Int

	Field Category:Int
	Field Rotation:Int
	
	Field HCell:Int=4
	Field VCell:Int=4
	Field UCell:Int[HCell,VCell]
	
	Method Create(xstart,ystart,catstart)
		XCell=xstart
		YCell=ystart
		Category=catstart
		
		Select Category
			Case 0
				' Normal L (you mean a reverse L?)
				UCell[1,2]=1
				UCell[2,2]=1
				UCell[3,2]=1
				UCell[3,1]=1
			Case 1
				' Line |
				
			Case 2
			
			
		End Select
	End Method
	
	Method Update()
		
	End Method
	
	Method Draw()
		For Local i:Int = 0 Until VCell
			For Local i2:Int = 0 Until HCell
				If UCell[i,i2]=1 Then 
					DrawRect XCell+i2*Cell_Size, YCell+i*Cell_Size, Cell_Size, Cell_Size
				EndIf
			Next
		Next
	End Method
End Type



Sorry, runs fine here. Press up/down arrow to rotate and left/right arrown to move left and right.

When the app starts press space to release the shape.

Itr should work, I just copied and pasted the code in to a new bmx file and ran it. It works.

Please note that it's not a full tetris game. Just an L Shape that drops, rotates and has collision to stack on top of another.

Ah Amon you didn't say about the space bar in your original post I read ;) Also the collision detection does not work perfectly. It is possible to overlap pieces by coming in on the horizontal side.

After having tried both the array and points concept in my program, I can definately say that the points method is easier to program, maintain and perform rotations with. Arrays deceptively seem like the best solution here but I disagree.

I hate to sound like an annoying know-it-all telling you the "best" ways to do things but I have researched into this quite a bit.

Yes you will need to have a "game board" grid to ultimately store the state of the game. Whether or not it is global will depend how you design your program. You will need to add methods to your blocks to add or remove themselves from the game board (and perform operations such as rotate and drop). To add, for example, simply use a double nested for-loop to go through the array adding those elements whose value is 1 and putting 1 on the game board, or for the points idea a single for loop going through the four elements and adding a 1 to the game board at each coordinate.

(Hopefully just from that you can see how the points idea is already simpler to program - hopefully lol)