筆者は、9VAeきゅうべえというモーショングラフィックスアプリを開発しており、それを、X68000 Z に移植しました。
X68000 は、1987年にシャープから発表された、当時最高のグラフィックスマシンですが、X68000 Z は、当時の性能を忠実に再現しており、現代のスマホの性能と比べると、相当遅いクソアプリになってしまいました。
X68000 Z 版9VAeきゅうべえダウンロード
- 9VAe X68000 Z 版ダウンロードはこちら
- SCSI HDD イメージが必要。作り方はこちら
9va フォルダを、DiskExplorer を使って、SCSI HDDイメージにいれてください。 - Z 実機から、9va フォルダの 9vae.x でアプリが起動します。
- X68000z実機で動かした動画を見る
SVG SMIL と OnePフォーマット
今の9VAeきゅうべえは、ベクトルグラフィックスアニメを、SVG SMIL というフォーマットで保存していますが、X68000 Z でこのフォーマットで保存すると、保存、読み出しが遅すぎて実用に耐えません。そこで、SVGより軽い OneP(One Picture)というベクトルグラフィックスフォーマットを開発しました。どこが違うのか、SVGとOnePを比較してみましょう。
9VAeサンプル「カニとたたかう」
これは9VAeきゅうべえのヘルプメニューの中にあるサンプルアニメ「カニとたたかう」です。これをSVG、OnePで保存してみました。
SVG SMIL | OneP | 比率 | |
---|---|---|---|
サイズ | 2.08MB | 185KB | 11:1 |
データサイズが11分の1になり、速度も数倍はやく保存できます。なぜ、これほど小さくなるか、理由は次の点にあります。
- SVGは、<animate というタグで、図形の各属性値が、何秒かかってどういう値に変化するかを記述します。図形は色、線の太さ、座標、など複数の属性をもっており、それらについて個別に、<animate をつけるため、記述が複雑、冗長になります。OnePでは、ページごとに図形を記述し、どの図形がどの図形に変化するか、リンクを記述するだけで、属性値の変化は記述しません。情報量がかなり削減されます。
- SVG は、図形とグラデーションを別々に定義します。そのため、図形が移動、変形するとグラデーションも移動変形させなくてはならず、記述が2重になります。OnePではグラデーションを図形の中に保存するため、図形を移動変形させれば、そのままグラデーションも移動変形します。
簡単なサンプルでOnePとSVGを比較
上のアニメーションの 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 にエフェクトがつけられる
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 ごとに時間軸が異なる
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.三角をかく
<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" という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)
- 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)
- 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度回転させて上に移動
- 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にリンクをつけて動かす
- 最初のページを複製
- 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.往復をいれて、アニメキャストにする
- 最初のページに往復(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ついれる
- "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.色を変更して時間を変更
- 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秒前にずらします |