Showing posts with label screen. Show all posts
Showing posts with label screen. Show all posts

Monday, October 1, 2012

Petit Computer Journal #9


Petit Computer Journal #9

Loops and Banner

A quick diversion here, I want to discuss a little bit about loops. We have been doing it, and it's not hard to do, but that doesn't mean people understand them completely. I keep seeing people do things in inefficient ways. I know I'm bucking the convention here, but I think making the program work the way you want it is the minimum requirement. You should also improve the program in such a way that it is well structured, implemented, and clear.

So, what's so hard about loops? Nothing. That's why it's important for you to master loops. There are several kinds:

1. Infinite loop: This is easy. You basically want to repeat something over and over. Most C programmers would use this construct:

while (1) { ... }

That's an infinite loop. But I think this is the case where GOTO is better. Here it is in Smile BASIC:

@LOOP
...
GOTO @LOOP

And that's it for infinite loop. It's good for use as IDLE loop.

2. REPEAT-UNTIL loop: Also known as DO-WHILE, this is just like infinite loop, but it ends when there is a certain condition to be met. You can do it like this:

@LOOP
...
IF (NUM

or this

@LOOP
...
IF !(NUM>=MAXNUM) GOTO @LOOP

or this

FOR I=1 TO 1:VSYNC 1:I=BTRIG():NEXT

That last example is basically "Press any BUTTON to continue". It works because as long as I is zero, the loop repeats.

Another example of REPEAT-LOOP would be this program in finding out the value of PI using fraction:

'PI
N1=3:N2=1
R1=ABS(PI()-(N1/N2))

FOR I=1 TO 1
R2=(ABS(PI()-(N1/N2)))
IF (N1/N2)
IF (N1/N2)>PI() THEN N2=N2+1
I=!R2:'TERMINATE WHEN I==0.

IF R2
NEXT

?PI()
?(N1/N2)

The structure is similar to HI-LO game, and it's a good exercise for you to do in order to see if you understand the concept. In the meantime, if you see the statement I=!R2 where R2 is fraction, we can say that I'm abusing ! operator to the max!

Haha, joking aside, I do tend to push the interpreter beyond standard convention. It takes a lot of trial and error, with mostly error on the result. But you can't argue that the result is good.

3. WHILE-WEND loop: This loop differs from REPEAT-UNTIL loop by the fact that the code may not be executed at least once. By putting the condition on top of the loop, the whole code may be skipped.

@LOOP
IF (NUM>=MAXNUM) GOTO ENDLOOP
...
GOTO @LOOP
@ENDLOOP

or this

@LOOP
GOTO @ENDLOOP
...
@ENDLOOP
IF (NUM

or this MADLIBS example

A$="HELLO [N]. HOWDY [N]. GOODBYE [N]."
LINPUT "NAME";N$
T$="[N]"

@WHILE LOOP
FOR I=0 TO INSTR(A$,T$)
A$=SUBST$(A$,INSTR(A$,T$),LEN(T$),N$)
NEXT
?A$

Yes, it's that easy! See explanation on FOR-LOOP on how this works.

4. FOR-LOOP. The standard BASIC loop. The workhorse loop of BASIC. How difficult can it be? It's just like WHILE loop, except the value of I is incremented within the code. Smile BASIC will not execute the loop when the parameters do not match, such as this:

FOR I=0 TO -1 STEP 1

I took advantage of this fact by putting INSTR() directly on the loop declaration. You don't see "STEP 1" written out, but it is implied. If you need stepping other than 1, then you need to write it out. STEP 4, STEP -1, and so on.

NUM=0
@LOOP
IF (NUM>MAXNUM) GOTO ENDLOOP
...
NUM=NUM+1:'OR NUM=NUM+N WHERE N IS THE STEP VALUE
GOTO @LOOP
@ENDLOOP

FOR NUM=0 TO MAXNUM: ... :NEXT

And that's it for LOOP structures. There is a couple more things we need to talk about. BREAK and CONTINUE.

CONTINUE is the way for the loop to skip processing to the next step. That is, whatever we want to do, we're done! We don't want to do any more.

@LOOP
...
IF CONTINUE GOTO LOOP
...
GOTO @LOOP

Let's do an example with FOR loop. Let's say we want to skip displaying vowels. We can do this:

A$="HELLO SAILOR!"
FOR I=0 TO LEN(A$)-1
IF INSTR("AEIOU",MID$(A$,I,1))>=0 THEN NEXT
? MID$(A$,I,1);
NEXT
?:?"DONE!"

Yes, you have two NEXT statements in there. The NEXT on IF line functions as CONTINUE. Pretty easy, right? (1)

BREAK, however, is not so easy. Not that it's difficult to understand, but it's difficult to implement because we cannot GOTO out of LOOP. Or maybe we can, but I don't quite understand how it works exactly despite my numerous experiments. So, we won't GOTO out of FOR loop.

@LOOP
...
IF BREAK GOTO @ENDLOOP
...
GOTO @LOOP
@ENDLOOP

That's it. Just breaking out of the loop cycle. Now let's see it with FOR loop.

A$="HELLO SAILOR!"
FOR I=0 TO LEN(A$)-1
IF INSTR(" ",MID$(A$,I,1))>=0 THEN I=LEN(A$):GOTO @ENDLOOP:'NEXT
? MID$(A$,I,1);
@ENDLOOP
NEXT
?:?"I=";I

You can see immediately that the structure isn't good. We have to use GOTO @ENDLOOP, instead of a simple NEXT because the program will return to the line of execution, resulting NEXT without FOR error. We have to put the label @ENDLOOP in separate line. The value of I is 14, which may not be what we want. In all, BREAKing out of loop isn't a good solution with this BASIC.

SAMPLE PROGRAM: TOUCH SCREEN KEYBOARD
@TOUCH
MX=256:MY=192:'MAXX,MAXY
SX=8:SY=6:'SPANX,SPANY
WX=FLOOR(MX/SX):WY=FLOOR(MY/SY):'WIDTHX,WIDTHY
TX=TCHX:TY=TCHY
FOR I=1 TO TCHST
IF TX
VSYNC 1:GFILL 0,0,MX,MY,0:GFILL KX*WX,KY*WY,(KX+1)*WX,(KY+1)*WY,8
LOCATE 0,0:?"KX=";KX;"  KY=";KY;"   "
NEXT
GOTO @TOUCH

Here is a simple way to divide the screen to rectangular areas.
MAXX,MAXY = SCREEN AREA/KEYBOARD SIZE
SPANX,SPANY=NUMBER OF KEYSPAN X,Y
WIDTHX,WIDTHY=INTERNAL VALUES USED FOR DRAWING
KX and KY =THE VALUE IN SPANX,SPANY THAT DENOTES ACTIVE CELL

If you look at FOR I=1 TO TCHST code, you maybe forgiven to think that it is a loop. It's not a loop. It is a multi-line IF, which is something Petit Computer does not support. It works in this case, but it's a special case.


SAMPLE PROGRAM: BANNER

Here is an example of nested loop. That is, loop within loop structure. It is also an example of GPUTCHR, where I'm using it for fine scrolling and zooming technique.

@ASKB
ACLS
LINPUT "MESSAGE 1/3?";B1$
LINPUT "MESSAGE 2/3?";B2$
LINPUT "MESSAGE 3/3?";B3$
B$="      "+B1$+B2$+B3$+"      "
ACLS

@LOOP
FOR I=1 TO LEN(B$)-5
FOR X=63 TO 0 STEP -4
VSYNC 1:IF BTRIG() THEN GOTO @ASKB
GCLS
FOR J=-1 TO 3:GPUTCHAR X+(J*64),40,"BGF0",ASC(MID$(B$,I+J,1)),0,8:NEXT
NEXT
NEXT
GOTO @LOOP

The sharp eyes among you will see that I did GOTO out of FOR loop with GOTO @ASKB. How does that work? Isn't GOTO out of loop is bad? Yes, it is. I don't understand it myself. It seems to work fine in this case, but I still discourage its use. Good for demos, but please don't use it for professional programs.

'HI-LO
S=RND(100)+1
FOR I=1 TO 1
INPUT "GUESS A NUMBER(1-99)";N
IF N>S THEN ?"TOO HIGH"
IF N
I=!ABS(N-S)
NEXT
?"CORRECT!"

'HI-LO
S=RND(100)+1
@LOOP
INPUT "GUESS A NUMBER(1-99)";N
IF N>S THEN ?"TOO HIGH"
IF N
IF N==S THEN ?"CORRECT!":END
GOTO @LOOP





(1) BTW, even though the CONTINUE looks fine, you have to be careful that you don't end the loop at CONTINUE, because the loop will end there and you will get NEXT without FOR error. There is the reason why I end the string with "!" when the condition only checks for vowels. That's being sneaky, and it's all right for you to do it, but do document it. Try adding exclamation mark at INSTR:

A$="HELLO SAILOR!"
FOR I=0 TO LEN(A$)-1
IF INSTR("AEIOU!",MID$(A$,I,1))>=0 THEN NEXT
? MID$(A$,I,1);
NEXT
?:?"DONE!"



Monday, September 3, 2012

Petit Computer Journal #5


Petit Computer Journal #5 - Buttons and Touchscreen

Let's take a little detour for now. We should be doing strings and graphics, but I want to do something else real quick: Buttons, Touchscreen, and Keyboard. In other words: INPUT.

We have done buttons, touchscreen, and keyboard inputs before. However, I'm interested in doing them all at once. And the trick is to do it without stopping the other input methods. That's not too easy.

Regarding keyboard input method that doesn't stop other process, we have INKEY$. We also have touchscreen variables TCHX,TCHY and all those. How about buttons? We have BUTTON(0), and that is sufficient. So, at the surface, we have all that we need.

The thing is, I don't want to have to structure the program into multi-threading format at this point in time. So, we will have to make some sacrifices. The INKEY$ is well enough. How about buttons and touchscreen?

In Touchscreen, it is convenient to have a drag-and-drop process. That means X1,Y1,X2,Y2,TouchStatus. Let's build that capability.

@SETT
IF TCHST==0 THEN TS1=TCHST:RETURN
IF TS1==0 THEN TX1=TCHX:TY1=TCHY:TS1=1
IF TS1==1 THEN TX2=TCHX:TY2=TCHY
TS1=TCHST
RETURN

That looks simple enough. Basically, we want to update the variables if TCHST==1. The first line takes care of that by returning from subroutine if TCHST==0. Next, we want to see which pair we want to update X1,Y1 or X2,Y2? And that's all there is to it!


The buttons isn't so simple, though. There are 4 possible arrangements that I can see:
1. No Wait+Multiple: BUTTON(0)
2. No wait+Single: @SETB1
3. Wait+Multiple: @SETB2
4. Wait+Single: @SETB3

Of these, we want no wait version. If the no wait version is equivalent to INKEY$, then the wait version is equivalent to INPUT. The whole process involve trying out different versions of the commands. You see the finished product as clean, but I assure you that the process involves repeatedly trying and failing to come up with that clean method. You do not see the hard work that is done. At least, if you ever wonder why my progress is at glacial pace, you know the reason: Lacking tutorial such as this, I do a lot of experiments, not all of them successful.

There are 4 cases and only 3 subroutines. The first case can be easily met via BUTTON(0). The rest is done with simple subroutines. It only works on the first 8 bits, corresponding to UDLRABXY. This is because the method I use requires string characters, and those only goes to 255. I typed in the character in the actual program, but for the purpose of tutorial there are two index variables used by INSTR()

1. IST1$=CHR$(128)+CHR$(64)+CHR$(32)+CHR$(16)+CHR$(8)+CHR$(4)+CHR$(2)+CHR$(1)
2. IST2$=CHR$(129)+CHR$(65)+CHR$(33)+CHR$(17)+CHR$(9)+CHR$(5)+CHR$(3)+CHR$(2)

I use this technique a lot as it simplifies things greatly. It's not the fastest running code, and so only amateur hobbyist would use it. Certainly not a professional quality code. If need be, I may changed the code later to a more efficient one. But I like doing rapid prototyping in the beginning.

One more thing, the no wait version is tricky. If you check out the clock, you will see that no-wait @SETB1 does cause the program to stop when you press the button for a long time. A way to fix this would be to use a variable, but I would rather just do it directly with BUTTON(0) or @SETB2.

@SETB1 :'SINGLE FIRE
INBUTTON$="":Z=BUTTON(0):IF!Z THEN RETURN
FOR Z=0 TO 1:Z=BUTTON(3):NEXT:Z=Z AND 255
Z=INSTR(IST2$,CHR$(Z)):IF Z< 0 THEN RETURN
INBUTTON$=MID$("YXBARLDU",Z,1)
RETURN

@SETB2 :'CONTINUOUS
INBUTTON$="":Z=BUTTON(0):IF!Z THEN RETURN
Z=Z AND 255:Z=INSTR(IST1$,CHR$(Z)):IF Z< 0 THEN RETURN
INBUTTON$=MID$("YXBARLDU",Z,1)
RETURN

@SETB3 :'WAIT
INBUTTON$=""
FOR Z=0 TO 1:VSYNC 1:Z=BUTTON(1):NEXT:Z=Z AND 255
Z=INSTR(IST2$,CHR$(Z)):IF Z< 0 THEN RETURN
INBUTTON$=MID$("YXBARLDU",Z,1)
RETURN

And those are the functions. Next, let's write a quick demo program to demonstrate the different functions. It may be best that you write a program and save it because you will be using this at all times. I know I do!

'BUTTON/TOUCHSCREEN TEST EXAMPLE
CLS:CLEAR:P1=0:P2=1
@MAINLOOP
LOCATE 0,0:?TIME$
VSYNC 1:A$=INKEY$():?A$
GOSUB @SETB1:'?INBUTTON$;
GOSUB @SETT

IF INBUTTON$!="" OR TS1 THEN GOSUB @DT
GOTO @MAINLOOP

@DT :'DRAW TEXT
IF INBUTTON$!="" THEN L1=(L1+1)%32:LOCATE L1,1:?INBUTTON$;

'DRAW BOX
IF INBUTTON$=="L" THEN P1=P1+15
IF INBUTTON$=="R" THEN P1=P1+1
IF INBUTTON$=="U" THEN P2=P2+15
IF INBUTTON$=="D" THEN P2=P2+1
P1=P1%16:P2=P2%16
SX1=FLOOR(TX1/8):SY1=FLOOR(TY1/8)
SX2=FLOOR(TX2/8):SY2=FLOOR(TY2/8)
FOR X=SX1 TO SX2:FOR Y=SY1 TO SY2:
C$=CHR$(151):COLOR P2:'0=BIG BLOCK CHARACTER IN PETIT COMPUTER
IF X==SX1 OR X==SX2 THEN C$=CHR$(150):COLOR P1:'1=VERT LINE
IF Y==SY1 OR Y==SY2 THEN C$=CHR$(149):COLOR P1:'2=HORZ LINE
IF X==SX1 AND Y==SY1 THEN C$=CHR$(152):COLOR P1:'3=UPPERLEFT
IF X==SX2 AND Y==SY1 THEN C$=CHR$(153):COLOR P1:'4=UPPERRIGHT
IF X==SX1 AND Y==SY2 THEN C$=CHR$(154):COLOR P1:'5=LOWERLEFT
IF X==SX2 AND Y==SY2 THEN C$=CHR$(155):COLOR P1:'6=UPPERRIGHT
LOCATE X,Y:?C$;
NEXT:NEXT

RETURN

For some reason, my computer does not read my memory card. That's a setback. I have to have those special characters, and so, I'm forced to do it the hard way, which is very annoying. However, either I overcome that setback, or I don't do this at all. I can work on the DSi no problem, but if I want to share it, I have to do this thankless work of translating those characters into their numeric equivalent. I wrote a simple program just for that:

'ASCII TABLE
S=0
@MAINLOOP
CLS
FOR I=S TO S+15
R=I%16
LOCATE 0,R:?I;:LOCATE 5,R:?CHR$(I)
NEXT

GOSUB @SETB3

IF INBUTTON$=="U" THEN S=S+16
IF INBUTTON$=="D" THEN S=S+256-16
S=S%256
?:?"S=";S;"   ";INBUTTON$:WAIT 60:'OPTIONAL FOR DEBUGGING
GOTO @MAINLOOP

And that's it. Not even 10 minutes. You need to provide Subroutine @SETB3, but that's trivial. Just copy the one above.



Problems and How to Ask Questions

You know how people say there's no such thing as stupid questions? I know I'm bucking the convention here, but I'd say there are! Here's a sample, quoted in its entirety:

"Help! SAVE doesn't work."

I'm not saying that SAVE command is so easy that it cannot fail. I am saying that the question doesn't even begin to show the framework in which the problem occurs. We need more data! You know how PRINT statement works, right? What if there's somebody who ask help like this: "How do you use PRINT?", following your answer with "It doesn't work."

You know it works, and you know how it works. The problem is, how does it doesn't work? You have no clue as to what problem this person encounter. So, here is how you handle a problem that you cannot solve, because the unwritten rule is, if you ask a question that you later answer without any prompting whatsoever, YOU JUST ASKED A STUPID QUESTION THAT YOU KNOW THE ANSWER TO!

Problem solving technique:
1. Ran into problem, WRITE IT DOWN!
2. Write down all the relevant elements.
3. Read the Manual/Help file
4. WRITE ALL THE POTENTIAL SOLUTIONS DOWN.
5. Implement them all.

That's step-by-step. You are not allowed to skip steps. Half of your problems can be solved this way. As for the rest, well, that's when it gets tricky.

Hard Problem Solving:
1. You are tired. STOP AND GO TO SLEEP!
2. Wake up. Eat something solid
3. Repeat problem solving steps above.

By this time, if you followed this advice, a lot of you would do a lot of face palming "Of course! Why didn't I think of that?" sequence. That happens to me, too.

Stubborn Problem Solving:
1. You are sadly misunderstanding the problem. YOU are at fault!
2. Find 3 different interpretations to the problem.
3. Also, find 3 different OTHER places where it may cause the problem.
4. Consult the manual for help.

It may help to pretend that you're a newbie who doesn't understand everything. Don't laugh. It works! I used that technique myself occasionally. For the next level you must first admit that you are stupid. No, really. You are! You may humbly ask other people for help. Ever seen somebody arrogantly ask for solution to their problem? That never gets resolved, does it? Bingo.

Impossible Problem Solving:
1. Explain What the Problem is
2. Tell what you think are the relevant elements
3. Show what you did to solve the problem
4. WRITE THE SIMPLEST, SHORTEST CODE to explain the problem.

That last element is vital. No one wants to read 200 lines of code just to debug your program. So, there. Problem solving explained. Either that or you explain your problem to a duck.

Haha, joking aside, the ability to properly explain your problem is crucial in getting it solved. You don't want to ask a question like a grade schooler if you can ask your questions like a professor!

My PRINT doesn't work!

1. Did you type it in RUN(direct) mode or EDIT (deferred) mode?
2. Did it give you Syntax Error?
3. Did it print 0?
4. Did you set VISIBILITY?

What if PRINT doesn't work because it was set to XOR Mode? How will you respond to that? You can't set Console to XOR mode, right? How does that work? This is where giving out sample code is crucial.

CLS
COLOR SET XOR ! DOIT
PRINT "HELLO WORLD"

SET and DOIT ARE not keywordS. Why is there an exclamation mark preceding it? Because when I put it after the word (DOIT!), the computer complained, DUH!

You see how sample source code clarifies the issue quickly and easily? Don't act like a grade schooler. Ask questions like a professor! When I see the words "I don't understand ..." it'd better be followed by "These are the things I tried in order to understand it."



Monday, August 27, 2012

Petit Computer Journal #4



Petit Computer Journal #4

Knowing that computer is composed of numbers makes it easy to understand. That does not make it easy to do, you see, just to understand. The point is: The computer does what you tell it to do, not what you think you tell the computer to do. Faulty language implementation is an exception to that rule, and even then, you need to figure out a way around the problem.

Computer programming can be fun, but it can be very frustrating, indeed. The question is, what will you do to make computer programming fun? If the answer is to make games, then you're probably off to the wrong start. If the answer is to make games that people want to play, then you're probably off to the right start.

You see, computer programming is all about problem solving. What problem are you trying to solve? Without a clear goal, you probably will just do things randomly. Maybe you discover something, or maybe not. With a clear goal, however, you can work on the steps to achieving that goal. Then, when you finally solve that problem and arrive at your goal, your satisfaction level is quite high. That, my friend, is the fun of computer programming.

It's like winning a game, solving a puzzle, guessing a riddle. Before you did it, you don't know. After you did it, you know. That's fun.

Speaking of goals, you are still a beginner, so let's keep things simple for now. Let's start by figuring out how to tell a computer to do something simple.

Inkey$, input, linput

Let's get the keyboard input out of the way real quick. What is the difference between INKEY$, INPUT, AND LINPUT? Write a small program to check it out!

'Keyboard input source code example
@MAINLOOP
VSYNC 1: A$=INKEY$
IF A$!="" THEN B$=A$
LOCATE 0,0:?"A$=";A$;"   "
LOCATE 0,2:?"B$=";B$;"   "
GOTO @MAINLOOP

There are 3 things you have to see here:
VSYNC 1: This synchronized the system 1/60 second. Try it with different values and see what happens!
A$=INKEY$: This gets the keyboard value and assign it to A$
IF A$!="" THEN B$=A$: Since the value disappear at the next iteration, and we want to keep the old value, we assign the value of A$ to B$, but only if there is something to copy.

And that's it! If you are writing a computer game that cannot wait for user input, then INKEY$ is the way to go. I understand that it isn't the easiest to use, but it's there if you want it.

What's the difference between INPUT AND LINPUT? Try them out and see!

@MAINLOOP
VSYNC 1: INPUT "X,Y",X,Y
?"X=";X:?"Y=";Y
?:?:'DOUBLE BLANK LINES
VSYNC 1: LINPUT "DATA:";A$
?"A$=";A$
WAIT 300
GOTO @MAINLOOP

INPUT takes several inputs and assign them to different variables. This is very useful for inputting numeric values. Just type them out and separate them with comma. LINPUT takes in a string, commas included. Just one string.

Can you take string and numbers using INPUT? Try it and see!

@MAINLOOP
VSYNC 1: INPUT "X$,Y",X$,Y  '<==change here
?"X=";X$:?"Y=";Y            '<==Change here
?:?:'DOUBLE BLANK LINES
VSYNC 1: LINPUT "DATA:";A$
?"A$=";A$
WAIT 300
GOTO @MAINLOOP

Yes, you can! If the program doesn't understand your input, it will ask you to re-enter the data "?Redo from start". In which case, you re-enter the data, hopefully without mistake this time!


Touch Screen TCHX,TCHY,TCHST,TCHTIME PNLTYPE

Buttons and keyboard are nice, but we have something there that is just begging to be used: Touchscreen! I know I'm bucking the convention here, since most people are satisfied writing their beginner's program using INPUT or BUTTON(), but I really want to use the touch screen. Fortunately, it's as easy to use as INKEY$.

It's just some variables, and you even use it like you do INKEY$. The difference is that there is more than one, and you use numeric variables. Let's do it. It is helpful if we disable the on-screen keyboard. We do it via PNLTYPE command. Simply set it to "OFF".

'Touchscreen input source code example
PNLTYPE "OFF"
CLS
@MAINLOOP
VSYNC 1
X=TCHX:Y=TCHY:S=TCHST:T=TCHTIME
LOCATE 0,0:?"X=";X;"   "
LOCATE 0,2:?"Y=";Y;"   "
LOCATE 0,4:?"S=";S;"   "
LOCATE 0,6:?"T=";T;"   "
GOTO @MAINLOOP

Hit the Select button to stop the program. Yup. Just like INKEY$. The difference is, X and Y values are not reset to zero when the stylus is off the screen even though the status (TCHST) and timer (TCHTIME) are reset.


Math - Arithmetic

Alright, I need you to confess: Who among you have not yet finished 1st Grade? You know, the school grade right after Kindergarten? Whaat? You don't know Arithmetic? Oh, dear. This is bad. I think maybe you need to learn how before we can continue.

Haha, joking aside, you do need to know Arithmetic. Some Trigonometry, too. How about Algebra? Yes, you do need to know how to manipulate variables. Fortunately, if you know Show-and-Tell, you may be alright. Here's a little something that's useful to know: Mapping function.

map() is something that is built-in in Processing computer programming language. It's a good programming language. Check out www.processing.org for details.

In the meantime, let's implement it in BASIC. The idea is, if you have a number that is between two numbers, given another two numbers, what will be the number that has the same ratio as the first? In mathematical format, assuming X is the first number, and Y is the second, we have

X1-X2-X3 X2 is between X1 & X3
Y1-Y2-Y3 Y2 is between Y1 & Y3
Since the ratio is the same, we have
(X2-X1)/(X3-X1)=(Y2-Y1)/(Y3-Y1)

Solve for Y2:
(Y2-Y1)/(Y3-Y1)=(X2-X1)/(X3-X1)
(Y2-Y1)=((X2-X1)/(X3-X1))*/(Y3-Y1)
Y2=(((X2-X1)/(X3-X1))*/(Y3-Y1))+Y1

And that's all there is to it! Work it out on paper if you're having trouble. I find it helpful to draw triangles to visualize the problem.


A Math Explorer sample program

We want to feature a lot of math here, so we're going to just do it all in one program. The program will features different modes, and take inputs from touch screen, normalized to 0-5 for both X and Y. Furthermore, if the stylus is on top-left corner, we'll change the mode.

0: Simple Arithmetic
1: Math functions
2: Logical Math
3: Exponent

Here goes:

Part 1: Touch screen input. No problem there. Just copy it from the sample program above.


'Math Explorer
PNLTYPE "OFF"
CLS
@MAINLOOP
VSYNC 1
X=TCHX:Y=TCHY:S=TCHST:T=TCHTIME

Part 2: Display X,Y, Mode, and Cycle Mode. If you remember our COUNTER program example? Yup, just like that!

IF (X<32 AND Y<24 AND T==1) THEN MODE=MODE+1
MODE=MODE%4:'MODE=0-3
LOCATE 0,0
?"X=";X;"     Y=";Y;"     MODE=";MODE

Part 3: Normalize X and Y. We already have the mathematical formula for this. Just implement that using GOSUB.

X1=0:X2=X:X3=255:Y1=0:Y3=5:GOSUB @MAP:XP=Y2:'CALCULATES XP=Y2
X1=0:X2=Y:X3=191:Y1=0:Y3=5:GOSUB @MAP:YP=Y2:'CALCULATES YP=Y2
?"XP=";XP;"     YP=";YP;"     "

GOTO @MAINLOOP

@MAP
Y2=(((X2-X1)/(X3-X1))*(Y3-Y1))+Y1
RETURN


And that's the beginning. We'll continue with Part 4 next, but first, run this program and see that we have normalized XP and YP, and that the MODE cycles 0-3 satisfactorily.



Change the program slightly to this before continuing. Yes, I expect you to be able to read! I know it's hard in the beginning, but please persevere.

'Math Explorer
PNLTYPE "OFF"
CLS
@MAINLOOP
VSYNC 1:IF MODE!=2 THEN CLS
X=TCHX:Y=TCHY:S=TCHST:T=TCHTIME

IF (X<32 AND Y<24 AND T==1) THEN MODE=MODE+1
MODE=MODE%4:'MODE=0-3
LOCATE 0,0
?"X=";X;"     Y=";Y;"     MODE=";MODE;"     "

X1=0:X2=X:X3=255:Y1=0:Y3=5:GOSUB @MAP:XP=Y2:'CALCULATES XP=Y2
X1=0:X2=Y:X3=191:Y1=0:Y3=5:GOSUB @MAP:YP=Y2:'CALCULATES YP=Y2
?"XP=";XP;"     YP=";YP;"     "

GOTO @MAINLOOP

@MAP
Y2=(((X2-X1)/(X3-X1))*(Y3-Y1))+Y1
RETURN


And that's the program. Now, here is some snippets of code. I trust that you know where to put this.

?:?
ON MODE GOTO @ARIT, @FUNC,@LOGI, @EXPO
GOTO @MAINLOOP:'INVALID CHOICE

@ARIT
?"X+Y=";(X+Y)
?"X-Y=";(X-Y)
?"X*Y=";(X*Y)
IF Y!=0 THEN ?"X/Y=";(X/Y)
IF Y!=0 THEN ?"X%Y=";(X%Y)
IF YP!=0 THEN ?"X%YP=";(X%YP)
GOTO @ENDLOOP

@FUNC
?"FLOOR(XP)=";FLOOR(XP)
?"RND(X)=";RND(X)
?"RND(XP)+20=";RND(XP)+20
?"ABS(X-128)=";ABS(X-128)
?"SGN(X-128)=";SGN(X-128)
?"SWAP  ":SWAP XP,YP
?"XP=";XP;"     YP=";YP
IF S==1 THEN WAIT 30
GOTO @ENDLOOP


@LOGI
LOCATE 0,4
?"X=  ";:V=X:GOSUB @BIN
?"Y=  ";:V=Y:GOSUB @BIN
?"AND ";:V=(X AND Y):GOSUB @BIN
?"OR  ";:V=(X OR Y):GOSUB @BIN
?"XOR ";:V=(X XOR Y):GOSUB @BIN
?
?"X=  ";:V=X:GOSUB @BIN
?"NOT ";:v=NOT(X):GOSUB @BIN
?"!   ";:v=!X:GOSUB @BIN
GOTO @ENDLOOP

@EXPO
?"SQR(X)=";SQR(X)
?"EXP(XP)=";EXP(XP)
IF X!=0 THEN ?"LOG(X)=";LOG(X)
?"POW(2,XP)=";POW(2,XP)
?"POW(3,XP)=";POW(3,XP)


@ENDLOOP
GOTO @MAINLOOP

'SPLIT THIS TO THE END

@BIN
FOR I=0 TO 7
P=POW(2,I)
IF (P AND V) THEN ?"1"; ELSE ?"0";
NEXT
PRINT
RETURN




One more round of Math and we'll be done! It's all about Trigonometry. We'll save it for later until after we learn Graphics!