Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Playing with the mouse
#1
I am running this program to play with the mouse, just playing with things to understand it before trying to imbed it into something else.


Code: (Select All)
$NOPREFIX

CONST FALSE = 0, TRUE = NOT FALSE

TYPE MouseType
    EndX AS INTEGER
    EndY AS INTEGER
    StartX AS INTEGER
    StartY AS INTEGER
    LButDown AS INTEGER
    RButDown AS INTEGER
    OldLBut AS INTEGER
    OldRBut AS INTEGER
END TYPE

SCREEN NEWIMAGE(1280, 720, 32)

DIM AS MouseType Mouse
DIM AS INTEGER highlight(500000)
DIM AS BIT Active

Mouse.OldLBut = --1
Active = FALSE

LINE (500, 200)-(600, 300), RGB(0, 0, 255), BF
DO
    'LIMIT 120
    DO WHILE MOUSEINPUT
    LOOP

    Mouse.StartX = MOUSEX
    Mouse.StartY = MOUSEY
    Mouse.LButDown = MOUSEBUTTON(1)

    IF Mouse.StartX >= 500 AND Mouse.StartX <= 600 AND Mouse.StartY >= 200 AND Mouse.StartY <= 300 AND NOT Active THEN
        GET (500, 200)-(600, 300), highlight()
        PUT (500, 200), highlight(), PRESET
        Active = TRUE
    ELSEIF Active EQV Mouse.StartX < 500 OR Mouse.StartX > 600 OR Mouse.StartY < 200 OR Mouse.StartY > 300 THEN
        GET (500, 200)-(600, 300), highlight()
        PUT (500, 200), highlight(), PRESET
        Active = FALSE
    END IF

    IF Mouse.LButDown AND NOT Mouse.OldLBut THEN
        LOCATE 1, 1
        PRINT Mouse.StartX, Mouse.StartY, Mouse.LButDown
    END IF

    Mouse.OldLBut = Mouse.LButDown

LOOP UNTIL INKEY$ = CHR$(27)



and it is working as expected with a box highlighting and not but I don't understand why this if statement needs EQV:

Code: (Select All)
    ELSEIF Active EQV Mouse.StartX < 500 OR Mouse.StartX > 600 OR Mouse.StartY < 200 OR Mouse.StartY > 300 THEN
        GET (500, 200)-(600, 300), highlight()
        PUT (500, 200), highlight(), PRESET
        Active = FALSE
    END IF
 
than the one I was trying to work with at first:


Code: (Select All)
    ELSEIF Active AND Mouse.StartX < 500 OR Mouse.StartX > 600 OR Mouse.StartY < 200 OR Mouse.StartY > 300 THEN
        GET (500, 200)-(600, 300), highlight()
        PUT (500, 200), highlight(), PRESET
        Active = FALSE
    END IF

My belief that If (false and True or True or True or True) should return a false with false and true.... condition. 


Never used EQV before but the table on the wiki implies both should return false. Maybe someone can educate me where my logic has gone wrong? Many thanks  Shy
Reply
#2
I avoid Boolean logic like the plague. Steve seems to like it, so I'll let him explain better if he reads this post.

I do like the use in this example; otherwise the difference is...

When you are using AND in the first condition, you only need to use ACTIVE once, because it combines with the 4 mouse pointer locations. In the second condition, you use OR to indicate the pointer has been moved outside the square, and since OR separates, you now need to place ACTIVE with each OR statement to achieve the same results...

Code: (Select All)
ELSEIF Active AND Mouse.StartX < 500 OR Active AND Mouse.StartX > 600 OR Active AND Mouse.StartY < 200 OR Active AND Mouse.StartY > 300 THEN

So using EQV as you did with...

Code: (Select All)
ELSEIF Active EQV Mouse.StartX < 500 OR Mouse.StartX > 600 OR Mouse.StartY < 200 OR Mouse.StartY > 300 THEN

...brilliantly reduces the repetition of ACTIVE in the prior use. +2 for that!

So when ACTIVE is FALSE we want to not re-enter that second condition again until ACTIVE becomes TRUE. The OR statements without EQV screw that up, because any one of the mouse location OR statements being true, that don't have an ACTIVE variable combined with it, makes the program flow return there again and again. Now with EQV, we use ACTIVE just once and compare it to EACH of the the 4 mouse position OR statements, so when just one of them is FALSE the whole condition is FALSE.

The basic why I would illustrate this is with the following group of OR statements with only the last of the 4 OR comparisons being true.

Code: (Select All)
PRINT 1 > 2 OR 3 > 4 OR 5 > 6 OR 10 > 0
Active = -1 ' True.
PRINT Active EQV 1 > 2 OR 3 > 4 OR 5 > 6 OR 10 > 0
Active = 0 ' True.
PRINT Active EQV 1 > 2 OR 3 > 4 OR 5 > 6 OR 10 > 0

Notice how EQV nicely made the comparison if one of the OR statements is true, but ACTIVE is false, the condition is now FALSE.

Just for fun, I also included the Boolean table from the wiki:

Code: (Select All)
  ┌───────────────┬────────────────────────────────────────────────────────┐
  │   Operands    │                   Logical operations                   │
  ├───────┬───────┼───────┬─────────┬────────┬─────────┬─────────┬─────────┤
  │   A   │   B   │ NOT B │ A AND B │ A OR B │ A XOR B │ A EQV B │ A IMP B │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ true  │ true  │ false │  true   │ true   │  false  │  true   │  true   │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ true  │ false │ true  │  false  │ true   │  true   │  false  │  false  │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ false │ true  │ false │  false  │ true   │  true   │  false  │  true   │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ false │ false │ true  │  false  │ false  │  false  │  true   │  true   │
  └───────┴───────┴───────┴─────────┴────────┴─────────┴─────────┴─────────┘   

Pete
Reply
#3
https://qb64phoenix.com/forum/showthread.php?tid=1187  <-- Read this for EQV, and then see if you have any questions.  Wink
Reply
#4
(12-11-2022, 02:47 PM)Pete Wrote: ...
Just for fun, I also included the Boolean table from the wiki:

Code: (Select All)
  ┌───────────────┬────────────────────────────────────────────────────────┐
  │   Operands    │                   Logical operations                   │
  ├───────┬───────┼───────┬─────────┬────────┬─────────┬─────────┬─────────┤
  │   A   │   B   │ NOT B │ A AND B │ A OR B │ A XOR B │ A EQV B │ A IMP B │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ true  │ true  │ false │  true   │ true   │  false  │  true   │  true   │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ true  │ false │ true  │  false  │ true   │  true   │  false  │  false  │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ false │ true  │ false │  false  │ true   │  true   │  false  │  true   │
  ├───────┼───────┼───────┼─────────┼────────┼─────────┼─────────┼─────────┤
  │ false │ false │ true  │  false  │ false  │  false  │  true   │  true   │
  └───────┴───────┴───────┴─────────┴────────┴─────────┴─────────┴─────────┘   

Pete

Just for fun, I looked at that table and tried NOT and AND with () around the OR conditions to make it work before I said "What the hell, can't be worse than a strobing box..." Imagine my surprise when EQV just worked...

Thank you for teaching the teacher. the double up the ANDs with the ORs make some sense to me!

(12-11-2022, 02:51 PM)SMcNeill Wrote: https://qb64phoenix.com/forum/showthread.php?tid=1187  <-- Read this for EQV, and then see if you have any questions.  Wink

I did read it before the post. Just didn't really explain the difference between AND and EQV to me well. If I get from Pete, then AND only works on the nearest OR operator (?) and EQV will work on the whole string of operations (?) Kind of like AND with OR multiply first and EQV gets added in at the end if I may use 5th grade math PEMDAS as a way to understand  Big Grin It is the teacher in me that wants to understand the WHY  Blush

Edit: I guess it really is the order of operations... I read it left to right and assumed that the one false on one side with the AND would make it all false but I guess I am messing up my Boolean order of operations...
Reply
#5
Hi NasaCow

yes your conditions in the control are very complex:
AND returns true only if both parameters are TRUE
EQV return true only if both parameters are the SAME (true or false is indifferent)

but watching nearer to the complex expression 
you use 5 conditions...the first is ACTIVE
so until you use as first operator AND you can get TRUE  (the block of code has been executed) only when Active is true plus the other conditions returns true on the other side of AND.

moreover putting 4 OR condition in sequence you must remember that  OR returns FALSE only if both the parameters are FALSE otherwise it returns TRUE... so you can expect false only when all the parameters are false 
F OR F  gives F  then  F OR F  gives F then F OR F gives false , at the end F AND F gives F  while F EQV F gives T
(I do not remember the order of execution of Boolean operator, it seems to me that first is OR and after AND...)
here a code test
Code: (Select All)
' we make some tests
Rem  AND versus EQV
Rem  wiki info https://qb64phoenix.com/qb64wiki/index.php/EQV

DefInt I
Dim iActive, ImouseX, ImouseY
iActive = 0
Locate 1, 1: Print " iActive  ImouseX   ImouseY"

For iActive = -1 To 0 Step 1
    ' the first run has iActive true while the second turn has iActive false
    ImouseX = 400: ImouseY = 100 ' ImouseX < 500 and ImouseY <200 are true
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;

    If iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " AND works "; Else Print " AND rests";
    '  If iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300) Then Print " AND + () work "; Else Print " AND +() rest";
    If iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " EQV works " Else Print " EQV rests"

    ImouseX = 600: ImouseY = 300 'All ImouseX and ImouseY are false
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;
    If iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " AND works "; Else Print " AND rests ";
    '  If iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300) Then Print " AND + () work "; Else Print " AND +() rest ";
    If iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " EQV works " Else Print " EQV rests "

    ImouseX = 700: ImouseY = 400 ' ImouseX>600 and ImouseY > 300 are true
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;

    If iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " AND works "; Else Print " AND rests ";
    '  If iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300) Then Print " AND + () work "; Else Print " AND +() rest ";
    If iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " EQV works " Else Print " EQV rests "

Next iActive


For iActive = -1 To 0 Step 1
    ' the first run has iActive true while the second turn has iActive false
    ImouseX = 400: ImouseY = 100 ' ImouseX < 500 and ImouseY <200 are true
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;

    Print iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300, ;
    '  Print iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300), ;
    Print iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300

    ImouseX = 600: ImouseY = 300 'All ImouseX and ImouseY are false
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;
    Print iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300, ;
    ' Print iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300), ;
    Print iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300

    ImouseX = 700: ImouseY = 400 ' ImouseX>600 and ImouseY > 300 are true
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;

    Print iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300, ;
    ' Print iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300), ;
    Print iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300

Next iActive

you can give a look at the results.
Reply
#6
@TempodiBasic

Che piacere vederti my friend from Italia!

Thanks for the better explanation. Boolean logic is not a must for programming, but it can make certain jobs, like in this neat mouse example, easier to code.

I want to get some more info on the SAME vs EQUALS above the bitwise comparison vs numeric values. For instance...

Code: (Select All)
DIM AS _UNSIGNED _BYTE a, b
a = 2
b = 4
PRINT a EQV b, a = b

So a EQV b is -7 in this example. I do not work with bits so I don't see how that -7 result was calculated.

I'll probably find uses for this EQV keyword in my code now, just like I did with SGN(). Funny, I actually found some code from several years ago that I did use SGN() in, but then forgot about it. I even forgot this was a Keyword of the Day I read less than 2 weeks ago. I mean isn't aging great?... Sure, if you're a damn bottle of wine! Oh well...

Note: Similar for strings in JAVA ==, which can work with strings and differentiates how the string was made. For instance, == is False for a$ = "Pete" b$="P"+"e"+"t"+"e" a$ == b$ is FALSE, while a$ = b$ is TRUE. Just saying.

Pete
Shoot first and shoot people who ask questions, later.
Reply
#7
wow I  googled and found the order of execution of the logical operator in QB
from first to last: NOT AND OR XOR EQV IMP


is this the same order of execution made by QB64pe? I think so, but I wait for developers response.


if so the above expression is


1.  iActive AND ImouseX<500
2.      result OR ImouseX>600
3.              result OR ImouseY < 200
4.                      result OR ImouseY> 300


so in the case iActive = 0 and ImouseX = 400 and ImouseY = 100
1.    0 AND -1 --->0
2.        0 OR 0  --->0
3.            0 OR -1  --->-1
4.                -1 OR 0 --->-1
Here there is a logical error if you need that iActive must be True to execute the block of code.
(here is like you are saying: if it is active and the mouse is at least at one of these positions (X<500, X>600, Y<200, Y>300) you do this...)


but using the ( ) ,surrounding the OR group of conditions, you can avoid this unwanted result... if you use AND is because you want that all the 2 parameters must be true to get back true as result. 


while  you use EQV when it is important to you to manage all the conditions that are both  F or  both  T.

Here a test code that compares expression original AND + 3 OR ,with the use of ()  AND +(3 OR), the use of EQV (EQV + 3 OR), the use of () (EQV + (3OR))

Code: (Select All)
' we make some tests
Rem  AND versus EQV
Rem  wiki info https://qb64phoenix.com/qb64wiki/index.php/EQV

DefInt I
Dim iActive, ImouseX, ImouseY
iActive = 0
Locate 1, 1: Print " iActive  ImouseX   ImouseY"

For iActive = -1 To 0 Step 1
    ' the first run has iActive true while the second turn has iActive false
    ImouseX = 400: ImouseY = 100 ' ImouseX < 500 and ImouseY <200 are true
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;

    If iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " AND works "; Else Print " AND rests";
    If iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300) Then Print " AND + () work "; Else Print " AND +() rest";
    If iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " EQV works "; Else Print " EQV rests";
    If iActive Eqv (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300) Then Print " EQV +() works " Else Print " EQV +() rests "


    ImouseX = 600: ImouseY = 300 'All ImouseX and ImouseY are false
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;
    If iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " AND works "; Else Print " AND rests ";
    If iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300) Then Print " AND + () work "; Else Print " AND +() rest ";
    If iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " EQV works "; Else Print " EQV rests ";
    If iActive Eqv (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300) Then Print " EQV +() works " Else Print " EQV +() rests "

    ImouseX = 700: ImouseY = 400 ' ImouseX>600 and ImouseY > 300 are true
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;

    If iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " AND works "; Else Print " AND rests ";
    If iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300) Then Print " AND + () work "; Else Print " AND +() rest ";
    If iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300 Then Print " EQV works "; Else Print " EQV rests ";
    If iActive Eqv (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300) Then Print " EQV +() works " Else Print " EQV +() rests "
Next iActive


For iActive = -1 To 0 Step 1
    ' the first run has iActive true while the second turn has iActive false
    ImouseX = 400: ImouseY = 100 ' ImouseX < 500 and ImouseY <200 are true
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;

    Print iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300, ;
    Print iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300), ;
    Print iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300; "       ";
    Print iActive Eqv (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300)


    ImouseX = 600: ImouseY = 300 'All ImouseX and ImouseY are false
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;
    Print iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300, ;
    Print iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300), ;
    Print iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300; "       ";
    Print iActive Eqv (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300)


    ImouseX = 700: ImouseY = 400 ' ImouseX>600 and ImouseY > 300 are true
    Locate , 7: Print " "; iActive; "   "; ImouseX; "   "; ImouseY;

    Print iActive And ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300, ;
    Print iActive And (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300), ;
    Print iActive Eqv ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300; "       ";
    Print iActive Eqv (ImouseX < 500 Or ImouseX > 600 Or ImouseY < 200 Or ImouseY > 300)

Next iActive


so the expression must pay attention to the order of execution of Logical operators to return the wanted result. As for all expression we can use () to modify the order of calculation.
Reply
#8
@Hi Pete
I am always fallen in love for this QB64pe community,
where I can talk, have good teacher, learn and expand my mind and my soul.
Yes I love BASIC, but there are so many dialects of it, only here I find so open persons to let me say, listen, try and learn from and with them.
That is fantastic!


Here my bitwise response to your question..
while  we use values more than 2 opposite you are working at bitwise level... if you want to work at logical level you must define 2 only value in opposite condition and use them only . So comparison and other kind of operation must reduce the result to one of the 2 value used for logical operation....
in this sense False = 0 is OK, True = not False is  good until in this logical universe we use only 0 for False and -1 for True 

(as you can see with this code
print 0, not 0
)
as far away we go from this binary universe (universe of 2 items and not the universe of number with basis 2) as we get back so bad unwanted results .


the response in code to your example is this
Dim As _Unsigned _Byte a, b
a = 2
b = 4
Print a Eqv b, a = b

Print "Here the bitwise explanation! In logical math there are only TRUE and FALSE, no numbers"
Print String$(14, "0") + _Bin$(a)
Print String$(13, "0") + _Bin$(b)
Print _Bin$(-7)


as you can see it is a bitwise operation using EQV so the bits in the same position if they are the same you get 1 and if they are different you get 0.
But the compiler (interpreter) at the end translates the binary number to the decimal number... so you get a signed number -7 also if you have declared 2 unsigned byte numbers.
To logical operators you must pass logical values (T or F) so conditions that returns those logical values
for example
print NOT(a=b) EQV (a not b)
no sense to pass numbers in any basis (binary, octal etc) to LOGICAL operators.


If you want code in bitwise, please talk with expert of this like Steve or anyone  else so ASM expert.

PS
JAVA is an universe that I would like explore... but I have 2 problems, the lack of time to use for, the fear to start a trip with no end.
Reply
#9
(12-11-2022, 04:50 PM)Pete Wrote: @TempodiBasic

Che piacere vederti my friend from Italia!
Mi piace vederti il mio amico d'Italia!

That's how I was taught in high school. I wouldn't have been able to come up with "vederti" without your help.  Heart

Umm... on topic, I would have never ventured using "EQV" for anything, and this is a new thing involving it to check if the mouse pointer is within a bounding box.
Reply
#10
(12-11-2022, 06:36 PM)mnrvovrfc Wrote:
(12-11-2022, 04:50 PM)Pete Wrote: @TempodiBasic

Che piacere vederti my friend from Italia!
Mi piace vederti il mio amico d'Italia!

That's how I was taught in high school. I wouldn't have been able to come up with "vederti" without your help.  Heart

Umm... on topic, I would have never ventured using "EQV" for anything, and this is a new thing involving it to check if the mouse pointer is within a bounding box.

Yeah, I absolutely love it for that application.
Reply




Users browsing this thread: 2 Guest(s)