Monday, May 27, 2013

Petit Computer Journal #15
Quickie Draw: A flipnote type app



I was reading messages in a Nintendo Life forum for Petit Computer when 2 people admitted to have inspiration to write a paint program over the weekend. I replied that it was unbelievable, because … me too! And suddenly, another one piped up and said that he too was inspired over the same weekend. Huh, sometimes real life is very strange.

So, anyway, I cooked up this drawing program real quick. I called it “Quickie Draw” because I wrote it in about one hour. It would have been faster, but it was done at the end of the day, and that day was extremely tiring because I was sick and was coughing and sneezing all day long. Overall, not a good condition to write computer programs.

QDRAW
@INIT
ACLS:GPAINT 1,1,1
PNLTYPE “OFF”
GPAGE 1: GPAINT 1,1,1

LOCATE 7,5:?”QUICKIE DRAW”
LOCATE 9,7:?”BY”
LOCATE 11,9:?”HARRY HARDJONO”

LOCATE 6,17:?”A CLEAR SCREEN”
LOCATE 6,18:?”B END PROGRAM”

So far, so good. There’s no problem at all here, or rather, there shouldn’t be at all. For some reason, I mixed up X and Y coordinates, so the “BY” somehow ended up in location 7,9. Ouch. How did that happen? Fixed it no problem.

@PRE
S=TCHST:X0=TCHX:Y0=TCHY
IF BTRIG()==16 GOTO @INIT
IF BTRIG()==32 GOTO @END
IF S==0 GOTO @PRE


You know, as simple as that @PRE is all about, I had a terrible time with it. The thing is, I knew it would be simple, but for some reason, I kept going off the deep end with various variables trying to keep track of different states of drawing. My brain was definitely jello when I did it. I kept thinking that my program was becoming too complicated and deleted my codes wholesale and started over. It was at my sixth attempt that I realized that S=TCHST should be the first thing I should grab. Doh! After that, no problem.

@LOOP
X1=TCHX:Y1=TCHY
GLINE X0,Y0,X1,Y1,14
X0=X1:Y0=Y1
IF TCHST==0 GOTO @PRE ELSE GOTO @LOOP

@END
END


@Loop is very simple, isn’t it? And in fact, that’s all there is to it. If you ever want to write a paint program where you never let the pen leave the paper, that’s all there is to it. Haha, joking aside, computer programming can be easy and fun. Just don’t do it while you’re on deathbed unless you’re addicted to it (like me).

So far so good.

I posted the program to the forum. Chat a little bit and 50 minutes later, I wrote: “BTW, I changed the program to flipnote type.”

Interesting, isn’t it? I was sick to my deathbed, but after a breakthrough, I just kept going, and changing it to flipnote app. It wasn’t hard at all!

‘PNLTYPE “OFF”:PP=6:GOTO@ANIM
PP=0
@INIT
IF PP>0 GOTO @FADE
ACLS:GPAINT 1,1,1
PNLTYPE “OFF”
GPAGE 1:GPAINT 1,1,15

@TITLE
LOCATE 7,5:?”QUICKIE DRAW”
LOCATE 9,7:?”BY”
LOCATE 11,9:?”HARRY HARDJONO”
LOCATE 6,15:?”(A) NEW PAGE”
LOCATE 6,16:?”(B) FLIP PICS”
LOCATE 6,17:?”(X) END PROGRAM”
LOCATE 10,20:?PP;”/99”
The first line is commented. This is because it goes to animator subroutine directly, just in case you want to see your masterpiece in action without having to redraw the whole thing. PP stands for number of pages, and although I peg it at 99 pages max, I doubt there is space in the program to hold that many.

@PRE
S=TCHST:X0=TCHX:Y0=TCHY
VSYNC 1
IF BTRIG()==16 THEN GOSUB @SP:GOTO @INIT
IF BTRIG()==32 THEN GOSUB @SP:GOTO @ANIM
IF BTRIG()==64 GOTO @END
IF S==0 GOTO @PRE
@LOOP
X1=TCHX:Y1=TCHY
GLINE X0,Y0,X1,Y1,14
X0=X1:Y0=Y1
IF TCHST==0 GOTO @PRE ELSE GOTO @LOOP
@END
END




It is very interesting that it doesn’t take much more code to turn the paint program into a flip note app. That’s because most of the work is done by the subroutines. A sign of well-designed program is that the implementation of such program is effortless. I know I’m bucking the convention here, but I think that heroic effort in computer programming is misguided. I’d rather have heroic effort in program design and pedestrian implementation of it. Computer programs that are easy to understand tend to get maintained more, and it’s not about documentation. It’s about the cleanliness of the algorithm. How many of you are willing to throw out existing code out and start over? Because if you do not, then you’re effectively working with first draft. Just ask any Communication teacher about the value of first draft. Not much, eh? Then why are you satisfied with your first implementation? Be willing to discard bad code!

@SP
GOSUB @ERASE
FN$=”GRP1:FLIP”+STR$(PP)
SAVE FN$
PP=PP+1:IF PP>99 THEN PP=99
RETURN

@ANIM
WAIT 15:SYSBEEP=FALSE
IF I<0 THEN I-0
FN$="GRP1:FLIP"+STR$(I)
LOAD FN$,FALSE
I=I+1:IF I>=PP THEN I=0
VSYNC 1:IF BTRIG()==64 GOTO @END
GOTO @ANIM

@ERASE
FOR Y=0 TO 191:FOR X=0 TO 255
IF GSPOIT(X,Y)==1 THEN GPSET X,Y,15
NEXT X
NEXT Y
RETURN

@FADE
FOR Y=0 TO 191:FOR X=0 TO 255
IF GSPOIT(X,Y)==14 THEN GPSET X,Y,1
NEXT X
NEXT Y
GOTO @TITLE
OK, so now we have a fully functioning flip note program. Notice, however, that it is not user friendly. It’s still rough on edges. However, due to good design, the algorithm is clean and modular and easy to change. One more round of polishing, and we’re good to go.

‘QUICKIE DRAW
‘A SIMPLE FLIPNOTE
‘HARRY HARDJONO MAY 2013
DELAY=10
PNLTYPE “OFF”
INPUT “HOW MANY PAGES”;PP
IF PP>0 GOTO@ANIM
PP=0:CC=14
@INIT
IF PP>0 THEN GOSUB @FADE:GOTO @TITLE
ACLS:GPAINT 1,1,1
PNLTYPE “OFF”
GPAGE 1:GPAINT 1,1,15
The first thing you notice is that there is an INPUT statement, asking you how many pages. This is for the @ANIM function. If you enter 0, then it will go to editing mode. Otherwise, it will animate the pages. This change will enable us to run the program from the main menu, instead of having to go to EDIT screen and edit the program manually.

Another change is that there is a variable DELAY right in the beginning. This is for the delay loop for the animation. The more loops, the slower the flip. I simply set it to a number, instead of asking the user what he wants. This is for simplification of the program. With better UI, I may let the user specify the delay.

@TITLE
LOCATE 7,5:?”QUICKIE DRAW”
LOCATE 9,7:?”BY”
LOCATE 11,9:?”HARRY HARDJONO”
LOCATE 6,15:?”(A) NEW PAGE”
LOCATE 6,16:?”(B) SAVE AND FLIP PICS”
LOCATE 6,17:?”(X) COPY TO NEW PAGE”
LOCATE 6,18:?”(Y) PEN/ERASER”
LOCATE 10,20:?PP;”/99”


Nothing too new here. The biggest change is that I’m now very specific about (B). There is a concern that ending the drawing mode may not save the image. I simply made it explicit that yes, there will be a saving. If you do not intend to save it, then during program restart, simply specify 1 frame less than before. No problem.

(X) copy function is actually easier to do, since you’re not doing anything much. The Pen/Eraser function comes out of the copy function. This way, you can simply erase the difference, instead of drawing the whole thing over. I don’t really need to do this but it’s very convenient to the user.

@PRE
S=TCHST:X0=TCHX:Y0=TCHY
VSYNC 1
IF BTRIG()==16 THEN GOSUB @SP:GOTO @INIT
IF BTRIG()==32 THEN GOSUB @SP:GOTO @ANIM
IF BTRIG()==64 THEN GOSUB @SP:GOTO @TITLE
IF BTRIG()==128 THEN CC=29-CC
LOCATE 1,0:IF CC==14 THEN ?”X” ELSE ?”O”
IF S==0 GOTO @PRE


There is a little trick in changing the CC color. Notice that CC=29-CC. This is very useful mathematical formula if you ever want to toggle the value of a variable between two numbers. Let’s say you want to toggle the variable G between 4 and 7. Simply add the two values and use the formula above. So, we have G=(4+7)-G. In this case, CC=(14+15)-CC. I suppose I should have written it that way so it won’t be so much a magic number.

Also, the X and O, is actually filled block and hollow block in the program. I simply put the ASCII equivalent here.

@LOOP
X1=TCHX:Y1=TCHY
IF CC==14 THEN GLINE X0,Y0,X1,Y1,CC ELSE GFILL X1-3,Y1-3,X1+3,Y1+3,CC
X0=X1:Y0=Y1
IF TCHST==0 GOTO @PRE ELSE GOTO @LOOP
@END
SYSBEEP=TRUE
END


There is GLINE and GFILL. Why the difference? One is drawing (pencil) the other is erasing (eraser). I did try to erase with GLINE. Didn’t like it one bit. I also added SYSBEEP=TRUE. This is because I turned off SYSBEEP during @ANIM. In general, it’s good to have a specific exit point such as @END in the program even if you don’t know what you want to do with it.

@SP
GOSUB @ERASE
FN$=”GRP1:FLIP”+STR$(PP)
SAVE FN$
PP=PP+1:IF PP>99 THEN PP=99
RETURN

@ANIM
LOCATE 6,15:?”                “
LOCATE 6,16:?”                “
LOCATE 6,17:?”(X) QUIT            “
LOCATE 6,18:?”                “
LOCATE 10,20:?RIGHT$(“0”+STR(I),2;”/99 “
SYSBEEP=FALSE
IF I<0 THEN I-0
@ANIM2
LOCATE 10,20:?RIGHT$("0"+STR$(I),2);"/99 "
FN$="GRP1:FLIP"+STR$(I)
LOAD FN$,FALSE
I=I+1:IF I>=PP THEN I=0
FOR J=0 TO DELAY:VSYNC 1:IF BTRIG()==64 GOTO @END
NEXT J
GOTO @ANIM2




I had to duplicate the screen displays so the screen will update properly. I suppose I can write yet another function to simplify the structure. Since I’m going to be done with this, I decided to just leave it out like that. It is a good idea to put the screen displaying routine to a function, though. It makes it cleaner.

@ERASE
LOCATE 0,0:?”Z”
FOR Y=0 TO 191:FOR X=0 TO 255
IF GSPOIT(X,Y)==5 THEN GPSET X,Y,15
NEXT X
NEXT Y
LOCATE 0,0:?” “
RETURN

@FADE
LOCATE 0,0:?”Z“
FOR Y=0 TO 191:FOR X=0 TO 255
IF GSPOIT(X,Y)==14 THEN GPSET X,Y,5
NEXT X
NEXT Y
LOCATE 0,0:?” “
RETURN


The “Z” is the clock in the program. It indicates that the program is busy. It does take a while for the computer to scan the whole screen.

And that’s about it. Not a bad program to write in a hurry.