コードの実行結果
ヘックスを押して移動を押すと、移動範囲3ヘックス分が表示される
停止ボタンまたは他のどこかの範囲を選択すると移動範囲が消え、最初の画面に戻る
コードの内容
先日投稿した記事(pythonのarcadeでhexmapを作成してみた!)に以下の機能を追加しました。
追加した内容
ヘックスを押して⇨移動ボタンを押す⇨範囲が表示
停止または違う箇所を押すと、範囲が消える
コード
import arcade
import math
import arcade.gui
WIDTH = 800
HEIGHT = 600
RADIUS = 30 # 半径
GRID_SIZE = 10 # hexの個数
TITLE = "test_hexmap"
# ボタンの配色の設定
default_style = {
"font_name": ("calibri", "Hiragino Sans")
, "font_size": 15
, "font_color": arcade.color.WHITE
, "border_width": 2
, "border_color": None
, "bg_color": (21, 19, 21),
# used if button is pressed
"bg_color_pressed": arcade.color.WHITE,
"border_color_pressed": arcade.color.WHITE, # also used when hovered
"font_color_pressed": arcade.color.BLACK,
}
"""
実現したこと
- ヘックスを押して⇨移動を押す⇨範囲が表示
- 停止または違う箇所を押すと、範囲が消える
"""
class UnitControlButtons:
def __init__(self, window, hex_map):
self.manager = arcade.gui.UIManager(window)
self.manager.enable()
self.hex_map = hex_map
self.window = window
# 移動ボタンの作成
move_button = arcade.gui.UIFlatButton(text="移動", style=default_style)
move_button.on_click = self.on_move_click
# 停止ボタンの作成
stop_button = arcade.gui.UIFlatButton(text="停止", style=default_style)
stop_button.on_click = self.on_stop_click
# ボタンの間隔を設定
v_box = arcade.gui.UIBoxLayout()
v_box.add(move_button.with_space_around(bottom=10))
v_box.add(stop_button)
# Add the layout to the UI manager
self.manager.add(arcade.gui.UIAnchorWidget(anchor_x="left", anchor_y="center_y", child=v_box))
def on_move_click(self, event):
print("ユニット移動")
if self.window.clicked_hex:
self.window.highlight = True
self.window.on_draw()
def on_stop_click(self, event):
print("ユニット停止")
self.window.highlight = False
self.window.on_draw()
class Hexmap:
def __init__(self, radius, grid_size):
self.radius = radius
self.grid_size = grid_size
self.hex_centers = []
# 頂点の計算
def hexagon_vertices(self, x, y):
vertices = []
for i in range(6):
angle = i * math.pi / 3
vx = x + self.radius * math.cos(angle)
vy = y + self.radius * math.sin(angle)
vertices.append((vx, vy))
return vertices
# ヘックスマップの描画
def draw_hexagon(self, highlight_trigger=False, clicked_hex=None):
root_3 = math.sqrt(3)
horizontal_spacing = 3 * self.radius / 2
vertical_spacing = root_3 * self.radius
for row in range(self.grid_size):
for col in range(self.grid_size):
x = col * horizontal_spacing
y = row * vertical_spacing
if col % 2 == 1:
y += vertical_spacing / 2
self.hex_centers.append((x, y))
points_list = self.hexagon_vertices(x, y)
self.draw_single_hexagon(x, y, points_list, clicked_hex, highlight_trigger)
def draw_single_hexagon(self, x, y, points_list, clicked_hex, highlight_trigger):
if clicked_hex and highlight_trigger == True:
# 距離を計算
dx = x - clicked_hex[0]
dy = y - clicked_hex[1]
distance = math.sqrt(dx**2 + dy**2)
if distance <= self.radius * 5.5: # ハイライト範囲内
self.draw_highlighted_hexagon(points_list)
else:
self.draw_normal_hexagon(points_list)
else:
self.draw_normal_hexagon(points_list)
# ハイライトヘックスを表示
def draw_highlighted_hexagon(self, points_list):
arcade.draw_polygon_filled(point_list=points_list, color=(255, 0, 0, 50))
arcade.draw_polygon_outline(point_list=points_list, color=arcade.color.BLACK, line_width=2)
# 通常のヘックスを表示
def draw_normal_hexagon(self, points_list):
arcade.draw_polygon_outline(point_list=points_list, color=arcade.color.BLACK, line_width=2)
def get_clicked_hex(self, mouse_x, mouse_y):
for center in self.hex_centers:
dx = mouse_x - center[0]
dy = mouse_y - center[1]
distance = math.sqrt(dx**2 + dy**2)
if distance <= self.radius:
return center
return None
class MyHexMap(arcade.Window):
def __init__(self, width, height, title):
super().__init__(width, height, title)
self.hex_map = Hexmap(radius=RADIUS, grid_size=GRID_SIZE)
self.clicked_hex = None
self.highlight = False
self.button_control = UnitControlButtons(self, self.hex_map)
def setup(self):
arcade.set_background_color(arcade.color.WHITE)
def on_draw(self):
arcade.start_render()
self.button_control.manager.draw()
self.hex_map.draw_hexagon(highlight_trigger=self.highlight, clicked_hex=self.clicked_hex)
def on_mouse_press(self, x, y, button, modifiers):
self.clicked_hex = self.hex_map.get_clicked_hex(mouse_x=x,mouse_y=y)
if self.clicked_hex:
print(f"Clicked hex point {self.clicked_hex}")
def on_key_press(self, symbol, modifiers):
if symbol == arcade.key.Q:
arcade.close_window()
def main():
myhexmap = MyHexMap(width=WIDTH, height=HEIGHT, title=TITLE)
myhexmap.setup()
arcade.run()
if __name__ == "__main__":
main()
他にもこんなのやってます!
- pythonのarcadeでhexmapを作成してみた!
- Python&arcadeで簡単!レトロ風シューティングゲームを作ろう!🚀
- pythonのarcadeを使って、ユニット選択とボタンの表示をやってみた
参考文献
-
- 計算方法や配置を理解するの参考になった良記事
-
- arcade公式サイト
-
- これらの記事は、様々なプログラミング言語やライブラリを用いてテキストを描画する方法を解説
- ここには、日本語の設定方法は載っていないので注意
- いい感じの日本語にしたい場合は、「Hiragino Sans」を使う
-
Gemini