Skip to content

Instantly share code, notes, and snippets.

@xenobrain
Last active January 5, 2023 16:07
Show Gist options
  • Save xenobrain/b652a3ad7f43bd9f501fea3d514d8588 to your computer and use it in GitHub Desktop.
Save xenobrain/b652a3ad7f43bd9f501fea3d514d8588 to your computer and use it in GitHub Desktop.
starting point for a hex based game
include MatrixFunctions
# Math constants
K_INV_6 = 1.0 / 6.0
K_2_OVER_3 = 2.0 / 3.0
K_2_PI = Math::PI * 2.0
K_SQRT_3 = Math.sqrt 3.0
K_NEG_1_OVER_3 = -1.0 / 3.0
K_DEG2RAD = Math::PI / 180.0
K_RAD2DEG = 360.0 / (2.0 * Math::PI)
K_HALF_SQRT_3 = 0.5 * (Math.sqrt 3.0)
K_SQRT_3_OVER_3 = (Math.sqrt 3.0) / 3.0
# Galaxy constants
GALAXY_WIDTH = 18
GALAXY_HEIGHT = 12
GALAXY_NUM_STARS = 30
GALAXY_CELL_WIDTH = 25.0
GALAXY_CELL_HEIGHT = 25.0
GALAXY_MAP_SHAPE = :hexagon
HALF_GALAXY_WIDTH = GALAXY_WIDTH >> 1
HALF_GALAXY_HEIGHT = GALAXY_HEIGHT >> 1
HALF_GALAXY_CELL_WIDTH = GALAXY_CELL_WIDTH * 0.5
HALF_GALAXY_CELL_HEIGHT = GALAXY_CELL_HEIGHT * 0.5
INV_HALF_GALAXY_CELL_WIDTH = 1.0 / HALF_GALAXY_CELL_WIDTH
INV_HALF_GALAXY_CELL_HEIGHT = 1.0 / HALF_GALAXY_CELL_HEIGHT
def tick args
defaults args
render args
input args
calc args
end
def defaults args
args.grid.origin_center!
args.state.galaxy ||= create_galaxy args
args.state.camera ||= create_camera args
args.state.mouse_x ||= args.inputs.mouse.x
args.state.mouse_y ||= args.inputs.mouse.y
end
def render args
render_galaxy args
end
def input args
if args.inputs.mouse.button_left
c = find_cell args
if c
c.vertices.each do |vertex|
args.outputs.sprites << { x: args.state.camera.position.x + vertex.x, y: args.state.camera.position.y + vertex.y, w: 20, h: 20, path: 'sprites/circle/blue.png'}
end
end
args.state.camera.position.x += args.inputs.mouse.x - args.state.mouse_x
args.state.camera.position.y += args.inputs.mouse.y - args.state.mouse_y
end
args.state.mouse_x = args.inputs.mouse.x
args.state.mouse_y = args.inputs.mouse.y
end
def calc args
end
def create_camera args
{ position: (vec2 0.0, 0.0) }
end
def calc_vertices q, r
center_x = 1.5 * q * HALF_GALAXY_CELL_WIDTH
center_y = (K_HALF_SQRT_3 * q + K_SQRT_3 * r) * HALF_GALAXY_CELL_HEIGHT
6.times.map do |index|
angle = K_2_PI * index * K_INV_6
offset_x = HALF_GALAXY_CELL_WIDTH * (Math.cos angle)
offset_y = HALF_GALAXY_CELL_HEIGHT * (Math.sin angle)
vec2 center_x + offset_x, center_y + offset_y
end
end
def create_galaxy args
galaxy = {}
case GALAXY_MAP_SHAPE
when :hexagon
radius = [GALAXY_WIDTH, GALAXY_HEIGHT].max >> 1
(-radius..radius).flat_map do |q|
([-radius, -(q + radius)].max..[radius, radius - q].min).map do |r|
galaxy[[q, r]] = { vertices: (calc_vertices q, r) }
end
end
when :rectangle
(-HALF_GALAXY_WIDTH..HALF_GALAXY_WIDTH).each do |q|
(-HALF_GALAXY_HEIGHT - (q >> 1)..HALF_GALAXY_HEIGHT - (q >> 1)).each do |r|
galaxy[[q, r]] = { vertices: (calc_vertices q, r) }
end
end
end
galaxy
end
def find_cell args
x = (args.inputs.mouse.x - args.state.camera.position.x) * INV_HALF_GALAXY_CELL_WIDTH
y = (args.inputs.mouse.y - args.state.camera.position.y) * INV_HALF_GALAXY_CELL_HEIGHT
q = (K_2_OVER_3 * x).round
r = (K_NEG_1_OVER_3 * x + K_SQRT_3_OVER_3 * y).round
args.state.galaxy[[q, r]]
end
def render_galaxy args
camera_x = args.state.camera.position.x
camera_y = args.state.camera.position.y
args.outputs.lines << args.state.galaxy.each_value.map do |cell|
cell.vertices.map.with_index do |vertex, index|
next_vertex = cell.vertices.at (index + 1) % 6
{ x: camera_x + vertex.x, y: camera_y + vertex.y, x2: camera_x + next_vertex.x, y2: camera_y + next_vertex.y, r: 100, g: 100, b: 100 }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment