# leafo/ludum-dare-26

Fetching contributors…
Cannot retrieve contributors at this time
249 lines (174 sloc) 4.87 KB
 { graphics: g } = love import insert from table export * -- 3 point bezier bez3 = (x1, y1, x2, y2, x3, y3, t) -> tt = 1 - t x = tt * (tt * x1 + t * x2) + t * (tt * x2 + t * x3) y = tt * (tt * y1 + t * y2) + t * (tt * y2 + t * y3) x,y -- derivative of 3 point bez bez3_prime = (x1, y1, x2, y2, x3, y3, t) -> tt = 1 - t x = 2 * tt * (x2 - x1) + 2 * t * (x3 - x2) y = 2 * tt * (y2 - y1) + 2 * t * (y3 - y2) x,y reverse = (t) -> return for i=#t,1,-1 do t[i] class Thing speed: 200 new: (@x, @y) => @flip = false update: (dt) => {:fx, :fy, :tx, :ty, :cx, :cy} = @ if tx and fx before = @time @time += dt * @tscale if @time > 1 @x, @y = @tx, @ty @tx, @ty = nil, nil else -- wow this is lame ax, ay = bez3 fx, fy, cx, cy, tx, ty, before bx, by = bez3 fx, fy, cx, cy, tx, ty, @time dx = bx - ax dy = by - ay @x += dx @y += dy draw: => g.point @x ,@y move_to: (@tx, @ty) => @time = 0 @fx, @fy = @x, @y move = Vec2d(@tx - @fx, @ty - @fy) move_len = move\len! control_len = 1 + move_len / 4 dir = move\normalized!\cross! dir = dir\flip! if @flip @flip = not @flip @cx = (@tx + @fx) / 2 + dir[1] * control_len @cy = (@ty + @fy) / 2 + dir[2] * control_len @tscale = 1 / move_len * @speed -- stores enemies in the entity list in the world class EnemySpawner extends Sequence new: (@world, num_enemies=3) => super -> for i=1, num_enemies targets = PathEnemy\gen_targets @world, 2 if math.random! < 0.5 targets = reverse targets {ix, iy} = table.remove targets, 1 -- @world.entities\add Enemy 0, 100, Vec2d(100, 0) @world.entities\add PathEnemy ix, iy, targets wait 2.0 draw: => class Enemy extends Box is_enemy: true w: 30 h: 30 life: 100 color: { 209, 100, 121 } lazy_value @, "sprite", -> Player.sprite new: (@x, @y, @vel=Vec2d(0,0), @accel=Vec2d(0,0))=> shoot: (world, dir) => sfx\play "enemy_shoot" dir = (Vec2d(world.player.box\center!) - Vec2d(@center!))\normalized! world.entities\add EnemyBullet dir, @x, @y take_hit: (thing, world) => if thing.is_bullet and not thing.is_enemy_bullet thing.life = 0 @life -= 34 spray_dir = thing.vel\normalized! world.particles\add Sparks spray_dir, world, thing\center! @damage_seq = Sequence -> @shake_time = 1 @rand = math.random! tween @, 0.5, shake_time: 0 @shake_time = nil if @life > 0 sfx\play "enemy_hit" else sfx\play "enemy_die" world.player.score += math.random 101, 127 update: (dt, world) => @vel\adjust unpack @accel * dt @damage_seq\update dt if @damage_seq @move unpack @vel * dt @life > 0 draw: => g.setColor 255,255,255 if t = @shake_time g.push! g.translate 5 * t * math.sin((t*10 + @rand)*5), 5 * t * math.cos((t*11 + @rand)*5) o = (1 - t) * 255 g.setColor 255, o, o else g.setColor 255, 255, 255 cx, cy = @center! @sprite\draw "273,19,30,25", cx, cy, 0, 2, 2, 15,12 if @shake_time g.pop! Sequence.default_scope.bezier_move_to = (thing, tx, ty, speed) -> speed or= thing.speed fx = thing.x fy = thing.y move = Vec2d tx - fx, ty - fy move_len = move\len! control_len = 1 + move_len / 4 dir = move\normalized!\cross! dir = dir\flip! if math.random! > 0.5 cx = (tx + fx) / 2 + dir[1] * control_len cy = (ty + fy) / 2 + dir[2] * control_len tscale = 1 / move_len * speed time = 0 remaining = 0 before_x, before_y = fx, fy while time < 1 dt = coroutine.yield! time += dt * tscale if time > 1 remaining = (1 - time) / tscale time = 1 -- wow this is lame nx, ny = bez3 fx, fy, cx, cy, tx, ty, smoothstep 0, 1, time dx = nx - before_x dy = ny - before_y before_x = nx before_y = ny thing.x += dx thing.y += dy if remaining > 0 coroutine.yield "more", remaining class PathEnemy extends Enemy @gen_targets: (world, num_targets=2) => max_height = world.box.h * 0.4 chunk = world.box.w / num_targets min_x = 0 targets = { { world.box.x - 100, rand(-200, max_height) } } for i=1,num_targets table.insert targets, { rand min_x, min_x + chunk rand 0, max_height } min_x += chunk targets[#targets + 1] = { world.box.w + 200, rand(-200, max_height) } targets speed: 200 new: (@x, @y, @targets) => @speed = rand 150, 250 @seq = Sequence -> for i, {x,y} in ipairs @targets bezier_move_to @, x, y unless i == #@targets @shoot @world wait rand 0.3, 0.7 update: (dt, world) => @world = world @damage_seq\update dt if @damage_seq @seq\update(dt) and @life > 0 nil