あんまり賢くないシューティングゲームの弾の計算方法。まず、240x160x2テーブルを用意します。起点を239, 159として、テーブルの各要素は1.各座標までの距離、2.x単位ベクトル、3.y単位ベクトル、4.角度とします。要素はs32の10.22固定小数点、角度は0~255整数です。
あと角度テーブルで1.x単位ベクトル、2.y単位ベクトルも作ります。思いっきり容量使ってやってみようという方針でしたけど、結果は2.4MB程度となりました。ん-これはコレでありかもです。
# 補助にchatgpt先生使用 import struct import math FRAC_BITS = 22 SCALE = 1 << FRAC_BITS WIDTH = 480 HEIGHT = 320 CENTER_X = 240 - 1 CENTER_Y = 160 - 1 def float2fixed(flo): return int(flo * SCALE) def fixed2float(fix): return fix / SCALE def make_table(): table = [[None for _ in range(WIDTH)] for _ in range(HEIGHT)] for y in range(HEIGHT): for x in range(WIDTH): dx = x - CENTER_X dy = y - CENTER_Y if dx == 0 and dy == 0: fx = 0 fy = 0 dist = 0 angle = 0 else: # 距離 dist_float = math.sqrt(dx * dx + dy * dy) dist = float2fixed(dist_float) # 単位ベクトル fx = float2fixed(dx / dist_float) fy = float2fixed(dy / dist_float) # 角度(0〜255) angle_float = math.degrees(math.atan2(dy, dx)) angle = int((angle_float + 360) * 256 / 360) % 256 table[y][x] = { 'fx': fx, 'fy': fy, 'dist': dist, 'angle': angle, } return table def verify_table(table): errors = 0 maxstep = WIDTH*2 for y in range(HEIGHT): for x in range(WIDTH): entry = table[y][x] fx = entry['fx'] fy = entry['fy'] # print(f"chk:({x},{y})") x_pos = x << FRAC_BITS y_pos = y << FRAC_BITS for step in range(maxstep): x_pos -= fx y_pos -= fy # print(f"org:({CENTER_X},{CENTER_Y}) pos:({(x_pos >> FRAC_BITS)},{(y_pos >> FRAC_BITS)})") # 到達判定(±0.5ピクセル以内) if abs(x_pos - (CENTER_X << FRAC_BITS)) < (1 << (FRAC_BITS - 1)) and \ abs(y_pos - (CENTER_Y << FRAC_BITS)) < (1 << (FRAC_BITS - 1)): # print(f"Hit") break else: errors += 1 print(f"Failed to reach origin from ({x},{y})") print(f"\n検証完了。誤差数: {errors}") def save_table_array(table, filename="bullet2.h", var_name="tblMath"): with open(filename, "w") as f: f.write(f"// fx(10.22), fy(10.22), dist(10.22), angle(32)\n\n") # fx f.write(f"ROM_DATA u32 tbl_fx[320 * 480] = {{\n") for y, row in enumerate(table): for x, cell in enumerate(row): fx = cell['fx'] & 0xFFFFFFFF f.write(f" 0x{fx:08X},\n") f.write("};\n\n") # fy f.write(f"ROM_DATA u32 tbl_fy[320 * 480] = {{\n") for y, row in enumerate(table): for x, cell in enumerate(row): fy = cell['fy'] & 0xFFFFFFFF f.write(f" 0x{fy:08X},\n") f.write("};\n\n") # dist f.write(f"ROM_DATA u32 tbl_dist[320 * 480] = {{\n") for y, row in enumerate(table): for x, cell in enumerate(row): dist = cell['dist'] & 0xFFFFFFFF f.write(f" 0x{dist:08X},\n") f.write("};\n\n") # angle f.write(f"ROM_DATA u32 tbl_angle[320 * 480] = {{\n") for y, row in enumerate(table): for x, cell in enumerate(row): angle = cell['angle'] & 0xFF f.write(f" 0x{angle:02X},\n") f.write("};\n\n") # 角度 → 単位ベクトルのテーブルを作成(0〜255) f.write(f"ROM_DATA u32 tbl_vxy[256*2] = {{\n") for angle in range(256): radians = math.radians(angle * 360 / 256) fx = float2fixed(math.cos(radians)) fy = float2fixed(math.sin(radians)) fx = fx & 0xFFFFFFFF fy = fy & 0xFFFFFFFF f.write(f" 0x{fx:08X},\n") f.write(f" 0x{fy:08X},\n") f.write("};\n\n") if __name__ == "__main__": table = make_table() verify_table(table) save_table_array(table)