LoginSignup
0
3

More than 3 years have passed since last update.

part1「璃奈ちゃんボード」をiPadだけで自作する

Last updated at Posted at 2021-03-15

動画

はじめに

最近りなちゃんボードを自作する人が増えていますが、マイコンを使ったり、3Dプリンターを使ったりするのは難しそう……高校生の璃奈ちゃんがあんな短期間で工作出来るわけないだろ、と思う方も多いでしょう。
私もそう思ったので、より現実的に、iPadやiPhoneだけで「りなちゃんボード」を再現(表示)するプログラムを作りました。
 コンセプトは、
誰でも,簡単に,どんな時でも使える璃奈ちゃんボードです。
使用する言語はpython3.xのみです。

必要なもの

  • iOS、iPadOSアプリ「Pythonista3」(1200円)
  • iPhoneやiPad(原寸大で作るためには9.7インチか、10.2インチ、11インチのiPadが必要)

たったこれだけ!

1200円のアプリは確かに高いですが、このアプリを入れるだけでほとんどのpythonプログラムが実行できるので、初心者の方も玄人の方もおすすめです。今回はPythonista に入っているuiモジュールを使うので必須となります。

用件定義

りなちゃんボードとは

 「ラブライブ!虹が咲学園スクールアイドル同好会」内に登場する高校1年生の女の子、天王寺璃奈は人前で感情を伝えることが大の苦手。そこで、様々な自分の表情を描いた「璃奈ちゃんボード」を常備し、それを顔前に掲げることで相手に思いを伝え易くなった。日常生活ではスケッチブックに描いたボードを使っているが、ライブの時には画面のついたヘッドセットを装着し、音楽に合わせて様々な顔を表示するボードを使う。
 今回はこのボードの画面を完全に再現しようと思う。

ボードの仕様

 ボードのマス目の数はアニメ、ゲーム漫画など、媒体により画面比が異なっているが、ここではアニメ版の画面比構成を採用する。
 すなわち、実質的な描画領域は横32マス×縦18マスくらいの長方形で、領域の外にも白マスが途切れなく続いている。

参考写真

FB965227-233B-4FDC-AA2A-C7FEB6BFCF89.jpeg
F270C791-9980-40AD-9A81-F27E59BEE2B2.jpeg
71C57C12-5D23-4C9B-B5D8-FB0D0839FC35.jpeg

機能

<実装する機能>

  • 画面上のドット絵で顔を表現(これは必須!)
  • 時間経過に応じた遅延のないアニメーション
  • 曲に合わせたり、セリフに合わせたりなど、様々な場面で使えるように、スクリプトを簡略化。作業時間を短縮する。

<いつか実装したい機能>

  • BlueToothLEを用いた通信を行うことで、マイコンや3Dプリンターで作った本物の「璃奈ちゃんボード」と接続。データをリアルタイムで出力する。(Pythonista3はBluetooth通信ができるので理論上可能)

実践(試行錯誤)

顔の描画方法

 とりあえず、まずはドット絵だけでも再現しようと思い、2日間の試行錯誤の末以下のようになった。
 18×32個のボタンを並べ、押したところがピンク色に変化するだけ。16078A7E-3683-4910-AAB9-970653DA5B49.jpeg
どこに色が付いているか分かるように左上のマスを基準にして座標を設定。B177EC23-8F49-4092-A7AC-5DBE99B6921B.png
折角作ったこの顔を残せないのは勿体ない……

ヨシ、csvファイルにして保存しよう!
133203D7-0116-488A-9CDF-24BBA06AE649.jpeg

ピンク色になっているボタンの座標を1行に列挙してcsvに保存する。次回このcsvファイルを読み込めば、この顔が表示される。
そしてこれを何行も書いていけば、顔をスライドショーのように表示できるのだが……↓
83DF992B-63F4-4804-A883-CE191FA79A49.png

  • 見づらい!
  • 1つの顔を表示するための文章量が大きい。
  • データを見ただけで、どんな顔が表示されるのか分からない。
  • 顔を部分的に修正することが困難(例えば、「目」のパーツだけを変えたいとき、顔全体を作り直す必要がある)。

など、問題点が多い。
これでは「使いやすい璃奈ちゃんボード」というコンセプトに合わない。

 そこで思いついたのがプリセットの登録機能である。
よく使う「目」や「口」のパーツを別ファイルに登録しておいて、短い単語で簡単に呼び出せる(表示できる)ようにすれば良い。

mouth1,mouth2などの名前をプリセットに登録して…
367E0E88-06D5-4973-AD1D-D4188E97D49C.jpeg
EE235303-F6CB-4085-8690-63BC3F4A45D8.jpeg
55E7C296-7F38-49C2-920E-EC114F1AE849.jpeg

実際に使う時には↓
4FEAE9EC-1688-4224-80A7-DD4DDEA676AA.jpeg
このわずか4行で、顔を上から順に4種類表示するスクリプトが書けた。(表示時間は3秒ずつ)

プリセット一覧は別の記事で

デザイン

ここで画面のデザインも本物そっくりに作り直し。

(アンカーポイントの設定が曖昧で、端のマスが切れているところも再現した)
もう少しいい顔はなかったのだろうか...
F36AC497-0F9D-431B-99D2-03B9AAA54483.png

 白の正方形の図形ノード(Pythonista3ではShapeNode)を端まで敷き詰めて、各ブロックの背景色をピンクと白に切り替えてドット絵を表現している。
9F13DB99-6C41-43AD-AAE4-2E804A3E0CEF.png
ボード外枠の画像を付けるとこんな感じ↓
 背景色を白→灰色にしてみた。
3EA6E312-7E45-4AB0-945C-9F3AA533C451.png
璃奈ちゃんボード、「にっこりん❤️」
258FD215-8A6F-4BF4-BAC6-35F1BFC321D6.png

 

導入方法(まずは再生するところまで)

配布しているデータについて

 課題曲はアニメ第6話挿入歌「ツナガルコネクト」。私はこのMVを見て璃奈ちゃんボードの制作を志しました。
最初の40秒だけ再現しています。

ダウンロード方法

ファイルに保存してから、zipを解凍。

  • iPadの場合、マルチタスクの状態でドラッグして配置
    イメージ.gif

  • RinachanBoard.pyを実行する
    6A9EBE9E-97BB-465F-A61A-078A46E91BC5.jpeg
     
     

  • 音源とスクリプトを選択する。
    93E8E173-A26D-466B-BC10-38470F817AB6.jpeg

 connect.csvRinachan.aiffを選択してチェックマークをタップ

タイミング(誤差)調整作業
  • 起動後、画面中央をタップ(端をタップすると別機能が起動します)。最後までスクリプトを再生する。

<この時点では時間の誤差、上下左右のずれがあるので、これから補正します>

  • 画面右上の×で実行を終了して、コンソールをチェックする。たくさんの数字の羅列が出力されています。

13E3C8CE-DC15-40B4-B987-51DFF43E471E.jpeg
 これは、スクリプトに書いてある時間と、実際に描画が完了した時間の誤差です。各フレームごとについて出力されています。正の値はスクリプトより遅い、負の値は早いことを示しています。
 これが0に近づくように調整をします。

 

 RinachanBoard.pyの始めの部分にはパラメータの変更をする場所があります。
今回は、写真の26行目timedurationに誤差(秒)を入力します。負の値は表示を早め、正の値は表示を遅らせます。(わざわざ表示を遅らせる人は少ないと思うので、多くの人は負の値を記入すると思います。)
9998C68A-E9A0-4F46-8E6F-5E9B1540B323.jpeg

 (参考までに、iPadPro 11インチでは-0.02で丁度良くなりました。)

位置調整作業

 続けて、表示される顔の上下左右のズレを直します。変更するパラメータはoffsetXoffsetYです。
34,35行目に移動するピクセル数を入力します。しかし、このままではどれくらいズラせば良いのかわかりません。
 そんなときに役に立つのはDEBUGMODEです。DEBUGMODE=Trueとすることで起動画面に1ブロック(1ドット)のサイズを表示してくれます。(サイズは端末の大きさに応じて自動計算されます)3CD222A6-378B-492B-A092-6BB0D9F44B8A.jpeg

 例えば、1マス41ピクセルで2.5マス分ずらしたいときは、41*2.5=102.5ピクセルずらせば良い、という感じです。 

操作方法(基礎編)

  • 起動後、「チャリーン♪」となったら読み込み完了です。画面のどこか(デバッグモードの時は、画面中央)をタップすると再生が始まります。

  • 再生中に画面を数回タップするともう一度最初から再生します。

  • 〈デバッグモードのみ〉再生中に画面右端をタップすると1つ先のフレームに進みます。左端をタップすると1つ手前のフレームに戻ります。(まだバグが残っていて、表示が乱れることがあります)

設定できる項目一覧

RinachanBoard.pyの始めの部分にはいくつか調整できるパラメータがあります。必要に応じて弄ってください。

RinachanBoard.py(抜粋)



'''
###########↓設定/config##########
'''

scriptFile='connect.csv'
musicFile='Rinachan.aiff'
timeduration=-0.02#時間ズレ補正,単位は秒
sizemode=0      #0:縦幅を基準 1:横幅を基準に合わせます。横画面時は0が規定値
DEBUGMODE=True    #True,False
boadcolor=[('#cccccc'),('#d00fd9')]#ボードの色[白,ピンク]   
linecolor='#eaeaea'    #枠線の色.   line's color


offsetX=42#x軸ズレ補正
offsetY=-10#y軸ズレ補正
blockSize=0#ブロックのサイズ。0の時、自動設定

'''
##########↑設定ここまで##########
'''


  • scriptFile:使用するスクリプトのファイル名を入れる。拡張子(.csv)も忘れずに。
  • musicFile:音源のファイル名を入れる
  • timeduration:時間補正(前述)
  • sizemode:横画面の時は0が良い
  • DEBUGMODE:デバッグ画面を出したい時はTrue、消す時はFalse
  • boadcolor:ボードの色を設定。list形式になっていて、形は[白,ピンク]
  • linecolor:ブロックの輪郭線の色を設定
  • offsetX:位置補正(前述)大きくすると右に動く
  • offsetY:位置補正(前述)大きくすると上に動く
  • blockSize:本来、端末の画面サイズに応じて一つ一つのブロックのサイズが自動設定されるが、手動で設定したい時はこの値をいじる。

コード

一応載せておきますが、長いので折りたたみ。上のリンクからダウンロードした方が早い。
qiita.py

from scene import *
import sound
import random
import math
import ui
import csv
import  re
import time
import ast
'''
#####################
璃奈ちゃんボードビューアー ver2.8
Rina-chan Board Viewer ver2.8
#####################
Created by @NSmagnets 
If you find any bugs,please inform me on Twitter(@NSmagnets)

使い方/How To Use
1、準備中……

###########↓設定/config##########
'''

scriptFile='connect.csv'#connect.csv
musicFile='Rinachan.aiff'
timeduration=-0.02#時間ズレ補正,単位は秒
sizemode=0      #0:縦幅を基準 1:横幅を基準に合わせます。横画面時は0が規定値
DEBUGMODE=False    #True,False
boadcolor=[('#cccccc'),('#d00fd9')]#ボードの色[白,ピンク]   Board's Color[(white),(pink)]
#boadcolor=[('#ffffff'),('#b700bf')]
linecolor='#eaeaea'    #枠線の色.   line's color
#boadcolor=[('#c9c9c9'),'#f400ff']

offsetX=42#x軸ズレ補正
offsetY=-10#y軸ズレ補正
blockSize=0#ブロックのサイズ。0の時、自動設定

'''
##########↑設定ここまで##########
'''



























#


'''
#「script」「music」というファイルを作り、そこにスクリプト(csv)と曲(wavなど)を入れれば、
#ファイルが整理されます。その際には' ' 'を削除してください
scriptFile='./script/'+scriptFile
musicFile='./music/'+musicFile
'''


global scene
color=[]#[9_9,2_3,3_4]
boforecolor=[]
global boad

class boad  (SpriteNode):
    def setup(self):
        bby = SpriteNode('ii.jpg', position=(self.size.w/2, self.size.h/2))
        #SpriteNode(self, 'shp:RoundRect', **kwargs)
        self.add_child(bby)
class MyScene (Scene):

    def csv_import(self):
        tapp=[]
        ee=[]
        self.boadU=[]
        #bill=[]
        self.preset={}
        self.dataprev=[]
        with open('preset.csv') as f:
            reader = csv.reader(f)
            l=[row for row in reader]
            #print(l)
            for yo in range(len(l)):
             #print(l[yo])
             #preset.update(dict(l[yo]))
             p=str(l[yo]).replace('["', '')
             q=p.replace('"]','')
             #m=q.replace('"','')
             s1=q.replace("/'",'')

             ss=ast.literal_eval(s1)
             self.preset.update(ss)
        with open(scriptFile) as f:
            reader = csv.reader(f)
            l=[row for row in reader]
            #self.deta=l
            #print(l)
            for yo in range(len(l)):
             if '<' in l[yo][0]:
              pass
             else:
              self.dataprev.append([l[yo]])
              tapp=[]
              ee=[]
              #a=int(l[yo][0])
              a=int(yo)
              k=l[yo][1]
              b=l[yo][2]
              c=float(l[yo][3])
             #print(type(k))
            #reader2= csv.reader(l)
            #for row in reader2:
              if '_' in k:
               p=k.replace('(', '')
               q=p.replace(')','')
               m=q.replace('"','')
               s=re.split(', ',m)
              else:
               p=re.split('//',k)
               #print(p)
               for e in p:
                qq=[self.preset[e][e1] for e1 in range(len(self.preset[e]))]
                ee.extend(qq)
               #print(ee)
               s=[uu for uu in ee]#配列外しの0。変更禁止
              #print(s,'s')

              for i in s:
               if type(i)==tuple:
                s1=str(i).replace("('",'')
                s2=s1.replace("')",'')
                s5=re.split('_',str(s2))
                s6=[re.sub('\\D','',ty) for ty in s5]
               #print(s6)
               else:
                s2=i.replace("/'",'')
               # s11=s1.replace("")
                s4=re.split('_',str(s2))

              #s5=ast.literal_eval(s4)

               s3=(int(s4[0])-1,19-int(s4[1]))#***+1,,19-***
               tapp.append(s3)
              #print(tapp)
              self.boadU.append([a,tapp,b,c])
              print(l[yo])

        #print(self.dataprev)
        #print(boadU[0][2])



    def setup(self):
        global offsetX,offsetY
        print(self.size.h)
        if blockSize==0:
         c=41#36.7
         c=(self.size.h//21)+2
         if sizemode==1:
          c=(self.size.w//30)
         elif sizemode==2:
          c=35
          offsetX=120
          offsetY=0
          timeduration=0.03

        else:
         c=blockSize

        self.alltime=0.0
        self.epoctime=0.0
        self.duration=0.0
        self.ready= False
        self.boad=[]
        self.block={}
        self.playing=False
        self.background_color = '#d9d9d9'
        #self.background_color = 'black'
        colorNo=0
        self.scenes=0
        self.touchcount=0
        #self.music=musicFile
        self.debugmode=DEBUGMODE
        self.onlights=[]
        self.offlights=[]
        self.dataprev=[]
        path = ui.Path()
        path.line_width = 3
        path.move_to(0, 0)
        #path.line_to(200, 0)
        path.line_to(0, self.size.h)
        path.close() 

              #②
        path2=ui.Path()
        path2.line_width = 1
        path2.move_to(0, 0)
        #path.line_to(200, 0)
        path2.line_to(0, c)
        path2.line_to(c, c)
        path2.line_to(c, 0)
        path2.close()
        #path = ui.Path.rect(0, 0, c, c)
        for x in range(34):

            for y in range(28):
                self.rectangle3=ShapeNode(path2,fill_color=boadcolor[0],stroke_color=linecolor,position=(c*(x-1)+offsetX,c*y+offsetY))
                #self.rectangle = SpriteNode(boadtex[0], position=(c*x+10, c*y))
                z=(x,y)
                self.boad.append([z,colorNo])
                self.block[z]=self.rectangle3
              #④
                self.add_child(self.rectangle3)
        self.rectangle3.fill_color=boadcolor[1]
        z=(7,9)
        '''

        '''
        self.boadcopy=self.boad
        if self.debugmode==True:
         score_font = ('Futura', c*1)
         self.score_label = LabelNode('0', score_font, parent=self)
         self.score_label.position = (self.size.w / 2, self.size.h - 120)
         self.score_label.z_position = 1
         self.score_label.color='#0016ff'
         self.add_child(self.score_label)
         self.score_label.text='DEBUG MODE ver2.8 block='+str(c)
         self.triangle2 = ShapeNode(path,fill_color='#66ffc3', stroke_color='#18a56e',position=(self.size.w/2, self.size.h/2), parent=self)
         self.add_child(self.triangle2)
         #self.block[z].texture=boadtex[1]
         sound.play_effect('arcade:Coin_2')
        self.csv_import()
        #sound.play_effect('arcade:Coin_1')
        for i in range( len(self.boadU)):   
         self.preload(i)
        #print(self.onlights)
        del offsetX,offsetY
        if sizemode==2:
         bby = SpriteNode('boad.png', position=(self.size.w/2, self.size.h/2),size=(self.size.w,self.size.h))
        #SpriteNode(self, 'shp:RoundRect', **kwargs)
         self.add_child(bby)
        sound.play_effect('game:Ding_3')
    def preload(self,scene):
         global color

         #scene=scenepic.text
         on=[]
         off=[]
         boforecolor=color
         color=[]


         #for r in len(boadU):
         #if scene== len(boadU):
         #print('heheheowowowoowo')
         v=self.boadU[int(scene)][1]
         duration=self.boadU[int(scene)][3]
         #t = threading.Timer(float(duration)-0.05,lambda:autoupdate(sender , int(scene)+1) )
         #clear(sender)
         #for qq in range():

         for www in self.boadcopy:
          we=www[0]
          #buttonbg= sender.superview[we]
          if [we,0] in self.boadcopy:
           ww=self.boadcopy.index([we,0])
          else:
           ww=self.boadcopy.index([we,1])
          #tt=colored[ww]
          self.boadcopy[ww:ww+1]=[[we,0]]
          #print(self.boad)
          #buttonbg.background_color= ('#ffffff')
 #vv=list(v)
         '''colored
         '''
 #u=sender.name
 #if [uu,False] in colored:
  #ww=colored.index([uu,False])
 #else:'''
         for x in v:
          y=[]


          #y=x.replace('"','')
          #print(colored)
          if [x,0] in self.boadcopy:
           ww=self.boadcopy.index([x,0])
          else:
           ww=self.boadcopy.index([x,1])              
          tt=self.boadcopy[ww]
          #buttonbg= sender.superview[y]
          #self.boad[ww:ww+1]=[[x,1]]
  #buttonbg.background_color= ('#fb99ff')
          color.append(self.boadcopy[ww][0])
  #tup
         if boforecolor==None:
          pass
         else:
          for bef in boforecolor:
           #buttonbg=sender.superview[bef]
           if bef in color:
             pass
           else:
            #self.block[bef].fill_color=boadcolor[0]
            off.append(bef)
            #buttonbg.background_color= ('#ffffff')

         for co in color:
          #buttonbg=sender.superview[co]
          if co in boforecolor:
            pass
          else:
            #self.block[co].fill_color=boadcolor[1]

           on.append(co)
            #buttonbg.background_color= ('#fb99ff')

         self.onlights.append(on)
         self.offlights.append(off)


         #ssd=(time.time()-self.epoctime-self.alltime+self.duration)

         #print('.                     .',ssd,self.scenes,str(self.checkcolor)+'Blocks')




    def autoupdate(self,scenes):
         global color

         #scene=scenepic.text

         boforecolor=color
         color=[]
         self.checkcolor= len(color+boforecolor)
         '''colV= sender.superview['colorView']'''
         #for r in len(boadU):
         #if scene== len(boadU):
         #print('heheheowowowoowo')
         v=self.boadU[int(self.scenes)-1][1]
         duration=self.boadU[int(self.scenes)-1][3]
         #t = threading.Timer(float(duration)-0.05,lambda:autoupdate(sender , int(scene)+1) )
         #clear(sender)
         #for qq in range():

         for www in self.boad:
          we=www[0]
          #buttonbg= sender.superview[we]
          if [we,0] in self.boad:
           ww=self.boad.index([we,0])
          else:
           ww=self.boad.index([we,1])
          #tt=colored[ww]
          self.boad[ww:ww+1]=[[we,0]]
          #print(self.boad)
          #buttonbg.background_color= ('#ffffff')
 #vv=list(v)
         '''colored
         '''
 #u=sender.name
 #if [uu,False] in colored:
  #ww=colored.index([uu,False])
 #else:'''
         for x in v:
          y=[]


          #y=x.replace('"','')
          #print(colored)
          if [x,0] in self.boad:
           ww=self.boad.index([x,0])
          else:
           ww=self.boad.index([x,1])              
          tt=self.boad[ww]
          #buttonbg= sender.superview[y]
          self.boad[ww:ww+1]=[[x,1]]
  #buttonbg.background_color= ('#fb99ff')
          color.append(self.boad[ww][0])
  #tup.append([ww])

         if boforecolor==None:
          pass
         else:
          for bef in boforecolor:
           #buttonbg=sender.superview[bef]
           if bef in color:
             pass
           else:
            self.block[bef].fill_color=boadcolor[0]

            #buttonbg.background_color= ('#ffffff')

         for co in color:
          #buttonbg=sender.superview[co]
          if co in boforecolor:
            pass
          else:
            self.block[co].fill_color=boadcolor[1]
            #buttonbg.background_color= ('#fb99ff')


         ssd=(time.time()-self.epoctime-self.alltime+self.duration)

         print('.                     .',ssd,self.scenes,str(self.checkcolor)+'Blocks')
         if self.debugmode==False:
          pass
         else:
          sse=int(ssd*1000)
          #wwq=time.time()-self.epoctime-self.alltime+self.duration,self.scenes,str(self.checkcolor)
          self.score_label.text=str(self.dataprev[self.scenes-1])+str(self.scenes)+'  '+str(sse)



         #colV.text = str(v)
#t.start()


        #AutoUpdateNEO

    def autoupdate2(self,scenes):
         global color


         if self.offlights==None:
          pass
         else:
          for bef in self.offlights[self.scenes]:
           self.block[bef].fill_color=boadcolor[0]
         for co in self.onlights[self.scenes]:
          self.block[co].fill_color=boadcolor[1]
         self.scenes+=1
         ssd=(time.time()-self.epoctime-self.alltime+self.duration)
         print('.                     .',ssd,self.scenes)
         if self.debugmode==False:
          pass
         else:
          sse=int(ssd*1000)
          self.score_label.text='Auto'+str(self.dataprev[self.scenes-1])+str(self.scenes)+'  '+str(sse) 


    def timekeep(self,scenes):
         if self.scenes==len(self.boadU):
          self.ready=False
          self.playing=False
          pass
         else:
          self.duration=self.boadU[int(self.scenes)][3]
          self.alltime =self.alltime + self.duration
          self.autoupdate2(self.scenes)



    def colorchange(self):
            #print(self.boad)
            pass

    def did_change_size(self):
        sound.stop_all_effects()
        self.ready=False
        self.playing=False
        #self.remove_all_actions()
        #self.setup()
        pass

    def update(self):
        #self.T=time.time()

        #print(self.T)
        if self.ready == True:
         if self.alltime+timeduration<= time.time()-self.epoctime:
          self.timekeep(self.scenes)





    def touch_began(self, touch):

        if self.playing==False:
          global offsetX,offsetY,blockSize,linecolor,sizemode,scriptFile
          try:
           del offsetX,offsetY,blockSize,linecolor,sizemode,scriptFile
          except :
           pass
          self.scenes=0
          self.alltime=0.0

          for qwe in self.block.values():
           qwe.fill_color=boadcolor[0]
          sound.stop_all_effects()
          sound.play_effect('arcade:Coin_4')

          time.sleep(1)
          ee=time.time()
          sound.play_effect(musicFile)
          print(time.time()-ee)
          t=touch.location
          print(t)
          self.playing=True
          self.ready=True
          self.epoctime=time.time()
          self.timekeep(0)
        else:
         self.touchcount+=1
         if self.touchcount==3:
          self.playing=False
          self.touchcount=0

         pass
        t=touch.location.x
        if self.debugmode==False :
            pass
        else:

         if self.scenes==len(self.boadU):

          self.ready=False
          self.playing=False
          pass

         else:

          if self.size.w*0.1>=t:
            print('prev')
            self.ready=False
            #self.playing=False
            self.touchcount=0
            self.scenes= self.scenes-1
            #for qwe in self.block.values():
             #qwe.fill_color=boadcolor[0]
            self.autoupdate(self.scenes-1)

          else:
           if self.size.w*0.8<=t:
            print('next')
            self.ready=False
            #self.playing=True
            self.touchcount=0
            self.autoupdate2(self.scenes)

        print(t)
    def stop(self):
     sound.stop_all_effects()

    def touch_moved(self, touch):
        pass

    def touch_ended(self, touch):
        pass

if __name__ == '__main__':
    run(MyScene(),'portrait', show_fps=True)


次回予告

長くなったので今回はここまで。次は、スクリプトファイルの作り方、を紹介します。

0
3
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
0
3