KUNISAN.JPブログ - 319 / 1695 ページ

新規書き込み
ページ:1 ... 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 ... 1695

Python + Pygameで擬似3Dサンプルプログラム

名前: 小川 邦久 リンク: http://kunisan.jp/ 日付: 2017年12月19日
Python + Pygameで擬似3Dサンプルプログラム本当はPythonでWebや機械学習などの方向に進もうと思っているのですが、Pygameでのミニゲームやサンプルプログラムの制作が楽しく、ここから中々抜け出せないでいます。ただ、楽しみながらもPythonの基本も学べてはいるので、まあ急がずにマイペースで続けていこうと思います。

先日、「Pythonゲームプログラミング 知っておきたい数学と物理の基本」というKindle本を購入したところ、この本に疑似3Dの視点と描写について分かりやすい解説がありました。私は高校生の時に「スペースハリアーのようなゲームが作りたい」と思ったことがあり、キャラクターの拡大・縮小や2D上の座標決めなど、色々とやってみたのですが、結局うまくいかずにそのまま時が過ぎてしまいました。あれから30年近く経ち、今になってようやく基本的な理論が理解できたのですが、考えていたよりも難しいものではなく、「何であの時に分からなかったんだろう?」と思ってしまいました。

過去のことを後悔しても仕方ないので、早速サンプルプログラムを作ってみることにしました。おおよそ事前に考えていたような内容のプログラムのまま、おおよそ思った通りに動いてくれました。

ということで、まずは動画です。


プログラムはこんな感じです。蛙はカーソルキーで上下左右、ZキーとXキーで前後に動きます。C、V、B、Nの各キーで視点の角度を変えることもできます。
""" 3d.py """

import pygame
import sys
from pygame.locals import *

pygame.init()
pygame.key.set_repeat(5, 5)
SURFACE = pygame.display.set_mode((400, 300))
FPSCLOCK = pygame.time.Clock()
pygame.display.set_caption("3D")

#【メモ】
#3D座標は x = 0, y = 0が画面の中心で、z = 0が画面の手前。キャラクターのx, y座標はキャラクターの中心。
#大きさ調整は、自分のz座標を-10、スクリーンのz座標を0(自分とスクリーンの距離10)とした場合、キャラクターのz座標が20の場合には3((20+10)÷10)で割り、30の場合には4((30+10)÷10)で割る計算。
#キャラクターの座標は、自分とスクリーンの距離を10とした場合、キャラクターのz座標が30の場合には、画面の中心の座標から、xを4((30+10)÷10)で割ったものを足し、キャラクターの大きさの半分を4((30+10)÷10)で割ったものをxから引く。yも同様。
#視点の調整は「係数 * z」を x や y に足す(その x や y をさらに上記の通りz座標の奥行きに合わせて割り算する)。

def location_in_view(x1, y1, z1, adj_x, adj_y, size_x = 0, size_y = 0):
""" 3D座標から2D上の座標算出 """
x2 = int((x1 + adj_x * z1) / (z1/10 + 1)) + 200 - int(size_x * 0.5 / (z1/10 + 1))
y2 = int((y1 + adj_y * z1) / (z1/10 + 1)) + 150 - int(size_y * 0.5 / (z1/10 + 1))
return (x2, y2)

def size_in_view(z1, size_x, size_y):
""" 3D座標から2D上のサイズ算出 """
size_x2 = int(size_x / (z1/10 + 1))
size_y2 = int(size_y / (z1/10 + 1))
return (size_x2, size_y2)

def main():
""" メインルーチン """
#変数初期設定
a, b, c, d = 0, 0, 0, 0
x = 0
y = 100
z = 0
scroll_count = 0
adjust_x = 0
adjust_y = 0
frog_image = pygame.image.load("frog.gif")
frog_size = 100
shadow_image = pygame.image.load("shadow.gif")
shadow_size = 100

while True:

#画面塗りつぶし
SURFACE.fill((0,0,0))

#ウィンドウ閉じるボタン
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()

#キー入力判定
pressed = pygame.key.get_pressed()
if pressed[K_LEFT] and x > -150:
x -= 20
if pressed[K_RIGHT] and x < 150:
x += 20
if pressed[K_UP] and y > -100:
y -= 20
if pressed[K_DOWN] and y < 100:
y += 20
if pressed[K_z] and z > -0:
z -= 2
if pressed[K_x] and z < 200:
z += 2
if pressed[K_c] and adjust_y > -10:
adjust_y -= 0.2
if pressed[K_v] and adjust_y < 10:
adjust_y += 0.2
if pressed[K_b] and adjust_x > -10:
adjust_x -= 0.2
if pressed[K_n] and adjust_x < 10:
adjust_x += 0.2

#背景スクロール
scroll_count += 1
if scroll_count > 7:
scroll_count = 0
for i in range(0-scroll_count, 200-scroll_count, 8):
a, b = location_in_view(-200, -150, i, adjust_x, adjust_y)
c, d = size_in_view(i, 400, 300)
pygame.draw.rect(SURFACE, (150-int(i/1.5), 150-int(i/1.5), 180-int(i/1.5)), (a, b, c, d))

#影表示
c, d = size_in_view(z, shadow_size, shadow_size)
shadow_image_3d = pygame.transform.scale(shadow_image, (c, d))
shadow_image.set_alpha(80)
a, b = location_in_view(x, 145, z, adjust_x, adjust_y, shadow_size, shadow_size)
SURFACE.blit(shadow_image_3d, (a, b))

#蛙表示
c, d = size_in_view(z, frog_size, frog_size)
frog_image_3d = pygame.transform.scale(frog_image, (c, d))
a, b = location_in_view(x, y, z, adjust_x, adjust_y, frog_size, frog_size)
print (a, b)
SURFACE.blit(frog_image_3d, (a, b))

#画面アップデート
pygame.display.update()
FPSCLOCK.tick(30)

if __name__ == '__main__':
main()


ファイル一式はこちらからダウンロードできます
※本プログラムやファイルの二次配布や二次掲載はご遠慮ください。個人的なプログラム改造はご自由にどうぞ。ただし、本プログラムに関するご質問等はお受けしません。

今回はキャラクターが1つだけなので、重ね合わせの処理が単純でしたが、いざ複数のキャラクターが動くようなゲームを作るとなると、そのあたりを考慮しながら作り込んでいく必要があります。

頭にあるのは「オブジェクトをリスト化して、そのオブジェクトのリスト全体をコピーして、コピーした方のリストをZ座標で並び替えて、Z座標が奥にあるものから手前にあるものにかけて描画していく」というアイデアです。Pythonそのものも学習の意味も兼ねて、また少し時間をかけて作り込んでいこうと思います。





Python関連記事(リンク一覧): Python + Pygameの疑似3Dゲーム (ミニゲーム第三弾) / Python + Pygameで擬似3Dサンプルプログラム / Python + Pygameのミニゲーム第二弾 『たけのこ狩り』 / Python - リスト内包表記とPygameのスプライト機能 / Pythonの学習とPygameを使ったミニアクションゲーム作成 / ...(記事連続表示)

Pythonゲームプログラミング 知っておきたい数学と物理の基本 (Future Coders(NextPublishing)) eBook
Pythonゲームプログラミング 知っておきたい数学と物理の基本 (Future Coders(NextPublishing)) eBookをAmazon.co.jpでチェック

ページ:1 ... 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 ... 1695