Skip to content

Instantly share code, notes, and snippets.

@syureri
Last active March 15, 2019 20:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save syureri/36aef853c20ec6d39f1653171b3eca6c to your computer and use it in GitHub Desktop.
Save syureri/36aef853c20ec6d39f1653171b3eca6c to your computer and use it in GitHub Desktop.
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ O core principal. Ocasionalmente será referenciado como "o prism". ║
#╚═════════════════════════════════════════════════════════════════════════════╝
module Prism; extend self
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Constantes │
#└───────────────────────────────────────────────────────────────────────────┘
NOTE_SEPARATOR = "<>" # Separador de notas do Database.
FIXED_UPDATE_COUNT = 15 # Tempo de espera para o fixed update.
SECOND_UPDATE_COUNT = 60 # Tempo de espera para o update de segundos.
MAIN = {} # Registra scripts oficiais do prism.
REGISTERED = {} # Usado para registrar scripts no prism.
STANDALONE = Module.new # Módulo para a criação de scripts standalone.
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância │
#└───────────────────────────────────────────────────────────────────────────┘
@fx_up_count = 15 # Contagem inicial do fixed update.
@sc_up_count = 60 # Contagem inicial do second update.
#┌────────────┬──────────────────────────────────────────────────────────────┐
#│ ♦ register │ Sistema de registro de scripts. │
#├────────────┴──────────────────────────────────────────────────────────────┤
#│ Se o script for oficial do prism (script que faz parte dele), então o │
#│ argumento official precisa ser true. Do contrário, caso o script esteja │
#│ apenas usando o prism como um core, official deve ser false. │
#│ → name: o nome do script. │
#│ → version: a versão do script. │
#│ → author: o autor do script. Não usado caso official == true. │
#│ → official: se o script é oficial do prism. Padrão: false │
#└───────────────────────────────────────────────────────────────────────────┘
def register(name, version, author, official = false)
if official
MAIN[name] = {:name => name, :version => version}
else
REGISTERED[name] = {:name => name, :version => version, :author => author}
end
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ check_register │ Checa se um script está registrado. │
#├──────────────────┴────────────────────────────────────────────────────────┤
#│ Retorna uma hash com as informações de registro do script. │
#│ Caso não esteja registrado, retorna nil, como previsto. │
#│ → name: o nome do script. │
#│ → official: se o script é oficial do prism. Padrão: false │
#└───────────────────────────────────────────────────────────────────────────┘
def check_register(name, official = false)
return official ? MAIN[name] : REGISTERED[name]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ export │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Usado para exportar conteúdo usando a compressão Zlib::BEST_COMPRESSION. │
#│ → data: o conteúdo a ser exportado. │
#│ → ext: o caminho de destino do arquivo que será salvo. │
#└───────────────────────────────────────────────────────────────────────────┘
def export(data, ext)
save_data(Zlib::Deflate.deflate(data, Zlib::BEST_COMPRESSION), ext)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ import │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Usado para importar conteúdo que foi comprimido com Zlib. │
#│ → data: o conteúdo a ser importado. │
#└───────────────────────────────────────────────────────────────────────────┘
def import(data)
return Zlib::Inflate.inflate(load_data(data)).force_encoding("UTF-8")
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualiza todos os elementos do prism. │
#├───────────┴───────────────────────────────────────────────────────────────┤
#│ → requer: Graphics, na área de complementos. │
#└───────────────────────────────────────────────────────────────────────────┘
def update
fixed_update
second_update
Prism::Event_Utils.update rescue nil
Prism::Touch.update rescue nil
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ fixed_update │ Atualiza a contagem para o fixed_update. │
#├─────────────────┴─────────────────────────────────────────────────────────┤
#│ O Fixed Update é um update que atualiza a cada 15 frames, ao invés de 60 │
#│ frames. Sabe-se lá pra quê isso seria necessário no RM, mas de qualquer │
#│ modo, achei que seria bom deixar aqui. │
#└───────────────────────────────────────────────────────────────────────────┘
def fixed_update
next_count = @fx_up_count + 1
next_count > FIXED_UPDATE_COUNT ? @fx_up_count = 0 : @fx_up_count += 1
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ second_update │ Atualiza a contagem para o second_update. │
#├──────────────────┴────────────────────────────────────────────────────────┤
#│ Seguindo a onda do Fixed Update, o Second Update é um update que atualiza │
#│ a cada 1 segundo. Bem útil para criar timers. │
#└───────────────────────────────────────────────────────────────────────────┘
def second_update
next_count = @sc_up_count + 1
next_count > SECOND_UPDATE_COUNT ? @sc_up_count = 0 : @sc_up_count += 1
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ folder_name_check │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Substitui os caracteres "\ / : ? * < > |" por caracteres válidos para │
#│ serem usados como nomes de pastas/arquivos. │
#│ → string: supostamente o nome da pasta/arquivo em uma string. │
#└───────────────────────────────────────────────────────────────────────────┘
def folder_name_check(string)
result = string
result.gsub!(/\\\//) {"_"}
result.gsub!(/:/) {"-"}
result.gsub!(/\*\?<>\|/) {""}
return result
end
#┌──────────────────────┬────────────────────────────────────────────────────┐
#│ ♦ run_fixed_update? │ Informa se o fixed update pode executar. │
#└──────────────────────┴────────────────────────────────────────────────────┘
def run_fixed_update?
@fx_up_count == 15
end
#┌───────────────────────┬───────────────────────────────────────────────────┐
#│ ♦ run_second_update? │ Informa se o second update pode executar. │
#└───────────────────────┴───────────────────────────────────────────────────┘
def run_second_update?
@sc_up_count == 60
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_center_screen │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Permite obter a posição do centro da tela. │
#│ Caso um bitmap seja especificado, ele irá obter a posição do centro para │
#│ o bitmap. │
#│ → pos: :x ou :y │
#│ → bitmap: um bitmap de base. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def get_center_screen(pos, bitmap = nil)
x = Graphics.width * 0.5
y = Graphics.height * 0.5
unless bitmap.nil?
x -= bitmap.width * 0.5
y -= bitmap.height * 0.5
end
pos == :x ? result = x : result = y
return result
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ rate │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém a taxa de um valor. Útil para obter porcentagem de hp e etc... │
#│ → value: o valor atual. │
#│ → max_value: o valor máximo. │
#└───────────────────────────────────────────────────────────────────────────┘
def rate(value, max_value)
result = value.to_f / max_value
return result
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ decrease │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Diminui um valor para movimentação de uma janela/sprite/viewport │
#│ O valor será dimiduído de pouco em pouco para que ele não passe do │
#│ limite especificado. │
#│ → source: o valor que será diminuído. │
#│ → value: o quanto o valor deve diminuir. │
#│ → min: o limite para o qual o valor deve diminuir. │
#└───────────────────────────────────────────────────────────────────────────┘
def decrease(source, value, min)
if source - value < min && !value.is_a?(Float)
if value.even?
source -= value / 2
else
source -= (value + 1) / 2
end
else
source -= value
end
source = min if source < min
return source
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ increase │
#├───────────────────────────────────────────────────────────────────────────┤
#│ O contrário do decrease. Serve para aumentar um valor até o limite. │
#│ → source: o valor que será aumentado. │
#│ → value: o quanto o valor deve aumentar. │
#│ → max: o limite para o qual o valor deve aumentar. │
#└───────────────────────────────────────────────────────────────────────────┘
def increase(source, value, max)
if source + value > max && !value.is_a?(Float)
if value.even?
source += value / 2
else
source += (value + 1) / 2
end
else
source += value
end
source = max if source > max
return source
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ string_to_num │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Usado para transformar uma string em uma array de códigos dos caracteres │
#│ em UTF-8 (basicamente, transformar letras em números) │
#│ → string: uma string qualquer. │
#└───────────────────────────────────────────────────────────────────────────┘
def string_to_num(string)
result = []
for i in 0...string.size
result.push(string[i].unpack("U")[0])
end
return result
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ num_to_string │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Converte uma array de códigos de caracteres em UTF-8 em uma string. │
#│ O formato precisa ser o mesmo gerado pelo Prism.string_to_num. │
#│ Ex: "Heya" seria [72, 101, 121, 97]. │
#│ → array: uma array no formato mostrado acima. │
#└───────────────────────────────────────────────────────────────────────────┘
def num_to_string(array)
result = ""
array.each do |n|
result << [n].pack("C")[0]
end
return result
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ to_hex │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Converte um número inteiro em hexadecimal. O resultado será retornado │
#│ como uma string. │
#│ → array: uma array no formato mostrado acima. │
#└───────────────────────────────────────────────────────────────────────────┘
def to_hex(num)
result = sprintf("%#x", num.to_i)
return result
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ color_convert │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Converte uma string contendo valores de cores em hex (HTML/CSS) no objeto │
#│ Color. │
#│ Ex: color_convert("0a0b41") retorna Color.new(10, 11, 65) │
#│ → array: uma array no formato mostrado acima. │
#└───────────────────────────────────────────────────────────────────────────┘
def color_convert(color, alpha = 255)
r = eval("0x#{color[0..1]}")
g = eval("0x#{color[2..3]}")
b = eval("0x#{color[4..5]}")
return Color.new(r, g, b, alpha)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ wrap_text │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Retorna um texto com quebra de linha se ele passar da largura definida. │
#│ → text: o texto em si. │
#│ → width: a largura limite do texto. │
#│ → src_bitmap: um bitmap de base para ser usado para medir a largura. │
#└───────────────────────────────────────────────────────────────────────────┘
def wrap_text(text, width, src_bitmap = nil)
if src_bitmap
bitmap = src_bitmap
else
bitmap = Bitmap.new(width, 24)
end
result = ""
words = text.split(/ /)
pointer = 0
for w in words
word_width = bitmap.text_size(w).width + 2
space_width = bitmap.text_size(" ").width + 2
if pointer < width
if pointer + word_width > width
result << "\n" << w << " "
pointer = word_width + space_width
else
result << w << " "
pointer += word_width + space_width
end
else
result << "\n" << w << " "
pointer = word_width + space_width
end
end
return result
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ cut_bitmap │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Corta um bitmap usando outro bitmap como base. Preserva anti-aliasing. │
#│ Este método consome tempo. │
#│ → sb: o bitmap que será usado como base. │
#│ → db: o bitmap que será recortado. │
#│ → x: a posição em x que será cortada. Padrão: nil │
#│ → y: a posição em y que será cortada. Padrão: nil │
#│ → width: a largura que será cortada. Padrão: nil │
#│ → height: a altura que será cortada. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def cut_bitmap(sb, db, x = nil, y = nil, width = nil, height = nil)
x ||= 0
y ||= 0
width ||= db.width
height ||= db.height
for w in 0...width
for h in 0...height
pixel = sb.get_pixel(w, h)
npixel = db.get_pixel(w + x, h + y)
next if pixel.alpha.zero? || npixel.alpha.zero?
npixel.alpha -= pixel.alpha
db.set_pixel(w + x, h + y, npixel)
end
end
end
#┌─────────────┬─────────────────────────────────────────────────────────────┐
#│ ♦ warn_box │ Chama uma caixa de aviso com a mensagem especificada. │
#├─────────────┴─────────────────────────────────────────────────────────────┤
#│ → title: o título da caixa. │
#│ → text: o texto da caixa. │
#└───────────────────────────────────────────────────────────────────────────┘
def warn_box(title, text)
wb = Win32API.new("user32", "MessageBox", "lppl", "i")
tx = text.unpack("U*").pack("C*")
tl = title.unpack("U*").pack("C*")
wb.call(0, tx, tl, 0x0020)
end
#┌────────┬──────────────────────────────────────────────────────────────────┐
#│ ♦ log │ Similar ao msgbox_p. │
#├────────┴──────────────────────────────────────────────────────────────────┤
#│ → info: a informação a ser mostrada. │
#└───────────────────────────────────────────────────────────────────────────┘
def log(info)
warn_box("Log", info.to_s)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ load_notetags │
#├───────────────────────────────────────────────────────────────────────────┤
#│ É iniciado junto do database. Serve para carregar as notas de todos os │
#│ campos que possuam notas (do database). │
#│ → requer: DataManager, na área de complementos. │
#│ → requer: RPG::BaseItem, na área de complementos. │
#└───────────────────────────────────────────────────────────────────────────┘
def load_notetags
container = [$data_actors, $data_classes, $data_skills, $data_items,
$data_weapons, $data_armors, $data_enemies, $data_states]
container.each do |object|
object.each do |item|
next unless item
item.start_note_container
end
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ extract_scripts │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Extrai todos os scripts da lista do RPG Maker para a pasta especificada. │
#│ → folder: A pasta ou diretório. Deve terminar com / │
#└───────────────────────────────────────────────────────────────────────────┘
def extract_scripts(folder)
Dir.mkdir(folder) unless Dir.exists?(folder)
c = 0
$RGSS_SCRIPTS.each {|sc|
n = folder_name_check(folder + sprintf("%d - #{sc[1]}.rb", c))
t = sc[3]
next if t.empty?
begin
f = File.open(n, "w")
f.write(t)
ensure
f.close
end
c += 1
}
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ► Complementos ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Esta área serve para guardar os complementos necessários do Prism. ║
#║ Todos os extras requeridos ficam aqui. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Graphics ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class << Graphics
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ prism_update │ update │
#└────────────────┴──────────────────────────────────────────────────────────┘
alias :prism_update :update
def update
prism_update
Prism.update
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Graphics ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Marshal ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class << Marshal
#┌───────────────┬──────┬────────────────────────────────────────────────────┐
#│ ♦ prism_load │ load │ Permite a leitura de arquivos que não sejam do RM. │
#└───────────────┴──────┴────────────────────────────────────────────────────┘
alias :prism_load :load
def load(port, proc = nil)
prism_load(port, proc)
rescue TypeError
if port.kind_of?(File)
port.rewind
port.read
else
port
end
end
end unless Marshal.respond_to?(:prism_load) # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Marshal ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ DataManager ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class << DataManager
#┌────────────────────────┬───────────────┬─────────────────────────────────┐
#│ ♦ prism_load_database │ load_database │ Inicia as notas do Database. │
#└────────────────────────┴───────────────┴─────────────────────────────────┘
alias :prism_load_database :load_database
def load_database
prism_load_database
Prism.load_notetags
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ DataManager ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ RPG::BaseItem ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class RPG::BaseItem
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :note_container
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ start_note_container │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Cria um depósito (container) onde todos os campos que estejam dentro do │
#│ NOTE_SEPARATOR do Prism sejam guardados individualmente. │
#└───────────────────────────────────────────────────────────────────────────┘
def start_note_container
sp = Prism::NOTE_SEPARATOR
@note_container = []
self.note.scan(/#{sp[0]}[^>]*#{sp[1]}/).collect {|tag|
@note_container.push(tag)
}
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ in_container? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Checa se uma tag existe dentro do container. │
#│ → expr: uma expressão regular (regular expression). │
#└───────────────────────────────────────────────────────────────────────────┘
def in_container?(expr)
@note_container.find {|tag| tag =~ expr}
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_tag │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém uma tag existente no container e o primeiro valor dela. │
#│ → expr: uma expressão regular (regular expression). │
#└───────────────────────────────────────────────────────────────────────────┘
def get_tag(expr)
tag = in_container?(expr)
if tag && tag =~ expr
return $1
else
return ""
end
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ RPG::BaseItem ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Game_Map ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Game_Map
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ adjust_x │
#└───────────────────────────────────────────────────────────────────────────┘
def adjust_x(x)
pos = (@display_x * 32).floor.to_f / 32
if loop_horizontal? && x < pos - (width - screen_tile_x) / 2
x - pos + @map.width
else
x - pos
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ adjust_y │
#└───────────────────────────────────────────────────────────────────────────┘
def adjust_y(y)
pos = (@display_y * 32).floor.to_f / 32
if loop_vertical? && y < pos - (height - screen_tile_y) / 2
y - pos + @map.height
else
y - pos
end
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Game_Map ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Export_Prism ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Isto serve para extrair o Prism inteiro em um arquivo Prism.data comprimido ║
#║ usando a compressão Zlib. ║
#║ O nome do script deve estar registrado logo abaixo para ser extraído. ║
#║ A ordem dos scripts no arquivo extraído é a mesma ordem dele na lista de ║
#║ scripts do editor. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Export_Prism
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Assim que você cria a classe, o initialize vai realizar todo o processo │
#│ de extração. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize
# Lembre-se de adicionar o script nessa lista.
@list = [
"♦ Prism",
"♦ Prism::File_Management",
"♦ Prism::Grid",
"♦ Prism::Point",
"♦ Prism::Scene",
"♦ Prism::Input",
"♦ Prism::Touch",
"♦ Prism::Touch_Input",
"♦ Prism::Event_Utils",
"♦ Prism::Base_Window",
"♦ Prism::Window_Select",
"♦ Prism::Window_Command",
"♦ Prism::Horz_Command",
"♦ Prism::Input_Window",
"♦ Prism::Base_Sprite",
"♦ Prism::Opening_Sprite",
"♦ Prism::Text_Sprite",
"♦ Prism::Gauge_Sprite",
"♦ Prism::Animated_Sprite",
"♦ Prism::Aura_Sprite",
"♦ Prism::Circular_Sprite",
"♦ Prism::Numeric_Sprite",
"♦ Prism::Jump_Sprite",
"♦ Prism::Flashing_Sprite",
"♦ Prism::Touch_Sprite",
"♦ Prism::Drag_Sprite",
"♦ Prism::GUI"]
extract_prism
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ extract_prism │ Nome auto-explicativo. │
#└─────────────────┴─────────────────────────────────────────────────────────┘
def extract_prism
data = ""
$RGSS_SCRIPTS.each {|script|
name = script[1]
code = script[3]
next unless @list.include?(name)
data += code + "\n\n"
}
Prism.export(data.force_encoding("UTF-8"), "Prism.data")
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Export_Prism ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::File_Management ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sistema de gerenciamento de arquivos em um subshell. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
module Prism::File_Management
extend self
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ move │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Move um arquivo ou pasta para o diretório especificado. │
#│ Se um arquivo já existir na pasta de destino, ele será substituído. │
#│ Para mover uma pasta, from não deve terminar em \\. │
#│ Note que o diretório de destino deve existir antes de ser movido. │
#│ → from: o diretório do arquivo/pasta. │
#│ → to: o destino do arquivo/pasta. │
#└───────────────────────────────────────────────────────────────────────────┘
def move(from, to)
Kernel.system("move \"#{from}\" \"#{to}\"")
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ copy │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Copia um arquivo para o diretório especificado. │
#│ Se um arquivo já existir na pasta de destino, ele será substituído. │
#│ Note que o diretório de destino deve existir antes de ser movido. │
#│ → from: o diretório do arquivo. │
#│ → to: o destino do arquivo. │
#└───────────────────────────────────────────────────────────────────────────┘
def copy(from, to)
Kernel.system("copy \"#{from}\" \"#{to}\"")
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ copy_folder │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Copia um diretório e todos os seus arquivos para outro diretório. │
#│ Se já existirem arquivos ou pastas no destino, eles serão substituídos. │
#│ A menos, é claro, que substitute seja false. │
#│ → from: a pasta que será movida (sem \\ no final). │
#│ → to: o destino da pasta (sem \\ no final). │
#│ → substitute: se ele deve substituir ou perguntar antes. │
#└───────────────────────────────────────────────────────────────────────────┘
def copy_folder(from, to, substitute = true)
sub = substitute ? " /y" : ""
Kernel.system("xcopy \"#{from}\" \"#{to}\" /e /i /h#{sub}")
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ rename │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Renomeia um arquivo ou pasta. │
#│ → source: o diretório do arquivo ou pasta que será renomeado. │
#│ → name: o nome, e apenas o novo nome do arquivo ou pasta. │
#└───────────────────────────────────────────────────────────────────────────┘
def rename(source, name)
Kernel.system("rename \"#{source}\" \"#{name}\"")
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::File_Management ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Grid ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ O Prism::Grid é uma coleção de arrays, contendo espaços verticais e ║
#║ horizontais, e também camadas. Basicamente uma grade de arrays. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Grid
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ initialize │ Cria a grade. │
#├───────────────┴───────────────────────────────────────────────────────────┤
#│ → x_size: o número de espaços horizontais na grade. │
#│ → y_size: o número de espaços verticais na grade. │
#│ → layers: o número de camadas da grade. Padrão: 1. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x_size, y_size, layers = 1)
@x_size = x_size
@y_size = y_size
@layers = layers
make_grid
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ make_grid │ Isto irá criar a grade. Não é preciso chamar novamente. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def make_grid
@grid = {}
layers = Array.new(@layers)
rows = Array.new(@y_size)
cols = Array.new(@x_size)
for i in 0...layers.size
@grid[i] = rows.clone
end
@grid.each_key do |layer|
for i in 0...@grid[layer].size
@grid[layer][i] = cols.clone
end
end
layers = rows = cols = nil
end
#┌───────┬───────────────────────────────────────────────────────────────────┐
#│ ♦ [] │ Obtém um elemento da grade. │
#├───────┴───────────────────────────────────────────────────────────────────┤
#│ Este método serve para que você obtenha qualquer elemento da grade. │
#│ Elementos que não existem na grade sempre retornarão nil. │
#│ Caso você tente obter informações sobre elementos que estejam além do │
#│ limite da grade, haverá uma mensagem de notificação e o resultado será │
#│ nil. │
#│ Os seguintes argumentos são necessários. │
#│ → x: a posição horizontal do objeto na grade. │
#│ → y: a posição vertical do objeto na grade. │
#│ → z: a camada do objeto na grade. │
#└───────────────────────────────────────────────────────────────────────────┘
def [](*val)
x = val[0]
y = val[1]
z = val[2] ? val[2] : 0
begin
if @grid[z]
res = @grid[z][y][x]
else
res = nil
end
rescue
w = "O conteúdo que você está tentando obter\nestá fora do limite da grade."
Prism.warn_box("Atenção", w)
return nil
end
return res
end
#┌────────┬──────────────────────────────────────────────────────────────────┐
#│ ♦ []= │ Altera um elemento da grade. │
#├────────┴──────────────────────────────────────────────────────────────────┤
#│ Similar ao [], porém serve para alterar um elemento da grade. │
#│ Se você tentar alterar um elemento que esteja fora dos limites da grade, │
#│ haverá uma mensagem de aviso e nenhuma alteração será feita. │
#│ Os seguintes argumentos são necessários. │
#│ → x: a posição horizontal do objeto na grade. │
#│ → y: a posição vertical do objeto na grade. │
#│ → z: a camada do objeto na grade. │
#└───────────────────────────────────────────────────────────────────────────┘
def []=(*val)
x = val[0]
y = val[1]
z = val[2] ? val[2] : 0
res = val[3]
begin
@grid[z][y][x] = res if @grid[z]
rescue
w = "O conteúdo que você está tentando alterar\nestá fora do limite da grade.\n"
w2 = "Nenhuma alteração será feita."
Prism.warn_box("Atenção", w << w2)
end
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ horizontal_size │ Retorna o número de espaços horizontais da grade. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def horizontal_size
@x_size
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ vertical_size │ Retorna o número de espaços verticais da grade. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def vertical_size
@y_size
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ layers_size │ Retorna o número de camadas da grade. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def layers_size
@layers
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ layer │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém todos os elementos existentes em uma específica camada. │
#│ Elementos que não existem (nil) serão ignorados. │
#│ → num: o número da camada específica. │
#└───────────────────────────────────────────────────────────────────────────┘
def layer(num)
array = []
for col in @grid[num]
next if col.compact.empty?
array.push(col.compact)
end
return array
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ up │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Retorna o elemento que esteja logo acima do objeto especificado. │
#│ Os seguintes argumentos são necessários: │
#│ → x: a posição horizontal do objeto. │
#│ → y: a posição vertical do objeto. │
#│ → z: a camada do objeto. │
#│ Lembrando que o que será retornado não será o objeto especificado, e sim │
#│ o que está logo acima dele. │
#└───────────────────────────────────────────────────────────────────────────┘
def up(*val)
layer = val[2]
row = val[1]
col = val[0]
return @grid[layer][row - 1][col]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ right │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Mesma coisa do up, porém retorna o elemento que está logo à direita do │
#│ objeto especificado. │
#│ Os argumentos são os mesmos do up. │
#└───────────────────────────────────────────────────────────────────────────┘
def right(*val)
layer = val[2]
row = val[1]
col = val[0]
return @grid[layer][row][col + 1]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ left │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Mesma coisa do up, porém retorna o elemento que está logo à esquerda do │
#│ objeto especificado. │
#│ Os argumentos são os mesmos do up. │
#└───────────────────────────────────────────────────────────────────────────┘
def left(*val)
layer = val[2]
row = val[1]
col = val[0]
return @grid[layer][row][col - 1]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ down │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Mesma coisa do up, porém retorna o elemento que está logo abaixo do │
#│ objeto especificado. │
#│ Os argumentos são os mesmos do up. │
#└───────────────────────────────────────────────────────────────────────────┘
def down(*val)
layer = val[2]
row = val[1]
col = val[0]
return @grid[layer][row + 1][col]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ resize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Altera o tamanho da grade para as dimensões especificadas. │
#│ Os dados já existentes serão mantidos. │
#│ → x_size: o número de espaços horizontais na grade. │
#│ → y_size: o número de espaços verticais na grade. │
#│ → layers: o número de camadas da grade. Requerido. │
#└───────────────────────────────────────────────────────────────────────────┘
def resize(x, y, z)
new_grid = {}
for i in 0...z
new_grid[i] = Array.new(y)
end
new_grid.each_key do |row|
for i in 0...new_grid[row].size
new_grid[row][i] = Array.new(x)
end
end
new_grid.each_key do |row|
for i in 0...new_grid[row].size
for j in 0...new_grid[row][i].size
new_grid[row][i][j] = @grid[row][i][j]
end
end
end
@x_size = x
@y_size = y
@layers = z
@grid = new_grid
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ resize! │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Altera "destrutivamente" o tamanho da grade para as dimensões │
#│ especificadas. │
#│ Obviamente, os dados já existentes serão deletados. │
#│ → x_size: o número de espaços horizontais na grade. │
#│ → y_size: o número de espaços verticais na grade. │
#│ → layers: o número de camadas da grade. Requerido. │
#└───────────────────────────────────────────────────────────────────────────┘
def resize!(x, y, z)
new_grid = {}
for i in 0...z
new_grid[i] = Array.new(y)
end
new_grid.each_key do |row|
for i in 0...new_grid[row].size
new_grid[row][i] = Array.new(x)
end
end
@x_size = x
@y_size = y
@layers = z
@grid = new_grid
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ move │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Move o objeto especificado para outro lugar da grade. │
#│ Se houver um objeto no lugar de destino, ele será substituído, cuidado. │
#│ Se você estiver tentando obter posições que estejam além do limite da │
#│ grade, você receberá uma mensagem de aviso e nenhuma alteração será │
#│ feita. │
#│ Exemplo: move([1, 1, 1], [1, 2, 1]) │
#│ → from: uma array contendo a posição do objeto que será movido. │
#│ → to: uma array contendo a posição de destino do objeto. │
#└───────────────────────────────────────────────────────────────────────────┘
def move(from, to)
if from[0] > @x_size || from[1] > @y_size || from[2] > @layers
w = "O conteúdo que você está tentando obter\nestá fora do limite da grade."
Prism.warn_box("Atenção", w)
return nil
elsif to[0] > @x_size || to[1] > @y_size || to[2] > @layers
w = "O conteúdo que você está tentando obter\nestá fora do limite da grade."
Prism.warn_box("Atenção", w)
return nil
end
current = @grid[from[2]][from[1]][from[0]]
@grid[to[2]][to[1]][to[0]] = current
@grid[from[2]][from[1]][from[0]] = nil
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Grid ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Point ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ A classe dos pontos do Prism. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Point
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância públicas │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :x
attr_accessor :y
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize
@x = 0
@y = 0
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Point ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Scene ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Uma scene que dá automaticamente o update em todas os sprites que forem ║
#║ herdados de Prism::Base_Sprite. E umas coisinhas a mais. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Scene < Scene_Base
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ start │ Inicia a cena. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def start
super
make_reserved_bitmap_list
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ make_reserved_bitmap_list │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Não processa o dispose nos bitmaps dos sprites que estiverem nessa │
#│ lista. │
#└───────────────────────────────────────────────────────────────────────────┘
def make_reserved_bitmap_list
@reserved_bitmaps = []
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def update
super
fixed_update if Prism.run_fixed_update?
second_update if Prism.run_second_update?
update_all_images
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ fixed_update │ Atualização a cada 15 frames. │
#└─────────────────┴─────────────────────────────────────────────────────────┘
def fixed_update
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ second_update │ Atualização a cada 1 segundo. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def second_update
end
#┌──────────────────────┬────────────────────────────────────────────────────┐
#│ ♦ update_all_images │ Atualiza todas as imagens do Prism. │
#└──────────────────────┴────────────────────────────────────────────────────┘
def update_all_images
instance_variables.each do |var|
ivar = instance_variable_get(var)
ivar.update if ivar.is_a?(Prism::Base_Sprite)
end
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ terminate │ Finalização da cena. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def terminate
Input.update
super
dispose_all_images
end
#┌───────────────────────┬───────────────────────────────────────────────────┐
#│ ♦ dispose_all_images │ Se livra de todas as imagens. │
#└───────────────────────┴───────────────────────────────────────────────────┘
def dispose_all_images
instance_variables.each do |var|
ivar = instance_variable_get(var)
if ivar.is_a?(Sprite)
unless @reserved_bitmaps.include?(ivar)
ivar.bitmap.dispose unless ivar.bitmap.disposed?
end
ivar.dispose unless ivar.disposed?
end
end
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Scene ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Input ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um Input que aceita mais teclas do teclado. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
module Prism::Input
extend self
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Códigos virtuais de tecla │
#└───────────────────────────────────────────────────────────────────────────┘
KEYS = {
:NUM0 => 0x60, :NUM5 => 0x65, :N0 => 0x30, :N5 => 0x35,
:NUM1 => 0x61, :NUM6 => 0x66, :N1 => 0x31, :N6 => 0x36,
:NUM2 => 0x62, :NUM7 => 0x67, :N2 => 0x32, :N7 => 0x37,
:NUM3 => 0x63, :NUM8 => 0x68, :N3 => 0x33, :N8 => 0x38,
:NUM4 => 0x64, :NUM9 => 0x69, :N4 => 0x34, :N9 => 0x39,
:A => 0x41, :E => 0x45, :I => 0x49, :M => 0x4D, :Q => 0x51, :U => 0x55,
:B => 0x42, :F => 0x46, :J => 0x4A, :N => 0x4E, :R => 0x52, :V => 0x56,
:C => 0x43, :G => 0x47, :K => 0x4B, :O => 0x4F, :S => 0x53, :W => 0x57,
:D => 0x44, :H => 0x48, :L => 0x4C, :P => 0x50, :T => 0x54, :X => 0x58,
:Y => 0x59, :Z => 0x5A, :Ç => 0xBA,
:BACKSPACE => 0x08, :CAPS => 0x14, :CTRL => 0x11, :PGDN => 0x22,
:TAB => 0x1B, :ESC => 0x1B, :ALT => 0x12, :PGUP => 0x21,
:ENTER => 0x23, :SPACE => 0x20, :End => 0x23, :MOUSEL => 0x01,
:SHIFT => 0x02, :DELETE => 0x2E, :INSERT => 0x2D, :MOUSER => 0x02,
:MOUSEM => 0x04, :PAUSE => 0x13, :RETURN => 0x0D,
:MULTIPLY => 0x6A, :DECIMAL => 0x6E, :MINUS => 0xBD, :ACCUTE => 0xDB,
:ADD => 0x6B, :DIVIDE => 0x6F, :DOT => 0xBE, :QUOTE => 0xC0,
:SEPARATOR => 0x6C, :PLUS => 0xBB, :COLON => 0xBF, :BRACKET => 0xDD,
:SUBTRACT => 0x6D, :COMMA => 0xBC, :LASH => 0xC1, :BRACKET2 => 0xDC,
:TIL => 0xDE, :BACKLASH => 0xE2,
:F1 => 0x70, :F5 => 0x74, :F9 => 0x78, :F13 => 0x7C, :F17 => 0x80,
:F2 => 0x71, :F6 => 0x75, :F10 => 0x79, :F14 => 0x7D, :F18 => 0x81,
:F3 => 0x72, :F7 => 0x76, :F11 => 0x7A, :F15 => 0x7E, :F19 => 0x82,
:F4 => 0x73, :F8 => 0x77, :F12 => 0x7B, :F16 => 0x7F, :F20 => 0x83,
:F21 => 0x84, :F22 => 0x85, :F23 => 0x86, :F24 => 0x87
}
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Hash que converte a tecla pressionada em texto. │
#└───────────────────────────────────────────────────────────────────────────┘
CHARACTERS = {
:caps => {
:NUM0 => '0', :NUM1 => '1', :NUM2 => '2', :NUM3 => '3', :NUM4 => '4',
:NUM5 => '5', :NUM6 => '6', :NUM7 => '7', :NUM8 => '8', :NUM9 => '9',
:N0 => ')', :N1 => '!', :N2 => '@', :N3 => '#', :N4 => '$',
:N5 => '%', :N6 => '¨', :N7 => '&', :N8 => '*', :N9 => '(',
:A => 'A', :B => 'B', :C => 'C', :D => 'D', :E => 'E', :F => 'F',
:G => 'G', :H => 'H', :I => 'I', :J => 'J', :K => 'K', :L => 'L',
:M => 'M', :N => 'N', :O => 'O', :P => 'P', :Q => 'Q', :R => 'R',
:S => 'S', :T => 'T', :U => 'U', :V => 'V', :W => 'W', :X => 'X',
:Y => 'Y', :Z => 'Z', :Ç => 'Ç',
:MULTIPLY => '*', :ADD => '+', :SEPARATOR => '.',
:SUBTRACT => '-', :DECIMAL => ',', :DIVIDE => '/',
:PLUS => '+', :COMMA => '<', :MINUS => '_',
:DOT => '>', :COLON => ':', :LASH => '?',
:ACCUTE => '`', :QUOTE => '"', :BRACKET => '{',
:BRACKET2 => '}', :BACKLASH => '|', :TIL => '^',
:SPACE => ' '},
:lower => {
:NUM0 => '0', :NUM1 => '1', :NUM2 => '2', :NUM3 => '3', :NUM4 => '4',
:NUM5 => '5', :NUM6 => '6', :NUM7 => '7', :NUM8 => '8', :NUM9 => '9',
:N0 => '0', :N1 => '1', :N2 => '2', :N3 => '3', :N4 => '4',
:N5 => '5', :N6 => '6', :N7 => '7', :N8 => '8', :N9 => '9',
:A => 'a', :B => 'b', :C => 'c', :D => 'd', :E => 'e', :F => 'f',
:G => 'g', :H => 'h', :I => 'i', :J => 'j', :K => 'k', :L => 'l',
:M => 'm', :N => 'n', :O => 'o', :P => 'p', :Q => 'q', :R => 'r',
:S => 's', :T => 't', :U => 'u', :V => 'v', :W => 'w', :X => 'x',
:Y => 'y', :Z => 'z', :Ç => 'ç',
:MULTIPLY => '*', :ADD => '+', :SEPARATOR => '.',
:SUBTRACT => '-', :DECIMAL => ',', :DIVIDE => '/',
:PLUS => '=', :COMMA => ',', :MINUS => '-',
:DOT => '.', :COLON => ';', :LASH => '/',
:ACCUTE => '´', :QUOTE => "'", :BRACKET => '[',
:BRACKET2 => ']', :BACKLASH => '\\', :TIL => '~',
:SPACE => ' '},
:accented => {
'a' => %w(á ã â à ä), 'A' => %w(Á Ã Â À Ä),
'e' => %w(é ~e ê è ë), 'E' => %w(É ~E Ê È Ë),
'i' => %w(í ~i î ì ï), 'I' => %w(Í ~I Î Ì Ï),
'o' => %w(ó õ ô ò ö), 'O' => %w(Ó Õ Ô Ò Ö),
'u' => %w(ú ~u û ù ü), 'U' => %w(Ú ~U Û Ù Ü),
'y' => %w(ý ~y ^y `y ÿ), 'Y' => %w(Ý ~Y ^Y `Y ¨Y)},
:accents => %w(´ ~ ^ ` ¨),
:accent_list => %w(A a E e I i O o U u Y y),
}
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Api │
#└───────────────────────────────────────────────────────────────────────────┘
KEYSTATE = Win32API.new("user32", "GetAsyncKeyState", "i", "i")
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ state │ Abreviação para adquirir o estado do teclado. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def state
KEYSTATE
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ shift? │ Indica se a tecla SHIFT está sendo pressionada. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def shift?
state.call(16) != 0 ? true : false
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de instância │
#└───────────────────────────────────────────────────────────────────────────┘
@trigger = []
@repeat_trigger = []
@count = []
@timer = 0
@touch = {}
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_pressed? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Informa se uma tecla está sendo pressionada. │
#│ → key: uma constante da lista acima. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_pressed?(key)
if key.is_a?(Symbol)
k = KEYS[key]
else
k = key
end
state.call(k) != 0 if k
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_triggered? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Informa se uma tecla foi pressionada uma vez. │
#│ → key: uma constante da lista acima. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_triggered?(key)
if is_pressed?(key)
if @trigger.include?(key)
return false
else
@trigger.push(key)
return true
end
else
@trigger.delete(key) if @trigger.include?(key)
return false
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_repeated? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Informa se uma tecla está sendo pressionada repetidamente. │
#│ → key: uma constante da lista acima. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_repeated?(key)
if is_pressed?(key)
@repeat_trigger.push(key) unless @repeat_trigger.include?(key)
ind = @repeat_trigger.index(key)
@count[ind].nil? ? @count[ind] = 0 : @count[ind] += 1
condition = (@count[ind] >= 30 && @count[ind] % 3 == 1)
return @count[ind] == 1 ? true : condition
else
ind = @repeat_trigger.index(key) if @repeat_trigger.include?(key)
@count[ind] = nil if ind
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_touch_triggered? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Mesma coisa do is_triggered?, porém é usado apenas pelo Touch_Input. │
#│ → obj: objeto que servirá como referência única do registro. │
#│ → key: uma constante da lista acima. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_touch_triggered?(obj, key)
@touch[obj] ||= {}; @touch[obj][:trigger] ||= []
if is_pressed?(key)
if @touch[obj][:trigger].include?(key)
return false
else
@touch[obj][:trigger].push(key)
return true
end
else
@touch[obj][:trigger].delete(key) if @touch[obj][:trigger].include?(key)
return false
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_touch_repeated? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Mesma coisa do is_repeated?, porém é usado apenas pelo Touch_Input. │
#│ → obj: objeto que servirá como referência única do registro. │
#│ → key: uma constante da lista acima. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_touch_repeated?(obj, key)
@touch[obj] ||= {}; @touch[obj][:repeat] ||= []
@touch[obj] ||= {}; @touch[obj][:repeat_count] ||= []
if is_pressed?(key)
@touch[obj][:repeat].push(key) unless @touch[obj][:repeat].include?(key)
ind = @touch[obj][:repeat].index(key)
@touch[obj][:repeat_count][ind].nil? ? @touch[obj][:repeat_count][ind] = 0 : @touch[obj][:repeat_count][ind] += 1
condition = (@touch[obj][:repeat_count][ind] >= 30 && @touch[obj][:repeat_count][ind] % 3 == 1)
return @touch[obj][:repeat_count][ind] == 1 ? true : condition
else
ind = @touch[obj][:repeat].index(key) if @touch[obj][:repeat].include?(key)
@touch[obj][:repeat_count][ind] = nil if ind
end
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Input ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Touch ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ A base para o sistema de toque do Prism. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
module Prism::Touch
extend self
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Apis do sistema │
#└───────────────────────────────────────────────────────────────────────────┘
Sys = {
:gcp => Win32API.new("user32", "GetCursorPos", "p", "i"),
:stc => Win32API.new("user32", "ScreenToClient", "lp", "i"),
:pps => Win32API.new("kernel32", "GetPrivateProfileStringA", "pppplp", "l"),
:fwn => Win32API.new("user32", "FindWindowA", "pp", "l"),
:scp => Win32API.new("user32", "SetCursorPos", "ll", "i"),
:scr => Win32API.new("user32", "ShowCursor", "i", "i")
}
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de posição. │
#└───────────────────────────────────────────────────────────────────────────┘
@real_mouse_x = 0 # A posição X real do mouse na tela.
@real_mouse_y = 0 # A posição Y real do mouse na tela.
@x = 0 # A posição X do mouse na tela do jogo.
@y = 0 # A posição Y do mouse na tela do jogo.
@last_x = 0 # A posição do último toque do mouse em X.
@last_y = 0 # A posição do último toque do mouse em Y.
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update │
#└───────────────────────────────────────────────────────────────────────────┘
def update
update_last_info
pos = [0, 0].pack("ll")
win = ->() {
gm = "\0" * 256
Sys[:pps].call("Game", "Title", "", gm, 255, ".\\Game.ini")
gm.delete!("\0")
return Sys[:fwn].call("RGSS Player", gm || "0")
}
Sys[:gcp].call(pos)
@real_mouse_x = pos.unpack("ll")[0]
@real_mouse_y = pos.unpack("ll")[1]
Sys[:stc].call(win.call(), pos)
@x = pos.unpack("ll")[0]
@y = pos.unpack("ll")[1]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update_last_info │
#└───────────────────────────────────────────────────────────────────────────┘
def update_last_info
if Prism::Input.is_pressed?(1) || Prism::Input.is_pressed?(2)
@last_x = @x
@last_y = @y
end
end
#┌─────────────┬─────────────────────────────────────────────────────────────┐
#│ ♦ last_pos │ Obtém a última posição de toque. │
#└─────────────┴─────────────────────────────────────────────────────────────┘
def last_pos
return [@last_x, @last_y]
end
#┌────────┬──────────────────────────────────────────────────────────────────┐
#│ ♦ pos │ Obtém as coordenadas do cursor. │
#└────────┴──────────────────────────────────────────────────────────────────┘
def pos
return [@x, @y]
end
#┌─────────────┬─────────────────────────────────────────────────────────────┐
#│ ♦ real_pos │ Obtém as coordenadas reais do cursor. │
#└─────────────┴─────────────────────────────────────────────────────────────┘
def real_pos
return [@real_mouse_x, @real_mouse_y]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Muda a posição do cursor para a posição desejada. │
#│ → x: a posição horizontal. │
#│ → y: a posição vertical. │
#└───────────────────────────────────────────────────────────────────────────┘
def set(x, y)
Sys[:scp].call(x, y)
end
#┌─────────┬─────────────────────────────────────────────────────────────────┐
#│ ♦ show │ Mostra o cursor. │
#└─────────┴─────────────────────────────────────────────────────────────────┘
def show
Sys[:scr].call(1)
end
#┌─────────┬─────────────────────────────────────────────────────────────────┐
#│ ♦ hide │ Esconde o cursor. │
#└─────────┴─────────────────────────────────────────────────────────────────┘
def hide
Sys[:scr].call(0)
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Touch ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Touch_Input ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ O sistema de toque do Prism. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
module Prism::Touch_Input
extend self
#┌──────┬────────────────────────────────────────────────────────────────────┐
#│ ♦ x │ A posição horizontal do mouse. │
#└──────┴────────────────────────────────────────────────────────────────────┘
def x
return Prism::Touch.pos[0]
end
#┌──────┬────────────────────────────────────────────────────────────────────┐
#│ ♦ y │ A posição vertical do mouse. │
#└──────┴────────────────────────────────────────────────────────────────────┘
def y
return Prism::Touch.pos[1]
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ is_pressed? │ Indica se está sendo tocado. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def is_pressed?
return Prism::Input.is_pressed?(1)
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ is_triggered? │ Indica se foi tocado uma vez. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def is_triggered?(obj = nil)
return Prism::Input.is_touch_triggered?(obj || self, 1)
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ is_repeated? │ Indica se está sendo tocado repetidamente. │
#└─────────────────┴─────────────────────────────────────────────────────────┘
def is_repeated?(obj = nil)
return Prism::Input.is_touch_repeated?(obj || self, 1)
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ is_cancelling? │ Indica se está sendo cancelado. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def is_cancelling?
return Prism::Input.is_pressed?(2)
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ is_cancelled? │ Indica se foi cancelado uma vez. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def is_cancelled?(obj = nil)
return Prism::Input.is_touch_triggered?(obj || self, 2)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ hovering? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se o cursor está acima de algo. │
#│ → sx: a posição horizontal do objeto. │
#│ → sy: a posição vertical do objeto. │
#│ → width: a largura do objeto. │
#│ → height: a altura do objeto. │
#└───────────────────────────────────────────────────────────────────────────┘
def hovering?(sx, sy, width, height)
c1 = x >= sx && x <= sx + width
c2 = y >= sy && y <= sy + height
return c1 && c2
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Touch_Input ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Event_Utils ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Alguns métodos que podem ajudar na hora de obter informações sobre os ║
#║ eventos no mapa. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
module Prism::Event_Utils
extend self
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Classe │
#└───────────────────────────────────────────────────────────────────────────┘
@@px = 0
@@py = 0
@@di = 0
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ player_pos │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Informa a posição do jogador, também informa a direção dele. │
#│ → type: um tipo da lista abaixo: │
#│ :x retorna a posição horizontal do jogador no mapa. │
#│ :y retorna a posição vertical do jogador no mapa. │
#│ :d retorna um número com a direção do jogador. │
#└───────────────────────────────────────────────────────────────────────────┘
def player_pos(type)
case type
when :x; return @@px
when :y; return @@py
when :d; return @@di
else; return false
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_player_direction │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Retorna a direção do jogador em :left, :right, :up ou :down. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_player_direction
res = :void
case @@di
when 4; res = :left
when 6; res = :right
when 8; res = :up
when 2; res = :down
end
return res
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_map_event │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém um evento no mapa nas coordenadas especificadas. │
#│ → x: a coordenada horizontal do evento no mapa. │
#│ → y: a coordenada vertical do evento no mapa. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_map_event(x, y)
ev = nil
$game_map.events.each {|event|
next unless event[1] && event[1].is_a?(Game_Event)
next unless event[1].x == x && event[1].y == y
ev = event[1]
break
}
return ev
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_right_event │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o evento que está exatamente à direita do jogador. │
#│ → range: a distância que o evento estará. │
#│ → in_range: se o evento deve estar dentro da distância ou não. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_right_event(range = 1, in_range = false)
res = nil
if in_range
for i in 0...range
if get_map_event(@@px + (i + 1), @@py)
res = get_map_event(@@px + (i + 1), @@py)
break
end
end
else
res = get_map_event(@@px + range, @@py)
end
return res
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_left_event │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o evento que está exatamente à esquerda do jogador. │
#│ → range: a distância que o evento estará. │
#│ → in_range: se o evento deve estar dentro da distância ou não. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_left_event(range = 1, in_range = false)
res = nil
if in_range
for i in 0...range
if get_map_event(@@px - (i + 1), @@py)
res = get_map_event(@@px - (i + 1), @@py)
break
end
end
else
res = get_map_event(@@px - range, @@py)
end
return res
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_up_event │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o evento que está exatamente acima do jogador. │
#│ → range: a distância que o evento estará. │
#│ → in_range: se o evento deve estar dentro da distância ou não. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_up_event(range = 1, in_range = false)
res = nil
if in_range
for i in 0...range
if get_map_event(@@px, @@py - (i + 1))
res = get_map_event(@@px, @@py - (i + 1))
break
end
end
else
res = get_map_event(@@px, @@py - range)
end
return res
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_down_event │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o evento que está exatamente abaixo do jogador. │
#│ → range: a distância que o evento estará. │
#│ → in_range: se o evento deve estar dentro da distância ou não. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_down_event(range = 1, in_range = false)
res = nil
if in_range
for i in 0...range
if get_map_event(@@px, @@py + (i + 1))
res = get_map_event(@@px, @@py + (i + 1))
break
end
end
else
res = get_map_event(@@px, @@py + range)
end
return res
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_diagonal_up_event │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Retorna uma array com os eventos que estiverem acima do jogador na │
#│ diagonal. │
#│ → range: a distância que o evento estará. │
#│ → in_range: se o evento deve estar dentro da distância ou não. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_diagonal_up_event(range = 1, in_range = false)
res = []
if in_range
for i in 0...range
up_right = get_map_event(@@px + (i + 1), @@py - (i + 1))
up_left = get_map_event(@@px - (i + 1), @@py - (i + 1))
if up_right
res.push(up_right)
end
if up_left
res.push(up_left)
end
end
else
up_right = get_map_event(@@px + 1, @@py - 1)
up_left = get_map_event(@@px - 1, @@py - 1)
res.push(up_right) if up_right
res.push(up_left) if up_left
end
return res
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_diagonal_down_event │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Retorna uma array com os eventos que estiverem abaixo do jogador na │
#│ diagonal. │
#│ → range: a distância que o evento estará. │
#│ → in_range: se o evento deve estar dentro da distância ou não. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_diagonal_down_event(range = 1, in_range = false)
res = []
if in_range
for i in 0...range
down_right = get_map_event(@@px + (i + 1), @@py + (i + 1))
down_left = get_map_event(@@px - (i + 1), @@py + (i + 1))
if down_right
res.push(down_right)
end
if down_left
res.push(down_left)
end
end
else
down_right = get_map_event(@@px + 1, @@py + 1)
down_left = get_map_event(@@px - 1, @@py + 1)
res.push(down_right) if down_right
res.push(down_left) if down_left
end
return res
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_event_comments │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém todos os comentários da página principal de um evento. │
#│ Se params for um Game_Event ou qualquer superclasse, ele irá obter │
#│ os comentários diretamente daquele evento. │
#│ Porém se params for x e y, ele irá obter o evento no mapa, e então irá │
#│ pegar os comentários dele. │
#│ → params: (x, y) ou (evento) │
#└───────────────────────────────────────────────────────────────────────────┘
def get_event_comments(*params)
text = ""
if params.size > 1
x = params[0]
y = params[1]
ev = get_map_event(x, y)
if ev.list
for cmd in ev.list
next unless cmd.is_a?(RPG::EventCommand)
next unless cmd.code == 108 || cmd.code == 408
text += cmd.parameters[0] + "\n"
end
end
else
ev = params[0]
if ev.list
for cmd in ev.list
next unless cmd.is_a?(RPG::EventCommand)
next unless cmd.code == 108 || cmd.code == 408
text += cmd.parameters[0] + "\n"
end
end
end
return text
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualização das informações. │
#└───────────────────────────────────────────────────────────────────────────┘
def update
update_components
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update_components │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualização de componentes. │
#└───────────────────────────────────────────────────────────────────────────┘
def update_components
@@px = $game_player.x
@@py = $game_player.y
@@di = $game_player.direction
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Event_Utils ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Base_Window ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Uma janela de base do Prism. Ela possui diversos métodos que podem ser bem ║
#║ úteis, e são essenciais para todas as outras janelas herdadas dela. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Base_Window < Window
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal. │
#│ → y: posição vertical. │
#│ → width: largura. │
#│ → height: altura. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height)
super
self.windowskin = Cache.system("Window")
update_padding
update_tone
create_contents
make_animation_list
@opening = @closing = @busy = false
@move_speed = 4
@opacity_speed = 4
@opening_speed = 18
@move_route = []
@write_message = {}
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ opening_speed │ Velocidade de abertura. Vale para o fechamento também. │
#└─────────────────┴─────────────────────────────────────────────────────────┘
def opening_speed
return @opening_speed
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ opening_speed= │ Altera a velocidade de abertura e fechamento. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def opening_speed=(v)
@opening_speed = v
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ make_animation_list │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Cria uma lista de animações de movimento para serem usadas a qualquer │
#│ momento. │
#└───────────────────────────────────────────────────────────────────────────┘
def make_animation_list
@anim_list = {}
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ add_animation │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Adiciona uma animação à lista de animações. │
#│ → name: o nome da animação na lista de animações. │
#│ → x: a posição de destino horizontal da janela. │
#│ → y: a posição de destino vertical da janela. │
#│ → width: a largura de destino da janela. │
#│ → height: a altura de destino da janela. │
#│ → op: a opacidade de destino da janela. │
#└───────────────────────────────────────────────────────────────────────────┘
def add_animation(name, x, y, w, h, op)
@anim_list[name] = [x, y, w, h, op]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ start_animation │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Executa uma animação da lista de animações de movimento. │
#│ → anim: o símbolo da animação na lista de animações. │
#└───────────────────────────────────────────────────────────────────────────┘
def start_animation(anim)
list = @anim_list[anim]
case list.size
when 1; move_to(list[0])
when 2; move_to(list[0], list[1])
when 3; move_to(list[0], list[1], list[2])
when 4; move_to(list[0], list[1], list[2], list[3])
when 5; move_to(list[0], list[1], list[2], list[3], list[4])
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ opening_sound │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Reproduz um som ao abrir a janela. │
#│ → enable: true para ativar, false para desativar. Padrão: false │
#│ → sound: o som para reproduzir. Deve estar na pasta Audio/SE │
#└───────────────────────────────────────────────────────────────────────────┘
def opening_sound(enable = false, sound = RPG::SE.new("Ice1", 80, 100))
if enable
sound.play
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ closing_sound │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Reproduz um som ao fechar a janela. │
#│ → enable: true para ativar, false para desativar. Padrão: false │
#│ → sound: o som para reproduzir. Deve estar na pasta Audio/SE │
#└───────────────────────────────────────────────────────────────────────────┘
def closing_sound(enable = false, sound = RPG::SE.new("Ice2", 80, 100))
if enable
sound.play
end
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ window_padding │ A distância entre a borda da janela e o conteúdo. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def window_padding
return 12
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ line_height │ A altura da linha da janela. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def line_height
return 24
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ fitting_height │ Calcula a altura da janela para o número de linhas. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def fitting_height(line_number)
line_number * line_height + window_padding * 2
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ create_contents │ Cria e recria o bitmap para o conteúdo da janela. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def create_contents
self.contents.dispose
if contents_width > 0 && contents_height > 0
self.contents = Bitmap.new(contents_width, contents_height)
else
self.contents = Bitmap.new(1, 1)
end
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ contents_width │ A largura do conteúdo visível da janela. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def contents_width
if self.width - window_padding * 2 < 1
return 1
end
return self.width - window_padding * 2
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ contents_height │ A altura do conteúdo visível da janela. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def contents_height
if self.height - window_padding * 2 < 1
return 1
end
return self.height - window_padding * 2
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ busy_mode │
#├───────────────────────────────────────────────────────────────────────────┤
#│ O modo de ocupação da janela. │
#│ → open_mode: estará ocupada quando estiver aberta. │
#│ → active_mode: estará ocupada quando estiver ativa. │
#│ → moving_mode: estará ocupada quando estiver se movendo. │
#│ → all_mode: quando estiver aberta e ativa ou se movendo. │
#└───────────────────────────────────────────────────────────────────────────┘
def busy_mode
return :active_mode
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ move_speed │ A velocidade de movimento da janela (em pixels). │
#└──────────────┴────────────────────────────────────────────────────────────┘
def move_speed
return @move_speed
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ opacity_speed │ A velocidade de alteração da opacidade. │
#└─────────────────┴─────────────────────────────────────────────────────────┘
def opacity_speed
return @opacity_speed
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ move_speed= │ Altera a velocidade de movimento para v. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def move_speed=(v)
@move_speed = v
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ opacity_speed= │ Altera a velocidade de alteração da opacidade para v. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def opacity_speed=(v)
@opacity_speed = v
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
fixed_update if Prism.run_fixed_update?
second_update if Prism.run_second_update?
update_tone
update_padding
update_busy
update_movement
update_write_message
update_open if @opening
update_close if @closing
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ fixed_update │ Atualização a cada 15 frames. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def fixed_update
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ second_update │ Atualização a cada 1 segundo (60 frames). │
#└─────────────────┴─────────────────────────────────────────────────────────┘
def second_update
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ update_tone │ Atualiza a tonalidade da janela. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def update_tone
self.tone.set($game_system.window_tone)
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ update_padding │ Atualiza o padding da janela. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def update_padding
self.padding = window_padding
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ update_busy │ Atualiza a ocupação da janela. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def update_busy
if busy_mode == :open_mode
open? ? @busy = true : @busy = false
elsif busy_mode == :active_mode
self.active ? @busy = true : @busy = false
elsif busy_mode == :moving_mode
moving? ? @busy = true : @busy = false
elsif busy_mode == :all_mode
con = open? && self.active
con2 = moving?
if con || con2
@busy = true
elsif !con || !con2
@busy = false
end
end
end
#┌─────────┬─────────────────────────────────────────────────────────────────┐
#│ ♦ busy? │ Checa se a janela está ocupada. │
#└─────────┴─────────────────────────────────────────────────────────────────┘
def busy?
@busy == true
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ moving? │ Checa se a janela está se movendo. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def moving?
!@move_route.empty?
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ showing_message? │ Checa se a janela está mostrando uma mensagem. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def showing_message?
!@write_message.empty?
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ waiting_message_input? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Checa se a janela está esperando o botão de confirmação ser pressionado │
#│ ao mostrar uma mensagem. │
#└───────────────────────────────────────────────────────────────────────────┘
def waiting_message_input?
@write_message[:wait_for_input].nil? ? false : true
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ update_open │ Atualiza a abertura da janela. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def update_open
self.openness += opening_speed
@opening = false if open?
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ update_close │ Atualiza o fechamento da janela. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def update_close
self.openness -= opening_speed
@closing = false if close?
end
#┌────────┬──────────────────────────────────────────────────────────────────┐
#│ ♦ open │ Abre a janela. │
#└────────┴──────────────────────────────────────────────────────────────────┘
def open
opening_sound unless open?
@opening = true unless open?
@closing = false
end
#┌─────────┬─────────────────────────────────────────────────────────────────┐
#│ ♦ close │ Fecha a janela. │
#└─────────┴─────────────────────────────────────────────────────────────────┘
def close
closing_sound unless close?
@closing = true unless close?
@opening = false
end
#┌────────────┬──────────────────────────────────────────────────────────────┐
#│ ♦ activate │ Ativa a janela. │
#└────────────┴──────────────────────────────────────────────────────────────┘
def activate
self.active = true
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ deactivate │ Desativa a janela. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def deactivate
self.active = false
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ move_to │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Move a janela até a posição especificada (ela vai se mover até lá). │
#│ → x: o destino em x. │
#│ → y: o destino em y. Padrão: self.y │
#│ → opacity: o destino da opacidade (do conteúdo também). │
#│ Padrão: self.opacity │
#│ → width: o destino da largura. Padrão: self.width │
#│ → height: o destino da altura. Padrão: self.height │
#└───────────────────────────────────────────────────────────────────────────┘
def move_to(x, y = self.y, opacity = self.opacity, width = self.width, height = self.height)
@move_route.clear
@move_route.push(x, y, width, height, opacity)
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ update_movement │ Atualiza o movimento da janela. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def update_movement
return if @move_route.empty?
x = @move_route[0]; y = @move_route[1]
w = @move_route[2]; h = @move_route[3]
op = @move_route[4]
if x < self.x
self.x = Prism.decrease(self.x, move_speed, x)
else
self.x = Prism.increase(self.x, move_speed, x)
end
if y < self.y
self.y = Prism.decrease(self.y, move_speed, y)
else
self.y = Prism.increase(self.y, move_speed, y)
end
if w < self.width
self.width = Prism.decrease(self.width, move_speed, w)
else
self.width = Prism.increase(self.width, move_speed, w)
end
if h < self.height
self.height = Prism.decrease(self.height, move_speed, h)
else
self.height = Prism.increase(self.height, move_speed, h)
end
if op < self.opacity
self.opacity = Prism.decrease(self.opacity, opacity_speed, op)
self.contents_opacity = Prism.decrease(self.opacity, opacity_speed, op)
else
self.opacity = Prism.increase(self.opacity, opacity_speed, op)
self.contents_opacity = Prism.increase(self.opacity, opacity_speed, op)
end
con = self.x == x && self.y == y && self.width == w && self.height == h
con2 = self.opacity == op
@move_route.clear if con && con2
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update_write_message │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualiza o desenho do write_message, desenhando caractere por caractere. │
#└───────────────────────────────────────────────────────────────────────────┘
def update_write_message(m = @write_message)
return if m.empty?
return if self.openness < 255
if m[:wait_for_input]
if Input.trigger?(:C)
m[:wait_for_input] = nil
else
return
end
elsif m[:wait] && m[:wait] > 0
m[:wait] -= 1 if m[:wait] > 0
if m[:wait] == 0
m[:wait] = nil
else
return
end
end
txt = m[:text]; ind = m[:text_index]
cnt = m[:count]; mcnt = m[:max_count]
if cnt >= mcnt
m[:count] = 0
else
m[:count] += 1
end
if cnt == mcnt
if txt[ind] == "\n"
txt[ind] = ""
m[:x] = m[:rx]
m[:y] += line_height
elsif txt[ind, 2] == "\\."
m[:wait_for_input] = true
m[:text_index] += 2
return
elsif txt[ind, 2] == "\\|"
m[:wait] = 15
m[:text_index] += 2
return
elsif txt[ind, 5] =~ /\\i\[(\d+)\]/i
txt[ind, 5] = ""
process_draw_icon $1.to_i, m
end
text_rect = self.contents.text_size(txt[ind])
draw_text(m[:x], m[:y], txt[ind])
m[:x] += text_rect.width
m[:text_index] += 1 if ind < txt.length
if ind >= txt.length
@write_message.clear
end
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ draw_text │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha um texto normal na janela. │
#│ → x: a posição horizontal do texto. │
#│ → y: a posição vertical do texto. │
#│ → text: o texto em si. │
#│ → align: alinhamento do texto. 0: esquerda, 1: centro, 2: direita. │
#└───────────────────────────────────────────────────────────────────────────┘
def draw_text(x, y, text, align = 0)
width = self.contents.text_size(text).width + 4
if align != 0
width = contents_width
end
height = line_height + 4
self.contents.draw_text(x, y, width, height, text, align)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ write_text │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Escreve um texto na janela com função de quebra de linha (\n). │
#│ → x: a posição horizontal do texto. │
#│ → y: a posição vertical do texto. │
#│ → text: o texto em si. │
#│ → align: alinhamento do texto. 0: esquerda, 1: centro, 2: direita. │
#│ → wrap: faz o texto quebrar uma linha automaticamente caso passe da │
#│ largura da janela. Padrão: false │
#└───────────────────────────────────────────────────────────────────────────┘
def write_text(x, y, text, align = 0, wrap = false)
lines = []
if wrap
text = Prism.wrap_text(text, contents_width)
end
text.scan(/[^\n]*/) {|line| lines.push(line) unless line == ""}
for i in 0...lines.size
width = self.contents.text_size(lines[i]).width + 4
height = line_height + 4
pos_y = y + line_height * i
if align != 0
width = contents_width
end
self.contents.draw_text(x, pos_y, width, height, lines[i], align)
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ write_message │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha um texto com as letras aparecendo lentamente. │
#│ Obs: Uso em loops não recomendado. │
#│ É como se fosse uma versão portátil da Window_Message. │
#│ Eu não usaria ele como uma Window_Message de verdade, mas ele tem lá suas │
#│ utilidades. │
#│ Há três comandos que podem ser utilizados: │
#│ \\. irá esperar o botão de confirmação ser pressionado antes de mostrar │
#│ o resto da mensagem. Enquanto \\| irá esperar 15 frames. │
#│ \\i[id] irá desenhar o ícone de número id. │
#│ O texto não será desenhado até que a janela esteja totalmente aberta. │
#│ A mensagem irá pular uma linha automaticamente se o texto for maior que │
#│ a largura da janela. │
#│ → x: a posição em x do texto. │
#│ → y: a posição em y do texto. │
#│ → text: o texto em si. │
#└───────────────────────────────────────────────────────────────────────────┘
def write_message(x, y, text)
@write_message[:x] = x
@write_message[:rx] = x
@write_message[:y] = y
@write_message[:max_count] = 1
@write_message[:count] = 15
@write_message[:text] = (Prism.wrap_text text, contents_width - 48)
@write_message[:text_index] = 0
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ process_draw_icon │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Processa o desenho de ícone para o write_message. │
#│ → icon_index: o index do ícone no iconset. │
#│ → pos: uma hash que contenha uma posição :x. │
#└───────────────────────────────────────────────────────────────────────────┘
def process_draw_icon(icon_index, pos)
draw_icon(icon_index, pos[:x], pos[:y])
pos[:x] += 24
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ draw_icon │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha um ícone na janela. │
#│ → icon_index: o index do ícone no iconset. │
#│ → x: posição horizontal do ícone. │
#│ → y: posição vertical do ícone. │
#│ → enabled: se o ícone irá aparecer translúcido ou completamente │
#│ visível. Padrão: true │
#└───────────────────────────────────────────────────────────────────────────┘
def draw_icon(icon_index, x, y, enabled = true)
bitmap = Cache.system("Iconset")
rect = Rect.new(icon_index % 16 * 24, icon_index / 16 * 24, 24, 24)
self.contents.blt(x, y, bitmap, rect, enabled ? 255 : 160)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ draw_face │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha um gráfico de rosto. │
#│ → face_name: o nome do arquivo da face. │
#│ → face_index: o index da face (começando por 0). │
#│ → x: posição horizontal da face. │
#│ → y: posição vertical da face. │
#│ → enabled: se a face irá aparecer translúcida ou completamente │
#│ visível. Padrão: true │
#└───────────────────────────────────────────────────────────────────────────┘
def draw_face(face_name, face_index, x, y, enabled = true)
bitmap = Cache.face(face_name)
rect = Rect.new(face_index % 4 * 96, face_index / 4 * 96, 96, 96)
self.contents.blt(x, y, bitmap, rect, enabled ? 255 : 160)
bitmap.dispose
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ draw_character │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha um char na janela. │
#│ → character_name: o nome do arquivo do char. │
#│ → character_index: o index do char (começando por 0). │
#│ → x: posição horizontal do char. │
#│ → y: posição vertical do char. │
#│ → enabled: se o char irá aparecer translúcido ou completamente │
#│ visível. Padrão: true │
#└───────────────────────────────────────────────────────────────────────────┘
def draw_character(character_name, character_index, x, y, enabled = true)
return unless character_name
bitmap = Cache.character(character_name)
sign = character_name[/^[\!\$]./]
if sign && sign.include?("$")
cw = bitmap.width / 3
ch = bitmap.height / 4
else
cw = bitmap.width / 12
ch = bitmap.height / 8
end
n = character_index
src_rect = Rect.new((n % 4 * 3 + 1) * cw, (n / 4 * 4) * ch, cw, ch)
self.contents.blt(x, y, bitmap, src_rect, enabled ? 255 : 160)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ draw_gauge │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha um gauge na janela. │
#│ → x: posição horizontal. │
#│ → y: posição vertical. │
#│ → width: largura do gauge. │
#│ → height: altura do gauge. │
#│ → rate: a taxa de preenchimento do gauge (de 0.0 a 1.0). │
#│ → color1: a cor inicial do gauge. │
#│ → color2: a cor final do gauge. │
#└───────────────────────────────────────────────────────────────────────────┘
def draw_gauge(x, y, width, rate, color1, color2)
fill_w = (width * rate).to_i
gauge_y = y + line_height - 8
n = 19
gbc = self.windowskin.get_pixel(64 + (n % 8) * 8, 96 + (n / 8) * 8)
self.contents.fill_rect(x, gauge_y, width, 6, gbc)
self.contents.gradient_fill_rect(x, gauge_y, fill_w, 6, color1, color2)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ draw_item │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha o nome de um item juntamente do ícone dele. │
#│ → item: o item. Precisa ser um RPG::Item ($data_items, por exemplo). │
#│ → x: posição horizontal. │
#│ → y: posição vertical. │
#│ → enabled: se irá aparecer translúcido ou visível. Padrão: true │
#└───────────────────────────────────────────────────────────────────────────┘
def draw_item(item, x, y, enabled = true)
return unless item
draw_icon(item.icon_index, x, y, enabled)
draw_text(x + 24, y, item.name)
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ dispose │ Efetua o dispose da janela. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def dispose
self.contents.dispose unless disposed?
super
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Base_Window ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Window_Select ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Uma janela de seleção que desliza o cursor suavemente. Ela é necessária ║
#║ para a Prism::Window_Command. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Window_Select < Prism::Base_Window
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância públicas. │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :mouse_enabled
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal. │
#│ → y: posição vertical. │
#│ → width: largura. │
#│ → height: altura. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height)
super
@index = 0
@hovering_over_option = false
@mouse_enabled = true
@new_rect = Rect.new(0, 0, selection_width, selection_height)
@new_scroll = 0
@rapid_scroll = false
self.cursor_rect.set(@new_rect)
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ selection_width │ A largura dos itens na janela. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def selection_width
(width - window_padding * 2 + spacing) / col_max - spacing
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ selection_height │ A altura dos itens na janela. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def selection_height
return 24
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ contents_height │ A altura do bitmap da janela. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def contents_height
[super - super % selection_height, row_max * selection_height].max
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ cursor_speed │ A velocidade de movimento do cursor em pixels. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def cursor_speed
return 4 + col_max
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ scroll_speed │ A velocidade de scroll da janela em pixels. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def scroll_speed
return 4 + col_max
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ spacing │ O espaço entre os itens desenhados horizontalmente. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def spacing
return 12
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ vertical_spacing │ O espaço entre os itens desenhados verticalmente. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def vertical_spacing
return 0
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ col_max │ O número máximo de colunas da janela. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def col_max
return 1
end
#┌────────────┬──────────────────────────────────────────────────────────────┐
#│ ♦ item_max │ O número máximo de itens na janela. │
#└────────────┴──────────────────────────────────────────────────────────────┘
def item_max
return 0
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ select │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Muda a posição do cursor para o número especificado. │
#│ → index: o número (index) da seleção na janela. │
#└───────────────────────────────────────────────────────────────────────────┘
def select(index)
@index = index
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ instant_select │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Seleciona instantâneamente um index. │
#│ → index: o index a ser selecionado. │
#└───────────────────────────────────────────────────────────────────────────┘
def instant_select(index)
select(index)
@new_rect.set(item_rect(@index))
self.cursor_rect.set(@new_rect)
ensure_cursor_visible
self.oy = @new_scroll
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ hide_cursor │ Esconde o cursor. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def hide_cursor
self.cursor_rect.width = self.cursor_rect.height = 0
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ show_cursor │ Mostra o cursor. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def show_cursor
instant_select(@index)
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ cursor_index │ O número da opção atual. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def cursor_index
@index
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ horizontal? │ Indica se há mais de uma coluna. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def horizontal?
col_max >= 2
end
#┌───────┬───────────────────────────────────────────────────────────────────┐
#│ ♦ row │ A fileira atual (para mais de uma coluna). │
#└───────┴───────────────────────────────────────────────────────────────────┘
def row
@index / col_max
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ top_row │ Quantas fileiras não visíveis existem no topo. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def top_row
self.oy / selection_height
end
#┌────────────┬──────────────────────────────────────────────────────────────┐
#│ ♦ top_row= │ Altera as fileiras do topo. │
#└────────────┴──────────────────────────────────────────────────────────────┘
def top_row= row
row = 0 if row < 0
row = row_max - 1 if row > row_max - 1
@new_scroll = row * selection_height
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ row_max │ O número máximo de fileiras. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def row_max
[(item_max + col_max - 1) / col_max, 1].max
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ page_row_max │ O número máximo de fileiras visíveis na janela. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def page_row_max
(self.height - self.padding - self.padding_bottom) / selection_height
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ bottom_row │ O inverso do top_row. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def bottom_row
top_row + page_row_max - 1
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ bottom_row= │ Altera as fileiras de baixo. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def bottom_row= row
self.top_row = row - (page_row_max - 1)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ item_rect │
#├───────────────────────────────────────────────────────────────────────────┤
#│ O tamanho exato de um item na janela. Assim como a posição correta │
#│ dependendo do index especificado. │
#│ → i: o index da posição de um item. Use isso para desenhar itens na │
#│ janela com loops, caso queira. │
#└───────────────────────────────────────────────────────────────────────────┘
def item_rect(i)
x = i % col_max * (selection_width + spacing)
y = i / col_max * (selection_height + vertical_spacing)
rect = Rect.new(x, y, selection_width, selection_height)
return rect
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ hovering_option? │ Indica se o cursor está acima de uma opção. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def hovering_option?
return @hovering_over_option
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ mouse_enabled? │ Indica se o mouse está ativado para a janela. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def mouse_enabled?
return @mouse_enabled
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
update_mouse if @mouse_enabled && self.active
update_index if self.active
update_cursor_pos
ensure_cursor_visible
update_scrolling
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ update_mouse │ Atualiza a seleção com o mouse. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def update_mouse
@delay = @delay ? @delay + 1 : 0
return if @delay % 3 > 0
tx = Prism::Touch_Input.x
ty = Prism::Touch_Input.y
vx = self.viewport ? self.x - self.viewport.ox + self.viewport.rect.x : self.x
vy = self.viewport ? self.y - self.viewport.oy + self.viewport.rect.y : self.y
if tx.between?(vx, vx + self.width) && ty.between?(vy, vy + self.height)
tx -= vx + padding
ty -= vy + padding
ty += oy
(0...item_max).each { |i|
rect = item_rect(i)
if tx.between?(rect.x, rect.x + rect.width) && ty.between?(rect.y, rect.y + rect.height)
@hovering_over_option = true
last_index = @index
select(i)
Sound.play_cursor unless @index == last_index
break
else
@hovering_over_option = false
end
}
else
@hovering_over_option = false
end
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ update_scrolling │ Atualiza o scrolling da janela, como o nome indica. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def update_scrolling
spd = scroll_speed
if @rapid_scroll
spd = contents_height / 3
end
if @new_scroll > self.oy
self.oy = Prism.increase(self.oy, spd, @new_scroll)
elsif @new_scroll < self.oy
self.oy = Prism.decrease(self.oy, spd, @new_scroll)
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ ensure_cursor_visible │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Vai executar o processo de scrolling caso o cursor saia da visão. │
#└───────────────────────────────────────────────────────────────────────────┘
def ensure_cursor_visible
self.top_row = row if row < top_row
self.bottom_row = row if row > bottom_row
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ update_index │ Atualiza a posição do cursor caso pressionado um botão. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def update_index
return unless item_max > 0
last_index = @index
cursor_down(Input.trigger?(:DOWN)) if Input.repeat?(:DOWN)
cursor_up(Input.trigger?(:UP)) if Input.repeat?(:UP)
cursor_right(Input.trigger?(:RIGHT)) if Input.repeat?(:RIGHT)
cursor_left(Input.trigger?(:LEFT)) if Input.repeat?(:LEFT)
Sound.play_cursor if @index != last_index
end
#┌─────────────────────┬─────────────────────────────────────────────────────┐
#│ ♦ update_cursor_pos │ Vai ajustar a posição do cursor. │
#└─────────────────────┴─────────────────────────────────────────────────────┘
def update_cursor_pos
@new_rect.set(item_rect(@index))
update_x_pos
update_y_pos
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ update_x_pos │ Ajusta a posição do cursor em x. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def update_x_pos
spd = cursor_speed
if @rapid_scroll
spd = contents_height / 3
end
if @new_rect.x < self.cursor_rect.x
self.cursor_rect.x = Prism.decrease(self.cursor_rect.x, spd, @new_rect.x)
elsif @new_rect.x > self.cursor_rect.x
self.cursor_rect.x = Prism.increase(self.cursor_rect.x, spd, @new_rect.x)
end
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ update_y_pos │ Ajusta a posição do cursor em y. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def update_y_pos
spd = cursor_speed
if @rapid_scroll
spd = contents_height / 2
end
if @new_rect.y < self.cursor_rect.y
self.cursor_rect.y = Prism.decrease(self.cursor_rect.y, spd, @new_rect.y)
elsif @new_rect.y > self.cursor_rect.y
self.cursor_rect.y = Prism.increase(self.cursor_rect.y, spd, @new_rect.y)
end
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ cursor_down │ Move o index da posição do cursor para baixo. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def cursor_down(wrap = false)
if @index < item_max - col_max || (wrap && col_max == 1)
if (@index + col_max) % item_max == 0
@rapid_scroll = true
else
@rapid_scroll = false
end
select((@index + col_max) % item_max)
end
end
#┌─────────────┬─────────────────────────────────────────────────────────────┐
#│ ♦ cursor_up │ Move o index da posição do cursor para cima. │
#└─────────────┴─────────────────────────────────────────────────────────────┘
def cursor_up(wrap = false)
if @index >= col_max || (wrap && col_max == 1)
if (@index - col_max + item_max) % item_max == item_max - 1
@rapid_scroll = true
else
@rapid_scroll = false
end
select((@index - col_max + item_max) % item_max)
end
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ cursor_right │ Move o index da posição do cursor para a direita. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def cursor_right(wrap = false)
if horizontal? && (@index < item_max - 1 || (wrap && page_row_max == 1))
select((@index + 1) % item_max)
end
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ cursor_left │ Move o index da posição do cursor para a esquerda. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def cursor_left(wrap = false)
if horizontal? && (@index > 0 || (wrap && page_row_max == 1))
select((@index - 1 + item_max) % item_max)
end
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ refresh │ Recria o bitmap da janela. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def refresh
create_contents
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Window_Select ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Window_Command ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Uma janela de comandos que aumenta bastante a produtividade na hora de ║
#║ desenhar os comandos. Ela possui alguns métodos inteligentes para desenhar ║
#║ os comandos. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Window_Command < Prism::Window_Select
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas │
#└───────────────────────────────────────────────────────────────────────────┘
attr_reader :list
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal. │
#│ → y: posição vertical. │
#│ → width: largura. │
#│ → height: altura. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height)
@list = {}
make_command_list
super
set_font_settings
draw_commands
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ make_command_list │
#├───────────────────────────────────────────────────────────────────────────┤
#│ É nesta área que as opções são adicionadas. │
#└───────────────────────────────────────────────────────────────────────────┘
def make_command_list
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ redraw_command_list │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Redesenha todos os comandos. Se external_commands for especificado, │
#│ ele irá criar os comandos do external_commands ao invés. │
#│ external_commands precisa ser uma array contendo os comandos em uma │
#│ hash (bloco), onde os parâmetros do add_command não podem ser omitidos. │
#└───────────────────────────────────────────────────────────────────────────┘
def redraw_command_list(external_commands = nil)
e = external_commands
if e
@list = {}
for i in 0...e.size
add_command(e[i][:type], e[i][:symbol], e[i][:enabled], e[i][:handler])
end
refresh
set_font_settings
draw_commands
else
make_command_list
refresh
set_font_settings
draw_commands
end
select(0)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ add_command │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → typ: ver logo abaixo. │
#│ → sym: o símbolo único do comando. │
#│ → enab: se a opção pode ser usada ou não. Padrão: true │
#│ → han: o método que será chamado ao confirmar a opção (interno). │
#│ Padrão: nil │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Em typ (type), você irá colocar a opção em si. │
#│ Se a opção for qualquer coisa exceto as abaixo, ele irá desenhar essa │
#│ opção. │
#│ Se a opção for um RPG::BaseItem ($data_items, $data_enemies, etc...), │
#│ ver logo abaixo. │
#│ Se a opção for um bitmap, ele irá, destrutivamente, desenhar esse │
#│ bitmap. │
#│ Caso você use um bitmap como Cache.picture('Nome'), use um clone. │
#│ Ex: Cache.picture('Nome').clone. Pois ele será destruído logo depois. │
#│ Agora você não precisa usar um clone se estiver criando um bitmap novo. │
#│ Ex: Bitmap.new('Graphics/Pictures/Nome') │
#├───────────────────────────────────────────────────────────────────────────┤
#│ No caso das opções que são um RPG::BaseItem, os seguintes itens podem ser │
#│ usados: $data_actors, $data_classes, $data_skills, $data_items, │
#│ $data_weapons, $data_armors, $data_enemies e $data_states. │
#│ Os seguintes métodos podem ser usados em sua janela: │
#│ → icon_only?: true para desenhar apenas ícones. │
#│ → face_only?: true para desenhar apenas faces. │
#│ → name_only?: true para desenhar apenas nomes (nas opções com ícones │
#│ ou faces). │
#│ → face_or_character?: caso esteja usando $data_actors: │
#│ :face irá desenhar a face ao invés do char. │
#│ :character irá desenhar o char ao invés da face. │
#└───────────────────────────────────────────────────────────────────────────┘
def add_command(typ, sym, enab = true, han = nil)
@list[sym] = {type: typ, symbol: sym, enabled: enab, handler: han}
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_font_settings │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Você pode usar esse método para realizar configurações de fonte antes │
#│ dos itens serem desenhados. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_font_settings
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ draw_commands │ Desenha todos os comandos. │
#└─────────────────┴─────────────────────────────────────────────────────────┘
def draw_commands
cmd = []
@list.each_value do |com|
cmd.push(com)
end
@ind = cmd
for i in 0...cmd.size
if cmd[i][:type].is_a?(RPG::BaseItem); process_base_item(cmd[i], i)
elsif cmd[i][:type].is_a?(Bitmap); process_bitmap(cmd[i], i)
else; process_string(cmd[i], i)
end
end
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ clear_commands │ Limpa a lista de comandos. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def clear_commands
@list.clear
@ind.clear
self.contents.clear
select(0)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_handler │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Configura o método que será chamado ao confirmar a opção (externamente). │
#│ Obs: Se já existir um método interno, o interno será chamado primeiro. │
#│ → symbol: o símbolo único da opção. │
#│ → handler: o método externo que será chamado. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_handler(symbol, handler)
@list[symbol][:external_handler] = handler
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ process_string │ Processa o desenho de texto. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def process_string(cmd, i)
old_alpha = self.contents.font.color.alpha
enabled = cmd[:enabled]
!enabled ? self.contents.font.color.alpha = 160 : nil
rect = item_rect(i)
draw_text(rect.x + 4, rect.y, cmd[:type].to_s)
self.contents.font.color.alpha = old_alpha
end
#┌─────────────────────┬─────────────────────────────────────────────────────┐
#│ ♦ process_base_item │ Identifica o tipo de item e o desenha de acordo. │
#└─────────────────────┴─────────────────────────────────────────────────────┘
def process_base_item(cmd, i)
if cmd[:type].is_a?(RPG::Actor)
process_actor(cmd, i)
elsif cmd[:type].is_a?(RPG::Class) || cmd[:type].is_a?(RPG::Enemy)
process_item_text(cmd, i)
else
process_normal_item(cmd, i)
end
end
#┌───────────────────────┬───────────────────────────────────────────────────┐
#│ ♦ process_normal_item │ Desenha um item normal. │
#└───────────────────────┴───────────────────────────────────────────────────┘
def process_normal_item(cmd, i)
old_alpha = self.contents.font.color.alpha
enabled = cmd[:enabled]
!enabled ? self.contents.font.color.alpha = 160 : nil
plus_x = name_only? ? 4 : 24
rect = item_rect(i)
draw_icon(cmd[:type].icon_index, rect.x, rect.y, enabled) unless name_only?
draw_text(rect.x + plus_x, rect.y, cmd[:type].name) unless icon_only?
self.contents.font.color.alpha = old_alpha
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ process_actor │ Desenha um RPG::Actor. │
#└─────────────────┴─────────────────────────────────────────────────────────┘
def process_actor(cmd, i)
old_alpha = self.contents.font.color.alpha
enabled = cmd[:enabled]
!enabled ? self.contents.font.color.alpha = 160 : nil
rect = item_rect(i)
min = (self.contents.font.size * 0.5).to_i + 1
plus_x = name_only? ? 4 : face_or_character? == :face ? 100 : 32
plus_y = name_only? ? 0 : face_or_character? == :face ? (48 - min) : (16 - min)
fn = cmd[:type].face_name; fi = cmd[:type].face_index
cn = cmd[:type].character_name; ci = cmd[:type].character_index
if face_or_character? == :face
draw_face(fn, fi, rect.x, rect.y, enabled) unless name_only?
else
draw_character(cn, ci, rect.x + 4, rect.y, enabled) unless name_only?
end
draw_text(rect.x + plus_x, rect.y + plus_y, cmd[:type].name) unless face_only?
self.contents.font.color.alpha = old_alpha
end
#┌─────────────────────┬─────────────────────────────────────────────────────┐
#│ ♦ process_item_text │ Desenha o nome de um item. │
#└─────────────────────┴─────────────────────────────────────────────────────┘
def process_item_text(cmd, i)
old_alpha = self.contents.font.color.alpha
enabled = cmd[:enabled]
!enabled ? self.contents.font.color.alpha = 160 : nil
rect = item_rect(i)
draw_text(rect.x + 4, rect.y, cmd[:type].name)
self.contents.font.color.alpha = old_alpha
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ process_bitmap │ Desenha um bitmap. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def process_bitmap(cmd, i)
enabled = cmd[:enabled]
opacity = enabled ? 255 : 160
rect = item_rect(i)
bit_rect = Rect.new(0, 0, cmd[:type].width, cmd[:type].height)
self.contents.blt(rect.x, rect.y, cmd[:type], bit_rect, opacity)
cmd[:type].dispose
end
#┌────────────┬──────────────────────────────────────────────────────────────┐
#│ ♦ item_max │ Número máximo de itens na janela. │
#└────────────┴──────────────────────────────────────────────────────────────┘
def item_max
@list.size
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ icon_only? │ Indica se apenas os ícones dos itens devem ser desenhados. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def icon_only?
return false
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ face_only? │ Indica se apenas as faces dos actors devem ser desenhadas. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def face_only?
return false
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ name_only? │ Indica se apenas os nomes devem ser desenhados. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def name_only?
return false
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ selected_item │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o item atualmente selecionado em formato de array com 2 elementos. │
#│ O primeiro elemento é o símbolo configurado em :sym. │
#│ O segundo elemento são os componentes em uma hash. │
#└───────────────────────────────────────────────────────────────────────────┘
def selected_item
selected = @list.to_a[cursor_index]
return selected
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ face_or_character? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se a face do actor deve ser desenhada ou o char dele. │
#│ → :face: desenha a face. │
#│ → :character: desenha o char. │
#└───────────────────────────────────────────────────────────────────────────┘
def face_or_character?
return :character
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
if mouse_enabled?
if (Input.trigger?(:C) || Prism::Touch_Input.is_triggered? && hovering_option?)
on_option_ok if self.active && !no_confirm
end
else
on_option_ok if Input.trigger?(:C) && self.active && !no_confirm
end
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ on_option_ok │ Confirma a opção, se o no_confirm for false. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def on_option_ok
Input.update
unless @ind[cursor_index]
Sound.play_buzzer
return
end
opt = @ind[cursor_index][:symbol]
if @list[opt][:enabled]
Sound.play_ok
@list[opt][:handler].call if @list && @list[opt][:handler]
@list[opt][:external_handler].call if @list[opt][:external_handler] rescue nil
deactivate if @list[opt][:handler] || @list[opt][:external_handler] rescue nil
else
Sound.play_buzzer
end
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ no_confirm │ Desativa confirmação de opções na janela. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def no_confirm
return false
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Window_Command ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Horz_Command ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Mesma coisa da Prism::Window_Command, mas com configurações horizontais. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Horz_Command < Prism::Window_Command
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal. │
#│ → y: posição vertical. │
#│ → width: largura. │
#│ → height: altura. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height)
super
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ col_max │ O número máximo de colunas da janela. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def col_max
return 4
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ spacing │ O espaço entre os itens desenhados horizontalmente. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def spacing
return 8
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ hide_cursor │ Esconde o cursor. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def hide_cursor
self.cursor_rect.width = self.cursor_rect.height = 0
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ show_cursor │ Mostra o cursor. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def show_cursor
instant_select(@index)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ instant_select │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Seleciona instantâneamente um index. │
#│ → index: o index a ser selecionado. │
#└───────────────────────────────────────────────────────────────────────────┘
def instant_select(index)
select(index)
@new_rect.set(item_rect(@index))
self.cursor_rect.set(@new_rect)
ensure_cursor_visible
self.ox = @new_scroll
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ contents_width │ A largura do conteúdo visível da janela. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def contents_width
(selection_width + spacing) * item_max - spacing
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ contents_height │ A altura do conteúdo visível da janela. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def contents_height
selection_height
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ top_col │ Dígitos dianteiros. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def top_col
ox / (selection_width + spacing)
end
#┌────────────┬──────────────────────────────────────────────────────────────┐
#│ ♦ top_col= │ Ajusta os dígitos dianteiros. │
#└────────────┴──────────────────────────────────────────────────────────────┘
def top_col=(col)
col = 0 if col < 0
@new_scroll = col * (selection_width + spacing)
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ bottom_col │ O inverso do top_col. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def bottom_col
top_col + col_max - 1
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ bottom_col= │ Ajusta os dígitos traseiros. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def bottom_col=(col)
self.top_col = col - (col_max - 1)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ ensure_cursor_visible │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Vai executar o processo de scrolling caso o cursor saia da visão. │
#└───────────────────────────────────────────────────────────────────────────┘
def ensure_cursor_visible
self.top_col = @index if @index < top_col
self.bottom_col = @index if @index > bottom_col
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ update_scrolling │ Atualiza o scrolling da janela, como o nome indica. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def update_scrolling
spd = scroll_speed
if @rapid_scroll
spd = contents_width / 3
end
if @new_scroll > self.ox
self.ox = Prism.increase(self.ox, spd, @new_scroll)
elsif @new_scroll < self.ox
self.ox = Prism.decrease(self.ox, spd, @new_scroll)
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ item_rect │
#├───────────────────────────────────────────────────────────────────────────┤
#│ O tamanho exato de um item na janela. Assim como a posição correta │
#│ dependendo do index especificado. │
#│ → i: o index da posição de um item. Use isso para desenhar itens na │
#│ janela com loops, caso queira. │
#└───────────────────────────────────────────────────────────────────────────┘
def item_rect(index)
rect = super
rect.x = index * (selection_width + spacing)
rect.y = 0
rect
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ cursor_right │ Move o index da posição do cursor para a direita. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def cursor_right(wrap = false)
if @index < item_max - 1 || (wrap && page_row_max == 1)
select((@index + 1) % item_max)
end
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ cursor_left │ Move o index da posição do cursor para a esquerda. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def cursor_left(wrap = false)
if @index > 0 || (wrap && page_row_max == 1)
select((@index - 1 + item_max) % item_max)
end
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ cursor_down │ Move o index da posição do cursor para baixo. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def cursor_down(wrap = false)
end
#┌─────────────┬─────────────────────────────────────────────────────────────┐
#│ ♦ cursor_up │ Move o index da posição do cursor para cima. │
#└─────────────┴─────────────────────────────────────────────────────────────┘
def cursor_up(wrap = false)
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Horz_Command ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Input_Window ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Uma janela onde o jogador pode digitar qualquer coisa que ele quiser. ║
#║ Você pode obter o texto inserido pelo jogador com user_text. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Input_Window < Prism::Base_Window
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas │
#└───────────────────────────────────────────────────────────────────────────┘
attr_reader :user_text
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal. │
#│ → y: posição vertical. │
#│ → width: largura. │
#│ → height: altura. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height)
super
@user_text = ""
reset_input_settings
create_input_sprite
end
#┌────────────────────────┬──────────────────────────────────────────────────┐
#│ ♦ reset_input_settings │ Reseta o texto inserido. │
#└────────────────────────┴──────────────────────────────────────────────────┘
def reset_input_settings
@text = ""
@accents = []
end
#┌───────────────────────┬───────────────────────────────────────────────────┐
#│ ♦ create_input_sprite │ Cria o sprite do cursor. │
#└───────────────────────┴───────────────────────────────────────────────────┘
def create_input_sprite
@input_sprite = Sprite.new
@input_sprite.bitmap = Bitmap.new(24, 24)
@input_sprite.bitmap.draw_text(0, 0, 24, 24, "|")
@input_sprite.x = self.x + self.padding
@input_sprite.y = self.y + self.padding + 1
@input_sprite.z = self.z + 1
@input_sprite.opacity = 0
@count = 0
end
#┌──────┬────────────────────────────────────────────────────────────────────┐
#│ ♦ z= │ Ajusta a prioridade z do sprite do cursor. │
#└──────┴────────────────────────────────────────────────────────────────────┘
def z=(v)
@input_sprite.z = v + 1
super
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ character_limit │ O limite de caracteres que podem ser inseridos. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def character_limit
return 25
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
return if !self.active
update_input
update_input_sprite
process_confirmation
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ update_input │ Atualiza o processamento do texto. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def update_input
input = Prism::Input
key = input::KEYS
cap = input.shift? ? :caps : :lower
char = input::CHARACTERS
dl = input.is_repeated?(key[:BACKSPACE]) || input.is_repeated?(key[:DELETE])
ac = char[:accents]
li = char[:accent_list]
ctd = char[:accented]
char[cap].each_pair do |n, ch|
if dl; process_delete; return; end
i = Prism::Input::KEYS[n]
if input.is_repeated?(i)
if ac.include?(ch) && @accents.empty?
@accents.push(ch)
next
elsif !@accents.empty? && li.include?(ch)
char = ctd[ch][ac.index(@accents[0])]
process_character(char)
@accents.clear
else
@accents.clear
process_character(ch)
end
end
end
end
#┌───────────────────────┬───────────────────────────────────────────────────┐
#│ ♦ update_input_sprite │ Atualiza o sprite do cursor. │
#└───────────────────────┴───────────────────────────────────────────────────┘
def update_input_sprite
@count += 1 unless @count >= 60
@count = 0 if @count >= 60
if @count < 30
@input_sprite.opacity += 15
else
@input_sprite.opacity -= 15
end
end
#┌─────────────────────┬─────────────────────────────────────────────────────┐
#│ ♦ process_character │ Desenha o caractere que acabou de ser inserido. │
#└─────────────────────┴─────────────────────────────────────────────────────┘
def process_character(ch)
if @text.size - 1 >= character_limit; Sound.play_buzzer; return; end
@text << ch
refresh_text
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ process_delete │ Apaga o último caractere do texto. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def process_delete
@text.chop!
refresh_text
end
#┌────────────────────────┬──────────────────────────────────────────────────┐
#│ ♦ process_confirmation │ Processa a confirmação e desativa a janela. │
#└────────────────────────┴──────────────────────────────────────────────────┘
def process_confirmation
rt = Prism::Input.is_triggered?(Prism::Input::KEYS[:RETURN])
en = Prism::Input.is_triggered?(Prism::Input::KEYS[:ENTER])
if rt || en
Sound.play_ok
@user_text = @text
@input_sprite.opacity = 0
reset_input_settings
refresh_text
deactivate
end
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ refresh_text │ Redesenha o texto. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def refresh_text
self.contents.clear
draw_text(0, 0, @text)
ox = self.x + self.padding
@input_sprite.x = ox + self.contents.text_size(@text).width
end
#┌────────────┬──────────────────────────────────────────────────────────────┐
#│ ♦ activate │ Reseta as configurações ao ativar a janela. │
#└────────────┴──────────────────────────────────────────────────────────────┘
def activate
super
reset_input_settings
refresh_text
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ dispose │ Se livra do cursor ao dar dispose na janela. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def dispose
@input_sprite.bitmap.dispose
@input_sprite.dispose
super
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Input_Window ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Base_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite que serve de base para todos os outros sprites do Prism. ║
#║ Ele inclui propriedades de movimento da Prism::Base_Window. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Base_Sprite < Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: automaticamente configura o bitmap se for especificado. │
#│ → viewport: o viewport associado ao sprite, se for especificado. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, viewport = nil)
super viewport
@move_speed = 4
@opacity_speed = 4
set(0, 0, 0, 255, bitmap)
@move_route = []
make_animation_list
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ bitmap= │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta as configurações de fonte ao definir um novo bitmap. │
#│ → bitmap: o novo bitmap. │
#└───────────────────────────────────────────────────────────────────────────┘
def bitmap=(bitmap)
super
set_font_settings
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_font_settings │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Este método serve para configurar a fonte toda vez que um novo bitmap for │
#│ especificado para o sprite. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_font_settings
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ make_animation_list │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Cria uma lista de animações de movimento para serem usadas a qualquer │
#│ momento. │
#└───────────────────────────────────────────────────────────────────────────┘
def make_animation_list
@anim_list = {}
# Usado por classes herdeiras.
# Para criar uma animação, use o modelo:
# @anim_list[:nome] = [x, y, op] # Apenas o x é exigido.
# op = opacidade.
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ start_animation │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Executa uma animação da lista de animações de movimento. │
#│ → anim: o símbolo da animação na lista de animações. │
#└───────────────────────────────────────────────────────────────────────────┘
def start_animation(anim)
list = @anim_list[anim]
case list.size
when 1; move_to(list[0])
when 2; move_to(list[0], list[1])
when 3; move_to(list[0], list[1], list[2])
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ move_to │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Move o sprite até a posição especificada (ele vai se mover até lá). │
#│ → x: o destino em x. │
#│ → y: o destino em y. Padrão: self.y │
#│ → opacity: o destino da opacidade. Padrão: 255 │
#└───────────────────────────────────────────────────────────────────────────┘
def move_to(x, y = self.y, opacity = self.opacity)
@move_route.clear
@move_route.push(x, y, opacity)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta de uma vez a posição, opacidade e o bitmap do sprite. │
#│ → x: a posição horizontal. │
#│ → y: a posição vertical. │
#│ → z: a prioridade do sprite. Padrão: 0 │
#│ → opacity: a opacidade do sprite. Padrão: 255 │
#│ → bitmap: o bitmap do sprite. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def set(x, y, z = 0, opacity = 255, bitmap = nil)
self.x = x + self.oy
self.y = y + self.oy
self.z = z
self.opacity = opacity
if bitmap
self.bitmap.dispose if self.bitmap
self.bitmap = bitmap
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_pos │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Coloca o sprite na posição especificada. │
#│ É necessário um bitmap existente. │
#│ → pos: um número das posições abaixo: │
#│ 1: Superior Equerda │
#│ 2: Superior │
#│ 3: Superior Direita │
#│ 4: Esquerda │
#│ 5: Centro │
#│ 6: Direita │
#│ 7: Inferior Esquerda │
#│ 8: Inferior │
#│ 9: Inferior Direita │
#└───────────────────────────────────────────────────────────────────────────┘
def set_pos(pos)
case pos
when 1; self.x = 0 + self.ox; self.y = 0 + self.oy
when 2
self.x = Prism.get_center_screen(:x, self.bitmap) + self.ox
self.y = 0 + self.oy
when 3
self.x = Graphics.width - self.bitmap.width + self.ox
self.y = 0 + self.oy
when 4
self.x = 0 + self.ox
self.y = Prism.get_center_screen(:y, self.bitmap) + self.oy
when 5
self.x = Prism.get_center_screen(:x, self.bitmap) + self.ox
self.y = Prism.get_center_screen(:y, self.bitmap) + self.oy
when 6
self.x = Graphics.width - self.bitmap.width + self.ox
self.y = Prism.get_center_screen(:y, self.bitmap) + self.oy
when 7
self.x = 0 + self.ox
self.y = Graphics.height - self.bitmap.height + self.oy
when 8
self.x = Prism.get_center_screen(:x, self.bitmap) + self.ox
self.y = Graphics.height - self.bitmap.height + self.oy
when 9
self.x = Graphics.width - self.bitmap.width + self.ox
self.y = Graphics.height - self.bitmap.height + self.oy
end
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ move_speed │ A velocidade de movimento do sprite (em pixels). │
#└──────────────┴────────────────────────────────────────────────────────────┘
def move_speed
return @move_speed
end
#┌─────────────────┬─────────────────────────────────────────────────────────┐
#│ ♦ opacity_speed │ A velocidade de alteração da opacidade. │
#└─────────────────┴─────────────────────────────────────────────────────────┘
def opacity_speed
return @opacity_speed
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ move_speed= │ Altera a velocidade de movimento para v. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def move_speed=(v)
@move_speed =(v)
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ opacity_speed= │ Altera a velocidade de alteração da opacidade para v. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def opacity_speed=(v)
@opacity_speed =(v)
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ moving? │ Checa se o sprite está se movendo. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def moving?
!@move_route.empty?
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
update_movement
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ update_movement │ Atualiza o movimento do sprite. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def update_movement
return if @move_route.empty?
x = @move_route[0]; y = @move_route[1]
op = @move_route[2]
if x < self.x
self.x = Prism.decrease(self.x, move_speed, x)
else
self.x = Prism.increase(self.x, move_speed, x)
end
if y < self.y
self.y = Prism.decrease(self.y, move_speed, y)
else
self.y = Prism.increase(self.y, move_speed, y)
end
if op < self.opacity
self.opacity = Prism.decrease(self.opacity, opacity_speed, op)
else
self.opacity = Prism.increase(self.opacity, opacity_speed, op)
end
con = self.x == x && self.y == y
con2 = self.opacity == op
@move_route.clear if con && con2
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ write_text │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Escreve um texto no sprite com função de quebra de linha (\n). │
#│ → x: a posição horizontal do texto. │
#│ → y: a posição vertical do texto. │
#│ → text: o texto em si. │
#│ → align: alinhamento do texto. 0: esquerda, 1: centro, 2: direita. │
#│ → wrap: faz o texto quebrar uma linha automaticamente caso passe da │
#│ largura do bitmap do sprite. Padrão: false │
#└───────────────────────────────────────────────────────────────────────────┘
def write_text(x, y, text, align = 0, wrap = false)
lines = []
if wrap
text = Prism.wrap_text(text, self.bitmap.width, self.bitmap)
end
text.scan(/[^\n]*/) {|line| lines.push(line) unless line == ""}
for i in 0...lines.size
width = self.bitmap.text_size(lines[i]).width + 4
height = self.bitmap.font.size + 4
pos_y = y + self.bitmap.font.size * i
if align != 0
width = self.bitmap.width
end
self.bitmap.draw_text(x, pos_y, width, height, lines[i], align)
end
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Base_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Opening_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite que abre e fecha, tanto horizontal quanto vertical... ou os dois. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Opening_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: automaticamente configura o bitmap se for especificado. │
#│ → open_mode: o modo de abertura. :horizontal, :vertical ou :both │
#│ → viewport: o viewport associado ao sprite, se for especificado. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, open_mode = :both, viewport = nil)
super(bitmap, viewport)
if open_mode == :horizontal
self.zoom_x = 0
elsif open_mode == :vertical
self.zoom_y = 0
else
self.zoom_x = 0; self.zoom_y = 0
end
@open_mode = open_mode
@open = false
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_properties │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Deve ser chamado exatamente após o sprite ser criado para configurar o │
#│ ponto de origem. │
#│ → bitmap: configura o bitmap, se já não foi criado antes. │
#│ → open_mode: o modo de abertura. :horizontal, :vertical ou :both │
#│ → viewport: o viewport associado ao sprite, se for especificado. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_properties(bitmap = nil)
unless self.bitmap
self.bitmap = bitmap
end
self.ox = self.bitmap.width * 0.5
self.oy = self.bitmap.height * 0.5
end
#┌────────┬──────────────────────────────────────────────────────────────────┐
#│ ♦ open │ Abre o sprite. │
#└────────┴──────────────────────────────────────────────────────────────────┘
def open
@open = true
end
#┌─────────┬─────────────────────────────────────────────────────────────────┐
#│ ♦ close │ Fecha o sprite. │
#└─────────┴─────────────────────────────────────────────────────────────────┘
def close
@open = false
end
#┌─────────┬─────────────────────────────────────────────────────────────────┐
#│ ♦ open? │ Indica se o sprite está aberto. │
#└─────────┴─────────────────────────────────────────────────────────────────┘
def open?
self.zoom_x >= 0.9 || self.zoom_y >= 0.9
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ close? │ Indica se o sprite está fechado. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def close?
self.zoom_x <= 0.1 || self.zoom_y <= 0.1
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
update_openness
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ update_openness │ Atualiza a abertura do sprite. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def update_openness
m = @open_mode; o = @open
if m == :horizontal
self.zoom_x += 0.1 if self.zoom_x < 0.9 && o
self.zoom_x -= 0.1 if self.zoom_x > 0.1 && !o
elsif m == :vertical
self.zoom_y += 0.1 if self.zoom_y < 0.9 && o
self.zoom_y -= 0.1 if self.zoom_y > 0.1 && !o
else
self.zoom_x += 0.1 if self.zoom_x < 0.9 && o
self.zoom_x -= 0.1 if self.zoom_x > 0.1 && !o
self.zoom_y += 0.1 if self.zoom_y < 0.9 && o
self.zoom_y -= 0.1 if self.zoom_y > 0.1 && !o
end
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Opening_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Text_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite que serve justamente para mostrar um texto. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Text_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas │
#└───────────────────────────────────────────────────────────────────────────┘
attr_reader :text
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → viewport: o viewport associado ao sprite, se for especificado. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(viewport = nil)
super
@text = ""
@enable_line_spacing = false
@line_spacing = Font.default_size
@font = {}
set_font_settings
@rect_bitmap = Bitmap.new(1, 1)
end
#┌─────────────────────┬─────────────────────────────────────────────────────┐
#│ ♦ set_font_settings │ Configurações de fonte para restauração. │
#└─────────────────────┴─────────────────────────────────────────────────────┘
def set_font_settings
@font[:name] = Font.default_name
@font[:size] = Font.default_size
@font[:bold] = Font.default_bold
@font[:italic] = Font.default_italic
@font[:outline] = Font.default_outline
@font[:shadow] = Font.default_shadow
@font[:color] = Font.default_color
@font[:out_color] = Font.default_out_color
end
#┌────────┬──────────────────────────────────────────────────────────────────┐
#│ ♦ font │ Permite obter informações sobre a fonte. │
#└────────┴──────────────────────────────────────────────────────────────────┘
def font
@font
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ enable_line_spacing? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se é para utilizar o espaço customizado de altura entre as linhas. │
#└───────────────────────────────────────────────────────────────────────────┘
def enable_line_spacing?
@enable_line_spacing
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ enable_line_spacing= │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Altera a propriedade de @enable_line_spacing para v. │
#│ v precisa ser true ou false. │
#└───────────────────────────────────────────────────────────────────────────┘
def enable_line_spacing=(v)
@enable_line_spacing = v
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ line_spacing │ Espaço customizado entre as linhas. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def line_spacing
@line_spacing
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ line_spacing= │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Altera o espaço customizado entre as linhas para v. │
#│ v precisa ser um número inteiro. │
#└───────────────────────────────────────────────────────────────────────────┘
def line_spacing=(v)
@line_spacing = v
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_font_property │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Permite alterar as propriedades da fonte. │
#│ → symbol: um símbolo contendo a informação a ser alterada. │
#│ Ex: :name, :size, :out_color... │
#│ → value: o valor que será atribuído. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_font_property(symbol, value)
@font[symbol] = value
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ restore_font │ Restaura as configurações de fonte. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def restore_font
self.bitmap.font.name = @font[:name]
self.bitmap.font.size = @font[:size]
self.bitmap.font.bold = @font[:bold]
self.bitmap.font.italic = @font[:italic]
self.bitmap.font.outline = @font[:outline]
self.bitmap.font.shadow = @font[:shadow]
self.bitmap.font.color = @font[:color]
self.bitmap.font.out_color = @font[:out_color]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_text │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha um texto normal. │
#│ → set_text: o texto a ser desenhado. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_text(text)
self.bitmap.dispose if self.bitmap
w = @rect_bitmap.text_size(text).width
h = @rect_bitmap.text_size(text).height
if w > 0 || h > 0
self.bitmap = Bitmap.new(w, h)
else
self.bitmap = Bitmap.new(1, 1)
end
restore_font
self.bitmap.draw_text(0, 0, w, h, text)
@text = text
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ write_text │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha um texto com quebra de linha (\n). │
#│ → set_text: o texto a ser desenhado. │
#└───────────────────────────────────────────────────────────────────────────┘
def write_text(text)
lines = []
r = @rect_bitmap
w = 0; h = 0
text.scan(/[^\n]*/) { |line| lines.push(line) unless line == "" }
h = r.text_size(lines[0]).height
for i in 0...lines.size
nw = r.text_size(lines[i]).width
w = nw if w < nw
end
self.bitmap.dispose if self.bitmap
self.bitmap = Bitmap.new(w, h * lines.size)
restore_font
for t in 0...lines.size
c = t == 0 ? 0 : enable_line_spacing? ? line_spacing * t : h * t
self.bitmap.draw_text(0, 0 + c, w + 4, h + 4, lines[t])
@text << lines[t]
end
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ dispose │ Se livra do bitmap extra ao realizar o dispose. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def dispose
@rect_bitmap.dispose
super
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Text_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Gauge_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite que funciona como uma barra. Ou gauge, para ser mais preciso. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Gauge_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: o bitmap, caso for usar um gauge baseado em imagem. │
#│ → mode: :normal ou :image. Use o que achar melhor. Padrão: :normal │
#│ → viewport: o viewport associado ao sprite. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, mode = :normal, viewport = nil)
super(viewport)
self.bitmap = bitmap if bitmap
@mode = mode
@rate = 0.0
set_gauge mode
end
#┌─────────────┬─────────────────────────────────────────────────────────────┐
#│ ♦ set_gauge │ Ajusta o gauge dependendo do modo. │
#└─────────────┴─────────────────────────────────────────────────────────────┘
def set_gauge m
if m == :normal
set_normal_gauge
else
set_bitmap_gauge
end
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ set_normal_gauge │ Ajusta o gauge normal, sem imagem. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def set_normal_gauge(w = gauge_width, h = gauge_height)
c = gauge_back_color
c2 = gauge_fill_color
fw = (gauge_width * @rate).to_i
self.bitmap.dispose if self.bitmap
self.bitmap = Bitmap.new(w, h)
self.bitmap.fill_rect(0, 0, w, h, c)
self.bitmap.gradient_fill_rect(1, 1, fw - 2, h - 2, c2[0], c2[1])
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ set_bitmap_gauge │ Ajusta o gauge com imagem. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def set_bitmap_gauge
fw = (self.bitmap.width * @rate).to_i
self.src_rect.width = fw
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ gauge_width │ É aqui que é definido a largura do gauge. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def gauge_width
return @mode == :normal ? 100 : self.bitmap.width
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ gauge_height │ É aqui que é definido a altura do gauge. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def gauge_height
return @mode == :normal ? 4 : self.bitmap.height
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ gauge_back_color │ A cor de fundo do gauge. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def gauge_back_color
return Color.new(50, 0, 0, 255)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ gauge_fill_color │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Retorna uma array de duas cores. A primeira é a cor inicial, e a segunda │
#│ é a cor final. │
#└───────────────────────────────────────────────────────────────────────────┘
def gauge_fill_color
start_color = Color.new(100, 0, 0, 255)
finish_color = Color.new(255, 0, 0, 255)
return [start_color, finish_color]
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_rate │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Configura a taxa de preenchimento do gauge externamente. │
#│ → rate: a taxa. De 0.0 a 1.0 │
#└───────────────────────────────────────────────────────────────────────────┘
def set_rate(rate)
@rate = rate
set_gauge(@mode)
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Gauge_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Animated_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite com animação de frames. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Animated_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → framesx: o número de frames na horizontal. │
#│ → framesy: o número de frames na vertical. │
#│ → max_frames: o número máximo de frames. │
#│ → bitmap: o bitmap necessário para animar. │
#│ → viewport: o viewport associado ao sprite. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(framesx, framesy, max_frames, bitmap, viewport = nil)
super(viewport)
self.bitmap = bitmap
@framesx = framesx
@framesy = framesy
@max_frames = max_frames
@animate = false
@count = 0
@index = 0
@sizex = self.bitmap.width / @framesx
@sizey = self.bitmap.height / @framesy
setup_rect
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ setup_rect │ Configura o retângulo para desenhar o frame. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def setup_rect
x = @index % @framesx * @sizex
y = @index / @framesx * @sizex
rect = Rect.new(x, y, @sizex, @sizey)
self.src_rect.set(rect)
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ start_animation │ Usado para iniciar a animação. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def start_animation
@animate = true
end
#┌──────────────────┬────────────────────────────────────────────────────────┐
#│ ♦ stop_animation │ Usado para parar a animação. │
#└──────────────────┴────────────────────────────────────────────────────────┘
def stop_animation
@animate = false
end
#┌───────────────────┬───────────────────────────────────────────────────────┐
#│ ♦ reset_animation │ Usado para reiniciar a animação. │
#└───────────────────┴───────────────────────────────────────────────────────┘
def reset_animation
@index = 0
setup_rect
end
#┌─────────────┬─────────────────────────────────────────────────────────────┐
#│ ♦ set_index │ Para manupular externamente o index do sprite. │
#└─────────────┴─────────────────────────────────────────────────────────────┘
def set_index(num)
@index = num
setup_rect
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
update_animation if @animate
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ update_animation │ Atualiza a animação. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def update_animation
@count + 1 > animate_wait ? @count = 0 : @count += 1
if @count == animate_wait
@index == @max_frames - 1 ? @index = 0 : @index += 1
setup_rect
end
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ animate_wait │ Quanto menor esse número, mais rápido é a animação. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def animate_wait
return 15
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Animated_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Aura_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite com um efeito de aura. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Aura_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: o bitmap do sprite. É recomendado usar um. │
#│ → viewport: o viewport associado ao sprite. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, viewport = nil)
super
@stopped = false
@comps = []
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
for i in 0...@comps.size
@comps[i].update
if @comps[i].done
@comps[i].dispose
@comps[i] = nil
end
end
@comps.compact!
fixed_update if Prism.run_fixed_update?
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ fixed_update │ Atualização a cada 15 frames. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def fixed_update
spawn_new_sprite unless @stopped
end
#┌────────┬──────────────────────────────────────────────────────────────────┐
#│ ♦ stop │ Usado para parar a animação. │
#└────────┴──────────────────────────────────────────────────────────────────┘
def stop
@stopped = true
end
#┌─────────┬─────────────────────────────────────────────────────────────────┐
#│ ♦ start │ Usado para iniciar a animação. Ela já inicia sozinha por padrão.│
#└─────────┴─────────────────────────────────────────────────────────────────┘
def start
@stopped = false
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ spawn_new_sprite │ Cria um novo sprite, que será deletado depois. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def spawn_new_sprite
@comps.push(Prism::Aura_Sprite_Comp.new(self.bitmap.clone, self.viewport))
@comps[-1].x = self.x
@comps[-1].x += @comps[-1].ox
@comps[-1].y = self.y
@comps[-1].y += @comps[-1].oy
@comps[-1].z = self.z - 1
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Aura_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Aura_Sprite_Comp ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Aura_Sprite_Comp < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas. │
#└───────────────────────────────────────────────────────────────────────────┘
attr_reader :done
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: o bitmap do sprite. │
#│ → viewport: o viewport associado ao sprite. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, viewport = nil)
super
self.ox = self.bitmap.width * 0.5
self.oy = self.bitmap.height * 0.5
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
update_animation
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ update_animation │ Atualização da animação. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def update_animation
self.opacity -= 8
self.zoom_x += 0.005
self.zoom_y += 0.005
if self.zoom_x >= 1.2 && self.zoom_y >= 1.2
@done = true
end
end
#┌───────────┬───────────────────────────────────────────────────────────────┐
#│ ♦ dispose │ Se livra do bitmap antes de efetuar o dispose. │
#└───────────┴───────────────────────────────────────────────────────────────┘
def dispose
self.bitmap.dispose
super
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Aura_Sprite_Comp ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Circular_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite que se move de maneira circular. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Circular_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas. │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :clockwise
attr_accessor :auto
attr_accessor :range
attr_accessor :speed
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: o bitmap do sprite. Padrão: nil. │
#│ → viewport: o viewport associado ao sprite. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, viewport = nil)
super
@clockwise = false
@auto = true
@angle = 0
@range = 48
@speed = 0.05
@origin_ox = self.ox
@origin_oy = self.oy
adjust_pos
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
adjust_count if @auto
adjust_pos
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ rotate_right │ Rotaciona o sprite para a direita. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def rotate_right
@angle -= @speed
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ rotate_left │ Rotaciona o sprite para a esquerda. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def rotate_left
@angle += @speed
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ adjust_count │ Ajusta a contagem para a rotação. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def adjust_count
@clockwise ? @angle -= @speed : @angle += @speed
end
#┌──────────────┬────────────────────────────────────────────────────────────┐
#│ ♦ adjust_pos │ Ajusta o ponto de origem para a rotação do sprite. │
#└──────────────┴────────────────────────────────────────────────────────────┘
def adjust_pos
self.ox = (@origin_ox + Math.sin(@angle) * @range)
self.oy = (@origin_oy + @range * Math.cos(@angle))
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Circular_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Numeric_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite que desenha números usando um bitmap como base. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Numeric_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas. │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :dimension
attr_accessor :source_bitmap
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: o bitmap do sprite. Padrão: nil. │
#│ → dimension: o tamanho de um caractere em pixels. │
#│ → bytes: a quantidade de caracteres na horizontal. Padrão: 10 │
#│ → viewport: o viewport associado ao sprite. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, dimension = 7, bytes = 10, viewport = nil)
super(nil, viewport)
@dimension = dimension
@align = 0
@value = 0
@bytes = bytes
@source_bitmap = bitmap
setup_base_bitmap
set_value(@value)
end
#┌─────────┬─────────────────────────────────────────────────────────────────┐
#│ ♦ align │ Usado para obter o alinhamento. │
#└─────────┴─────────────────────────────────────────────────────────────────┘
def align
@align
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ align= │ Usado para alterar o alinhamento. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def align=(num)
@align = num
set_value(@value)
end
#┌─────────────────────┬─────────────────────────────────────────────────────┐
#│ ♦ setup_base_bitmap │ Configura o bitmap de base. │
#└─────────────────────┴─────────────────────────────────────────────────────┘
def setup_base_bitmap
self.bitmap.dispose if self.bitmap
self.bitmap = Bitmap.new(@bytes * @dimension, @dimension)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_value │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta o novo valor de desenho do sprite. │
#│ → integer: um número que será o novo valor do sprite. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_value(integer)
@value = integer
return false unless @source_bitmap
self.bitmap.clear
char = integer.to_s
px = x_for_align(@align, char)
dsrc = Rect.new(px, 0, @dimension, @dimension)
for i in 0...char.size
dsrc.x = char[i].to_i * @dimension
self.bitmap.blt(px + (@dimension * i), 0, @source_bitmap, dsrc)
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ x_for_align │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém a posição de desenho do sprite dependendo do alinhamento. │
#│ → a: o número do alinhamento. │
#│ → c: o número completo convertido em string. │
#└───────────────────────────────────────────────────────────────────────────┘
def x_for_align(a, c)
res = 0
if a == 1
res += self.bitmap.width * 0.5 - (c.size * @dimension) * 0.5
elsif a == 2
res += self.bitmap.width - (c.size * @dimension)
end
return res
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Numeric_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Jump_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite com propriedades de pulo. Ele também inclui propriedades de ║
#║ movimento, usando add_force_left ou add_force_right. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Jump_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas. │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :auto
attr_accessor :range
attr_accessor :speed
attr_accessor :x_force_max
attr_accessor :bounciness
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: o bitmap do sprite. Padrão: nil. │
#│ → viewport: o viewport associado ao sprite. Padrão: nil │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Abaixo há algumas explicações das instâncias usadas no sprite para melhor │
#│ entendimento. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap, viewport = nil)
super
@auto = true # Indica se o sprite irá pular constantemente.
@angle = 0 # O contador do ângulo de pulo.
@range = 98 # A distância do pulo.
@speed = 0.1 # A velocidade de pulo.
@bounciness = 0.3 # Esse valor pode aplicar "bounce" no pulo.
@jump_times = 0 # Número de vezes que o sprite irá pular.
@default_speed = 0.1 # É recomendado ser o mesmo que speed.
@default_range = 98 # É recomendado ser o mesmo que range.
@x_force = 0 # A força de velocidade em X.
@x_force_max = 4 # A força máxima de velocidade em X.
@jumping = false # Indica se o sprite está pulando.
@landed = false # Indica se o sprite aterrissou.
@source_y = self.y # O ponto de origem do pulo.
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
adjust_count if @auto
adjust_jump
adjust_force
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ adjust_count │ Ajuste da incrementação do ângulo. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def adjust_count
@angle += @speed
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ adjust_jump │ Ajuste do pulo. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def adjust_jump
adjust_auto_jump if @auto
adjust_normal_jump if !@auto
end
#┌────────────────────┬──────────────────────────────────────────────────────┐
#│ ♦ adjust_auto_jump │ Ajuste do pulo automático. │
#└────────────────────┴──────────────────────────────────────────────────────┘
def adjust_auto_jump
self.y = -(Math.sin(@angle) * @range).abs + @source_y
end
#┌──────────────────────┬────────────────────────────────────────────────────┐
#│ ♦ adjust_normal_jump │ Ajuste do pulo normal. │
#└──────────────────────┴────────────────────────────────────────────────────┘
def adjust_normal_jump
if @range != @default_range && !@jumping
@speed = @default_speed
@range = @default_range
@angle = 0
end
if !@jumping && self.y != @source_y
self.y = @source_y
end
return unless @jumping
self.y = -(Math.sin(@angle) * @range).abs + @source_y
@range = Prism.decrease(@range, @bounciness, 0)
if self.y.between?(@source_y - 2, @source_y)
@landed = true
else
@landed = false
end
if @range == 0 && @jump_times <= 0
@jumping = false
end
if @landed && @jump_times > 0
@jump_times -= 1
@angle = 0
@speed = @default_speed
@range = @default_range
end
@speed += 0.001
adjust_count
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ refresh_position │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualiza o novo ponto de origem da posição Y. É recomendado chamar este │
#│ método quando quiser gravar o novo ponto onde o sprite deve "cair". │
#└───────────────────────────────────────────────────────────────────────────┘
def refresh_position
@source_y = self.y
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ jump │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Faz o sprite pular o número de vezes desejados. Começando por 0. │
#│ → times: o número de vezes que ele irá pular. Padrão: 0 │
#└───────────────────────────────────────────────────────────────────────────┘
def jump(times = 0)
@jumping = true
@jump_times = times
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ adjust_force │ Ajusta a força de velocidade X. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def adjust_force
self.x += @x_force
if @x_force > 0
@x_force - 0.1 < 0 ? @x_force = 0 : @x_force -= 0.1
elsif @x_force < 0
@x_force + 0.1 > 0 ? @x_force = 0 : @x_force += 0.1
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ add_force_right │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Adiciona uma certa quantidade de força de movimento X para a direita. │
#│ → force: a força desejada, em float. │
#└───────────────────────────────────────────────────────────────────────────┘
def add_force_right(force)
if @x_force + force > @x_force_max
@x_force = @x_force_max
else
@x_force += force
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ add_force_left │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Adiciona uma certa quantidade de força de movimento X para a esquerda. │
#│ → force: a força desejada, em float. │
#└───────────────────────────────────────────────────────────────────────────┘
def add_force_left(force)
if @x_force - force < -@x_force_max
@x_force = -@x_force_max
else
@x_force -= force
end
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Jump_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Flashing_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite que pisca. Você pode ajustar o tom, velocidade e etc... ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Flashing_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas. │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :auto
attr_accessor :speed
attr_accessor :source_tone
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: o bitmap do sprite. Padrão: nil. │
#│ → viewport: o viewport associado ao sprite. Padrão: nil │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, viewport = nil)
super
@auto = true
@phase = 0
@speed = 15
@flash_times = 0
@manual_flashing = false
@source_tone = Tone.new(255, 255, 255, 255)
end
#┌──────────┬────────────────────────────────────────────────────────────────┐
#│ ♦ update │ Atualização de frames. │
#└──────────┴────────────────────────────────────────────────────────────────┘
def update
super
adjust_tone if @auto || @manual_flashing
adjust_flash if @auto || @manual_flashing
end
#┌───────────────┬───────────────────────────────────────────────────────────┐
#│ ♦ adjust_tone │ Ajuste de tonalidade. │
#└───────────────┴───────────────────────────────────────────────────────────┘
def adjust_tone
tr = self.tone.red
tg = self.tone.green
tb = self.tone.blue
ta = self.tone.gray
sr = @source_tone.red
sg = @source_tone.green
sb = @source_tone.blue
sa = @source_tone.gray
c1 = tr >= sr && tg >= sg && tb >= sb && ta >= sa
c2 = tr <= 0 && tg <= 0 && tb <= 0 && ta <= 0
if c1 && @phase == 0
@phase = 1
@flash_times - 1 < 0 ? @flash_times = 0 : @flash_times -= 1
elsif c2 && @phase == 1
@phase = 0
end
@manual_flashing = !(@flash_times <= 0 && c2 && @phase == 0)
end
#┌────────────────┬──────────────────────────────────────────────────────────┐
#│ ♦ adjust_flash │ Ajuste de flash. │
#└────────────────┴──────────────────────────────────────────────────────────┘
def adjust_flash
if @phase == 0
self.tone.red = Prism.increase(self.tone.red, @speed, @source_tone.red)
self.tone.green = Prism.increase(self.tone.green, @speed, @source_tone.green)
self.tone.blue = Prism.increase(self.tone.blue, @speed, @source_tone.blue)
self.tone.gray = Prism.increase(self.tone.gray, @speed, @source_tone.gray)
elsif @phase == 1
self.tone.red = Prism.decrease(self.tone.red, @speed, 0)
self.tone.green = Prism.decrease(self.tone.green, @speed, 0)
self.tone.blue = Prism.decrease(self.tone.blue, @speed, 0)
self.tone.gray = Prism.decrease(self.tone.gray, @speed, 0)
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ flash │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Faz o sprite piscar o número de vezes desejado. Começando por 1. │
#│ → times: o número de vezes que ele irá piscar. Padrão: 1 │
#└───────────────────────────────────────────────────────────────────────────┘
def flash(times = 1)
@flash_times = times
@manual_flashing = true
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Flashing_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Touch_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite com métodos de toque. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Touch_Sprite < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: automaticamente configura o bitmap se for especificado. │
#│ → viewport: o viewport associado ao sprite, se for especificado. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, viewport = nil)
super
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_pressed? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se o sprite está sendo tocado. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_pressed?
return Prism::Touch_Input.is_pressed? && is_hovered?
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_triggered? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se o sprite foi tocado uma vez. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_triggered?
return Prism::Touch_Input.is_triggered?(self) && is_hovered?
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_repeated? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se o sprite está sendo pressionado repetidamente. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_repeated?
return Prism::Touch_Input.is_repeated?(self) && is_hovered?
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_cancelling? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se o sprite está sendo cancelado. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_cancelling?
return Prism::Touch_Input.is_cancelling? && is_hovered?
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_cancelled? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se o sprite foi cancelado. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_cancelled?
return Prism::Touch_Input.is_cancelled?(self) && is_hovered?
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_hovered? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se o cursor está sobre o sprite. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_hovered?
x = self.x
y = self.y
w = self.bitmap.width
h = self.bitmap.height
return Prism::Touch_Input.hovering?(x, y, w, h)
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Touch_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::Drag_Sprite ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um sprite que você pode arrastar por aí com o toque. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::Drag_Sprite < Prism::Touch_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → bitmap: automaticamente configura o bitmap se for especificado. │
#│ → viewport: o viewport associado ao sprite, se for especificado. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(bitmap = nil, viewport = nil)
super
@mouse_coords = Prism::Point.new
@new_points = Prism::Point.new
@dragging = false
@block_to_screen = true
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualização de frames. │
#└───────────────────────────────────────────────────────────────────────────┘
def update
super
update_mouse_coords
check_if_dragging
on_drag if @dragging
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update_mouse_coords │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualiza as coordenadas do cursor. │
#└───────────────────────────────────────────────────────────────────────────┘
def update_mouse_coords
@mouse_coords.x = Prism::Touch_Input.x - self.x
@mouse_coords.y = Prism::Touch_Input.y - self.y
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ check_if_dragging │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Checa se o sprite está sendo arrastado. │
#└───────────────────────────────────────────────────────────────────────────┘
def check_if_dragging
if is_pressed?
@dragging = true
@new_points.x = Prism::Touch.last_pos[0] - self.x
@new_points.y = Prism::Touch.last_pos[1] - self.y
else
@dragging = false
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ on_drag │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Processa o arrastamento do sprite. │
#└───────────────────────────────────────────────────────────────────────────┘
def on_drag
if @mouse_coords.x < @new_points.x
if !getting_off_screen(:lb) && @block_to_screen
self.x -= @new_points.x - @mouse_coords.x
@new_points.x = Prism::Touch.last_pos[0] - self.x
elsif !@block_to_screen
self.x -= @new_points.x - @mouse_coords.x
@new_points.x = Prism::Touch.last_pos[0] - self.x
else
self.x = 0
end
elsif @mouse_coords.x > @new_points.x
if !getting_off_screen(:rb) && @block_to_screen
self.x += @mouse_coords.x - @new_points.x
@new_points.x = Prism::Touch.last_pos[0] - self.x
elsif !@block_to_screen
self.x += @mouse_coords.x - @new_points.x
@new_points.x = Prism::Touch.last_pos[0] - self.x
else
self.x = Graphics.width - self.bitmap.width
end
end
if @mouse_coords.y < @new_points.y
if !getting_off_screen(:ub) && @block_to_screen
self.y -= @new_points.y - @mouse_coords.y
@new_points.y = Prism::Touch.last_pos[1] - self.y
elsif !@block_to_screen
self.y -= @new_points.y - @mouse_coords.y
@new_points.y = Prism::Touch.last_pos[1] - self.y
else
self.y = 0
end
elsif @mouse_coords.y > @new_points.y
if !getting_off_screen(:db) && @block_to_screen
self.y += @mouse_coords.y - @new_points.y
@new_points.y = Prism::Touch.last_pos[1] - self.y
elsif !@block_to_screen
self.y += @mouse_coords.y - @new_points.y
@new_points.y = Prism::Touch.last_pos[1] - self.y
else
self.y = Graphics.height - self.bitmap.height
end
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ getting_off_screen │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se o sprite está prestes a sair da tela. │
#└───────────────────────────────────────────────────────────────────────────┘
def getting_off_screen(type)
lb = self.x - (@new_points.x - @mouse_coords.x) < 0
rb = self.x + (@mouse_coords.x - @new_points.x + self.bitmap.width) > Graphics.width
ub = self.y - (@new_points.y - @mouse_coords.y) < 0
db = self.y + (@mouse_coords.y - @new_points.y + self.bitmap.height) > Graphics.height
return lb if type == :lb
return rb if type == :rb
return ub if type == :ub
return db if type == :db
return true
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::Drag_Sprite ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::GUI ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um módulo contendo sprites para a criação de GUIs simples. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
module Prism::GUI; end
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::GUI::Button ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um botão que pode ser clicado. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::GUI::Button < Prism::Touch_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :on_click
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal do botão. │
#│ → y: posição vertical do botão. │
#│ → width: largura do botão. │
#│ → height: altura do botão. │
#│ → text: o texto que será mostrado no botão. │
#│ → viewport: o viewport associado ao botão. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height, text = "", viewport = nil)
@normal_bmp = main_bitmap(width, height, text)
@highlight_bmp = main_bitmap(width, height, text, true)
@on_click = nil
super(@normal_bmp, viewport)
self.x = x
self.y = y
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ main_bitmap │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o bitmap do botão. │
#│ → w: largura do bitmap. │
#│ → h: altura do bitmap. │
#│ → t: texto que será desenhado no bitmap. │
#│ → highlight: bitmap caso o cursor esteja acima do botão. │
#└───────────────────────────────────────────────────────────────────────────┘
def main_bitmap(w, h, t, highlight = false)
bmp = Bitmap.new(w, h)
c1 = highlight ? Prism.color_convert("e5f1fb") : Prism.color_convert("e1e1e1")
c2 = highlight ? Prism.color_convert("0179d7") : Prism.color_convert("adadad")
bmp.fill_rect(0, 0, w, h, c1)
bmp.fill_rect(0, 0, w, 1, c2)
bmp.fill_rect(0, h - 1, w, 1, c2)
bmp.fill_rect(0, 0, 1, h, c2)
bmp.fill_rect(w - 1, 0, 1, h, c2)
bmp.font.name = "Segoe UI"
bmp.font.size = 14
bmp.font.outline = false
bmp.font.color = Prism.color_convert("010101")
bmp.draw_text(0, 0, w, h, t, 1)
return bmp
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualização de frames. │
#└───────────────────────────────────────────────────────────────────────────┘
def update
super
if is_hovered?
self.bitmap = @highlight_bmp
else
self.bitmap = @normal_bmp
end
if is_triggered? && @on_click
@on_click.call
end
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::GUI::Button ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::GUI::Background ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um background padrão para servir de modelo na criação de GUIs. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::GUI::Background < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → viewport: o viewport associado ao background. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(viewport = nil)
rect = Rect.new(0, 0, Graphics.width, Graphics.height)
color = Prism.color_convert("efefef")
super(Bitmap.new(rect.width, rect.height), viewport)
self.bitmap.fill_rect(0, 0, rect.width, rect.height, color)
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::GUI::Background ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::GUI::Panel ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um painel com uma cor um tanto mais clara que o background do GUI. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::GUI::Panel < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal do painel. │
#│ → y: posição vertical do painel. │
#│ → width: largura do painel. │
#│ → height: altura do painel. │
#│ → viewport: o viewport associado ao painel. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height, viewport = nil)
bmp = main_bitmap(width, height)
super(bmp, viewport)
self.x = x
self.y = y
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ main_bitmap │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha o bitmap principal do painel. │
#│ → w: largura do bitmap do painel. │
#│ → h: altura do bitmap do painel. │
#└───────────────────────────────────────────────────────────────────────────┘
def main_bitmap(w, h)
bmp = Bitmap.new(w, h)
c1 = Prism.color_convert("ffffff")
c2 = Prism.color_convert("d8d8d8")
bmp.fill_rect(0, 0, w, h, c1)
bmp.fill_rect(0, 0, w, 1, c2)
bmp.fill_rect(0, h - 1, w, 1, c2)
bmp.fill_rect(0, 0, 1, h, c2)
bmp.fill_rect(w - 1, 0, 1, h, c2)
return bmp
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::GUI::Panel ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::GUI::Text_Input ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Uma caixa onde o usuário pode inserir texto. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::GUI::Text_Input < Prism::Input_Window
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :text
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal do campo de texto. │
#│ → y: posição vertical do campo de texto. │
#│ → width: largura do campo de texto. │
#│ → height: altura do campo de texto. │
#│ → viewport: o viewport associado ao campo de texto. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height, viewport = nil)
@box_input_bmp_n = get_box_input_bmp(width, height)
@box_input_bmp_h = get_box_input_bmp(width, height, true)
create_box_input(viewport)
super(x, y, width, height + 8)
self.opacity = 0
self.viewport = viewport
@box_input.x = self.x
@box_input.y = self.y + (window_padding * 2) + 1
adjust_font
self.deactivate
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Obtém o sprite da caixa de texto para associação de um tooltip. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_associative_tooltip
return @box_input
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ adjust_font │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta as configurações de fonte principais. │
#└───────────────────────────────────────────────────────────────────────────┘
def adjust_font
self.contents.font.name = "Segoe UI"
self.contents.font.size = 14
self.contents.font.outline = false
self.contents.font.color = Prism.color_convert("010101")
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ create_input_sprite │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Configuração do sprite de cursor. │
#└───────────────────────────────────────────────────────────────────────────┘
def create_input_sprite
super
@input_sprite.bitmap.clear
@input_sprite.bitmap.font.name = "Segoe UI"
@input_sprite.bitmap.font.size = 14
@input_sprite.bitmap.font.outline = false
@input_sprite.bitmap.font.color = Prism.color_convert("010101")
@input_sprite.bitmap.draw_text(0, 0, 24, 24, "|")
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ process_character │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajuste no processamento de caracteres. │
#│ → ch: o caractere que está prestes a ser inserido. │
#└───────────────────────────────────────────────────────────────────────────┘
def process_character(ch)
if self.contents.text_size(@text + ch).width > contents_width
Sound.play_buzzer
return
else
@text << ch
refresh_text
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualização de frames. │
#└───────────────────────────────────────────────────────────────────────────┘
def update
if @box_input && @box_input.bitmap && @box_input_bmp_h && @box_input_bmp_n
if @box_input.is_hovered?
@box_input.bitmap = @box_input_bmp_h
else
@box_input.bitmap = @box_input_bmp_n
end
if @box_input.is_triggered?
self.activate unless self.active
elsif Prism::Touch_Input.is_triggered? && !@box_input.is_hovered?
self.deactivate unless !self.active
end
end
if @input_sprite && @count
@input_sprite.opacity = 0 if !self.active
@count = 0 if !self.active
end
super
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ process_confirmation │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Processamento de confirmação. │
#└───────────────────────────────────────────────────────────────────────────┘
def process_confirmation; end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ activate │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ativação. │
#└───────────────────────────────────────────────────────────────────────────┘
def activate
self.active = true
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ window_padding │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Distância entre o texto e as bordas. │
#└───────────────────────────────────────────────────────────────────────────┘
def window_padding
return 4
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ z= │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajuste na posição z dos componentes. │
#│ → v: o novo valor z. │
#└───────────────────────────────────────────────────────────────────────────┘
def z=(v)
@box_input.z = v - 1
@input_sprite.z = v + 1
super
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ viewport= │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajuste no viewport dos componentes. │
#│ → vp: o novo viewport. │
#└───────────────────────────────────────────────────────────────────────────┘
def viewport=(vp)
@box_input.viewport = vp
@input_sprite.viewport = vp
super
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ create_box_input │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Cria a caixa de digitação. │
#└───────────────────────────────────────────────────────────────────────────┘
def create_box_input(vp)
@box_input = Prism::Touch_Sprite.new(@box_input_bmp_n, vp)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_box_input_bmp │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o bitmap para a caixa de digitação. │
#│ → width: a largura do bitmap. │
#│ → height: a altura do bitmap. │
#│ → highlight: bitmap caso o cursor esteja acima da caixa. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_box_input_bmp(width, height, highlight = false)
bmp = Bitmap.new(width, height)
c1 = Prism.color_convert("ffffff")
c2 = highlight ? Prism.color_convert("0078d6") : Prism.color_convert("646464")
bmp.fill_rect(0, 0, width, height, c1)
bmp.fill_rect(0, 0, width, 1, c2)
bmp.fill_rect(0, height - 1, width, 1, c2)
bmp.fill_rect(0, 0, 1, height, c2)
bmp.fill_rect(width - 1, 0, 1, height, c2)
return bmp
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ dispose │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Efetua o dispose do @box_input. │
#└───────────────────────────────────────────────────────────────────────────┘
def dispose
@box_input.dispose if @box_input
super
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::GUI::Text_Input ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::GUI::Label ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um texto normal para ser mostrado em GUIs. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::GUI::Label < Prism::Text_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal do texto. │
#│ → y: posição vertical do texto. │
#│ → text: o texto a ser desenhado. │
#│ → viewport: o viewport associado ao botão. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, text = "", viewport = nil)
super(viewport)
self.x = x
self.y = y
set_font_property(:name, "Segoe UI")
set_font_property(:size, 14)
set_font_property(:outline, false)
set_font_property(:color, Prism.color_convert("010101"))
set_text(text)
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::GUI::Label ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::GUI::Explorer ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Sistema de explorador de arquivos. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::GUI::Explorer < Prism::Window_Command
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ Variáveis de Instância Públicas │
#└───────────────────────────────────────────────────────────────────────────┘
attr_accessor :selected # Se a janela terminou de selecionar.
attr_accessor :directory # O diretório onde o explorer está.
attr_accessor :selected_file # O nome do arquivo selecionado.
attr_accessor :selected_file_type # O tipo do arquivo selecionado.
# :file, :image ou :text.
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal do explorador. │
#│ → y: posição vertical do explorador. │
#│ → width: largura do explorador. │
#│ → height: altura do explorador. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height)
@directory = Dir.getwd
@selected = false
@selected_file = nil
@selected_file_type = nil
@viewer = nil
super
self.windowskin = explorer_windowskin
self.back_opacity = 255
update_viewer
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ make_command_list │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Criação da lista de comandos. │
#└───────────────────────────────────────────────────────────────────────────┘
def make_command_list
@list = {}
list = []
@back = []
@folders = []
@files = []
@images = []
@texts = []
d = @directory.unpack("U*").pack("C*")
Dir.entries(d, {encoding: "UTF-8"}).each {|dir|
ext = File.extname(dir)
next if dir == "."
list.push(dir)
@back.push(dir) if dir == ".."
@folders.push(dir) if ext.empty? && (dir != "." && dir != "..")
@files.push(dir) if !ext.empty? && !is_image?(ext) && !is_text?(ext)
@images.push(dir) if is_image?(ext)
@texts.push(dir) if is_text?(ext)
}
@back.each {|item| add_command(item, item.to_sym, true, get_handler(item))}
@folders.each {|item| add_command(item, item.to_sym, true, get_handler(item))}
@files.each {|item| add_command(item, item.to_sym, true, get_handler(item))}
@images.each {|item| add_command(item, item.to_sym, true, get_handler(item))}
@texts.each {|item| add_command(item, item.to_sym, true, get_handler(item))}
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_image? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se a extensão é reconhecida como uma imagem. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_image?(extension)
return true if extension =~ /jpg/i
return true if extension =~ /jpeg/i
return true if extension =~ /png/i
return false
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ is_text? │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Indica se a extensão é reconhecida como um arquivo de texto. │
#└───────────────────────────────────────────────────────────────────────────┘
def is_text?(extension)
return true if extension =~ /txt/i
return false
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ get_handler │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o método que será chamado dependendo do item passado. │
#└───────────────────────────────────────────────────────────────────────────┘
def get_handler(item)
return method(:on_back) if item == ".."
return method(:on_folder_select) if @folders.include?(item)
return method(:on_file_select) if @files.include?(item)
return method(:on_image_select) if @images.include?(item)
return method(:on_text_select) if @texts.include?(item)
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ on_back │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Faz o explorer voltar um diretório acima. │
#└───────────────────────────────────────────────────────────────────────────┘
def on_back
path = ""
folders = @directory.split("/")
return if folders.size < 3
for i in 0...folders.size - 1
path += folders[i] + "/"
end
@directory = path.slice(0, path.size - 1)
redraw_command_list
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ on_folder_select │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Faz o explorer ir para a pasta selecionada. │
#└───────────────────────────────────────────────────────────────────────────┘
def on_folder_select
path = @directory + "/#{selected_item[1][:type]}"
if File.directory?(path)
@directory = path
redraw_command_list
else
Sound.play_buzzer
if @viewer
alert_message = "Ocorreu um erro ao abrir o diretório.\nTalvez ele não seja um diretório."
@viewer.receive_information(alert_message, :alert)
end
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ on_file_select │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Processamento de seleção de um arquivo. │
#└───────────────────────────────────────────────────────────────────────────┘
def on_file_select
@selected_file = selected_item[1][:type]
@selected_file_type = :file
@selected = true
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ on_text_select │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Processamento de seleção de um arquivo de texto. │
#└───────────────────────────────────────────────────────────────────────────┘
def on_text_select
@selected_file = selected_item[1][:type]
@selected_file_type = :text
@selected = true
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ on_image_select │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Processamento de seleção de um arquivo de imagem. │
#└───────────────────────────────────────────────────────────────────────────┘
def on_image_select
@selected_file = selected_item[1][:type]
@selected_file_type = :image
path = @directory + "/" + @selected_file
name = File.basename(@selected_file, ".*")
dir = File.dirname(path) + "/"
begin
bmp = Bitmap.new(dir + name)
rescue
if @viewer
alert_message = "Ocorreu um erro ao carregar a imagem."
@viewer.receive_information(alert_message, :alert)
end
return
end
@selected = true
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ folder_icon │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o bitmap desenhado com o ícone de uma pasta. │
#└───────────────────────────────────────────────────────────────────────────┘
def folder_icon
bmp = Bitmap.new(16, 16)
c = Prism.color_convert("e7c147")
c2 = Prism.color_convert("ffe486")
bmp.fill_rect(4, 4, 8, 1, c)
bmp.fill_rect(4, 4, 1, 9, c)
bmp.fill_rect(4, 12, 8, 1, c)
bmp.fill_rect(11, 4, 1, 9, c)
bmp.fill_rect(9, 4, 1, 9, c)
bmp.fill_rect(5, 5, 4, 7, c2)
bmp.fill_rect(10, 5, 1, 7, c2)
return bmp
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ file_icon │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o bitmap desenhado com o ícone de um arquivo. │
#└───────────────────────────────────────────────────────────────────────────┘
def file_icon
bmp = Bitmap.new(16, 16)
c = Prism.color_convert("0a0a0a")
c2_1 = Prism.color_convert("75daed")
c2_2 = Prism.color_convert("e5f8fc")
bmp.fill_rect(4, 4, 5, 1, c)
bmp.fill_rect(4, 4, 1, 9, c)
bmp.fill_rect(4, 12, 8, 1, c)
bmp.fill_rect(11, 5, 1, 8, c)
bmp.fill_rect(8, 5, 4, 1, c)
bmp.gradient_fill_rect(6, 7, 4, 4, c2_1, c2_2, true)
return bmp
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ text_icon │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o bitmap desenhado com o ícone de um texto. │
#└───────────────────────────────────────────────────────────────────────────┘
def text_icon
bmp = Bitmap.new(16, 16)
c = Prism.color_convert("808283")
bmp.fill_rect(4, 4, 8, 1, c)
bmp.fill_rect(4, 4, 1, 9, c)
bmp.fill_rect(11, 4, 1, 9, c)
bmp.fill_rect(4, 12, 8, 1, c)
bmp.fill_rect(6, 6, 2, 1, c)
bmp.fill_rect(9, 6, 1, 1, c)
bmp.fill_rect(6, 8, 1, 1, c)
bmp.fill_rect(8, 8, 1, 1, c)
bmp.fill_rect(7, 10, 3, 1, c)
return bmp
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ image_icon │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o bitmap desenhado com o ícone de uma imagem. │
#└───────────────────────────────────────────────────────────────────────────┘
def image_icon
bmp = Bitmap.new(16, 16)
c = Prism.color_convert("0179d7")
bmp.fill_rect(4, 4, 8, 1, c)
bmp.fill_rect(11, 4, 1, 9, c)
bmp.fill_rect(4, 12, 8, 1, c)
bmp.fill_rect(4, 4, 1, 9, c)
bmp.fill_rect(5, 8, 2, 1, c)
bmp.fill_rect(7, 7, 2, 1, c)
bmp.fill_rect(9, 8, 1, 1, c)
bmp.fill_rect(10, 9, 1, 1, c)
bmp.fill_rect(5, 9, 5, 3, c)
bmp.fill_rect(7, 8, 2, 1, c)
bmp.fill_rect(10, 10, 1, 2, c)
return bmp
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualização de frames. │
#└───────────────────────────────────────────────────────────────────────────┘
def update
old_index = @index
super
self.active = !@selected
update_viewer if @viewer && old_index != @index
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ cursor_speed │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Velocidade do cursor. │
#└───────────────────────────────────────────────────────────────────────────┘
def cursor_speed
return 12
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ scroll_speed │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Velocidade de rolamento. │
#└───────────────────────────────────────────────────────────────────────────┘
def scroll_speed
return 12
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_font_settings │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Configura a fonte para desenhar as opções. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_font_settings
self.contents.font.name = "Segoe UI"
self.contents.font.size = 14
self.contents.font.outline = false
self.contents.font.color = Prism.color_convert("010101")
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ process_string │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha os comandos. │
#└───────────────────────────────────────────────────────────────────────────┘
def process_string(cmd, i)
if @folders.include?(cmd[:type])
process_bitmap(folder_icon, i)
elsif @files.include?(cmd[:type])
process_bitmap(file_icon, i)
elsif @texts.include?(cmd[:type])
process_bitmap(text_icon, i)
elsif @images.include?(cmd[:type])
process_bitmap(image_icon, i)
end
old_alpha = self.contents.font.color.alpha
enabled = cmd[:enabled]
!enabled ? self.contents.font.color.alpha = 160 : nil
rect = item_rect(i)
draw_text(rect.x + 20, rect.y - 4, cmd[:type].to_s)
self.contents.font.color.alpha = old_alpha
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ process_bitmap │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Desenha os ícones dos comandos. │
#└───────────────────────────────────────────────────────────────────────────┘
def process_bitmap(bmp, i)
rect = item_rect(i)
bit_rect = Rect.new(0, 0, bmp.width, bmp.height)
self.contents.blt(rect.x, rect.y + 2, bmp, bit_rect)
bmp.dispose
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ selection_height │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Altura de cada item. │
#└───────────────────────────────────────────────────────────────────────────┘
def selection_height
return 18
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ explorer_windowskin │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o bitmap para ser usado como windowskin do explorer. │
#└───────────────────────────────────────────────────────────────────────────┘
def explorer_windowskin
bmp = Bitmap.new(128, 128)
c1 = Prism.color_convert("ffffff"); c2 = Prism.color_convert("e5f3ff")
c3 = Prism.color_convert("d8d8d8"); c4 = Prism.color_convert("999999")
# Desenho principal.
bmp.fill_rect(0, 0, 64, 128, c1)
bmp.fill_rect(64, 96, 64, 32, c1)
bmp.fill_rect(96, 64, 32, 32, c1)
bmp.fill_rect(64, 64, 32, 32, c2)
bmp.fill_rect(64, 0, 64, 1, c3)
bmp.fill_rect(127, 0, 1, 64, c3)
bmp.fill_rect(64, 63, 64, 1, c3)
bmp.fill_rect(64, 0, 1, 64, c3)
# Seta superior
bmp.fill_rect(92, 20, 5, 1, c4)
bmp.fill_rect(93, 19, 3, 1, c4)
bmp.fill_rect(94, 18, 1, 1, c4)
# Seta esquerda
bmp.fill_rect(84, 28, 1, 5, c4)
bmp.fill_rect(83, 29, 1, 3, c4)
bmp.fill_rect(82, 30, 1, 1, c4)
# Seta direita
bmp.fill_rect(105, 28, 1, 5, c4)
bmp.fill_rect(106, 29, 1, 3, c4)
bmp.fill_rect(107, 30, 1, 1, c4)
# Seta inferior
bmp.fill_rect(92, 41, 5, 1, c4)
bmp.fill_rect(93, 42, 3, 1, c4)
bmp.fill_rect(94, 43, 1, 1, c4)
return bmp
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update_tone │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta a tonalidade do explorer. │
#└───────────────────────────────────────────────────────────────────────────┘
def update_tone
self.tone.set(Tone.new(0, 0, 0))
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_viewer │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Configura o visualizador de informações do explorer. │
#│ → viewer: o visualizador. Precisa ser um Prism::Base_Sprite ou um │
#│ Prism::GUI::Viewer. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_viewer(viewer)
@viewer = viewer
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ redraw_command_list │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta o visualizador ao redesenhar comandos. │
#└───────────────────────────────────────────────────────────────────────────┘
def redraw_command_list(*args)
super(*args)
update_viewer
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update_viewer │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualiza o conteúdo do visualizador. │
#└───────────────────────────────────────────────────────────────────────────┘
def update_viewer
return unless @viewer
item = selected_item[1][:type]
info = "#{@directory}/#{item}"
if @texts.include?(item)
@viewer.receive_information(info, :text)
elsif @files.include?(item)
@viewer.receive_information(info, :file)
elsif @images.include?(item)
@viewer.receive_information(info, :image)
else
@viewer.receive_information(nil, nil)
end
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::GUI::Explorer ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::GUI::Viewer ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um visualizador de imagens ou texto para o Prism::GUI::Explorer. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::GUI::Viewer < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → x: posição horizontal do visualizador. │
#│ → y: posição vertical do visualizador. │
#│ → width: largura do visualizador. │
#│ → height: altura do visualizador. │
#│ → viewport: o viewport associado ao visualizador. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(x, y, width, height, viewport = nil)
super(main_bmp(width, height), viewport)
@main_rect = [width, height]
@main_sprite = Prism::Base_Sprite.new(nil, viewport)
self.x = x
self.y = y
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ z= │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta a posição z do @main_sprite de acordo. │
#│ → v: a nova posição z. │
#└───────────────────────────────────────────────────────────────────────────┘
def z=(v)
@main_sprite.z = v + 1 if @main_sprite
super
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ x= │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta a posição x do @main_sprite de acordo. │
#│ → v: a nova posição x. │
#└───────────────────────────────────────────────────────────────────────────┘
def x=(v)
@main_sprite.x = v + 1 if @main_sprite
super
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ y= │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta a posição y do @main_sprite de acordo. │
#│ → v: a nova posição y. │
#└───────────────────────────────────────────────────────────────────────────┘
def y=(v)
@main_sprite.y = v + 1 if @main_sprite
super
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ viewport= │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta o viewport do @main_sprite de acordo. │
#│ → vp: o novo viewport. │
#└───────────────────────────────────────────────────────────────────────────┘
def viewport=(vp)
@main_sprite.viewport = vp if @main_sprite
super
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ set_font_settings │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Ajusta as configurações de fonte do bitmap principal. │
#└───────────────────────────────────────────────────────────────────────────┘
def set_font_settings
self.bitmap.font.name = "Segoe UI"
self.bitmap.font.size = 14
self.bitmap.font.outline = false
self.bitmap.font.color = Prism.color_convert("000000")
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ main_bmp │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o bitmap original do visualizador. │
#│ → w: a largura do bitmap. │
#│ → h: a altura do bitmap. │
#└───────────────────────────────────────────────────────────────────────────┘
def main_bmp(w, h)
bmp = Bitmap.new(w, h)
c1 = Prism.color_convert("ffffff")
c2 = Prism.color_convert("d8d8d8")
bmp.fill_rect(0, 0, w, h, c1)
bmp.fill_rect(0, 0, w, 1, c2)
bmp.fill_rect(0, h - 1, w, 1, c2)
bmp.fill_rect(0, 0, 1, h, c2)
bmp.fill_rect(w - 1, 0, 1, h, c2)
return bmp
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ receive_information │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Recebe uma informação que será passada ao visualizador. │
#│ Caso type seja :text, info será desenhado no bitmap do visualizador. │
#│ → info: a informação a ser passada ao visualizador. │
#│ → type: o tipo de informação a ser passada. │
#└───────────────────────────────────────────────────────────────────────────┘
def receive_information(info, type)
self.bitmap = main_bmp(@main_rect[0], @main_rect[1])
@main_sprite.bitmap.dispose if @main_sprite.bitmap
if type == :text
if File.size(info) > 500
text = "Este arquivo de texto é muito grande para ser lido pelo visualizador."
else
text = load_data(info).unpack("C*").pack("U*")
end
write_text(4, 4, text.to_s, 0, true)
elsif type == :file
text = "Este arquivo não pode ser lido pelo visualizador."
write_text(4, 4, text, 0, true)
elsif type == :alert
write_text(4, 4, info, 0, true)
elsif type == :image
name = File.basename(info, ".*")
dir = File.dirname(info) + "/"
begin
@main_sprite.bitmap = Bitmap.new(dir + name)
rescue
return
end
if @main_sprite.bitmap.width > self.bitmap.width
@main_sprite.zoom_x = (self.bitmap.width - 2).to_f / @main_sprite.bitmap.width
elsif @main_sprite.bitmap.width < self.bitmap.width
@main_sprite.zoom_x = 1
end
if @main_sprite.bitmap.height > self.bitmap.height
@main_sprite.zoom_y = (self.bitmap.height - 2).to_f / @main_sprite.bitmap.height
elsif @main_sprite.bitmap.height < self.bitmap.height
@main_sprite.zoom_y = 1
end
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ dispose │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Efetua o dispose do @main_sprite. │
#└───────────────────────────────────────────────────────────────────────────┘
def dispose
@main_sprite.dispose if @main_sprite
super
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::GUI::Viewer ◄
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ ҉ Prism::GUI::Tooltip ║
#╠═════════════════════════════════════════════════════════════════════════════╣
#║ Um pequeno sprite que serve como tooltip para algumas opções. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
class Prism::GUI::Tooltip < Prism::Base_Sprite
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ initialize │
#├───────────────────────────────────────────────────────────────────────────┤
#│ → width: largura do tooltip. │
#│ → height: altura do tooltip. │
#│ → viewport: o viewport associado ao tooltip. │
#└───────────────────────────────────────────────────────────────────────────┘
def initialize(width, height, text = "", viewport = nil)
super(main_bitmap(width, height, text), viewport)
@fixed_pos = [nil, nil]
@associated_object = nil
@wait_count = 0
self.visible = false
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ associate │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Associa um objeto ao tooltip. O objeto precisa ser um Prism::Touch_Sprite │
#│ ou um Prism::GUI::Text_Input. │
#│ → obj: o objeto a ser associado. │
#└───────────────────────────────────────────────────────────────────────────┘
def associate(obj)
if obj.is_a?(Prism::Touch_Sprite)
@associated_object = obj
elsif obj.is_a?(Prism::GUI::Text_Input)
@associated_object = obj.get_associative_tooltip
end
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ main_bitmap │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Obtém o bitmap do tooltip. │
#│ → w: largura do bitmap. │
#│ → h: altura do bitmap. │
#│ → text: o texto a ser desenhado no bitmap. │
#└───────────────────────────────────────────────────────────────────────────┘
def main_bitmap(w, h, text)
lines = []
text.split("\n").each {|line| lines.push(line) unless line == ""}
bmp = Bitmap.new(w, h)
c1 = Prism.color_convert("feffe1")
c2 = Prism.color_convert("646464")
bmp.fill_rect(0, 0, w, h, c1)
bmp.fill_rect(0, 0, w, 1, c2)
bmp.fill_rect(0, 0, 1, h, c2)
bmp.fill_rect(w - 1, 0, 1, h, c2)
bmp.fill_rect(0, h - 1, w, 1, c2)
bmp.font.name = "Segoe UI"
bmp.font.size = 14
bmp.font.outline = false
bmp.font.color = Prism.color_convert("010101")
for i in 0...lines.size
bmp.draw_text(4, 4 + (14 * i), w, 14, lines[i])
end
return bmp
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualização de frames. │
#└───────────────────────────────────────────────────────────────────────────┘
def update
super
update_associated_object if @associated_object
end
#┌───────────────────────────────────────────────────────────────────────────┐
#│ ♦ update_associated_object │
#├───────────────────────────────────────────────────────────────────────────┤
#│ Atualização do objeto associado. │
#└───────────────────────────────────────────────────────────────────────────┘
def update_associated_object
@associated_object.is_hovered? ? @wait_count += 0.01 : @wait_count = 0
self.visible = @wait_count.between?(1, 5)
self.z = @associated_object.z + 1
@wait_count = 5 if @wait_count > 5
@wait_count = 0 if Prism::Touch_Input.is_triggered?
if self.visible && @fixed_pos[0].nil? && @fixed_pos[1].nil?
@fixed_pos[0] = Prism::Touch_Input.x
@fixed_pos[1] = Prism::Touch_Input.y
elsif !self.visible
@fixed_pos[0] = nil
@fixed_pos[1] = nil
end
self.x = @fixed_pos[0] || 0
self.y = @fixed_pos[1] || 0
end
end # ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ ▫ Prism::GUI::Tooltip ◄
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment