Téléporteur

Effet de téléportation avec Solar2D

Présentation

Voila (plus ou moins) le code utilisé pour gérer l'effet de téléportation dans notre jeu (vous savez quand Mario entre dans un tuyau et réapparait un peu plus loin).
Il est à noter que l'effet SumBeams ne fonctionne pas sur tous les téléphones.
Mon Samsung Galaxy J3 d'ailleurs ne le gère pas. Il va donc falloir que je fasse une version dégradée pour les vieux téléphones.

Pour savoir si votre mobile gère cet effet, vous devrez faire un appel à la fonction system.getInfo("gpuSupportsHighPrecisionFragmentShaders")

_G.frame = 0                                                                    -- Le compteur de Frame
_G.bTeleportRunning = false -- Le teleporteur fonctionne t-il ?
_G.teleportFrame = 0 -- Le compteur de frame de l'animation
_G.teleportPart = 0 -- L'animation est en 3 parties.
_G.teleSpeed1 = 45
_G.teleSpeed2 = 45
_G.telePoint = {x = 0, y = 0}

local image1, image2 = "world1.jpg", "world2.jpg"
local oBack, oOver = nil, nil

local cntWidth = display.contentWidth -- largeur de l'écran virtuel
local cntHeight = display.contentHeight -- hauteur de l'ecran virtuel
local cntX = display.contentCenterX -- centre X et Y de l'écran virtuel
local cntY = display.contentCenterY

local oSnapshot = display.newSnapshot(cntWidth, cntHeight) -- on crée un Snapshot
oSnapshot.x, oSnapshot.y = cntX, cntY
oSnapshot.isVisible = false

local oBlackScreen = display.newRect(0, 0, cntWidth, cntHeight) -- on crée un rectangle noir
oBlackScreen:setFillColor( 0, 0, 0 )
oBlackScreen.isVisible = false
oSnapshot.group:insert(oBlackScreen) -- qu'on insère dans le Snapshot

local oSB = display.newRect(0, 0, cntWidth, cntHeight) -- on crée le sunBeams
oSB.fill.effect = "generator.sunbeams"
oSB.fill.effect.posX = 0.5
oSB.fill.effect.posY = 0.5
oSB.fill.effect.aspectRatio = ( oSB.width / oSB.height )
oSB.fill.effect.seed = 0
oSnapshot.group:insert(oSB) -- qu'on insère dans le Snapshot (au dessus du rectangle noir)

local oMask = graphics.newMask("telemask.png") -- le mask utile pour la deuxième partie du teleporteur

function loadImages()
if oBack then oBack:removeSelf() end
oBack = display.newImage(image1, cntWidth, cntHeight) -- on charge l'image 1
oBack.x, oBack.y = cntX, cntY -- que l'on place au centre
oBack.isVisible = true
oBack:toBack()

if oOver then oOver:removeSelf() end
oOver = display.newImage(image2, cntWidth, cntHeight) -- on charge l'image 2
oOver.x, oOver.y = cntX, cntY -- que l'on place au centre
oOver.isVisible = false
oOver:toFront()

image1, image2 = image2, image1 -- inversion des images
end

local fireBcl = function( event )
_G.frame = _G.frame + 1

if _G.bTeleportRunning then -- Téléportation Mr Spock
if _G.teleportPart == 0 then -- Première partie: passage au blanc avec le sunBeams
local deltaFrame = _G.frame - _G.teleportFrame
if deltaFrame == 1 then -- Afin de rendre l'écran noir
oSB.x = _G.telePoint.x
oSB.y = _G.telePoint.y
oSB.xScale = 0.01
oSB.yScale = 0.01
end

oSnapshot:invalidate() -- On fait grossir le SunBeams jusqu'à ce sa partie blanche
local coef = deltaFrame / _G.teleSpeed1 -- couvre tout l'écran
coef = coef * coef + 0.0001
local scale = coef * 20
oSB.xScale = scale
oSB.yScale = scale
oSB.rotation = deltaFrame * 7
oOver.isVisible = false
oSnapshot.fill.effect = ""
oSnapshot.isVisible = true
if deltaFrame == _G.teleSpeed1 - 1 then
_G.teleportPart = 1 -- L'écran est blanc on passe à la partie 2 !
_G.teleportFrame = _G.frame
end
elseif _G.teleportPart == 1 then -- Deuxième partie: negatif du sunbeams et halo transparent
local deltaFrame = _G.frame - _G.teleportFrame -- Dans cette partie, on va prendre le negatif du SunBeams
if deltaFrame == 1 then -- Afin de rendre l'écran noir
oBlackScreen.isVisible = true -- Et en même temps on va masquer le résultat pour faire apparaitre
oBack.isVisible = false -- La deuxième image.
oOver.isVisible = true
end

oSnapshot:invalidate()
local coef = deltaFrame / _G.teleSpeed2
coef = coef * coef * coef + 0.0001
local scale = coef * 50
oSB.xScale = scale
oSB.yScale = scale
oSB.rotation = deltaFrame * 7

oSnapshot.fill.effect = "filter.invert"
oSnapshot.isVisible = true

oOver:setMask(oMask)
oOver.maskX = _G.telePoint.x
oOver.maskY = _G.telePoint.y
oOver.maskScaleX = coef * 5
oOver.maskScaleY = coef * 5
if deltaFrame == _G.teleSpeed2 - 1 then
_G.teleportPart = 2
_G.teleportFrame = _G.frame
end
else -- Fin de l'animation
loadImages() -- On echange les deux images

_G.bTeleportRunning = false -- Et on remets tous les états à zero !
oSnapshot.isVisible = false
oBlackScreen.isVisible = false
end
end
end


local fireStart = function(event) -- Dès qu'on touche l'écran
if not _G.bTeleportRunning then -- Si on est pas déjà en cours de téléportation
_G.telePoint.x = event.x - display.contentCenterX
_G.telePoint.y = event.y - display.contentCenterY

_G.teleportFrame = _G.frame
_G.teleportPart = 0
_G.bTeleportRunning = true
end
end

loadImages()

Runtime:addEventListener( "tap", fireStart )
Runtime:addEventListener( "enterFrame", fireBcl )

Téléchargement

Vous pouvez télécharger l’archive du projet fonctionnant sous Solar2D

Commentaires