Snake
A starting point for a simple snake game on a 80x60 grid (640x480 px).
I was planning to use @sn[:trail] for collision detection.. but that went south and I added @map and the @mapper lambda for that.
Missing: no food, no points, no start- or exit screen.
Defaults right now to a 88 grid long snake.
Keys: arrow keys & ‘q’ for quit.
require 'ruby2d'
DIFFICULTY, SPEED, WRAP, GROW = nil, 30, true, 2
case DIFFICULTY
when 1 then SPEED, WRAP, GROW = 30, true, 1
when 2 then SPEED, WRAP, GROW = 40, true, 2
when 3 then SPEED, WRAP, GROW = 50, true, 3
when 4 then SPEED, WRAP, GROW = 55, false, 3
when 5 then SPEED, WRAP, GROW = 60, false, 5
end
set fps_cap: SPEED
@mapper = ->(x,y, set) { @map[y/8][x/8] = (set ? '1' : '0') }
@map = [].tap {|ar| 60.times {ar << '0' * 80 } }
@mapper.(320, 240, true)
class Integer alias :btw :between? end
class Array alias :→ :include? end
class Pos
attr_accessor :x, :y
def initialize(x, y) = ( @x, @y = x, y )
end
@sn = { len: 88, trail: [Square.new(x: 320, y: 240, size: 8)],
pos: Pos.new(40, 30), dir: Pos.new(8, 0) }
def grow_or_move(pos, grow: false)
abort('oroboro') if @map[pos.y/8][pos.x/8] == '1'
@sn[:trail] << (grow ? Square.new(size: 8) : @sn[:trail].shift)
@mapper.(pos.x, pos.y, true)
@mapper.(@sn[:trail].last.x, @sn[:trail].last.y, false) unless grow
@sn[:trail].last.x, @sn[:trail].last.y = pos.x, pos.y
end
on :key_down do |e|
if %w(left right).→(e.key) && @sn[:dir].x.zero?
@sn[:dir].x, @sn[:dir].y = (e.key == 'left') ? -8 : 8, 0
elsif %w(up down).→(e.key) && @sn[:dir].y.zero?
@sn[:dir].y, @sn[:dir].x = (e.key == 'up') ? -8 : 8, 0
else close if e.key == 'q'
end
end
update do
grow_or_move(Pos.new(@sn[:trail].last.x += @sn[:dir].x, @sn[:trail].last.y += @sn[:dir].y), grow: @sn[:trail].size <= @sn[:len])
if WRAP
@sn[:trail].last.x, @sn[:trail].last.y = @sn[:trail].last.x % 640, @sn[:trail].last.y % 480
else abort('outside') unless @sn[:trail].last.x.btw(0, 640) && @sn[:trail].last.y.btw(0, 480)
end
end
show