DEV Community

Andy Maleh
Andy Maleh

Posted on

Glimmer Battleship

Glimmer DSL for SWT 4.20.13.15 just shipped with Glimmer Battleship.

Mid-game battle

Glimmer Battleship

Placing ships on grid using drag and drop

Placement

All ships placed. Ready for battle.

Ready for Battle

Finished game, beating the enemy.

Finished Win

Game over message box dialog.

Game Over

You may check out the code over here.

# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#battleship require 'glimmer-dsl-swt' require 'facets/string/titlecase' require 'facets/string/underscore' require_relative 'battleship/model/game' require_relative 'battleship/view/grid' require_relative 'battleship/view/ship_collection' require_relative 'battleship/view/action_panel' class Battleship include Glimmer::UI::CustomShell COLOR_WATER = rgb(156, 211, 219) COLOR_SHIP = :dark_gray before_body do @game = Model::Game.new end after_body do observe(@game, :over) do |game_over_value| if game_over_value game_over_message = if game_over_value == :you "Game over!\nYou Won!" else "Game over!\nYou Lost!" end message_box { text 'Game Over!' message game_over_message }.open end end end body { shell(:no_resize) { grid_layout(2, false) { horizontal_spacing 15 vertical_spacing 15 } text 'Glimmer Battleship' @enemy_grid = grid(game: @game, player: :enemy) @enemy_ship_collection = ship_collection(game: @game, player: :enemy) @player_grid = grid(game: @game, player: :you) @player_ship_collection = ship_collection(game: @game, player: :you) action_panel(game: @game) } } end Battleship.launch 
Enter fullscreen mode Exit fullscreen mode
# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#battleship require_relative '../model/grid' require_relative 'cell' class Battleship module View class Grid include Glimmer::UI::CustomWidget options :game, :player body { composite { grid_layout(Model::Grid::WIDTH + 1, true) { margin_width 0 margin_height 0 horizontal_spacing 0 vertical_spacing 0 } label(:center) { layout_data(:fill, :center, true, false) { horizontal_span (Model::Grid::WIDTH + 1) } text player.to_s.capitalize font height: 20, style: :bold } label # filler Model::Grid::WIDTH.times do |column_index| label { text (column_index + 1).to_s font height: 16 } end Model::Grid::HEIGHT.times do |row_index| label { text Model::Grid::ROW_ALPHABETS[row_index] font height: 16 } Model::Grid::WIDTH.times do |column_index| cell(game: game, player: player, row_index: row_index, column_index: column_index) { layout_data { width_hint 25 height_hint 25 } } end end } } end end end 
Enter fullscreen mode Exit fullscreen mode
# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#battleship class Battleship module View class Cell include Glimmer::UI::CustomWidget class << self attr_accessor :dragging alias dragging? dragging end COLOR_WATER = rgb(156, 211, 219) COLOR_SHIP = :gray COLOR_PLACED = :white COLOR_EMPTY = :black COLOR_NO_HIT = :white COLOR_HIT = :red options :game, :player, :row_index, :column_index, :ship option :type, default: :grid # other type is :ship body { canvas { if type == :grid if player == :you background <= [model, :ship, on_read: ->(s) {s ? COLOR_SHIP : COLOR_WATER}] else background COLOR_WATER end else background <= [ship, :sunk, on_read: ->(s) {s ? COLOR_HIT : COLOR_PLACED}] background <= [ship, :top_left_cell, on_read: ->(c) {c ? COLOR_PLACED : COLOR_SHIP}] end rectangle(0, 0, [:max, -1], [:max, -1]) oval(:default, :default, 10, 10) { foreground <= [model, :hit, on_read: ->(h) {h == nil ? COLOR_EMPTY : (h ? COLOR_HIT : COLOR_NO_HIT)}] } oval(:default, :default, 5, 5) { background <= [model, :hit, on_read: ->(h) {h == nil ? COLOR_EMPTY : (h ? COLOR_HIT : COLOR_NO_HIT)}] } on_mouse_move do |event| if game.started? if type == :grid if player == :enemy body_root.cursor = :cross else body_root.cursor = :arrow end else body_root.cursor = :arrow end end end if player == :enemy on_mouse_up do game.attack!(row_index, column_index) end end if player == :you on_drag_detected do |event| unless game.started? || game.over? Cell.dragging = true body_root.cursor = :hand if type == :grid end end on_drag_set_data do |event| the_ship = ship || model&.ship if the_ship && !game.started? && !game.over? && !(type == :ship && the_ship.top_left_cell) event.data = the_ship.name.to_s else event.doit = false Cell.dragging = false end end on_mouse_up do unless game.started? || game.over? Cell.dragging = false change_cursor end end if type == :grid on_mouse_move do |event| unless game.started? || game.over? change_cursor end end on_mouse_hover do |event| unless game.started? || game.over? change_cursor end end on_mouse_up do |event| unless game.started? || game.over? begin model.ship&.toggle_orientation! rescue => e Glimmer::Config.logger.debug e.full_message end change_cursor end end on_drop do |event| unless game.started? || game.over? ship_name = event.data place_ship(ship_name.to_s.to_sym) if ship_name Cell.dragging = false change_cursor end end end end } } def model game.grids[player].cell_rows[row_index][column_index] if type == :grid end def place_ship(ship_name) ship = game.ship_collections[player].ships[ship_name] model.place_ship!(ship) end def change_cursor if type == :grid && model.ship && !Cell.dragging? body_root.cursor = model.ship.orientation == :horizontal ? :sizens : :sizewe elsif !Cell.dragging? body_root.cursor = :arrow end end end end end 
Enter fullscreen mode Exit fullscreen mode
# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#battleship require_relative '../model/game' require_relative '../model/ship_collection' require_relative 'ship' class Battleship module View class ShipCollection include Glimmer::UI::CustomWidget options :game, :player body { composite { row_layout(:vertical) { fill true margin_width 0 margin_height 0 } Model::ShipCollection::BATTLESHIPS.each do |ship_name, ship_length| ship(game: game, player: player, ship_name: ship_name, ship_length: ship_length) end } } end end end 
Enter fullscreen mode Exit fullscreen mode
# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#battleship require_relative 'cell' class Battleship module View class Ship include Glimmer::UI::CustomWidget options :game, :player, :ship_name, :ship_length body { composite { row_layout(:vertical) { fill true margin_width 0 margin_height 0 } label { text ship_name.to_s.titlecase font height: 16 } composite { grid_layout(ship_length, true) { margin_width 0 margin_height 0 horizontal_spacing 0 vertical_spacing 0 } ship_length.times do |column_index| cell(game: game, player: player, type: :ship, column_index: column_index, ship: game.ship_collections[player].ships[ship_name]) { layout_data { width_hint 25 height_hint 25 } } end } } } end end end 
Enter fullscreen mode Exit fullscreen mode
# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#battleship class Battleship module View class ActionPanel include Glimmer::UI::CustomWidget options :game body { composite { row_layout(:horizontal) { margin_width 0 margin_height 0 } layout_data(:center, :center, true, false) @battle_button = button { text 'Battle!' enabled <= [game.ship_collections[:you], :placed_count, on_read: ->(c) {c == 5}] on_widget_selected do game.battle! @battle_button.enabled = false end } button { text 'Restart' on_widget_selected do game.reset! end } } } end end end 
Enter fullscreen mode Exit fullscreen mode

This is another reminder that Glimmer DSL for SWT lets you build apps that normally take months and years in just days and weeks.

Happy Glimmering!

Top comments (0)