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

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

今回は、マッチ棒枠の表示に関する関数の作成を行います。具体的には、マッチ棒枠の表示とマッチ棒枠の表示の更新です。

 

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

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

 

 

 

スポンサードサーチ


マッチ棒枠の初期表示

マッチ棒枠をinit関数内で初期表示させます。init関数内で初期表示させておくことで、後述するマッチ棒枠の表示の更新が簡潔になります。

 

マッチ棒枠はマッチ棒を動かす場所となるため、「8 + 8 = 8」のように表示してどんな式でも当てはめられるようにします。

 

 

コードの提示

マッチ棒枠の初期表示のソースコードを以下に示します。

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
        # MatchStickFrameWidget Initialization
        for idx, k in enumerate(["base", "+", "base", "=", "base"]):
            pos_list = self.calcPos(self.base_x+idx*(self.ms_w+self.ms_h+self.ms_w), self.base_y, k)
            for pos_t in pos_list:
                obj = MatchStickFrameWidget(pos=[pos_t[0], pos_t[1]], ms_w=self.ms_w, angle=pos_t[2])
                self.frameList.append(obj)
                self.add_widget(obj)
        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
    def calcPos(self, base_x, base_y, k, *args):
        # 省略

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

 

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

  

 

コードの解説

35行目から40行目の「for文」は、マッチ棒枠を初期表示する処理です。

 

35行目の「for文」では、[“base”, “+”, “base”, “=”, “base”]を繰り返しています。つまり、「8 + 8 = 8」という形になるように繰り返しを設定しています。

また、enumerate関数によって繰り返しているため、取得した要素のインデックスも取得しています。

 

36行目の「pos_list」は、calcPosによって計算した座標を代入する変数です。

calcPosの引数には、x座標、y座標、表示したい数字又は記号を代入しています。

x座標の「self.base_x+idx*(self.ms_w+self.ms_h+self.ms_w)」については、以下の画像をご覧ください。

薄い緑色の部分はself.ms_wを表しています。薄いピンク色の部分はself.ms_hを表しています。

数字と記号は、緑ピンク緑、緑ピンク緑、、、と規則的に並んでいるため「idx*(self.ms_w+self.ms_h+self.ms_w)」というように計算することができます。

 

36行目の「pos_list」は、calcPosによって計算した座標を代入する変数です。

calcPosの引数には、x座標、y座標、表示したい数字又は記号を代入しています。

x座標の「self.base_x+idx*(self.ms_w+self.ms_h+self.ms_w)」については、以下の画像をご覧ください。

薄い緑色の部分はself.ms_wを表しています。薄いピンク色の部分はself.ms_hを表しています。

数字と記号は、緑ピンク緑、緑ピンク緑、、、と規則的に並んでいるため「idx*(self.ms_w+self.ms_h+self.ms_w)」というように計算することができます。

  

37行目の「for文」は、座標の数だけ繰り返す処理です。

 

38行目の「obj」は、マッチ棒枠のクラスに座標とマッチ棒の横幅、角度を代入して生成したオブジェクトを代入する変数です。

 

39行目は、マッチ棒枠を保持しておく変数に追加しています。

 

40行目の「self.add_widget(obj)」は、PlayFieldWidget自体に追加することでマッチ棒枠を表示しています。

 

 

動作確認

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

python matchstickquiz.py

 

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

  

表示が更新されていないため、左下を中心としてマッチ棒枠が表示されてしまっています。

 

 

スポンサードサーチ


マッチ棒枠の表示更新

マッチ棒枠の表示の更新を行う関数を作成します。

初期表示をしただけでは、左下にマッチ棒枠が表示されているだけで真ん中に表示されません。

常にレイアウトの真ん中に表示されるように、マッチ棒枠の表示を更新する関数を作成します。

 

 

コードの提示

マッチ棒枠の表示の更新を行う関数のソースコードを以下に示します。

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
        # MatchStickFrameWidget Initialization
        for idx, k in enumerate(["base", "+", "base", "=", "base"]):
            pos_list = self.calcPos(self.base_x+idx*(self.ms_w+self.ms_h+self.ms_w), self.base_y, k)
            for pos_t in pos_list:
                obj = MatchStickFrameWidget(pos=[pos_t[0], pos_t[1]], ms_w=self.ms_w, angle=pos_t[2])
                self.frameList.append(obj)
                self.add_widget(obj)
        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
        self.drawFrame()    # Added
    def calcPos(self, base_x, base_y, k, *args):
        # 省略
    def drawFrame(self, *args):
        c = 0 # index of self.frameList
        for idx, k in enumerate(["base", "+", "base", "=", "base"]):
            pos_list = self.calcPos(self.base_x+idx*(self.ms_w+self.ms_h+self.ms_w), self.base_y, k)
            for pos_t in pos_list:
                obj = self.frameList[c]
                obj.ms_w = self.ms_w
                obj.pos = [pos_t[0], pos_t[1]]
                obj.angle = pos_t[2]
                c += 1


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

 

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

 

 

コードの解説

48行目の「self.drawFrame()」は、後述するマッチ棒枠の表示の更新を実行しています。レイアウトのサイズが変更された際に実行したいため、on_size関数の中に記述しています。

  

 

51行目から60行目の「drawFrame関数」は、マッチ棒枠の表示を更新する関数です。

 

52行目の「c」は、frameListからオブジェクトを取り出すためのインデックスを代入する変数です。

 

53行目の「for文」は、[“base”, “+”, “base”, “=”, “base”]を繰り返しています。つまり、「8 + 8 = 8」という形になるように繰り返しを設定しています。

また、enumerate関数によって繰り返しているため、取得した要素のインデックスも取得しています。

 

54行目の「pos_list」は、calcPosによって計算した座標を代入する変数です。

 

55行目の「for文」は、pos_listに代入されている座標の数だけ繰り返す処理です。

 

56行目の「obj」は、self.frameListから取り出したオブジェクトを代入する変数です。

 

57行目の「obj.ms_w」は、マッチ棒枠の横幅を代入する変数です。

 

58行目の「obj.pos」は、新たな座標を代入する変数です。

 

59行目の「obj.angle」は、新たな角度を代入する変数です。

 

60行目の「c += 1」は、cに1足しています。

 

 

動作確認

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

python matchstickquiz.py

 

ウィンドウを最大化し、以下のように表示されれば動作確認完了です。

 

 

スポンサードサーチ


まとめ

今回は、マッチ棒枠の初期表示とマッチ棒枠の表示を更新する関数を作成しました。

難しい処理はなかったため、直ぐに理解できたと思います。

 

次回Part12では、問題を表示する関数を作成します。

 

  

 

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


スポンサードサーチ