本記事はPythonistaのsceneライブラリの使い方について紹介するものです。
今回は、スマホをタッチした時の処理の実装方法について説明します。
具体的には以下の2点です。
・Pythonista+sceneタッチ(タップ)の基本メソッド
・Pythonista+sceneタッチ(タップ)の応用編
目次
Pythonista+sceneタッチ(タップ)の基本メソッド
Pythonistaのsceneライブラリで使用できるタッチに関するメソッドは以下の3つです。
・touch_began():タッチした時に処理を実行する
・touch_moved():フリックした時に処理を実行する
・touch_ended():スマホから指を離した時に処理を実行する
いずれのメソッドも未定義にすることが可能です。
メソッドが複数定義されている場合は、
touch_began()→touch_moved()→touch_ended()
の順に処理されます。
引数の「touch」からはタッチした位置情報を取得できます。
touch_began():タッチした時に処理を実行する
touch_began()はスマホをタッチした時に処理を実行するメソッドです。
「瞬間的にタッチした場合」、「フリック入力した場合」、「長押しした場合」のすべてで実行されます。
スマホタッチ処理の基本となるメソッドです。
まずはこのメソッドの使い方を覚えましょう。
◆記述例
1 2 3 4 5 6 | from scene import * class MyScene (Scene): def touch_began(self, touch): # タッチした時に処理を実行 pass |
touch_moved():フリックした時に処理を実行する
touch_moved()はスマホをタッチした場合(フリックした場合)に処理が実行されるメソッドです。
「瞬間的にタッチした場合」や「長押しした場合」には処理されません。
指がちょっとでも動くと呼び出されてしまうので扱いが難しいメソッドです。
スマホの画面を長押ししている時に指がずれて「touch_moved()」が動いてしまう場合もあります。
◆記述例
1 2 3 4 5 6 | from scene import * class MyScene (Scene): def touch_moved(self, touch): # フリックした時に処理を実行 pass |
touch_ended():スマホから指を離した時に処理を実行する
touch_ended()はスマホから指を離したときに処理が実行されるメソッドです。
「瞬間的にタッチした場合」、「フリック入力した場合」、「長押しした場合」のすべてで実行されます。
画面から指を離すまでは何も実行されません。
◆記述例
1 2 3 4 5 6 | from scene import * class MyScene (Scene): def touch_ended(self, touch): # 画面から指を離した時に実行 pass |
Pythonista+sceneタッチ(タップ)の応用編
「touch_began()」、「touch_moved()」、「touch_ended()」の3つをそのまま使うだけではあまり複雑な操作は実装できません。
「複数のアクションを実装したい場合」や「タッチした長さで処理を変えたい場合」などは工夫する必要があります。
ここからは少し応用的な使い方を紹介します。
具体的には以下の通り。
・タッチの長さで処理を変える
・タッチできる範囲に絞る
長押しで処理を変える
アクションゲームでよくある「溜めうち」や「溜めジャンプ」などタッチした長さで処理を変える方法について説明します。
上記の通りタッチの長さで処理を変えるメソッドはありません。
よって長押しで処理を変えたい場合は一工夫が必要です。
以前に以下のツイートでも方法を紹介しました。
Pythonista+sceneでスマホ画面をタッチした長さによって処理を変える
・touch_began()でカウントフラグを立てる
・update()で毎周カウントアップする
・touch_ended()でカウントを見て処理を変える#プログラミング#Python— みやびの@miyabino.py (@miyabikno) December 17, 2019
Pythonista+sceneでスマホ画面をタッチした長さによって処理を変える
・touch_began()でカウントフラグを立てる
・update()で毎周カウントアップする
・touch_ended()でカウントを見て処理を変える
上記の具体的な実装方法について説明します。
◆1.touch_began()でカウントフラグを立てる
まずはスマホをタッチしたタイミング(touch_began()の処理タイミング)でカウントアップフラグを立てます。
タッチした瞬間にやる処理はこれだけです。
◆2.update()で毎周カウントアップする
カウントアップフラグが立っている場合のみカウントアップします。
◆3.touch_ended()でカウントを見て処理を変える
指を離したタイミング(touch_ended()の処理タイミング)でカウントの値を見て処理を変えます。
カウントのたまり具合によって2パターン以上の処理にわけることが可能です。
タッチできる範囲に絞る
「touch_began()」などのメソッドをそのまま実装すると画面全体がタッチ操作を受け付けます。
このまま使うとあまり多くのアクションは実装できません。
タッチの範囲に絞ることでタッチした範囲によってアクションをわけることができます。
・ボタンをタッチした場合は攻撃
・ボタン以外の場所をタッチした場合はジャンプ
など。
長押しとボタン設置の実装例
長押しとボタン設置の実装例について紹介します。
◆プログラム概要
ボタンを短く押すと小さなジャンプ。
ボタンを長く押してから離すと大ジャンプできます。
ボタン以外の場所にタッチしても何も起きません。
コードは以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | # coding: utf-8 from scene import * from sound import * class Game (Scene): def setup(self): # バックグラウンド設定 self.background_color = '#004f82' ground = Node(parent=self) x = 0 # 地面の高さ self.base_height = 50 # 背景の設定 while x <= self.size.w + 64: tile = SpriteNode('plf:Ground_Planet', position=(x, self.base_height)) ground.add_child(tile) x += 64 # プレイヤーの初期設定 self.player_height = self.base_height + 32 self.player = SpriteNode('emj:Ghost') self.player.anchor_point = (0.5, 0) self.player.position = (self.size.w/2, self.player_height) self.add_child(self.player) # ジャンプボタンの初期設定 self.jump = 'ready' self.jump_button = SpriteNode('emj:Blue_Circle', position=(320,50)) self.add_child(self.jump_button) self.charge = False self.power = 0 def update(self): g = gravity() x = self.player.position.x y = self.player.position.y # 左右の移動 if abs(g.x) > 0.05: max_speed = 40 x = max(0, min(self.size.w, x + g.x * max_speed)) self.player.position = (x, y) self.check_jump(x,y) if self.charge and self.power < 100: self.power += 1 def touch_began(self, touch): # フラグを立てる self.charge = True def touch_ended(self, touch): # タップした位置の取得 touch_loc = self.point_from_scene(touch.location) # タップした位置がボタンならジャンプ if touch_loc in self.jump_button.frame: if self.jump == 'ready': play_effect('game:Boing_1') self.jump = 'up' def check_jump(self, x, y): # 上昇時の処理 if self.jump == 'up': max_height = 180 + self.power up_speed = 10 y = max(self.player_height, min(self.size.h, y + up_speed)) self.player.position = (x, y) if y > max_height + self.player_height: self.jump = 'down' # 落下時の処理 if self.jump == 'down': down_speed = 10 y = max(self.player_height, min(self.size.h, y - down_speed)) self.player.position = (x, y) if y == self.player_height: self.jump = 'ready' self.charge = False self.power = 0 if __name__ == '__main__': run(Game(), PORTRAIT, show_fps=True) |
◆実行例
画面キャプチャなのでわかりにくいですが、長押し大ジャンプが可能で高い位置の星も取れます。
※アイテムを取る処理は今回のコードだけでは実現できません。
アイテムを取る処理については「Pythonista+sceneで当たり判定を作成する方法」をお読みください。
終わりに
Pythonistaのsceneライブラリで使用できるタッチに関するメソッドは以下の3つです。
・touch_began():タッチした時に処理を実行する
・touch_moved():フリックした時に処理を実行する
・touch_ended():スマホから指を離した時に処理を実行する
上記メソッドをそのまま使うだけだとできることがあまり多くありません。
しかし、update()で監視したりタッチの範囲を絞ったりすると、タッチ操作だけでもかなり複雑な処理を作ることができます。
本記事やサンプルゲームも参考にしつつ試行錯誤をしてみてください。
Pythonistaについては「Pythonistaの使い方まとめ」にまとめています。