I decided this weekend to create a [very] simple Swing-based game using JRuby; in a matter of hours. Although I spent most of my time failing to make it pretty with image sprites (I fell back on background colors), I ended up with a simple prototype.
#!/usr/bin/env jruby
# import java classes
import javax . swing . JFrame
import javax . swing . ImageIcon
import java . awt . Color
class Game
# define struct to represent a button
SwingButton = Struct . new ( :jbutton , :row , :column , :value )
def initialize
@frame = javax . swing . JFrame . new
# define how many in a row collapse
@adjacent_count = 3
# button/window display settings
@button_width = 100
@button_height = 100
@button_rows = 5
@button_cols = 5
@button_spacing = 5
@frame . set_size @button_width * @button_cols + (( @button_cols - 1 ) * @button_spacing ),
@button_height * @button_cols + (( @button_rows - 1 ) * @button_spacing )
# create buttons
@buttons = []
define_buttons_colors
create_buttons
# create swing frame
@frame . set_layout ( java . awt . GridLayout . new ( @button_rows , @button_cols , @button_spacing , @button_spacing ))
@frame . setDefaultCloseOperation JFrame :: EXIT_ON_CLOSE
@frame . setResizable false
@frame . show
end
# method to define RGB values for a button value
def define_buttons_colors
@button_colors = [
[ 255 , 255 , 255 ], #ffffff white
[ 255 , 153 , 153 ], #ff9999 pink
[ 255 , 153 , 102 ], #ff9966 orange
[ 255 , 255 , 153 ], #ffff99 yellow
[ 153 , 255 , 153 ], #99ff99 green
[ 102 , 255 , 204 ], #66ffcc green/blue
[ 153 , 255 , 255 ], #99ffff light blue
[ 102 , 204 , 255 ], #66ccff blue
[ 153 , 153 , 255 ], #9999ff purple
[ 255 , 153 , 255 ], #ff99ff purple/pink
]
end
def create_buttons
( 1 .. @button_rows ). each do | row |
( 1 .. @button_cols ). each do | column |
# create a new swing button
swing_button = SwingButton . new ( javax . swing . JButton . new ( "0" ), row , column , 0 )
swing_button . jbutton . setOpaque true
swing_button . jbutton . setBorderPainted false
swing_button . jbutton . setBackground Color . new ( * @button_colors [ swing_button . value ])
# add "click" action listener
swing_button . jbutton . add_action_listener do | evt |
handle_click ( swing_button , evt )
end
@buttons << swing_button
end
end
@buttons . each { | button | @frame . add button . jbutton }
end
# button click event handler
def handle_click ( swing_button , evt )
# for now, if the button has already been clicked, return
return if swing_button . value > 0
swing_button . value += 1
# looping until nothing left to collapse
begin
# check for adjacent similar values, todo
adjacent_buttons = check_adjacent_count_same_value swing_button
# update single button
if adjacent_buttons . size < @adjacent_count
swing_button . jbutton . setText swing_button . value . to_s
swing_button . jbutton . setBackground Color . new ( * @button_colors [ swing_button . value ])
return
end
adjacent_buttons . each do | button |
# clicked button
if button == swing_button
button . value += 1
button . jbutton . setText button . value . to_s
button . jbutton . setBackground Color . new ( * @button_colors [ button . value ])
# adjacent buttons
else
button . value = 0
button . jbutton . setText button . value . to_s
button . jbutton . setBackground Color . new ( * @button_colors [ button . value ])
end
end
end until check_adjacent_count_same_value ( swing_button ). size < @adjacent_count
end
def check_adjacent_count_same_value ( swing_button )
checked = []
not_checked = [ swing_button ]
while ! not_checked . empty?
button = not_checked . pop
checked << button
adjacent_buttons_with_same_value ( button ). each do | button |
next if checked . include? button
next if not_checked . include? button
not_checked << button
end
end
checked
end
def adjacent_buttons_with_same_value ( swing_button )
coordinates = []
# top
coordinates << { row: swing_button . row - 1 , column: swing_button . column } if swing_button . row > 1
# right
coordinates << { row: swing_button . row , column: swing_button . column + 1 } if swing_button . column < @button_cols
# bottom
coordinates << { row: swing_button . row + 1 , column: swing_button . column } if swing_button . row < @button_rows
# left
coordinates << { row: swing_button . row , column: swing_button . column - 1 } if swing_button . column > 1
@buttons . select { | button | coordinates . include? ({ row: button . row , column: button . column }) }. select { | button | button . value == swing_button . value }
end
end
Game . new
# run
./main.rb
The premise is to click on the buttons and 3 or more adjacent buttons in a row collapse and increment to the next higher value. Sound familiar?
Screenshot:
Todo:
umm, scoring?!
image sprites
wildcards
hazards