class MyWindow

MY WINDOW CLASS. This class is the main workhorse class of the game. It maintains all of the objects and variables associated with the game, as well

as rendering the window and allowing the user to interface with the tiles through picking. Each function is described in a comment block above the function declaration.

Constants

BOTTOM_COLOR
LBOTTOM_COLOR
LTOP_COLOR

constants that will represent the background color for the window when the user loses

TOP_COLOR

constants that will represent the background color for the window

WBOTTOM_COLOR
WTOP_COLOR

constants that will represent the background color for the window when the user wins

Public Class Methods

new(w, h) click to toggle source
Calls superclass method
# File lib/tumblr-game/gosu.rb, line 24
def initialize(w, h)

 ## define variables for the width and height of the window
 @width = w
 @height = h  
 
 ## variables for WIN or LOSE state
 @win = false
 @lose = false  
 
 ## initialize the window and caption it
 super(@width, @height, false) 
 self.caption = 'Tumblr Image Match!'
 
 ## define a variable that indicates what state the game is in
 # when phase = 0, that indicates that the user is in the "picking" stage of the game and is selecting a face down card for an
 # initial guess
 # when phase = 1, that indicates that the user is in the "matching" stage of the game and is selecting another card to see if it
 # matches the previous one. after the user clicks the mouse, the images will be shown and then they will be left face up if they match,
 # otherwise both cards will go back to facedown. phase is always set to 0 after this stage.
 @phase = 0
 @frameCounter = 0
 
 ## define two variables that indicates the ID of the first card that was selected when phase was 0 and the ID of the second card selected when
 # phase = 1
 @picked = 0
 @picked2 = 0
 
 # variable that indicates the second card was actually picked
 @pickedSecond = false
      
 ## initialize a Timer object that will keep track of the time remaining for the given game
 # also create a Gosu font object that will be passed to the Timer object
 font = Gosu::Font.new(self, Gosu::default_font_name, 20)
 @timer = Timer.new(font, @width/2, @height/2, 30)
 
 ## create a font for the end of the game, either win or lose
 @endFont = Gosu::Font.new(self, Gosu::default_font_name, 20)

 # create a pseudorandom number generator for shuffling
 prng = Random.new(Random.new_seed())
 
 # create a hash of the image names that we are using along with their associated id
 imgNames = Hash[
      File.join(Dir.home, 'Desktop/image1.png') => 0,
      File.join(Dir.home, 'Desktop/image2.png') => 1,
      File.join(Dir.home, 'Desktop/image3.png') => 2,
      File.join(Dir.home, 'Desktop/image4.png') => 3,
      File.join(Dir.home, 'Desktop/image5.png') => 4,
      File.join(Dir.home, 'Desktop/image6.png') => 0,
      File.join(Dir.home, 'Desktop/image7.png') => 1,
      File.join(Dir.home, 'Desktop/image8.png') => 2,
      File.join(Dir.home, 'Desktop/image9.png') => 3,
      File.join(Dir.home, 'Desktop/image10.png') => 4 ]
 
 ## Durstenfield's Shuffling Algorithm
 # convert the hash from above into a two-dimensional array that will be shuffled in order to
 # randomize the appearance of the images on the board
 imgArr = imgNames.to_a
 for i in(9).downto(1)
   j = prng.rand(i)
   tempK = imgArr[i][0]
   tempV = imgArr[i][1]
   imgArr[i][0] = imgArr[j][0]
   imgArr[i][1] = imgArr[j][1]
   imgArr[j][0] = tempK
   imgArr[j][1] = tempV
 end
 
 # create the Gosu images so they can be put in to each Tile object
 chk = Gosu::Image.new(self, File.join(File.dirname(File.expand_path('../..', __FILE__)), '/resources/check.png'), true)      # completion image
 img0 = Gosu::Image.new(self, File.join(File.dirname(File.expand_path('../..', __FILE__)), '/resources/tumblr.png'), true)    # the back of each card
 img1 = Gosu::Image.new(self, imgArr[0][0], true)
 img2 = Gosu::Image.new(self, imgArr[1][0], true)
 img3 = Gosu::Image.new(self, imgArr[2][0], true)
 img4 = Gosu::Image.new(self, imgArr[3][0], true)
 img5 = Gosu::Image.new(self, imgArr[4][0], true)
 img6 = Gosu::Image.new(self, imgArr[5][0], true)
 img7 = Gosu::Image.new(self, imgArr[6][0], true)
 img8 = Gosu::Image.new(self, imgArr[7][0], true)
 img9 = Gosu::Image.new(self, imgArr[8][0], true)
 img10 = Gosu::Image.new(self, imgArr[9][0], true)
 
 # initialize the game board with the tile objects
 @game_board = Board.new( Tile.new(img1, 0, 0, img0, imgArr[0][1], chk), 
                                                      Tile.new(img2, 250, 0, img0, imgArr[1][1], chk), 
                                                      Tile.new(img3, 500, 0, img0, imgArr[2][1], chk), 
                                                      Tile.new(img4, 750, 0, img0, imgArr[3][1], chk), 
                                                      Tile.new(img5, 1000, 0, img0, imgArr[4][1], chk), 
                                                      Tile.new(img6, 0, 500, img0, imgArr[5][1], chk), 
                                                      Tile.new(img7, 250, 500, img0, imgArr[6][1], chk), 
                                                      Tile.new(img8, 500, 500, img0, imgArr[7][1], chk), 
                                                      Tile.new(img9, 750, 500, img0, imgArr[8][1], chk), 
                                                      Tile.new(img10, 1000, 500, img0, imgArr[9][1], chk) )
end

Public Instance Methods

check_match() click to toggle source
the check_match function will be called after the the frameCounter has reached a certain point.

this function will check if the two tiles that have been selected match. it will compare the strings that determine each tile's id. if the strings are the same then the two tiles match; the strings are the path to that tile's main image. if the strings do not match then the tiles are flipped over and the game is set back to phase 0.

# File lib/tumblr-game/gosu.rb, line 285
def check_match
      if @phase == 1 and @pickedSecond == true
              # check if they match
              if(@game_board.get_id(@picked) == @game_board.get_id(@picked2))
                      @game_board.matchTile(@picked)
                      @game_board.matchTile(@picked2)
      
      # increment match counter
      @game_board.inc_match
              else
                      # flip the tiles
                      @game_board.flip_tile(@picked, false)
                      @game_board.flip_tile(@picked2, false)
              end
              @pickedSecond = false
              @phase = 0
      end
end
check_win() click to toggle source
this function is called at the end of the display period for images. since pictures display for a few seconds before flipping over again,

this function will allow the user to win if they flip over the last pair when the time left is less than the display period.

# File lib/tumblr-game/gosu.rb, line 340
def check_win
  if @game_board.return_count == 5 and @timer.return_time >= 0
    @win = true
  end
  if @game_board.return_count < 5 and @timer.return_time == 0
    @lose = true
  end
end
draw() click to toggle source
draw function. this function will draw one of the three backgrounds for the game. if the game is in the LOSE state, if the time has run out and the

player has not matched 5 tiles, the player loses. if the player matches 5 tiles before the time runs out, then they win. else, the regular game board is drawn for the user to play on. when the user wins or loses, that screen is displayed for 120 frames and the window calls its close function to exit properly

# File lib/tumblr-game/gosu.rb, line 147
def draw
  if (!@win and @lose) or (@frameCounter == 0 and @game_board.return_count < 5 and @timer.return_time == 0)
    draw_lose
  elsif (@win and !@lose)
    draw_win
  elsif (!@win and !@lose)
    draw_background
    @game_board.draw_board
    @timer.draw  
  end
end
draw_background() click to toggle source

function that will be used to draw a blue background with a slight gradient towards the bottom

# File lib/tumblr-game/gosu.rb, line 310
def draw_background
    draw_quad( 0, 0, TOP_COLOR,
               @width, 0, TOP_COLOR,
               0, @height, BOTTOM_COLOR,
               @width, @height, BOTTOM_COLOR,
               -1 )
end
draw_lose() click to toggle source

function that draws the background and losing font when the users loses the game

# File lib/tumblr-game/gosu.rb, line 329
def draw_lose
  draw_quad( 0, 0, LTOP_COLOR,
             @width, 0, LTOP_COLOR,
             0, @height, LBOTTOM_COLOR,
             @width, @height, LBOTTOM_COLOR,
             -1 )
  @endFont.draw("You lose...", @width/2 - 150, @height/2, 0, 4, 4, 0xFFFFFFFF)
end
draw_win() click to toggle source

function that draws the background and winning font when the user wins the game

# File lib/tumblr-game/gosu.rb, line 319
def draw_win
  draw_quad( 0, 0, WTOP_COLOR,
             @width, 0, WTOP_COLOR,
             0, @height, WBOTTOM_COLOR,
             @width, @height, WBOTTOM_COLOR,
             -1 )
  @endFont.draw("You win!", @width/2 - 150, @height/2, 0, 4, 4, 0xFFFFFFFF)
end
needs_cursor?() click to toggle source

this function specifies that the cursor should be displayed when it is inside the main gosu window

# File lib/tumblr-game/gosu.rb, line 305
def needs_cursor?
      true
end
pick_tiles() click to toggle source
pick_tiles function

this function has two parts. if the game is in phase 0, the user is picking an initial tile. the function will check the location of the user's mouse and flip the appropriate tile and keep track of which tile was flipped. then, the game is set to phase 1. in phase 1, the user is picking the tile they want to match with the first one. if a tile is successfully picked, the pickedSecond variable is set to true and the game stores which tile was picked and flipped.

# File lib/tumblr-game/gosu.rb, line 164
def pick_tiles
  if button_down? Gosu::KbEscape then
    close
  end
      if @phase == 0 
              if button_down? Gosu::MsLeft then
                      # TILE 1
                      if (mouse_x >= 0 and mouse_x <= 250) and (mouse_y >= 0 and mouse_y <= 250) and (!@game_board.is_matched(0)) then
                              @game_board.flip_tile(0, true)
                              @picked = 0
                              @phase = 1
                      # TILE 2
                      elsif (mouse_x > 250  and mouse_x <= 500) and (mouse_y >= 0 and mouse_y <= 250) and (!@game_board.is_matched(1)) then
                              @game_board.flip_tile(1, true)
                              @picked = 1
                              @phase = 1
                      # TILE 3
                      elsif (mouse_x > 500  and mouse_x <= 750) and (mouse_y >= 0 and mouse_y <= 250) and (!@game_board.is_matched(2)) then
                              @game_board.flip_tile(2, true)
                              @picked = 2
                              @phase = 1
                      # TILE 4
                      elsif (mouse_x > 750  and mouse_x <= 1000) and (mouse_y >= 0 and mouse_y <= 250) and (!@game_board.is_matched(3))then
                              @game_board.flip_tile(3, true)
                              @picked = 3
                              @phase = 1
                      # TILE 5
                      elsif (mouse_x > 1000  and mouse_x <= 1250) and (mouse_y >= 0 and mouse_y <= 250) and (!@game_board.is_matched(4)) then
                              @game_board.flip_tile(4, true)
                              @picked = 4
                              @phase = 1
                      # TILE 6
                      elsif (mouse_x >= 0 and mouse_x <= 250) and (mouse_y > 500 and mouse_y <= 750) and (!@game_board.is_matched(5)) then
                              @game_board.flip_tile(5, true)
                              @picked = 5
                              @phase = 1
                      # TILE 7
                      elsif (mouse_x > 250  and mouse_x <= 500) and (mouse_y > 500 and mouse_y <= 750) and (!@game_board.is_matched(6)) then
                              @game_board.flip_tile(6, true)
                              @picked = 6
                              @phase = 1
                      # TILE 8
                      elsif (mouse_x > 500  and mouse_x <= 750) and (mouse_y > 500 and mouse_y <= 750) and (!@game_board.is_matched(7)) then
                              @game_board.flip_tile(7, true)
                              @picked = 7
                              @phase = 1
                      # TILE 9
                      elsif (mouse_x > 750  and mouse_x <= 1000) and (mouse_y > 500 and mouse_y <= 750) and (!@game_board.is_matched(8)) then
                              @game_board.flip_tile(8, true)
                              @picked = 8
                              @phase = 1
                      # TILE 10
                      elsif (mouse_x > 1000  and mouse_x <= 1250) and (mouse_y > 500 and mouse_y <= 750) and (!@game_board.is_matched(9)) then
                              @game_board.flip_tile(9, true)
                              @picked = 9
                              @phase = 1
                      end
                      sleep(0.2) # needs delay because gosu's mouse click event seems to be hyper sensitive and picks up multiple clicks instead of 1
              end
      else @phase == 1
              if button_down? Gosu::MsLeft then
              # TILE 1
                      if (mouse_x >= 0 and mouse_x <= 250) and (mouse_y >= 0 and mouse_y <= 250) and (@picked != 0) and (!@game_board.is_matched(0)) then
                              @game_board.flip_tile(0, true)
                              @picked2 = 0
                              @pickedSecond = true
                      # TILE 2
                      elsif (mouse_x > 250  and mouse_x <= 500) and (mouse_y >= 0 and mouse_y <= 250) and (@picked != 1) and (!@game_board.is_matched(1)) then
                              @game_board.flip_tile(1, true)
                              @picked2 = 1
                              @pickedSecond = true
                      # TILE 3
                      elsif (mouse_x > 500  and mouse_x <= 750) and (mouse_y >= 0 and mouse_y <= 250) and (@picked != 2) and (!@game_board.is_matched(2)) then
                              @game_board.flip_tile(2, true)
                              @picked2 = 2
                              @pickedSecond = true
                      # TILE 4
                      elsif (mouse_x > 750  and mouse_x <= 1000) and (mouse_y >= 0 and mouse_y <= 250) and (@picked != 3) and (!@game_board.is_matched(3)) then
                              @game_board.flip_tile(3, true)
                              @picked2 = 3
                              @pickedSecond = true
                      # TILE 5
                      elsif (mouse_x > 1000  and mouse_x <= 1250) and (mouse_y >= 0 and mouse_y <= 250) and (@picked != 4) and (!@game_board.is_matched(4)) then
                              @game_board.flip_tile(4, true)
                              @picked2 = 4
                              @pickedSecond = true
                      # TILE 6
                      elsif (mouse_x >= 0 and mouse_x <= 250) and (mouse_y > 500 and mouse_y <= 750) and (@picked != 5) and (!@game_board.is_matched(5)) then
                              @game_board.flip_tile(5, true)
                              @picked2 = 5
                              @pickedSecond = true
                      # TILE 7
                      elsif (mouse_x > 250  and mouse_x <= 500) and (mouse_y > 500 and mouse_y <= 750) and (@picked != 6) and (!@game_board.is_matched(6)) then
                              @game_board.flip_tile(6, true)
                              @picked2 = 6
                              @pickedSecond = true
                      # TILE 8
                      elsif (mouse_x > 500  and mouse_x <= 750) and (mouse_y > 500 and mouse_y <= 750) and (@picked != 7) and (!@game_board.is_matched(7)) then
                              @game_board.flip_tile(7, true)
                              @picked2 = 7
                              @pickedSecond = true
                      # TILE 9
                      elsif (mouse_x > 750  and mouse_x <= 1000) and (mouse_y > 500 and mouse_y <= 750) and (@picked != 8) and (!@game_board.is_matched(8)) then
                              @game_board.flip_tile(8, true)
                              @picked2 = 8
                              @pickedSecond = true
                      # TILE 10
                      elsif (mouse_x > 1000  and mouse_x <= 1250) and (mouse_y > 500 and mouse_y <= 750) and (@picked != 9) and (!@game_board.is_matched(9)) then
                              @game_board.flip_tile(9, true)
                              @picked2 = 9
                              @pickedSecond = true
                      end
                      sleep(0.2) # needs delay because gosu's mouse click event seems to be hyper sensitive and picks up multiple clicks instead of 1
              end
      end
end
update() click to toggle source

update function. this function contains all of the game logic

# File lib/tumblr-game/gosu.rb, line 121
def update
      ## only allow the user to pick tiles if the frameCounter is at 0
      # this means that the user can only pick tiles when two tiles are not being displayed
      # after the 96 frames of display are over, we then call the check_match function and set the frameCounter back to 0
  
  if @frameCounter == 0 then 
              pick_tiles  
      elsif @frameCounter == 96 then
              check_match
    check_win
           @frameCounter = 0
      end
      
      ## if the user has picked their second tile then we increment the frame counter to display both of them for a few seconds
      if @phase == 1 and @pickedSecond then
       @frameCounter += 1
      end
  
  ## update the Timer object
  @timer.update
end