Guest User

RGSS - Tower defense

a guest
Oct 27th, 2015
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 38.84 KB | None | 0 0
  1. #===============================================================================
  2. # * Tower defense
  3. #-------------------------------------------------------------------------------
  4. # Version 0.9.0
  5. # Until 30th October 2015 usable only by people of the Evil Lair
  6. # After that day, it's free for all as Apache 2.0.
  7. #-------------------------------------------------------------------------------
  8. # By Ramiro
  9. # Apache 2.0 license
  10. #-------------------------------------------------------------------------------
  11. # Usage:
  12. #
  13. # * Configuring the map:
  14. #   > In order to configure the map you need to edit its regions:
  15. #     - set it to 2 if the enemy should move down from this tile
  16. #     - set it to 4 if the enemy should move left from here
  17. #     - set it to 6 if the enemy should move right from here
  18. #     - set it to 8 if the enemy should move up from here
  19. #     There are special cases to choose a random direction:
  20. #     - 1 is random between down or left
  21. #     - 3 is random between down or right
  22. #     - 5 is random between left or right
  23. #     - 7 is random between up or left
  24. #     - 9 is random between up or right
  25. #     - 10 is random between up or down
  26. #     The map marked as the region 20, is the tile where if the enemy reach
  27. #     this tile it's game over (in other words, the end of the path)
  28. #
  29. #     You also have to mark your summon places, in order to do that, mark each
  30. #     summon area as the region 50.
  31. #
  32. #
  33. # * Starting the scene:
  34. #   - Teleport to the tower defense map.
  35. #   - Set your party's gold to the amount of starting gold to use
  36. #   - Script call: id = put here the id of the stage
  37. #                  $game_system.tower_defense.setup(id)
  38. #                  SceneManager.call(Scene_TowerDefense)
  39. #   - Wait 1 frame
  40. #   - Check if the switch is true (victory) or false (defeat) and continue
  41. #     the event as normal.
  42. #
  43. # * Adding enemy types or tower types:
  44. #   - Configure the script here in order to add, remove or change values
  45. #
  46. #===============================================================================
  47.  
  48. #===============================================================================
  49. # Configure things here
  50. #===============================================================================
  51.  
  52. TOWER_DEFENSE = {
  53.  #------------------------------------------------------------------------------
  54.  # * General configuration
  55.  #------------------------------------------------------------------------------
  56.  # select the id of the switch than returns the result of the battle
  57.  SWITCH_ID: 1,
  58.  # The name used by the summoning area.
  59.  SUMMON_AREA_NAME: "Summon area",
  60.  # The icon used in the gold window
  61.  SUMMONING_POWER_ICON_INDEX: 1,
  62.  #------------------------------------------------------------------------------
  63.  # * Allies configuration
  64.  #------------------------------------------------------------------------------
  65.  ALLIES: [ nil, # leave id 0 out
  66.   {
  67.     # The name used by this tower
  68.     name: 'Ghost',
  69.     # The character (must exists in Graphics/characters)
  70.     character_name: 'monster1',
  71.     # The index of the character (0 first, 7 last)
  72.     character_index: 0,
  73.     # The name of the projectile's graphic (must exists in Graphics/characters)
  74.     projectile_name: 'fire1',
  75.     # The color the enemy flashes when hit by the bullet (r, g, b)
  76.     bullet_color: Color.new(255, 0, 0),
  77.     # The maximun hp a tower can handle
  78.     mhp:     1000,
  79.     # the atk power at lvl 1
  80.     atk:       10,
  81.     # delay (in frames) between each bullet
  82.     delay:     60,
  83.     # The maximun level of the tower
  84.     max_level: 10,
  85.     # The time
  86.     time:       4,
  87.     # The starting price
  88.     price:    100,
  89.     # The radius (in tiles) the tower has
  90.     distance:   4
  91.   },
  92.   {
  93.     name: 'Skeleton',
  94.     character_name: 'monster1',
  95.     character_index: 1,
  96.     projectile_name: 'fire1',
  97.     bullet_color: Color.new(255, 0, 0),
  98.     mhp:     1000,
  99.     atk:       10,
  100.     delay:     60,
  101.     max_level: 10,
  102.     time:       4,
  103.     price:    100,
  104.     distance:   4
  105.   },
  106.   {
  107.     name: 'Orc',
  108.     character_name: 'monster1',
  109.     character_index: 2,
  110.     projectile_name: 'fire1',
  111.     bullet_color: Color.new(255, 0, 0),
  112.     mhp:     1000,
  113.     atk:       10,
  114.     delay:     60,
  115.     max_level: 10,
  116.     time:       4,
  117.     price:    100,
  118.     distance:   4
  119.   },
  120.   {
  121.     name: 'Demon',
  122.     character_name: 'monster1',
  123.     character_index: 3,
  124.     projectile_name: 'fire1',
  125.     bullet_color: Color.new(255, 0, 0),
  126.     mhp:     1000,
  127.     atk:       10,
  128.     delay:     60,
  129.     max_level: 10,
  130.     time:       4,
  131.     price:    100,
  132.     distance:   4
  133.   },
  134.   {
  135.     name: 'Reaper',
  136.     character_name: 'monster1',
  137.     character_index: 6,
  138.     projectile_name: 'fire1',
  139.     bullet_color: Color.new(255, 0, 0),
  140.     mhp:     1000,
  141.     atk:       10,
  142.     delay:     60,
  143.     max_level: 10,
  144.     time:       4,
  145.     price:    100,
  146.     distance:   4
  147.   },
  148.   {
  149.     name: 'Overlord',
  150.     character_name: 'monster1',
  151.     character_index: 7,
  152.     projectile_name: 'fire1',
  153.     bullet_color: Color.new(255, 0, 0),
  154.     mhp:     1000,
  155.     atk:       10,
  156.     delay:     60,
  157.     radius:    96,
  158.     max_level: 10,
  159.     time:       4,
  160.     price:    100,
  161.     distance:   4
  162.   }    
  163.  ],
  164.  #------------------------------------------------------------------------------
  165.  # * Enemies configuration
  166.  #------------------------------------------------------------------------------
  167.  ENEMIES: [ nil, # leave id 0 out
  168.   { # enemy starts like this
  169.     # The name showed at the hud
  170.     name: 'Slime',
  171.     # The name of the character (must be in graphics/characters)
  172.     character_name: 'monster2',
  173.     # The index of the graphic (0 first, 7 last)
  174.     character_index: 2,
  175.     # The level displayed at the hud
  176.     level:           1,
  177.     # The maximun hp this enemy has
  178.     mhp: 100,
  179.     # The speed of the enemy
  180.     speed:     2,
  181.     # The frecuency (not used by now)
  182.     frecuency: 1,
  183.     # Amount of gold the enemy leaves when dead
  184.     gold: 100,
  185.   } # enemy ends with this (remember to separate them with ,)
  186.  ],
  187.  #------------------------------------------------------------------------------
  188.  # * Stage configuration
  189.  #------------------------------------------------------------------------------
  190.  STAGES: [ nil, # leave id 0 out
  191.   {
  192.     # spawn coordinates [x, y]
  193.     spawn: [1, 0],
  194.     # time between each monster spawn
  195.     tick: 60,      
  196.     # This are the waves, eyou can add as many as you need per stage
  197.     waves: [  
  198.       # wave 1 [enemy_id1, enemy_id2, ...]
  199.       # nil means "skip one spawn"
  200.       [1, nil, nil, nil, 1, nil, nil, nil, 1, nil, nil, nil, 1, nil, nil, nil, 1],
  201.       # wave 2 [enemy_id1, enemy_id2, ...]
  202.       [1, 1, 1, 1, 1],
  203.       # wave 3 [enemy_id1, enemy_id2, ...]
  204.       [1, 1, 1, 1, 1]  
  205.     ]
  206.   }
  207.  ]
  208.  
  209. }
  210.  
  211. #===============================================================================
  212. # Script starts here, editing something past here will cause a meltdown...
  213. # or not, you may know what you are doing.
  214. #===============================================================================
  215.  
  216. #===============================================================================
  217. # ** Game_TowerDefense
  218. #-------------------------------------------------------------------------------
  219. # This class (inside Game_System) manages the flow of the Tower Defense game
  220. #===============================================================================
  221. class Game_TowerDefense
  222.   #-----------------------------------------------------------------------------
  223.   # Class properties
  224.   #-----------------------------------------------------------------------------
  225.   attr_reader   :enemies
  226.   attr_reader   :towers
  227.   attr_reader   :bullets
  228.   attr_reader   :rest_time
  229.   attr_reader   :cursor
  230.  
  231.   attr_accessor :wave_tick
  232.   attr_accessor :wave_index
  233.   attr_accessor :on_wave_start
  234.   attr_accessor :on_rest_start
  235.   attr_accessor :on_wave_update
  236.   attr_accessor :on_rest_update
  237.   attr_accessor :on_victory
  238.   attr_accessor :on_defeat
  239.   attr_accessor :on_spawn
  240.   attr_accessor :on_summon
  241.   attr_accessor :on_hit
  242.   attr_accessor :on_kill
  243.   attr_accessor :on_shoot
  244.  
  245.   #-----------------------------------------------------------------------------
  246.   # constructor
  247.   #-----------------------------------------------------------------------------
  248.   def initialize
  249.     @cursor             = Game_TowerDefenseCursor.new
  250.     @stage_id           = 1
  251.     @wave_id            = 0
  252.     @wave_index         = 0
  253.     @wave_tick          = 0
  254.     @towers             = []
  255.     clear_containers
  256.     @rest_time          = 3600  
  257.     self.on_wave_start  = nil
  258.     self.on_rest_start  = nil
  259.     self.on_wave_update = nil
  260.     self.on_rest_update = nil
  261.     self.on_victory     = nil
  262.     self.on_defeat      = nil
  263.     self.on_spawn       = nil
  264.     self.on_summon      = nil
  265.     self.on_kill        = nil
  266.     self.on_hit         = nil
  267.     self.on_shoot       = nil
  268.   end
  269.  
  270.   #-----------------------------------------------------------------------------
  271.   # Clears both enemies and bullets
  272.   #-----------------------------------------------------------------------------
  273.   def clear_containers
  274.     @enemies            = []
  275.     @bullets            = []
  276.   end
  277.  
  278.   #-----------------------------------------------------------------------------
  279.   # All dead enemies
  280.   #-----------------------------------------------------------------------------
  281.   def dead_enemies
  282.     enemies.select { |i| i.dead? }
  283.   end
  284.  
  285.   #-----------------------------------------------------------------------------
  286.   # All alive enemies
  287.   #-----------------------------------------------------------------------------
  288.   def alive_enemies
  289.     enemies.select { |i| i.alive? }
  290.   end
  291.  
  292.   #-----------------------------------------------------------------------------
  293.   # Gets all alive towers
  294.   #-----------------------------------------------------------------------------
  295.   def alive_towers
  296.     towers.select { |i| i.alive? }
  297.   end
  298.  
  299.   #-----------------------------------------------------------------------------
  300.   # starts a new stage by id
  301.   #-----------------------------------------------------------------------------
  302.   def setup(stage_id)
  303.     @stage_id = stage_id
  304.     @towers = []
  305.     @wave_index = 0
  306.     create_summoning_areas
  307.   end
  308.  
  309.   #-----------------------------------------------------------------------------
  310.   # Creates the places to summon
  311.   #-----------------------------------------------------------------------------
  312.   def create_summoning_areas
  313.     for x in 0...$game_map.width
  314.       for y in 0...$game_map.height
  315.         if $game_map.region_id(x, y) == 50
  316.           @towers << Game_TowerSpace.new(@towers.size, x, y)
  317.         end
  318.       end
  319.     end
  320.   end
  321.  
  322.   #-----------------------------------------------------------------------------
  323.   # Gets the current stage
  324.   #-----------------------------------------------------------------------------
  325.   def stage
  326.     TOWER_DEFENSE[:STAGES][@stage_id]
  327.   end
  328.  
  329.   #-----------------------------------------------------------------------------
  330.   # Gets the current wave
  331.   #-----------------------------------------------------------------------------
  332.   def wave
  333.     self.stage[:waves][@wave_id]
  334.   end
  335.  
  336.   #-----------------------------------------------------------------------------
  337.   # gets the current stage's tick
  338.   #-----------------------------------------------------------------------------
  339.   def tick
  340.     stage[:tick]
  341.   end
  342.  
  343.   #-----------------------------------------------------------------------------
  344.   # Gets the wave number to display on windows
  345.   #-----------------------------------------------------------------------------
  346.   def wave_number
  347.     @wave_id + 1
  348.   end
  349.  
  350.   #-----------------------------------------------------------------------------
  351.   # Advances to the next wave
  352.   #-----------------------------------------------------------------------------
  353.   def next_wave
  354.     @wave_id += 1
  355.     if @wave_id >= self.stage[:waves].size
  356.       start_wave
  357.     else
  358.       start_victory
  359.     end
  360.   end
  361.  
  362.   #-----------------------------------------------------------------------------
  363.   # Starts the battle
  364.   #-----------------------------------------------------------------------------
  365.   def start
  366.     clear_containers
  367.     @wave_id = 0
  368.     @wave_index = 0
  369.     start_rest
  370.   end
  371.  
  372.   #-----------------------------------------------------------------------------
  373.   # Updates the current phase
  374.   #-----------------------------------------------------------------------------  
  375.   def update
  376.     self.cursor.update
  377.     case @phase
  378.     when :rest
  379.       update_rest
  380.     when :wave
  381.       update_wave
  382.     when :victory
  383.       update_victory
  384.     else
  385.       update_defeat
  386.     end    
  387.   end
  388.   #-----------------------------------------------------------------------------
  389.   # Updates the rest time between waves (1 minute)
  390.   #-----------------------------------------------------------------------------
  391.   def update_rest
  392.     if @rest_time > 0
  393.       @rest_time -= 1
  394.     else
  395.       start_wave
  396.     end    
  397.     self.on_rest_update.call if self.on_rest_update
  398.   end
  399.  
  400.   #-----------------------------------------------------------------------------
  401.   # Updates the wave attack
  402.   #-----------------------------------------------------------------------------
  403.   def update_wave
  404.     if @wave_tick > 0
  405.       @wave_tick -= 1
  406.     else
  407.       spawn_enemy
  408.     end
  409.     update_enemies
  410.     update_bullets
  411.     update_towers
  412.     self.on_wave_update.call if self.on_wave_update
  413.   end
  414.  
  415.   #-----------------------------------------------------------------------------
  416.   # Updates enemies
  417.   #-----------------------------------------------------------------------------
  418.   def update_enemies
  419.     @enemies.each { |i| i.update }
  420.   end
  421.  
  422.   #-----------------------------------------------------------------------------
  423.   # Updates bullets
  424.   #-----------------------------------------------------------------------------
  425.   def update_bullets
  426.     @bullets.each { |i| i.update }
  427.   end
  428.  
  429.   #-----------------------------------------------------------------------------
  430.   # Updates towers
  431.   #-----------------------------------------------------------------------------
  432.   def update_towers  
  433.     @towers.each { |i| i.update }
  434.   end
  435.  
  436.   #-----------------------------------------------------------------------------
  437.   # Starts the next wave
  438.   #-----------------------------------------------------------------------------
  439.   def start_wave
  440.     @phase = :wave
  441.     @wave_tick          = 0    
  442.     self.on_wave_start.call if self.on_wave_start
  443.   end
  444.  
  445.   #-----------------------------------------------------------------------------
  446.   # Starts the rest phase between waves
  447.   #-----------------------------------------------------------------------------
  448.   def start_rest(time=3600)
  449.     @phase = :rest
  450.     self.wave_tick = 0
  451.     @rest_time = time
  452.     self.on_rest_start.call if self.on_wave_start
  453.   end
  454.  
  455.   #-----------------------------------------------------------------------------
  456.   # Starts the victory process
  457.   #-----------------------------------------------------------------------------
  458.   def start_victory
  459.     @phase = :victory
  460.     self.on_victory.call if self.on_victory
  461.   end
  462.  
  463.   #-----------------------------------------------------------------------------
  464.   # Starts the defeat process
  465.   #-----------------------------------------------------------------------------
  466.   def start_defeat
  467.     @phase = :defeat
  468.     self.on_defeat.call if self.on_defeat  
  469.   end
  470.  
  471.   #-----------------------------------------------------------------------------
  472.   # Spawns a new enemy according to the wave's tick
  473.   #-----------------------------------------------------------------------------
  474.   def spawn_enemy
  475.     @wave_tick = tick
  476.     if @wave_index >= self.wave.size
  477.       if alive_enemies.size < 1
  478.         start_rest
  479.       end
  480.     else
  481.       e = wave_enemy
  482.       if e
  483.         enemy = Game_TowerEnemy.new(e)
  484.         @enemies << enemy
  485.         self.on_spawn.call(enemy) if self.on_spawn
  486.       end
  487.       @wave_index += 1
  488.     end
  489.   end
  490.  
  491.   #-----------------------------------------------------------------------------
  492.   # Gets the enemy the wave should spawn
  493.   #-----------------------------------------------------------------------------
  494.   def wave_enemy
  495.     if wave[@wave_index]
  496.       TOWER_DEFENSE[:ENEMIES][wave[@wave_index]]
  497.     else
  498.       nil
  499.     end
  500.   end
  501.  
  502.   #-----------------------------------------------------------------------------
  503.   # Updates the victory phase
  504.   #-----------------------------------------------------------------------------
  505.   def update_victory
  506.   end
  507.  
  508.   #-----------------------------------------------------------------------------
  509.   # Updates the defeat phase
  510.   #-----------------------------------------------------------------------------
  511.   def update_defeat
  512.   end
  513.  
  514.   #-----------------------------------------------------------------------------
  515.   # Get targets at position
  516.   #-----------------------------------------------------------------------------
  517.   def targets_at(x, y)
  518.     targets.select { |i| i.x == x && i.y == y }
  519.   end
  520.  
  521.   #-----------------------------------------------------------------------------
  522.   # targets are any enemy or tower
  523.   #-----------------------------------------------------------------------------
  524.   def targets
  525.     enemies + towers
  526.   end
  527.  
  528.   #-----------------------------------------------------------------------------
  529.   # Shoots a bullet from a tower to an enemy
  530.   #-----------------------------------------------------------------------------
  531.   def shoot(tower, enemy)
  532.     bullet = Game_TowerBullet.new(tower, bullet)
  533.     self.on_shoot.call(bullet) if self.on_shoot
  534.     @bullets << bullet
  535.   end
  536.  
  537.   #-----------------------------------------------------------------------------
  538.   # Get the first target you can find at position
  539.   #-----------------------------------------------------------------------------
  540.   def first_target_at(x, y)
  541.     targets = targets_at(x, y)
  542.     targets.size > 0 ? targets[0] : nil
  543.   end
  544.  
  545.   #-----------------------------------------------------------------------------
  546.   # Corrects the x acording to display
  547.   #-----------------------------------------------------------------------------
  548.   def tile_x(x)
  549.     (x - $game_map.display_x) / 32
  550.   end
  551.  
  552.   #-----------------------------------------------------------------------------
  553.   # Corrects the y acording to display
  554.   #-----------------------------------------------------------------------------
  555.   def tile_y(y)
  556.     (y - $game_map.display_y) / 32
  557.   end
  558.  
  559.   #-----------------------------------------------------------------------------
  560.   # Summons a new tower
  561.   #-----------------------------------------------------------------------------
  562.   def summon(index, ally)
  563.     return nil if ally[:price] > $game_party.gold
  564.     $game_party.lose_gold(ally[:price])
  565.     old = @towers[index]
  566.     @towers[index] = Game_TowerAlly.new(index, ally, old.x, old.y)
  567.     self.on_summon.call(index, @towers[index]) if self.on_summon
  568.     return @towers[index]
  569.   end
  570.  
  571.   #-----------------------------------------------------------------------------
  572.   # Process the hit of an enemy by a bullet
  573.   #-----------------------------------------------------------------------------
  574.   def process_hit(bullet, enemy)
  575.     @bullets.delete(bullet)
  576.     self.on_hit(bullet) if self.on_hit
  577.     enemy.hp -= bullet.atk
  578.     enemy.hit = bullet.color
  579.     if enemy.dead?
  580.       $game_party.gain_gold(enemy.gold)
  581.       self.on_kill.call(enemy) if self.on_kill
  582.     end
  583.   end
  584.  
  585. end
  586.  
  587. #===============================================================================
  588. # ** Game_System
  589. #===============================================================================
  590. class Game_System
  591.  
  592.   #-----------------------------------------------------------------------------
  593.   # added: tower_defense
  594.   #-----------------------------------------------------------------------------
  595.   def tower_defense
  596.     @tower_defense ||= Game_TowerDefense.new
  597.   end
  598.  
  599. end
  600.  
  601. #===============================================================================
  602. # ** Game_TowerCharacter
  603. #-------------------------------------------------------------------------------
  604. # This class is the parent of all towers and enemies of the tower defense.
  605. #===============================================================================
  606. class Game_TowerCharacter < Game_Character
  607.  
  608.   attr_reader :hp
  609.   attr_reader :name
  610.   attr_reader :level
  611.  
  612.   attr_accessor :hit
  613.  
  614.   def initialize
  615.     super
  616.     @name = 0
  617.     @level = 0
  618.     @hp = mhp
  619.     @transparent        = false
  620.     @opacity            = 255    
  621.     @hit                = nil
  622.   end
  623.  
  624.   def passable?(x, y, d)
  625.     true
  626.   end
  627.  
  628.   def hp=(value)
  629.     @hp = [0, [mhp, value].min ].max
  630.   end
  631.  
  632.   def mhp
  633.    0
  634.   end
  635.  
  636.   def ally?
  637.     false
  638.   end  
  639.  
  640.   def enemy?
  641.     false
  642.   end
  643.  
  644.   def dead?
  645.     self.hp <= 0
  646.   end
  647.  
  648.   def alive?
  649.     !dead?
  650.   end    
  651.  
  652.   def hp_rate
  653.     self.hp.to_f / self.mhp
  654.   end
  655.  
  656.   def built?
  657.     true
  658.   end  
  659.  
  660. end
  661.  
  662. class Game_TowerSpace < Game_TowerCharacter
  663.  
  664.   attr_reader :index
  665.  
  666.   def initialize(index, x, y)
  667.     super()
  668.     @name = TOWER_DEFENSE[:SUMMON_AREA_NAME]
  669.     @level = 0
  670.     @mhp  = 100
  671.     @index = index
  672.     self.moveto(x, y)
  673.   end
  674.  
  675.   def built?
  676.     false
  677.   end
  678.  
  679. end
  680.  
  681. class Game_TowerAlly < Game_TowerCharacter
  682.  
  683.   attr_reader :price
  684.   attr_reader :level
  685.   attr_reader :max_level
  686.   attr_reader :mhp
  687.   attr_reader :atk
  688.   attr_reader :delay
  689.   attr_reader :time
  690.   attr_reader :distance
  691.   attr_reader :index
  692.   attr_reader :bullet_color
  693.  
  694.   def initialize(index, data, x, y)
  695.     @index = index
  696.     @data  = data
  697.     @atk   = data[:atk]
  698.     @mhp   = data[:mhp]
  699.     @price = data[:price]
  700.     @max_level = data[:max_level]
  701.     @delay = data[:delay]
  702.     @speed = data[:speed]
  703.     @distance = data[:distance]
  704.     @character_name = data[:character_name]
  705.     @character_index = data[:character_index]
  706.     super()
  707.     @tick  = 0
  708.     @level = 1  
  709.     @name = data[:name]
  710.     @bullet_color = data[:bullet_color] ? data[:bullet_color] : Color.new(255, 0, 0)
  711.     self.moveto(x, y)
  712.   end
  713.  
  714.   def level_up
  715.     return if maxed?
  716.     cost = price_for(@level + 1)
  717.     return if $game_party.gold < cost
  718.     $game_party.lose_gold(cost)
  719.     @level = @level + 1
  720.     @atk   = @data[:atk]   + @data[:atk]   * @level * @level / @max_level
  721.     @mhp   = @data[:mhp]   + @data[:mhp]   * @level * @level / @max_level
  722.     @delay = @data[:delay] - @data[:delay] * @level * @level / (@max_level * 10)
  723.     @time  = @data[:time]  - @data[:time]  * @level * @level / (@max_level * 10)
  724.     @distance = @data[:distance] + @data[:distance] * @level * @level / @max_level
  725.     heal_hp
  726.   end
  727.  
  728.   def repair_cost
  729.     prive_for(level) * self.hp / self.mhp
  730.   end
  731.  
  732.   def price_for(level)
  733.     self.price * level * level
  734.   end
  735.  
  736.   def heal_hp
  737.     self.hp = self.mhp
  738.   end
  739.  
  740.   def maxed?
  741.     return self.level >= self.max_level
  742.   end
  743.  
  744.   def ally?
  745.     true
  746.   end
  747.  
  748.   def repair
  749.     cost = repair_cost
  750.     return if $game_party.gold < cost
  751.     $game_party.lose_gold(cost)
  752.     heal_hp
  753.   end
  754.  
  755.   def distance_from(charecter)
  756.     Math.hypot(self.x - character.x, self.y - character.y)
  757.   end
  758.  
  759.   def closest_enemy
  760.     enemies = $game_system.tower_defense.alive_enemies
  761.     return nil if enemies.size < 1
  762.     x = enemies.sort {|a, b| a.distance_from(self)<=>b.distance_from(self) }
  763.     x[0]
  764.   end
  765.  
  766.   def reached_enemy
  767.     enemy = closest_enemy
  768.     return nil if !enemy
  769.     return nil if self.distance_from(enemy) > self.distance
  770.     enemy
  771.   end
  772.  
  773.   def update
  774.     super
  775.     if @tick > 0
  776.       @tick -= 1
  777.     else
  778.       update_bullet_check
  779.     end
  780.   end
  781.  
  782.   def update_bullet_check
  783.     enemy = reached_enemy
  784.     if enemy
  785.       @tick = @delay
  786.       $game_system.tower_defense.shoot(self, enemy)
  787.     end
  788.   end
  789.  
  790. end
  791.  
  792. class Game_TowerEnemy < Game_TowerCharacter
  793.  
  794.   def initialize(data)
  795.     @mhp = data[:mhp]
  796.     super()
  797.     @name = data[:name]
  798.     @level = data[:level]
  799.     @move_speed = data[:speed]
  800.     @move_frequency = data[:frecuency]    
  801.     @character_name = data[:character_name]
  802.     @character_index = data[:character_index]    
  803.     spawn = $game_system.tower_defense.stage[:spawn]
  804.     self.moveto(spawn[0], spawn[1])
  805.   end
  806.  
  807.   def mhp
  808.     @mhp
  809.   end
  810.  
  811.   def update
  812.     super
  813.     if !moving?
  814.       do_next_move
  815.     end
  816.   end
  817.  
  818.   def do_next_move
  819.     region = region_id
  820.     case region
  821.     when  2..8
  822.       move_straight(region)
  823.     when 1
  824.       move_straight( rand(2) == 0 ? 4 : 2 )
  825.     when 3
  826.       move_straight( rand(2) == 0 ? 6 : 2 )
  827.     when 5
  828.       move_straight( rand(2) == 0 ? 4 : 6 )
  829.     when 7
  830.       move_straight( rand(2) == 0 ? 4 : 8 )
  831.     when 9
  832.       move_straight( rand(2) == 0 ? 6 : 8 )
  833.     when 10
  834.       move_straight( rand(2) == 0 ? 2 : 8 )
  835.     when 20
  836.       $game_system.tower_defense.start_defeat
  837.     end
  838.   end
  839.  
  840.   def enemy?
  841.     true
  842.   end
  843.  
  844. end
  845.  
  846. class Game_TowerBullet
  847.  
  848.   attr_reader :mhp
  849.   attr_reader :x
  850.   attr_reader :y
  851.   attr_reader :name  
  852.  
  853.   def initialize(tower, target)
  854.     @tower = tower
  855.     @target = target
  856.     @time = tower.time
  857.     @x = tower.real_x
  858.     @y = tower.real_y - 16
  859.     @name = tower.projectile_name
  860.   end
  861.  
  862.   def atk
  863.     @tower.atk
  864.   end
  865.  
  866.   def rect
  867.     r = Rect.new(@tower.bullet_rect)
  868.     r.x = self.x
  869.     r.y = self.y
  870.     return r
  871.   end
  872.  
  873.   def color
  874.     @tower.bullet_color
  875.   end
  876.  
  877.   def update
  878.     if active?
  879.       update_position
  880.     else
  881.       process_hit
  882.     end
  883.   end
  884.  
  885.   def update_position
  886.     @x = ( @x * (@time - 1) + @target.real_x ) / @time
  887.     @y = ( @y * (@time - 1) + @target.real_y - 16 ) / @time
  888.     @time -= 1
  889.   end
  890.  
  891.   def process_hit
  892.     $game_system.tower_defense.process_hit(self, @target)
  893.   end
  894.  
  895.   def active?
  896.     @time > 0
  897.   end
  898.  
  899. end
  900.  
  901. class Sprite_TowerDefenseCharacter < Sprite_Character
  902.  
  903.   def update
  904.     super
  905.     return unless @character
  906.     if @character.hit
  907.       flash(@character.hit, 6)
  908.       @character.hit = nil
  909.     end
  910.   end
  911.  
  912. end
  913.  
  914. class Sprite_TowerDefenseBullet < Sprite
  915.  
  916.   def initialize(viewport, bullet)
  917.     super(viewport)
  918.     @bullet = bullet
  919.     self.bitmap = Cache.character(buller.name)
  920.   end
  921.  
  922.   def update
  923.     super
  924.     self.x = @bullet.x
  925.     self.y = @bullet.y
  926.   end
  927.  
  928. end
  929.  
  930. class Spriteset_TowerDefense < Spriteset_Map
  931.  
  932.   #--------------------------------------------------------------------------
  933.   # * Free
  934.   #--------------------------------------------------------------------------
  935.   def dispose
  936.     super
  937.     dispose_counter_sprite
  938.   end
  939.  
  940.   def update
  941.     super
  942.     update_counter_sprite
  943.   end
  944.  
  945.   def create_counter_sprite
  946.     @sprite_counter = Sprite_TowerDefenseCounter.new(@viewport3)
  947.     @sprite_counter.z = 99999
  948.   end
  949.  
  950.   def dispose_counter_sprite
  951.     @sprite_counter.dispose
  952.   end
  953.  
  954.   def update_counter_sprite
  955.     @sprite_counter.update
  956.   end
  957.  
  958.  
  959.   #--------------------------------------------------------------------------
  960.   # * Create Character Sprite
  961.   #--------------------------------------------------------------------------
  962.   def create_characters
  963.     @character_sprites = []
  964.     @sprite_owner  = {}
  965.     create_counter_sprite
  966.     @character_sprites << Sprite_Character.new(@viewport2, $game_system.tower_defense.cursor)
  967.     @map_id = $game_map.map_id
  968.   end  
  969.  
  970.   def add_enemy(enemy)
  971.     sprite = Sprite_TowerDefenseCharacter.new(@viewport1, enemy)
  972.     @character_sprites << sprite
  973.     @sprite_owner[enemy] = sprite
  974.   end
  975.  
  976.   def add_tower(tower)
  977.     sprite = Sprite_TowerDefenseCharacter.new(@viewport1, tower)
  978.     @character_sprites << sprite
  979.     @sprite_owner[tower] = sprite
  980.   end
  981.  
  982.   def add_bullet(bullet)
  983.     sprite = Sprite_TowerDefenseBullet.new(@viewport1, bullet)
  984.     @character_sprites << sprite
  985.     @sprite_owner[bullet] = sprite
  986.   end
  987.  
  988.   def delete_sprite(target)
  989.     sprite = @sprite_owner[target]
  990.     return unless sprite
  991.     @character_sprites.delete(sprite)
  992.     sprite.dispose
  993.   end
  994.  
  995. end
  996.  
  997. class Window_TowerDefenseGold < Window_Base
  998.  
  999.   def initialize
  1000.     super(0, 0, window_width, window_height)
  1001.     @gold = -1
  1002.   end
  1003.  
  1004.   def window_width
  1005.     160
  1006.   end
  1007.  
  1008.   def window_height
  1009.     fitting_height(1)
  1010.   end
  1011.  
  1012.   def update
  1013.     super
  1014.     if @gold != $game_party.gold
  1015.       @gold = $game_party.gold
  1016.       refresh
  1017.     end
  1018.   end
  1019.  
  1020.   def refresh
  1021.     self.contents.clear
  1022.     draw_text(0, 0, self.contents.width, self.contents.height, @gold)
  1023.     icon_index = TOWER_DEFENSE[:SUMMONING_POWER_ICON_INDEX]
  1024.     draw_icon(icon_index, self.contents.width - 24, 0)
  1025.   end
  1026.  
  1027. end
  1028.  
  1029. class Window_TowerDefenseHud < Window_Base
  1030.  
  1031.   def initialize
  1032.     super(window_x, window_y, window_width, window_height)
  1033.     self.visible = false
  1034.     @target = nil
  1035.     @last_hp = -1
  1036.     @gold = 1
  1037.   end
  1038.  
  1039.   def window_x
  1040.     0
  1041.   end
  1042.  
  1043.   def window_y
  1044.     Graphics.height - window_height
  1045.   end
  1046.  
  1047.   def window_width
  1048.     Graphics.width
  1049.   end
  1050.  
  1051.   def window_height
  1052.     fitting_height(3)
  1053.   end
  1054.  
  1055.   def update
  1056.     super
  1057.     return if !@target
  1058.     if @target.hp != @last_hp
  1059.       refresh
  1060.       @last_hp = @target.hp
  1061.     end
  1062.     update_options
  1063.     cursor_rect.set(Rect.new)
  1064.     return if @target.built?
  1065.     refresh_on_gold_change
  1066.     update_mouse_index
  1067.   end
  1068.  
  1069.   def refresh_on_gold_change
  1070.     if @gold != $game_party.gold
  1071.       @gold = $game_party.gold
  1072.       refresh
  1073.     end
  1074.   end
  1075.  
  1076.   def update_mouse_index
  1077.     for i in 0...item_max
  1078.       if Mouse.in_area?(mouse_item_rect(i))
  1079.         @index = i
  1080.         return cursor_rect.set(item_rect(i))
  1081.       end
  1082.     end    
  1083.   end  
  1084.  
  1085.   def mouse_item_rect(index)
  1086.     r = item_rect(index)
  1087.     r.x += self.real_x - self.ox
  1088.     r.y += self.real_y - self.oy
  1089.     return r
  1090.   end  
  1091.  
  1092.   def real_x
  1093.     viewport ? self.x + viewport.rect.x - viewport.ox : self.x
  1094.   end
  1095.  
  1096.   def real_y
  1097.     viewport ? self.y + viewport.rect.y - viewport.oy : self.y
  1098.   end    
  1099.  
  1100.   def update_options
  1101.     return if !@target.ally?
  1102.   end
  1103.  
  1104.   def display(target)
  1105.     if target != @target
  1106.       $game_system.tower_defense.cursor.target = target
  1107.       @target = target
  1108.       refresh
  1109.     end
  1110.   end
  1111.  
  1112.   def refresh
  1113.     self.contents.clear
  1114.     self.visible = @target ? true : false
  1115.     return if !self.visible
  1116.     draw_character_sprite
  1117.     draw_name_and_level
  1118.     if @target.ally?
  1119.       draw_ally_stats
  1120.     elsif @target.enemy?
  1121.       draw_enemy_stats
  1122.     else
  1123.       draw_summon_area
  1124.     end
  1125.     draw_unit_options   if @target.ally?  
  1126.     draw_summon_options if !@target.built?  
  1127.   end
  1128.  
  1129.   def draw_character_sprite
  1130.     draw_character(@target.character_name, @target.character_index, 16, 32)
  1131.   end
  1132.  
  1133.   def draw_name_and_level
  1134.     draw_text(32, 0, contents_width - 32, line_height, @target.name)
  1135.     draw_text(32, 0, contents_width - 32, line_height, "Level #{@target.level}", 2)  
  1136.   end
  1137.  
  1138.   def draw_ally_stats
  1139.     y = line_height
  1140.     x = 32
  1141.     w = (contents_width - 32) / 2
  1142.     tw = (contents_width - w) / 3
  1143.     draw_actor_hp(@target, x, y, w)
  1144.     self.contents.font.color = system_color
  1145.     draw_text(x + w, y, tw, line_height, "ATK")
  1146.     self.contents.font.color = normal_color
  1147.     draw_text(x + w, y, tw, line_height, @target.atk)
  1148.     self.contents.font.color = system_color
  1149.     draw_text(x + w * 2, y, tw, line_height, "SPD")
  1150.     self.contents.font.color = normal_color
  1151.     draw_text(x + w * 2, y, tw, line_height, @target.atk)
  1152.      self.contents.font.color = system_color
  1153.     draw_text(x + w * 3, y, tw, line_height, "DLY")
  1154.     self.contents.font.color = normal_color
  1155.     draw_text(x + w * 3, y, tw, line_height, @target.atk)    
  1156.   end
  1157.  
  1158.   def draw_enemy_stats
  1159.     y = line_height
  1160.     x = 32
  1161.     w = (contents_width - 32) / 2
  1162.     tw = (contents_width - w) / 3
  1163.     draw_actor_hp(@target, x, y, w)    
  1164.   end  
  1165.  
  1166.   def draw_summon_area
  1167.     summons = all_summons
  1168.     for i in 1...summons.size
  1169.       s = summons[i]
  1170.       r = item_rect(i - 1)
  1171.       x = r.x + 24
  1172.       y = r.y + 40
  1173.       disabled = s[:price] > @gold
  1174.       opacity = disabled ? 128 : 255
  1175.       draw_character(s[:character_name], s[:character_index], x, y, opacity)
  1176.       self.contents.font.size = 14
  1177.       self.contents.font.color = disabled ? disabled_color : normal_color
  1178.       draw_text(r.x, r.y, r.width, 14, s[:name], 1)
  1179.       draw_text(r.x, r.y, r.width, r.height - 14, "#{s[:price]} SP", 1)
  1180.     end
  1181.   end
  1182.  
  1183.   def item_rect(index)
  1184.     Rect.new(index * 64 + 16, line_height, 48, 48)
  1185.   end
  1186.  
  1187.   def draw_unit_options
  1188.   end
  1189.  
  1190.   def draw_summon_options
  1191.   end  
  1192.  
  1193.   def trigger?
  1194.     return false if !self.visible
  1195.     return false if @target && @target.built?
  1196.     for i in 0...item_max
  1197.       if Mouse.in_area?(mouse_item_rect(i))
  1198.         summon(i)
  1199.         return true
  1200.       end
  1201.     end
  1202.     return false
  1203.   end
  1204.  
  1205.   def summon(i)
  1206.     char = $game_system.tower_defense.summon(@target.index, all_summons[i + 1])
  1207.     if char
  1208.       self.target(char)
  1209.     end
  1210.   end
  1211.  
  1212.   def all_summons
  1213.     TOWER_DEFENSE[:ALLIES]
  1214.   end
  1215.  
  1216.   def item_max
  1217.     all_summons.size - 1
  1218.   end
  1219.  
  1220. end
  1221.  
  1222. class Sprite_TowerDefenseCounter < Sprite
  1223.  
  1224.   def initialize(viewport = nil)
  1225.     super(viewport)
  1226.     self.bitmap = Bitmap.new(Graphics.width, 32)
  1227.     refresh
  1228.   end
  1229.  
  1230.  
  1231.  
  1232.   def dispose
  1233.     self.bitmap.dispose
  1234.     super
  1235.   end
  1236.  
  1237.   def update
  1238.     super
  1239.     new_text = text
  1240.     if @last_text != new_text
  1241.       @last_text = text
  1242.       refresh
  1243.     end
  1244.   end
  1245.  
  1246.   def text
  1247.     if $game_system.tower_defense.rest_time > 0
  1248.       rest_text
  1249.     else
  1250.       wave_text
  1251.     end
  1252.   end
  1253.  
  1254.   def rest_text
  1255.     time = $game_system.tower_defense.rest_time / 60
  1256.     sec  = time % 60
  1257.     min  = time / 60
  1258.     "%02d:%02d To next wave!" % [min, sec]
  1259.   end
  1260.  
  1261.   def wave_text
  1262.     id    = $game_system.tower_defense.wave_number
  1263.     left  = $game_system.tower_defense.dead_enemies.size
  1264.     total = $game_system.tower_defense.wave.compact.size
  1265.     "Wave #{id}: #{left}/#{total}"    
  1266.   end
  1267.  
  1268.   def refresh
  1269.     self.bitmap.clear
  1270.     self.bitmap.draw_text(0,0, self.width, self.height, text, 2)
  1271.   end
  1272.  
  1273. end
  1274.  
  1275. class Game_TowerDefenseCursor < Game_Character
  1276.  
  1277.   attr_accessor :target
  1278.  
  1279.   def initialize
  1280.     super
  1281.     @tile_id = 0
  1282.     @opacity = 255
  1283.     @transparent = false
  1284.     @target = nil
  1285.   end
  1286.  
  1287.   def update
  1288.     super
  1289.   end
  1290.  
  1291.   def character_name
  1292.     "$cursor"
  1293.   end
  1294.  
  1295.   def chatacter_index
  1296.     0
  1297.   end
  1298.  
  1299.   def step_anime
  1300.     true
  1301.   end
  1302.  
  1303.   def screen_x
  1304.     return @target.screen_x if @target
  1305.     Mouse.x / 32 * 32 + 16
  1306.   end
  1307.  
  1308.   def screen_y
  1309.     return @target.screen_y + 4 if @target
  1310.     Mouse.y / 32 * 32 + 32
  1311.   end
  1312.  
  1313. end
  1314.  
  1315. class Scene_TowerDefense < Scene_Base
  1316.  
  1317.   def start
  1318.     setup_manager
  1319.     create_spriteset
  1320.     create_gold_window
  1321.     create_hud
  1322.   end
  1323.  
  1324.   def terminate
  1325.     delete_hud
  1326.     delete_spriteset
  1327.   end
  1328.  
  1329.   def create_spriteset
  1330.     @spriteset = Spriteset_TowerDefense.new
  1331.   end  
  1332.  
  1333.   def create_gold_window
  1334.     @gold_window = Window_TowerDefenseGold.new
  1335.     @gold_window.z = 99999
  1336.   end
  1337.  
  1338.   def create_hud
  1339.     @hud = Window_TowerDefenseHud.new
  1340.     @hud.z = 99999
  1341.   end
  1342.  
  1343.   def setup_manager
  1344.     $game_system.tower_defense.on_wave_start  = method(:start_wave)
  1345.     $game_system.tower_defense.on_rest_start  = method(:start_rest)
  1346.     $game_system.tower_defense.on_wave_update = method(:update_wave)
  1347.     $game_system.tower_defense.on_rest_update = method(:update_rest)
  1348.     $game_system.tower_defense.on_victory     = method(:process_victory)
  1349.     $game_system.tower_defense.on_defeat      = method(:process_defeat)
  1350.     $game_system.tower_defense.on_spawn       = method(:spawn_enemy)
  1351.     $game_system.tower_defense.on_summon      = method(:summon_tower)
  1352.     $game_system.tower_defense.on_hit         = method(:remove_sprite)
  1353.     $game_system.tower_defense.on_kill        = method(:remove_sprite)
  1354.     $game_system.tower_defense.on_shoot       = method(:shoot_bullet)
  1355.     $game_system.tower_defense.start
  1356.   end
  1357.  
  1358.   def delete_spriteset
  1359.     @spriteset.dispose
  1360.   end
  1361.  
  1362.   def delete_hud
  1363.     @hud.dispose
  1364.   end
  1365.  
  1366.   def update
  1367.     super
  1368.     update_spriteset
  1369.     update_hud
  1370.     $game_system.tower_defense.update
  1371.   end
  1372.  
  1373.   def update_wave
  1374.     update_wave_input
  1375.   end
  1376.  
  1377.   def update_rest
  1378.     update_rest_input
  1379.   end
  1380.  
  1381.   def update_rest_input
  1382.     update_basic_input
  1383.   end
  1384.  
  1385.  
  1386.   def update_wave_input
  1387.     update_basic_input
  1388.   end
  1389.  
  1390.   def update_basic_input
  1391.     if Mouse.trigger?
  1392.       return if @hud.trigger?
  1393.       x = $game_system.tower_defense.tile_x(Mouse.x)
  1394.       y = $game_system.tower_defense.tile_y(Mouse.y)
  1395.       target = $game_system.tower_defense.first_target_at(x, y)
  1396.       @hud.display(target)
  1397.     end
  1398.   end
  1399.  
  1400.   def update_spriteset
  1401.     @spriteset.update
  1402.   end
  1403.  
  1404.   def update_hud
  1405.     @hud.update
  1406.   end
  1407.  
  1408.   def process_victory
  1409.     show_text("Victory!")
  1410.     $game_switches[TOWER_DEFENSE[:SWITCH_ID]] = true
  1411.     return_scene
  1412.   end
  1413.  
  1414.   def process_defeat
  1415.     show_text("Defeated...")
  1416.     $game_switches[TOWER_DEFENSE[:SWITCH_ID]] = false
  1417.     return_scene
  1418.   end
  1419.  
  1420.   def next_wave
  1421.     $game_system.tower_defense.next_wave
  1422.   end
  1423.  
  1424.   def start_wave
  1425.     show_text("Wave #{ $game_system.tower_defense.wave_number }")
  1426.   end
  1427.  
  1428.   def start_rest
  1429.   end
  1430.  
  1431.   def spawn_enemy(enemy)
  1432.     @spriteset.add_enemy(enemy)
  1433.   end
  1434.  
  1435.   def summon_tower(index, tower)
  1436.     @spriteset.add_tower(tower)
  1437.   end
  1438.  
  1439.   def shoot_bullet(buller)
  1440.     @spriteset.add_bullet(buller)
  1441.   end
  1442.  
  1443.   def spawn_bullet(bullet)
  1444.     @spriteset.add_bullet(bullet)
  1445.   end
  1446.  
  1447.   def remove_sprite(target)
  1448.     @spriteset.delete_sprite(target)
  1449.   end
  1450.  
  1451.   def show_text(text)
  1452.     sprite = Sprite.new
  1453.     sprite.z = 99999
  1454.     sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height / 8)
  1455.     sprite.bitmap.font.size = Graphics.height / 9
  1456.     sprite.bitmap.draw_text(0, 0, sprite.bitmap.width, sprite.bitmap.height, text, 1)
  1457.     sprite.ox = sprite.width / 2
  1458.     sprite.oy = sprite.height / 2
  1459.     sprite.opacity = 0
  1460.     sprite.zoom_x = 0.0
  1461.     sprite.zoom_y = 0.0
  1462.     sprite.x = Graphics.width / 2
  1463.     sprite.y = sprite.height / 2 + Graphics.height
  1464.     i = 60
  1465.     while i > 0
  1466.       basic_update
  1467.       sprite.opacity = (sprite.opacity * (i - 1) + 255) / i
  1468.       sprite.zoom_x = (sprite.zoom_x * (i - 1) + 1.0) / i
  1469.       sprite.zoom_y = sprite.zoom_x
  1470.       sprite.y = (sprite.y * (i - 1) + Graphics.height / 2) / i
  1471.       i -= 1
  1472.     end
  1473.     60.times { |i| basic_update }
  1474.     i = 20
  1475.     while i > 0
  1476.       basic_update
  1477.       sprite.opacity = (sprite.opacity * (i - 1)) / i
  1478.       sprite.zoom_x = (sprite.zoom_x * (i - 1) + 4.0) / i
  1479.       sprite.zoom_y = sprite.zoom_x
  1480.       sprite.y = (sprite.y * (i - 1) + sprite.height) / i
  1481.       i -= 1
  1482.     end  
  1483.     sprite.bitmap.dispose
  1484.     sprite.dispose
  1485.   end
  1486.  
  1487.   def basic_update
  1488.     Graphics.update
  1489.     update_spriteset
  1490.     update_hud
  1491.     #$game_system.tower_defense.update
  1492.   end
  1493.  
  1494. end
Advertisement
Add Comment
Please, Sign In to add comment