samples/elaborate/snake.rb
require 'glimmer-dsl-swt'
require_relative 'snake/presenter/grid'
class Snake
include Glimmer::UI::CustomShell
CELL_SIZE = 15
SNAKE_MOVE_DELAY = 100 # millis
before_body do
@game = Model::Game.new
@grid = Presenter::Grid.new(@game)
@game.start
@keypress_queue = []
display {
on_swt_keydown do |key_event|
if key_event.keyCode == 32
@game.toggle_pause
else
@keypress_queue << key_event.keyCode
end
end
}
end
after_body do
register_observers
end
body {
shell(:no_resize) {
grid_layout(@game.width, true) {
margin_width 0
margin_height 0
horizontal_spacing 0
vertical_spacing 0
}
# data-bind window title to game score, converting it to a title string on read from the model
text <= [@game, :score, on_read: -> (score) {"Snake (Score: #{@game.score})"}]
minimum_size @game.width * CELL_SIZE, @game.height * CELL_SIZE
@game.height.times do |row|
@game.width.times do |column|
canvas {
layout_data {
width_hint CELL_SIZE
height_hint CELL_SIZE
}
rectangle(0, 0, CELL_SIZE, CELL_SIZE) {
background <= [@grid.cells[row][column], :color] # data-bind square fill to grid cell color
}
}
end
end
}
}
def register_observers
observe(@game, :over) do |game_over|
async_exec do
if game_over
message_box {
text 'Game Over!'
message "Score: #{@game.score} | High Score: #{@game.high_score}"
}.open
@game.start
end
end
end
timer_exec(SNAKE_MOVE_DELAY, &method(:move_snake))
end
def move_snake
unless @game.paused? || @game.over?
process_queued_keypress
@game.snake.move
end
timer_exec(SNAKE_MOVE_DELAY, &method(:move_snake))
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
if [@game.snake.head.orientation, key] == [:north, swt(:arrow_right)] ||
[@game.snake.head.orientation, key] == [:east, swt(:arrow_down)] ||
[@game.snake.head.orientation, key] == [:south, swt(:arrow_left)] ||
[@game.snake.head.orientation, key] == [:west, swt(:arrow_up)]
@game.snake.turn_right
elsif [@game.snake.head.orientation, key] == [:north, swt(:arrow_left)] ||
[@game.snake.head.orientation, key] == [:west, swt(:arrow_down)] ||
[@game.snake.head.orientation, key] == [:south, swt(:arrow_right)] ||
[@game.snake.head.orientation, key] == [:east, swt(:arrow_up)]
@game.snake.turn_left
end
end
end
Snake.launch