グラフィカルなユーザーインターフェイスとゲーム開発

グラフィカルなユーザーインターフェイスとゲーム開発

tkinterモジュールに基づくGUIGUI
は、Graphical User Interfaceの略語です。GraphicalUserInterfaceは、コンピューターを使用したことのある人にはなじみのあるものである必要があり、ここで繰り返す必要はありません。PythonのデフォルトのGUI開発モジュールはtkinter(以前のバージョンのPython 3ではTkinterと呼ばれていました)です。この名前から、Tkに基づいていることがわかります。Tkは元々Tcl用に設計され、後で移植されたツールキットです。他の多くのスクリプト言語では、クロスプラットフォームのGUIコントロールを提供します。もちろん、Tkは最新で最良の選択ではなく、特に強力なGUIコントロールもありません。実際、GUIアプリケーションの開発はPythonの最良の仕事ではありません。本当にPythonを使用してGUIアプリケーション、wxPython、PyQt、PyGTKなどを開発する必要がある場合。モジュールは良い選択です。

基本的に、tkinterを使用してGUIアプリケーションを開発するには、次の5つの手順が必要です。

  1. 必要なものをtkinterモジュールにインポートします。
  2. トップレベルのウィンドウオブジェクトを作成し、それを使用してGUIアプリケーション全体をホストします。
  3. GUIコンポーネントをトップレベルのウィンドウオブジェクトに追加します。
  4. これらのGUIコンポーネントの機能をコードで整理します。
  5. メインイベントループ(メインループ)に入ります。

次のコードは、tkinterを使用して単純なGUIアプリケーションを作成する方法を示しています。

import tkinter
import tkinter.messagebox


def main():
    flag = True

    # 修改标签上的文字
    def change_label_text():
        # nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量;
        # global关键字用来在函数或其他局部作用域中使用全局变量。
        nonlocal flag  
        flag = not flag
        color, msg = ("red", "Hello, world!") \
            if flag else ("blue", "Goodbye, world!")
        label.config(text=msg, fg=color)

    # 确认退出
    def confirm_to_quit():
        if tkinter.messagebox.askokcancel("温馨提示", "确定要退出吗?"):
            top.quit()

    # 创建顶层窗口
    top = tkinter.Tk()
    # 设置窗口大小
    top.geometry("240x160")
    # 设置窗口标题
    top.title("小游戏")
    # 创建标签对象并添加到顶层窗口
    label = tkinter.Label(top, text="Hello, world!", font="Arial -32", fg="red")
    label.pack(expand=1)
    # 创建一个装按钮的容器
    panel = tkinter.Frame(top)
    # 创建按钮对象,指定添加到哪个容器中 通过command参数绑定事件回调函数
    button1 = tkinter.Button(panel, text="修改", command=change_label_text)
    button1.pack(side="left")
    button2 = tkinter.Button(panel, text="退出", command=confirm_to_quit)
    button2.pack(side="right")
    panel.pack(side="bottom")
    # 开启主事件循环
    tkinter.mainloop()


if __name__ == '__main__':
    main()

GUIアプリケーションは通常、イベント駆動型であることに注意してください。メインイベントループに入る理由は、マウスやキーボードなどのさまざまなイベントの発生を監視し、対応するコードを実行してイベントを処理するためです。イベントは引き続き発生するためです。したがって、このようなループを実行して、次のイベントが発生するのを待つ必要があります。一方、Tkは、コントロールの配置用に3つのレイアウトマネージャーを提供します。コントロールは、レイアウトマネージャーを介して配置できます。3つのレイアウトマネージャーは次のとおりです。配置ツール(開発者がコントロールのサイズと配置を提供します) 、Packer(コントロールを適切な位置に自動的に入力)およびGrid(グリッド座標に基づいてコントロールを配置)、ここでは繰り返しません。

ゲーム開発に
Pygameを使用するPygameは、マルチメディアアプリケーション(ビデオゲームなど)の開発専用のオープンソースPythonモジュールであり、画像、音声、ビデオ、イベント、衝突などのサポートが含まれています。PygameはSDLに基づいて構築されています。SDLはクロスプラットフォームのマルチメディア開発ライブラリであり、C言語で実装されており、ゲーム、シミュレーター、プレーヤーなどの開発に広く使用されています。Pygameを使用すると、ゲーム開発者は基盤となる言語に縛られることがなくなり、ゲームの機能とロジックにさらに注意を払うことができます。

次に、簡単なゲームを完成させましょう。ゲームの名前は「Big Ball Eats Little Ball」です。もちろん、このゲームを完成させることは重要ではありません。Pygameの使い方を学ぶことは重要ではありません。最も重要なことは、プロセスでフロントを使用する方法を理解する必要があることです。オブジェクト指向のプログラミングについて説明し、このプログラミングのアイデアを使用して実際の問題を解決する方法を学びます。

ゲームウィンドウを作成する

import pygame


def main():
    # 初始化导入pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption("大球吃小球")
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running == False


if __name__ == '__main__':
    main()

ウィンドウでの描画

pygameのdrawモジュールの機能を使用して、ウィンドウに描画できます。描画できるグラフィックには、線、長方形、ポリゴン、円、楕円、円弧などがあります。画面の座標系は、画面の左上隅を座標原点(0、0)に設定し、右方向がx軸の正の方向、下方向がy軸の正の方向であることに注意してください。位置を示すとき、またはサイズを設定するときは、デフォルトの単位はピクセルです。いわゆるピクセルは画面上のポイントです。画像を閲覧するためのソフトウェアを使用して、画像を数倍に拡大してこれらのポイントを確認できます。pygameの色は、色と光の3つの主要な色で表されます。つまり、色のRGB値はタプルまたはリストで指定され、各主要な色は8ビット(ビット)を使用するため、各値は0〜255です。 3色は合計24ビットに相当し、「24ビットカラー表現」と呼ばれることがよくあります。

import pygame


def main():
    # 初始化导入pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption("大球吃小球")
    # 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)
    screen.fill((242, 242, 242))
    # 绘制一个圆(参数分别是:屏幕,颜色,圆心位置,半径,0表示填充圆)
    pygame.draw.circle(screen, (255, 0, 0), (100, 100), 30, 0)
    # 刷新当前窗口(渲染窗口将绘制的图像呈现出来)
    pygame.display.flip()
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running == False


if __name__ == '__main__':
    main()

画像を読み込む

画像をウィンドウに直接ロードする必要がある場合は、pygameのimageモジュールの機能を使用して画像をロードし、前に取得したウィンドウオブジェクトのblitメソッドを使用して画像をレンダリングできます。コードを以下に示します。

import pygame


def main():
    # 初始化导入pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption("大球吃小球")
    # 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)
    screen.fill((255, 255, 255))
    # 通过制定的文件名加载图像
    ball_image = pygame.image.load("xxx.jpg")
    # 在窗口上渲染图像
    screen.blit(ball_image, (50, 50))
    # 刷新当前窗口(渲染窗口将绘制的图像呈现出来)
    pygame.display.flip()
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running == False


if __name__ == '__main__':
    main()

アニメーション効果を実現

アニメーションに関しては、誰もがよく知っています。実際、アニメーション効果を実現するための原則自体は非常に単純です。不連続な画像を連続して再生することです。1秒あたりの一定のフレーム数に達する限り、それを実行できます。比較的スムーズなアニメーション効果。上記のコードでボールを移動させたい場合は、変数を使用してボールの位置を示し、ループ内のボールの位置を変更してから、ウィンドウ全体を更新できます。

import pygame


def main():
    # 初始化导入pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption("大球吃小球")
    # 定义变量来表示小球在屏幕上的位置
    x, y = 50, 50
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running == False
        screen.fill((255, 255, 255))
        pygame.draw.circle(screen, (255, 0, 0), (x, y), 30, 0)
        pygame.display.flip()
        # 每隔50毫秒就改变小球的位置再刷新窗口
        pygame.time.delay(50)
        x, y = x + 5, y + 5


if __name__ == '__main__':
    main()

影響チェック

通常、ゲームには多くのオブジェクトがあり、シェルが飛行機にぶつかったり、ボックスが地面にぶつかったりするなど、これらのオブジェクト間の「衝突」は避けられません。衝突検出は、ほとんどのゲームで対処しなければならない重要な問題です。pygameのスプライト(アニメーションスプライト)モジュールは、衝突検出をサポートします。ここでは、スプライトモジュールが提供する機能については紹介しません。 2つの小さなボールが衝突するかどうかを検出するのは非常に簡単なので、球の中心間の距離が2つのボールの半径の合計よりも小さいかどうかを確認するだけです。より小さなボールを作成するために、マウスイベントを処理して、マウスをクリックするだけでランダムな色、サイズ、移動速度の小さなボールを作成できます。もちろん、これを行うには、以前に学んだことを取り入れることができます。オブジェクト指向の知識が適用されます。

from enum import Enum, unique
from math import sqrt
from random import randint
import pygame


@unique
class Color(Enum):
    """颜色"""

    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    BLUE = (0, 0, 255)
    BLACK = (0, 0, 0)
    WHITE = (255, 255, 255)
    GRAY = (242, 242, 242)

    @staticmethod
    def random_color():
        """获得随机颜色"""
        r = randint(0, 255)
        g = randint(0, 255)
        b = randint(0, 255)
        return (r, g, b)

class Ball(object):
    """球"""

    def __init__(self, x, y, radius, sx, sy, color=Color.RED):
        """初始化方法"""
        self.x = x
        self.y = y
        self.radius = radius
        self.sx = sx
        self.sy = sy
        self.color = color
        self.alive = True
        
    def move(self, screen):
        """移动"""
        self.x += self.sx
        self.y += self.sy
        if self.x - self.radius <= 0 or self.x + self.radius >= screen.get_width():
            self.sx = -self.sx
        if self.y - self.radius <= 0 or self.y + self.radius >= screen.get_height():
            self.xy = -self.sy
    
    def eat(self, other):
        """吃其他球"""
        if self.alive and other.alive and self != other:
            dx, dy = self.x - other.x, self.y - other.y
            distance = sqrt(dx ** 2 + dy ** 2)
            if distance < self.radius + other.radius and self.radius > other.radius:
                other.alive = False
                self.radius = self.radius + int(other.radius * 0.146)
    
    def draw(self, screen):
        """在窗口上绘制球"""
        pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius, 0)

イベント処理

マウスイベントはイベントループで処理でき、イベントタイプはイベントオブジェクトのtype属性を介して決定でき、マウスクリックの位置はpos属性を介して取得できます。この場所でキーボードイベントを処理する場合、アプローチはマウスイベントの処理に似ています。

def main():
    # 定义用来装所有球的容器
    balls = []
    # 初始化导入pygame中的模块
    pygame.init()
    # 初始化用于显示的窗口并设置窗口尺寸
    screen = pygame.display.set_mode((800, 600))
    # 设置当前窗口的标题
    pygame.display.set_caption("大球吃小球")
    running = True
    # 开启一个事件循环处理发生的事件
    while running:
        # 从消息队列中获取事件并对事件进行处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            # 处理鼠标事件的代码
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 获取点击鼠标的位置
                x, y = event.pos
                radius = randint(10, 100)
                sx, sy = randint(-10, 10), randint(-10, 10)
                color = Color.random_color()
                # 在点击鼠标的位置创建一个球(大小、速度和颜色随机)
                ball = Ball(x, y, radius, sx, sy, color)
                # 将球添加到列表容器中
                balls.append(ball)
        screen.fill((255, 255, 255))
        # 取出容器中的球 如果没被吃掉就绘制 被吃掉了就移除
        for ball in balls:
            if ball.alive:
                ball.draw(screen)
            else:
                balls.remove(ball)
        pygame.display.flip()
        # 每隔50毫秒就改变小球的位置再刷新窗口
        pygame.time.delay(50)
        for ball in balls:
            ball.move(screen)
            for other in balls:
                ball.eat(other)


if __name__ == '__main__':
    main()

上記の2つのコードを組み合わせて、「大球吃小球ゲームを完成させました。正確には、ゲームではありませんが、この例を通じて小さなゲームを作成するための基本的な知識をすでに説明しました。この知識を使用して、ミニゲーム開発の旅を始めることができます。実際、上記のコードにはまだ改善に値する領域がたくさんあります。たとえば、ウィンドウを更新してボールを移動するためのコードをイベントループに配置しないでください。マルチスレッドの知識を習得したら、バックグラウンドスレッドを使用してこれらを処理します。より良い選択です。より良いユーザーエクスペリエンスを実現したい場合は、ゲームにバックグラウンドミュージックを追加したり、ボールがボールに衝突したときにサウンドエフェクトを再生したりすることもできます。pygamemixermusicモジュールを使用すると、これを簡単に行うことができます。これは自分で理解できます。アスペクト知識。実際、pygameについてもっと知りたい場合は、pygameの公式ウェブサイトが最適です。英語に問題がなければ、見に行くことができます。3Dゲームを開発したいのなら、pygameそれは無力のようです。3Dゲーム開発に興味のある読者は見てみたいと思うかもしれませんPanda3D

おすすめ

転載: blog.csdn.net/weixin_47312141/article/details/108326306