Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Neverending loop
#1
So here's one that has me scratching my head, that maybe you guys can take a look at with a fresh set of eyes and sort out:

Code: (Select All)
Screen _NewImage(1280, 720, 32)
$Color:32
f = _LoadFont("courbd.ttf", 128, "monospace")
_Font f
Color Red, Transparent
_PrintString (284, 200), "Steve is" '284 - 644
_PrintString (284, 328), "Awesome!"
Sleep
_Font 8

Explode 284, 200, 644, 456, 16, 16


Print "FINISHED!!"






Sub Explode (x1, y1, x2, y2, pw, ph)
    tempScreen = _NewImage(_Width, _Height, 32)
    _PutImage , 0, tempScreen
    w = x2 - x1 + 1: h = y2 - y1 + 1
    ax = 2 * w \ pw + 1: ay = 2 * h \ ph + 1
    cx = x1 + w \ 2: cy = y1 + h \ 2

    Type box
        x As Single
        y As Single
        handle As Long
        rotation As Single
        changex As Single
        changey As Single
    End Type

    Dim Array(0 To ax, 0 To ay) As box
    For x = 0 To ax
        For y = 0 To ay
            Array(x, y).handle = _NewImage(pw, ph, 32)
            Array(x, y).x = x1 + pw * x
            Array(x, y).y = y1 + ph * y
            _PutImage , 0, Array(x, y).handle, (x1 + pw * x, y1 + ph * y)-Step(pw, ph)
            Array(x, y).changex = -(cx - Array(x, y).x) / 10
            Array(x, y).changey = -(cy - Array(x, y).y) / 10
        Next
    Next

    Do
        Cls , 0
        finished = -1
        For x = 0 To ax
            For y = 0 To ay
                Array(x, y).x = Array(x, y).x + Array(x, y).changex
                Array(x, y).y = Array(x, y).y + Array(x, y).changey
                If Array(x, y).x >= 0 And Array(x, y).y >= 0 And _
                   Array(x, y).x <= _Width And Array(x, y).y <= _Height Then finished = 0
                _PutImage (Array(x, y).x, Array(x, y).y)-Step(pw, ph), Array(x, y).handle, 0, (0, 0)-(pw, ph)
            Next
        Next
        _Display
        _Limit 60

    Loop Until finished
    _AutoDisplay
End Sub


This is supposed to be just a simple little routine which explodes a portion of the screen off the screen.  It works as intended, except for the simple fact that it doesn't know when to stop working, resulting in an endless loop!

Our main logic here comes from this little snippet of code:

    Do
        Cls , 0
        finished = -1
        For x = 0 To ax
            For y = 0 To ay
                Array(x, y).x = Array(x, y).x + Array(x, y).changex
                Array(x, y).y = Array(x, y).y + Array(x, y).changey
                If Array(x, y).x >= 0 And Array(x, y).y >= 0 And _
                   Array(x, y).x <= _Width And Array(x, y).y <= _Height Then finished = 0
                _PutImage (Array(x, y).x, Array(x, y).y)-Step(pw, ph), Array(x, y).handle, 0, (0, 0)-(pw, ph)
            Next
        Next
        _Display
        _Limit 60

    Loop Until finished


Our DO loop.
   We clear the screen
   Set a flag for being finished
   The FOR loops
     change the X/Y coordinates
     IF we still have an X/Y coordinate on the screen, then we're not finished
     Draw the image in its new positon
   NEXT
   Display
LOOP until finished

*********************************************

So the question becomes, "Why isn't this simple logic working?"  We set the flag by default every time, and only if we draw on screen do we clear that flag...  Why is this running as a non-terminating loop?  Enquiring, tired old eyes are going to bed, and hoping that maybe someone here will figure out what the heck is going wrong with such a simple process.
Reply
#2
It worked for me by changing line 7 to...

_PRINTSTRING (284, 328), "Mediocre!"

Okay, It does finish for me, but it takes about 20 seconds of looking at a blank screen before that happens, and "Finished" is in a very small font, displayed in the upper right left of the window. Oh, on my system, I can't get the height of the window to fit on my desktop.

Pete
Shoot first and shoot people who ask questions, later.
Reply
#3
Better?

Code: (Select All)
SCREEN _NEWIMAGE(1280, 720, 32)
$COLOR:32
f = _LOADFONT("courbd.ttf", 128, "monospace")
_FONT f
COLOR Red, Transparent
_PRINTSTRING (284, 200), "Steve is" '284 - 644
_PRINTSTRING (284, 328), "Mediocre!"
SLEEP
_FONT 8

Explode 284, 200, 644, 456, 16, 16


PRINT "FINISHED!!"






SUB Explode (x1, y1, x2, y2, pw, ph)
    tempScreen = _NEWIMAGE(_WIDTH, _HEIGHT, 32)
    _PUTIMAGE , 0, tempScreen
    w = x2 - x1 + 1: h = y2 - y1 + 1
    ax = 2 * w \ pw + 1: ay = 2 * h \ ph + 1
    cx = x1 + w \ 2: cy = y1 + h \ 2

    TYPE box
        x AS SINGLE
        y AS SINGLE
        handle AS LONG
        rotation AS SINGLE
        changex AS SINGLE
        changey AS SINGLE
    END TYPE

    DIM Array(0 TO ax, 0 TO ay) AS box
    FOR x = 0 TO ax
        FOR y = 0 TO ay
            Array(x, y).handle = _NEWIMAGE(pw, ph, 32)
            Array(x, y).x = x1 + pw * x
            Array(x, y).y = y1 + ph * y
            _PUTIMAGE , 0, Array(x, y).handle, (x1 + pw * x, y1 + ph * y)-STEP(pw, ph)
            Array(x, y).changex = -(cx - Array(x, y).x) / 10
            Array(x, y).changey = -(cy - Array(x, y).y) / 10
        NEXT
    NEXT

    DO
        CLS , 0
        finished = -1
        FOR x = 0 TO ax
            FOR y = 0 TO ay
                Array(x, y).x = Array(x, y).x + Array(x, y).changex
                Array(x, y).y = Array(x, y).y + Array(x, y).changey
                IF Array(x, y).x >= 0 AND Array(x, y).y >= 0 AND Array(x, y).x <= _WIDTH / 4 AND Array(x, y).y <= _HEIGHT / 2 THEN finished = 0
                _PUTIMAGE (Array(x, y).x, Array(x, y).y)-STEP(pw, ph), Array(x, y).handle, 0, (0, 0)-(pw, ph)
            NEXT
        NEXT
        _DISPLAY
        _LIMIT 60

    LOOP UNTIL finished
    _AUTODISPLAY
END SUB
Shoot first and shoot people who ask questions, later.
Reply
#4
It does finish but takes longer than expected and never expected little tiny bitty message in red in top left corner. What Pete said! ;-))

This explains what happened visually by making something invisible, visible, I think?
Code: (Select All)
Option _Explicit
Screen _NewImage(1280, 700, 32)
$Color:32
Dim As Long f

f = _LoadFont("courbd.ttf", 128, "monospace")
_Font f
Color Red, White
_PrintString (284, 200), "Steve is" '284 - 644
_PrintString (284, 328), "Awesome!"
Sleep
_Font 8

Explode 284, 200, 644, 456, 16, 16


Print "FINISHED!!"






Sub Explode (x1, y1, x2, y2, pw, ph)
    Dim As Long finished, tempscreen
    Dim w, h, ax, ay, cx, cy, x, y
    tempscreen = _NewImage(_Width, _Height, 32)
    _PutImage , 0, tempscreen
    w = x2 - x1 + 1: h = y2 - y1 + 1
    ax = 2 * w \ pw + 1: ay = 2 * h \ ph + 1
    cx = x1 + w \ 2: cy = y1 + h \ 2

    Type box
        x As Single
        y As Single
        handle As Long
        rotation As Single
        changex As Single
        changey As Single
    End Type

    Dim Array(0 To ax, 0 To ay) As box
    For x = 0 To ax
        For y = 0 To ay
            Array(x, y).handle = _NewImage(pw, ph, 32)
            Array(x, y).x = x1 + pw * x
            Array(x, y).y = y1 + ph * y
            _PutImage , 0, Array(x, y).handle, (x1 + pw * x, y1 + ph * y)-Step(pw, ph)
            Array(x, y).changex = -(cx - Array(x, y).x) / 10
            Array(x, y).changey = -(cy - Array(x, y).y) / 10
        Next
    Next

    Do
        Cls , 0
        finished = 1
        For x = 0 To ax
            For y = 0 To ay
                Array(x, y).x = Array(x, y).x + Array(x, y).changex
                Array(x, y).y = Array(x, y).y + Array(x, y).changey
                If (Array(x, y).x >= 0 And Array(x, y).y >= 0) Then
                    If Array(x, y).x <= _Width And Array(x, y).y <= _Height Then
                        finished = 0
                    End If
                End If
                _PutImage (Array(x, y).x, Array(x, y).y)-Step(pw, ph), Array(x, y).handle, 0, (0, 0)-(pw, ph)
            Next
        Next
        _Display
        _Limit 60

    Loop Until finished
    _AutoDisplay
End Sub
b = b + ...
Reply
#5
Well I'll be @PhilOfPerth I can not Select All of the code I just posted! But I can Select All Pete's code.
b = b + ...
Reply
#6
Good idea, Mark! I just tried mine by replacing Steve with blocks. You can hardly tell the difference! so a string of CHR$(219)s blows apart much like your background demo. In mine, by cutting the width by 4 and height by 2 only a few pieces of blocks are left on the screen, but the lettering (if substituted back in) would be gone.

In any event, waiting until all the character particles (solid blocks or letters with a background) are off the screen simply takes too long, even if you remark out _LIMIT.

Pete
Shoot first and shoot people who ask questions, later.
Reply
#7
Aye, the problem with the code was simply: There was no problem!  I was simply curious to see how many people might end up banging their head all night over a trick question -- which is something which you guys end up having us poor devs do all the time.  Somebody will report an issue, and at first glance, it appears to be an actual issue...  Then, after spending *forever* digging into it, we finally realize, "Everything is working 100% as it should -- it's just that how it should work isn't how the user expects it to work!" 

In this case, it's exactly as Mark (and Matt over at Discord, before him), has deduced:  The explosion *is* working as intended -- the problem here is that we set the speed of the exploding pieces based upon the distance from the center.  In this case, there's several transparent boxes created near the center of the screen, and as such, they only have a movement rate of about 0.4 pixels per loop.  With a loop limit of 60, those blocks move all of 24 pixels per second, and have about 500 pixels to travel.  Simple math tells us that they're not going to exit the screen for 20+ seconds -- which is *exactly* what we see happening in the program.

Visibly, it appears as if there's a glitch in the matrix -- the program runs, and within a few seconds all visible content is exploded off the screen, leaving it to appear to be doing nothing for the next dozen seconds.  If you're an impatient programmer, it's easy to jump to a conclusion and say, "Welp, that's an endless loop!", as there's no visible confirmation of any changes happening inside the program or on the screen.  In all actuality, the program *is* working 100% as intended; it's just that it's working with transparent boxes of pixels.  Color the background as Mark has in his code above, and you can easily see what's going on here.

Lesson to be learned from this?

Not all code is "broken".  Often, its just the user's expectations which is incorrect! 
Reply
#8
Yeah, yesterday I started pitching a fit expecting a Typo to work as if it were typed correctly. LOL! (now)

Option _Explicit didn't catch it because lblN was typed lblT and that was another DIM'd variable.
b = b + ...
Reply
#9
Ben Franklin once said something along the lines of don't ruin an apology with an excuse. Hmmm, now why did this remind me of that???

Big Grin Big Grin Big Grin

I wonder who said, "Whatever you have to tell yourself to wake up in the morning." Maybe that was Mrs. Franklin?

LOL at my estimate of taking 20sec to finish, and your calculation of 20 seconds to finish. In high school, I estimated my way to a A in algebra, too!

Anyway, nice gag. Too bad you and Matt didn't catch any suckers this time around. Oh, and kudos to Mark for "visualizing" the unseen.

Pete
Reply
#10
Quote:I was simply curious to see how many people might end up banging their head all night over a trick question -- which is something which you guys end up having us poor devs do all the time.  Somebody will report an issue, and at first glance, it appears to be an actual issue...


Yes, . . . I can there only think of one thing  Tongue :

Reply




Users browsing this thread: 2 Guest(s)