What the hex
* @see http://yizzle.com/whatthehex/
* @see http://wonderfl.net/c/cuY4 (ランキング+Tweet部分)
* @author jc at bk-zen
/**
* Copyright bkzen ( http://wonderfl.net/user/bkzen )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/kYyY
*/
/**
* @see http://yizzle.com/whatthehex/
* @see http://wonderfl.net/c/cuY4 (ランキング+Tweet部分)
* @author jc at bk-zen
*/
package
{
import com.bit101.components.HUISlider;
import com.bit101.components.Style;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import net.wonderfl.utils.WonderflAPI;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.tweens.ITween;
[SWF (backgroundColor = "0x333333", frameRate = "30", width = "465", height = "465")]
public class WhatTheHex extends Sprite
{
private const resultTxts: Array = ["stage click to start", "guess the color", "correct!", "stage click and try again.\nthat color was \n", "next stage", "game over", "time up", "stage click to restart"];
private const topY: int = 85;
private const maxBtns: int = 48;
private const baseTime: int = 10000;
private const LIFE: int = 10;
private var title: LLabel, colorLabel: LLabel, lifeLabel: LLabel, scoreLabel: LLabel, resultLabel: LLabel, pointLabel: LLabel;
private var difficulty: HUISlider;
private var diffValue: int, _score: int, _life: int;
private var stageW: int, stageH: int, areaW: int, areaH: int;
private var targetColor: uint;
private var isGameStart: Boolean;
private var bgSprite: Sprite, bg: Graphics;
private var areaSprite: Sprite;
private var container: CButtonContainer;
private var resTween: ITween;
private var _point: int;
private var correctCnt: int;
private var timer:LimitTimer;
private var loadingLabel: LLabel;
private var clickSp: Sprite, clickBg: Graphics;
public function WhatTheHex()
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e: Event = null): void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
Style.LABEL_TEXT = 0xFFFFFF;
loadingLabel = new LLabel(this, 0, 0, "Now Loading...", 2);
loadingLabel.x = stage.stageWidth - loadingLabel.width >> 1;
loadingLabel.y = stage.stageHeight - loadingLabel.height >> 1;
var obj: Object = loaderInfo.parameters;
ScoreWindowLoader.init(this, new WonderflAPI(obj), compLib);
}
private function compLib():void
{
removeChild(loadingLabel);
// UI を作る
var f: Array = [new DropShadowFilter(1, 45, 0, 1, 5, 5, 100, 1)];
addChild(bgSprite = new Sprite());
addChild(areaSprite = new Sprite());
container = new CButtonContainer(areaSprite, maxBtns, onClickBtn);
bg = bgSprite.graphics;
title = new LLabel(this, 0, 0, "What the Hex", 2.5);
colorLabel = new LLabel(this, 0, title.y + title.height, " ", 3);
lifeLabel = new LLabel(this, 0, 0, "LIFE : " + life);
scoreLabel = new LLabel(this, 10, 0, "SCORE : 0");
resultLabel = new LLabel(this, 0, 0, " ", 3, 0xCCCCCC);
difficulty = new HUISlider(this, 0, 0, "difficulty");
difficulty.labelPrecision = 0;
difficulty.setSliderParams(3, maxBtns, diffValue = 5);
pointLabel = new LLabel(this, 0, 0, "+score", 1.5, 0xCCCCCC);
timer = new LimitTimer(this, "limit time");
title.filters = colorLabel.filters = lifeLabel.filters = scoreLabel.filters = resultLabel.filters = difficulty.filters = pointLabel.filters = timer.label.filters = f;
addChild(clickSp = new Sprite());
clickBg = clickSp.graphics;
// 一旦リサイズ
onResize();
stage.addEventListener(Event.RESIZE, onResize);
stage.addEventListener(MouseEvent.MOUSE_UP, onChanged); // HUISlider の Change Event は 変わるたびに送出されるから Stage の MouseUp を取得する。
resultLabel.alpha = 0;
showRes(resultTxts[0]);
clickSp.addEventListener(MouseEvent.CLICK, onClickStart);
timer.addEventListener(Event.COMPLETE, onTimer);
}
/**
* タイムアップ
* @param e
*/
private function onTimer(e:Event):void
{
container.allChangeEnabled(false);
damage();
}
/**
* ボタンが押された時の処理
* @param e
*/
private function onClickBtn(e: Event):void
{
var c: CButton = CButton(e.target);
if (c.color == targetColor)
{
container.allHide();
score += _point;
correctCnt ++;
timer.stop();
showRes(resultTxts[2], function(): void {
showRes(resultTxts[4], function(): void {
initColors();
}, true)
}, true);
}
else
{
container.allChangeEnabled(false);
difficulty.enabled = false;
point -= diffValue >> 1;
damage(c);
}
}
/**
* ダメージ処理
* @param c
*/
private function damage(c: CButton = null):void
{
if (--life > 0)
{
if (c)
{
showRes(resultTxts[3] + getColorStr(c.color), function(): void {
clickSp.mouseEnabled = true;
clickSp.addEventListener(MouseEvent.CLICK, onClickRetry);
});
}
else showRes(resultTxts[6], initColors, true);
}
else
{
showRes(resultTxts[5], function(): void {
ScoreWindowLoader.show(score, onCloseEndWindow);
});
}
}
/**
* ScoreWindow の表示が終了
*/
private function onCloseEndWindow():void
{
showRes(resultTxts[7], function(): void {
clickSp.mouseEnabled = true;
clickSp.addEventListener(MouseEvent.CLICK, onClickStart);
});
}
/**
* リトライ
* @param e
*/
private function onClickRetry(e:MouseEvent):void
{
clickSp.mouseEnabled = false;
clickSp.removeEventListener(MouseEvent.CLICK, onClickRetry);
hideRes(function(): void {
container.allChangeEnabled(true);
difficulty.enabled = true;
})
}
/**
* スタート
* @param e
*/
private function onClickStart(e: MouseEvent): void
{
clickSp.mouseEnabled = false;
clickSp.removeEventListener(MouseEvent.CLICK, onClickStart);
score = 0, life = LIFE, correctCnt = 0, _point = 0;
hideRes(startStage);
}
/**
* result label に文字表示
* @param str : 表示する文字列
* @param onComp : Tween終了ハンドラ andHide が true の時は消えた後に送出される。
* @param andHide : ついでに消す
*/
private function showRes(str: String, onComp: Function = null, andHide: Boolean = false):void
{
resultLabel.alpha = 0, resultLabel.text = str;
resultLabel.draw();
resultLabel.x = stageW - resultLabel.width >> 1;
resultLabel.y = areaSprite.y - resultLabel.height;
if (resTween && resTween.isPlaying) resTween.stop(), resTween.onComplete && resTween.onComplete();
resTween = BetweenAS3.to(resultLabel, { alpha: 1 }, 0.5);
if (andHide) resTween.onComplete = function(): void { hideRes(onComp) }
else resTween.onComplete = onComp;
resTween.play();
}
/**
* result label を消す
* @param onComp
*/
private function hideRes(onComp: Function = null): void
{
if (resTween && resTween.isPlaying) resTween.stop(), resTween.onComplete && resTween.onComplete();
resTween = BetweenAS3.to(resultLabel, { alpha: 0 }, 0.5);
resTween.onComplete = onComp;
resTween.play();
}
/**
* 難易度が変わった時の処理
* @param e
*/
private function onChanged(e: Event):void
{
if (diffValue != int(difficulty.value))
{
diffValue = difficulty.value;
if (isGameStart) initColors();
}
}
/**
* ゲーム開始
*/
private function startStage(): void
{
showRes(resultTxts[1], function(): void {
isGameStart = true;
}, true);
initColors();
}
/**
* CButton 初期化
*/
private function initColors(): void
{
point = diffValue * Math.sqrt(diffValue);
colorLabel.text = getColorStr(targetColor = container.init(diffValue));
colorLabel.draw();
colorLabel.x = stageW - colorLabel.width >> 1;
container.layout(areaW, areaH);
timer.start((20 + diffValue) * baseTime - correctCnt * 100); // TODO 適当に 20 秒
}
/**
* 0x000000 のように6桁の文字列にする(Hex)
* @param col
* @return
*/
private function getColorStr(col: uint): String
{
var str: String = col.toString(16);
var i: int = str.length;
for (; i < 6; i ++) str = "0" + str;
return "0x" + str.toUpperCase();
}
/**
* 画面のリサイズ
* @param e
*/
private function onResize(e: Event = null): void
{
stageW = stage.stageWidth, stageH = stage.stageHeight;
bg.clear();
bg.beginFill(0x333333);
bg.drawRect(0, 0, stageW, stageH);
bg.beginFill(0x444444);
bg.drawRoundRect(10, topY, areaW = stageW - 20, areaH = stageH - topY - 40, 5, 5);
clickBg.clear();
clickBg.beginFill(0, 0);
clickBg.drawRect(10, topY, areaW, areaH);
areaSprite.x = stageW >> 1;
areaSprite.y = (areaH >> 1) + topY;
title.x = stageW - title.width >> 1;
colorLabel.x = stageW - colorLabel.width >> 1;
difficulty.x = stageW - difficulty.width + 20 >> 1;
difficulty.y = stageH - difficulty.height - 15;
lifeLabel.x = stageW - lifeLabel.width - 10;
lifeLabel.y = stageH - lifeLabel.height - 20;
scoreLabel.y = stageH - scoreLabel.height - 20;
resultLabel.x = stageW - resultLabel.width >> 1;
resultLabel.y = areaSprite.y - resultLabel.height;
pointLabel.x = stageW - pointLabel.width >> 1;
pointLabel.y = difficulty.y - pointLabel.height - 5;
timer.y = stageH - 16;
timer.setSize(stageW);
container.layout(areaW, areaH);
}
public function get life():int { return _life; }
public function set life(value:int):void
{
lifeLabel.text = "LIFE : " + (_life = value);
lifeLabel.draw();
lifeLabel.x = stageW - lifeLabel.width - 10;
}
public function get score():int { return _score; }
public function set score(value:int):void
{
scoreLabel.text = String(_score = value);
}
public function get point(): int { return _point; }
public function set point(value:int):void
{
pointLabel.text = "+" + (_point = value);
pointLabel.draw();
pointLabel.x = stageW - pointLabel.width >> 1;
}
}
}
import com.bit101.components.Label;
import com.bit101.components.Style;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import net.wonderfl.utils.WonderflAPI;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Quad;
import org.libspark.betweenas3.tweens.ITween;
/**
* サイズ・色変更付きの Label
*/
class LLabel extends Label
{
protected var _scale: Number = 1;
function LLabel(parent: DisplayObjectContainer = null, x: int = 0, y: int = 0, text: String = "", scale: Number = 1, color: uint = 0xFFFFFF)
{
var c: uint = Style.LABEL_TEXT;
Style.LABEL_TEXT = color;
super(parent, x, y, text);
Style.LABEL_TEXT = c;
scaleX = scaleY = _scale = scale;
}
override public function get width(): Number { return super.width * _scale; }
override public function get height(): Number { return _tf.textHeight * _scale; }
}
/**
* Color 表示用のボタン
*/
class CButton extends Sprite
{
private var _color: uint, _size: int, targetSize: int;
function CButton()
{
buttonMode = true, mouseEnabled = false, alpha = 0;
addEventListener(MouseEvent.CLICK, onClick);
}
/**
* ボタンをクリックしたときのアクション(非表示にするだけ)
* @param e
*/
private function onClick(e: MouseEvent): void
{
hide();
}
/**
* 色の初期化
* @param color
*/
public function init(color: uint, size: int): void
{
mouseEnabled = visible = true;
_color = color, alpha = 0;
setSize(size);
}
/**
* サイズ変更
*/
public function setSize(value: int): void
{
targetSize = value >> 1;
BetweenAS3.to(this, { alpha: 1, size: value }, 0.5, Quad.easeOut).play();
}
/**
* ボタンを非表示にして押せなくする。
*/
public function hide():void
{
mouseEnabled = false;
var tw: ITween = BetweenAS3.to(this, { alpha: 0, size: 0 }, 0.5, Quad.easeOut);
tw.onComplete = function(): void { visible = false; }
tw.play();
}
public function get size(): int { return _size; }
public function set size(value: int): void
{
_size = value;
var g: Graphics = graphics, d: int = value - 4, t: int = targetSize - (d >> 1);
g.clear();
g.beginFill(_color);
g.drawRoundRect(t, t, d, d, 4, 4);
}
public function get color(): uint { return _color; }
}
/**
* CButton をもじゃもじゃするやつ
*/
class CButtonContainer
{
private const SIZE: int = 40;
private var parent: Sprite;
private var maxBtns: int;
private var btns: Array/*CButton*/ = [];
private var _diffValue:int;
function CButtonContainer(parent: Sprite, maxBtns: int, handler: Function)
{
this.parent = parent, this.maxBtns = maxBtns;
for (var i: int = 0; i < maxBtns; i++) (btns[i] = parent.addChild(new CButton())).addEventListener(MouseEvent.CLICK, handler);
}
/**
* 初期化
* @param diffValue : ボタンの個数(難易度)
* @return 正解の色
*/
public function init(diffValue: int): uint
{
var i: int, n: int = Math.random() * (_diffValue = diffValue), c: CButton, targetColor: uint = getRandomColor();
for (i = 0; i < maxBtns; i++)
{
c = btns[i];
if (i < diffValue) c.init(i == n ? targetColor : getRandomColor(), SIZE)
else c.hide();
}
return targetColor;
}
/**
* タイル状に並べる
* TODO: もっときれいに並べる。適当過ぎた・・・
* @param areaW : エリアの幅
* @param areaH : エリアの高さ
*/
public function layout(areaW: int, areaH: int): void
{
var i: int, c: CButton, tx: int, ty: int, n: int;
var maxRows: int = (areaW - 120) / SIZE;
if (maxRows < 2) maxRows = 2;
var numCols: int = (_diffValue - 1) / maxRows + 1;
if (numCols == 1) maxRows = _diffValue;
for (i = 0; i < _diffValue; i++)
{
c = btns[i];
tx = i % maxRows;
ty = i / maxRows;
n = ty < numCols - 1 ? maxRows : _diffValue % maxRows || maxRows;
c.x = (tx - n / 2) * SIZE;
c.y = (ty - numCols / 2) * SIZE;
}
}
/**
* ランダムな色取得
* @return
*/
public function getRandomColor(): uint
{
var r: int = (0xCC * Math.random() + 0x33) & 0xFF, g: int = (0xCC * Math.random() + 0x33) & 0xFF, b: int = (0xCC * Math.random() + 0x33) & 0xFF;
return (r << 0x10) | (g << 0x08) | (b << 0x00);
}
/**
* 全部消す
*/
public function allHide(): void
{
for (var i: int = 0; i < _diffValue; i++) btns[i].hide();
}
/**
* 全部の enabled を変える
* @param value
*/
public function allChangeEnabled(value: Boolean):void
{
for (var i: int = 0; i < _diffValue; i++) btns[i].mouseEnabled = value;
}
}
/**
* 時間制限を設けるためのもじゃもじゃするやつ。
*/
[Event(name="complete", type="flash.events.Event")]
class LimitTimer extends Sprite
{
private var _label: Label;
private var _time: int, currentTime: Number, passTime: int;
private var line: Shape;
private var _size: int, _lineSize: int;
function LimitTimer(parent: DisplayObjectContainer, label: String)
{
mouseEnabled = mouseChildren = false;
addChild(line = new Shape());
_label = new Label(this, 0, -2, label);
_label.draw();
parent.addChild(this);
}
public function setSize(size: int): void
{
if (_size == size) return;
_lineSize = (_size = size) - 8;
var g: Graphics = graphics;
g.clear();
g.beginFill(0x555555);
g.drawRect(2, 2, _size - 4, 12);
_label.x = size - _label.width >> 1;
draw();
}
private function draw():void
{
var g: Graphics = line.graphics;
g.clear();
g.beginFill(0x333333);
g.drawRect(4, 4, _lineSize * passTime / _time || 1, 8);
}
public function start(time: int): void
{
_time = time, passTime = 0, currentTime = new Date().getTime();
removeEventListener(Event.ENTER_FRAME, loop);
addEventListener(Event.ENTER_FRAME, loop);
}
public function stop(): void
{
removeEventListener(Event.ENTER_FRAME, loop);
}
private function loop(e:Event):void
{
var t: Number = new Date().getTime(), d: int = t - currentTime;
if (d < 0) passTime -= 1000 / stage.frameRate
else passTime += d;
currentTime = t;
draw();
if (passTime >= _time)
{
removeEventListener(Event.ENTER_FRAME, loop);
dispatchEvent(new Event(Event.COMPLETE));
}
}
public function get label():Label { return _label; }
}
class ScoreWindowLoader
{
private static var _top: DisplayObjectContainer;
private static var _api: WonderflAPI;
private static var _content: Object;
//private static const URL: String = "wonderflScore.swf";
private static const URL: String = "http://swf.wonderfl.net/swf/usercode/5/57/579a/579a46e1306b5770d429a3738349291f05fec4f3.swf";
private static const TWEET: String = "Playing What the Hex [score: %SCORE%] #wonderfl";
public static function init(top: DisplayObjectContainer, api: WonderflAPI, handler: Function): void
{
_top = top, _api = api;
var loader: Loader = new Loader();
var comp: Function = function(e: Event): void
{
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, comp);
_content = loader.content;
handler();
}
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, comp);
loader.load(new URLRequest(URL), new LoaderContext(true));
}
/**
* Wonderfl の Score API 用
* ランキング表示から Tweet までをひとまとめにしたSWF素材を使う
* @param score : 取得スコア
* @param closeHandler : Window が閉じるイベントハンドら
*/
public static function show( score: int, closeHandler: Function): void
{
var window: DisplayObject = _content.makeScoreWindow(_api, score, "What the Hex", 1, TWEET);
var close: Function = function(e: Event): void
{
window.removeEventListener(Event.CLOSE, close);
closeHandler();
}
window.addEventListener(Event.CLOSE, close);
_top.addChild(window);
}
}