Skip to content

Instantly share code, notes, and snippets.

@oeloeloel
Created April 3, 2021 05:05
Show Gist options
  • Save oeloeloel/974e05cf112aff3ae49383131917059b to your computer and use it in GitHub Desktop.
Save oeloeloel/974e05cf112aff3ae49383131917059b to your computer and use it in GitHub Desktop.
Breakout made quickly
$gtk.reset
def tick args
defaults args
handle_input args
calc args
render args
end
def handle_input args
args.state.bat_x = args.mouse.x - (args.state.bat_w / 2)
args.state.ball_active = true if args.mouse.click
if args.inputs.keyboard.key_down.space
$gtk.reset
end
end
def defaults args
args.state.num_cols ||= 16
args.state.num_rows ||= 8
args.state.brick_width ||= 80
args.state.brick_height ||= 40
args.state.bricks ||= make_bricks args
args.state.ball_size ||= 20
args.state.ball_x ||= (args.grid.w - args.state.ball_size) / 2
args.state.ball_y ||= 60
args.state.ball_active ||= false
args.state.ball_speed_x ||= 4
args.state.ball_speed_y ||= 4
args.state.bat_x ||= -1000
args.state.bat_y ||= 40
args.state.bat_w ||= 100
args.state.bat_h ||= 20
end
def calc args
return unless args.state.ball_active
next_x = args.state.ball_x + args.state.ball_speed_x
next_y = args.state.ball_y + args.state.ball_speed_y
next_ball_rect = [next_x, next_y, args.state.ball_size, args.state.ball_size]
bat_rect = [args.state.bat_x, args.state.bat_y, args.state.bat_w, args.state.bat_h]
# bounce on walls
args.state.ball_speed_x = 0 - args.state.ball_speed_x unless (0..1260) === next_x
# args.state.ball_speed_y = 0 - args.state.ball_speed_y unless (0..700) === next_y
args.state.ball_speed_x = 0 - args.state.ball_speed_x if 720 < next_y
if next_y < 0
$gtk.reset
return
end
# HIT DETECTOR
hit_brick = false
top_bottom_hits = 0
left_right_hits = 0
args.state.bricks.map_2d do |col, row, brick|
next if brick == []
if brick.intersect_rect? next_ball_rect
args.state.bricks[col][row] = []
hit_brick = true
# check the last position of the ball
# keep track of the numbers of horizontal or vertical sides the ball crossed
# if the ball's top or bottom is outside of the brick, it crossed a horizontal
top_bottom_hits += 1 if args.state.ball_y + args.state.ball_size <= brick[1] ||
args.state.ball_y >= brick[1] + brick[3]
# if the ball's left or right is outside of the brick, it crossed a vertical
left_right_hits += 1 if args.state.ball_x + args.state.ball_size <= brick[0] ||
args.state.ball_x >= brick[0] + brick[2]
end
end
if hit_brick
# puts [left_right_hits, top_bottom_hits]
# bounce x
# if the ball crossed 1 horizontal, no vertical (it hit one brick)
# or the ball crossed 2 horizontals, 0-1 vertical (it hit two bricks side by side)
if left_right_hits > top_bottom_hits
ball_bounce(args, true, false)
# bounce y
# if the ball crossed 1 vertical, no hotizontal (it hit one brick)
# or the ball crossed 2 verticals, 0-1 horizontal (it hit two bricks, one on top of the other)
elsif top_bottom_hits > left_right_hits
ball_bounce(args, false, true)
# bounce x and y
# if the ball crossed 1 vertical and 1 horizontal
# (it hit the corner of 1 brick, or the corner between 2 bricks)
else
ball_bounce(args, true, true)
end
end
# hit bat
if bat_rect.intersect_rect? next_ball_rect
top_bottom_hits = 0
left_right_hits = 0
bounce_y = args.state.ball_y + args.state.ball_size <= bat_rect[1] ||
args.state.ball_y >= bat_rect[1] + bat_rect[3]
bounce_x = args.state.ball_x + args.state.ball_size <= bat_rect[0] ||
args.state.ball_x >= bat_rect[0] + bat_rect[2]
# do something if the ball hits near the end of the bat
bat_strike_point = next_x - bat_rect[0]
if bat_strike_point < 20
args.state.ball_speed_x -= 0.5
end
if bat_strike_point > bat_rect[2] - args.state.ball_size
args.state.ball_speed_x += 0.5
end
ball_bounce(args, bounce_x, bounce_y)
end
args.state.ball_x = next_x
args.state.ball_y = next_y
end
def ball_bounce(args, bounce_x, bounce_y)
args.state.ball_speed_x = 0 - args.state.ball_speed_x if bounce_x
args.state.ball_speed_y = 0 - args.state.ball_speed_y if bounce_y
end
def make_bricks args
args.state.bricks = args.state.num_cols.times.map do |c|
args.state.num_rows.times.map do |r|
[
c * args.state.brick_width,
720 - (r + 1) * args.state.brick_height,
args.state.brick_width,
args.state.brick_height,
'sprites/square/green.png'
]
end
end
end
def render args
args.outputs.sprites << [
args.state.ball_x,
args.state.ball_y,
args.state.ball_size,
args.state.ball_size,
'sprites/square/red.png'
]
args.outputs.sprites << [
args.state.bat_x,
args.state.bat_y,
args.state.bat_w,
args.state.bat_h,
'sprites/square/blue.png'
]
args.outputs.sprites << args.state.bricks
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment