Prechádzať zdrojové kódy

✨ Add new Acrofony mini game

- Fix some issues with other scripts.
Pedro Tonini Rosenberg Schneider 3 rokov pred
rodič
commit
7c4056d6cf

+ 11 - 0
index.html

@@ -6,6 +6,7 @@
 
     <title>Alfabetiza</title>
 
+    <link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Lato" />
     <link rel="stylesheet" type="text/css" href="style.css">
 
     <!-- p5Js Modules -->
@@ -31,6 +32,16 @@
     <script type="text/javascript" src="src/elements/earth/letterHunt/LetterHuntDialogue.js"></script>
     <script type="text/javascript" src="src/elements/earth/letterHunt/LetterHuntPlant.js"></script>
     <script type="text/javascript" src="src/elements/earth/letterHunt/LetterHuntGame.js"></script>
+    <!-- Acrofony -->
+    <script type="text/javascript" src="src/elements/earth/acrofony/AcrofonyLevels.js"></script>
+    <script type="text/javascript" src="src/elements/earth/acrofony/tutorial/AcrofonyTutorialDialogue.js"></script>
+    <script type="text/javascript" src="src/elements/earth/acrofony/tutorial/AcrofonyTutorial.js"></script>
+    <script type="text/javascript" src="src/elements/earth/acrofony/game/AcrofonyCardVisualEffect.js"></script>
+    <script type="text/javascript" src="src/elements/earth/acrofony/game/AcrofonyOptionCard.js"></script>
+    <script type="text/javascript" src="src/elements/earth/acrofony/game/AcrofonyQuestionCard.js"></script>
+    <script type="text/javascript" src="src/elements/earth/acrofony/game/AcrofonyGameDialogue.js"></script>
+    <script type="text/javascript" src="src/elements/earth/acrofony/game/AcrofonyGame.js"></script>
+    <script type="text/javascript" src="src/elements/earth/acrofony/AcrofonyLevelManager.js"></script>
     <!-- Rébus -->
     <script type="text/javascript" src="src/elements/earth/rebus/RebusLevels.js"></script>
     <script type="text/javascript" src="src/elements/earth/rebus/level_selector/RebusLevelButton.js"></script>

+ 2 - 1
src/elements/EelementSelector.js

@@ -18,6 +18,7 @@ class EelementSelector extends Object2D
 
     _setup()
     {
+        
         this.backButton = new Button("BackButton");
         this.backButton.setLabel("Voltar");
         this.backButton.setFontSize(30);
@@ -25,7 +26,7 @@ class EelementSelector extends Object2D
         this.backButton.setSize(110, 75);
         this.backButton.connect("mouseClicked", this, "_onBackClicked");
         this.addChild(this.backButton);
-
+        
         var buttonSize = new Vector2(1920 / 4, 1080 / 4);
         var buttonPosition = new Vector2(1920 / 2, 1080 / 2 + 100);
         var buttonMargin = new Vector2(50, 50);

+ 3 - 1
src/elements/earth/EarthMinigameSelector.js

@@ -141,7 +141,9 @@ class EarthMinigameSelector extends Object2D
 
     _onAcrofonySelected()
     {
-        console.log("Acrofony has been selected");
+        var alm = new AcrofonyLevelManager("AcrofonyLevelManager");
+        GameHandler.addRootObject(alm);
+        this.queueFree();
     }
 
     _onValise1Selected()

+ 139 - 0
src/elements/earth/acrofony/AcrofonyLevelManager.js

@@ -0,0 +1,139 @@
+class AcrofonyLevelManager extends Object2D
+{
+
+    constructor(name)
+    {
+        super(name);
+
+        /** @type {AcrofonyGame} */
+        this.curGame = null;
+        /** @type {Button} */
+        this.continueButton = null;
+        /** @type {Button} */
+        this.backButton = null;
+        /** @type {Timer} */
+        this.timer = null;
+
+        /** @type {Array} */
+        this.levels = [];
+        /** @type {Number} */
+        this.curLevel = -1;
+        /** @type {Number} */
+        this.totalPoints = 0;
+        /** @type {Number} */
+        this.totalLevels = 15;
+        /** @type {Boolean} */
+        this.doTutorial = true;
+
+        /** @type {Number} */
+        this.bgOpacity = 0;
+        /** @type {Number} */
+        this.textOpacity = 0;
+    }
+
+    _setup()
+    {
+        this.backButton = new Button("BackButton");
+        this.backButton.setLabel("Voltar");
+        this.backButton.setFontSize(30);
+        this.backButton.setPosition(20, 20);
+        this.backButton.setSize(110, 75);
+        this.backButton.connect("mouseClicked", this, "_onBackClicked");
+        this.addChild(this.backButton);
+
+        this.continueButton = new Button("ContinueButton", "Continuar");
+        this.continueButton.setPosition(1920 / 2 - this.continueButton.getSize().x / 2, 600);
+        this.continueButton.setFontSize(40);
+        this.continueButton.connect("mouseClicked", this, "_onContinueButtonMouseClicked");
+        this.continueButton.hide();
+        this.addChild(this.continueButton);
+
+        this.timer = new Timer("Timer", 2, false, true);
+        this.timer.connect("timeout", this, "_onTimerTimeout");
+        this.addChild(this.timer);
+
+        for (let i = 0; i < 45; i++)
+            this.levels.push(i + 1);
+
+        randomSeed(Date.now());
+        this.levels = shuffle(this.levels);
+
+        if (this.doTutorial)
+            this.startTutorial();
+        else
+            this.nextLevel();
+    }
+
+    _draw( /** @type {Number} */ delta, /** @type {p5.Graphics} */ db)
+    {
+        background(52);
+
+        if (this.curLevel < this.totalLevels)
+        {
+            db.fill(255);
+            db.textSize(70);
+            db.textAlign(CENTER, CENTER);
+            if (this.curLevel >= 0)
+                db.text(`Nível ${this.curLevel+1}`, 1920 / 2, 100);
+            else
+                db.text(`Tutorial`, 1920 / 2, 100);
+
+        }
+        else
+        {
+            this.timer.start();
+            db.noStroke();
+            db.fill(0, min(this.bgOpacity += 75 * delta, 200));
+            db.rectMode(CENTER);
+            db.rect(db.width / 2, db.height / 2, 1800, 600, 40, 40);
+            db.textAlign(CENTER, CENTER);
+            db.fill(255, min(this.textOpacity += 80 * delta, 255));
+            db.textSize(40);
+            db.text(`PARABÉNS, TODOS OS NÍVEIS FORAM CONCLUÍDOS\n\nVOCÊ GANHOU ${this.totalPoints} PONTOS!`, db.width / 2, db.height / 2 - 100);
+        }
+    }
+
+    startTutorial()
+    {
+        this.curGame = new AcrofonyTutorial("Tutorial");
+        this.curGame.levelData = ACROFONY_LEVELS.tutorial;
+        this.curGame.connect("endGame", this, "_onEndLevel");
+        this.addChild(this.curGame);
+    }
+
+    nextLevel()
+    {
+        this.curLevel++;
+        if (this.curGame) this.curGame.queueFree();
+        if (this.curLevel >= this.totalLevels) return;
+        this.curGame = new AcrofonyGame("AcrofonyGame");
+        this.curGame.levelData = ACROFONY_LEVELS[`level${this.levels[this.curLevel]}`];
+        this.curGame.connect("endGame", this, "_onEndLevel");
+        this.addChild(this.curGame);
+    }
+
+    _onEndLevel(points)
+    {
+        this.totalPoints += points;
+        this.nextLevel();
+    }
+
+    _onTimerTimeout()
+    {
+        this.continueButton.show();
+    }
+
+    _onContinueButtonMouseClicked()
+    {
+        var ems = new EarthMinigameSelector("EarthMinigameSelector");
+        GameHandler.addRootObject(ems);
+        this.queueFree();
+    }
+
+    _onBackClicked()
+    {
+        var ems = new EarthMinigameSelector("EarthMinigameSelector");
+        GameHandler.addRootObject(ems);
+        this.queueFree();
+    }
+}

+ 94 - 94
src/elements/earth/acrofony/AcrofonyLevels.js

@@ -1,323 +1,323 @@
 var ACROFONY_LEVELS = {
     tutorial:
     {
-        path: "assets/textures/glasses.png",
-        name: "Rrelógio",
-        syllable: ["RE", "LO", "GI"],
+        path: "assets/textures/monke.png",
+        name: "Relógio",
+        syllables: ["RE", "LO", "GI"],
     },
 
     level1:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Dedo",
-        syllable: ["DE", "DO", "DA"],
+        syllables: ["DE", "DO", "DA"],
     },
 
     level2:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Cueca",
-        syllable: ["CU", "E", "CA"],
+        syllables: ["CU", "E", "CA"],
     },
 
     level3:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Tigre",
-        syllable: ["TI", "GRE", "TO"],
+        syllables: ["TI", "GRE", "TO"],
     },
 
     level4:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Abelha",
-        syllable: ["A", "BE", "LHA"],
+        syllables: ["A", "BE", "LHA"],
     },
 
     level5:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Macaco",
-        syllable: ["MA", "CA", "CO"],
+        syllables: ["MA", "CA", "CO"],
     },
 
     level6:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Tomate",
-        syllable: ["TO", "MA", "TE"],
+        syllables: ["TO", "MA", "TE"],
     },
 
     level7:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Óculos",
-        syllable: ["Ó", "CU", "LOS"],
+        syllables: ["Ó", "CU", "LOS"],
     },
 
     level8:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Casa",
-        syllable: ["CA", "CO", "SA"],
+        syllables: ["CA", "CO", "SA"],
     },
 
     level9:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Unha",
-        syllable: ["U", "O", "NHA"],
+        syllables: ["U", "O", "NHA"],
     },
 
     level10:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Vaca",
-        syllable: ["VA", "VE", "CA"],
+        syllables: ["VA", "VE", "CA"],
     },
 
     level11:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Foca",
-        syllable: ["FO", "FA", "CA"],
+        syllables: ["FO", "FA", "CA"],
     },
 
     level12:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Mesa",
-        syllable: ["ME", "MA", "SA"],
+        syllables: ["ME", "MA", "SA"],
     },
 
     level13:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Cavalo",
-        syllable: ["CA", "LO", "VA"],
+        syllables: ["CA", "LO", "VA"],
     },
 
     level14:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Juba",
-        syllable: ["JU", "BA", "UVA"],
+        syllables: ["JU", "BA", "UVA"],
     },
 
     level15:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Pena",
-        syllable: ["PE", "NE", "NA"],
+        syllables: ["PE", "NE", "NA"],
     },
 
     level16:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Rato",
-        syllable: ["RA", "RU", "TO"],
+        syllables: ["RA", "RU", "TO"],
     },
 
     level17:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Maçã",
-        syllable: ["MA", "MI", "ÇÃ"],
+        syllables: ["MA", "MI", "ÇÃ"],
     },
 
     level18:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Chave",
-        syllable: ["CHA", "VO", "VE"],
+        syllables: ["CHA", "VO", "VE"],
     },
 
     level19:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Dominó",
-        syllable: ["DO", "MI", "NÓ"],
+        syllables: ["DO", "MI", "NÓ"],
     },
 
     level20:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Toalha",
-        syllable: ["TO", "A", "LHA"],
+        syllables: ["TO", "A", "LHA"],
     },
 
     level21:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Mato",
-        syllable: ["MA", "TO", "TU"],
+        syllables: ["MA", "TO", "TU"],
     },
 
     level22:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Telefone",
-        syllable: ["TE", "LE", "FO"],
+        syllables: ["TE", "LE", "FO"],
     },
 
     level23:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Avião",
-        syllable: ["A", "VI", "ÃO"],
+        syllables: ["A", "VI", "ÃO"],
     },
 
     level24:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Banana",
-        syllable: ["BA", "NA", "NE"],
+        syllables: ["BA", "NA", "NE"],
     },
 
     level25:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Cadeira",
-        syllable: ["CA", "DEI", "RA"],
+        syllables: ["CA", "DEI", "RA"],
     },
 
     level26:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Xícara",
-        syllable: ["XÍ", "CA", "RA"],
+        syllables: ["XÍ", "CA", "RA"],
     },
 
     level27:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Baleia",
-        syllable: ["BA", "LEI", "A"],
+        syllables: ["BA", "LEI", "A"],
     },
 
     level28:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Tatu",
-        syllable: ["TA", "TU", "TO"],
+        syllables: ["TA", "TU", "TO"],
     },
 
     level29:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Tapete",
-        syllable: ["TA", "PE", "TE"],
+        syllables: ["TA", "PE", "TE"],
     },
 
     level30:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Anel",
-        syllable: ["A", "NEL", "LA"],
+        syllables: ["A", "NEL", "LA"],
     },
 
     level31:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Batata",
-        syllable: ["BA", "TA", "TO"],
+        syllables: ["BA", "TA", "TO"],
     },
 
     level32:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Caju",
-        syllable: ["CA", "JU", "JO"],
+        syllables: ["CA", "JU", "JO"],
     },
 
     level33:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Tesoura",
-        syllable: ["TE", "SOU", "RA"],
+        syllables: ["TE", "SOU", "RA"],
     },
 
     level34:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Cebola",
-        syllable: ["CE", "BO", "LA"],
+        syllables: ["CE", "BO", "LA"],
     },
 
     level35:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Noiva",
-        syllable: ["NO", "VA", "VI"],
+        syllables: ["NO", "VA", "VI"],
     },
 
     level36:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Uva",
-        syllable: ["U", "O", "VA"],
+        syllables: ["U", "O", "VA"],
     },
 
     level37:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Raio",
-        syllable: ["RA", "TO", "IO"],
+        syllables: ["RA", "TO", "IO"],
     },
 
     level38:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Macaco",
-        syllable: ["MA", "CO", "CA"],
+        syllables: ["MA", "CO", "CA"],
     },
 
     level39:
     {
-        path: "assets/textures/glasses.png",
-        name: "Caju",
-        syllable: ["RA", "TO", "TA"],
+        path: "assets/textures/monke.png",
+        name: "Rato",
+        syllables: ["RA", "TO", "TA"],
     },
 
     level40:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Cutia",
-        syllable: ["CU", "TI", "A"],
+        syllables: ["CU", "TI", "A"],
     },
 
     level41:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Jacaré",
-        syllable: ["JA", "CA", "RÉ"],
+        syllables: ["JA", "CA", "RÉ"],
     },
 
     level42:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Janela",
-        syllable: ["JA", "NE", "LA"],
+        syllables: ["JA", "NE", "LA"],
     },
 
     level43:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Bule",
-        syllable: ["BU", "LE", "LO"],
+        syllables: ["BU", "LE", "LO"],
     },
 
     level44:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Bala",
-        syllable: ["BA", "BO", "LA"],
+        syllables: ["BA", "BO", "LA"],
     },
 
     level45:
     {
-        path: "assets/textures/glasses.png",
+        path: "assets/textures/monke.png",
         name: "Rei",
-        syllable: ["RE", "LO", "GI"],
+        syllables: ["RE", "LO", "GI"],
     },
 }

+ 36 - 0
src/elements/earth/acrofony/game/AcrofonyCardVisualEffect.js

@@ -0,0 +1,36 @@
+class AcrofonyCardVisualEffect extends Object2D
+{
+    constructor(name)
+    {
+        super(name);
+
+        /** @type {number} */
+        this.glowIterations = 7;
+        /** @type {number} */
+        this.glowAmount = 0;
+    }
+
+    _draw( /** @type {number} */ delta, /** @type {p5.Graphics} */ db)
+    {
+        db.rectMode(CENTER);
+        if (this.parent.selected)
+        {
+            if (!this.parent.isAnswer)
+            {
+                db.fill(0, 80);
+                db.rect(0, 0, 250, 200, 10, 10);
+            }
+            else
+            {
+                db.noFill();
+                this.glowAmount = min(1.0, this.glowAmount + 0.03);
+                for (let i = 0; i < this.glowIterations; i++)
+                {
+                    db.stroke(255, 255, 100, this.glowAmount * 200 / (this.glowIterations + 1 - i));
+                    db.strokeWeight((this.glowIterations - i) * 6);
+                    db.rect(0, 0, 250, 200, 10);
+                }
+            }
+        }
+    }
+}

+ 72 - 0
src/elements/earth/acrofony/game/AcrofonyGame.js

@@ -0,0 +1,72 @@
+class AcrofonyGame extends Object2D
+{
+    constructor(name)
+    {
+        super(name);
+
+        /** @type {Object} */
+        this.levelData = ACROFONY_LEVELS.level5;
+        /** @type {Boolean} */
+        this.gameFinished = false;
+        /** @type {Number} */
+        this.points = 3;
+
+        /** @type {AcrofonyQuestionCard} */
+        this.questionCard = null;
+        /** @type {AcrofonyGameDialogue} */
+        this.dialogue = null;
+        /** @type {Object2D} */
+        this.answerCards = null;
+    }
+
+    _initSignals()
+    {
+        this.addSignal("endGame");
+    }
+
+    _setup()
+    {
+        AssetHandler.loadTexture(this.levelData.name, this.levelData.path);
+        this.questionCard = new AcrofonyQuestionCard("QuestionCard");
+        this.questionCard.thumb = AssetHandler.getTextureByName(this.levelData.name);
+        this.questionCard.imgName = this.levelData.name;
+        this.questionCard.setPosition(1920 / 2, 400);
+        this.addChild(this.questionCard);
+
+        var answers = [0, 1, 2];
+        randomSeed(Date.now());
+        answers = shuffle(answers);
+        this.answerCards = new Object2D("AnswerCards");
+        this.addChild(this.answerCards);
+        for (let i = 0; i < 3; i++)
+        {
+            var newCard = new AcrofonyOptionCard(`AnswerCard${i}`);
+            newCard.syllable = this.levelData.syllables[answers[i]] + "\n🗢";
+            newCard.setPosition((i + 1) * 1920 / 4, 900);
+            newCard.isAnswer = answers[i] == 0;
+            newCard.connect("selected", this, "_onCardSelected");
+            this.answerCards.addChild(newCard);
+        }
+
+        this.dialogue = new AcrofonyGameDialogue("AcrofonyGameDialogue");
+        this.dialogue.connect("endGame", this, "_onDialogueEndGame")
+        this.addChild(this.dialogue);
+    }
+
+    _onCardSelected( /** @type {Boolean} */ isAnswer)
+    {
+        if (!isAnswer)
+            this.points--;
+        else
+        {
+            this.gameFinished = true;
+            for (let i = 0; i < 3; i++)
+                this.answerCards.children[i].selectable = false;
+        }
+    }
+
+    _onDialogueEndGame()
+    {
+        this.emitSignal("endGame", this.points);
+    }
+}

+ 65 - 0
src/elements/earth/acrofony/game/AcrofonyGameDialogue.js

@@ -0,0 +1,65 @@
+class AcrofonyGameDialogue extends Object2D
+{
+    constructor(name)
+    {
+        super(name);
+
+        /** @type {Button} */
+        this.continueButton = null;
+        /** @type {Timer} */
+        this.timer;
+
+        /** @type {String} */
+        this.suffix = "";
+        /** @type {number} */
+        this.bgOpacity = 0;
+        /** @type {number} */
+        this.textOpacity = 0;
+    }
+
+    _initSignals()
+    {
+        this.addSignal("endGame");
+    }
+
+    _setup()
+    {
+        this.timer = new Timer("Timer", 2, false, true);
+        this.timer.connect("timeout", this, "_onTimerTimeout");
+        this.addChild(this.timer);
+
+        this.continueButton = new Button("ContinueButton", "Continuar");
+        this.continueButton.setFontSize(40);
+        this.continueButton.setPosition(1920 / 2 - this.continueButton.getSize().x / 2, 600);
+        this.continueButton.connect("mouseClicked", this, "_onContinueButtonClicked");
+        this.addChild(this.continueButton);
+        this.continueButton.hide();
+    }
+
+    _draw( /** @type {number} */ delta, /** @type {p5.Graphics} */ db)
+    {
+        if (this.parent.gameFinished)
+        {
+            this.timer.start();
+            db.noStroke();
+            db.fill(0, min(this.bgOpacity += 75 * delta, 200));
+            db.rectMode(CENTER);
+            db.rect(db.width / 2, db.height / 2, 1800, 600, 40, 40);
+            db.textAlign(CENTER, CENTER);
+            db.fill(255, min(this.textOpacity += 80 * delta, 255));
+            db.textSize(40);
+            this.parent.points > 1 ? this.suffix = "S" : this.suffix = "";
+            db.text(`PARABÉNS, NÍVEL CONCLUÍDO\n\nVOCÊ GANHOU ${this.parent.points} PONTO${this.suffix}!`, db.width / 2, db.height / 2 - 100);
+        }
+    }
+
+    _onTimerTimeout()
+    {
+        this.continueButton.show();
+    }
+
+    _onContinueButtonClicked()
+    {
+        this.emitSignal("endGame");
+    }
+}

+ 121 - 0
src/elements/earth/acrofony/game/AcrofonyOptionCard.js

@@ -0,0 +1,121 @@
+class AcrofonyOptionCard extends Object2D
+{
+    constructor(name)
+    {
+        super(name);
+
+        /** @type {String} */
+        this.syllable = "";
+        /** @type {Boolean} */
+        this.isAnswer = false;
+        /** @type {Boolean} */
+        this.selected = false;
+        /** @type {Boolean} */
+        this.selectable = true;
+        /** @type {Boolean} */
+        this.mouseOver = false;
+        /** @type  {Boolean} */
+        this.mousePress = false;
+
+        /** @type {Color} */
+        this.fillColor = new Color(200, 200, 200);
+        /** @type {Boolean} */
+        this.tweenStarted = false;
+        /** @type {Tween} */
+        this.tween = null;
+        /** @type {Timer} */
+        this.timer = null;
+    }
+
+    _initSignals()
+    {
+        this.addSignal("selected");
+    }
+
+    _setup()
+    {
+        var area = new Area2D("area", SHAPES.RECT, new Rect(250, 200), true);
+        area.connect("mouseEntered", this, "_onMouseEntered");
+        area.connect("mouseExited", this, "_onMouseExited");
+        this.addChild(area);
+
+        this.addChild(new AcrofonyCardVisualEffect("CardVfx"));
+
+        this.tween = new Tween("Tween");
+        this.tween.interpolateProperty(this, "scale", PROPERTY_TYPE.VECTOR2, Vector2.ZERO(), Vector2.ONE(), 2, TRANS_TYPE.ELASTIC, EASE_TYPE.OUT);
+        this.addChild(this.tween);
+
+        this.timer = new Timer("Timer", 1, false, true);
+        this.timer.connect("timeout", this, "_onTimerTimeout");
+        this.addChild(this.timer);
+    }
+
+    _update( /** @type {Number} */ delta)
+    {
+        if (this.visible && !this.tweenStarted)
+        {
+            this.timer.start();
+            this.tween.startAll();
+            this.tweenStarted = true;
+        }
+
+        if (this.selectable && this.mouseOver)
+        {
+            if (InputHandler.mouseIsClicked)
+            {
+                this.selected = true;
+                this.selectable = false;
+                this.emitSignal("selected", this.isAnswer);
+            }
+
+            if (InputHandler.mouseIsPressed)
+            {
+                this.scale.x = max(this.scale.x - 3.0 * delta, 0.95);
+                this.scale.y = max(this.scale.y - 3.0 * delta, 0.95);
+            }
+            else
+            {
+                this.scale.x = min(this.scale.x + 2.0 * delta, 1.2);
+                this.scale.y = min(this.scale.y + 2.0 * delta, 1.2);
+            }
+        }
+
+        else
+        {
+            this.scale.x = max(this.scale.x - 2.0 * delta, 1);
+            this.scale.y = max(this.scale.y - 2.0 * delta, 1);
+        }
+    }
+
+    _draw( /** @type {Number} */ delta, /** @type {p5.Graphics} */ db)
+    {
+        db.rectMode(CENTER);
+        db.fill(this.fillColor.getP5Color());
+        db.rect(0, 0, 250, 200, 10, 10);
+        db.textAlign(CENTER, CENTER);
+        db.fill(0);
+        db.textSize(50);
+        db.text(this.syllable, 0, 0);
+
+        if (this.selected && !this.isAnswer)
+        {
+            db.fill(0, 80);
+            db.rect(0, 0, 250, 200, 10, 10);
+        }
+    }
+
+    _onMouseEntered()
+    {
+        this.mouseOver = true;
+    }
+
+    _onMouseExited()
+    {
+        this.mouseOver = false;
+    }
+
+    _onTimerTimeout()
+    {
+        this.tween.stopAll();
+    }
+}

+ 48 - 0
src/elements/earth/acrofony/game/AcrofonyQuestionCard.js

@@ -0,0 +1,48 @@
+class AcrofonyQuestionCard extends Object2D
+{
+    constructor(name)
+    {
+        super(name);
+
+        /** @type {TextureRes} */
+        this.thumb = null;
+        /** @type {String} */
+        this.imgName = "";
+
+        /** @type {Color} */
+        this.fillColor = new Color(200, 200, 200);
+        /** @type {Tween} */
+        this.tween = null;
+    }
+
+    _setup()
+    {
+        var sprite = new Sprite2D("sprite", this.thumb);
+        sprite.width = 250;
+        sprite.height = 250;
+        sprite.setPosition(0, -75);
+        this.addChild(sprite);
+        this.scale = Vector2.ZERO();
+
+        this.tween = new Tween("Tween");
+        this.tween.interpolateProperty(this, "scale", PROPERTY_TYPE.VECTOR2, Vector2.ZERO(), Vector2.ONE(), 2, TRANS_TYPE.ELASTIC, EASE_TYPE.OUT);
+        this.addChild(this.tween);
+    }
+
+    _update( /** @type {Number} */ delta)
+    {
+        if (this.visible) this.tween.startAll();
+    }
+
+    _draw( /** @type {Number} */ delta, /** @type {p5.Graphics} */ db)
+    {
+        db.strokeWeight(10);
+        db.rectMode(CENTER);
+        db.fill(this.fillColor.getP5Color());
+        db.rect(0, 0, 300, 400, 10, 10);
+        db.textAlign(CENTER, CENTER);
+        db.fill(0);
+        db.textSize(40);
+        db.text(this.imgName, 0, 100);
+    }
+}

+ 155 - 0
src/elements/earth/acrofony/tutorial/AcrofonyTutorial.js

@@ -0,0 +1,155 @@
+class AcrofonyTutorial extends Object2D
+{
+    constructor(name)
+    {
+        super(name);
+
+        /** @type {Object} */
+        this.levelData = ACROFONY_LEVELS.level5;
+        /** @type {Boolean} */
+        this.gameFinished = false;
+        /** @type {Number} */
+        this.tutorialStep = 0;
+
+        /** @type {AcrofonyQuestionCard} */
+        this.questionCard = null;
+        /** @type {AcrofonyGameDialogue} */
+        this.dialogue = null;
+        /** @type {Object2D} */
+        this.answerCards = null;
+        /** @type {Timer} */
+        this.timer = null;
+    }
+
+    _initSignals()
+    {
+        this.addSignal("endGame");
+    }
+
+    _setup()
+    {
+        AssetHandler.loadTexture(this.levelData.name, this.levelData.path);
+        this.questionCard = new AcrofonyQuestionCard("QuestionCard");
+        this.questionCard.thumb = AssetHandler.getTextureByName(this.levelData.name);
+        this.questionCard.imgName = this.levelData.name;
+        this.questionCard.setPosition(1920 / 2, 400);
+        this.addChild(this.questionCard);
+
+        var answers = [0, 1, 2];
+        randomSeed(Date.now());
+        answers = shuffle(answers);
+        this.answerCards = new Object2D("AnswerCards");
+        this.addChild(this.answerCards);
+        for (let i = 0; i < 3; i++)
+        {
+            var newCard = new AcrofonyOptionCard(`AnswerCard${i}`);
+            newCard.syllable = this.levelData.syllables[answers[i]] + "\n🗢";
+            newCard.setPosition((i + 1) * 1920 / 4, 900);
+            newCard.isAnswer = answers[i] == 0;
+            newCard.selectable = false;
+            newCard.connect("selected", this, "_onCardSelected");
+            this.answerCards.addChild(newCard);
+        }
+
+        this.dialogue = new AcrofonyTutorialDialogue("AcrofonyGameDialogue");
+        this.dialogue.connect("continue", this, "_onDialogueContinue")
+        this.addChild(this.dialogue);
+
+        this.timer = new Timer("Timer", 2, false, true);
+        this.timer.connect("timeout", this, "_onTimerTimeout");
+        this.addChild(this.timer);
+
+        this.timer.start();
+    }
+
+    _update( /** @type {number} */ delta)
+    {
+        switch (this.tutorialStep)
+        {
+            case 3:
+                this.answerCards.children[0].selectable = true;
+                this.answerCards.children[0].mouseOver = true;
+                this.answerCards.children[1].selectable = false;
+                this.answerCards.children[1].mouseOver = false;
+                this.answerCards.children[2].selectable = false;
+                this.answerCards.children[2].mouseOver = false;
+                break;
+            case 4:
+                this.answerCards.children[1].selectable = true;
+                this.answerCards.children[1].mouseOver = true;
+                this.answerCards.children[0].selectable = false;
+                this.answerCards.children[0].mouseOver = false;
+                this.answerCards.children[2].selectable = false;
+                this.answerCards.children[2].mouseOver = false;
+                break;
+            case 5:
+                this.answerCards.children[2].selectable = true;
+                this.answerCards.children[2].mouseOver = true;
+                this.answerCards.children[0].selectable = false;
+                this.answerCards.children[0].mouseOver = false;
+                this.answerCards.children[1].selectable = false;
+                this.answerCards.children[1].mouseOver = false;
+                break;
+            case 6:
+                this.answerCards.children[0].selectable = false;
+                this.answerCards.children[0].mouseOver = false;
+                this.answerCards.children[1].selectable = false;
+                this.answerCards.children[1].mouseOver = false;
+                this.answerCards.children[2].selectable = false;
+                this.answerCards.children[2].mouseOver = false;
+                break;
+            case 7:
+                this.answerCards.children[0].selected = true;
+                this.answerCards.children[1].selected = true;
+                this.answerCards.children[2].selected = true;
+        }
+    }
+
+    _onTimerTimeout()
+    {
+        switch (this.tutorialStep)
+        {
+            case 0:
+                this.tutorialStep++;
+                break;
+            case 2:
+                this.tutorialStep++;
+                this.timer.start(0.5);
+                break;
+            case 3:
+                this.tutorialStep++;
+                this.timer.start(0.5);
+                break;
+            case 4:
+                this.tutorialStep++;
+                this.timer.start(0.5);
+                break;
+            case 5:
+                this.tutorialStep++;
+                this.timer.start(1);
+                break;
+            case 6:
+                this.tutorialStep++;
+                this.timer.start(1);
+                break;
+            case 7:
+                this.tutorialStep++;
+                break;
+        }
+    }
+
+    _onDialogueContinue()
+    {
+        this.tutorialStep++;
+
+        switch (this.tutorialStep)
+        {
+            case 2:
+                this.timer.start(2);
+                break;
+            case 9:
+                this.emitSignal("endGame", 0);
+                break;
+        }
+    }
+}

+ 80 - 0
src/elements/earth/acrofony/tutorial/AcrofonyTutorialDialogue.js

@@ -0,0 +1,80 @@
+class AcrofonyTutorialDialogue extends Object2D
+{
+    constructor(name)
+    {
+        super(name);
+
+        /** @type {Button} */
+        this.continueButton = null;
+        /** @type {Timer} */
+        this.timer;
+
+        /** @type {String} */
+        this.text = "";
+        /** @type {number} */
+        this.bgOpacity = 0;
+        /** @type {number} */
+        this.textOpacity = 0;
+    }
+
+    _initSignals()
+    {
+        this.addSignal("continue");
+    }
+
+    _setup()
+    {
+        this.continueButton = new Button("ContinueButton", "Continuar");
+        this.continueButton.connect("mouseClicked", this, "_onContinueButtonMouseClicked");
+        this.continueButton.hide();
+        this.continueButton.setFontSize(40);
+        this.continueButton.setPosition(1920 / 2 - this.continueButton.getSize().x / 2, 600);
+        this.addChild(this.continueButton);
+    }
+
+    _draw( /** @type {number} */ delta, /** @type {p5.Graphics} */ db)
+    {
+        switch (this.parent.tutorialStep)
+        {
+            case 0:
+                this.bgOpacity = 0;
+                this.textOpacity = 0;
+                break;
+            case 1:
+                this.bgOpacity = min(this.bgOpacity + 150 * delta, 200);
+                this.textOpacity = min(this.textOpacity + 150 * delta, 255);
+                this.text = "Qual o primeiro pedacinho da palavra RELÓGIO?"
+                if (this.textOpacity == 255) this.continueButton.show();
+                break;
+            case 2:
+                this.continueButton.hide();
+                this.bgOpacity = max(this.bgOpacity - 150 * delta, 0);
+                this.textOpacity = max(this.textOpacity - 150 * delta, 0);
+                this.text = "Qual o primeiro pedacinho da palavra RELÓGIO?"
+                break;
+            case 3:
+                this.bgOpacity = 0;
+                this.textOpacity = 0;
+                break;
+            case 8:
+                this.bgOpacity = min(this.bgOpacity + 150 * delta, 200);
+                this.textOpacity = min(this.textOpacity + 150 * delta, 255);
+                this.text = "O primeiro pedacinho de RELÓGIO é RE\n\nAgora é sua vez!"
+                if (this.textOpacity == 255) this.continueButton.show();
+        }
+
+        db.noStroke();
+        db.fill(0, this.bgOpacity);
+        db.rectMode(CENTER);
+        db.rect(db.width / 2, db.height / 2, 1800, 600, 40, 40);
+        db.textAlign(CENTER, CENTER);
+        db.fill(255, this.textOpacity);
+        db.textSize(40);
+        db.text(this.text, db.width / 2, db.height / 2 - 100);
+    }
+
+    _onContinueButtonMouseClicked()
+    {
+        this.emitSignal("continue");
+    }
+}

+ 6 - 1
src/elements/earth/rebus/game/RebusGame.js

@@ -31,7 +31,7 @@ class RebusGame extends Object2D
         this.gameFinished = false;
         /** @type {number} */
         this.points = 3;
-    
+
         /** @type {Button} */
         this.backButton = null;
         /** @type {Button} */
@@ -40,6 +40,11 @@ class RebusGame extends Object2D
         this.timer = null;
     }
 
+    _initSignals()
+    {
+        this.addSignal("slected");
+    }
+
     _setup()
     {
         var arr = [];

+ 3 - 3
src/elements/earth/rebus/game/RebusGameVisualEffects.js

@@ -27,9 +27,9 @@ class RebusGameVisualEffects extends Object2D
 
         /** @type {String} */
         this.suffix = "";
-        /** @type {number} */
+        /** @type {Number} */
         this.bgOpacity = 0;
-        /** @type {number} */
+        /** @type {Number} */
         this.textOpacity = 0;
     }
 
@@ -45,7 +45,7 @@ class RebusGameVisualEffects extends Object2D
             db.fill(255, min(this.textOpacity += 80 * delta, 255));
             db.textSize(40);
             this.parent.points > 1 ? this.suffix = "S" : this.suffix = "";
-            db.text(`PARABÉNS, NÍVEL CONCLUÍDO\nVOCÊ GANHOU ${this.parent.points} PONTO${this.suffix}!`, db.width / 2, db.height / 2 - 100);
+            db.text(`PARABÉNS, NÍVEL CONCLUÍDO\n\nVOCÊ GANHOU ${this.parent.points} PONTO${this.suffix}!`, db.width / 2, db.height / 2 - 100);
         }
     }
 }

+ 4 - 10
src/elements/earth/rebus/game/RebusOptionCard.js

@@ -35,14 +35,14 @@ class RebusOptionCard extends Object2D
         this.selected = false;
         /** @type {Boolean} */
         this.selectable = true;
-    
-        /** @type {Color} */
-        this.fillColor = new Color(200, 200, 200);
         /** @type {Boolean} */
         this.mouseOver = false;
         /** @type  {Boolean} */
         this.mousePress = false;
-    
+
+        /** @type {Color} */
+        this.fillColor = new Color(200, 200, 200);
+
         /** @type {Boolean} */
         this.tweenStarted = false;
         /** @type {Tween} */
@@ -126,12 +126,6 @@ class RebusOptionCard extends Object2D
         db.fill(0);
         db.textSize(40);
         db.text(this.imgName, 0, 100);
-
-        if (this.selected && !this.isAnswer)
-        {
-            db.fill(0, 80);
-            db.rect(0, 0, 300, 400, 10, 10);
-        }
     }
 
     _onMouseEntered()

+ 5 - 5
src/elements/earth/rebus/tutorial/RebusTutorialVisualEffects.js

@@ -39,12 +39,12 @@ class RebusTutorialVisualEffects extends Object2D
         {
             case 0:
                 this.bgOpacity = min(this.bgOpacity + 150 * delta, 200);
-                this.textOpacity = min(this.bgOpacity + 150 * delta, 255);
+                this.textOpacity = min(this.textOpacity + 150 * delta, 255);
                 this.text = `Vamos ler rébus?\nRébus é uma palavra formada quando juntamos os primeiros\npedacinhos de outras palavras.\nVeja!`;
                 break;
             case 1:
                 this.bgOpacity = max(this.bgOpacity - 150 * delta, 0);
-                this.textOpacity = max(this.bgOpacity - 150 * delta, 0);
+                this.textOpacity = max(this.textOpacity - 150 * delta, 0);
                 this.text = `Vamos ler rébus?\nRébus é uma palavra formada quando juntamos os primeiros\npedacinhos de outras palavras.\nVeja!`;
                 break;
             case 2:
@@ -53,12 +53,12 @@ class RebusTutorialVisualEffects extends Object2D
                 break;
             case 3:
                 this.bgOpacity = min(this.bgOpacity + 150 * delta, 200);
-                this.textOpacity = min(this.bgOpacity + 150 * delta, 255);
+                this.textOpacity = min(this.textOpacity + 150 * delta, 255);
                 this.text = `Que palavra será formada ao juntarmos o começo dessas duas palavras?`;
                 break;
             case 4:
                 this.bgOpacity = max(this.bgOpacity - 150 * delta, 0);
-                this.textOpacity = max(this.bgOpacity - 150 * delta, 0);
+                this.textOpacity = max(this.textOpacity - 150 * delta, 0);
                 this.text = `Que palavra será formada ao juntarmos o começo dessas duas palavras?`;
                 break;
             case 5:
@@ -67,7 +67,7 @@ class RebusTutorialVisualEffects extends Object2D
                 break;
             case 7:
                 this.bgOpacity = min(this.bgOpacity + 150 * delta, 200);
-                this.textOpacity = min(this.bgOpacity + 150 * delta, 255);
+                this.textOpacity = min(this.textOpacity + 150 * delta, 255);
                 this.text = `Agora é sua vez!`;
                 break;
         }

+ 6 - 3
src/main.js

@@ -28,10 +28,13 @@ GameHandler._setup = function()
 {
     GameHandler.drawDebugFPS(true);
     GameHandler.drawDebugBufferBounds(true);
-    // textFont(AssetHandler.getP5FontByName("Lato"));
+    textFont("Lato");
 
-    // var lh = new LetterHuntGame("LetterHunt");
-    // GameHandler.addRootObject(lh);
+    // var ag = new AcrofonyGame("AcrofonyGame");
+    // GameHandler.addRootObject(ag);
+
+    // var alm = new AcrofonyLevelManager("AcrofonyLevelManager");
+    // GameHandler.addRootObject(alm);
     var menu = new EelementSelector("ElementSelector");
     GameHandler.addRootObject(menu);
 }