JRuby Swing-based JButton clicking game
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