-
Notifications
You must be signed in to change notification settings - Fork 17
/
snake.rb
95 lines (81 loc) · 2.59 KB
/
snake.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
require 'glimmer-dsl-libui'
require_relative 'snake/presenter/grid'
class Snake
include Glimmer
CELL_SIZE = 15
SNAKE_MOVE_DELAY = 0.1
def initialize
@game = Model::Game.new
@grid = Presenter::Grid.new(@game)
@game.start
@keypress_queue = []
create_gui
register_observers
end
def launch
@main_window.show
end
def register_observers
observe(@game, :over) do |game_over|
Glimmer::LibUI.queue_main do
if game_over
msg_box('Game Over!', "Score: #{@game.score} | High Score: #{@game.high_score}")
@game.start
end
end
end
Glimmer::LibUI.timer(SNAKE_MOVE_DELAY) do
unless @game.paused? || @game.over?
process_queued_keypress
@game.snake.move
end
end
end
def process_queued_keypress
# key press queue ensures one turn per snake move to avoid a double-turn resulting in instant death (due to snake illogically going back against itself)
key = @keypress_queue.shift
case [@game.snake.head.orientation, key]
in [:north, :right] | [:east, :down] | [:south, :left] | [:west, :up]
@game.snake.turn_right
in [:north, :left] | [:west, :down] | [:south, :right] | [:east, :up]
@game.snake.turn_left
else
# No Op
end
end
def create_gui
@main_window = window {
# data-bind window title to game score, converting it to a title string on read from the model
title <= [@game, :score, on_read: -> (score) {"Snake (Score: #{@game.score})"}]
content_size @game.width * CELL_SIZE, @game.height * CELL_SIZE
resizable false
vertical_box {
padded false
@game.height.times do |row|
horizontal_box {
padded false
@game.width.times do |column|
area {
square(0, 0, CELL_SIZE) {
fill <= [@grid.cells[row][column], :color] # data-bind square fill to grid cell color
}
on_key_down do |area_key_event|
handled = true # assume we will handle the event
if area_key_event[:key] == ' '
@game.toggle_pause
elsif %i[up right down left].include?(area_key_event[:ext_key])
@keypress_queue << area_key_event[:ext_key]
else
handled = false # we won't handle the event after all
end
handled
end
}
end
}
end
}
}
end
end
Snake.new.launch