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

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

今回は、マッチ棒の枠を作成します。白地にマッチ棒だけを置いていたら、どこにマッチ棒を動かしたら良いのか分からなくなるため、予め動かす場所にマッチ棒の枠を置いておきます。

 

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

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

 

 

 

スポンサードサーチ


初期化と回転

マッチ棒の枠を作成します。以下の画像におけるグレーの部分です。

 

ここでは特に、初期化の関数と回転したときの関数を作成します。

 

以降、「マッチ棒の枠」を「マッチ棒枠」と表現します。

 

 

コードの提示

マッチ棒枠クラスの初期化と回転の関数のソースコードを以下に示します。

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):
    def __init__(self, ms_w, angle, **kwargs):
        super(MatchStickFrameWidget, self).__init__(**kwargs)
        self.size = [0, 0]
        self.ms_w = ms_w
        self.create_property("angle", value=angle)
        with self.canvas:
            PushMatrix()
            self.rot = Rotate()
            self.rot.angle = self.angle
            self.rot.origin = (self.x + self.ms_w / 2, self.y + self.ms_w * 6.8 / 2)
            Color(rgb=[0.95, 0.95, 0.95])
            self.stick = Rectangle(pos=[self.x+self.ms_w*0.2, self.y],
                                   size=[self.ms_w * 0.6, self.ms_w * 5.6])
            self.powder = Ellipse(pos=[self.x, self.y+self.ms_w * 5.2],
                                   size=[self.ms_w, self.ms_w * 1.6])
            PopMatrix()
        self.bind(angle=self.rotateTheta)
    def rotateTheta(self, *args):
        self.rot.angle = self.angle

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(MatchStickFrameWidget(25, 45, pos=[100, 100]))
        return root

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

 

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

  

 

コードの解説

16行目から35行目の「MatchStickFrameWidget」は、マッチ棒枠を表現するクラスです。

 

 

17行目から33行目の「__init__関数」は、MatchStickFrameWidgetの初期化を行う関数です。

第2引数の「ms_w」は、マッチ棒枠の横幅を指定するための引数です。マッチ棒の横幅と同じ値を代入します。

第3引数の「angle」は、マッチ棒枠の角度を指定するための引数です。

 

19行目の「self.size」は、マッチ棒枠のサイズを指定するための変数です。[0, 0]を代入しています。

 

20行目の「self.ms_w」は、マッチ棒枠の横幅を指定するための変数です。引数で与えられたms_wを代入しています。

 

21行目の「create_property」は、MatchStickFrameWidgetクラスに新しいプロパティを生成しています。プロパティにすることで、後述する「bind」という機能を使用することができます。

第1引数に指定された文字列がプロパティ名となります。つまり、「angle」がプロパティ名です。

第2引数の「value=angle」は、angleプロパティにangle(初期角度)を代入しています。

  

22行目の「with文」は、self.canvasオブジェクトに対てして処理を行うためものです。

 

23行目の「PushMatrix」は、回転の範囲の始まりを示しています。PushMatrixからPopMatrixが回転の範囲となります。

 

24行目の「self.rot」は、回転を実装するためのクラスであるRotateが代入された変数です。Rotateクラスの角度や原点が変化することで他のgraphicsも変化します。

 

25行目の「self.rot.angle」は、Rotateクラスのangleに角度を代入しています。

 

26行目の「self.rot.origin」は、Rotateクラスのoriginに原点を代入しています。

 

27行目の「Color」は、後述するRectangleとEllipseの色をグレーに指定しています。

 

28行目と29行目の「self.stick」は、マッチ棒枠の棒部分が代入されている変数です。Rectangleで指定しているsizeとposはマッチ棒クラスの時と同じです。

 

30行目と31行目の「self.powder」は、マッチ棒枠の火薬部分が代入されている変数です。Ellipseで指定しているsizeとposはマッチ棒クラスの時と同じです。

 

32行目の「PopMatrix」は、回転の範囲の終わりを示しています。PushMatrixからPopMatrixが回転の範囲となります。

 

33行目の「self.bind(angle=self.rotateTheta)」は、angleプロパティが変化したときに後述するrotateTheta関数が実行されるように紐づけています。

 

 

34行目の「rotateTheta関数」は、angleの値が変化したときに実行される関数です。

 

35行目の「self.rot.angle」は、Rotateクラスのangleにangleプロパティを代入しています。

  

 

動作確認

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

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):
    def __init__(self, ms_w, angle, **kwargs):
        super(MatchStickFrameWidget, self).__init__(**kwargs)
        self.size = [0, 0]
        self.ms_w = ms_w
        self.create_property("angle", value=angle)
        with self.canvas:
            PushMatrix()
            self.rot = Rotate()
            self.rot.angle = self.angle
            self.rot.origin = (self.x + self.ms_w / 2, self.y + self.ms_w * 6.8 / 2)
            Color(rgb=[0.95, 0.95, 0.95])
            self.stick = Rectangle(pos=[self.x+self.ms_w*0.2, self.y],
                                   size=[self.ms_w * 0.6, self.ms_w * 5.6])
            self.powder = Ellipse(pos=[self.x, self.y+self.ms_w * 5.2],
                                   size=[self.ms_w, self.ms_w * 1.6])
            PopMatrix()
        self.bind(angle=self.rotateTheta)
        self.bind(pos=self.drawMSF)     # Added
    def rotateTheta(self, *args):
        self.rot.angle = self.angle
    def drawMSF(self, *args):
        self.rot.origin = (self.x + self.ms_w / 2, self.y + self.ms_w * 6.8 / 2)
        # StickWidget
        self.stick.pos = [self.x+self.ms_w*0.2, self.y]
        self.stick.size = [self.ms_w * 0.6, self.ms_w * 5.6]
        # PowderWidget
        self.powder.pos = [self.x, self.y+self.ms_w*5.2]
        self.powder.size = [self.ms_w, self.ms_w * 1.6]

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()
        msf = MatchStickFrameWidget(25, 0, pos=[100, 100])
        root.add_widget(msf)
        msf.pos = [600, 100]
        return root

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

 

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

 

 

コードの解説

34行目の「self.bind(pos=self.drawMSF)」は、posプロパティが変化したときに後述するdrawMSF関数が実行されるように紐づけています。

 

 

37行目の「drawMSF関数」は、マッチ棒枠の表示を更新する関数です。

 

38行目の「self.rot.origin」は、更新された回転の中心座標が代入されている変数です。

 

40行目の「self.stick.pos」は、更新された棒部分の座標が代入されている変数です。

 

41行目の「self.stick.size」は、棒部分のサイズが代入されている変数です。サイズは変わらないため、記述しなくてもよいです。サイズも変更したいという場合に使用します。

 

43行目の「self.powder.pos」は、更新された火薬部分の座標が代入されている変数です。

 

44行目の「self.powder.size」は、火薬部分のサイズが代入されている変数です。サイズは変わらないため、記述しなくてもよいです。サイズも変更したいという場合に使用します。

 

 

動作確認

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

python matchstickquiz.py

  

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

 

 

スポンサードサーチ


まとめ

今回は、マッチ棒枠を作成しました。実際にプレイする際にマッチ棒を置く場所として使用します。

マッチ棒と似ているため直ぐに理解できたと思います。

 

次回Part10では、実際にマッチ棒を動かすレイアウトを作成します。

 

 

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


スポンサードサーチ