Skip to content

Animating cascading cards

kkrmno edited this page Mar 19, 2020 · 1 revision

Animating cascading cards

Using a small image: , the following “waterfall” animation is generated:

require "imgrb"

width = 400
height = 300
background = Imgrb::Image.new(width, height, [0, 150, 20])

card_img = Imgrb::Image.new("ace_of_spades.png")
#Make grayscale card image rgb to match background
card_img_rgb = Imgrb::Image.new(card_img, card_img, card_img)

#Point that determines starting positions of cards
anchor_x = 20
anchor_y = 20

#Place card into first frame
background.paste(anchor_x, anchor_y, card_img_rgb)


#Method to update card position and speed
def update_card_pos(current_x, current_y, speed_x, speed_y, height, card_height, gravity)
  new_x = current_x + speed_x
  new_y = current_y + speed_y

  if new_y + card_height > height
    new_y = height - card_height
    speed_y = -speed_y
  end

  speed_y = speed_y + gravity

  return [new_x.round, new_y.round, speed_x*0.99, speed_y*0.99]
end

num_cards = 2
num_cards.times do
  |off|

  #Throw from left or right?
  mult = off % 2 == 0 ? 1 : -1
  card_x = (mult*anchor_x) % (width - card_img_rgb.width)
  card_y = anchor_y+off*25
  speed_x = (3+off*1.5)*mult
  speed_y = 0

  #Initial position and speed
  card_x, card_y, speed_x, speed_y = update_card_pos(card_x, card_y, speed_x, speed_y,
                                                     height, card_img_rgb.height, 1)
  #Update card position and speed until it reaches an edge (left or right)
  while (card_x + card_img_rgb.width) <= background.width && card_x >= 0

    speed_x = mult if speed_x.abs < 1 #Always move the card at least one pixel

    #Only the card image needs to be pushed as a frame (not the entire width x height-image),
    #since it is simply pasted on top of the image from the previous frame data at the
    #appropriate position. This results in a smaller image.
    background.push_frame(card_img_rgb, card_x, card_y, 1, 24, :none, :source)
    card_x, card_y, speed_x, speed_y = update_card_pos(card_x, card_y, speed_x, speed_y,
                                                       height, card_img_rgb.height, 1)

  end

end

#Add a comment describing the image.
background.add_text("Comment", "Animation of cascading cards.")

background.save("animated_card_cascade.png")
Clone this wiki locally