Author Topic: DrawFrame - animation sub using DRAW  (Read 6688 times)

0 Members and 1 Guest are viewing this topic.

Offline dajan

  • Newbie
  • Posts: 41
    • View Profile
DrawFrame - animation sub using DRAW
« on: January 18, 2020, 02:05:14 pm »
The DRAW is a cool sub, having it's own sublanguage. But can it be more cool? Sure thing! Let's just encapsulate it by another sub, say DrawFrame, that takes one more parameter - time of the frame to draw - and can process 2 more statements within the drawstring for animation purposes: the "K" statement to define time intervals for animation and the "Q" statement for easy statements sequence repeating.

Here's the mentioned sub's code with a  simple player and a 60 seconds long demo clip$ showcasing most of new statements in simple animations.
Syntax of the new statements is described in code comments at the beginning.
Demo player is controled by arrow keys (time shift, speed), space (pause), R(reverse) and +/- (size).

Code: QB64: [Select]
  1. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2. ' DrawFrame + DrawPlayer demonstration
  3. '
  4. ' ver. 1.0.1
  5. ' by Daniel Janec, 2020
  6. ' DrawFrame sub adds the "K", "V" and "Q" statements to the Draw sub statement set to handle mostly animation
  7.  
  8. ' Syntax:
  9. '    DrawFrame ( sourceString$, frameTime, size )
  10. ' Parameters:
  11. '    sourceString$ - a string containing Draw statements and new/modified Drawferame statements described bellow
  12. '    frameTime - in seconds, specifying the time, in which animated statements are drawed
  13. '    size - draw magnifying factor, 1 is original size, 2 is double, 0.5 is half size etc.
  14. '
  15. ' Syntax of the new or modified DrawFrame statements:
  16. ' K [id [ _ idRelativeK ] : ] [+/-] startTime; [+/-] endTime [ [# / *] [repeatCount] ]
  17. '    Defines time interval "id" used for grapihical statements animation, starting at strartTime sec, ending at endTime sec,
  18. '      optionaly repeating animation repeatCount times (or indefinetly if omitted) by using "*" for straight repeat or "#" for back-and-forth repeat.
  19. '    Also sets this interval for next animated statements.
  20. '    If "_" is used, the "+" or "-" sign can by used in time definition to set startTime/endTime relatively to another defined K interval "idReativeK".
  21. '
  22. ' K [id]
  23. '    Sets defined interval "id" for next animated statements
  24. '    Following statements written in form X [!] x1,y1; [!] x2;y2 (e.g. M 100,100;200;200) will be animated accordingly to the frametime parameter of Drawframe; acquiring x1, y1 values at startTime and x2, y2 at endTime
  25. '
  26. ' Q [id] [ : startTime [ ; endTime ] ] ]  [ * [repeatCount] ] [ ( commandSequenceString ) ]
  27. '    Defines the "id" named sequence of statements commandSequenceString and repeats it repeatCount times.
  28. '    If startTime and/or endTime are defined, this sequence does not apply outside of this time interval.
  29. '
  30. ' V angle
  31. '    Turns the draw direction relatively to actual direction by <angle> degrees
  32. '
  33. ' S size %
  34. '    Extends the S statement usage by % option.
  35. '    Sets the drawing size relatively to the last absolute size set - to the <size>% of it
  36. '
  37. ' DrawPlayer controls:
  38. '    Left / Right arrow: skip back / forward in time
  39. '    Up / Down arrow: increase / decrease playback speed
  40. '    Space: pause / play
  41. '    R: toggle reverse playback on/off
  42. '    + / -: increase / decrease size picture size
  43. '
  44. '----------------------------------------------------------------------------------------------------------------------------------------------------
  45.  
  46.  
  47. '----------------------------------------------------------------------------------------------------------------------------------------------------
  48. ' The Tree string
  49. '----------------------------------------------------------------------------------------------------------------------------------------------------
  50. leaf1$ = "Q1:17;* (V30 K11:17;17.5 S1%;!40% K11:17.5;19 S!40%;50% V-90 K12 V-10;10 U50 V-800U20 V30U20 V30U20 V20U40 V20U40 V20U50 V100U50 V20U40 V20U40 V20U20 V30U20 V30U20 V-800 K12 U50;47 V180 K12 V10;-10 V90 V-30 S100%)"
  51. smallimb2$ = "Q2:7;* (V-90 K22:7;14 S1%;100% U100 K23:40;44 BM+0,+0;-4000,-100 K12:22;22.2# Q1 K23 BM+0,+0;+4000,+100 K22 S1%;100% U200 K23:47;49 BM+0,+0;-4000,-100 K12:22.1;22.3# Q1 K23 BM+0,+0;+4000,+100 K22 S1%;100% U100 V90 U10 V90 V-90 K23:49;51 BM+0,+0;-4000,-100 K12:22.2;22.4# Q1 K23 BM+0,+0;+4000,+100 K22 S1%;100% V90 U200 V-60 K23:49.5;51.5 BM+0,+0;-4000,-100 K12:22.3;22.5# Q1 K23 BM+0,+0;+4000,+100 K22 S1%;100% V60 U200 V-90 S100%)"
  52. biglimb3$ = "Q3:4;* (V-88 K31:4.0;11 S1%;100% U250 K32:25;25.4# V30;50 Q2 K32 V-30;-50 K31 S1%;100% U200 V88 K33:25.1;25.5# V-35;-15 Q2 K33 V35;15 V88 K34:25.2;25.6# V-40;-20 Q2 K34 V40;20 K31 S1%;100% U450 V92 V-180 S100%)"
  53. trunk4$ = "Q4 (K41:0;10 S1%;100% U500 K42:28.9;29.3# V30;40 Q3 K42 V-30;-40 K41 S1%;100% U400 V88 K43:29;29.4# V0;5 Q3 K43 V0;-5 V88 K41 S1%;100% U200 K44:29.1;29.5# V-30;-20 Q3 K44 V30;20 K41 S1%;100% M+0,+0;-10,-10 K45:17;17.6 M+0,+0;-25,-20 U700 V92 V92 S100%)"
  54. cloud5$ = "Q51:17; (Q5*8(U30-V30) S150% V200 Q5*6 S130% V230 Q5*6 S120% V210 Q5*8 S160% V220 Q5*6 S160% V235 Q5*6) S2"
  55. clip$ = "S2 BM1200,1000" + leaf1$ + smallimb2$ + biglimb3$ + "K1:0;10#C35;52 L400 K101:24.9;25.3# M-3,-0;+3,+0 " + trunk4$ + " K101 M+3,+0;-3,-0 M910,1000 L400 K102:17;23 BM2500,50;1400,100 TA90 K51:0;0.3# S2;2.05 " + cloud5$ + " TA0 K103:20;30 BM0,0 BM-800,+100;+500,+300 TA90 K51:0;0.3# S3;3.05 Q51"
  56.  
  57. '----------------------------------------------------------------------------------------------------------------------------------------------------
  58. ' Examples of clip strings
  59. '----------------------------------------------------------------------------------------------------------------------------------------------------
  60. 'clip$ = "BM500,300 Q1*12( U20 V30 )" '1 circle
  61. 'clip$ = "B M500,300 Q2*6( BU100 Q1*12( U20 V30 ) BD100 V60 )" '6 circles queued in round
  62. 'clip$ = "B M500,300 K1:0;3# V0;360 Q2*6( BU50 Q1*12( U10 V30 ) BD50 V60 )" '6 circles queued in round rotating
  63. 'clip$ = "B M500,300 K1:0;3* V0;360 Q2*6( K2:0;2# BU50;200 Q1*12( U10 V30 ) BD50;200 V60 )" '6 circles queued in round rotating and swingigng towards centre
  64. 'clip$ = "B M500,300 K2:0;2# K1:0;3* V0;360 Q2*6( K2_2:+0.2;+0.2# BU50;200 Q1*12( U10 V30 ) BD50;200 V60 )" '6 circles queued in round rotating and swingigng towards centre in different phase
  65. 'clip$ = "B M500,300 K2:0;1# K1:0;3* V0;360 Q2*6( K2_2:+0.2;+0.2# BU50;200 S100%;300% Q1*12( U10 V30 ) S100% BD50;200 V60 )" '6 circles queued in round rotating and swingigng towards centre in different phase changing size
  66.  
  67. '----------------------------------------------------------------------------------------------------------------------------------------------------
  68. ' The Dog string
  69. '----------------------------------------------------------------------------------------------------------------------------------------------------
  70. ' Q0 - dog positioning
  71. ' Q2 - dog walking
  72. ' Q3 - dog head shape, Q31 - head running
  73. ' Q4 - dog ear shape, Q41 - ear running
  74. ' Q5 - dog tail shape, Q51 - tail running
  75. ' Q7 - dog foot shape, Q71 - foot running
  76.  
  77. 'clip$ = "S2 BM1900,518 L3500 Q0*(K0:0;10 BM1800,400;300,400 TA0)  Q7*(L40 D20 R40 U20)  Q71*(BM+20,+180 K71_71:-0.5;-0.5* K72_71:+0;-0.5# K71 V0;360 BD40 V360;0 K72 V-10;30 Q7) K41:0;0.25#"+_
  78. '        "Q4*(L40M+20,-40M+20,40) Q41*(K41_41:+0.05;+0.05# V-35;15 Q4 V35;-15) " + _
  79. '        "Q5*(R50 U40 L50 D40) Q51*(K51:0;0.25#  V10;30 BM+100,-40 Q5)" + _
  80. '        "Q3*(BM-20,-110 L200D120R200U120 BM-70,+30 R20D20L20U20 BM-120,-20 R30D30L30U30)  Q31*(K32:4;4.5 V0;50 K33_32:+3;+2.8 V!0;-50 K32 BM+0,0;-50,20 K33 BM+0,0;+50,-20 K31:0;0.25# BD-20;10 Q3 BM+140,-30 Q41 BR60 Q41) "+ _
  81. '        "Q2(Q0 K21:-0.125;0.125# BU0;40 D150R250U150L250 BM+200,+70 Q51 K71:0;1* Q0 Q71 Q0 Q71 Q0BM+250,0 Q71 Q0BM+250,+0 Q71 Q0 Q31)
  82.  
  83. '----------------------------------------------------------------------------------------------------------------------------------------------------
  84. SCREEN _NEWIMAGE(1920, 1080, 256)
  85.  
  86. DrawPlayer clip$, 0, 60, 30, _WIDTH / 1920, 1
  87.  
  88. '----------------------------------------------------------------------------------------------------------------------------------------------------
  89. 'Player demonstration
  90. '----------------------------------------------------------------------------------------------------------------------------------------------------
  91. SUB DrawPlayer (movie$, playfromtime, playtotime, fps, size, speed)
  92.     t = playfromtime * fps
  93.     dir = 1
  94.     DO
  95.         CLS
  96.         _PRINTSTRING (0, 5), "size:" + STR$(RoundDec(size, 2)) + "   speed:" + STR$(dir * speed) + "x  time:" + STR$(RoundDec(t / fps * speed, 2))
  97.         DrawFrame movie$, t / fps * speed, size
  98.         IF k = 32 THEN SLEEP: k = _KEYHIT: k = _KEYHIT
  99.         IF k = 20480 AND speed > 0.1 THEN speed = speed / 2: t = t * 2
  100.         IF k = 18432 AND speed < 100 THEN speed = speed * 2: t = t / 2
  101.         IF k = 19200 THEN t = t - 2 * fps
  102.         IF k = 19712 THEN t = t + 2 * fps
  103.         IF k = 43 THEN size = size + 0.01
  104.         IF k = 45 THEN size = size - 0.01
  105.         IF k = 114 THEN dir = -dir
  106.         t = t + dir
  107.         IF size > 10 THEN size = 10
  108.         IF size < 0.01 THEN size = 0.01
  109.         IF t > playtotime * fps / speed THEN t = playtotime * fps / speed
  110.         IF t < 0 THEN t = 0
  111.         k = _KEYHIT
  112.         _DISPLAY
  113.         _LIMIT fps
  114.     LOOP UNTIL _KEYDOWN(27)
  115.  
  116. '----------------------------------------------------------------------------------------------------------------------------------------------------
  117. 'Sub & Function definitions
  118. '----------------------------------------------------------------------------------------------------------------------------------------------------
  119. SUB DrawFrame (SrcStrOrig AS STRING, frametime AS SINGLE, size AS SINGLE)
  120.  
  121.     CONST CMD_LEN_MAX = 1000 'max. command sequence length definable using statement Q()
  122.  
  123.     TYPE TKFset 'Key frame set type
  124.         id AS INTEGER
  125.         defined AS _BYTE
  126.         timestart AS SINGLE
  127.         timeend AS SINGLE
  128.         repeat AS STRING * 1
  129.         repeatcount AS INTEGER
  130.     END TYPE
  131.  
  132.     TYPE TCmdSeq 'Command Sequence
  133.         id AS INTEGER
  134.         CmdStr AS STRING * CMD_LEN_MAX
  135.         defined AS _BYTE
  136.         startpos AS LONG
  137.         endpos AS LONG
  138.         timestart AS SINGLE
  139.         timeend AS SINGLE
  140.         repeatcount AS INTEGER
  141.     END TYPE
  142.  
  143.     TYPE TDrawState 'global Draw state
  144.         SrcLen AS LONG 'Source string length
  145.         SrcPos AS LONG 'Source string last read char position
  146.         ActKFSetIdx AS INTEGER 'KFset index applied to actual statement if KF enabled
  147.         ActTA AS SINGLE 'Actual parameter value of previous TA statement (in degrees)
  148.         ActS AS SINGLE 'Actual parameter value of previous "S" statement usage
  149.         ErrDsc AS STRING * 50 'Error description
  150.     END TYPE
  151.  
  152.     DIM KFset(0 TO 999) AS TKFset
  153.     DIM CmdSeq(0 TO 99) AS TCmdSeq
  154.     DIM DS AS TDrawState
  155.     DIM char AS STRING * 1
  156.     DIM prevchar AS STRING * 1
  157.     DIM TrgStr AS STRING
  158.     DIM c$, code$, label$, x1$, y1$, x2$, y2$, sgnx1$, sgny1$, rep$, repcnt$, par$, exclfrom$, exclto$, csstart$, percx1$, percx2$
  159.     DIM x AS SINGLE, y AS SINGLE, x1 AS SINGLE, y1 AS SINGLE, x2 AS SINGLE, y2 AS SINGLE, kid AS INTEGER, csid AS INTEGER
  160.     DIM readstate AS _BYTE
  161.     DIM stat$, ParseStatement$ ' Actual statement being read from source draw string
  162.     DIM SrcStr AS STRING
  163.  
  164.     SrcStr = SrcStrOrig
  165.     TrgStr = ""
  166.     stat$ = ""
  167.     prevchar = ""
  168.     SrcStr = SrcStr + "&"
  169.     DS.SrcLen = LEN(SrcStr)
  170.     DS.SrcPos = 0
  171.     DS.ActKFSetIdx = 0
  172.     DS.ActTA = 0
  173.     DS.ActS = 4
  174.  
  175.     DO 'read statement
  176.         DS.SrcPos = DS.SrcPos + 1
  177.         char = MID$(SrcStr, DS.SrcPos, 1)
  178.         IF (ASC(char) >= 64 AND ASC(char) <= 90 AND NOT (char = "A" AND prevchar = "T")) OR char = "&" THEN
  179.             '-------------------------------------------Parser begin-----------------------------------------------------------
  180.             stat$ = stat$ + "&"
  181.             ParseStatement$ = ""
  182.             readstate = 0
  183.             KFenabled = 0
  184.             omitstate = 0
  185.             par$ = "": code$ = "": label$ = "": x1$ = "": y1$ = "": x2$ = "": y2$ = "": sgnx1$ = "": sgny1$ = "": sgnx2$ = ""
  186.             rep$ = "": repcnt$ = "": par$ = "": exclfrom$ = "": exclto$ = "": csstart$ = "": percx1$ = "": percx2$ = "": rel$ = "": krel$ = ""
  187.             x = 0: y = 0: x1 = 0: y1 = 0: x2 = 0: y2 = 0: kid = 0: csid = 0
  188.  
  189.             FOR i = 1 TO LEN(stat$)
  190.                 c$ = MID$(stat$, i, 1)
  191.                 SELECT CASE readstate
  192.                     CASE 0:
  193.                         SELECT CASE c$
  194.                             CASE "A" TO "Z":
  195.                                 code$ = code$ + c$
  196.                             CASE "_":
  197.                                 label$ = par$: par$ = "": rel$ = c$: readstate = 11
  198.                             CASE ":":
  199.                                 label$ = par$: par$ = "": readstate = 1
  200.                             CASE ",":
  201.                                 x1$ = par$: par$ = "": readstate = 2
  202.                             CASE ";":
  203.                                 x1$ = par$: par$ = "": readstate = 3
  204.                                 KFenabled = 1
  205.                             CASE "!":
  206.                                 exclfrom$ = c$
  207.                             CASE "+", "-":
  208.                                 par$ = par$ + c$
  209.                                 sgnx1$ = c$
  210.                             CASE "0" TO "9", ".":
  211.                                 par$ = par$ + c$
  212.                             CASE "%":
  213.                                 percx1$ = percx1$ + c$
  214.                             CASE "*":
  215.                                 label$ = par$: par$ = "": rep$ = c$: readstate = 5
  216.                             CASE "(":
  217.                                 label$ = par$: csstart$ = c$: readstate = 10
  218.                             CASE "&", ")":
  219.                                 x1$ = par$: par$ = "": readstate = 10
  220.                             CASE ELSE: readstate = 99
  221.                         END SELECT
  222.                     CASE 11:
  223.                         SELECT CASE c$
  224.                             CASE "0" TO "9":
  225.                                 par$ = par$ + c$
  226.                             CASE ":":
  227.                                 krel$ = par$: par$ = "": readstate = 1
  228.                             CASE ELSE: readstate = 99
  229.                         END SELECT
  230.                     CASE 1:
  231.                         SELECT CASE c$
  232.                             CASE ",":
  233.                                 x1$ = par$: par$ = "": readstate = 2
  234.                             CASE ";":
  235.                                 x1$ = par$: par$ = "": readstate = 3
  236.                                 KFenabled = 1
  237.                             CASE "!":
  238.                                 exclfrom$ = c$
  239.                             CASE "+", "-":
  240.                                 par$ = par$ + c$
  241.                                 sgnx1$ = c$
  242.                             CASE "0" TO "9", ".":
  243.                                 par$ = par$ + c$
  244.                             CASE "%":
  245.                                 percx1$ = percx1$ + c$
  246.                             CASE "(":
  247.                                 x1$ = par$: csstart$ = c$: readstate = 10
  248.                             CASE "&", ")":
  249.                                 x1$ = par$: par$ = "": readstate = 10
  250.                             CASE ELSE: readstate = 99
  251.                         END SELECT
  252.                     CASE 2:
  253.                         SELECT CASE c$
  254.                             CASE ";":
  255.                                 y1$ = par$: par$ = "": readstate = 3
  256.                                 KFenabled = 1
  257.                             CASE "+", "-":
  258.                                 par$ = par$ + c$
  259.                                 sgny1$ = c$
  260.                             CASE "0" TO "9", ".":
  261.                                 par$ = par$ + c$
  262.                             CASE "&", ")":
  263.                                 y1$ = par$: par$ = "": readstate = 10
  264.                             CASE ELSE: readstate = 99
  265.                         END SELECT
  266.                     CASE 3:
  267.                         SELECT CASE c$
  268.                             CASE ",":
  269.                                 x2$ = par$: par$ = "": readstate = 4
  270.                             CASE "#":
  271.                                 x2$ = par$: par$ = "": rep$ = c$: readstate = 5
  272.                             CASE "*":
  273.                                 x2$ = par$: par$ = "": rep$ = c$: readstate = 5
  274.                             CASE "!":
  275.                                 exclto$ = c$
  276.                             CASE "+", "-":
  277.                                 par$ = par$ + c$
  278.                                 sgnx2$ = c$
  279.                             CASE "0" TO "9", ".":
  280.                                 par$ = par$ + c$
  281.                             CASE "%":
  282.                                 percx2$ = percx2$ + c$
  283.                             CASE "(":
  284.                                 x2$ = par$: csstart$ = c$: readstate = 10
  285.                             CASE "&", ")":
  286.                                 x2$ = par$: par$ = "": readstate = 10
  287.                             CASE ELSE: readstate = 99
  288.                         END SELECT
  289.                     CASE 4:
  290.                         SELECT CASE c$
  291.                             CASE "#":
  292.                                 y2$ = par$: par$ = "": rep$ = c$: readstate = 5
  293.                             CASE "*":
  294.                                 y2$ = par$: par$ = "": rep$ = c$: readstate = 5
  295.                             CASE "0" TO "9", "+", "-", ".":
  296.                                 par$ = par$ + c$
  297.                             CASE "&", ")":
  298.                                 y2$ = par$: par$ = "": readstate = 10
  299.                             CASE ELSE: readstate = 99
  300.                         END SELECT
  301.                     CASE 5:
  302.                         SELECT CASE c$
  303.                             CASE "0" TO "9", "+", "-", ".":
  304.                                 par$ = par$ + c$
  305.                             CASE "(":
  306.                                 repcnt$ = par$: par$ = "": csstart$ = c$: readstate = 10
  307.                             CASE "&", ")":
  308.                                 repcnt$ = par$: par$ = "": readstate = 10
  309.                             CASE ELSE: readstate = 99
  310.                         END SELECT
  311.                 END SELECT
  312.             NEXT i
  313.  
  314.             IF readstate = 99 THEN DS.ErrDsc = "Error in statement: " + LEFT$(stat$, LEN(stat$) - 1) ELSE DS.ErrDsc = ""
  315.             IF code$ = "K" THEN
  316.                 IF x2$ <> "" THEN ' defining KFset
  317.                     tsdelta = 0: tedelta = 0
  318.                     kid = VAL(label$)
  319.                     KFset(kid).id = kid
  320.                     KFset(kid).defined = 1
  321.                     IF krel$ <> "" THEN
  322.                         krel = VAL(krel$)
  323.                         IF sgnx1$ <> "" THEN tsdelta = KFset(krel).timestart
  324.                         IF sgnx2$ <> "" THEN tedelta = KFset(krel).timeend
  325.                     END IF
  326.                     KFset(kid).timestart = VAL(x1$) + tsdelta
  327.                     KFset(kid).timeend = VAL(x2$) + tedelta
  328.                     KFset(kid).repeat = rep$
  329.                     KFset(kid).repeatcount = VAL(repcnt$)
  330.                     DS.ActKFSetIdx = kid
  331.                 ELSE ' referencing KFset
  332.                     IF label$ = "" AND x1$ <> "" THEN label$ = x1$
  333.                     kid = VAL(label$)
  334.                     DS.ActKFSetIdx = kid
  335.                 END IF
  336.  
  337.             ELSEIF code$ = "Q" THEN
  338.                 IF x1$ <> "" OR x2$ <> "" AND label$ <> "" THEN
  339.                     csid = VAL(label$)
  340.                     CmdSeq(csid).timestart = VAL(x1$)
  341.                     CmdSeq(csid).timeend = VAL(x2$)
  342.                 END IF
  343.                 IF label$ = "" AND x1$ <> "" AND x2$ = "" THEN label$ = x1$
  344.                 csid = VAL(label$)
  345.                 CmdSeq(csid).id = csid
  346.                 IF repcnt$ <> "" THEN CmdSeq(csid).repeatcount = VAL(repcnt$)
  347.  
  348.                 ipos = 0
  349.                 IF csstart$ = "(" THEN ' defining command sequence
  350.                     parcnt = 1: c$ = ""
  351.                     DO ' Find corresponding right parenthes in the source string
  352.                         ipos = ipos + 1
  353.                         c$ = MID$(SrcStr$, DS.SrcPos + ipos, 1)
  354.                         IF c$ = "(" THEN parcnt = parcnt + 1
  355.                         IF c$ = ")" THEN parcnt = parcnt - 1
  356.                     LOOP UNTIL (c$ = ")" AND parcnt = 0) OR DS.SrcPos + ipos >= DS.SrcLen OR ipos >= CMD_LEN_MAX
  357.                     IF (c$ = ")" AND parcnt = 0) THEN
  358.                         CmdSeq(csid).CmdStr = MID$(SrcStr, DS.SrcPos, ipos)
  359.                         CmdSeq(csid).defined = 1
  360.                     ELSE
  361.                         CmdSeq(csid).defined = 0
  362.                     END IF
  363.                 ELSE 'Referencing command sequence
  364.                 END IF
  365.  
  366.                 IF CmdSeq(csid).defined = 1 THEN 'modify source string if command sequence defined
  367.                     IF CmdSeq(csid).repeatcount > 0 THEN
  368.                         rpt = CmdSeq(csid).repeatcount
  369.                     ELSEIF rep$ = "*" THEN
  370.                         rpt = 0
  371.                     ELSE
  372.                         rpt = 1
  373.                     END IF
  374.                     IF CmdSeq(csid).timeend <> 0 AND (frametime < CmdSeq(csid).timestart OR frametime > CmdSeq(csid).timeend) THEN rpt = 0
  375.                     IF frametime < CmdSeq(csid).timestart THEN rpt = 0
  376.                     cmdrpt$ = ""
  377.                     FOR i = 1 TO rpt: cmdrpt$ = cmdrpt$ + RTRIM$(CmdSeq(csid).CmdStr): NEXT i
  378.                     SrcStr = RTRIM$(cmdrpt$) + RIGHT$(SrcStr, DS.SrcLen - DS.SrcPos - ipos + 1)
  379.                     DS.SrcLen = LEN(SrcStr)
  380.                     DS.SrcPos = 0
  381.                     char = ""
  382.                 END IF
  383.  
  384.             ELSE 'do for other graphics statements
  385.                 x1 = VAL(x1$): y1 = VAL(y1$): x2 = VAL(x2$): y2 = VAL(y2$)
  386.                 kid = DS.ActKFSetIdx
  387.                 IF KFenabled = 1 AND KFset(kid).defined = 1 THEN 'change parameters if statement is keyframed
  388.                     fk = (frametime - KFset(kid).timestart) / (KFset(kid).timeend - KFset(kid).timestart)
  389.                     IF (frametime >= KFset(kid).timestart AND frametime <= KFset(kid).timeend) THEN
  390.                         IF x1$ <> "" THEN x1 = x1 + (x2 - x1) * fk
  391.                         IF y1$ <> "" THEN y1 = y1 + (y2 - y1) * fk
  392.                     ELSEIF (frametime > KFset(kid).timeend AND exclto$ <> "!") THEN
  393.                         period = INT((frametime - KFset(kid).timestart) / (KFset(kid).timeend - KFset(kid).timestart))
  394.                         IF (KFset(kid).repeat = "*" OR KFset(kid).repeat = "#") AND (period < KFset(kid).repeatcount OR KFset(kid).repeatcount = 0) THEN
  395.                             IF KFset(kid).repeat = "#" AND period MOD 2 = 1 THEN
  396.                                 fk = (KFset(kid).timeend - frametime + period * (KFset(kid).timeend - KFset(kid).timestart)) / (KFset(kid).timeend - KFset(kid).timestart)
  397.                             ELSE
  398.                                 fk = (frametime - KFset(kid).timestart - period * (KFset(kid).timeend - KFset(kid).timestart)) / (KFset(kid).timeend - KFset(kid).timestart)
  399.                             END IF
  400.                             IF x1$ <> "" THEN x1 = x1 + (x2 - x1) * fk
  401.                             IF y1$ <> "" THEN y1 = y1 + (y2 - y1) * fk
  402.                         ELSE
  403.                             IF KFset(kid).repeat = "#" AND KFset(kid).repeatcount MOD 2 = 0 THEN
  404.                                 IF x1$ <> "" THEN x1 = x1
  405.                                 IF y1$ <> "" THEN y1 = y1
  406.                             ELSE
  407.                                 IF x1$ <> "" THEN x1 = x2
  408.                                 IF y1$ <> "" THEN y1 = y2
  409.                             END IF
  410.                         END IF
  411.                     ELSEIF (frametime < KFset(kid).timestart AND exclfrom$ <> "!") THEN
  412.                         omitstate = 0
  413.                     ELSE
  414.                         omitstate = 1
  415.                     END IF
  416.                 END IF
  417.                 IF omitstate = 0 THEN
  418.                     SELECT CASE code$
  419.                         CASE "T", "TA":
  420.                             x1 = RoundDec(x1, 6)
  421.                             DS.ActTA = x1
  422.                             IF (DS.ActTA > 360) OR (DS.ActTA < -360) THEN DS.ActTA = DS.ActTA + (DS.ActTA > 0) * 360
  423.                         CASE "V":
  424.                             DS.ActTA = DS.ActTA + RoundDec(x1, 6)
  425.                             IF (DS.ActTA > 360) OR (DS.ActTA < -360) THEN DS.ActTA = DS.ActTA + (DS.ActTA > 0) * 360
  426.                             code$ = "TA"
  427.                             x1 = RoundDec(DS.ActTA, 6)
  428.                         CASE "C":
  429.                             x1 = _ROUND(x1)
  430.                         CASE "M", "D", "E", "F", "G", "H", "L", "R", "U":
  431.                             x1 = RoundDec(x1 * size, 4)
  432.                             y1 = RoundDec(y1 * size, 4)
  433.                         CASE "S":
  434.                             IF percx1$ <> "" OR percx2$ <> "" THEN
  435.                                 x1 = RoundDec(x1 * DS.ActS / 100, 5)
  436.                                 IF x1 > 8 THEN x1 = 8
  437.                             ELSE
  438.                                 DS.ActS = x1
  439.                             END IF
  440.                     END SELECT
  441.                     IF sgnx1$ <> "" AND x1 < 0 THEN sgnx1$ = ""
  442.                     IF sgnx1$ <> "" AND x1 > 0 THEN sgnx1$ = "+"
  443.                     IF sgny1$ <> "" AND y1 < 0 THEN sgny1$ = ""
  444.                     IF sgny1$ <> "" AND y1 > 0 THEN sgny1$ = "+"
  445.                     ParseStatement$ = code$
  446.                     IF x1$ <> "" THEN
  447.                         ParseStatement$ = ParseStatement$ + sgnx1$ + LTRIM$(STR$(x1))
  448.                         IF y1$ <> "" THEN ParseStatement$ = ParseStatement$ + "," + sgny1$ + LTRIM$(STR$(y1))
  449.                     END IF
  450.                 ELSE
  451.                     ParseStatement$ = ""
  452.                 END IF
  453.             END IF
  454.  
  455.             ''---DEBUG BEGIN-----------
  456.             'IF CmdSeq(csid).defined = 1 THEN cmd$ = RTRIM$(CmdSeq(csid).CmdStr) ELSE cmd$ = ""
  457.             'PRINT
  458.             'PRINT stat$ + " > ", , code$ + "/" + label$ + "/" + x1$ + "/" + y1$ + "/" + x2$ + "/" + y2$ + "/" + exclfrom$ + "/" + exclto$ + "/" + rep$ + "/" + repcnt$
  459.             'PRINT "TrgStr: "; TrgStr
  460.             'PRINT "SrcStr: "; SrcStr
  461.             'PRINT "cmd$: ", cmd$
  462.             'PRINT "DS.Srcpos", DS.SrcPos
  463.             'PRINT "ParseStatement$: ", ParseStatement$
  464.             'IF stat$ = "Q1*(&" OR stat$ = "Q1(&" THEN stopable = 1
  465.             'IF stopable THEN
  466.             '    DO
  467.             '    LOOP UNTIL _KEYHIT = 32
  468.             'END IF
  469.             ''---DEBUG END-------------
  470.  
  471.             '-------------------------------------------Parser end-----------------------------------------------------------
  472.             TrgStr = TrgStr + ParseStatement$
  473.             IF LTRIM$(DS.ErrDsc) <> "" THEN PRINT RTRIM$(DS.ErrDsc) + " at position:" + STR$(DS.SrcPos - LEN(stat$))
  474.             stat$ = ""
  475.         END IF
  476.         IF char <> " " THEN
  477.             stat$ = stat$ + char
  478.         END IF
  479.         prevchar = char
  480.     LOOP WHILE DS.SrcPos < DS.SrcLen
  481.  
  482.     DRAW TrgStr
  483.  
  484.     'PRINT SrcStr '---DEBUG code----
  485.     'PRINT TrgStr '---DEBUG code----
  486.  
  487. '----------------------------------------------------------------------------------------------------------------------------------------------------
  488. FUNCTION RoundDec (x AS SINGLE, n AS INTEGER)
  489.     RoundDec = _ROUND(x * 10 ^ n) / (10 ^ n)
  490.  
  491. '----------------------------------------------------------------------------------------------------------------------------------------------------
  492.  

For those interested in handling new commands, here's a quick tutorial, based on uncommenting corresponding line code "clip$=" in the part "Examples of clip strings".
Let's start simple and develop the string gradualy to something more complex.


1 circle
Quote
clip$ = "BM500,300 Q1*12( U20 V30 )"
Q statement defines sequence "U20 V30" as sequence "1" and repeats it 12 times -  line up (U20) , turn 30 degrees relative (V30), effectively drawing a circle (12*30=360).


6 circles queued in round
Quote
clip$ = "B M500,300 Q2*6( BU100 Q1*12( U20 V30 ) BD100 V60 )"
Q1 is nested into Q2 command sequence, together with additional movement before drawing the circle Q1 and movement + turning after drawing the circle.


6 circles queued in round rotating
Quote
clip$ = "B M500,300 K1:0;3# V0;360 Q2*6( BU50 Q1*12( U10 V30 ) BD50 V60 )"
K statement defines keyframes interval "1", begining at time 0s, ending at 3s. The # means the animation, the interval "1" is set before, will be repeated back and forth indefinetly.
Next command V is animated with KF interval "1" set, thus turning the direction from 0 degrees at 0 s to 360 degrees at 2 s and then backwards.


6 circles queued in round rotating and swingigng towards centre
Quote
clip$ = "B M500,300 K1:0;3* V0;360 Q2*6( K2:0;2# BU50;200 Q1*12( U10 V30 ) BD50;200 V60 )"
Another KF interval "2" is added and set before modified D50, that is thus animated acquiring values  from 50 to 200 in time 0s to 2s.


6 circles queued in round rotating and swingigng towards centre in different phase
Quote
clip$ = "B M500,300 K2:0;2# K1:0;3* V0;360 Q2*6( K2_2:+0.2;+0.2# BU50;200 Q1*12( U10 V30 ) BD50;200 V60 )"
This one is bit tricky. KF interval "2" (K2) is now initialy defined outside the Q2 sequence, so that it could be later redefined within the Q2, using relative start and end time (+0.2s) to current itself's definition (K2_2).


6 circles queued in round rotating and swingigng towards centre in different phase while changing size
Quote
clip$ = "B M500,300 K2:0;1# K1:0;3* V0;360 Q2*6( K2_2:+0.2;+0.2# BU50;200 S100%;300% Q1*12( U10 V30 ) S100% BD50;200 V60 )"
This one demonstrates relative size change. Before drawing the circle (Q1) there is animated S statement, with animation drived by the last previous KF set (K2).
Immediately after the Q1 circle is drawed, size has to be reset to 100% of absolute size. The advantage of setting the size relatively inside definition is that you can scale the whole sequence (say object) by setting absolute size before it.

Edit1: I'll be updating this post to the the most recent code version; now for v.1.0.1 - mostly bugs fixes, TA works with decimals now
« Last Edit: January 21, 2020, 04:29:17 am by dajan »

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #1 on: January 18, 2020, 02:23:45 pm »
That's truely impressive work and a cool demo. It's always interesting to see what's possible with simple statements, if somebody really takes the time to investigate how it can be used effectively and builts a useful framework around it.
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #2 on: January 18, 2020, 03:42:01 pm »
Very nicely done indeed!! To quote Darth Vader (Star Wars IV: A new Hope: 1977), "Impressive. Most impressive."

J
Logic is the beginning of wisdom.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #3 on: January 18, 2020, 04:03:13 pm »
Love the animation!

I too extended DRAW with circles, boxes, arcs filled or not and with repeat code and with variable and variable changer... but it was all static, so cool to see it made dynamic.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #4 on: January 18, 2020, 04:13:06 pm »
Very nice work!

Offline dajan

  • Newbie
  • Posts: 41
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #5 on: January 19, 2020, 05:42:04 am »
Guys, thanks a lot for your appreciation.

@bplus: do you have a link or code somewhere by chance? Now, I'm rather interested in your approach, since I also got involved into DRAW enhancing. I have been thinking about some kind of variables too, but it seemed too hardcore and I decided to keep it rather simple.

Offline Dimster

  • Forum Resident
  • Posts: 500
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #6 on: January 19, 2020, 09:40:59 am »
I have never used "Draw" statement, this was pretty cool Dan. Thanks for same. I would imagine it would be pretty difficult to add a "dimension" factor to Draw statement or perhaps would that simply be a matter of a slight offset to multiple Frames or multiple parallel lines?

FellippeHeitor

  • Guest
Re: DrawFrame - animation sub using DRAW
« Reply #7 on: January 19, 2020, 09:47:52 am »
Wow! This is really impressive, man!

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #8 on: January 19, 2020, 10:59:33 am »
Hi dajan
I like it very much!
and for three reasons:
1 movement into a single string of command
2 multiple shapes into a single string of command
3 player interacting with user


Some time ago I made some experiment to use DRAW in 32 bit mode and moreover  to build a library of simple shapes on a 2D plane. For polygons I used a method posted on [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] in a thread of Steve SmcNeill and peharps also for the whole circle.
For scaling the size of the images I use the inner command of DRAW.
The next step, for now left on the world of ideas, was to build an editor to draw on a graphic panel and to convert the final image painted in a sequence of DRAW statements or/and in DATA. (for saving as images to load them after using _LOADIMAGE there are too professional programs like Windows MsPaint, Gimp, IconEditor etc etc)

Programming isn't difficult, only it's  consuming time and coffee

Offline dajan

  • Newbie
  • Posts: 41
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #9 on: January 19, 2020, 12:03:21 pm »
@FellippeHeitor: thanks man, glad to hear that.

@Dimster: That is actualy pretty interesting idea, to add the third dimension to DRAW graphical statement M and also add 2 new directional statements to U, D, L, R for forward and backward direction.  Then the DRAW sub would get the camera position as parameter in addition. Two problems with that anyway: it would be hell of a drawing to create something reasonable = long and comlicated string. Also, the demo clip included in the code above alone completely devastates one CPU core (mainly due to extensive use of strings operations), I could not imagine how would the 3D DRAW manage.

@TempodiBasic: actually, it was my intention, to squeeze the whole movie into one, shortest string possible. This 60 sec. demo clip has 1251 characters (without spaces), it is possible to 7zip it to 661 bytes. And yes, it also came to my mind to build a graphuic GUI, where you could build the string with mouse and keyboard. Long strings are fairly CPU intensive, however, so it is more suitable to use it as single object animation tool in some kind of minigames. I will put an example here some time soon, cause I 'm having an idea yet.

FellippeHeitor

  • Guest
Re: DrawFrame - animation sub using DRAW
« Reply #10 on: January 19, 2020, 01:40:52 pm »
Your idea was both innovative and so well executed. I love that you can control the animation, moving the playing head back and forth.

Also, your code is very neatly organised and so easy to follow.

If you do actually come up with a way to build the strings with mouse and keyboard, that'll be amazing.

Kudos, man. Way to go.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #11 on: January 19, 2020, 03:07:46 pm »
Quote
@bplus: do you have a link or code somewhere by chance? Now, I'm rather interested in your approach, since I also got involved into DRAW enhancing. I have been thinking about some kind of variables too, but it seemed too hardcore and I decided to keep it rather simple.

OK just translated and did a little update to 1st pentagon screen demo the rest is mostly as it was in 2017:
Code: QB64: [Select]
  1. _TITLE "Draw Strings trans" 'b+ 2020-01-19 translate from
  2. ' Draw strings 2.bas SmallBASIC 0.12.9 (B+=MGA) 2017-05-06
  3. 'Deluxe draw strings.sdlbas [B+=MGA] 2017-01-03
  4. 'translated from:
  5. 'v2 turtle strings.bas  SmallBASIC 0.12.2 [B+=MGA] 2016-04-04
  6. '2017-05-08 fixes Box d and e for width and height
  7. ' test draw strings fixed for arc
  8.  
  9. '=================================================================
  10. '                   Commands Set
  11. '==================================================================
  12. 'Note all commands are a letter for function followed by number n
  13.  
  14. 'commands pn -1 to 15, 0-15 are QB colors,  -1 is pen up
  15.  
  16. 'command xn set absolute screen coordinate for turtle x
  17.  
  18. 'command yn set absolute screen coordinate for turtle y
  19.  
  20. 'command gn move turtle relative to its current x position
  21. '        + n = right, -n = left (pneumonic g for go!)
  22.  
  23. 'command hn move turtle relative to its current y position
  24. '        + n down?, -n up?  depends which way the angle is set
  25. '        (pnuemonic h follows g like y follows x)
  26.  
  27. 'command fn draws at current ta angle a distance of n (set ta turtle angle first by tn or an)
  28. '        (pnuemonic f is for forward use -n for back)
  29.  
  30. 'command an sets angle or heading of turtle
  31. '        (pnuemonic a is for angle (degrees)
  32. '        0 degrees is true North or 12 o'clock)
  33.  
  34. 'command tn (turns) t=right n degrees when positive
  35. '        and turn left n degrees when negative
  36.  
  37. 'v2 2016-04-05 the great and powerful repeat uses recursive sub
  38.  
  39. 'command rn repeat drawstrings n amount of times
  40.  
  41. 'command tv for setting a turtle var probably need another
  42.  
  43. 'add 2 more commands for setting and incrementing the tv variable
  44.  
  45. 'command sn will set tv at n value
  46.  
  47. 'command in will increment tv with n value
  48.  
  49. 'Deluxe draw strings 2017-01-03
  50. ' draw filled box  current tx, ty is one corner
  51.  
  52. 'command zn for pen siZe radius to draw thick lines
  53.  
  54. 'command dn sets box width
  55.  
  56. 'command en sets box height
  57.  
  58. 'command bn for Box color n = 0 - 15
  59.  
  60. 'command un to set a circle radius
  61.  
  62. 'command cn to draw a filled circle of color n = 0 - 15
  63.  
  64. 'command jn to set the arc deg angle start
  65.  
  66. 'command kn to set the arc deg angle end
  67.  
  68. 'command ln draw arc color n = 0 - 15
  69.  
  70. '================================================ QB64 translation notes
  71. 'Looks like we will need to setup screen with _newimage(xmax, ymax, 12) for easy color numbers for pen p, p9 = blue
  72. ' p-1 means no drawing color = just moving pen into a new position, p0 is pen with Black ink
  73. CONST xmax = 800, ymax = 600 'standard 800 x 600 screen
  74. SCREEN _NEWIMAGE(xmax, ymax, 12)
  75. _SCREENMOVE 300, 40 'center
  76. '======================================================================
  77. 'turtle globals should you translate to another dialect
  78. DIM SHARED scale, tx, ty, tx2, ty2, tr, taStart, taStop, tc, ta, tv, tz 'keep all these as single?
  79. 'initialize turle constants
  80. scale = 1 'external to string settings
  81. tx = 0: ty = 0 ' x, y turtle position
  82. tx2 = 0: ty2 = 0 ' 2nd x,y for fill box or for ellipse width and height
  83. taStart = 0 ' turtle arc Start
  84. taStop = 0 ' turtle arc Stop
  85. tc = 15 ' turtle color (QB colors 0 - 15 and -1 means pen up
  86. ta = 0 ' turtle angle
  87. tv = 0 ' new turtle increment var for changing tv
  88. tz = 1 ' tz is tracking pen size
  89. tr = 0 ' radius
  90.  
  91. 'tests
  92. 'blue pentagon, line thickness 8
  93. tt "z1p-1x400y100z12p4t126" 'start at top point turn 90 + 36
  94. tt "r5f300t72"
  95. scale = .75
  96. tt "z1p-1x400y160z6p2"
  97. tt "r5f300t72"
  98. scale = .5
  99. tt "z1p-1x400y220z3p1"
  100. tt "r5f300t72"
  101. scale = 1
  102. LOCATE 1, 1: PRINT "Pentagons: 12 thick dark red, 6 thick dark green, 3 thick dark blue,     press any for next test..."
  103.  
  104. '===================== Tomaaz/Johnno's turtle art
  105. tt "z2" 'single thick pen
  106. FOR i = 1 TO 2
  107.     tt "a0p12x110y300"
  108.     tt "r100f250t-198"
  109.     tt "a0p10x230y440"
  110.     tt "r10g2h2r18f-20p10t10f-20p-1t10"
  111.     tt "a0p6x350y550"
  112.     tt "s500r248i-2fvt90.5"
  113.     COLOR 15
  114.     LOCATE 1, 1
  115.     PRINT "Scale: "; scale;
  116.     PRINT " Turtle art from Johnno and Tomaaz,"
  117.     PRINT " again with z (Pen size) set at"; tz
  118.     PRINT "  press any to continue.."
  119.     SLEEP
  120.     tt "z1" 'single thickness
  121.     scale = .75 'scale is used for tt drawing
  122.     CLS
  123.  
  124. '== latest mods box bn, circle cn, arc ln <<< fixed
  125. PRINT "Testing arcs, boxes (filled) and circles (filled)"
  126. scale = 1
  127. tt "z1a0p9x300y200d50e50r4b12p-1t-90f100"
  128. tt "p9r4f-100t90"
  129. tt "g-40h30p9a270r8f16.6t-45"
  130. tt "p-1x600y275u50c14"
  131. tt "p-1z2x600y275p12u30j40k140l12"
  132. tt "p-1x585y270p12u5c9"
  133. tt "p-1x615y270p12u5c9"
  134.  
  135. SUB tt (tstring$)
  136.     'local cmd, ds, i, c, d, tst, across, down, lngth, dx, dy, j, aa, stepper
  137.     tstring$ = UCASE$(tstring$)
  138.     cmd$ = "": d$ = ""
  139.     FOR i = 1 TO LEN(tstring$)
  140.         c$ = MID$(tstring$, i, 1)
  141.         IF c$ = "V" THEN ds$ = STR$(tv)
  142.         IF INSTR("0123456789.-", c$) THEN ds$ = ds$ + c$
  143.         IF INSTR("ABCDEFGHIJKLPRSTUXYZ", c$) OR i = LEN(tstring$) THEN
  144.             'execute last cmd if one
  145.             IF cmd$ <> "" THEN
  146.                 n = VAL(ds$)
  147.                 SELECT CASE cmd$
  148.                     CASE "G": tx = tx + n 'move relative to tx, ty
  149.                     CASE "H": ty = ty + n
  150.                     CASE "X": tx = n 'move to absolute screen x, y
  151.                     CASE "Y": ty = n
  152.                     CASE "D": tx2 = n '2nd corner box relative to tx
  153.                     CASE "E": ty2 = n '2nd corner box relative to ty
  154.                     CASE "J": taStart = n 'arc start angle
  155.                     CASE "K": taStop = n 'arc stop angle
  156.                     CASE "P": tc = n 'pen to qb color, -1 no pen
  157.                     CASE "Z": tz = n 'pen size
  158.                     CASE "A": ta = n 'set angle
  159.                     CASE "T": ta = ta + n 'change angle - = left, + = right
  160.                     CASE "U": tr = n 'set radius for circle (R used for repeat)
  161.                     CASE "I": tv = tv + n 'increment variable
  162.                     CASE "S": tv = n 'set or reset variable
  163.                     CASE "R" ' repeat calls out for another call to tt
  164.                         tst$ = MID$(tstring$, i) ' this assumes the rest of the string
  165.                         repete tst$, n ' is the repeat part.
  166.                         EXIT FOR
  167.                     CASE "F" 'Forward d distance according to angle ta
  168.                         across = scale * n * COS(_D2R(ta - 90))
  169.                         down = scale * n * SIN(_D2R(ta - 90))
  170.                         IF tc > -1 THEN
  171.                             IF tz <= 1 THEN
  172.                                 LINE (tx, ty)-STEP(across, down), tc
  173.                             ELSE
  174.                                 lngth = ((across) ^ 2 + (down) ^ 2) ^ .5
  175.                                 IF lngth THEN
  176.                                     dx = across / lngth: dy = down / lngth
  177.                                     FOR j = 0 TO lngth
  178.                                         fcirc tx + dx * j, ty + dy * j, tz, tc
  179.                                     NEXT
  180.                                 END IF
  181.                             END IF
  182.                         END IF
  183.                         tx = tx + across: ty = ty + down 'update turtle position
  184.                     CASE "B"
  185.                         LINE (tx - tx2 / 2, ty - ty2 / 2)-(tx + tx2 / 2, ty + ty2 / 2), n, BF
  186.                     CASE "C"
  187.                         fcirc tx, ty, tr, n
  188.                     CASE "L" 'arc ld u sets radius, j and k set start and end angle
  189.                         IF tc > -1 THEN
  190.                             stepper = 1 / (3 * _PI * tr)
  191.                             FOR aa = taStart TO taStop STEP stepper
  192.                                 dx = tr * COS(_D2R(aa))
  193.                                 dy = tr * SIN(_D2R(aa))
  194.                                 IF tz < 1 THEN
  195.                                     PSET (tx + dx, ty + dy), n
  196.                                 ELSE
  197.                                     fcirc tx + dx, ty + dy, tz, n
  198.                                 END IF
  199.                             NEXT
  200.                         END IF
  201.                 END SELECT
  202.                 ds$ = "": cmd$ = "" 'reset for next build of ds and cmd
  203.             END IF
  204.             cmd$ = c$
  205.         END IF
  206.     NEXT
  207.  
  208. SUB repete (tts$, times)
  209.     'local i
  210.     FOR i = 1 TO times
  211.         tt tts$
  212.     NEXT
  213.  
  214. 'from Steve Gold standard
  215. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  216.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  217.     DIM X AS INTEGER, Y AS INTEGER
  218.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  219.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  220.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  221.     WHILE X > Y
  222.         RadiusError = RadiusError + Y * 2 + 1
  223.         IF RadiusError >= 0 THEN
  224.             IF X <> Y + 1 THEN
  225.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  226.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  227.             END IF
  228.             X = X - 1
  229.             RadiusError = RadiusError - X * 2
  230.         END IF
  231.         Y = Y + 1
  232.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  233.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  234.     WEND
  235.  
  236.  

Haven't looked at this code since 2017 but all commands are a single letter followed by a number including repeat r10 for repeat 10 times. For variable, the v letter can be used as substitute for a number to another command eg rv repeat v times, i increments v as g increments x or h increments y or t (turn) increments a for angle (degrees).

tt (main sub) is short for turtle as this is turtle drawing influenced by Johnno with a Logo at SmallBASIC forum attempt and with JB coding for one way of doing drawings  (mostly pen size = z command) Here: pen off p-1 or pen color 0 to 15, say p9 for light blue.
« Last Edit: January 19, 2020, 03:12:33 pm by bplus »

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #12 on: January 19, 2020, 04:27:20 pm »
Ah... Turtle Art...  I miss the old days when you had to sit there and watch the "turtle" draw the images... 4mhz CPU's... ya gotta love 'em....

J
Logic is the beginning of wisdom.

Offline dajan

  • Newbie
  • Posts: 41
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #13 on: January 20, 2020, 01:14:02 pm »
@bplus: I see you actualy even did not use the original DRAW there, instead you invented completely new language and treated all graphics by yourself. That is quite an advantage over using DRAW, where some limitations I cannot bypass - e.g.  I can't turn the direction in decimals (TA10.25 doesn't work), which makes turning large object choppy.

@FellippeHeitor> Yes, the "come up with a way" part seems to be critical here :o) The more I'm trying to animate some compoud objects (like with more movable parts relative to each other), the more it reminds of a solving a puzzle in a simplistic language, trying to trick it's limitations, while each solution found is unique and cannot be generalized. So I'm rather skeptical at the moment, waiting for enlightment.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: DrawFrame - animation sub using DRAW
« Reply #14 on: January 20, 2020, 01:50:11 pm »
Hm, reverse engineering turtle graphics to use mouse input for shapes... this question has my attention... hmmmm. Gotta learn what DRAW does first, but this does sound interesting.
You're not done when it works, you're done when it's right.