2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

MicroPythonで、ひとコマアニメーション

Last updated at Posted at 2023-07-06

X68000 ZMicro Pythonで、ひとコマアニメーションアプリ「まいくろえほん」を作成したので、紹介します。

ひとコマアニメーションとは

1koma-mac.gif

幼稚園の子供でもできるので、キッズプラザ大阪では、毎日 150-200本のひとコマアニメーションが作られています

ひとコマアニメーションが作れるアプリ

うるさいえほんは、JavaScriptで記述された、音声合成つきひとコマアニメーションアプリです。使い方、説明はこちら

まいくろえほんは、うるさいえほんを、X68000 Z で再現しようとつくったアプリです。

9VAeきゅうべえは、ひとコマアニメの元になった無料のモーショングラフィックスアプリです。

PEAS motch!は、キッズプラザ大阪で使われているアプリで、9VAeから作られました。

まいくろえほん

うるさいえほんに掲載されているひまわり.onep を再生した結果です。作者は、ごっほこはま(2022)

ひまわり2.png

仕様

popmenu.png

  • メニュー外をクリックしたあと描画できます。線をひくと音が鳴ります。Runで再生
  • RYGCBMW:描画色設定(赤黄緑水色青紫白)
  • 数字: ペンの太さ。9以上は〇で描きます
  • HSV:描画色の調整。マウスカーソルが設定された色。
  • <-- -->: アプリと同じフォルダに OnePファイルがある場合、メニューに表示し、クリックで再生できます。そのファイルの切り替え。上のひまわりの例では、ONEP-HAN.ONE, MUKASHI.ONE, HIMAWARI.ONE というOnePファイルが同じフォルダにあります。
  • Quit:描画した絵をout.oneファイルに保存して終了。
  • X68000 は描画性能が低いため、太い線を4本の直線または円で表現しています。

MicroPython版「まいくろえほん」 ソースコード

X68000 Z または、エミュレータXM6で動きます。描画、音の発声に x68k.iocs関数を使っています。x68k.iocs関数の説明はこちら

ehon.py
import sys
import os
from x68k import *
from struct import pack

iocs(i.OS_CUROF)   #Text Cursor OFF
#crtmod(14,1)      #255x255x64kColor
crtmod(12,1)       #512x512x64kColor
iocs(i.MS_CURON)   #Mouse Cursor ON
iocs(i.SKEY_MOD,0) #SoftKeyboard OFF
g=GVRam(0)         #Graphic
tx=TVRam()         #Text VRam


SAVFILE="out.one"
TMPFILE="out.###"

stIS = -1
stSaved = -1
strk = []   # line (x,y)
strc = []   # line color
onep = []   # oneP file name
sx0,sy0 = -999,-999
oneS=0 # oneP start

wrH,wrS,wrV=128,31,15
wrtCol=iocs(i.HSVTORGB,(wrH<<16)|(wrS<<8)|wrV)
wrtW=2

colHue =(0,32,64,96,128,160,0) #RYGCBMR




def fnQuit(x):
  drawMenu(0,0)
  fnSave(x)
  iocs(i.OS_CURON)    #Text Cursor ON
  crtmod(16,1)        #768x512x16
  iocs(i.SKEY_MOD,-1) #SoftKeyboard ON
  iocs(i.B_CLR_ST,2)  #Screen Reset
  sys.exit()


def opm_init():
    opmdrv = iocs(i.B_LPEEK, a1=(0x000400 + 4 * 0xf0))
    if opmdrv < 0 or (opmdrv >= 0xfe0000 and opmdrv <= 0xffffff):
        iocs(i.OS_CURON)    #Text Cursor ON
        crtmod(16,1)        #768x512x16
        iocs(i.SKEY_MOD,-1) #SoftKeyboard ON
        iocs(i.B_CLR_ST,2)  #Screen Reset
        print("OPMDRV is not installed")
        sys.exit()
    iocs(i.OPMDRV, 0x00)

def opm_alloc(size):
    iocs(i.OPMDRV, 0x01, (1 << 16) | size)
    #iocs(i.OPMDRV, 0x01, (2 << 16) | size)
    #iocs(i.OPMDRV, 0x01, (3 << 16) | size)
    iocs(i.OPMDRV, 0x02, (1 << 16) | 1) #assign 1
    #iocs(i.OPMDRV, 0x02, (2 << 16) | 2) #assign 2
    #iocs(i.OPMDRV, 0x02, (3 << 16) | 3) #assign 3

def opm_free():
    ret = 0
    ret |= iocs(i.OPMDRV, 0x07, 1)
    #ret |= iocs(i.OPMDRV, 0x07, 2)
    #ret |= iocs(i.OPMDRV, 0x07, 3)
    return ret

def opm_trk(trk, mml):
    mml += "\x00"
    iocs(i.OPMDRV, 0x06, trk, a1=mml)


opm_init()
opm_alloc(1000)
iocs(i.OPMDRV, 0x05, 200) #tempo 32-200
mml='@65A'
opm_trk(1,mml)


def setPal():
  global wrtCol,wrH,wrS,wrV
  wrtCol=iocs(i.HSVTORGB,((wrH%192)<<16)|((wrS%32)<<8)|(wrV%32))
  iocs(i.TPALET,8,wrtCol) #Mouse Color
  if wrtCol&0xf800 > 0xc800:
    iocs(i.TPALET,7,0x30) #Mouse Edge
  else:
    iocs(i.TPALET,7,0xfffe)



def fnRGBW(x):
  global wrtCol,wrH,wrS,wrV
  wrS,wrV=31,31
  if x/8<6:
    wrH=colHue[int(x/8)]
  else:
    wrS=0
  setPal()

def fnHue(x):
  global wrH
  if len(onep)>0:
    fnRun(-1)
    return
  if x/8<4:
    wrH-=8
  else:
    wrH+=8
  setPal()

def fnSat(x):
  global wrS
  if len(onep)>1:
    fnRun(-2)
    return
  if x/8<4:
    wrS-=4
  else:
    wrS+=4
  setPal()

def fnVal(x):
  global wrV
  if len(onep)>2:
    fnRun(-3)
    return
  if x/8<4:
    wrV-=4
  else:
    wrV+=4
  setPal()


def getPal(col):
    rr=int("0x"+col[0:2])
    gg=int("0x"+col[2:4])
    bb=int("0x"+col[4:6])
    return ((gg<<8)&0xf800)|((rr<<3)&0x07c0)|((bb>>2)&0x3e)

def getRGB(cc):
    rr=(cc & 0x7c0)>>3
    gg=(cc & 0xf800)>>8
    bb=(cc & 0x3e)<<2
    return '#{:02x}{:02x}{:02x}'.format(rr,gg,bb)



def drawLine(lin):
    global mml

    x=lin.find('width=')
    wid=1
    if x>0:
      y=lin[x+7:].find('\"')
      wid=int(float(lin[x+7:x+7+y])/2)

    x=lin.find('stroke=')
    pal=15
    if x>0:
      y=lin[x:].find('#')
      x+=y+1
      pal=getPal(lin[x:x+6])    

    y=lin.find('d="M')
    x=y+4
    x0,y0=-999,-999
    while 1:
      y=lin[x:].find(',')
      xx=int(float(lin[x:x+y]))
      x+=y+1
      y=lin[x:].find('L')
      if y<0:
        return 0
      yy=int(float(lin[x:x+y]))
      x+=y+1
      if x0!=-999 or y0!=-999:
        if wid>8:
          g.circle(x0,y0,wid,pal,0,360,388)
        else:
          g.line(x0,y0,xx-wid,yy,pal)
          if wid>0:
            g.line(x0,y0,xx,yy-wid,pal)
            g.line(x0,y0,xx+wid,yy,pal)
            g.line(x0,y0,xx,yy+wid,pal)        
        iocs(i.OPMDRV, 0x08, pack('L',1), 0,0) #play 1ch
      x0,y0=xx,yy
      btn = iocs(i.MS_GETDT)&0xff #R-btn
      if btn>0:
         return 1


def fnRun(x):
  g.wipe()
  if x<0:
    drawMenu(0,0)
    g.fill(0,0,512,512,wrtCol)
    fn=onep[-x-1+oneS]
    print(fn)
  else:
    fn=SAVFILE

  try:
    with open(fn) as f:
      for line in f:
        if '</page' in line:
          break       
        if '<path' in line:  
          brk=drawLine(line)
          if brk>0:
            break
  except:
    pass
  drawMenu(mx,my)


def fnSave(x):
  global mx,my,stIS,stSaved
  if stIS < 0:
     return
  if stIS<=stSaved:
     return
  to = open(TMPFILE,'w')
  to.write('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n')
  to.write('<onep viewBox="0 0 512 512">\n')
  to.write('<page>\n')
  wrt=0
  try:
    with open(SAVFILE) as f:
      for line in f:
        if '</page' in line:
           break
        if wrt>0:
           to.write(line) 
        if '<page' in line:
           wrt=1
  except:
    pass
  for st in range(stIS+1):
     if stIS<=stSaved:
       continue
     to.write( strc[st] +' d="'+strk[st]+'" />\n')
  stSaved = stIS
  to.write('</page>\n')
  to.write('</onep>\n')
  to.close()
  try:
    os.remove(SAVFILE)
  except:
    pass
  os.rename(TMPFILE,SAVFILE)

def fnSaveRun(x):
  drawMenu(0,0) #menu off
  fnSave(x)
  fnRun(x)

def fnSelect(x):
  global oneS
  if x/8<4:
    if oneS>0:
      oneS-=1
  else:
    if oneS+3<len(onep):
      oneS+=1
  drawMenu(0,0)
  drawMenu(mx,my)

def fnWidth(x):
  global wrtW
  if x/8<4:
    if wrtW>=2:
      wrtW=int(wrtW/2)
  else:
    if wrtW<=32:
      wrtW*=2
  drawMenu(0,0)
  drawMenu(mx,my)

#-------------------
menu=('RYGCBMW','-  %d  +','-  H  +','-  S  +','-  V  +','<-- -->','Run','Quit')
func=(fnRGBW   ,fnWidth   ,fnHue   ,fnSat   ,fnVal      ,fnSelect  ,fnSaveRun,fnQuit)
#-------------------

files=[f for f in os.listdir(".")]
for fn in files:
  if fn.find(SAVFILE)>=0:
    continue
  if fn.find('.one')>0 or fn.find('.ONE')>0:
    onep.append(fn)

mnOn=0
mh=len(menu)*16
mw=0
for it in menu:
  if len(it)>mw:
     mw=len(it)
for it in onep:
  if len(it)>mw:
     mw=len(it)
mw *= 8
mx,my=100,100

def drawMenu(x,y):
  global mnOn,mx,my
  if mnOn>0:
      mnOn=0
      iocs(i.B_CLR_ST,2)
      return
  
  if x+mw>511:
    x=511-mw
  if y+mh>511:
    y=511-mh
  iocs(i.TPALET,2,0x1e) 
  mnOn,mx,my = 1,x-(x%8), y-(y%16)
  tx.box(0,mx-4,my-4,mw+8,mh+8)
  y=int(my/16)
  z=0
  for it in menu:
      iocs(i.B_LOCATE,int(mx/8),y)
      if z==1:
        print("- ",wrtW," +")
      elif z==5 and len(onep)==0:
        print("No OneP")
      elif z>=2 and z-2<len(onep) and z<=4:
        print(onep[z-2+oneS]) #File Name
      else: 
        print(it)
      y+=1
      z+=1
  tx.rev(1,mx-4,my-4,mw+8,mh+8)

def execMenu(x,y):
  global mnOn,mx,my #for Menu
  if mnOn==0 or x<mx or x>mx+mw or y<my or y>my+mh:
     return 0
  if y-my<len(func)*16:
    func[int((y-my)/16)](x-mx) 
  return 1


def addLine():
  global strk,stIS,wrtW
  strk.append('x')
  strc.append('  <path stroke="'+ getRGB(wrtCol)+'"' +' width="'+str(wrtW)+'"' )
  stIS +=1
  sx0,sy0 = -999,-999

def addPoint(x,y):
  global sx0,sy0,wrtCol,wrtW
  if abs(x-sx0)<3 and abs(y-sy0)<3:
     return
  if strk[stIS][0]!='M':
     strk[stIS]='M'+str(x)+','+str(y)
  else:
     strk[stIS]=strk[stIS]+'L'+str(x)+","+str(y)
     if wrtW>8:
       g.circle(sx0,sy0,wrtW,wrtCol,0,360,388)
     else:
       g.line(sx0,sy0,x-wrtW,y,wrtCol)
       g.line(sx0,sy0,x,y-wrtW,wrtCol)
       g.line(sx0,sy0,x+wrtW,y,wrtCol)
       g.line(sx0,sy0,x,y+wrtW,wrtCol)
     iocs(i.OPMDRV, 0x08, pack('L',1), 0,0) #play 1ch
  sx0,sy0 = x,y
  

# Main Loop
mnOn=1
fnRun(0)
drawMenu(100,100)

bt0=0
while 1:
  pos = iocs(i.MS_CURGT)
  x = (pos >>16)&0xffff
  y = pos & 0xffff
  btn = iocs(i.MS_GETDT)&0xffff
  if btn==bt0:
    if mnOn==0 and btn & 0xff00: #left Down
      addPoint(x,y)
    continue
  bt0=btn
  if btn & 0xff: #right
    drawMenu(x,y)
  if btn & 0xff00: #left
    if execMenu(x,y):
      continue
    if mnOn:
      drawMenu(x,y)
    addLine()


iocs(i.OS_CURON)
input("End")
crtmod(16,1)
iocs(i.SKEY_MOD,-1)
iocs(i.B_CLR_ST,2)

関数 処理内容 引数
fnQuit 終了処理
opm_init FM音源初期化
opm_alloc FM音源トラック用メモリ確保
opm_free FM音源メモリ解放
opm_trk 音の追加 mml=音
setPal テキストグラフィックのパレット設定
fnRGBW 色の設定 x=クリック水平位置
fnHue 色合い設定 x=クリック水平位置
fnSat 彩度設定 x=クリック水平位置
fnVal 明度設定 =クリック水平位置
getPal 線の色からX68Kの色への変換 col=RRGGBB文字
getRGB X68K色からRGB文字列への変換 cc=X68K色
drawLine 線を描く lin=<path文字列
fnRun 再生
fnSave ファイル保存
fnSaveRun 保存して再生
drawMenu ポップアップメニュー表示 (x,y)表示位置
execMenu メニュー項目の実行 (x,y)クリックした位置
addLine 線のタグを1つ追加
addPoint 線の座標点を追加し、描画も行う (x,y)座標

実行のしかた

  1. X68000 Z または、X68Kエミュレータが必要です。
  2. Micro Python用SDカードを作ります。作り方はこちら。automount.xdfというフロッピーディスクイメージを作ります。
  3. 上のソースコードを ehon.py ファイルに保存し、automount.xdf の中にいれます。
  4. X68000 Z のコマンドプロンプトから以下の命令を実行します。
micropyt ehon.py

音を出すには、OPMDRV をいれておく必要があります。

OneP データ解説

  • ひとコマアニメーション(One Picture Animation)を保存するXMLテキストフォーマットです。拡張子は「.onep」または「.one」
  • うるさいえほんの「はっぴょう」にサンプルデータがあります。「むかしばなし」がおすすめ
  • 再生したあと「ファイル」「ファイルにほぞん」でダウンロードできます。
  • OnePデータは9VAeきゅうべえで読み込み、保存ができます。
  • 文字コードは UTF8 ですが、まいくろえほんは ShiftJIS

サンプルデータ(はあと)

うるさいえほんの「はっぴょう」にある「はあと.onep」です

onep-hana.gif

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<onep viewBox="0 0 640 480">
    <page>
        <path stroke="#000000" width="10" d="M312.33,332L308.33,332L307.33,332L297.33,332L281.33,329L259.33,318L232.33,297L212.33,273L205.33,252L205.33,236L209.33,221L215.33,212L225.33,207L234.33,207L245.33,208L256.33,216L269.33,225L279.33,232L282.33,235L287.33,230L300.33,218L316.33,206L339.33,199L353.33,199L361.33,199L365.33,202L367.33,210L368.33,228L365.33,249L356.33,266L341.33,286L331.33,300L326.33,306L322.33,312L319.33,316L315.33,321L309.33,327L307.33,332L305.33,334L304.33,334"/>
        <path stroke="#ff0000" width="50" d="M307.33,372L307.33,372L304.33,370L294.33,368L280.33,366L262.33,362L255.33,360L250.33,357L244.33,355L237.33,353L230.33,350L221.33,346L213.33,342L209.33,341L205.33,338L202.33,334L197.33,332L191.33,325L186.33,318L181.33,311L175.33,305L174.33,301L171.33,298L169.33,292L167.33,286L163.33,280L161.33,272L160.33,266L157.33,260L156.33,251L155.33,245L155.33,238L155.33,231L155.33,222L155.33,216L156.33,208L157.33,204L159.33,197L163.33,190L167.33,183L171.33,178L172.33,176L177.33,172L180.33,168L184.33,164L189.33,162L195.33,158L199.33,156L201.33,154L203.33,153L206.33,152L210.33,151L216.33,151L220.33,151L222.33,151L226.33,151L231.33,151L237.33,155L239.33,156L244.33,159L246.33,161L250.33,162L255.33,164L257.33,166L261.33,167L262.33,168L263.33,170L265.33,170L268.33,171L270.33,172L273.33,173L279.33,175L282.33,179L283.33,180L284.33,180L286.33,178L295.33,175L305.33,171L314.33,168L326.33,165L338.33,162L349.33,158L358.33,156L362.33,155L367.33,154L369.33,154L369.33,154L371.33,154L373.33,154L379.33,154L388.33,154L396.33,158L399.33,159L403.33,162L408.33,164L411.33,169L415.33,176L419.33,183L421.33,189L422.33,195L422.33,203L422.33,211L422.33,217L422.33,225L422.33,231L421.33,237L419.33,246L417.33,252L413.33,259L411.33,267L408.33,272L406.33,278L405.33,283L401.33,287L399.33,291L395.33,298L392.33,302L387.33,310L383.33,315L381.33,319L377.33,325L373.33,329L370.33,334L365.33,340L361.33,346L358.33,350L352.33,357L346.33,362L341.33,368L337.33,370L332.33,373L326.33,375L323.33,376L323.33,376L321.33,377L321.33,378"/>
        <path stroke="#29ad63" width="1" d="M314.33,373L311.33,371L307.33,370L301.33,369L297.33,368L293.33,368L287.33,367L281.33,367L275.33,366L272.33,365L268.33,364L263.33,362L259.33,361L253.33,359L251.33,357L244.33,350L237.33,344L230.33,338L220.33,332L213.33,328L209.33,326L206.33,324L205.33,324L202.33,322L200.33,321L197.33,320L193.33,318L191.33,316L188.33,315L185.33,313L183.33,312L181.33,307L177.33,300L173.33,293L171.33,286L167.33,279L164.33,271L161.33,262L160.33,256L158.33,250L157.33,242L157.33,237L157.33,231L157.33,225L157.33,220L157.33,214L157.33,210L157.33,204L157.33,198L159.33,193L161.33,186L162.33,182L165.33,176L167.33,174L172.33,169L174.33,164L178.33,163L181.33,158L185.33,158L187.33,157L191.33,155L192.33,154L195.33,154L199.33,153L203.33,153L208.33,153L216.33,153L221.33,153L226.33,154L230.33,155L235.33,156L239.33,158L243.33,160L247.33,161L250.33,163L255.33,166L259.33,168L260.33,170L261.33,172L262.33,173L265.33,175L267.33,176L268.33,177L269.33,180L271.33,180L273.33,182L273.33,182L274.33,183L276.33,184L277.33,184L277.33,184L278.33,185L279.33,185L279.33,186L282.33,186L283.33,188L284.33,190L284.33,191L284.33,194L282.33,196L281.33,197L280.33,198L279.33,198L278.33,198L275.33,194L275.33,194L275.33,193L275.33,189L278.33,186L285.33,182L290.33,180L295.33,178L297.33,177L298.33,176L302.33,176L307.33,175L313.33,172L318.33,171L323.33,170L327.33,169L332.33,167L336.33,166L339.33,164L343.33,164L348.33,163L350.33,163L356.33,162L361.33,161L367.33,160L369.33,160L373.33,160L376.33,160L381.33,160L388.33,164L392.33,164L393.33,165L397.33,168L399.33,170L403.33,173L407.33,176L410.33,180L411.33,182L415.33,186L417.33,189L418.33,194L421.33,196L421.33,202L421.33,205L421.33,209L421.33,216L421.33,222L421.33,227L421.33,230L421.33,233L421.33,239L421.33,242L421.33,246L421.33,249L420.33,253L419.33,256L418.33,260L417.33,262L415.33,266L413.33,272L411.33,276L408.33,279L405.33,287L401.33,294L399.33,297L397.33,300L395.33,306L393.33,310L390.33,317L388.33,320L385.33,324L383.33,329L379.33,334L372.33,342L369.33,346L364.33,350L358.33,356L352.33,360L348.33,362L341.33,367L333.33,370L327.33,373L321.33,373L318.33,376L317.33,376L317.33,376L316.33,376L315.33,376L314.33,376L313.33,376L313.33,376L312.33,376L309.33,374L306.33,373L304.33,371L301.33,370"/>
        <path stroke="#2c8bc4" width="40" d="M163.33,369L162.33,369L160.33,369L157.33,370L156.33,372L150.33,375L142.33,382L131.33,388L123.33,392L122.33,393L123.33,394L125.33,394"/>
        <path stroke="#2c8bc4" width="40" d="M216.33,406L217.33,406L218.33,406L216.33,415L208.33,428L203.33,436L203.33,440"/>
        <path stroke="#2c8bc4" width="40" d="M300.33,426L301.33,429L301.33,441L300.33,453L300.33,460L300.33,460L300.33,461L300.33,462"/>
        <path stroke="#2c8bc4" width="40" d="M387.33,406L387.33,406L391.33,406L395.33,410L400.33,418L404.33,426L408.33,434L410.33,437"/>
        <path stroke="#2c8bc4" width="40" d="M430.33,364L431.33,364L435.33,364L441.33,364L450.33,365L471.33,375L485.33,380L489.33,381L489.33,381L491.33,381L491.33,381"/>
        <path stroke="#2c8bc4" width="40" d="M473.33,298L473.33,297L474.33,296L479.33,296L485.33,296L497.33,293L513.33,290L521.33,288"/>
        <path stroke="#2c8bc4" width="40" d="M483.33,218L483.33,216L486.33,216L490.33,216L497.33,214L511.33,209L526.33,202L539.33,195L543.33,193L542.33,193L539.33,193"/>
        <path stroke="#2c8bc4" width="40" d="M472.33,149L471.33,148L475.33,146L484.33,141L493.33,137L499.33,135"/>
        <path stroke="#2c8bc4" width="40" d="M422.33,103L423.33,103L423.33,102L431.33,96L445.33,82L454.33,72L454.33,72"/>
        <path stroke="#2c8bc4" width="40" d="M363.33,98L363.33,97L363.33,94L361.33,86L357.33,69L353.33,56L352.33,51L351.33,51"/>
        <path stroke="#2c8bc4" width="40" d="M293.33,113L293.33,113L293.33,112L292.33,106L292.33,97L292.33,82L292.33,70L292.33,58L292.33,52"/>
        <path stroke="#2c8bc4" width="40" d="M209.33,91L209.33,88L209.33,78L197.33,57L191.33,46L191.33,44"/>
        <path stroke="#2c8bc4" width="40" d="M159.33,110L155.33,108L145.33,100L135.33,92L126.33,86L121.33,84L120.33,84L119.33,84"/>
        <path stroke="#2c8bc4" width="40" d="M113.33,167L112.33,169L108.33,169L105.33,169L102.33,168L97.33,166L86.33,161L64.33,153L56.33,150L53.33,149L53.33,149L53.33,149L54.33,149L55.33,149"/>
        <path stroke="#2c8bc4" width="40" d="M91.33,215L89.33,216L87.33,218L85.33,219L85.33,220L79.33,222L61.33,227L37.33,230L23.33,232L18.33,232L18.33,232"/>
        <path stroke="#2c8bc4" width="40" d="M86.33,273L86.33,274L86.33,275L81.33,281L59.33,292L39.33,302L29.33,305L28.33,305L32.33,305L33.33,305"/>
        <path stroke="#2c8bc4" width="40" d="M107.33,324L109.33,324L103.33,328L92.33,334L83.33,338L81.33,339"/>
    </page>
</onep>

OneP フォーマットの拡張計画

  • 今後、OnePフォーマットを拡張し、9VAeの全データを保存できるようにしたいと考えています。今、9VAeは、SVG形式で保存していますが、ブラウザで再生できるようにするため、かなり複雑な構造です。それをもっと可読性の高いテキストフォーマットで保存したいと思っています。
2
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?