Bitmap é simplesmente a classe com os dados da imagem (largura, altura, pixels...), mas sem ter a ver com qualquer coisa do jogo/tela de exibição (coordenadas, ângulo de rotação, por aí), considere como "a imagem bruta".
Sprite é uma classe que
possui um Bitmap (ou seja, um de seus atributos é um bitmap, ver code abaixo), e trata de ter métodos e atributos que operam com o jogo/tela (coordenadas, rotação, zoom x/y, src_rect, etc... como atributos, e update, flash, etc... como métodos).
No caso, sobre uma Sprite possuir um bitmap, isso significa poder fazer:
Código:
my_sprite = Sprite.new
my_sprite.bitmap = Bitmap.new(20, 20) # Isso cria um bitmap com tamanho 20x20
my_sprite.bitmap.fill_rect(Rect.new(0, 0, 20, 20), Color.new(255, 0, 0)) # Preenche o bitmap com vermelho
Para entender um pouco mais como essas duas classes interoperam, um exemplinho:
Código:
bmp = Bitmap.new(100, 50) # Cria Bitmap 100x50
bmp.fill_rect(Rect.new(0, 0, 50, 50), Color.new(255, 0, 0)) # Preenche o lado esquerdo com vermelho
bmp.fill_rect(Rect.new(50, 0, 50, 50), Color.new(0, 0, 255)) # Preenche o lado direito com azul
# Cria 2 sprites
sprite1 = Sprite.new
sprite1.x = 0
sprite1.y = 0
sprite2 = Sprite.new
sprite2.x = 200
sprite2.y = 200
# Associa o mesmo Bitmap às duas Sprites
sprite1.bitmap = bmp
sprite2.bitmap = bmp
# Troca a região do Bitmap que as sprites irão exibir
sprite1.src_rect = Rect.new(0, 0, 50, 50) # Exibe apenas o lado esquerdo do bitmap
sprite2.src_rect = Rect.new(50, 0, 50, 50) # Exibe apenas o lado direito do bitmap
Basicamente, se você pudesse ver a memória do jogo e ver o Bitmap da variável bmp, ele seria algo como isso (no momento):
Se você rodar o código acima, vai ter como resultado algo aproximado do seguinte:
Agora veja o seguinte: lembra que as duas sprites estão com o mesmo Bitmap, certo?
Isso significa que se você fizer...:
Código:
bmp.fill_rect(Rect.new(15, 15, 70, 20), Color.new(0, 255, 0)) # Preenche uma faixa verde no meio da imagem
O Bitmap ficará da seguinte forma:
E por resultado:
Perceba que nada foi alterado (diretamente, via código) nas sprites, mas sim no bitmap, e isso alterou a mesma coisa para as duas. RPG Maker usa algo parecido com ícones e algumas outras coisas, a fim de que você não fique com bitmaps repetidos na memória. Inclusive, se em vez de usar bmp.fill_rect você usar sprite1.bitmap.fill_rect, obterá os mesmos resultados, porque a
referência do bitmap é a mesma (se não quiser guardar a mesma referência na sprite2, e sim uma cópia, só usar
sprite2.bitmap = bmp.clone, que o .clone vai tratar de fazer uma cópia).
Agora respondendo tópico a tópico:
Assim que eu crio um novo Sprite ele automaticamente aparece no jogo? Ou tem que, sei la, estar associado a algum evento?
Sim, só por dar um Sprite.new a sprite já vai aparecer automaticamente. Se não quiser que isso acontece, simplesmente use sprite.visible = false. Lembre-se de que isso não é o caso de Bitmaps.
Digamos que eu tenha todo um iconset, mas eu quero pegar só um certo ícone para estar no sprite, que tem tamanho (w, h) e está nas coordenadas (x, y) da imagem. Como faço isso?
Como falei, as sprites possuem um atributo "src_rect", que é da classe Rect e que diz qual parte do Bitmap da sprite que vai ser exibida por aquela sprite. Se você quiser que a sprite
seja o ícone, faça algo como:
Código:
sprite = Sprite.new
sprite.bitmap = Cache.system("iconset.png")
sprite.src_rect = Rect.new(x, y, w, h) # o (x, y) e (w, h) que você se referia
Se você tem um bitmap e quer "pintar" o ícone em um canto dela, use o método
blt(x, y, bitmap, src_rect) (ou
stretch_blt(dest_rect, bitmap, src_rect), caso queira esticar/encolher o ícone por um determinado retângulo), que copia um bitmap para parte de outro nas coordenadas especificadas:
Código:
sprite.bitmap.blt(4, 4, Cache.system("iconset.png"), Rect.new(x, y, w, h)) # o (x, y) e (w, h) que você se referia
Isso irá copiar o retângulo (x, y, w, h) do iconset para o bitmap já existente da sprite
Se quiser dar uma checada nos métodos do bitmap: http://www.rpg-maker.fr/dl/monos/aide/vx/source/rgss/gc_bitmap.html
Sobre bitmaps. Eu queria tirar uma screen do jogo com o Graphics.snap_to_bitmap e depois salvar num arquivo. Mas não quero salvar uma screen toda, só uma parte dela, um retângulo (x, y, w, h). Como faz?
Quanto a isso não tem muita saída, não há um método padrão. O que você pode fazer é usar este script: http://forums.rpgmakerweb.com/index.php?/topic/21633-bitmap-export/
E no caso fazer:
Código:
bitmap = Bitmap.new(w, h)
bitmap.blt(0, 0, Graphics.snap_to_bitmap, Rect.new(x, y, w, h))
bitmap.export("meu_print.png")
Por enquanto é isso, espero ter sanado suas dúvidas.
Minha sugestão quanto a coisas da 1ª dúvida é fazer scripts curtos como o que fiz para testar e respondê-la:
Código:
class Scene_SpriteTest < Scene_Base
def start
super
@sprite = Sprite.new
@sprite.bitmap = Bitmap.new(50, 50)
@sprite.bitmap.fill_rect(Rect.new(0, 0, 50, 50), Color.new(255, 0, 0))
end
end
Aí só criei um evento no mapa que chamasse o script:
Código:
SceneManager.call(Scene_SpriteTest)
"Falei" com o evento e minha scene apareceu com a sprite ali, mesmo sem dar @sprite.update nem nada