Il template di oggi riguarda Construct 3 e YouTube. È un progetto molto semplice, pensato con l’unico obiettivo di testare l’integrazione tra questi due mondi. Il risultato è carino e permette di fare delle cose interessanti.
Come ho fatto negli ultimi progetti, sto continuando a integrare la struttura “event sheets” di C3 con i “moduli js” introdotti con la release r226 del 24 novembre 2020. Devo ammettere che mi sto trovando bene: posso scrivere funzioni abbastanza comprensibili direttamente sull’editor e nel contempo renderle facilmente utilizzabili tramite alcune funzioni di Construct 3.

Il codice JavaScript è diviso in alcuni moduli:
main.js
è molto semplice:
runOnStartup(async runtime => { globalThis.g_runtime = runtime; });
Non ricordo di averne mai parlato, ma questo è un trucco molto semplice per poter accedere a runtime
da ogni parte di Construct 3: mi serve in praticamente tutti gli script successivi.
C’è una possibile variante, ed è questa:
import * as YouTube from "./youTube.js";
runOnStartup(async runtime => {
globalThis.g_runtime = runtime;
await YouTube.LoadAPI();
});
Nell’esempio che ho pubblicato su GitHub il comando await YouTube.LoadAPI();
lo eseguo direttamente dal foglio Loader
. L’importante è che ci sia, prima o poi, nel progetto. Perché? Perché serve per caricare l’API di YouTube.
Il secondo file è globals.js
e serve per avere delle variabili globali, trasversali a tutto il progetto.
const Globals = {
ytPlayer: {},
playlist: {
askGamdev: ["k2-AfT0-V-c","JF404Smm4Og","MkNHQjBuCcE","F7j5h03W3CA","kFqpgqn1dEk","0V2d2S9j5Og","rzwJZC3cGlw", "oTm5cxZEdmU", "xkH5NemDPSY", "CxI-ptHu3rQ", "wxM7hsydzdQ", "onvs1ib98R"],
extraCredits: ["z06QR-tz1_o","dHMNeNapL1E","UvCri1tqIxQ","qxsEimJ_3bM","2xfxx27HbM4","rDjrOaoHz9s"]
}
};
export default Globals;
Voglio fare notare Globals.ytPlayer
: è un oggetto vuoto, verrà riempito più avanti in maniera dinamica, con tanti elementi quanti sono i player YouTube disegnati a schermo.
Il file successivo è quello che permette il collegamento tra YouTube e Construct 3, youTube.js
, e contiene due funzioni fondamentali: LoadAPI
e CreatePlayer
.
export function LoadAPI()
{
const scriptTag = document.createElement("script");
scriptTag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag);
return new Promise(resolve =>
{
globalThis["onYouTubeIframeAPIReady"] = resolve;
});
}
export function CreatePlayer(iframeId, eventHandlers)
{
return new Promise(resolve =>
{
if (!eventHandlers)
eventHandlers = {};
eventHandlers["onReady"] = (e => resolve(e.target));
new globalThis["YT"]["Player"](iframeId, {
"events": eventHandlers
});
});
}
La prima, LoadAPI
, inserisce il collegamento all’API di YouTube direttamente nell’header della pagina. È una funzione asincrona (restituisce una promessa) e può essere utilizzata nel loader per ritardare l’avvio del progetto fino al momento giusto.
La seconda funzione, sempre asincrona, collega un Player YouTube a un Iframe usando come riferimento l’ID dell’elemento nella pagina HTML.
Una volta importato questo nel progetto è finalmente possibile divertirsi un po’ implementando i comandi che ci servono. Lo faccio nel file videoYT.js
import * as YouTube from "./youTube.js";
import Globals from "./globals.js";
export function initializeVideo(iframeId){
Globals.ytPlayer[iframeId] = {};
Globals.ytPlayer[iframeId]["player"] = null;
}
export async function createVideo(iframeId) {
Globals.ytPlayer[iframeId]["player"] = await YouTube.CreatePlayer(iframeId, {
"onStateChange": e => { Globals.ytPlayer[iframeId]["state"] = e.data; },
"onReady": e => {}
});
return true;
};
export function cueVideoById(iframeId, videoId) { Globals.ytPlayer[iframeId]["player"].cueVideoById(videoId); }
export function loadVideoById(iframeId, videoId) { Globals.ytPlayer[iframeId]["player"].loadVideoById(videoId); }
export function loadVideoByUrl(iframeId, videoId) { Globals.ytPlayer[iframeId]["player"].loadVideoByUrl(videoId); }
export function loadPlaylist(iframeId, videoId) { Globals.ytPlayer[iframeId]["player"].loadPlaylist(Globals.playlist[videoId]); }
export function setLoopTrue(iframeId) { Globals.ytPlayer[iframeId]["player"].setLoop(true); }
export function setLoopFalse(iframeId) { Globals.ytPlayer[iframeId]["player"].setLoop(false); }
export function setShuffleTrue(iframeId) { Globals.ytPlayer[iframeId]["player"].setShuffle(true); }
export function setShuffleFalse(iframeId) { Globals.ytPlayer[iframeId]["player"].setShuffle(false); }
export function playVideo(iframeId) { Globals.ytPlayer[iframeId]["player"].playVideo(); }
export function pauseVideo(iframeId) { Globals.ytPlayer[iframeId]["player"].pauseVideo(); }
export function stopVideo(iframeId) { Globals.ytPlayer[iframeId]["player"].stopVideo(); }
export function setVolume(iframeId, volume) { Globals.ytPlayer[iframeId]["player"].setVolume(volume); }
export function mute(iframeId) { Globals.ytPlayer[iframeId]["player"].mute(); }
export function unMute(iframeId) { Globals.ytPlayer[iframeId]["player"].unMute(); }
export function lengthPlaylist(iframeId) { return Globals.ytPlayer[iframeId]["player"].getPlaylist().length; }
La prima funzione, initializeVideo(iframeId)
va eseguita una sola volta per elemento e non fa altro che inserire un riferimento al player nella variabile Globals
.
Anche createVideo(iframeId)
va lanciata solamente una volta per ogni elemento: crea un player YouTube per ogni elemento, e lo salva dentro Globals
.
Infine ci sono le varie funzioni, che richiamano quelle ufficiali di YouTube e che possono essere eseguite direttamente da Construct 3. O, meglio, lo potranno dopo aver inserito un altro file, importForEvents.js
import Globals from "./globals.js";
import * as YouTube from "./youTube.js";
import * as VideoYT from "./videoYT.js";
Questo script è anche l’unico con la proprietà Purpose
impostata su Imports for events
.
Basta, questo è tutto. Come ultima cosa i link al progetto: