mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-18 19:54:21 +02:00
G2 support
This commit is contained in:
@@ -0,0 +1,456 @@
|
||||
-- The egg hatch cutscene: engine/pokemon/breeding.asm
|
||||
-- EggHatch_AnimationSequence, the beat HatchEggs runs between "Huh?" and
|
||||
-- "<NAME> came out of its EGG!".
|
||||
--
|
||||
-- The sequence, in the cart's own order:
|
||||
--
|
||||
-- 1. `ld de, MUSIC_NONE / call PlayMusic`, then BlankScreen and DisableLCD.
|
||||
-- isOpaque is therefore correct: the map really is torn down.
|
||||
-- 2. EggHatchGFX's two tiles to vTiles0, the hatchling's frontpic to
|
||||
-- vTiles2 $00 and the EGG's to $31.
|
||||
-- 3. MUSIC_EVOLUTION, EnableLCD, and the EGG pic laid at hlcoord 7, 4.
|
||||
-- 4. `ld c, 80 / call DelayFrames`: the egg just sits there.
|
||||
-- 5. Eight rounds. Round r wobbles r times -- each wobble is hSCX = +2 for
|
||||
-- two frames then -2 for two frames, with wGlobalAnimXOffset carrying the
|
||||
-- sprites the same way so the cracks stay on the shell -- then sixteen
|
||||
-- still frames, then EggHatch_CrackShell.
|
||||
-- 6. SFX_EGG_HATCH, ten shell fragments, the HATCHLING's pic at hlcoord 6, 3,
|
||||
-- then Hatch_ShellFragmentLoop's 129 frames, WaitSFX and PlayMonCry.
|
||||
--
|
||||
-- The two sprite objects are built here rather than in
|
||||
-- src/ui/gen2/SpriteAnims.lua because both are one 8x8 tile with a fixed
|
||||
-- frameset (data/sprite_anims/framesets.asm .Frameset_EggCrack and
|
||||
-- .Frameset_EggHatch1..4 are each a single `oamframe ..., 32 / oamend`) and
|
||||
-- only ONE of the two moves at all. Coordinates follow the same convention
|
||||
-- every other caller of _InitSpriteAnimStruct uses (engine/sprite_anims/
|
||||
-- core.asm:113, "at pixel x=e, y=d"), and OAM's own -8 / -16 bias is applied
|
||||
-- at draw time exactly as src/ui/gen2/GoldSilverIntro.lua does it.
|
||||
--
|
||||
-- Every asset is optional. A cache built before the extractor grew
|
||||
-- menu_gfx.eggHatch has no egg pic and no shell tiles, and the screen then
|
||||
-- runs the same clock with whatever it does have -- which is the timing beat
|
||||
-- src/world/gen2/World.lua's hatch path used to stand in for on its own.
|
||||
|
||||
local Assets = require("src.render.Assets")
|
||||
local Chrome = require("src.ui.gen2.Chrome")
|
||||
local GbcPalette = require("src.render.GbcPalette")
|
||||
local Music = require("src.core.Music")
|
||||
local Palettes = require("src.world.gen2.Palettes")
|
||||
local Sound = require("src.core.Sound")
|
||||
local SpriteAnims = require("src.ui.gen2.SpriteAnims")
|
||||
|
||||
local EggHatchAnim = {}
|
||||
EggHatchAnim.__index = EggHatchAnim
|
||||
EggHatchAnim.isOpaque = true
|
||||
|
||||
local SCREEN_W, SCREEN_H = 160, 144
|
||||
|
||||
-- Hatch_UpdateFrontpicBGMapCenter is called twice with different hlcoords:
|
||||
-- the egg sits at (7,4) and the hatchling at (6,3). Both are `lb bc, 7, 7`
|
||||
-- PlaceGraphic boxes, and the pic inside that box has already been padded to
|
||||
-- 7x7 in VRAM, so a 40x40 egg and a 56x56 mon share a ground line.
|
||||
local EGG_TILE_X, EGG_TILE_Y = 7, 4
|
||||
local MON_TILE_X, MON_TILE_Y = 6, 3
|
||||
|
||||
-- PadFrontpic (engine/gfx/load_pics.asm:342) fills the 7x7 box column by
|
||||
-- column: one whole blank column first, then per pic column a fixed run of
|
||||
-- blank tiles above the pic tiles. `.six` fills one tile per column and
|
||||
-- `.five` two, so the pic's top-left tile lands at (1,1) and (1,2)
|
||||
-- respectively and a 7-wide pic fills the box. Same table, for the same
|
||||
-- reason, as src/ui/gen2/SummaryMenu.lua:120.
|
||||
local PIC_PAD = { [7] = { 0, 0 }, [6] = { 1, 1 }, [5] = { 1, 2 } }
|
||||
|
||||
-- `ld c, 80 / call DelayFrames` between the egg appearing and the first wobble.
|
||||
local HOLD_FRAMES = 80
|
||||
-- `.outerloop`'s `cp 8`: rounds 0..7, so eight of them, and round r (1-based)
|
||||
-- wobbles r times because `ld e, [hl]` reads the counter AFTER `inc [hl]`.
|
||||
local ROUNDS = 8
|
||||
-- Each half of a wobble is `ld c, 2 / call DelayFrames`, i.e. two frames.
|
||||
local WOBBLE_HALF = 2
|
||||
-- `ld a, 2 / ldh [hSCX]` then `ld a, -2`: the screen shifts two pixels.
|
||||
local SHAKE = 2
|
||||
-- `ld c, 16 / call DelayFrames` after the wobbles of a round.
|
||||
local STILL_FRAMES = 16
|
||||
-- Hatch_ShellFragmentLoop's `ld c, 129`.
|
||||
local FRAGMENT_FRAMES = 129
|
||||
|
||||
-- Hatch_InitShellFragments' .SpriteData, one row per `shell_fragment`. The
|
||||
-- macro emits two coordinate bytes and Hatch_InitShellFragments loads the first
|
||||
-- into e and the second into d, which _InitSpriteAnimStruct reads as x and y
|
||||
-- respectively -- the same pairing `depixel` produces for every other object.
|
||||
-- `frameset` is the offset from SPRITE_ANIM_FRAMESET_EGG_HATCH_1, and the four
|
||||
-- framesets differ only in their OAM flip flags (data/sprite_anims/framesets
|
||||
-- .asm:360-374): 1 plain, 2 X-flipped, 3 Y-flipped, 4 both.
|
||||
local FRAGMENTS = {
|
||||
{ x = 10 * 8 + 4, y = 9 * 8, flipX = false, flipY = false, angle = 0x3c },
|
||||
{ x = 11 * 8 + 4, y = 9 * 8, flipX = true, flipY = false, angle = 0x04 },
|
||||
{ x = 10 * 8 + 4, y = 10 * 8, flipX = false, flipY = false, angle = 0x30 },
|
||||
{ x = 11 * 8 + 4, y = 10 * 8, flipX = true, flipY = false, angle = 0x10 },
|
||||
{ x = 10 * 8 + 4, y = 11 * 8, flipX = false, flipY = true, angle = 0x24 },
|
||||
{ x = 11 * 8 + 4, y = 11 * 8, flipX = true, flipY = true, angle = 0x1c },
|
||||
{ x = 10 * 8, y = 9 * 8 + 4, flipX = false, flipY = false, angle = 0x36 },
|
||||
{ x = 12 * 8, y = 9 * 8 + 4, flipX = true, flipY = false, angle = 0x0a },
|
||||
{ x = 10 * 8, y = 10 * 8 + 4, flipX = false, flipY = true, angle = 0x2a },
|
||||
{ x = 12 * 8, y = 10 * 8 + 4, flipX = true, flipY = true, angle = 0x16 },
|
||||
}
|
||||
|
||||
-- AnimSeq_RevealNewMon: var1 starts at 0 and grows by 8 a frame until it
|
||||
-- reaches $80, at which point DeinitializeSprite drops the fragment. Sixteen
|
||||
-- frames of flight, then the hatchling stands alone for the rest of the loop.
|
||||
local FRAGMENT_STEP = 8
|
||||
local FRAGMENT_LIMIT = 0x80
|
||||
|
||||
-- Both egg objects use .OAMData_1x1_Palette0, whose single entry is
|
||||
-- `dbsprite -1, -1, 4, 4, $00, 0` (data/sprite_anims/oam.asm:94-95, 112-114).
|
||||
-- dbsprite folds tile and pixel into one byte, so that is a per-object -4 on
|
||||
-- each axis, added by UpdateAnimFrame through AddOrSubtractX/Y on top of the
|
||||
-- struct coordinate (engine/sprite_anims/core.asm:240-266). The flip arm
|
||||
-- computes `-8 - a`, which for a = -4 is -4 again, so the one constant covers
|
||||
-- all four framesets. The remaining -8 / -16 is the hardware's own OAM bias,
|
||||
-- the same one every other Gold screen applies on its way out.
|
||||
local OAM_X = -8 - 4
|
||||
local OAM_Y = -16 - 4
|
||||
|
||||
function EggHatchAnim:wantsFillScale() return true end
|
||||
function EggHatchAnim:drawsWidescreen() return true end
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Construction
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- opts:
|
||||
-- mon the hatchling's party record (species, shiny, nickname)
|
||||
-- species the hatchling's species, when there is no record to hand
|
||||
-- onDone() the beat after PlayMonCry
|
||||
function EggHatchAnim.new(game, opts)
|
||||
opts = opts or {}
|
||||
local self = setmetatable({}, EggHatchAnim)
|
||||
self.game = game
|
||||
self.data = (game and game.data) or {}
|
||||
self.palettes = self.data.gen2Palettes
|
||||
self.mon = opts.mon
|
||||
self.species = opts.species or (self.mon and self.mon.species)
|
||||
self.onDone = opts.onDone
|
||||
|
||||
local gfx = (opts.menuGfx or self.data.gen2MenuGfx or {}).eggHatch or {}
|
||||
self.eggPath = gfx.egg
|
||||
self.shellPath = gfx.shell
|
||||
self.picCache = {}
|
||||
self.shell = nil
|
||||
self.shellQuads = nil
|
||||
|
||||
-- The screen starts on the egg and only swaps to the hatchling at `.done`,
|
||||
-- which is the one thing a viewer has to be able to see happen.
|
||||
self.showMon = false
|
||||
self.shakeX = 0
|
||||
self.sprites = {}
|
||||
|
||||
-- `ld de, MUSIC_NONE / call PlayMusic` and then MUSIC_EVOLUTION, with the
|
||||
-- map theme handed back by HatchEggs' own RestartMapMusic afterwards.
|
||||
Music.stop()
|
||||
local songs = self.data.audio and self.data.audio.songs
|
||||
if songs and songs.Music_Evolution then
|
||||
Music.play(self.data, "Music_Evolution", true, { reason = "hatch" })
|
||||
end
|
||||
|
||||
self.beats = self:buildBeats()
|
||||
self.beatIndex = 1
|
||||
self.beatLeft = self.beats[1] and self.beats[1].frames or 0
|
||||
self:runBeat(self.beats[1])
|
||||
return self
|
||||
end
|
||||
|
||||
-- The whole sequence as a flat list of { frames, enter }. Building it up front
|
||||
-- rather than nesting phase machines is what keeps the frame counts readable
|
||||
-- against the ASM: every number here is one `DelayFrames` operand.
|
||||
function EggHatchAnim:buildBeats()
|
||||
local beats = {}
|
||||
local function beat(frames, enter)
|
||||
beats[#beats + 1] = { frames = frames, enter = enter }
|
||||
end
|
||||
|
||||
beat(HOLD_FRAMES, function() self.shakeX = 0 end)
|
||||
|
||||
for round = 1, ROUNDS do
|
||||
for _ = 1, round do
|
||||
beat(WOBBLE_HALF, function() self.shakeX = SHAKE end)
|
||||
beat(WOBBLE_HALF, function() self.shakeX = -SHAKE end)
|
||||
end
|
||||
beat(STILL_FRAMES, function() self.shakeX = 0 end)
|
||||
beat(0, function() self:crackShell(round) end)
|
||||
end
|
||||
|
||||
-- `.done`: hSCX and wGlobalAnimXOffset are zeroed, ClearSprites drops the
|
||||
-- cracks, the fragments go up and the pic becomes the hatchling's.
|
||||
beat(FRAGMENT_FRAMES, function()
|
||||
self.shakeX = 0
|
||||
self.sprites = {}
|
||||
self:playSfx("Sfx_EggHatch")
|
||||
self:initFragments()
|
||||
self.showMon = true
|
||||
end)
|
||||
-- WaitSFX then `ld a, [wJumptableIndex] / call PlayMonCry`. The port has no
|
||||
-- channel state to poll, so the cry simply follows the loop.
|
||||
beat(0, function() self:playCry() end)
|
||||
return beats
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Sound
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
function EggHatchAnim:playSfx(name)
|
||||
local sfx = self.data.audio and self.data.audio.sfx
|
||||
if sfx and sfx[Sound.resolve(self.data, name)] then
|
||||
Sound.play(self.data, name)
|
||||
end
|
||||
end
|
||||
|
||||
function EggHatchAnim:playCry()
|
||||
local species = self.species
|
||||
if not species then return end
|
||||
local cries = self.data.audio and self.data.audio.cries
|
||||
if cries and cries[species] then Sound.playCry(self.data, species) end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- The two sprite objects
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- EggHatch_CrackShell (breeding.asm:756). wFrameCounter has already been
|
||||
-- incremented, so `dec a / and $7` is the round index 0..7; `cp $7 / ret z`
|
||||
-- drops the last round and `srl a / ret nc` drops every even one, leaving
|
||||
-- rounds 2, 4 and 6. The surviving index picks the y coordinate:
|
||||
-- `swap a / srl a` is a multiply by eight, and `add 9 * TILE_WIDTH` puts the
|
||||
-- first crack on tile row 9. x is the fixed `ld e, 11 * TILE_WIDTH`.
|
||||
function EggHatchAnim:crackShell(round)
|
||||
local a = (round - 1) % 8
|
||||
if a == 7 then return end
|
||||
if a % 2 == 0 then return end
|
||||
local step = math.floor(a / 2)
|
||||
self.sprites[#self.sprites + 1] = {
|
||||
kind = "crack",
|
||||
x = 11 * 8,
|
||||
y = step * 8 + 9 * 8,
|
||||
}
|
||||
self:playSfx("Sfx_EggCrack")
|
||||
end
|
||||
|
||||
-- Hatch_InitShellFragments, then the SFX_EGG_HATCH it ends on (which the
|
||||
-- caller's `.done` has already played -- the cart plays it twice).
|
||||
function EggHatchAnim:initFragments()
|
||||
for _, row in ipairs(FRAGMENTS) do
|
||||
self.sprites[#self.sprites + 1] = {
|
||||
kind = "fragment",
|
||||
x = row.x, y = row.y,
|
||||
flipX = row.flipX, flipY = row.flipY,
|
||||
-- SPRITEANIMSTRUCT_JUMPTABLE_INDEX carries the fragment's angle, which
|
||||
-- AnimSeq_RevealNewMon flips by $20 every frame.
|
||||
angle = row.angle,
|
||||
var1 = 0,
|
||||
xOffset = 0, yOffset = 0,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
-- AnimSeq_RevealNewMon (engine/sprite_anims/functions.asm:1270), one frame:
|
||||
-- the amplitude grows by eight, the angle is XORed with $20, and the sine and
|
||||
-- cosine of that pair become the fragment's y and x offsets. So each shard
|
||||
-- alternates between two opposite headings while drifting further out, which
|
||||
-- is what reads as tumbling.
|
||||
local function stepFragment(sprite)
|
||||
if sprite.var1 >= FRAGMENT_LIMIT then return false end
|
||||
local amplitude = sprite.var1
|
||||
sprite.var1 = sprite.var1 + FRAGMENT_STEP
|
||||
-- `xor $20` toggles bit 5, i.e. half a period of the six-bit angle. Written
|
||||
-- as a bit test rather than an operator because the engine targets LuaJIT's
|
||||
-- 5.1 semantics, where there is none.
|
||||
local angle = sprite.angle % 256
|
||||
local bit5 = math.floor(angle / 0x20) % 2
|
||||
sprite.angle = bit5 == 1 and (angle - 0x20) or (angle + 0x20)
|
||||
sprite.yOffset = SpriteAnims.sine(sprite.angle, amplitude)
|
||||
sprite.xOffset = SpriteAnims.cosine(sprite.angle, amplitude)
|
||||
return true
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Update
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
function EggHatchAnim:runBeat(beat)
|
||||
if beat and beat.enter then beat.enter() end
|
||||
end
|
||||
|
||||
function EggHatchAnim:finish()
|
||||
self.done = true
|
||||
local cb = self.onDone
|
||||
self.onDone = nil
|
||||
if cb then cb() end
|
||||
end
|
||||
|
||||
function EggHatchAnim:update(_dt)
|
||||
if self.done then return end
|
||||
|
||||
-- EggHatch_DoAnimFrame is PlaySpriteAnimations + DelayFrame, so the sprites
|
||||
-- advance on every frame the sequence spends anywhere. A fragment that has
|
||||
-- run out its amplitude leaves the screen: AnimSeq_RevealNewMon's
|
||||
-- `.finish_EggShell` is a DeinitializeSprite (engine/sprite_anims/functions
|
||||
-- .asm:1303), sixteen frames into a 129-frame loop, so the shards do not
|
||||
-- hang in mid-air for the rest of it. Cracks are never dropped here; the
|
||||
-- ClearSprites at `.done` has already emptied the list by then.
|
||||
local live = {}
|
||||
for _, sprite in ipairs(self.sprites) do
|
||||
if sprite.kind ~= "fragment" or stepFragment(sprite) then
|
||||
live[#live + 1] = sprite
|
||||
end
|
||||
end
|
||||
self.sprites = live
|
||||
|
||||
while self.beatLeft <= 0 do
|
||||
self.beatIndex = self.beatIndex + 1
|
||||
local beat = self.beats[self.beatIndex]
|
||||
if not beat then return self:finish() end
|
||||
self.beatLeft = beat.frames
|
||||
self:runBeat(beat)
|
||||
end
|
||||
self.beatLeft = self.beatLeft - 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- Draw
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
function EggHatchAnim:image(path)
|
||||
if not path then return nil end
|
||||
local cached = self.picCache[path]
|
||||
if cached == nil then
|
||||
-- `and` truncates a multi-return, so the pcall stands alone.
|
||||
local ok, image = pcall(Assets.image, path)
|
||||
cached = (ok and image) or false
|
||||
self.picCache[path] = cached
|
||||
end
|
||||
return cached or nil
|
||||
end
|
||||
|
||||
function EggHatchAnim:pic()
|
||||
if self.showMon then
|
||||
local def = self.species and self.data.pokemon
|
||||
and self.data.pokemon[self.species]
|
||||
return self:image(def and def.spriteFront)
|
||||
end
|
||||
return self:image(self.eggPath)
|
||||
end
|
||||
|
||||
-- Hatch_LoadFrontpicPal is SCGB_EVOLUTION with c = 0, i.e. the pic's own
|
||||
-- palette, and the species it is handed is whatever
|
||||
-- Hatch_UpdateFrontpicBGMapCenter was called with: EGG while the shell is up.
|
||||
-- PokemonPalettes carries a real EGG row (data/pokemon/palettes.asm:530) and
|
||||
-- _CGB_Evolution indexes straight into it through GetPlayerOrMonPalettePointer
|
||||
-- (engine/gfx/color.asm:620), so the egg gets its own cream and brown. A
|
||||
-- cache built before the extractor grew that row has no "EGG" key, and
|
||||
-- monColors returning nil then leaves the shader off and the raw shades in
|
||||
-- place, exactly as before.
|
||||
function EggHatchAnim:picColors()
|
||||
local species = self.showMon and self.species or "EGG"
|
||||
return Palettes.monColors(self.palettes, species,
|
||||
self.mon and self.mon.shiny)
|
||||
end
|
||||
|
||||
function EggHatchAnim:drawPic()
|
||||
local image = self:pic()
|
||||
if not image then return end
|
||||
local G = love.graphics
|
||||
local w = image:getWidth()
|
||||
local tx = self.showMon and MON_TILE_X or EGG_TILE_X
|
||||
local ty = self.showMon and MON_TILE_Y or EGG_TILE_Y
|
||||
-- PadFrontpic's own placement, not a centring rule: the two agree at 7 and
|
||||
-- 5 wide but a 6-wide pic sits a whole tile in, not half of one.
|
||||
local pad = PIC_PAD[math.floor(w / 8)] or PIC_PAD[7]
|
||||
local px = tx * 8 + pad[1] * 8
|
||||
local py = ty * 8 + pad[2] * 8
|
||||
G.setColor(1, 1, 1, 1)
|
||||
local colors = self:picColors()
|
||||
local function body() G.draw(image, px, py) end
|
||||
if colors and GbcPalette.available() then
|
||||
GbcPalette.with(colors, body)
|
||||
else
|
||||
body()
|
||||
end
|
||||
end
|
||||
|
||||
-- EggHatchGFX is one tile wide and two tall: tile $00 is the crack
|
||||
-- (SPRITE_ANIM_OAMSET_EGG_CRACK's `spriteanimoam $00`) and tile $01 the shell
|
||||
-- fragment (`spriteanimoam $01`), both 1x1 on OBJ palette 0.
|
||||
function EggHatchAnim:shellQuad(index)
|
||||
local image = self:image(self.shellPath)
|
||||
if not image then return nil, nil end
|
||||
if not self.shellQuads then
|
||||
self.shellQuads = {
|
||||
love.graphics.newQuad(0, 0, 8, 8, image:getDimensions()),
|
||||
love.graphics.newQuad(0, 8, 8, 8, image:getDimensions()),
|
||||
}
|
||||
end
|
||||
return image, self.shellQuads[index]
|
||||
end
|
||||
|
||||
function EggHatchAnim:drawSprites()
|
||||
if #self.sprites == 0 then return end
|
||||
local G = love.graphics
|
||||
G.setColor(1, 1, 1, 1)
|
||||
for _, sprite in ipairs(self.sprites) do
|
||||
local slot = sprite.kind == "crack" and 1 or 2
|
||||
local image, quad = self:shellQuad(slot)
|
||||
if image and quad then
|
||||
-- OAM_X / OAM_Y carry both the hardware bias and .OAMData_1x1_Palette0's
|
||||
-- own -4, and the draw call below adds the flip origin correction.
|
||||
local x = sprite.x + (sprite.xOffset or 0) + OAM_X
|
||||
local y = sprite.y + (sprite.yOffset or 0) + OAM_Y
|
||||
-- The two offsets are the bytes the ASM leaves in a, i.e. two's
|
||||
-- complement, so anything past $7f is a negative drift.
|
||||
if (sprite.xOffset or 0) > 0x7f then x = x - 256 end
|
||||
if (sprite.yOffset or 0) > 0x7f then y = y - 256 end
|
||||
local flipX, flipY = sprite.flipX, sprite.flipY
|
||||
G.draw(image, quad,
|
||||
x + (flipX and 8 or 0), y + (flipY and 8 or 0), 0,
|
||||
flipX and -1 or 1, flipY and -1 or 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- BlankScreen leaves the whole tilemap on the palette's colour 0, and nothing
|
||||
-- prints during the sequence: HatchEggs' text boxes are on either side of it.
|
||||
function EggHatchAnim:drawPanel()
|
||||
Chrome.clear()
|
||||
local G = love.graphics
|
||||
G.push()
|
||||
-- Both layers move the SAME way each wobble half (breeding.asm:707-719):
|
||||
-- `ldh [hSCX]` of +2 scrolls the viewport right, i.e. slides the background
|
||||
-- two pixels left on screen, and the paired `ld [wGlobalAnimXOffset], -2` is
|
||||
-- summed into every object's OAM x byte (engine/sprite_anims/core.asm:253
|
||||
-- -266), sliding the sprites two pixels left as well. So the cracks stay
|
||||
-- put on the shell and the whole picture shakes as one.
|
||||
G.translate(-(self.shakeX or 0), 0)
|
||||
self:drawPic()
|
||||
self:drawSprites()
|
||||
G.pop()
|
||||
G.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
function EggHatchAnim:draw()
|
||||
self:drawPanel()
|
||||
end
|
||||
|
||||
function EggHatchAnim:drawWidescreen(winW, winH)
|
||||
local G = love.graphics
|
||||
G.setColor(1, 1, 1, 1)
|
||||
G.rectangle("fill", 0, 0, winW, winH)
|
||||
local scale = Chrome.fitScale(winW, winH)
|
||||
G.push()
|
||||
G.translate(math.floor((winW - SCREEN_W * scale) / 2),
|
||||
math.floor((winH - SCREEN_H * scale) / 2))
|
||||
G.scale(scale, scale)
|
||||
self:drawPanel()
|
||||
G.pop()
|
||||
end
|
||||
|
||||
return EggHatchAnim
|
||||
Reference in New Issue
Block a user