Created
August 6, 2019 15:43
-
-
Save amirrajan/30be700d54d05e102f14653d7871bfa8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Game | |
attr_accessor :args, :state, :inputs, :outputs, :grid | |
def update_line_of_sight | |
variations = [-1, 0, 1] | |
newly_visible = variations.product(variations).flat_map do |rise, run| | |
thick_line_of_sight state.x, state.y, rise, run, 15, | |
lambda { |x, y| dungeon_cell_exists? x, y } | |
end.uniq | |
state.dungeon.each do |d| | |
d.is_visible = newly_visible.find { |v| v.x == d.x && v.y == d.y } | |
end | |
end | |
def label text, x, y, color = nil | |
color ||= white | |
[x, y, text, 1, 1, *color] | |
end | |
def cell_border x, y, color = nil | |
[left_margin + x * grid_size, | |
bottom_margin + y * grid_size, | |
grid_size, | |
grid_size, | |
*color] | |
end | |
def green | |
[60, 200, 100] | |
end | |
def blue | |
[50, 50, 210] | |
end | |
def white | |
[255, 255, 255] | |
end | |
def red | |
[230, 80, 80] | |
end | |
def orange | |
[255, 80, 60] | |
end | |
def pink | |
[255, 0, 200] | |
end | |
def gray | |
[75, 75, 75] | |
end | |
def recolor_border border, r, g, b | |
border[4] = r | |
border[5] = g | |
border[6] = b | |
border | |
end | |
def left_margin | |
40 | |
end | |
def bottom_margin | |
60 | |
end | |
def grid_size | |
40 | |
end | |
def render_canvas | |
return | |
outputs.borders << state.canvas.map do |c| | |
c.border | |
end | |
end | |
def export_dungeon | |
state.dungeon.each do |d| | |
puts "state.dungeon << [#{d.x}, #{d.y}]" | |
end | |
end | |
def print_cell_coordinates | |
return unless state.debug | |
state.dungeon.each do |d| | |
outputs.labels << [grid_x(d.x) + 2, | |
grid_y(d.y) - 2, | |
"#{d.x},#{d.y}", | |
-2, 0, *white] | |
end | |
end | |
def distance_to_cell cell | |
distance_to state.x, cell.x, state.y, cell.y | |
end | |
def distance_to from_x, x, from_y, y | |
(from_x - x).abs + (from_y - y).abs | |
end | |
def render_dungeon | |
outputs.solids << [0, 0, grid.w, grid.h] | |
outputs.borders << state.dungeon.map do |d| | |
d.alpha += if d.is_visible | |
255.fdiv(30) | |
else | |
255.fdiv(600) * -1 | |
end | |
d.alpha = d.alpha.cap_min_max(0, 255) | |
cell_border d.x, d.y, [*blue, d.alpha] | |
end.reject_nil | |
end | |
def render_player | |
outputs.labels << [grid_x(state.x) + 20, | |
grid_y(state.y) + 35, | |
"@", | |
1, 1, *white] | |
end | |
def grid_x x | |
left_margin + x * grid_size | |
end | |
def grid_y y | |
bottom_margin + y * grid_size | |
end | |
def render_enemies | |
state.enemies.map do |e| | |
alpha = 255 | |
if e.is_dead | |
alpha = 255 * state.tick_count.perc_to_zero(e.attacked_at, 30) | |
end | |
outputs.labels << [ | |
left_margin + 20 + e.x * grid_size, | |
bottom_margin + 35 + e.y * grid_size, | |
"r", | |
1, 1, *white, alpha] | |
outputs.borders << [grid_x(e.x), grid_y(e.y), grid_size, grid_size, *red] | |
end | |
end | |
def visible? cell | |
state.visible_cells.find { |c| c.x == cell.x && c.y == cell.y} | |
end | |
def calc_canvas | |
return if state.canvas.length > 0 | |
15.times do |x| | |
15.times do |y| | |
state.canvas << state.new_entity(:canvas) do |c| | |
c.x = x | |
c.y = y | |
c.border = [left_margin + x * grid_size, | |
bottom_margin + y * grid_size, | |
grid_size, | |
grid_size, | |
*white, 30] | |
end | |
end | |
end | |
end | |
def input_click_map | |
return unless inputs.mouse.click | |
canvas_entry = state.canvas.find do |c| | |
inputs.mouse.click.inside_rect? c.border | |
end | |
puts canvas_entry | |
end | |
def dungeon_cell_exists? x, y | |
state.dungeon.find { |d| d.x == x && d.y == y } | |
end | |
def enemy_at x, y | |
state.enemies.find { |e| e.x == x && e.y == y && !e.is_dead } | |
end | |
def input_target_cell | |
if inputs.keyboard.key_down.up | |
[state.x, state.y + 1, 0, 1] | |
elsif inputs.keyboard.key_down.down | |
[state.x, state.y - 1, 0, -1] | |
elsif inputs.keyboard.key_down.left | |
[state.x - 1, state.y, -1, 0] | |
elsif inputs.keyboard.key_down.right | |
[state.x + 1, state.y, 1, 0] | |
else | |
nil | |
end | |
end | |
def thick_line_of_sight start_x, start_y, rise, run, distance, cell_exists_lambda | |
result = [] | |
result += line_of_sight start_x, start_y, rise, run, distance, cell_exists_lambda | |
result += line_of_sight start_x - 1, start_y, rise, run, distance, cell_exists_lambda | |
result += line_of_sight start_x + 1, start_y, rise, run, distance, cell_exists_lambda | |
result | |
end | |
def line_of_sight start_x, start_y, rise, run, distance, cell_exists_lambda | |
result = [] | |
points = points_on_line start_x, start_y, rise, run, distance | |
points.each do |p| | |
if cell_exists_lambda.call(p.x, p.y) | |
result << p | |
else | |
return result | |
end | |
end | |
result | |
end | |
def points_on_line start_x, start_y, rise, run, distance | |
distance.times.map do |i| | |
[start_x + run * i, start_y + rise * i] | |
end | |
end | |
def defaults | |
state.canvas ||= [] | |
state.dungeon ||= [] | |
state.enemies ||= [] | |
if !state.area | |
load_area_one | |
derive_dungeon_from_area | |
state.x = 7 | |
state.y = 5 | |
state.enemies << state.new_entity(:enemy) do |e| | |
e.x = 13 | |
e.y = 5 | |
e.previous_hp = 3 | |
e.hp = 3 | |
e.max_hp = 3 | |
e.is_dead = false | |
end | |
update_line_of_sight | |
end | |
end | |
def derive_dungeon_from_area | |
state.dungeon = [] | |
state.area.each do |a| | |
state.dungeon << state.new_entity(:dungeon_cell) do |d| | |
d.x = a.x | |
d.y = a.y | |
d.is_visible = false | |
d.alpha = 0 | |
d.border = [left_margin + a.x * grid_size, | |
bottom_margin + a.y * grid_size, | |
grid_size, | |
grid_size, | |
*blue, | |
255] | |
d | |
end | |
end | |
end | |
def input_move | |
x, y, x_diff, y_diff = input_target_cell | |
return unless dungeon_cell_exists? x, y | |
return if enemy_at x, y | |
state.x += x_diff | |
state.y += y_diff | |
update_line_of_sight | |
end | |
def load_area_one | |
state.area ||= [] | |
state.area << [8, 6] | |
state.area << [7, 6] | |
state.area << [7, 7] | |
state.area << [8, 9] | |
state.area << [7, 8] | |
state.area << [7, 9] | |
state.area << [6, 4] | |
state.area << [7, 3] | |
state.area << [7, 4] | |
state.area << [6, 5] | |
state.area << [7, 5] | |
state.area << [8, 5] | |
state.area << [8, 4] | |
state.area << [1, 1] | |
state.area << [0, 1] | |
state.area << [0, 2] | |
state.area << [1, 2] | |
state.area << [2, 2] | |
state.area << [2, 1] | |
state.area << [2, 3] | |
state.area << [1, 3] | |
state.area << [1, 4] | |
state.area << [2, 4] | |
state.area << [2, 5] | |
state.area << [1, 5] | |
state.area << [2, 6] | |
state.area << [3, 6] | |
state.area << [4, 6] | |
state.area << [4, 7] | |
state.area << [4, 8] | |
state.area << [5, 8] | |
state.area << [5, 9] | |
state.area << [6, 9] | |
state.area << [7, 10] | |
state.area << [7, 11] | |
state.area << [7, 12] | |
state.area << [7, 12] | |
state.area << [7, 13] | |
state.area << [8, 13] | |
state.area << [9, 13] | |
state.area << [10, 13] | |
state.area << [11, 13] | |
state.area << [12, 13] | |
state.area << [12, 12] | |
state.area << [8, 12] | |
state.area << [9, 12] | |
state.area << [10, 12] | |
state.area << [11, 12] | |
state.area << [12, 11] | |
state.area << [13, 11] | |
state.area << [13, 10] | |
state.area << [13, 9] | |
state.area << [13, 8] | |
state.area << [13, 7] | |
state.area << [13, 6] | |
state.area << [12, 6] | |
state.area << [14, 6] | |
state.area << [14, 5] | |
state.area << [13, 5] | |
state.area << [12, 5] | |
state.area << [12, 4] | |
state.area << [13, 4] | |
state.area << [14, 4] | |
state.area << [1, 6] | |
state.area << [6, 6] | |
end | |
def tick | |
defaults | |
render_canvas | |
render_dungeon | |
render_player | |
render_enemies | |
print_cell_coordinates | |
calc_canvas | |
input_move | |
input_click_map | |
end | |
end | |
$game = Game.new | |
def tick args | |
$game.args = args | |
$game.state = args.state | |
$game.inputs = args.inputs | |
$game.outputs = args.outputs | |
$game.grid = args.grid | |
$game.tick | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment