1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Day4:python初心者がダンジョンゲーム作成してみる

Posted at

Day 4: レベルの生成

本日の成果

開くたびに自動でダンジョンの地形が変わるものを作成
Python 3.11 2023_07_09 20_21_04.png

レベル生成アルゴリズムの学習:

Procedural Generation in Game Design by Tanya X. Short
RogueBasin
Dungeon Generation
ヘロンの数学ちゃんねる で概要を確認

アルゴリズムの概要

このコードは、ランダムなダンジョンを生成するためのアルゴリズムを利用しています。以下にアルゴリズムの概要を説明します。

  1. ダンジョンの要素を表す定数 WALL(壁)、FLOOR(床)、PLAYER(プレイヤー)を定義します。

  2. create_dungeon 関数では、指定された幅と高さを持つダンジョンを作成します。初期状態ではすべてのセルが壁で埋められています。

  3. create_room 関数では、指定された範囲内でランダムな幅と高さの部屋を生成し、ダンジョンに部屋を配置します。部屋は床で埋められます。

  4. place_rooms 関数では、指定された数の部屋をダンジョン内に配置します。部屋の配置はランダムです。

  5. create_corridor 関数では、2つの部屋の中間点を結ぶ通路を生成し、ダンジョンに床を配置します。

  6. generate_dungeon 関数では、ダンジョンの生成と部屋の配置、通路の生成を行います。また、プレイヤーの初期位置もランダムな部屋内に設定されます。

  7. draw_dungeon 関数では、ダンジョンをグラフィックスウィンドウに描画します。各セルは矩形で表示され、壁、床、プレイヤーは異なる色で描画されます。

  8. メインのゲームループでは、Pygame のイベントを処理し、プレイヤーの移動を制御します。プレイヤーが移動するたびに、ダンジョン内のセルの状態が更新されます。

  9. ゲームループの中で draw_dungeon 関数を呼び出してダンジョンを描画し、pygame.display.flip() でウィンドウを更新します。

このアルゴリズムにより、部屋と通路からなるランダムなダンジョンが生成され、プレイヤーがキーボード入力に応じて移動することができます。

コードの詳細

モジュールのインポート:

import pygame
import random
  • pygame モジュール: ゲーム開発用の Python ライブラリです。
  • random モジュール: 乱数生成のための Python ライブラリです。

ダンジョンの要素を表す定数の定義:

WALL = 0
FLOOR = 1
PLAYER = 2
  • WALL: 壁を表す定数
  • FLOOR: 床を表す定数
  • PLAYER: プレイヤーを表す定数

ダンジョン生成関連の関数の定義:

 def create_dungeon(width, height):
     dungeon = [[WALL for _ in range(width)] for _ in range(height)]
     return dungeon
  • create_dungeon(width, height): 指定された幅と高さのダンジョンを作成し、壁で初期化して返します。
 def create_room(min_width, max_width, min_height, max_height, dungeon):
     width = random.randint(min_width, max_width)
     height = random.randint(min_height, max_height)
     x = random.randint(1, len(dungeon[0]) - width - 1)
     y = random.randint(1, len(dungeon) - height - 1)
     
     for i in range(y, y + height):
         for j in range(x, x + width):
             dungeon[i][j] = FLOOR
     
     return (x, y, width, height)
  • create_room(min_width, max_width, min_height, max_height, dungeon): 指定された範囲内でランダムなサイズの部屋を作成し、ダンジョン上の床に変換します。部屋の位置とサイズの情報をタプルとして返します。
 def place_rooms(num_rooms, min_width, max_width, min_height, max_height, dungeon):
     rooms = []
     
     for _ in range(num_rooms):
         room = create_room(min_width, max_width, min_height, max_height, dungeon)
         rooms.append(room)
     
     return rooms
  • place_rooms(num_rooms, min_width, max_width, min_height, max_height, dungeon): 指定された数の部屋を生成し、ダンジョン内に配置します。各部屋の位置とサイズの情報をリストとして返します。
 def create_corridor(start, end, dungeon):
     x1, y1 = start
     x2, y2 = end
     
     while x1 != x2 or y1 != y2:
         if x1 < x2:
             x1 += 1
         elif x1 > x2:
             x1 -= 1
         elif y1 < y2:
             y1 += 1
         elif y1 > y2:
             y1 -= 1
         
         dungeon[y1][x1] = FLOOR
  • create_corridor(start, end, dungeon): 部屋の中心座標を指定して通路を生成し、ダンジョン上の床に変換します。

ダンジョン全体の生成関数:

def generate_dungeon(width, height, num_rooms, min_width, max_width, min_height, max_height):
    dungeon = create_dungeon(width, height)
    rooms = place_rooms(num_rooms, min_width, max_width, min_height, max_height, dungeon)

    for i in range(len(rooms) - 1):
        start = (rooms[i][0] + rooms[i][2] // 2, rooms[i][1] + rooms[i][3] // 2)
        end = (rooms[i+1][0] + rooms[i+1][2] // 2, rooms[i+1][1] + rooms[i+1][3] // 2)
        create_corridor(start, end, dungeon)

    player_room = random.choice(rooms)
    player_x = random.randint(player_room[0], player_room[0] + player_room[2] - 1)
    player_y = random.randint(player_room[1], player_room[1] + player_room[3] - 1)
    dungeon[player_y][player_x] = PLAYER

    return dungeon, rooms, player_x, player_y
  • generate_dungeon 関数: 指定されたパラメータに基づいてダンジョン全体を生成します。ダンジョンの作成、部屋の配置、通路の作成、プレイヤーの初期位置の設定を行います。ダンジョン、部屋のリスト、プレイヤーの初期位置を返します。

ダンジョンの描画関数:

def draw_dungeon(dungeon):
    for y in range(len(dungeon)):
        for x in range(len(dungeon[y])):
            cell = dungeon[y][x]
            cell_rect = pygame.Rect(x * cell_size, y * cell_size, cell_size, cell_size)
         
            if cell == WALL:
                pygame.draw.rect(window, (0, 0, 0), cell_rect)
            elif cell == FLOOR:
                pygame.draw.rect(window, (255, 255, 255), cell_rect)
            elif cell == PLAYER:
                pygame.draw.rect(window, (255, 0, 0), cell_rect)
  • draw_dungeon 関数: ダンジョンの状態を描画します。ダンジョンの各セルに対応する矩形を作成し、セルの値に応じて色を設定して描画します。

Pygame の初期化とウィンドウの作成:

dungeon_width = 800
dungeon_height = 600
cell_size = 20

pygame.init()
window = pygame.display.set_mode((dungeon_width, dungeon_height))
pygame.display_set_caption("Dungeon Game")
  • dungeon_widthdungeon_height はそれぞれウィンドウの幅と高さを表します。
  • cell_size はダンジョン内のセル(部屋や通路のタイル)のサイズを表します。
  • pygame.init() は Pygame ライブラリを初期化します。
  • window 変数に pygame.display.set_mode((dungeon_width, dungeon_height)) を用いてウィンドウを作成します。
  • pygame.display.set_caption("Dungeon Game") はウィンドウのキャプション(タイトル)を設定します。

プレイヤーの初期位置の設定:

player_x = 0
player_y = 0
  • player_xplayer_y はプレイヤーの初期位置の座標を表します。ここでは 0 で初期化されています。

ダンジョンの生成とプレイヤーの初期位置の取得:

dungeon, rooms, player_x, player_y = generate_dungeon(40, 30, 15, 3, 10, 3, 10)
  • generate_dungeon 関数を呼び出して、ダンジョンを生成し、部屋のリストとプレイヤーの初期位置を取得します。引数として、ダンジョンの幅と高さ、部屋の数、部屋の最小幅と最大幅、部屋の最小高さと最大高さが指定されています。

ゲームループ:

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if event.type == pygame.KEYDOWN:
            # プレイヤーの移動処理
            if event.key == pygame.K_UP:
                # 上キーが押された場合の処理
            elif event.key == pygame.K_DOWN:
                # 下キーが押された場合の処理
            elif event.key == pygame.K_LEFT:
                # 左キーが押された場合の処理
            elif event.key == pygame.K_RIGHT:
                # 右キーが押された場合の処理

    # ダンジョンの描画処理
    draw_dungeon(dungeon)

    # 画面の更新
    pygame.display.flip()

pygame.quit()
  • running 変数が True の間、ゲームループが実行されます。
  • イベントループ内でキーボードイベントを処理し、プレイヤーの移動を制御します。
  • draw_dungeon 関数を呼び出してダンジョンを描画します。
  • pygame.display.flip() でウィンドウの内容を更新します。
  • ゲームループが終了した後、pygame.quit() を呼び出して Pygame を終了します。

まとめ

今回作成したものを基準に、前回までに学んだ内容を追加したら敵キャラやアイテムを作れないかな~

アルゴリズムについては、正直理解できなかった…
英語と数学、アルゴリズムの勉強しなければ…
とりあえずは、手を動かして完成までもっていこう!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?