Advertisement
Guest User

battle script

a guest
Jul 1st, 2016
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.91 KB | None | 0 0
  1. require "better_variables"
  2. require "better_debugging"
  3.  
  4. -- Global effects
  5. effects = {}
  6. -- Global bullets
  7. bullets = {}
  8.  
  9. -- Song related
  10. bpm = 225
  11. fps = 60
  12. song_end_beat = 208
  13. time_offset = 0.15
  14.  
  15. -- Global notes
  16. notes = {}
  17. -- Each note should have a function named `create_bullets`
  18. -- and it is executed at the first frame when current_beat > note.beat
  19.  
  20. function distance(p1, p2)
  21.     --- Calculate distance of two points p1, p2
  22.     -- assummes p1.x, p1.y, p2.x, p2.y exists.
  23.     return math.sqrt((p1.x-p2.x) * (p1.x-p2.x) + (p1.y-p2.y) * (p1.y-p2.y))
  24. end
  25.  
  26.  
  27. function generate_linear_bullet_note(beat, start_x, start_y, radius, sprite_name, beat_until_collision)
  28.     --- Linear Bullet Note
  29.     -- Generates a bullet with start position `(start_x, start_y)`
  30.     -- heading to `(player.x, player.y)`
  31.     -- after beat_until_collision, bullet should be right in front of `(player.x, player.y)`
  32.     -- to be percise, `distance(player, bullet)` should be `grace_distance`
  33.  
  34.     -- set defaults
  35.     radius = radius or 4
  36.     sprite_name = sprite_name or 'bullet_circle'
  37.     beat_until_collision = beat_until_collision or 4
  38.     grace_distance = 25
  39.  
  40.  
  41.     -- generate note
  42.     note = {}
  43.     note.beat = beat
  44.     note.beat_until_collision = beat_until_collision
  45.     note.start_beat = note.beat - beat_until_collision
  46.     note.create_bullets = function()
  47.         -- calculate the goal point
  48.         start = {x=start_x, y=start_y}
  49.         d = grace_distance
  50.         s = distance(start, player)
  51.         goal = {
  52.             x = ((s-d) * player.x + d * start.x) / s,
  53.             y = ((s-d) * player.y + d * start.y) / s
  54.         }
  55.  
  56.         bullet = create_bullet(sprite_name, start_x, start_y)
  57.         time_until_collision = beat_until_collision * 60 / bpm
  58.         bullet.vx = (goal.x - bullet.x) / time_until_collision / fps
  59.         bullet.vy = (goal.y - bullet.y) / time_until_collision / fps
  60.         bullet.r = radius
  61.         bullet.update = function(self)
  62.             self.Move(self.vx or 0, self.vy or 0)
  63.         end
  64.         table.insert(bullets, bullet)
  65.     end
  66.     return note
  67. end
  68.  
  69. function generate_notes()
  70.     r = 300
  71.     for i, n in ipairs({32, 34, 36, 38, 40, 42, 44, 46,
  72.                         48, 50, 52, 54, 56, 58, 60, 62,
  73.                         64, 66, 68, 70, 72, 74, 76, 78,
  74.                         80, 82, 84, 86, 88, 90, 92, 94,
  75.                         96, 98, 100, 102, 104, 106, 108, 110,
  76.                         112, 114, 116, 118, 120, 122, 124, 126,
  77.                         128, 129.5, 132, 133.5, 136, 138, 140, 142,
  78.                         144, 145.5, 148, 149.5, 152, 153, 154, 154 + 2/3, 154 + 4/3, 156, 158,
  79.                         160, 161.5, 164, 165.5, 168, 170, 172, 174,
  80.                         176, 177.5, 180, 181.5, 184, 185, 186, 186 + 2/3, 186 + 4/3, 188, 190,
  81.                         }) do
  82.         theta = math.random() * math.pi
  83.         table.insert(notes, generate_linear_bullet_note(n, r * math.cos(theta), r * math.sin(theta)))
  84.         table.insert(notes, generate_linear_bullet_note(n, r * math.cos(math.pi + theta), r * math.sin(math.pi + theta)))
  85.         if n >= 128 then
  86.             table.insert(notes, generate_linear_bullet_note(n, r * math.cos(math.pi / 2 +theta), r * math.sin(math.pi / 2 + theta)))
  87.             table.insert(notes, generate_linear_bullet_note(n, r * math.cos(math.pi * 3 / 2 + theta), r * math.sin(math.pi * 3 / 2 + theta)))
  88.         end
  89.     end
  90. end
  91. generate_notes()
  92.  
  93. -- Set base positions
  94. -- Note since players aren't allowed to move around,
  95. -- we track them via (x_base, y_base) not (x, y)
  96. player.x_base = 0
  97. player.y_base = 0
  98. -- Amusingly, `player.x_base, player.y_base = 0, 0` crashes the game
  99.  
  100. -- beat
  101. function current_beat()
  102.     --- Get current beat in float
  103.     -- not int because there can be beats that are not integer (e.g. 1/3 beats)
  104.     return bpm / 60 * (Time.time - encounter.start_time - time_offset)
  105.     -- note that start_time should be defined when audio starts
  106. end
  107.  
  108.  
  109. -- Bullet wrapper
  110.  
  111. function create_projectile(sprite, x, y)
  112.     local projectile = wrap(CreateProjectile(sprite, x, y))
  113.     projectile.created_time = Time.time
  114.     return projectile
  115. end
  116.  
  117. function create_bullet(sprite, x, y)
  118.     local bullet = create_projectile(sprite, x, y)
  119.     bullet.type = 'bullet'
  120.     return bullet
  121. end
  122.  
  123. function create_effect(sprite, x, y)
  124.     local effect = create_projectile(sprite, x, y)
  125.     effect.type = 'effect'
  126.     return effect
  127. end
  128.  
  129. -- Main update loop
  130. update_counter = 0  -- current update number
  131. function Update()
  132.     update_counter = update_counter + 1
  133.     -- players can't move
  134.     player.MoveTo(player.x_base, player.y_base, false)
  135.     handle_keyboard_inputs()
  136.     create_bullets()
  137.     update_bullets()
  138.     if not pcall(update_effects) then
  139.         enter_log_mode()
  140.     end
  141.  
  142.     -- Update once per beat
  143.  
  144.     beat_counter = beat_counter or 0
  145.     if current_beat() > beat_counter then
  146.         update_per_beat(beat_counter)
  147.         beat_counter = beat_counter + 1
  148.     end
  149.  
  150.     for i, effect in ipairs(effects) do
  151.         if effect.name == 'heartbeat' then
  152.             log(update_counter, effect.name or '',
  153.                 effect, 'lifespan: ', effect.lifespan)
  154.         end
  155.     end
  156. end
  157.  
  158. function update_per_beat(beat)
  159.     -- print current beat
  160.     log('Beat= ' .. tostring(beat))
  161.     -- Add heartbeat animation
  162.     if beat % 2 == 0 then
  163.         local heartbeat_effect = create_effect('heartbeat', player.x, player.y)
  164.         heartbeat_effect.lifespan = 3
  165.         heartbeat_effect.name = 'heartbeat'
  166.         table.insert(effects, heartbeat_effect)
  167.     end
  168.  
  169.     -- Check song end
  170.     if current_beat() > song_end_beat then
  171.         Audio.Stop()
  172.         EndWave()
  173.     end
  174. end
  175.  
  176. function handle_keyboard_inputs()
  177.  
  178.     if(Input.Left == 1) then
  179.         player.Move(-4, 0)  -- Lean slightly left
  180.     elseif(Input.Left == 2) then
  181.         player.Move(-8, 0)  -- Lean left
  182.     end
  183.  
  184.     if(Input.Right == 1) then
  185.         player.Move(4, 0)  -- Lean slightly right
  186.     elseif(Input.Right == 2) then
  187.         player.Move(8, 0)  -- Lean right
  188.     end
  189.  
  190.     if(Input.Down == 1) then
  191.         player.Move(0, -4)  -- Lean slightly downward
  192.     elseif(Input.Down == 2) then
  193.         player.Move(0, -8)  -- Lean downward
  194.     end
  195.  
  196.     if(Input.Up == 1) then
  197.         player.Move(0, 4)  -- Lean slightly upward
  198.     elseif(Input.Up == 2) then
  199.         player.Move(0, 8)  -- Lean upward
  200.     end
  201.  
  202.     -- Handle stomp last since it uses player.x, player.y
  203.     if(Input.Confirm == 1) then
  204.         stomp()
  205.     end
  206.  
  207.     if(Input.Up >=1 and Input.Down >=1 and Input.Left >=1 and Input.Right >=1 and Input.Confirm >=1) then
  208.         enter_log_mode()
  209.     end
  210. end
  211.  
  212. function stomp()
  213.     log('stomped: ' .. tostring(current_beat()))
  214.     -- Play sound
  215.     Audio.PlaySound('stomp1')
  216.  
  217.     -- Add stomping animation
  218.     local stomp_effect = create_effect('stomp_effect', player.x, player.y)
  219.     stomp_effect.lifespan = 20  -- lifespan frame
  220.     stomp_effect.name = 'stomp' -- for debugging
  221.     table.insert(effects, stomp_effect)
  222.  
  223.     -- Delete bullets in radius
  224.     for i = #bullets, 1, -1 do
  225.         local bullet = bullets[i]
  226.         if distance(player, bullet) < 50 then
  227.             bullet.Remove()
  228.             table.remove(bullets, i)
  229.         end
  230.     end
  231. end
  232.  
  233.  
  234. function create_bullets()
  235.     --- Create Bullets along the beat
  236.     for i, note in ipairs(notes) do
  237.         if (current_beat() >= note.start_beat) then
  238.             if not note.created then
  239.                 note.create_bullets()
  240.                 note.created = true
  241.             end
  242.         end
  243.     end
  244. end
  245.  
  246. function update_bullets()
  247.     -- iterate reverse since table is modified when removing
  248.     for i = #bullets, 1, -1 do
  249.         local bullet = bullets[i]
  250.         bullet:update()
  251.         if bullet.lifespan ~= nil then
  252.             -- If lifespan is given, handle it
  253.             if (bullet.lifespan < 0) then
  254.                 bullet.Remove()
  255.                 table.remove(bullets, i)
  256.             else
  257.                 bullet.lifespan = bullet.lifespan - 1
  258.             end
  259.         end
  260.     end
  261. end
  262.  
  263. function update_effects()
  264.     for i = #effects, 1, -1 do  -- BUG: this loop only executes the first iteration and exits
  265.                                 -- when Z is spammed
  266.         local effect = effects[i]
  267.  
  268.         -- If update is given, handle it
  269.         if effect.update then
  270.             effect:update()
  271.         end
  272.  
  273.         -- If lifespan is given, handle it
  274.         if effect.lifespan ~= nil then
  275.             if(effect.lifespan <= 0) then
  276.                 effect.Remove()
  277.                 table.remove(effects, i)
  278.             else
  279.                 effect.lifespan = effect.lifespan - 1  -- This line is the culprit
  280.             end
  281.         end
  282.     end
  283. end
  284.  
  285. function OnHit(projectile)
  286.     bullet = wrap(projectile)
  287.     if bullet.type == 'effect' then
  288.         -- Ignore all effect type projectiles
  289.         return
  290.     end
  291.     player.Hurt(1)
  292. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement