This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Spawner | |
Classes.CrabAttachment_CrabAttachment_BeamBlasterSpawner = Class(CrabAttachmentSpawner) | |
CrabAttachment_CrabAttachment_BeamBlasterSpawner.spawnClassName = "CrabAttachment_BeamBlaster" | |
-- Enemy | |
Classes.CrabAttachment_BeamBlaster = Class(CrabAttachment) | |
function CrabAttachment_BeamBlaster:SetupActiveState() | |
self.animSetBottom = { | |
disarmed = "CrabGiant_Laser_Idle", | |
arming = "CrabGiant_Laser_Warmup", | |
armed = "CrabGiant_Laser_Ready", | |
blastStart = "CrabGiant_Laser_Ready", | |
blasting = "CrabGiant_Laser_Ready", | |
blastStop = "CrabGiant_Laser_Cooldown", | |
} | |
self.animSetTop = { | |
disarmed = "CrabGiant_Laser_Top", | |
arming = "CrabGiant_Laser_Top", | |
armed = "CrabGiant_Laser_Top", | |
blastStart = "CrabGiant_Laser_Top", | |
blasting = "CrabGiant_Laser_Top", | |
blastStop = "CrabGiant_Laser_Top", | |
} | |
self.blasterBottomSprite = self:Sprite(self.animSetBottom.disarmed, self.defLayer, 0) | |
self.blasterTopSprite = self:Sprite(self.animSetTop.disarmed, self.defLayer, 15) | |
self:AddPiece(self.blasterBottomSprite) | |
self:AddPiece(self.blasterTopSprite) | |
self.armed = false | |
end | |
function CrabAttachment_BeamBlaster:Arm(finishFunc) | |
FadeOutDestroyComponent(self, "chargeAc", 0.15) | |
self:DelayCall(0.6, self.activeMachine, function() | |
self.chargeAc = game.loopManager:PlaySound("crabLaserCharge", 1, Vec2(0, 0)) | |
self.machine:Add(function() | |
FadeOutDestroyComponent(self, "chargeAc", 0.15) | |
end) | |
self:PlayAnim(self.blasterBottomSprite, self.animSetBottom.arming) | |
self:PlayAnim(self.blasterTopSprite, self.animSetTop.arming, self.machine, function() | |
self:PlayAnim(self.blasterBottomSprite, self.animSetBottom.armed) | |
self:PlayAnim(self.blasterTopSprite, self.animSetTop.armed) | |
self.emitter = self:Emitter("BurnyParticlesBurstBeam2", self.defLayer, 13, Vec2(0, 28)) | |
self.emitter.palette = "Pink" | |
self:AddPiece(self.emitter) | |
self.armed = true | |
CallCallback(finishFunc) | |
end) | |
end) | |
end | |
local jPatternDef = | |
Bp_Shoot(11, | |
function(pattern, i, num) | |
pattern.dir = Vec2(0, -1) | |
local alpha = (i - 1) / (num - 1) | |
alpha = alpha < 0 and 0 or alpha > 1 and 1 or alpha | |
pattern.offset = Vec2(alpha * 64 - 32, 0) / 32 | |
pattern.speed = 160 + (1 - math.abs(alpha - 0.5) * 2) * 40 | |
end, | |
Sp_UseDef(BaseEnemy.unvauntableBulletDef) | |
) | |
function CrabAttachment_BeamBlaster:DoBlast(finishFunc) | |
if game.gameSessionInfo.difficulty == "judgement" then | |
self.activeMachine:Add(self:StartBulletPattern(jPatternDef, Vec2(0, 0))) | |
end | |
FadeOutDestroyComponent(self, "chargeAc", 0.15) | |
self.fireAc = game.loopManager:PlaySound("crabLaserFire", 1, Vec2(0, 0)) | |
self.activeMachine:Add(function() | |
FadeOutDestroyComponent(self, "fireAc", 0.15) | |
end) | |
local beamSet = BeamSpecial.beamSetBurst | |
local laserOffset = Vec2(0, 28) | |
local laser = self.activeMachine:Add(self:CreateLaser({ laserOffset = laserOffset, beamSet = beamSet, })) | |
laser.scale = Vec2(0.2, 1) | |
self:AddPiece(laser) | |
local attachTick = self.activeMachine:Add(Tick{ | |
owner = self, | |
tickWorld = self.world.postPhysTickWorld, | |
priority = 2000, | |
func = function(dt) | |
laser.pos = self.phys.pos * 32 + laserOffset | |
end, | |
}) | |
local maxWidth = 50 | |
local maxScale = maxWidth / beamSet.width | |
local attackDur, sustainDur, releaseDur = 0.08, 0.25, 0.2 | |
local sync = Synchronizer{} | |
sync:Add(self.blasterTopSprite) | |
self:InterpLaser(laser, maxScale, attackDur, sustainDur, releaseDur, function(state) | |
if state == 'attack' then | |
self:PlayAnim(self.blasterBottomSprite, self.animSetBottom.blastStart) | |
self:PlayAnim(self.blasterTopSprite, self.animSetTop.blastStart, self.machine, function() | |
self:PlayAnim(self.blasterBottomSprite, self.animSetBottom.blasting) | |
self:PlayAnim(self.blasterTopSprite, self.animSetTop.blasting) | |
end) | |
elseif state == 'release' then | |
DestroyComponent(self, "emitter") | |
self:PlayAnim(self.blasterBottomSprite, self.animSetBottom.blastStop) | |
self:PlayAnim(self.blasterTopSprite, self.animSetTop.blastStop, self.machine, function() | |
self:PlayAnim(self.blasterBottomSprite, self.animSetBottom.blastStop) | |
self:PlayAnim(self.blasterTopSprite, self.animSetTop.blastStop, self.machine, function() sync:Remove(self.blasterTopSprite) end) | |
end) | |
elseif state == 'finish' then | |
laser:Destroy() | |
self.armed = false | |
self:PlayAnim(self.blasterBottomSprite, self.animSetBottom.disarmed) | |
self:PlayAnim(self.blasterTopSprite, self.animSetTop.disarmed) | |
FadeOutDestroyComponent(self, "fireAc", 0.15) | |
sync:Sync(finishFunc) | |
end | |
end) | |
end | |
function CrabAttachment_BeamBlaster:Blast(finishFunc) | |
self:DoBlast(finishFunc) | |
end | |
function CrabAttachment_BeamBlaster:Active_FireState(finishFunc) | |
if not self.armed then | |
self:Arm(finishFunc) | |
else | |
self:Blast(finishFunc) | |
end | |
end | |
function CrabAttachment_BeamBlaster:CreateLaser(beamInfo) | |
local layer = self.defLayer | |
local laser = Laser{ | |
world = self.world, | |
width = beamInfo.beamSet.width, | |
segmentAnims = beamInfo.beamSet.animSet, | |
segmentLength = 16, | |
centralBlockMask = self.world.physWorld:Filter("enemy", "obstruction"), | |
blockMask = 0, | |
hitMask = COLLISION_MASK_ENEMY_BULLET, | |
minLength = 512, | |
maxLength = 512, | |
numTraces = beamInfo.beamSet.numTraces, | |
speed = 640, | |
pos = self.phys.pos * 32 + beamInfo.laserOffset, | |
dir = Vec2(0, -1), | |
layer = self.world.layers:Get(self.defLayer), | |
depth = self.depth + 1, | |
cap = beamInfo.beamSet.cap, | |
capBlocked = beamInfo.beamSet.capBlocked, | |
palette = "Pink", | |
blockFunc = function(hitShape) return false end, | |
hitFunc = function(hitShape) | |
local ud = hitShape.userdata | |
local mt = getmetatable(ud) | |
if ud and IsChildOf(mt, PlayerShip) and not ud.__destroyed and not ud.invincible and hitShape ~= ud.shape then | |
ud:Die(self) | |
end | |
end, | |
} | |
return laser | |
end | |
function CrabAttachment_BeamBlaster:InterpLaser(laser, maxScale, attackDur, sustainDur, releaseDur, stateFunc) | |
assert(stateFunc) | |
local function InterpLaserOut(t) | |
local scale = self:Ease(t, 0.01, maxScale, "outQuad") | |
laser.scale = Vec2(scale, 1) | |
end | |
local function InterpLaserIn(t) | |
local scale = self:Ease(t, maxScale, 0.01, "inExpo") | |
laser.scale = Vec2(scale, 1) | |
end | |
stateFunc('attack') | |
self:Interp(attackDur, self.activeMachine, InterpLaserOut, function() | |
stateFunc('sustain') | |
self:DelayCall(sustainDur, self.activeMachine, function() | |
stateFunc('release') | |
self:Interp(releaseDur, self.activeMachine, InterpLaserIn, function() stateFunc('finish') end) | |
end) | |
end) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment