LoginSignup
3
0

X68000Z用クソアプリでOnePアニメをつくる

Last updated at Posted at 2023-12-02

筆者は、9VAeきゅうべえというモーショングラフィックスアプリを開発しており、それを、X68000 Z に移植しました。
X68000 は、1987年にシャープから発表された、当時最高のグラフィックスマシンですが、X68000 Z は、当時の性能を忠実に再現しており、現代のスマホの性能と比べると、相当遅いクソアプリになってしまいました。

X68000 Z 版9VAeきゅうべえダウンロード

SVG SMIL と OnePフォーマット

今の9VAeきゅうべえは、ベクトルグラフィックスアニメを、SVG SMIL というフォーマットで保存していますが、X68000 Z でこのフォーマットで保存すると、保存、読み出しが遅すぎて実用に耐えません。そこで、SVGより軽い OneP(One Picture)というベクトルグラフィックスフォーマットを開発しました。どこが違うのか、SVGとOnePを比較してみましょう。

9VAeサンプル「カニとたたかう」

(new-sample).gif

これは9VAeきゅうべえのヘルプメニューの中にあるサンプルアニメ「カニとたたかう」です。これをSVG、OnePで保存してみました。

SVG SMIL OneP 比率
サイズ 2.08MB 185KB 11:1

データサイズが11分の1になり、速度も数倍はやく保存できます。なぜ、これほど小さくなるか、理由は次の点にあります。

  • SVGは、<animate というタグで、図形の各属性値が、何秒かかってどういう値に変化するかを記述します。図形は色、線の太さ、座標、など複数の属性をもっており、それらについて個別に、<animate をつけるため、記述が複雑、冗長になります。OnePでは、ページごとに図形を記述し、どの図形がどの図形に変化するか、リンクを記述するだけで、属性値の変化は記述しません。情報量がかなり削減されます。
  • SVG は、図形とグラデーションを別々に定義します。そのため、図形が移動、変形するとグラデーションも移動変形させなくてはならず、記述が2重になります。OnePではグラデーションを図形の中に保存するため、図形を移動変形させれば、そのままグラデーションも移動変形します。

簡単なサンプルでOnePとSVGを比較

0000.gif

上のアニメーションの OneP表現が以下です。

<onep viewBox="0 0 300 100">
 <page sec="5">
   <cmd id="C1" ctype="Turn" />
   <use id="U2" label="heart" at="90,60" vec1="40,0" vec2="30,90" />
 </page>
 <page sec="1">
   <cmd linkTo="C1" ctype="Turn" />
   <use linkTo="U2" label="heart" at="250,60" vec1="40,720" vec2="30,810" />
 </page>

  <page sec="1" label="#-1">
   <cmd ctype="Exit" />
 </page>

 <page sec="0.5" label="heart">
   <cmd ctype="BaseFrame" cp1="20,30" cp2="100,90" />     
   <cmd ctype="Turn" />  
   <path id="P3"
     fill="red" stroke="red" width="8"
     gtype="1" fil2="pink" gp1="60,20" gp2="60,100" gpo="60,60" gp3="100,60"
     curve="011011"
     d="M60,50 L80,30 100,50 60,90 20,50 40,30 z" />
 </page>
 <page sec="1">
   <path linkTo="P3"
     fill="pink" stroke="black" width="1"
     gtype="1" fil2="pink" gp1="60,40" gp2="60,80" gpo="60,60" gp3="80,60"
     curve="011011"
     d="M60,55 L70,44 80.75,55 60,76 40,55 50,44 z" />
 </page>
</onep>

これを、SVG SMILで書くと下のようになります。(表記の一例です)

SVG SMIL OneP 違い
グラデーション <linearGradient gtype="1" OnePはpathの中に書く
動きの記述 <animate keyTimes values linkTo SVGは属性ごとに記述
OnePはページの時間とリンクで記述
キーフレーム ない page SVGにはない
曲線 d= curve=
d=
OnePは曲線情報をcurveで記述
ループ repeatCount="indefinite" <cmd ctype="Turn" OnePには往復、繰り返しがある
<svg xmlns:xlink="http://www.w3.org/1999/xlink" image-rendering="optimizeSpeed" baseProfile="basic" version="1.1"  xmlns="http://www.w3.org/2000/svg"
 viewBox="0 0 300 100" >

 <defs>
 <linearGradient id="LGp1_1a10">
   <stop style="stop-color:red;stop-opacity:1;" offset="0" />
   <stop style="stop-color:pink;stop-opacity:1;" offset="1" />
 </linearGradient>
 <linearGradient id="LAp1_1a10">
   <stop offset="0" style="stop-opacity:1;">
     <set fill="freeze" begin="Sa10.begin" attributeName="stop-opacity" to="1" />
     <animate repeatCount="indefinite" keyTimes="0;0.5;1" begin="Sa10.begin" dur="1s" attributeName="stop-color" values="red;#ffc0cb;red" />
   </stop>
   <stop offset="1" style="stop-color:pink;stop-opacity:1;">
     <set fill="freeze" begin="Sa10.begin" attributeName="stop-color" to="pink" />
     <set fill="freeze" begin="Sa10.begin" attributeName="stop-opacity" to="1" />
   </stop>
 </linearGradient>
 <linearGradient id="LGp2_1a10">
   <stop style="stop-color:pink;stop-opacity:1;" offset="0" />
   <stop style="stop-color:pink;stop-opacity:1;" offset="1" />
 </linearGradient>
 <linearGradient id="SGp1_1a10" xlink:href="#LGp1_1a10"
   x1="0.5" y1="-0.1665" x2="0.5" y2="1.1655">
 </linearGradient>
 <linearGradient id="AGp1_1a10" xlink:href="#LAp1_1a10"
   x1="0.5" y1="-0.1665" x2="0.5" y2="1.1655">
 <animate repeatCount="indefinite" keyTimes="0;0.5;1" begin="Sa10.begin" dur="1s" attributeName=  "x1"
     values="0.4995;0.4873;0.4995" />
 <animate repeatCount="indefinite" keyTimes="0;0.5;1" begin="Sa10.begin" dur="1s" attributeName=  "y1"
     values="-0.1665;-0.1248;-0.1665" />
 <animate repeatCount="indefinite" keyTimes="0;0.5;1" begin="Sa10.begin" dur="1s" attributeName=  "x2"
     values="0.4995;0.4873;0.4995" />
 <animate repeatCount="indefinite" keyTimes="0;0.5;1" begin="Sa10.begin" dur="1s" attributeName=  "y2"
     values="1.1655;1.1228;1.1655" />
 </linearGradient>

 <linearGradient id="SGp2_1a10" xlink:href="#LGp2_1a10"
   x1="0.4873" y1="-0.1248" x2="0.4873" y2="1.1228">
 </linearGradient>
 
 <symbol id="AC_heart_a10" overflow="visible" preserveAspectRatio="none">
 <rect><!--9vaC05-->
 <animate id="Sa10" repeatCount="indefinite" begin="0s" dur="1s" attributeName="visibility" from="hidden" to="hidden" /></rect>
 <g id="P1a10:turn1,0">
 <path fill="url(#AGp1_1a10)" stroke-width="8">
   <animate repeatCount="indefinite" begin="Sa10.begin" dur="1s"
     keyTimes="0;0.5;1" attributeName="d"
     values="M60,50.00C64.25,42.81 71.38,32.81 80,30 C91.38,30 101.38,37.13 100,50 C91.38,64.25 72.81,80 60,90.00C47.13,80 28.56,64.25 20,50 C18.56,37.13 28.56,30 40,30 C48.56,32.81 55.69,42.81 60,50.00Z
        ;M60,55.00C62.06,51.06 65.56,45.56 70,44 C75.94,44.06 81.31,48.06 80.75,55 C76.31,62.56 66.69,70.75 60,76.00C53.56,70.75 44.25,62.56 40,55 C39.25,48.06 44.25,44.06 50,44 C54.25,45.56 57.81,51.06 60,55.00Z
        ;M60,50.00C64.25,42.81 71.38,32.81 80,30 C91.38,30 101.38,37.13 100,50 C91.38,64.25 72.81,80 60,90.00C47.13,80 28.56,64.25 20,50 C18.56,37.13 28.56,30 40,30 C48.56,32.81 55.69,42.81 60,50.00Z" />
   <animate repeatCount="indefinite" begin="Sa10.begin" dur="1s"
     keyTimes="0;0.5;1"  attributeName="stroke"
     values="red;black;red"/>
   <animate repeatCount="indefinite" begin="Sa10.begin" dur="1s"
     keyTimes="0;0.5;1"  attributeName="stroke-width"
     values="8;1;8"/>
 </path>
 </g>
 </symbol>

 <symbol id="AS_heart_a10" overflow="visible" preserveAspectRatio="none">
   <path fill="url(#SGp1_1a10)" stroke="red" stroke-width="8" d="M60,50.00C64.25,42.81 71.38,32.81 80,30 C91.38,30 101.38,37.13 100,50 C91.38,64.25 72.81,80 60,90.00C47.13,80 28.56,64.25 20,50 C18.56,37.13 28.56,30 40,30 C48.56,32.81 55.69,42.81 60,50.00Z"></path>
 </symbol>
 </defs>

 <g id="SVG_Start">
   <rect fill="white" x="0" y="0" width="300" height="100">
   <animate id="Sa" repeatCount="indefinite" begin="0s" dur="12s" attributeName="visibility" from="visible" to="visible" /></rect>
 </g>

 <g>
 <use xlink:href="#AC_heart_a10">
   <animateTransform  repeatCount="indefinite" begin="Sa.begin" dur="12s"
     keyTimes="0;0.41;0.5;0.91;1"  attributeName="transform"
     type="translate"
     values="90,60;250,60;250,60;90,60;90,60"/>
   <animateTransform  repeatCount="indefinite" begin="Sa.begin" dur="12s"
     keyTimes="0;0.41;0.5;0.91;1"  attributeName="transform"
     type="scale"
     values="1,1;1,1;1,1;1,1;1,1" additive="sum" />
   <animateTransform  repeatCount="indefinite" begin="Sa.begin" dur="12s"
     keyTimes="0;0.41;0.5;0.91;1"  attributeName="transform"
     type="rotate"
     values="0;720;720;0;0" additive="sum" />
   <animateTransform  repeatCount="indefinite" begin="Sa.begin" dur="12s"
     keyTimes="0;0.41;0.5;0.91;1"  attributeName="transform"
     type="translate"
    values="-60,-60;-60,-60;-60,-60;-60,-60;-60,-60" additive="sum" />
 </use>
 </g>
</svg>
  • SVG SMILは、動きの記述が animate で各属性ごとに分散して記述されており、テキストで動きを修正することはほぼ不可能です。(このデータは9VAeの出力を手で修正)
  • OnePは、ページごとに図形を記述し、linkToでつなぐだけなのでシンプルでわかりやすいです。

SVGでは難しい表現

  • さらに、OneP には、SVGにはないエフェクトがあり、それを使うとさらに差がつきます。(SVGでできるが、OnePではできない表現もたくさんあります。JavaScript、CSS、マスクといった機能がOnePにはありません。)

<use にエフェクトがつけられる

ex10acol.gif

OnePの <use に色やぼかしをつければ、影のような表現ができます。同じパーツに異なる表現を追加できます。

<onep viewBox="0 0 300 100">
  <page sec="5">
    <use label="heart"
      at="155,50" vec1="40,0" vec2="70,150" 
      stroke="gray" fill="gray" width="1" blurTyp="2,10,30" />
    <use label="heart"
      at="90,60" vec1="40,0" vec2="30,90" />
  </page>

   <page sec="1" label="#-1">
    <cmd ctype="Exit" />
  </page>

  <page sec="0.5" label="heart">
    <cmd ctype="BaseFrame" cp1="20,30" cp2="100,90" />     
    <cmd ctype="Turn" />  
    <path id="P1"
      fill="red" stroke="black" width="1"
      curve="011011"
      d="M60,50 L80,30 100,50 60,90 20,50 40,30 z" />
  </page>
  <page sec="1">
    <path linkTo="P1"
      fill="pink" stroke="black" width="1"
      curve="011011"
      d="M60,55 L70,44 80.75,55 60,76 40,55 50,44 z" />
  </page>
</onep>

<use ごとに時間軸が異なる

ex11atime.gif

OnePでは、<use の時間をずらすことができます。左右にゆれるふりこを3個複製し、色をかえて時間をずらしています。SVG の <use には、時間軸が1つしかなく同じ動作しかしないようです。

<onep viewBox="0 0 300 100">
  <page sec="10">
    <use label="anime"
      at="151,51" vec1="75.5,0" vec2="56.5,90" />
    <use label="anime"
      at="155,55" vec1="75.5,0" vec2="56.5,90" 
      fill="red" leadSec="0.2" />
    <use label="anime"
      at="159,59" vec1="75.5,0" vec2="56.5,90" 
      fill="black" leadSec="0.5" />
  </page>

  <page sec="1" label="#-1">
    <cmd ctype="Exit" />
  </page>

  <page sec="1" label="stick">
    <cmd ctype="BaseFrame" cp1="170,50" cp2="230,280" />     
    <path 
      fill="white" stroke="black" width="1"
      d="M195,44 L205,44 205,250 195,250 z"/>
  </page>

  <page sec="1" label="#-2">
    <cmd ctype="Exit" />
  </page>
  
   <page sec="1" label="anime">
    <cmd ctype="BaseFrame" cp1="25,19" cp2="375,281" />     
    <cmd ctype="Turn" cp1="199,150" />     
    <use id="U1" label="stick" regNo="1"
      at="200,50" vec1="30,-90" vec2="115,0" vec0="115,45" />
    <timeCurve regNo="1"
      curve="11"
      d="M29,259 L63,242 125,146 157,131 " />
  </page>
  <page sec="1">
    <use linkTo="U1"
      at="200,50" vec1="30,-90" vec2="115,0" vec0="115,135" />
  </page>
</onep>

X68000 Z 版 9VAe で OnePアニメの作り方

  • X68000 Z 版 9VAe (230611) を起動します。
  • ツールメニュー(F6) の「OneP編集」を実行します。ED.x が起動するはずです。(X68000 Z用に作った新機能です)
  • 以下の OnePを入力し、ESC E で終了すれば、OnePアニメが読み込まれます。 X68000 Z 実機動画はこちら

1.三角をかく

add.svg.gif

<onep viewBox="0,0,300,100">
  <page sec="1">
    <path stroke="white" fill="blue"
      d="M5,0 L10,100 0,100" />
  </page>
</onep>
書き方 パラメータ 意味
viewBox= 0,0,300,100 用紙の左上が0,0 サイズが300x100
sec= 1 ページの再生時間が1秒
時間指定がないとひとコマアニメになります
stroke= white 線の色が白
fill= blue 塗り色青
d= M5,0 L10,100 0,100 Mは始点、L以降は線でつなぐ
最後にzをつけると閉じます

2.ページにラベルをつけてアニメキャストにする

aaa.onep.gif

  • ページに"aaa" というlabelをつけました。
  • 基準枠(BaseFrame 幅10、高さ100)を追加しました。
<onep viewBox="0,0,300,100">
  <page sec="1" label="aaa">
    <cmd ctype="BaseFrame" cp1="0,0" cp2="10,100" />
    <path stroke="white" fill="blue"
      d="M5,0 L10,100 0,100" />
  </page>
</onep>
書き方 パラメータ 意味
label= aaa ページにラベルをつけると useで参照できます
ctype="BaseFrame" cp1="0,0" cp2="10,100" 基準枠左上が0,0 右下10,100

3.aaaページを配置(use at,vec1,vec2)

bck.svg.gif

  • 5秒のページに "aaa" ページを配置しました。
  • at=100,50は中心。vec1=5,0の5は基準枠幅の半分、0は水平角度、vec2=50,90の50は基準枠高さの半分、90は下向き角度です。
  • ページの区切りを追加しました。これをいれないと5秒後に aaa ページを再生してしまいます。
<onep viewBox="0,0,300,100">
  <page sec="5">
    <use label="aaa" 
      at="100,50" vec1="5,0" vec2="50,90" />
  </page>

  <page label="#-1" />

  <page sec="1" label="aaa">
    <cmd ctype="BaseFrame" cp1="0,0" cp2="10,100" />
    <path stroke="white" fill="blue"
      d="M5,0 L10,100 0,100" />
  </page>
</onep>
書き方 パラメータ 意味
<page label= "#-1" #-数字というラベルのページは区切りです
<use label= "aaa" "aaa"というページをいれる
at= "100,50" useの中心座標が100,50
vec1= "5,0" 5は基準枠幅10の半分、0は角度0度
vec2= "50,90" 50は基準枠高さ100の半分、0は角度90度

4.回転中心を追加(vec0)

aaa.onep.gif

  • vec0=50,90を追加しました。at=の場所から、vect0の位置50(基準枠の高さの半分、方向は90度で下向き)に移動した位置に中心が移動します。vec1,vec2が90度回転し、横向きになります。
<onep viewBox="0,0,300,100">
  <page sec="5">
    <use label="aaa" 
      at="100,50" vec1="5,0" vec2="50,90" vec0="50,90" />
  </page>

  <page label="#-1" />

  <page sec="1" label="aaa">
    <cmd ctype="BaseFrame" cp1="0,0" cp2="10,100" />
    <path stroke="white" fill="blue"
      d="M5,0 L10,100 0,100" />
  </page>
</onep>
書き方 パラメータ 意味
<use vec0= "50,90" 50は基準枠高さ100の半分、0は角度90度

5.図形を-90度回転させて上に移動

add.svg.gif

  • at=のy座標を0、vec1,vec2の角度を-90度回転させました。
<onep viewBox="0,0,300,100">
  <page sec="5">
    <use label="aaa" 
      at="100,0" vec1="5,-90" vec2="50,0" vec0="50,90" />
  </page>

  <page label="#-1" />

  <page sec="1" label="aaa">
    <cmd ctype="BaseFrame" cp1="0,0" cp2="10,100" />
    <path stroke="white" fill="blue"
      d="M5,0 L10,100 0,100" />
  </page>
</onep>

6.次のページを作成、useにリンクをつけて動かす

aaa.onep.gif

  • 最初のページを複製
  • use に id="U1"を追加。2ページめの use にlinkToをつけました。
  • vec0 の角度を、1ページ2ページで45度マイナスプラスしました
<onep viewBox="0,0,300,100">
  <page sec="5">
    <use id="U1" label="aaa" 
      at="100,0" vec1="5,-90" vec2="50,0" vec0="50,45" />
  </page>
  <page sec="5">
    <use linkTo="U1" label="aaa" 
      at="100,0" vec1="5,-90" vec2="50,0" vec0="50,135" />
  </page>

  <page label="#-1" />

  <page sec="1" label="aaa">
    <cmd ctype="BaseFrame" cp1="0,0" cp2="10,100" />
    <path stroke="white" fill="blue"
      d="M5,0 L10,100 0,100" />
  </page>
</onep>
書き方 パラメータ 意味
<use label= "U1" idをつけます。どんな名前でもかまいません
<use linkTo= "U1" "U1"とリンクします

7.往復をいれて、アニメキャストにする

aaa.onep.gif

  • 最初のページに往復(Turn)をいれました
  • 基準枠を入れて、ラベル"bbb"をつけました
<onep viewBox="0,0,300,100">
  <page sec="5" label="bbb">
    <cmd ctype="BaseFrame" cp1="50,0" cp2="150,100" />
    <cmd ctype="Turn" />
    <use id="U1" label="aaa" 
      at="100,0" vec1="5,-90" vec2="50,0" vec0="50,45" />
  </page>
  <page sec="5">
    <use linkTo="U1" label="aaa" 
      at="100,0" vec1="5,-90" vec2="50,0" vec0="50,135" />
  </page>

  <page label="#-1" />

  <page sec="1" label="aaa">
    <cmd ctype="BaseFrame" cp1="0,0" cp2="10,100" />
    <path stroke="white" fill="blue"
      d="M5,0 L10,100 0,100" />
  </page>
</onep>
書き方 パラメータ 意味
<cmd ctype= "Turn" 往復
<use linkTo= "U1" "U1"とリンクします

8.往復するアニメを新しいページに3ついれる

bck.svg.gif

  • "bbb"を3つ複製したページを追加しました
  • 水平位置 at を、100,125,150にしました
<onep viewBox="0,0,300,100">

  <page sec="5" >
    <use label="bbb" 
      at="100,50" vec1="50,0" vec2="50,90" />
    <use label="bbb" 
      at="125,50" vec1="50,0" vec2="50,90" />
    <use label="bbb" 
      at="150,50" vec1="50,0" vec2="50,90" />
  </page>

  <page label="#-2" />

  <page sec="5" label="bbb">
    <cmd ctype="BaseFrame" cp1="50,0" cp2="150,100" />
    <cmd ctype="Turn" />
    <use id="U1" label="aaa" 
      at="100,0" vec1="5,-90" vec2="50,0" vec0="50,45" />
  </page>
  <page sec="5">
    <use linkTo="U1" label="aaa" 
      at="100,0" vec1="5,-90" vec2="50,0" vec0="50,135" />
  </page>

  <page label="#-1" />

  <page sec="1" label="aaa">
    <cmd ctype="BaseFrame" cp1="0,0" cp2="10,100" />
    <path stroke="white" fill="blue"
      d="M5,0 L10,100 0,100" />
  </page>
</onep>

9.色を変更して時間を変更

aaa.onep.gif

  • fill=をつけて色を変更、leadSec=をつけて時間をずらしました。
  • 往復をいれました
<onep viewBox="0,0,300,100">

  <page sec="5" >
    <cmd ctype="Turn" />
    <use label="bbb" 
      at="100,50" vec1="50,0" vec2="50,90" />
    <use label="bbb" fill="red" leadSec="2"
      at="125,50" vec1="50,0" vec2="50,90" />
    <use label="bbb" fill="yellow" leadSec="3"
      at="150,50" vec1="50,0" vec2="50,90" />
  </page>

  <page label="#-2" />

  <page sec="5" label="bbb">
    <cmd ctype="BaseFrame" cp1="50,0" cp2="150,100" />
    <cmd ctype="Turn" />
    <use id="U1" label="aaa" 
      at="100,0" vec1="5,-90" vec2="50,0" vec0="50,45" />
  </page>
  <page sec="5">
    <use linkTo="U1" label="aaa" 
      at="100,0" vec1="5,-90" vec2="50,0" vec0="50,135" />
  </page>

  <page label="#-1" />

  <page sec="1" label="aaa">
    <cmd ctype="BaseFrame" cp1="0,0" cp2="10,100" />
    <path stroke="white" fill="blue"
      d="M5,0 L10,100 0,100" />
  </page>
</onep>
書き方 パラメータ 意味
<use fill= "red" 塗り色を赤にします
<use leadSec= "2" 時間を2秒前にずらします
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0