View Single Post
 
Old 01-10-2014, 01:43 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,028
Default

Because of the single threaded nature of the GUI interface, pressing the up arrow to rotate the shape should not cause a problem with Movement Timer since each will run to completion atomically, that is, neither event will interrupt the other in the middle of its processing, unless you specifically called DoEvents in the middle of an event handler, which you do not.
If you have an issue, it is because the rotation code doesn't work properly, and modifies the game into an invalidate state, which then causes the Movement code to fail.

I don't know if we have a good VB.Net debugging tutorial on this site. We have one for VB6, but VB.Net is a bit different. Learning to set breakpoints, stepping through the code and observing is the best way to work through these type of issues.

For instance, your rotation code is based on finding the four blocks that need to be rotated, then rotating them. But, even though I didn't troubleshoot the cause, I did note when I tried to rotate one of the shapes, more than four blocks were tagged with "1" for some reason, perhaps temporarily, which caused your counter to go greater than 4 so when your movement code is doing a compare " = 4", it will never equal 4 since it has already bypassed it. When I put a break in the movement code to see why the movement had stopped, I saw the downCount was over 900 by that point. Since it would continue to increment and never = 4, the movement would never happen.

Now, the above may have been cause because I had already "fixed" another problem.
If you start the game and just let the first piece fall to the bottom, the second piece seems to have problems starting, does some odd things, or hangs.
So I looked at that first, and there are at least two initial problems, and the fix of one of those may have led to the problem with the downCount.

First, what happens when the piece hits the bottom.
Code:
 Private Sub tmrMovement_Tick(sender As Object, e As EventArgs) Handles tmrMovement.Tick

    For x = 0 To 19
      For y = 0 To 11
        If map(x, y).Text = "1" Then
          downCount += 1
          If downCount = 1 Then
            rows1 = x
            columns1 = y
          ElseIf downCount = 2 Then
            rows2 = x
            columns2 = y
          ElseIf downCount = 3 Then
            rows3 = x
            columns3 = y
          ElseIf downCount = 4 Then
            rows4 = x
            columns4 = y
            Exit For
          End If
        End If
      Next
      If map(rows1 + 1, columns1).Text = "2" Or 
         map(rows2 + 1, columns2).Text = "2" Or 
         map(rows3 + 1, columns3).Text = "2" Or 
         map(rows4 + 1, columns4).Text = "2" Then
        map(rows1, columns1).Text = "2"
        map(rows2, columns2).Text = "2"
        map(rows3, columns3).Text = "2"
        map(rows4, columns4).Text = "2"
        shapes()
      ElseIf downCount = 4 Then
        map(rows1, columns1).Text = "0"
        map(rows2, columns2).Text = "0"
        map(rows3, columns3).Text = "0"
        map(rows4, columns4).Text = "0"
        map(rows1 + 1, columns1).Text = "1"
        map(rows2 + 1, columns2).Text = "1"
        map(rows3 + 1, columns3).Text = "1"
        map(rows4 + 1, columns4).Text = "1"
        downCount = 0
        Exit For
      End If
    Next
  End Sub
If you look at that code, each time you move the shape down (ElseIf case), you reset downCount to 0 so you're ready to count the four blocks the next time. But, if you've run into something, so stop the movement and generate a new shape (If case), you don't set downCount = 0 and so the second shape starts with downCount already set to 4 and increments it to 5, 6, ... and the shape never moves because it never equals 4.
So, my first change was to reset downCount to 0 in either case, which fixed that.

The second issue is the way you have the loops nested. You scan one row of your game field, and then test the four blocks found. What if there were no blocks found, or at least not four. In that case, you are testing previously found blocks (associated with your first shape, which is at the bottom of the field and have been flags as "2"s. There is a good chance you'll find one of those "2"s below one of the old blocks, and you'll plant the second shape where it is (at the top of the field), and launch another shape, which is likely to do the same thing, or your downCount will reach 4 and might kick the shape loose if by chance the random blocks you are now testing happen to pass the if condition.
So, my second fix was to move the Next up, so you're doing scan of the whole field, not just one row, and then do the movement, like this (both changes)
Code:
  Private Sub tmrMovement_Tick(sender As Object, e As EventArgs) Handles tmrMovement.Tick

    For x = 0 To 19
      For y = 0 To 11
        If downCount < 4 Then  'only looking for four blocks, allow the loops to do nothing once they're found
          If map(x, y).Text = "1" Then
            downCount += 1
            If downCount = 1 Then
              rows1 = x
              columns1 = y
            ElseIf downCount = 2 Then
              rows2 = x
              columns2 = y
            ElseIf downCount = 3 Then
              rows3 = x
              columns3 = y
            ElseIf downCount = 4 Then
              rows4 = x
              columns4 = y
            End If
          End If
        End If
      Next
    Next
    If map(rows1 + 1, columns1).Text = "2" Or
       map(rows2 + 1, columns2).Text = "2" Or
       map(rows3 + 1, columns3).Text = "2" Or
       map(rows4 + 1, columns4).Text = "2" Then
      map(rows1, columns1).Text = "2"
      map(rows2, columns2).Text = "2"
      map(rows3, columns3).Text = "2"
      map(rows4, columns4).Text = "2"
      shapes()
    ElseIf downCount = 4 Then
      map(rows1, columns1).Text = "0"
      map(rows2, columns2).Text = "0"
      map(rows3, columns3).Text = "0"
      map(rows4, columns4).Text = "0"
      map(rows1 + 1, columns1).Text = "1"
      map(rows2 + 1, columns2).Text = "1"
      map(rows3 + 1, columns3).Text = "1"
      map(rows4 + 1, columns4).Text = "1"
    Else
      MsgBox("Houston, we have a problem. (didn't find four blocks to move)")
    End If
    downCount = 0 'always reset downCount

  End Sub

If you haven't done so, you should probably "unit test" the rotation routines to make sure they do what you want. Probably put a break point in the shapes routine, so you can specifically choose each shape, rather than have random pick it. Start the code up let the movement code move the shape down a bit, then probably stop the Movement timer, and just hit your rotate and move keys to verify the shape rotates and moves left, right, down correctly. I didn't test them directly like that, but I did notice that shape 3 definitely looks to have rotation issues.

The other change I did, was rather than recreate the two dimension label map from scratch multiple times in the various routines, just declared it in the form level variables, and initialize it once, in the Form_Load event, then remove all the other local declarations and initializations of the map. Also the same with the static Random instance, just create once and reuse, rather than creating a new instance each time used.
Code:
' ...
  Dim rotate As Integer
  Dim downCount As Integer

'declare in Class level scope
  Dim map(,) As Label
  Dim rand As New Random

  Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    map = {{lbl11, lbl12, lbl13, lbl14, lbl15, lbl16, lbl17, lbl18, lbl19, lbl110, lbl111, lbl112},
{lbl21, lbl22, lbl23, lbl24, lbl25, lbl26, lbl27, lbl28, lbl29, lbl210, lbl211, lbl212},
'...etc...
{lbll211, lbll212, lbl213, lbl214, lbl215, lbl216, lbl217, lbl218, lbl219, lbl2110, lbl2111, lbl2112}}
    shapes()
    tmrColor.Start()
    tmrMovement.Start()
  End Sub
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 01-10-2014 at 01:50 PM.
Reply With Quote