Je fais un jeu avec la bibliothèque python "pygame" dans le cadre de mes études à l'école. Puisqu'il s'agit d'un jeu de simulation, j'ai essayé de créer une carte hexadécimale commune, mais le code qui peut être utilisé ne frappe pas facilement. Après tout, j'ai décidé de le créer à partir de zéro. C'était ... mais j'ai demandé à l'utilisateur de Qiita shiracamus de réécrire le code enfantin! Merci beaucoup.
Site référencé http://www.redblobgames.com/grids/hexagons/ http://qiita.com/kapipara-games/items/7978a7b51a47df8ace38
environnement
my_hexmap.py
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import pygame
from pygame.locals import *
# colors (Red, Green, Blue)
BLACK = (0, 0, 0)
ORANGE = (255, 120, 0)
YELLOW = (255, 255, 0)
CYAN = (0, 255, 255)
class Hexagon:
"""
Hexagon index/pixel coordinate converter
There is no limit to the number of hexagon.
x: 0/4 1/4 3/4 4/4
y: | | | |
0/2-- v0 _____ v1
/ \
1/2-- / \
v5 \ / v2
2/2-- \_____/
v4 v3
"""
VERTEXES = (1, 0), (3, 0), (4, 1), (3, 2), (1, 2), (0, 1)
def __init__(self, size):
self.SIZE = size
self.HALF = size * 1 // 2
self.QUARTER = size * 1 // 4
self.WIDTH = size * 3 // 4
self.HEIGHT = size
def index_at(self, pixel_x, pixel_y):
"""get the index coordinae at the pixel coordinate"""
x = pixel_x // self.WIDTH
x0 = pixel_x % self.WIDTH
if x0 < self.QUARTER: # overlap area
y0 = (pixel_y - (x % 2) * self.HALF) % self.HEIGHT
if y0 >= self.HALF: # lower half
y0 = self.SIZE - y0
is_leftarea = x0 < self.QUARTER - y0 * self.QUARTER // self.HALF
if is_leftarea:
x -= 1
y = (pixel_y - (x % 2) * self.HALF) // self.HEIGHT
return x, y
def origin_of(self, x, y):
return x * self.WIDTH, y * self.HEIGHT + (x % 2) * self.HALF
def vertexes_of(self, x, y):
"""get vertex coodinates of the index coordinate"""
origin_x, origin_y = self.origin_of(x, y)
return [(origin_x + vx * self.QUARTER, origin_y + vy * self.HALF)
for vx, vy in self.VERTEXES]
class HexMap:
"""
Hexagon map
___ x,y ___
/0,0\___/2,0\
\___/1,0\___/
/0,1\___/2,1\
\___/1,1\___/
/0,2\___/2,2\
\___/ \___/
"""
def __init__(self, columns, rows, hexagon_size):
self.COLUMNS = columns
self.ROWS = rows
self.hexagon = Hexagon(hexagon_size)
width, height = self.hexagon.origin_of(self.COLUMNS, self.ROWS)
width += self.hexagon.QUARTER
self.size = width + 1, height + 1
self.clear_clicked()
def clear_clicked(self):
self.clicked = [[False] * self.ROWS for x in range(self.COLUMNS)]
def click_at(self, pixel_x, pixel_y):
x, y = self.hexagon.index_at(pixel_x, pixel_y)
if 0 <= x < self.COLUMNS and 0 <= y < self.ROWS:
self.clicked[x][y] = not self.clicked[x][y]
def is_clicked_on(self, x, y):
return (0 <= x < self.COLUMNS and 0 <= y < self.ROWS and
self.clicked[x][y])
def hexagons(self):
for x in range(self.COLUMNS):
for y in range(self.ROWS - (x % 2)):
yield self.hexagon, x, y
class HexCanvas:
LINE_WIDTH = 1
CURSOR_SIZE = 5
def __init__(self, hexmap):
self.hexmap = hexmap
self.canvas = pygame.display.set_mode(hexmap.size)
self.font = pygame.font.SysFont(None, 17)
self.cursor = None
def cursor_at(self, pixel_x, pixel_y):
self.cursor = pixel_x, pixel_y
def draw(self):
canvas = self.canvas
canvas.fill(BLACK)
hexmap = self.hexmap
for hexagon, x, y in hexmap.hexagons():
vertexes = hexagon.vertexes_of(x, y)
#Remplissage hexagonal
color = ORANGE if hexmap.is_clicked_on(x, y) else YELLOW
pygame.draw.polygon(canvas, color, vertexes)
#Dessin de bordure hexagonale
for v1, v2 in zip(vertexes, vertexes[1:] + vertexes[:1]):
pygame.draw.line(canvas, BLACK, v1, v2, self.LINE_WIDTH)
#Dessin d'étiquette de coordonnées
tag = "{0}, {1}".format(x, y)
text = self.font.render(tag, True, CYAN)
origin_x, origin_y = hexagon.origin_of(x, y)
text_area = text.get_rect(center=(origin_x + hexagon.HALF,
origin_y + hexagon.HALF))
canvas.blit(text, text_area)
#Dessin du curseur
if self.cursor:
pygame.draw.circle(canvas, BLACK, self.cursor, self.CURSOR_SIZE, 0)
def main():
pygame.init()
FPSCLOCK = pygame.time.Clock()
hexmap = HexMap(columns=20, rows=15, hexagon_size=50)
canvas = HexCanvas(hexmap)
while True:
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYDOWN and event.key == K_q:
pygame.quit()
return
if event.type == MOUSEMOTION:
x, y = pygame.mouse.get_pos()
canvas.cursor_at(x, y)
elif event.type == MOUSEBUTTONDOWN:
x, y = pygame.mouse.get_pos()
hexmap.click_at(x, y)
canvas.draw()
pygame.display.update()
FPSCLOCK.tick(30)
if __name__ == '__main__':
main()
Image de l'exécution de ce qui suit dans ubuntu
Recommended Posts