はじめに
今回は、タイピングゲームのためのPythonモジュールを作ったので、紹介したいと思います。そもそも作ろうと思ったきっかけですが、筆者が高校生のころから寿司打ヘビーユーザーというのもあり、タイピングゲームに興味があったこと。Pythonで、複数パターンの入力に対応したタイピングゲームを作ってる人が、見られなかったこと。この2つになります。
コンセプト
とにかく使いやすさを重視しています。print('HelloWorld!!')
レベルの手軽さが理想ですが、ゲーム画面の描画と、キーイベントの検知もこちらで実装すると、あまりにも自由度が低すぎます。したがって、これらの機能をどのモジュールで実装するかは、各自に委ねる形にしました。音声なども扱えますし、個人的にはpygame
がおすすめです。(単に筆者の好みです。typehandler
の機能的に、pygame
と相性が良いという事ではありません。)
参考にしたサイト
こちらのサイトを真似させてもらい、チャンクというのを使った方法を採用しています。どうやって判定していくのかについては、こちらのサイトに載っているので、割愛させてもらいます。筆者がメインにやったことは、それらをPythonに落とし込んで、機能ごとに使いやすくまとめるってだけです。とりあえずタイピングゲームを作りたいだけだから、モジュールがあるならそれでいいや、という方はこのままお進みください。自分で実装したいんだ!という人はこちらのサイトへどうぞ。
インストール方法
以下の名前でpipできます。
pip install typehandler
最新版は0.3なので、もしも0.1や0.2がインストールされていたら、以下のようにしてください(0.1と0.2はPyPIに不慣れ故に動かなかったやつです)
pip install typehandler==0.3
メソッドの一覧
とりあえず使いたいだけの人は、次の項目にサンプルコードを置いてあるので、この項目は飛ばしてください。あと細かい使い方はREADMEの方に載せてあります。
READMEこちら
divide(hurigana: str) -> List[str]
ひらがなだけの文字列を受け取って、入力パターンのリストを返します。自分で別の判定方法などを実装したい場合に、こちらを活用していただけます。
他のメソッドも見る
set_new_sentence(words: Dict[str, str] = None) ->None
別の文章に変更するためのものです。例えば時間制限に引っかかったり、文章を打ち終わったら、これを呼び出すみたいな使い方を想定しています。引数に辞書を渡すと、その辞書から新しい文章を選びます。
set_new_words(words: Dict[str, str]) ->None
別の辞書をセットします。これを呼び出すと、その時点で文章も再設定されます。
check_correct_input(key: str) ->bool
キーの名前を受け取って、そのキーが入力パターンにあればTrue
, なければFalse
を返します。if
の条件として使うことを想定しています。
check_chunk_completion() ->bool
こちらもif
の条件として使うことを想定しています。check_correct_input
がTrue
を返した後、こちらでひらがなを打ち終わったかどうか判定します。ひらがなを打ち終わっていたらTrue
、いなければFalse
を返します。
check_sentence_completion() ->bool:
こちらもif
の条件として使うことを想定しています。check_chunk_completion
がTrue
を返した後、こちらで文章を打ち終わったかどうか判定します。文章を打ち終わっていたらTrue
、いなければFalse
を返します。
update_show_roman() ->str
現在入力してあるところまでを基に、入力パターンの一例を返します。常に最新の状態にするために、ゲームループ中で毎回呼び出すことをお勧めします。
main() ->None
特に音声などを付けないのであれば、これを呼び出すだけで、正誤判定から文章の打ち終わりまで判定して文章の更新もしてくれます。
その他変数
input
既に入力済みのローマ字
show_roman
入力パターンの一例
sentence
お題の文章
これらにアクセスできますので、画面にこれらの情報を描画したい時にお使いください。
使用例
import tkinter, typehandler
words = dict(リンゴ = 'りんご',バナナ = 'ばなな',ブドウ = 'ぶどう',レモン = 'れもん')
root = tkinter.Tk()
game = typehandler.Process(words)
def key_pressed(event):
game.main(event.keysym)
print(f'{game.input}\n{game.sentence}')
root.bind('<Key>', key_pressed)
root.mainloop()
↑最小でこんな感じで実装できます。(wordsを変数として宣言しなければ8行になりますが、見づらいので止めました)
import pygame, sys
from typehandler import Process
pygame.init()
screen = pygame.display.set_mode((600, 500))
pygame.display.set_caption('example')
font = pygame.font.SysFont("MSP Gothic", 32)
def vocalize(se):
#音声を再生する
pygame.mixer.init(frequency=44100)
pygame.mixer.set_num_channels(32)
sound_key = pygame.mixer.Sound(se)
sound_key.play()
words = dict(リンゴ = 'りんご',
ブドウ = 'ぶどう',
レモン = 'れもん',
バナナ = 'ばなな',
)
def main():
clock = pygame.time.Clock()
process = Process(words)
while True:
process.update_show_roman()
screen.fill((255, 255, 255))
text_roman = font.render(process.show_roman, True, (192, 192, 192))
text_input = font.render(process.input, True, (0, 0, 0))
text_sentence = font.render(process.sentence, True, (0, 0, 0))
pygame.draw.line(screen, (0, 128, 255), (0, 50), (600, 50), 5) #青い線を描画
pygame.draw.line(screen, (255, 128, 0), (0, 150), (600, 150), 5) #オレンジの線を描画
screen.blit(text_roman, (30,60))
screen.blit(text_input, (30,60))
screen.blit(text_sentence, (30, 100))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
correct_input = process.check_correct_input(pygame.key.name(event.key)) #ミスタイプを判定
if correct_input:
vocalize('input.ogg')
chunk_conpleted = process.check_chunk_completion() #文の打ち終わりを判定
if chunk_conpleted:
sentence_completed = process.check_sentence_completion()
if sentence_completed:
vocalize('next.mp3')
process.set_new_sentence() #新しい文を用意
else:
vocalize('miss.ogg')
pygame.display.update()
clock.tick(50)
if __name__ == '__main__':
main()
もうちょっとまともな例を用意しました。音声の再生とかをするならこのようになります。音声ファイルを用意するのがめんどくさい方は、コメントアウトして、動きだけどんな感じか見てください。先ほどはtkinter
で今度はpygame
を使っている通り、キー入力の判定さえできれば、何のモジュールを使っていただいても構わないです。
ちなみにですが、fpsは50くらいあった方がいいと思います。30も試しましたが、筆者の入力速度でも、たまに追いついてきてくれませんでした。筆者より速い人は60くらい必要だったりするんでしょうか...?世の中には化け物みたいに速い人もいますからね....
参考までに筆者のレベルが分かるものを置いておきます
最後に
ここまで読んでいただきありがとうございました。PyPIに登録してpipできるようにするのが初めてだったので、ちょっと大変でした。ひらがなの辞書の部分を除けば150行くらいしかないので、ブラウザゲームを作りたいから、外部モジュール使えないなーって人は、以下のページからprocess.py
の中身をコピペして使っちゃってください。
ちなみにブラウザゲームの公開方法の記事も出しているので、タイピングゲームを自作して公開までを行いたい方は、この記事と併せてご覧いただけると嬉しいです。(ちゃっかり宣伝)
実際に筆者が公開してみたタイピングゲームはこちらから遊べます