【Python】マッチ棒クイズ開発 Part10

こんにちは、にわこまです。

今回は、実際にマッチ棒を動かすレイアウトを作成していきます。マッチ棒枠を表示したり、問題通りにマッチ棒を配置したり、マッチ棒がマッチ棒枠にカチッとハマるようにしたりするレイアウトを作成していきます。

 

誤字脱字や分からない点がございましたらご連絡お願いいたします!

メールまたはTwitterのDMまで!!

 

 

 

スポンサードサーチ


レイアウトの初期化

まず、実際にプレイする画面のレイアウトを以下に示します。このレイアウトには、問題文やマッチ棒を動かす範囲、回答ボタンなどを配置します。

 

今回作成するマッチ棒を動かすレイアウトは、上記の画像におけるPlayFieldWidgetと書かれた薄い赤色の範囲です。

このレイアウトでは、問題の表示や正解不正解の判定を行います。

 

 

コードの提示

PlayFieldWidgetのinit関数とon_size関数のソースコードを以下に示します。

import kivy
kivy.require("2.0.0")

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.graphics import Color, Rectangle, Ellipse
from kivy.graphics import Rotate
from kivy.graphics.context_instructions import PushMatrix, PopMatrix

import numpy as np

class MatchStickWidget(Widget):
    # 省略

class MatchStickFrameWidget(Widget):
    # 省略

class PlayFieldWidget(FloatLayout):
    def __init__(self, **kwargs):
        super(PlayFieldWidget, self).__init__(**kwargs)
        self.ms_w = 25              # width of matchstick
        self.ms_h = self.ms_w * 6.8 # height of matchstick
        self.base_x = self.center_x - (45 * self.ms_w) / 2
        self.base_y = self.center_y - (17 * self.ms_w) / 2
        self.frameList = []     # List of MatchStickFrameWidget
        self.msList = []        # List of MatchStickWidget
        self.msDict = {}        # Dict of MatchStickWidget
        self.onMoveObj = None
        self.QADict = {}        # {Answer : Question1, Question2, ..}
        self.quesList = []      # List of Question / ex) ["3", "-", "6", "=", "9"]
        self.ansList = []       # List of Answer   / ex) ["9", "-", "6", "=", "3"]
        self.input_ansList = [] # List of Player's Answer
        with self.canvas.before:
                Color(rgb=[1, 1, 1])
                self.bg_rect = Rectangle(pos=self.pos, size=self.size)
    def on_size(self, *args):
        self.base_x = self.center_x - (45 * self.ms_w) / 2
        self.base_y = self.center_y - (17 * self.ms_w) / 2
        self.bg_rect.size = self.size

class RootWidget(FloatLayout):
    def __init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)
        with self.canvas.before:
            Color(rgb=[1, 1, 1])
            self.bg_rect = Rectangle(pos=self.pos, size=self.size)
    def on_size(self, *args):
        self.bg_rect.size = self.size

class MatchStickQuizApp(App):
    def build(self):
        root = RootWidget()
        root.add_widget(PlayFieldWidget())
        return root

if __name__ == '__main__':
    MatchStickQuizApp().run()
    pass

 

上記のコードは以下からダウンロードできます。

 

 

コードの解説

19行目から40行目の「PlayFieldWidgetクラス」は、問題を表示したり、マッチ棒を動かしたりするクラスです。

 

20行目から36行目の「init関数」は、PlayFieldWidgetの初期化を行っています。

 

22行目の「self.ms_w」は、マッチ棒の横幅を指定する変数です。

23行目の「self.ms_h」は、マッチ棒の高さを指定する変数です。

  

24行目の「self.base_x」は、マッチ棒で作られた問題を真ん中に表示するための左下のx座標です。

25行目の「self.base_y」は、マッチ棒で作られた問題を真ん中に表示するための左下のy座標です。

self.base_xとself.base_yは以下の画像の青い点の座標を指しています。

  

26行目の「self.frameList」は、マッチ棒枠オブジェクトをまとめておくための変数です。

 

27行目の「self.msList」は、マッチ棒オブジェクトをまとめておくための変数です。

 

28行目の「self.msDict」は、キーにマッチ棒オブジェクトを代入し、値にそのマッチ棒オブジェクトのposやangleを代入する変数です。

 

29行目の「self.onMoveObj」は、「今動かしているマッチ棒オブジェクト」を保持する変数です。初期値としてNoneが代入されています。

 

30行目の「self.QADict」は、キーに答えを代入し、値に問題を代入する変数です。Part1からPart4で作成したmatchstickquiz_QA.pyで生成した問題と答えが代入されます。

 

31行目の「self.quesList」は、現在表示している問題を保持する変数です。

 

32行目の「self.ansList」は、答えを保持する変数です。

 

33行目の「self.input_ansList」は、プレイヤーが入力した答えを保持する変数です。

34行目の「with文」は、self.canvas.beforeオブジェクトを扱うための文です。

 

35行目の「Color」は、後述するRectangleの色を指定するためのオブジェクトです。白色に設定しています。

 
36行目の「self.bg_rect」は、背景を表現するRectangleを代入する変数です。Rectangleのposとsizeには、それぞれPlayFieldWidgetのposとsizeを代入しています。

 

 

37行目の「on_size関数」は、PlayFieldWidgetのsizeが変更された際に実行する関数です。

 

38行目の「self.base_x」は、マッチ棒で作られた問題を真ん中に表示するための左下のx座標です。再計算して代入しています。

39行目の「self.base_y」は、マッチ棒で作られた問題を真ん中に表示するための左下のy座標です。再計算して代入しています。

 
40行目の「self.bg_rect.size」は、背景のsizeを更新しています。

 

 

動作確認

コードを保存したら、コマンドプロンプトを開きファイルを保存したフォルダまで移動します。移動したら、以下のコマンドを入力し実行します。

python matchstickquiz.py

 

以下のように表示されれば動作確認完了です。

  

 

スポンサードサーチ


表示位置の計算

マッチ棒を任意の位置に表示させるために、表示位置の計算が必要になります。

今回は、「x + y = z」という形式で表示させるための座標を計算します。

 

 

コードの提示

PlayFieldWidgetのinit関数とon_size関数のソースコードを以下に示します。

import kivy
kivy.require("2.0.0")

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.graphics import Color, Rectangle, Ellipse
from kivy.graphics import Rotate
from kivy.graphics.context_instructions import PushMatrix, PopMatrix

import numpy as np

class MatchStickWidget(Widget):
    # 省略

class MatchStickFrameWidget(Widget):
    # 省略

class PlayFieldWidget(FloatLayout):
    def __init__(self, **kwargs):
        # 省略
    def on_size(self, *args):
        # 省略
    def calcPos(self, base_x, base_y, k, *args):
        # base (xが若い順 -> yが若い順)
        base_num_pos = [(base_x, base_y+self.ms_w, 0), (base_x, base_y+self.ms_w+self.ms_h+self.ms_w, 0),
                        (base_x+self.ms_w+self.ms_h/2-self.ms_w/2, base_y-self.ms_h/2+self.ms_w/2, 90),
                        (base_x+self.ms_w+self.ms_h/2-self.ms_w/2, base_y+self.ms_w+self.ms_h+self.ms_w/2-self.ms_h/2, 90),
                        (base_x+self.ms_w+self.ms_h/2-self.ms_w/2, base_y+self.ms_w+self.ms_h+self.ms_w+self.ms_h+self.ms_w/2-self.ms_h/2, 90),
                        (base_x+self.ms_w+self.ms_h, base_y+self.ms_w, 0), (base_x+self.ms_w+self.ms_h, base_y+self.ms_w+self.ms_h+self.ms_w, 0)]
        # sign
        plus_sign_pos = [(base_x+self.ms_w+self.ms_h/2-self.ms_w/2, base_y+self.ms_w+self.ms_h+self.ms_w/2-self.ms_h/2, 0),
                         (base_x+self.ms_w+self.ms_h/2-self.ms_w/2, base_y+self.ms_w+self.ms_h+self.ms_w/2-self.ms_h/2, 90)]
        minus_sign_pos = [(base_x+self.ms_w+self.ms_h/2-self.ms_w/2, base_y+self.ms_w+self.ms_h+self.ms_w/2-self.ms_h/2, 90)]
        equal_sign_pos = [(base_x+self.ms_w+self.ms_h/2-self.ms_w/2, base_y+self.ms_w+self.ms_h-(self.ms_h/2-self.ms_w)/2-self.ms_h/2, 90),
                          (base_x+self.ms_w+self.ms_h/2-self.ms_w/2, base_y+self.ms_w+self.ms_h+self.ms_w+(self.ms_h/2-self.ms_w)/2-self.ms_h/2, 90)]
        # number
        zero_num_pos  = base_num_pos[0:3] + base_num_pos[4:]
        one_num_pos   = base_num_pos[5:]
        two_num_pos   = [base_num_pos[i] for i in [0, 2, 3, 4, 6]]
        three_num_pos = base_num_pos[2:]
        four_num_pos  = [base_num_pos[i] for i in [1, 3, 5, 6]]
        five_num_pos  = base_num_pos[1:6]
        six_num_pos   = base_num_pos[:-1]
        seven_num_pos = [base_num_pos[1]] + base_num_pos[4:]
        eight_num_pos = base_num_pos
        nine_num_pos  = base_num_pos[1:]
        pos_dict = {"base":base_num_pos, "+":plus_sign_pos, "-":minus_sign_pos, "=":equal_sign_pos,
                    "0":zero_num_pos, "1":one_num_pos, "2":two_num_pos, "3":three_num_pos, "4":four_num_pos,
                    "5":five_num_pos, "6":six_num_pos, "7":seven_num_pos, "8":eight_num_pos, "9":nine_num_pos}
        return pos_dict[k]

class RootWidget(FloatLayout):
    def __init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)
        with self.canvas.before:
            Color(rgb=[1, 1, 1])
            self.bg_rect = Rectangle(pos=self.pos, size=self.size)
    def on_size(self, *args):
        self.bg_rect.size = self.size

class MatchStickQuizApp(App):
    def build(self):
        root = RootWidget()
        root.add_widget(PlayFieldWidget())
        return root

if __name__ == '__main__':
    MatchStickQuizApp().run()
    pass

 

上記のコードは以下からダウンロードできます。

  

 

コードの解説

24行目から51行目の「calcPos関数」は、マッチ棒の表示位置を計算する関数です。

第2引数には、基準となるx座標を代入します。

第3引数には、基準となるy座標を代入します。

第4引数には、数字または記号を代入します。

 

26行目から30行目の「base_num_pos」は、数字の表示位置を示す変数です。以下の画像の順で代入されています。

  

32行目と33行目の「plus_sign_pos」は、「+」の表示位置を示す変数です。縦横の順で代入されています。

 

34行目の「minus_sign_pos」は、「ー」の表示位置を示す変数です。

 

35行目と36行目の「equal_sign_pos」は、「=」の表示位置を示す変数です。y座標が小さい順に代入されています。

 

38行目から47行目は、0から9で使う表示位置をそれぞれの変数に代入しています。

 

48行目から50行目の「pos_dict」は、キーに数字や記号を代入し、値に表示位置を代入した変数です。

 

51行目の「return文」は、第3引数に与えらえた数字または記号の表示位置を返しています。

 

 

動作確認

コードを保存したら、コマンドプロンプトを開きファイルを保存したフォルダまで移動します。移動したら、以下のコマンドを入力し実行します。

python matchstickquiz.py

 

以下のように表示されれば動作確認完了です。

 

 

スポンサードサーチ


まとめ

今回は、問題を表示したり、マッチ棒を動かしたりするレイアウトを作成しました。特に初期化と表示位置の計算を行う関数を作成しました。

 

次回Part11では、マッチ棒枠の表示に関する関数を作成します。

 

 

  

最後までお読みいただきありがとうございます。


スポンサードサーチ