Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #===============================================================================
- # * Tower defense
- #-------------------------------------------------------------------------------
- # Version 0.9.0
- # Until 30th October 2015 usable only by people of the Evil Lair
- # After that day, it's free for all as Apache 2.0.
- #-------------------------------------------------------------------------------
- # By Ramiro
- # Apache 2.0 license
- #-------------------------------------------------------------------------------
- # Usage:
- #
- # * Configuring the map:
- # > In order to configure the map you need to edit its regions:
- # - set it to 2 if the enemy should move down from this tile
- # - set it to 4 if the enemy should move left from here
- # - set it to 6 if the enemy should move right from here
- # - set it to 8 if the enemy should move up from here
- # There are special cases to choose a random direction:
- # - 1 is random between down or left
- # - 3 is random between down or right
- # - 5 is random between left or right
- # - 7 is random between up or left
- # - 9 is random between up or right
- # - 10 is random between up or down
- # The map marked as the region 20, is the tile where if the enemy reach
- # this tile it's game over (in other words, the end of the path)
- #
- # You also have to mark your summon places, in order to do that, mark each
- # summon area as the region 50.
- #
- #
- # * Starting the scene:
- # - Teleport to the tower defense map.
- # - Set your party's gold to the amount of starting gold to use
- # - Script call: id = put here the id of the stage
- # $game_system.tower_defense.setup(id)
- # SceneManager.call(Scene_TowerDefense)
- # - Wait 1 frame
- # - Check if the switch is true (victory) or false (defeat) and continue
- # the event as normal.
- #
- # * Adding enemy types or tower types:
- # - Configure the script here in order to add, remove or change values
- #
- #===============================================================================
- #===============================================================================
- # Configure things here
- #===============================================================================
- TOWER_DEFENSE = {
- #------------------------------------------------------------------------------
- # * General configuration
- #------------------------------------------------------------------------------
- # select the id of the switch than returns the result of the battle
- SWITCH_ID: 1,
- # The name used by the summoning area.
- SUMMON_AREA_NAME: "Summon area",
- # The icon used in the gold window
- SUMMONING_POWER_ICON_INDEX: 1,
- #------------------------------------------------------------------------------
- # * Allies configuration
- #------------------------------------------------------------------------------
- ALLIES: [ nil, # leave id 0 out
- {
- # The name used by this tower
- name: 'Ghost',
- # The character (must exists in Graphics/characters)
- character_name: 'monster1',
- # The index of the character (0 first, 7 last)
- character_index: 0,
- # The name of the projectile's graphic (must exists in Graphics/characters)
- projectile_name: 'fire1',
- # The color the enemy flashes when hit by the bullet (r, g, b)
- bullet_color: Color.new(255, 0, 0),
- # The maximun hp a tower can handle
- mhp: 1000,
- # the atk power at lvl 1
- atk: 10,
- # delay (in frames) between each bullet
- delay: 60,
- # The maximun level of the tower
- max_level: 10,
- # The time
- time: 4,
- # The starting price
- price: 100,
- # The radius (in tiles) the tower has
- distance: 4
- },
- {
- name: 'Skeleton',
- character_name: 'monster1',
- character_index: 1,
- projectile_name: 'fire1',
- bullet_color: Color.new(255, 0, 0),
- mhp: 1000,
- atk: 10,
- delay: 60,
- max_level: 10,
- time: 4,
- price: 100,
- distance: 4
- },
- {
- name: 'Orc',
- character_name: 'monster1',
- character_index: 2,
- projectile_name: 'fire1',
- bullet_color: Color.new(255, 0, 0),
- mhp: 1000,
- atk: 10,
- delay: 60,
- max_level: 10,
- time: 4,
- price: 100,
- distance: 4
- },
- {
- name: 'Demon',
- character_name: 'monster1',
- character_index: 3,
- projectile_name: 'fire1',
- bullet_color: Color.new(255, 0, 0),
- mhp: 1000,
- atk: 10,
- delay: 60,
- max_level: 10,
- time: 4,
- price: 100,
- distance: 4
- },
- {
- name: 'Reaper',
- character_name: 'monster1',
- character_index: 6,
- projectile_name: 'fire1',
- bullet_color: Color.new(255, 0, 0),
- mhp: 1000,
- atk: 10,
- delay: 60,
- max_level: 10,
- time: 4,
- price: 100,
- distance: 4
- },
- {
- name: 'Overlord',
- character_name: 'monster1',
- character_index: 7,
- projectile_name: 'fire1',
- bullet_color: Color.new(255, 0, 0),
- mhp: 1000,
- atk: 10,
- delay: 60,
- radius: 96,
- max_level: 10,
- time: 4,
- price: 100,
- distance: 4
- }
- ],
- #------------------------------------------------------------------------------
- # * Enemies configuration
- #------------------------------------------------------------------------------
- ENEMIES: [ nil, # leave id 0 out
- { # enemy starts like this
- # The name showed at the hud
- name: 'Slime',
- # The name of the character (must be in graphics/characters)
- character_name: 'monster2',
- # The index of the graphic (0 first, 7 last)
- character_index: 2,
- # The level displayed at the hud
- level: 1,
- # The maximun hp this enemy has
- mhp: 100,
- # The speed of the enemy
- speed: 2,
- # The frecuency (not used by now)
- frecuency: 1,
- # Amount of gold the enemy leaves when dead
- gold: 100,
- } # enemy ends with this (remember to separate them with ,)
- ],
- #------------------------------------------------------------------------------
- # * Stage configuration
- #------------------------------------------------------------------------------
- STAGES: [ nil, # leave id 0 out
- {
- # spawn coordinates [x, y]
- spawn: [1, 0],
- # time between each monster spawn
- tick: 60,
- # This are the waves, eyou can add as many as you need per stage
- waves: [
- # wave 1 [enemy_id1, enemy_id2, ...]
- # nil means "skip one spawn"
- [1, nil, nil, nil, 1, nil, nil, nil, 1, nil, nil, nil, 1, nil, nil, nil, 1],
- # wave 2 [enemy_id1, enemy_id2, ...]
- [1, 1, 1, 1, 1],
- # wave 3 [enemy_id1, enemy_id2, ...]
- [1, 1, 1, 1, 1]
- ]
- }
- ]
- }
- #===============================================================================
- # Script starts here, editing something past here will cause a meltdown...
- # or not, you may know what you are doing.
- #===============================================================================
- #===============================================================================
- # ** Game_TowerDefense
- #-------------------------------------------------------------------------------
- # This class (inside Game_System) manages the flow of the Tower Defense game
- #===============================================================================
- class Game_TowerDefense
- #-----------------------------------------------------------------------------
- # Class properties
- #-----------------------------------------------------------------------------
- attr_reader :enemies
- attr_reader :towers
- attr_reader :bullets
- attr_reader :rest_time
- attr_reader :cursor
- attr_accessor :wave_tick
- attr_accessor :wave_index
- attr_accessor :on_wave_start
- attr_accessor :on_rest_start
- attr_accessor :on_wave_update
- attr_accessor :on_rest_update
- attr_accessor :on_victory
- attr_accessor :on_defeat
- attr_accessor :on_spawn
- attr_accessor :on_summon
- attr_accessor :on_hit
- attr_accessor :on_kill
- attr_accessor :on_shoot
- #-----------------------------------------------------------------------------
- # constructor
- #-----------------------------------------------------------------------------
- def initialize
- @cursor = Game_TowerDefenseCursor.new
- @stage_id = 1
- @wave_id = 0
- @wave_index = 0
- @wave_tick = 0
- @towers = []
- clear_containers
- @rest_time = 3600
- self.on_wave_start = nil
- self.on_rest_start = nil
- self.on_wave_update = nil
- self.on_rest_update = nil
- self.on_victory = nil
- self.on_defeat = nil
- self.on_spawn = nil
- self.on_summon = nil
- self.on_kill = nil
- self.on_hit = nil
- self.on_shoot = nil
- end
- #-----------------------------------------------------------------------------
- # Clears both enemies and bullets
- #-----------------------------------------------------------------------------
- def clear_containers
- @enemies = []
- @bullets = []
- end
- #-----------------------------------------------------------------------------
- # All dead enemies
- #-----------------------------------------------------------------------------
- def dead_enemies
- enemies.select { |i| i.dead? }
- end
- #-----------------------------------------------------------------------------
- # All alive enemies
- #-----------------------------------------------------------------------------
- def alive_enemies
- enemies.select { |i| i.alive? }
- end
- #-----------------------------------------------------------------------------
- # Gets all alive towers
- #-----------------------------------------------------------------------------
- def alive_towers
- towers.select { |i| i.alive? }
- end
- #-----------------------------------------------------------------------------
- # starts a new stage by id
- #-----------------------------------------------------------------------------
- def setup(stage_id)
- @stage_id = stage_id
- @towers = []
- @wave_index = 0
- create_summoning_areas
- end
- #-----------------------------------------------------------------------------
- # Creates the places to summon
- #-----------------------------------------------------------------------------
- def create_summoning_areas
- for x in 0...$game_map.width
- for y in 0...$game_map.height
- if $game_map.region_id(x, y) == 50
- @towers << Game_TowerSpace.new(@towers.size, x, y)
- end
- end
- end
- end
- #-----------------------------------------------------------------------------
- # Gets the current stage
- #-----------------------------------------------------------------------------
- def stage
- TOWER_DEFENSE[:STAGES][@stage_id]
- end
- #-----------------------------------------------------------------------------
- # Gets the current wave
- #-----------------------------------------------------------------------------
- def wave
- self.stage[:waves][@wave_id]
- end
- #-----------------------------------------------------------------------------
- # gets the current stage's tick
- #-----------------------------------------------------------------------------
- def tick
- stage[:tick]
- end
- #-----------------------------------------------------------------------------
- # Gets the wave number to display on windows
- #-----------------------------------------------------------------------------
- def wave_number
- @wave_id + 1
- end
- #-----------------------------------------------------------------------------
- # Advances to the next wave
- #-----------------------------------------------------------------------------
- def next_wave
- @wave_id += 1
- if @wave_id >= self.stage[:waves].size
- start_wave
- else
- start_victory
- end
- end
- #-----------------------------------------------------------------------------
- # Starts the battle
- #-----------------------------------------------------------------------------
- def start
- clear_containers
- @wave_id = 0
- @wave_index = 0
- start_rest
- end
- #-----------------------------------------------------------------------------
- # Updates the current phase
- #-----------------------------------------------------------------------------
- def update
- self.cursor.update
- case @phase
- when :rest
- update_rest
- when :wave
- update_wave
- when :victory
- update_victory
- else
- update_defeat
- end
- end
- #-----------------------------------------------------------------------------
- # Updates the rest time between waves (1 minute)
- #-----------------------------------------------------------------------------
- def update_rest
- if @rest_time > 0
- @rest_time -= 1
- else
- start_wave
- end
- self.on_rest_update.call if self.on_rest_update
- end
- #-----------------------------------------------------------------------------
- # Updates the wave attack
- #-----------------------------------------------------------------------------
- def update_wave
- if @wave_tick > 0
- @wave_tick -= 1
- else
- spawn_enemy
- end
- update_enemies
- update_bullets
- update_towers
- self.on_wave_update.call if self.on_wave_update
- end
- #-----------------------------------------------------------------------------
- # Updates enemies
- #-----------------------------------------------------------------------------
- def update_enemies
- @enemies.each { |i| i.update }
- end
- #-----------------------------------------------------------------------------
- # Updates bullets
- #-----------------------------------------------------------------------------
- def update_bullets
- @bullets.each { |i| i.update }
- end
- #-----------------------------------------------------------------------------
- # Updates towers
- #-----------------------------------------------------------------------------
- def update_towers
- @towers.each { |i| i.update }
- end
- #-----------------------------------------------------------------------------
- # Starts the next wave
- #-----------------------------------------------------------------------------
- def start_wave
- @phase = :wave
- @wave_tick = 0
- self.on_wave_start.call if self.on_wave_start
- end
- #-----------------------------------------------------------------------------
- # Starts the rest phase between waves
- #-----------------------------------------------------------------------------
- def start_rest(time=3600)
- @phase = :rest
- self.wave_tick = 0
- @rest_time = time
- self.on_rest_start.call if self.on_wave_start
- end
- #-----------------------------------------------------------------------------
- # Starts the victory process
- #-----------------------------------------------------------------------------
- def start_victory
- @phase = :victory
- self.on_victory.call if self.on_victory
- end
- #-----------------------------------------------------------------------------
- # Starts the defeat process
- #-----------------------------------------------------------------------------
- def start_defeat
- @phase = :defeat
- self.on_defeat.call if self.on_defeat
- end
- #-----------------------------------------------------------------------------
- # Spawns a new enemy according to the wave's tick
- #-----------------------------------------------------------------------------
- def spawn_enemy
- @wave_tick = tick
- if @wave_index >= self.wave.size
- if alive_enemies.size < 1
- start_rest
- end
- else
- e = wave_enemy
- if e
- enemy = Game_TowerEnemy.new(e)
- @enemies << enemy
- self.on_spawn.call(enemy) if self.on_spawn
- end
- @wave_index += 1
- end
- end
- #-----------------------------------------------------------------------------
- # Gets the enemy the wave should spawn
- #-----------------------------------------------------------------------------
- def wave_enemy
- if wave[@wave_index]
- TOWER_DEFENSE[:ENEMIES][wave[@wave_index]]
- else
- nil
- end
- end
- #-----------------------------------------------------------------------------
- # Updates the victory phase
- #-----------------------------------------------------------------------------
- def update_victory
- end
- #-----------------------------------------------------------------------------
- # Updates the defeat phase
- #-----------------------------------------------------------------------------
- def update_defeat
- end
- #-----------------------------------------------------------------------------
- # Get targets at position
- #-----------------------------------------------------------------------------
- def targets_at(x, y)
- targets.select { |i| i.x == x && i.y == y }
- end
- #-----------------------------------------------------------------------------
- # targets are any enemy or tower
- #-----------------------------------------------------------------------------
- def targets
- enemies + towers
- end
- #-----------------------------------------------------------------------------
- # Shoots a bullet from a tower to an enemy
- #-----------------------------------------------------------------------------
- def shoot(tower, enemy)
- bullet = Game_TowerBullet.new(tower, bullet)
- self.on_shoot.call(bullet) if self.on_shoot
- @bullets << bullet
- end
- #-----------------------------------------------------------------------------
- # Get the first target you can find at position
- #-----------------------------------------------------------------------------
- def first_target_at(x, y)
- targets = targets_at(x, y)
- targets.size > 0 ? targets[0] : nil
- end
- #-----------------------------------------------------------------------------
- # Corrects the x acording to display
- #-----------------------------------------------------------------------------
- def tile_x(x)
- (x - $game_map.display_x) / 32
- end
- #-----------------------------------------------------------------------------
- # Corrects the y acording to display
- #-----------------------------------------------------------------------------
- def tile_y(y)
- (y - $game_map.display_y) / 32
- end
- #-----------------------------------------------------------------------------
- # Summons a new tower
- #-----------------------------------------------------------------------------
- def summon(index, ally)
- return nil if ally[:price] > $game_party.gold
- $game_party.lose_gold(ally[:price])
- old = @towers[index]
- @towers[index] = Game_TowerAlly.new(index, ally, old.x, old.y)
- self.on_summon.call(index, @towers[index]) if self.on_summon
- return @towers[index]
- end
- #-----------------------------------------------------------------------------
- # Process the hit of an enemy by a bullet
- #-----------------------------------------------------------------------------
- def process_hit(bullet, enemy)
- @bullets.delete(bullet)
- self.on_hit(bullet) if self.on_hit
- enemy.hp -= bullet.atk
- enemy.hit = bullet.color
- if enemy.dead?
- $game_party.gain_gold(enemy.gold)
- self.on_kill.call(enemy) if self.on_kill
- end
- end
- end
- #===============================================================================
- # ** Game_System
- #===============================================================================
- class Game_System
- #-----------------------------------------------------------------------------
- # added: tower_defense
- #-----------------------------------------------------------------------------
- def tower_defense
- @tower_defense ||= Game_TowerDefense.new
- end
- end
- #===============================================================================
- # ** Game_TowerCharacter
- #-------------------------------------------------------------------------------
- # This class is the parent of all towers and enemies of the tower defense.
- #===============================================================================
- class Game_TowerCharacter < Game_Character
- attr_reader :hp
- attr_reader :name
- attr_reader :level
- attr_accessor :hit
- def initialize
- super
- @name = 0
- @level = 0
- @hp = mhp
- @transparent = false
- @opacity = 255
- @hit = nil
- end
- def passable?(x, y, d)
- true
- end
- def hp=(value)
- @hp = [0, [mhp, value].min ].max
- end
- def mhp
- 0
- end
- def ally?
- false
- end
- def enemy?
- false
- end
- def dead?
- self.hp <= 0
- end
- def alive?
- !dead?
- end
- def hp_rate
- self.hp.to_f / self.mhp
- end
- def built?
- true
- end
- end
- class Game_TowerSpace < Game_TowerCharacter
- attr_reader :index
- def initialize(index, x, y)
- super()
- @name = TOWER_DEFENSE[:SUMMON_AREA_NAME]
- @level = 0
- @mhp = 100
- @index = index
- self.moveto(x, y)
- end
- def built?
- false
- end
- end
- class Game_TowerAlly < Game_TowerCharacter
- attr_reader :price
- attr_reader :level
- attr_reader :max_level
- attr_reader :mhp
- attr_reader :atk
- attr_reader :delay
- attr_reader :time
- attr_reader :distance
- attr_reader :index
- attr_reader :bullet_color
- def initialize(index, data, x, y)
- @index = index
- @data = data
- @atk = data[:atk]
- @mhp = data[:mhp]
- @price = data[:price]
- @max_level = data[:max_level]
- @delay = data[:delay]
- @speed = data[:speed]
- @distance = data[:distance]
- @character_name = data[:character_name]
- @character_index = data[:character_index]
- super()
- @tick = 0
- @level = 1
- @name = data[:name]
- @bullet_color = data[:bullet_color] ? data[:bullet_color] : Color.new(255, 0, 0)
- self.moveto(x, y)
- end
- def level_up
- return if maxed?
- cost = price_for(@level + 1)
- return if $game_party.gold < cost
- $game_party.lose_gold(cost)
- @level = @level + 1
- @atk = @data[:atk] + @data[:atk] * @level * @level / @max_level
- @mhp = @data[:mhp] + @data[:mhp] * @level * @level / @max_level
- @delay = @data[:delay] - @data[:delay] * @level * @level / (@max_level * 10)
- @time = @data[:time] - @data[:time] * @level * @level / (@max_level * 10)
- @distance = @data[:distance] + @data[:distance] * @level * @level / @max_level
- heal_hp
- end
- def repair_cost
- prive_for(level) * self.hp / self.mhp
- end
- def price_for(level)
- self.price * level * level
- end
- def heal_hp
- self.hp = self.mhp
- end
- def maxed?
- return self.level >= self.max_level
- end
- def ally?
- true
- end
- def repair
- cost = repair_cost
- return if $game_party.gold < cost
- $game_party.lose_gold(cost)
- heal_hp
- end
- def distance_from(charecter)
- Math.hypot(self.x - character.x, self.y - character.y)
- end
- def closest_enemy
- enemies = $game_system.tower_defense.alive_enemies
- return nil if enemies.size < 1
- x = enemies.sort {|a, b| a.distance_from(self)<=>b.distance_from(self) }
- x[0]
- end
- def reached_enemy
- enemy = closest_enemy
- return nil if !enemy
- return nil if self.distance_from(enemy) > self.distance
- enemy
- end
- def update
- super
- if @tick > 0
- @tick -= 1
- else
- update_bullet_check
- end
- end
- def update_bullet_check
- enemy = reached_enemy
- if enemy
- @tick = @delay
- $game_system.tower_defense.shoot(self, enemy)
- end
- end
- end
- class Game_TowerEnemy < Game_TowerCharacter
- def initialize(data)
- @mhp = data[:mhp]
- super()
- @name = data[:name]
- @level = data[:level]
- @move_speed = data[:speed]
- @move_frequency = data[:frecuency]
- @character_name = data[:character_name]
- @character_index = data[:character_index]
- spawn = $game_system.tower_defense.stage[:spawn]
- self.moveto(spawn[0], spawn[1])
- end
- def mhp
- @mhp
- end
- def update
- super
- if !moving?
- do_next_move
- end
- end
- def do_next_move
- region = region_id
- case region
- when 2..8
- move_straight(region)
- when 1
- move_straight( rand(2) == 0 ? 4 : 2 )
- when 3
- move_straight( rand(2) == 0 ? 6 : 2 )
- when 5
- move_straight( rand(2) == 0 ? 4 : 6 )
- when 7
- move_straight( rand(2) == 0 ? 4 : 8 )
- when 9
- move_straight( rand(2) == 0 ? 6 : 8 )
- when 10
- move_straight( rand(2) == 0 ? 2 : 8 )
- when 20
- $game_system.tower_defense.start_defeat
- end
- end
- def enemy?
- true
- end
- end
- class Game_TowerBullet
- attr_reader :mhp
- attr_reader :x
- attr_reader :y
- attr_reader :name
- def initialize(tower, target)
- @tower = tower
- @target = target
- @time = tower.time
- @x = tower.real_x
- @y = tower.real_y - 16
- @name = tower.projectile_name
- end
- def atk
- @tower.atk
- end
- def rect
- r = Rect.new(@tower.bullet_rect)
- r.x = self.x
- r.y = self.y
- return r
- end
- def color
- @tower.bullet_color
- end
- def update
- if active?
- update_position
- else
- process_hit
- end
- end
- def update_position
- @x = ( @x * (@time - 1) + @target.real_x ) / @time
- @y = ( @y * (@time - 1) + @target.real_y - 16 ) / @time
- @time -= 1
- end
- def process_hit
- $game_system.tower_defense.process_hit(self, @target)
- end
- def active?
- @time > 0
- end
- end
- class Sprite_TowerDefenseCharacter < Sprite_Character
- def update
- super
- return unless @character
- if @character.hit
- flash(@character.hit, 6)
- @character.hit = nil
- end
- end
- end
- class Sprite_TowerDefenseBullet < Sprite
- def initialize(viewport, bullet)
- super(viewport)
- @bullet = bullet
- self.bitmap = Cache.character(buller.name)
- end
- def update
- super
- self.x = @bullet.x
- self.y = @bullet.y
- end
- end
- class Spriteset_TowerDefense < Spriteset_Map
- #--------------------------------------------------------------------------
- # * Free
- #--------------------------------------------------------------------------
- def dispose
- super
- dispose_counter_sprite
- end
- def update
- super
- update_counter_sprite
- end
- def create_counter_sprite
- @sprite_counter = Sprite_TowerDefenseCounter.new(@viewport3)
- @sprite_counter.z = 99999
- end
- def dispose_counter_sprite
- @sprite_counter.dispose
- end
- def update_counter_sprite
- @sprite_counter.update
- end
- #--------------------------------------------------------------------------
- # * Create Character Sprite
- #--------------------------------------------------------------------------
- def create_characters
- @character_sprites = []
- @sprite_owner = {}
- create_counter_sprite
- @character_sprites << Sprite_Character.new(@viewport2, $game_system.tower_defense.cursor)
- @map_id = $game_map.map_id
- end
- def add_enemy(enemy)
- sprite = Sprite_TowerDefenseCharacter.new(@viewport1, enemy)
- @character_sprites << sprite
- @sprite_owner[enemy] = sprite
- end
- def add_tower(tower)
- sprite = Sprite_TowerDefenseCharacter.new(@viewport1, tower)
- @character_sprites << sprite
- @sprite_owner[tower] = sprite
- end
- def add_bullet(bullet)
- sprite = Sprite_TowerDefenseBullet.new(@viewport1, bullet)
- @character_sprites << sprite
- @sprite_owner[bullet] = sprite
- end
- def delete_sprite(target)
- sprite = @sprite_owner[target]
- return unless sprite
- @character_sprites.delete(sprite)
- sprite.dispose
- end
- end
- class Window_TowerDefenseGold < Window_Base
- def initialize
- super(0, 0, window_width, window_height)
- @gold = -1
- end
- def window_width
- 160
- end
- def window_height
- fitting_height(1)
- end
- def update
- super
- if @gold != $game_party.gold
- @gold = $game_party.gold
- refresh
- end
- end
- def refresh
- self.contents.clear
- draw_text(0, 0, self.contents.width, self.contents.height, @gold)
- icon_index = TOWER_DEFENSE[:SUMMONING_POWER_ICON_INDEX]
- draw_icon(icon_index, self.contents.width - 24, 0)
- end
- end
- class Window_TowerDefenseHud < Window_Base
- def initialize
- super(window_x, window_y, window_width, window_height)
- self.visible = false
- @target = nil
- @last_hp = -1
- @gold = 1
- end
- def window_x
- 0
- end
- def window_y
- Graphics.height - window_height
- end
- def window_width
- Graphics.width
- end
- def window_height
- fitting_height(3)
- end
- def update
- super
- return if !@target
- if @target.hp != @last_hp
- refresh
- @last_hp = @target.hp
- end
- update_options
- cursor_rect.set(Rect.new)
- return if @target.built?
- refresh_on_gold_change
- update_mouse_index
- end
- def refresh_on_gold_change
- if @gold != $game_party.gold
- @gold = $game_party.gold
- refresh
- end
- end
- def update_mouse_index
- for i in 0...item_max
- if Mouse.in_area?(mouse_item_rect(i))
- @index = i
- return cursor_rect.set(item_rect(i))
- end
- end
- end
- def mouse_item_rect(index)
- r = item_rect(index)
- r.x += self.real_x - self.ox
- r.y += self.real_y - self.oy
- return r
- end
- def real_x
- viewport ? self.x + viewport.rect.x - viewport.ox : self.x
- end
- def real_y
- viewport ? self.y + viewport.rect.y - viewport.oy : self.y
- end
- def update_options
- return if !@target.ally?
- end
- def display(target)
- if target != @target
- $game_system.tower_defense.cursor.target = target
- @target = target
- refresh
- end
- end
- def refresh
- self.contents.clear
- self.visible = @target ? true : false
- return if !self.visible
- draw_character_sprite
- draw_name_and_level
- if @target.ally?
- draw_ally_stats
- elsif @target.enemy?
- draw_enemy_stats
- else
- draw_summon_area
- end
- draw_unit_options if @target.ally?
- draw_summon_options if !@target.built?
- end
- def draw_character_sprite
- draw_character(@target.character_name, @target.character_index, 16, 32)
- end
- def draw_name_and_level
- draw_text(32, 0, contents_width - 32, line_height, @target.name)
- draw_text(32, 0, contents_width - 32, line_height, "Level #{@target.level}", 2)
- end
- def draw_ally_stats
- y = line_height
- x = 32
- w = (contents_width - 32) / 2
- tw = (contents_width - w) / 3
- draw_actor_hp(@target, x, y, w)
- self.contents.font.color = system_color
- draw_text(x + w, y, tw, line_height, "ATK")
- self.contents.font.color = normal_color
- draw_text(x + w, y, tw, line_height, @target.atk)
- self.contents.font.color = system_color
- draw_text(x + w * 2, y, tw, line_height, "SPD")
- self.contents.font.color = normal_color
- draw_text(x + w * 2, y, tw, line_height, @target.atk)
- self.contents.font.color = system_color
- draw_text(x + w * 3, y, tw, line_height, "DLY")
- self.contents.font.color = normal_color
- draw_text(x + w * 3, y, tw, line_height, @target.atk)
- end
- def draw_enemy_stats
- y = line_height
- x = 32
- w = (contents_width - 32) / 2
- tw = (contents_width - w) / 3
- draw_actor_hp(@target, x, y, w)
- end
- def draw_summon_area
- summons = all_summons
- for i in 1...summons.size
- s = summons[i]
- r = item_rect(i - 1)
- x = r.x + 24
- y = r.y + 40
- disabled = s[:price] > @gold
- opacity = disabled ? 128 : 255
- draw_character(s[:character_name], s[:character_index], x, y, opacity)
- self.contents.font.size = 14
- self.contents.font.color = disabled ? disabled_color : normal_color
- draw_text(r.x, r.y, r.width, 14, s[:name], 1)
- draw_text(r.x, r.y, r.width, r.height - 14, "#{s[:price]} SP", 1)
- end
- end
- def item_rect(index)
- Rect.new(index * 64 + 16, line_height, 48, 48)
- end
- def draw_unit_options
- end
- def draw_summon_options
- end
- def trigger?
- return false if !self.visible
- return false if @target && @target.built?
- for i in 0...item_max
- if Mouse.in_area?(mouse_item_rect(i))
- summon(i)
- return true
- end
- end
- return false
- end
- def summon(i)
- char = $game_system.tower_defense.summon(@target.index, all_summons[i + 1])
- if char
- self.target(char)
- end
- end
- def all_summons
- TOWER_DEFENSE[:ALLIES]
- end
- def item_max
- all_summons.size - 1
- end
- end
- class Sprite_TowerDefenseCounter < Sprite
- def initialize(viewport = nil)
- super(viewport)
- self.bitmap = Bitmap.new(Graphics.width, 32)
- refresh
- end
- def dispose
- self.bitmap.dispose
- super
- end
- def update
- super
- new_text = text
- if @last_text != new_text
- @last_text = text
- refresh
- end
- end
- def text
- if $game_system.tower_defense.rest_time > 0
- rest_text
- else
- wave_text
- end
- end
- def rest_text
- time = $game_system.tower_defense.rest_time / 60
- sec = time % 60
- min = time / 60
- "%02d:%02d To next wave!" % [min, sec]
- end
- def wave_text
- id = $game_system.tower_defense.wave_number
- left = $game_system.tower_defense.dead_enemies.size
- total = $game_system.tower_defense.wave.compact.size
- "Wave #{id}: #{left}/#{total}"
- end
- def refresh
- self.bitmap.clear
- self.bitmap.draw_text(0,0, self.width, self.height, text, 2)
- end
- end
- class Game_TowerDefenseCursor < Game_Character
- attr_accessor :target
- def initialize
- super
- @tile_id = 0
- @opacity = 255
- @transparent = false
- @target = nil
- end
- def update
- super
- end
- def character_name
- "$cursor"
- end
- def chatacter_index
- 0
- end
- def step_anime
- true
- end
- def screen_x
- return @target.screen_x if @target
- Mouse.x / 32 * 32 + 16
- end
- def screen_y
- return @target.screen_y + 4 if @target
- Mouse.y / 32 * 32 + 32
- end
- end
- class Scene_TowerDefense < Scene_Base
- def start
- setup_manager
- create_spriteset
- create_gold_window
- create_hud
- end
- def terminate
- delete_hud
- delete_spriteset
- end
- def create_spriteset
- @spriteset = Spriteset_TowerDefense.new
- end
- def create_gold_window
- @gold_window = Window_TowerDefenseGold.new
- @gold_window.z = 99999
- end
- def create_hud
- @hud = Window_TowerDefenseHud.new
- @hud.z = 99999
- end
- def setup_manager
- $game_system.tower_defense.on_wave_start = method(:start_wave)
- $game_system.tower_defense.on_rest_start = method(:start_rest)
- $game_system.tower_defense.on_wave_update = method(:update_wave)
- $game_system.tower_defense.on_rest_update = method(:update_rest)
- $game_system.tower_defense.on_victory = method(:process_victory)
- $game_system.tower_defense.on_defeat = method(:process_defeat)
- $game_system.tower_defense.on_spawn = method(:spawn_enemy)
- $game_system.tower_defense.on_summon = method(:summon_tower)
- $game_system.tower_defense.on_hit = method(:remove_sprite)
- $game_system.tower_defense.on_kill = method(:remove_sprite)
- $game_system.tower_defense.on_shoot = method(:shoot_bullet)
- $game_system.tower_defense.start
- end
- def delete_spriteset
- @spriteset.dispose
- end
- def delete_hud
- @hud.dispose
- end
- def update
- super
- update_spriteset
- update_hud
- $game_system.tower_defense.update
- end
- def update_wave
- update_wave_input
- end
- def update_rest
- update_rest_input
- end
- def update_rest_input
- update_basic_input
- end
- def update_wave_input
- update_basic_input
- end
- def update_basic_input
- if Mouse.trigger?
- return if @hud.trigger?
- x = $game_system.tower_defense.tile_x(Mouse.x)
- y = $game_system.tower_defense.tile_y(Mouse.y)
- target = $game_system.tower_defense.first_target_at(x, y)
- @hud.display(target)
- end
- end
- def update_spriteset
- @spriteset.update
- end
- def update_hud
- @hud.update
- end
- def process_victory
- show_text("Victory!")
- $game_switches[TOWER_DEFENSE[:SWITCH_ID]] = true
- return_scene
- end
- def process_defeat
- show_text("Defeated...")
- $game_switches[TOWER_DEFENSE[:SWITCH_ID]] = false
- return_scene
- end
- def next_wave
- $game_system.tower_defense.next_wave
- end
- def start_wave
- show_text("Wave #{ $game_system.tower_defense.wave_number }")
- end
- def start_rest
- end
- def spawn_enemy(enemy)
- @spriteset.add_enemy(enemy)
- end
- def summon_tower(index, tower)
- @spriteset.add_tower(tower)
- end
- def shoot_bullet(buller)
- @spriteset.add_bullet(buller)
- end
- def spawn_bullet(bullet)
- @spriteset.add_bullet(bullet)
- end
- def remove_sprite(target)
- @spriteset.delete_sprite(target)
- end
- def show_text(text)
- sprite = Sprite.new
- sprite.z = 99999
- sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height / 8)
- sprite.bitmap.font.size = Graphics.height / 9
- sprite.bitmap.draw_text(0, 0, sprite.bitmap.width, sprite.bitmap.height, text, 1)
- sprite.ox = sprite.width / 2
- sprite.oy = sprite.height / 2
- sprite.opacity = 0
- sprite.zoom_x = 0.0
- sprite.zoom_y = 0.0
- sprite.x = Graphics.width / 2
- sprite.y = sprite.height / 2 + Graphics.height
- i = 60
- while i > 0
- basic_update
- sprite.opacity = (sprite.opacity * (i - 1) + 255) / i
- sprite.zoom_x = (sprite.zoom_x * (i - 1) + 1.0) / i
- sprite.zoom_y = sprite.zoom_x
- sprite.y = (sprite.y * (i - 1) + Graphics.height / 2) / i
- i -= 1
- end
- 60.times { |i| basic_update }
- i = 20
- while i > 0
- basic_update
- sprite.opacity = (sprite.opacity * (i - 1)) / i
- sprite.zoom_x = (sprite.zoom_x * (i - 1) + 4.0) / i
- sprite.zoom_y = sprite.zoom_x
- sprite.y = (sprite.y * (i - 1) + sprite.height) / i
- i -= 1
- end
- sprite.bitmap.dispose
- sprite.dispose
- end
- def basic_update
- Graphics.update
- update_spriteset
- update_hud
- #$game_system.tower_defense.update
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment