(var SPRITE_SPACING 20) (var SPRITE_SIZE 100) (var TEXT_SIZE 24) (prop &mut :FlxText docText null) (method &override :Void create [] #{ super.create(); var background = new FlxSprite(); background.makeGraphic(1280, 720, FlxColor.BLACK); // background.x = 0; // background.y = 0; FlxSpriteUtil.beginDraw(FlxColor.WHITE); var x = SPRITE_SPACING; var y = FlxG.height - SPRITE_SIZE - SPRITE_SPACING; // Split the screen into text area and dance area: var splitX = SPRITE_SPACING * 5 + SPRITE_SIZE * 4; background.drawLine(splitX, 0, splitX, FlxG.height); docText = new FlxText(splitX, 0, "", TEXT_SIZE); docText.setFormat(null, 8, FlxColor.WHITE); add(background); add(docText); // this is actually just distracting: // Split the left side into upper/lower: //background.drawLine(0, FlxG.height - SPRITE_SIZE - SPRITE_SPACING * 2, splitX, FlxG.height - SPRITE_SIZE - SPRITE_SPACING * 2); /* makeTriangleSprite(Left, "", y); makeTriangleSprite(Down, "", y); makeTriangleSprite(Up, "", y); makeTriangleSprite(Right, "", y); */ add(actionSprites); }#) (prop :Map inputCodes (new Map)) (var DIR_ORDER [ Left Down Up Right ]) (prop &mut :FlxText instructionText null) (method &override :Void update [:Float elapsed] (super.update elapsed) (let [mappedCodes (count inputCodes) nextToMap (nth DIR_ORDER mappedCodes)] (if (= DIR_ORDER.length mappedCodes) // Handle an arrow press { (set instructionText.text "") (unless timer (set timer (new FlxTimer)) (let [&mut i 0] (timer.start ARROW_DELAY ->_ { #{ var stuff = _model.generateArrowStuff(); makeTriangleSprite(DIR_ORDER[i++ % DIR_ORDER.length], stuff.text, -SPRITE_SIZE, stuff.action); }# } 0))) (whenLet [(Some id) (getFirstInputId) dir (dictGet inputCodes id)] (let [&mut :ActionSprite lowestMatching null &mut :Float highestY -SPRITE_SIZE-1] (actionSprites.forEachAlive ->spr (when (= dir spr.dir) (when (> spr.y highestY) (set highestY spr.y) (set lowestMatching spr)))) (when lowestMatching (lowestMatching.action) (updateDocText) (lowestMatching.kill)))) } // Prompt to map the arrows { (unless instructionText (set instructionText (new FlxText "" TEXT_SIZE)) (add instructionText)) (set instructionText.text "Press $nextToMap") (instructionText.screenCenter) (whenLet [(Some id) (getFirstInputId)] (dictSet inputCodes id nextToMap)) }))) (method updateDocText [] (set docText.text (StringTools.replace _model.content "\t" " "))) (prop :FlxTypedGroup actionSprites (new FlxTypedGroup)) (prop &mut :DocumentModel _model null) (prop &mut :FlxTimer timer null) (var ARROW_DELAY 0.25) (method setModel [:DocumentModel m] (set _model m) (updateDocText)) (method :FlxSprite makeTriangleSprite [:ArrowDir dir :String text :Int y &opt :Void->Void action] #{ var spr = new ActionSprite(action, dir); spr.makeGraphic(SPRITE_SIZE, SPRITE_SIZE, FlxColor.TRANSPARENT, true); FlxSpriteUtil.beginDraw(FlxColor.WHITE); spr.drawTriangle(0, 0, SPRITE_SIZE); spr.angle = switch (dir) { case Left: -90; case Down: 180; case Up: 0; case Right: 90; }; text = switch (text) { case "\n": ""; case "\r": ""; case " ": ""; case "\t": ""; default: text; }; var ftext = new FlxText(text, TEXT_SIZE); ftext.angle = -spr.angle; ftext.color = FlxColor.BLACK; if (text.length > 1) { ftext.size = 12; } spr.stamp(ftext, Math.floor(SPRITE_SIZE/2) - Math.floor(ftext.width / 2), Math.floor(SPRITE_SIZE/2) - Math.floor(ftext.height / 2)); spr.x = SPRITE_SPACING + DIR_ORDER.indexOf(dir) * (SPRITE_SIZE + SPRITE_SPACING); spr.y = y; if (action != null) { actionSprites.add(spr); FlxTween.linearMotion(spr, spr.x, spr.y, spr.x, FlxG.height, 200, false, { onComplete: (_) -> { spr.kill(); } }); } else { add(spr); } return spr; }#)