0
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?

Pythonで学ぶゲーム数理工学:スプラトゥーン編1

Last updated at Posted at 2025-03-29

はじめに

スプラトゥーンのようなアクションゲームでも、実はその動きの裏側には数学がしっかりと活用されています。
本記事では、スプラトゥーンに登場するキャラクターの操作や弾の挙動を例に、ゲーム内の動きがどのような数式で表現され、どのように計算されているのかを、Pythonコードを使って解説します。

参考リンクまとめ

image.png
この人を参考にしました

image.png

フレームの計算ものせておきます

命中率を考慮したキル速の期待値

Pythonコード

フレーム速度計算とベクトル回転と 弧長と角度の関係 

image.png

# 日本語と英語のコメント付き / With Japanese and English comments

# === 与えられた値 Given values ===
speed_per_frame = 3.2     # 1フレームあたりの移動距離 / Distance per frame [m/frame]
frame_rate = 50           # フレームレート / Frame rate: frames per second

# === 各時間単位ごとの速度計算 Compute speeds per second, minute, and hour ===
speed_per_second = speed_per_frame * frame_rate               # m/s
speed_per_minute = speed_per_second * 60                      # m/min
speed_per_hour = speed_per_minute * 60                        # m/h

# === プリントで表示 Print the results ===
print("=== 速度の情報 / Speed Information ===")
print(f"1フレームあたりの移動距離 / Distance per frame: {speed_per_frame} m/frame")
print(f"フレームレートの定義 / Frame rate: {frame_rate} frames per second")
print(f"1秒あたりの移動距離 / Speed per second: {speed_per_second:.2f} m/s")
print(f"1分あたりの移動距離 / Speed per minute: {speed_per_minute:.2f} m/min")
print(f"1時間あたりの移動距離 / Speed per hour: {speed_per_hour:.2f} m/h")




import numpy as np
import matplotlib.pyplot as plt

# === パラメータ設定 Parameters ===
distance = 10             # ベクトルの長さ / Vector length [m]
base_angle_deg = 90       # 元の角度(度) / Base angle (degrees)
deviation_angle_deg = 15  # 回転させる角度 / Rotation angle (degrees)

# === ラジアンへの変換 Convert to radians ===
base_angle_rad = np.radians(base_angle_deg)
deviation_angle_rad = np.radians(deviation_angle_deg)

# === ベクトルの定義 Define vectors using complex numbers ===
v0 = distance * np.exp(1j * base_angle_rad)          # 元のベクトル Original vector
v1 = v0 * np.exp(1j * deviation_angle_rad)           # 回転後のベクトル Rotated vector

# === 座標の差の計算 Compute coordinate differences ===
x_diff = v1.real - v0.real  # X座標の差 / Difference in X [m]
y_diff = v1.imag - v0.imag  # Y座標の差 / Difference in Y [m]

# === 結果表示 Print results ===
print("=== ベクトルの座標と変化量 / Vector Coordinates and Differences ===")
print(f"Original vector ({base_angle_deg}°): x = {v0.real:.2f} m, y = {v0.imag:.2f} m")
print(f"Rotated vector ({base_angle_deg + deviation_angle_deg}°): x = {v1.real:.2f} m, y = {v1.imag:.2f} m")
print(f"X座標の差 / ΔX: {x_diff:.2f} m")
print(f"Y座標の差 / ΔY: {y_diff:.2f} m")

# === プロット設定 Plot ===
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.grid(True)

margin = 5
ax.set_xlim(-distance - margin, distance + margin)
ax.set_ylim(-distance - margin, distance + margin)

# 円を描画 Draw a reference circle
circle = plt.Circle((0, 0), distance, color='lightblue', fill=False, linestyle='--', label=f'Radius = {distance} m')
ax.add_artist(circle)

# ベクトルの描画 Draw vectors
ax.arrow(0, 0, v0.real, v0.imag, head_width=0.5, head_length=1, fc='blue', ec='blue', label=f'Original ({base_angle_deg}°)')
ax.arrow(0, 0, v1.real, v1.imag, head_width=0.5, head_length=1, fc='red', ec='red', label=f'Rotated (+{deviation_angle_deg}°)')

ax.plot(0, 0, 'ko')  # 原点 / Origin
ax.legend()

# タイトルに差を表示 Show differences in title
plt.title(f"Vector Rotation ΔX = {x_diff:.2f} m, ΔY = {y_diff:.2f} m")
plt.xlabel("X [m]")
plt.ylabel("Y [m]")
plt.show()


import numpy as np
import matplotlib.pyplot as plt

# 弧の長さ fixed arc length
arc_length = (5 * np.pi) / 3  # = 5π/3

# 射程 before and after (range)
r_before = 10
r_after = 13

# 角度(度)を求める Calculate angles (degrees)
theta_before = 360 * arc_length / (2 * np.pi * r_before)
theta_after = 360 * arc_length / (2 * np.pi * r_after)

# 各角度を半分にして左右に分ける(扇形描画用) Split into left/right half angles
left_before = -theta_before / 2
right_before = theta_before / 2
left_after = -theta_after / 2
right_after = theta_after / 2

# プロット設定 Plotting
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
ax.set_theta_zero_location("N")  # 上向きを0度に設定 / Set 0° to top
ax.set_theta_direction(-1)       # 時計回り / Clockwise

# 角度をラジアンに変換 Convert to radians
theta1 = np.radians(np.linspace(left_before, right_before, 100))
theta2 = np.radians(np.linspace(left_after, right_after, 100))

# 扇形を描く Draw the sectors
ax.plot(theta1, [r_before]*len(theta1), label=f'Before: {theta_before:.3f}° (r=10 m)', color='red')
ax.plot(theta2, [r_after]*len(theta2), label=f'After: {theta_after:.3f}° (r=13 m)', color='blue')

# 装飾 Styling
ax.set_rmax(15)
ax.set_rticks([5, 10, 13]) 
ax.set_title("Same Arc Length, Different Range", va='bottom')
ax.legend(loc='lower left')

# 角度差の確認用プリント Print coordinate angles
print("=== Calculation Results ===")
print(f"弧の長さ (Arc Length): {arc_length:.4f} m")
print(f"元の角度 θ1: {theta_before:.4f}°")
print(f"射程13m時の角度 θ2: {theta_after:.4f}°")
print(f"角度差: {theta_before - theta_after:.4f}°")

plt.show()

image.png

image.png

image.png


import numpy as np
import matplotlib.pyplot as plt

# パラメータ設定 / Parameter settings
s = 5  # 最大ブレ角(最大でs度までブレる) / Max possible deviation angle in degrees
b = 0.01  # ブレ値 / Blur coefficient (smaller means more accurate)

# 乱数xとブレ角度yの関係 (式1) / Equation (1): y = s * x^(log_0.5(b))
x = np.linspace(0, 1, 1000)
exponent = np.log(b) / np.log(0.5)  # log base 0.5 of b
y = s * x ** exponent  # ブレ角度 / Deviation angle in degrees

# 命中率計算 (式2) / Equation (2): x = (y/s)^(log_b(0.5)) = (y/s)**(log(0.5)/log(b))
y_vals = np.linspace(0, s, 1000)
x_cdf = (y_vals / s) ** (np.log(0.5) / np.log(b))  # 累積分布関数 / Cumulative probability

# --- Plot 1: x vs y (Deviation angle for random number) ---
plt.figure(figsize=(10, 5))
plt.plot(x, y, label=f'b = {b}')
plt.xlabel('Random value x (0 to 1)')
plt.ylabel('Deviation angle y [°]')
plt.title('Deviation angle y versus random value x')
plt.grid(True)
plt.legend()
plt.show()

# --- Plot 2: y vs probability (CDF) ---
plt.figure(figsize=(10, 5))
plt.plot(y_vals, x_cdf, label=f'b = {b}')
plt.xlabel('Deviation angle y [°]')
plt.ylabel('Probability that deviation ≤ y')
plt.title('Probability of deviation angle being less than y (Hit rate)')
plt.grid(True)
plt.legend()
plt.show()

image.png

image.png

0
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
0
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?