ドットフ絵リカ(ドットフェリカと読む) 連動アプリ 第1弾 PuyoDot Fork ver
forked from PuyoDot (diff: 1019)
PuyoDot プヨっとしたドット。 下のほうにあるパレットから拾ってきて表示するよ。 ぐりぐりしたり、引っ張ったり、新しいドット絵を追加して遊んでね。 (マップが意外と見ずらくなった。wonderflって等倍フォントじゃないんだね 等倍のテキストエディタか何かで編集すると楽かも) 本当はドットを編集する機能も入れたかったんだけど 力尽きるどころの話じゃなかったから今回は諦めた。 でもいつか作りたいね。 ドット状、任意外形の弾性体を表現します。 こういう、ぐにぐにしたものは、各頂点をテンションで繋ぐfladdict式が一番軽くて綺麗なのですが、 そうすると自由な形にはしにくいという欠点があります。 今回の手法では、小さな点が、バネで繋がっているモデルをしており、一部が欠けてもそれらしい動作をします。 バネは回転方向への力も持ち、隣の点を、距離だけではなく正常な角度に保とうとします。 欠点として、点の数が多くなるため圧倒的に重いことと 力の伝わり方が遅いため、伸びやすい物体になってしまうことです。 前者はリファクタリングしていく必要があります。 後者は、今回解決のために点を2個先まで接続する手法をとりました。 キング・カズマのドットバージョンを入れたかったんだけど 16x32ドットは重くなりすぎて断念。 軽量化して、そのくらいは動くようになりたい。 wonderflにあるpuyodotのソースをFeliCa の NFC Type 3タグの 情報を読み込むように改造したものです。 wonderfl上にアップしている NFC Type 3 タグ対応の ドットフ絵リカ(ドットフェリカ)と読むというドットエディタと連動してます。
ActionScript3 source code
/**
* Copyright tokufxug ( http://wonderfl.net/user/tokufxug )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/cl20
*/
// forked from tail_y's PuyoDot
package
{
/*
PuyoDot
プヨっとしたドット。
下のほうにあるパレットから拾ってきて表示するよ。
ぐりぐりしたり、引っ張ったり、新しいドット絵を追加して遊んでね。
(マップが意外と見ずらくなった。wonderflって等倍フォントじゃないんだね
等倍のテキストエディタか何かで編集すると楽かも)
本当はドットを編集する機能も入れたかったんだけど
力尽きるどころの話じゃなかったから今回は諦めた。
でもいつか作りたいね。
*/
/*
ドット状、任意外形の弾性体を表現します。
こういう、ぐにぐにしたものは、各頂点をテンションで繋ぐfladdict式が一番軽くて綺麗なのですが、
そうすると自由な形にはしにくいという欠点があります。
今回の手法では、小さな点が、バネで繋がっているモデルをしており、一部が欠けてもそれらしい動作をします。
バネは回転方向への力も持ち、隣の点を、距離だけではなく正常な角度に保とうとします。
欠点として、点の数が多くなるため圧倒的に重いことと
力の伝わり方が遅いため、伸びやすい物体になってしまうことです。
前者はリファクタリングしていく必要があります。
後者は、今回解決のために点を2個先まで接続する手法をとりました。
キング・カズマのドットバージョンを入れたかったんだけど
16x32ドットは重くなりすぎて断念。
軽量化して、そのくらいは動くようになりたい。
*/
/*
wonderflにあるpuyodotのソースをFeliCa の NFC Type 3タグの
情報を読み込むように改造したものです。
wonderfl上にアップしている NFC Type 3 タグ対応の
ドットフ絵リカ(ドットフェリカ)と読むというドットエディタと連動してます。
*/
import com.sony.jp.felica.FeliCaCloseReaderWriterRequest;
import com.sony.jp.felica.FeliCaCloseReaderWriterResponse;
import com.sony.jp.felica.FeliCaControl;
import com.sony.jp.felica.FeliCaOpenReaderWriterAutoRequest;
import com.sony.jp.felica.FeliCaOpenReaderWriterAutoResponse;
import com.sony.jp.felica.FeliCaPollingAndGetCardInformationRequest;
import com.sony.jp.felica.FeliCaPollingAndGetCardInformationResponse;
import com.sony.jp.felica.FeliCaSessionRequest;
import com.sony.jp.felica.FeliCaSessionResponse;
import com.sony.jp.felica.NFCType3TagRequest;
import com.sony.jp.felica.NFCType3TagResponse;
import com.sony.jp.felica.error.FeliCaAccessError;
import com.sony.jp.felica.event.FeliCaStatusEvent;
import com.sony.jp.felica.event.OpenStatusEvent;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageQuality;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
public class PuyoDot3 extends Sprite
{
public static const STAGE_W:uint = 465;
public static const STAGE_H:uint = 465;
private static const _WALL_LEFT:Number = 0;
private static const _WALL_RIGHT:Number = 465;
private static const _GROUND_LINE:Number = 350;
private static const _DOT_CONNECT_MAX:int = 4;
private static const _DERIVATION:int = 3; // 計算の分割数。
private static const _MAP_SIZE:Number = 200;
private static const _PI:Number = Math.PI;
private static const _PI2:Number = 2.0 * _PI;
private static const _RADIAN90:Number = _PI * 0.5;
private static const _RADIAN180:Number = _PI * 1.0;
private static const _RADIAN270:Number = _PI * -0.5;
private static const _TO_DEGREE:Number = 180 / _PI;
private static const _GRAVITY:Number = 0.2 / _DERIVATION;
private static const _ROTATION_RATE:Number = 0.05 / _DERIVATION; // 自身バネ(根元)
private static const _VERTICAL_RATE:Number = 0.2 / _DERIVATION; // ターゲットバネ(さきっぽ)
private static const _MOUSE_PULL_RATE:Number = 2.0 / _DERIVATION;
private static const _FRICTION:Number = 0.1 / _DERIVATION;
private static const _ROTATE_FRICTION:Number = 1 - 0.2 / _DERIVATION;
private static const _MOUSE_ROTATE_FRICTION:Number = 1 - 0.8 / _DERIVATION;
private static const _MOUSE_MOVE_FRICTION:Number = 1 - 0.5 / _DERIVATION;
private static const _GROUND_FRICTION:Number = 1 - 0.2 / _DERIVATION;
// パーティクル
public var _dotMap:DotMap;
public var dotData:String;
private var _particleList:Array = []; //:Array :Particle
private var _particleDistance:int;
private var _w:int;
private var _h:int;
// ドラッグ
private var _dragIdX:int = -1;
private var _dragIdY:int = -1;
// レイヤー
private var _bgLayer:Bitmap;
private var _displayLayer:Bitmap;
private var _debugLayer:Sprite;
private var _debugDisplayList:Array = [];
private var _dragLayer:Sprite;
private var _dragList:Array = [];
// ビットマップ
private var _clearBitmap:BitmapData = new BitmapData(STAGE_W, STAGE_H, true, 0x00000000);
private var _displayBitmap:BitmapData = new BitmapData(STAGE_W, STAGE_H);
private var _bgBitmap:BitmapData = new BitmapData(STAGE_W, STAGE_H);
private var _gradiationBitmap:BitmapData = new BitmapData(STAGE_W, STAGE_H);
private var _reflectAlphaBitmap:BitmapData = new BitmapData(STAGE_W, STAGE_H, true, 0x00000000);
private var _rect:Rectangle = new Rectangle(0, 0, STAGE_W, STAGE_H);
private var _point:Point = new Point();
private var _refrectPoint:Point = new Point(0, -2*_GROUND_LINE + STAGE_H);
public function PuyoDot3()
{
new WonderflFelica().doFeliCa(this);
// flexBuilderとの互換性。
}
public function init(isBegin:Boolean = true):void { // ここから開始
// SWF設定
if (isBegin) {
stage.frameRate = 60;
stage.quality = StageQuality.LOW;
var bg:Sprite = new Sprite(); // wonderflではキャプチャに背景色が反映されないので、背景色Spriteで覆う。
bg.graphics.beginFill(0xffffff);
bg.graphics.drawRect(0, 0, STAGE_W, STAGE_H);
addChild(bg);
}
_dotMap = new DotMap(dotData);
if (isBegin) {
addChild(_bgLayer = new Bitmap(_bgBitmap));
addChild(_displayLayer = new Bitmap(_displayBitmap));
addChild(_debugLayer = new Sprite());
addChild(_dragLayer = new Sprite());
_debugLayer.visible = false;
_bgLayer.scaleY = -1;
_bgLayer.y = STAGE_H;
_w = _dotMap.w+1;
_h = _dotMap.h+1;
_particleDistance = _MAP_SIZE / _w;
}
var tmpBaceX:Number = (STAGE_W - _MAP_SIZE) / 2;
var tmpBaceY:Number = 20;
var x:int, y:int;
var particle:Particle;
// 生成
for (x = 0; x < _w; x++){
if (isBegin) {
_particleList[x] = [];
_dragList[x] = [];
}
for (y = 0; y < _h; y++){
particle = _particleList[x][y];
particle = particle == null ? new Particle() : particle;
var tmpNearDotList:Array = [_dotMap.isDot(x, y), _dotMap.isDot(x-1, y),
_dotMap.isDot(x-1, y-1), _dotMap.isDot(x, y-1)];
particle.connect[0] = (tmpNearDotList[0] || tmpNearDotList[3]) && x < _w-1; // 右
particle.connect[1] = (tmpNearDotList[1] || tmpNearDotList[0]) && y < _h-1; // 下
particle.connect[2] = (tmpNearDotList[2] || tmpNearDotList[1]) && 0 < x; // 左
particle.connect[3] = (tmpNearDotList[3] || tmpNearDotList[2]) && 0 < y; // 上
if (!particle.connect[0] && !particle.connect[1] && !particle.connect[2] && !particle.connect[3]){
_particleList[x][y] = null;
continue;
}
particle.color = _dotMap.getColor(x, y);
if (isBegin) {
particle.x = tmpBaceX + _particleDistance * x + Math.random()*3;
particle.y = tmpBaceY + _particleDistance * y;
}
_particleList[x][y] = particle;
createDragSprite(x, y, isBegin);
}
}
for (x = 0; x < _w; x++){
for (y = 0; y < _h; y++){
particle = _particleList[x][y];
if (particle == null) continue;
particle.connect[4] = particle.connect[0] && Particle(_particleList[x+1][y]).connect[0]; // 右右
particle.connect[5] = particle.connect[1] && Particle(_particleList[x][y+1]).connect[1]; // 下下
particle.connect[6] = particle.connect[2] && Particle(_particleList[x-1][y]).connect[2]; // 左左
particle.connect[7] = particle.connect[3] && Particle(_particleList[x][y-1]).connect[3]; // 上上
}
}
if (isBegin) {
trace("init*****************");
displayInit();
// フレームの処理を登録
addEventListener(Event.ENTER_FRAME, frame);
// マウスドラッグ
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpEvent());
}
}
private function createDragSprite(x:int, y:int, isBegin:Boolean):void{ // ドラッグ判定を作る
var sprite:Sprite = _dragList[x][y] == null ? new Sprite() : _dragList[x][y];
if (_dragList[x][y] == null) {
_dragLayer.addChild(sprite);
_dragList[x][y] = sprite;
var g:Graphics = sprite.graphics;
g.beginFill(0x000000, 0);
g.drawCircle(0, 0, _particleDistance*0.8);
// マウスイベント
sprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownEvent(x, y));
}
}
// フレーム挙動
private function frame(event:Event):void{
for (var i:int=0; i<_DERIVATION; i++){
rotate(); // 回転の計算
force(); // 力の計算
move(); // 移動処理
}
draw(); // 描画処理
}
// ボーンの向きを決定する
private function rotate():void{
var x:int, y:int;
for (x = 0; x < _w; x++){
for (y = 0; y < _h; y++){
var particle:Particle = _particleList[x][y];
if (particle == null) continue;
var subParticle:Particle;
if (particle.connect[0]){ // 右パーティクルに対する処理
subParticle = _particleList[x+1][y];
calcConnectRForce(particle, subParticle, 0);
calcConnectRForce(subParticle, particle, _RADIAN180);
}
if (particle.connect[1]){ // 下パーティクルに対する処理
subParticle = _particleList[x][y+1];
calcConnectRForce(particle, subParticle, _RADIAN90);
calcConnectRForce(subParticle, particle, _RADIAN270);
}
if (particle.connect[4]){ // 右右パーティクルに対する処理
subParticle = _particleList[x+2][y];
calcConnectRForce(particle, subParticle, 0);
calcConnectRForce(subParticle, particle, _RADIAN180);
}
if (particle.connect[5]){ // 下下パーティクルに対する処理
subParticle = _particleList[x][y+2];
calcConnectRForce(particle, subParticle, _RADIAN90);
calcConnectRForce(subParticle, particle, _RADIAN270);
}
if (x == _dragIdX && y == _dragIdY) particle.vr *= _MOUSE_ROTATE_FRICTION;
else particle.vr *= _ROTATE_FRICTION; // 摩擦
particle.radian += particle.vr;
}
}
}
// 接続されたパーツの回転方向を計算する
private function calcConnectRForce(particle:Particle, targetParticle:Particle, connectAngle:Number):void{
var angle:Number = Math.atan2(targetParticle.y - particle.y, targetParticle.x - particle.x);
particle.vr += ajustRadian(angle - (connectAngle + particle.radian)) * _ROTATION_RATE;
}
private function force():void{
var x:int, y:int;
for (x = 0; x < _w; x++){
for (y = 0; y < _h; y++){
var particle:Particle = _particleList[x][y];
if (particle == null) continue;
var subParticle:Particle;
if (particle.connect[0]){ // 右パーティクルに対する処理
subParticle = _particleList[x+1][y];
calcConnectFoce(particle, subParticle, 0, _particleDistance);
calcConnectFoce(subParticle, particle, _RADIAN180, _particleDistance);
}
if (particle.connect[1]){ // 下パーティクルに対する処理
subParticle = _particleList[x][y+1];
calcConnectFoce(particle, subParticle, _RADIAN90, _particleDistance);
calcConnectFoce(subParticle, particle, _RADIAN270, _particleDistance);
}
if (particle.connect[4]){ // 右右パーティクルに対する処理
subParticle = _particleList[x+2][y];
calcConnectFoce(particle, subParticle, 0, _particleDistance*2);
calcConnectFoce(subParticle, particle, _RADIAN180, _particleDistance*2);
}
if (particle.connect[5]){ // 下下パーティクルに対する処理
subParticle = _particleList[x][y+2];
calcConnectFoce(particle, subParticle, _RADIAN90, _particleDistance*2);
calcConnectFoce(subParticle, particle, _RADIAN270, _particleDistance*2);
}
particle.ay += _GRAVITY;
if (_dragIdX == x && _dragIdY == y){ // マウスで引っ張る
var point:Point = pullForce(particle.x, particle.y, mouseX, mouseY, _MOUSE_PULL_RATE);
particle.ax += point.x;
particle.ay += point.y;
particle.vx *= _MOUSE_MOVE_FRICTION;
particle.vy *= _MOUSE_MOVE_FRICTION;
}
}
}
}
// 接続された2パーツの力を計算する
private function calcConnectFoce(particle:Particle, targetParticle:Particle, connectAngle:Number, distance:Number):void{
var toAngle:Number = ajustRadian(connectAngle + particle.radian);
var toX:Number = particle.x + Math.cos(toAngle) * distance;
var toY:Number = particle.y + Math.sin(toAngle) * distance;
var ax:Number = (targetParticle.x - toX) * _VERTICAL_RATE;
var ay:Number = (targetParticle.y - toY) * _VERTICAL_RATE;
particle.ax += ax;
particle.ay += ay;
targetParticle.ax -= ax;
targetParticle.ay -= ay;
}
// ポイントx1 y1を、ポイントx2 y2へ、係数rateだけ移動させる場合の、XYの力を返す
private function pullForce(x1:Number, y1:Number, x2:Number, y2:Number, rate:Number):Point{
var point:Point = new Point();
var distance:Number = calcDistance(x1, y1, x2, y2);
var angle:Number = Math.atan2(y2 - y1, x2 - x1);
point.x = Math.cos(angle) * distance * rate;
point.y = Math.sin(angle) * distance * rate;
return point;
}
// ポイントx1 y1から、ポイントx2 y2までの距離
private function calcDistance(x1:Number, y1:Number, x2:Number, y2:Number):Number{
return Math.sqrt(Math.pow(x2-x1, 2) + Math.pow(y2-y1, 2));
}
// radian角度を、-π~πの範囲に修正する
private function ajustRadian(radian:Number):Number{
return radian - _PI2 * Math.floor( 0.5 + radian / _PI2);
}
private function move():void{
var x:int, y:int;
for (x = 0; x < _w; x++){
for (y = 0; y < _h; y++){
var particle:Particle = _particleList[x][y];
if (particle == null) continue;
// 空気抵抗 TODO:速度に対しての処理で良いはず。
particle.ax += -_FRICTION * particle.vx;
particle.ay += -_FRICTION * particle.vy;
// 速度、位置への反映
particle.vx += particle.ax;
particle.vy += particle.ay;
particle.x += particle.vx;
particle.y += particle.vy;
particle.ax = 0;
particle.ay = 0; // 力をクリア
// 壁チェック
if (0 < particle.vy && _GROUND_LINE < particle.y){
particle.y = _GROUND_LINE;
particle.vy *= -0.8;
if (particle.vy < -50) particle.vy = -50;
particle.vx *= _GROUND_FRICTION;
}
if (particle.vx < 0 && particle.x < _WALL_LEFT){
particle.x = _WALL_LEFT;
particle.vx = 0;
particle.vy *= _GROUND_FRICTION;
}else if (0 < particle.vx && _WALL_RIGHT < particle.x){
particle.x = _WALL_RIGHT;
particle.vx = 0;
particle.vy *= _GROUND_FRICTION;
}
// ドラッグエリアを移動
var sprite:Sprite = _dragList[x][y];
sprite.x = particle.x;
sprite.y = particle.y;
}
}
}
private var _drawShape:Shape = new Shape();
private function displayInit():void{
var g:Graphics = _drawShape.graphics;
g.clear();
var matrix:Matrix = new Matrix();
matrix.createGradientBox(STAGE_W, STAGE_H, Math.PI / 2, 0, 0);
g.beginGradientFill(GradientType.LINEAR, [0xf8f8f8, 0xe8e8e8], [1, 1], [0, 255], matrix);
g.drawRect(0, 0, STAGE_W, STAGE_H);
_gradiationBitmap.draw(_drawShape);
g.clear();
g.beginGradientFill(GradientType.LINEAR, [0x000000, 0x000000], [0, 0.3], [125, 230], matrix);
g.drawRect(0, 0, STAGE_W, STAGE_H);
_reflectAlphaBitmap.draw(_drawShape);
}
private function draw():void{
var g:Graphics = _drawShape.graphics;
var particle:Particle;
g.clear();
var x:int, y:int;
for (y = 0; y < _h-1; y++){
for (x = 0; x < _w-1; x++){
if(!_dotMap.isDot(x, y)) continue; // ドットが無いなら描画省略
g.beginFill(_dotMap.getColor(x, y));
particle = _particleList[x][y];
g.moveTo(particle.x, particle.y);
particle = _particleList[x+1][y];
g.lineTo(particle.x, particle.y);
particle = _particleList[x+1][y+1];
g.lineTo(particle.x, particle.y);
particle = _particleList[x][y+1];
g.lineTo(particle.x, particle.y);
g.endFill();
}
}
_displayBitmap.copyPixels(_clearBitmap, _rect, _point);
_displayBitmap.draw(_drawShape);
_bgBitmap.copyPixels(_gradiationBitmap, _rect, _point);
_bgBitmap.copyPixels(_displayBitmap, _rect, _refrectPoint, _reflectAlphaBitmap, _point, true);
}
// マウスイベント
private function mouseDownEvent(x:int, y:int):Function{
return function (event:Event):void{ startBornDrag(x, y);};
}
private function mouseUpEvent():Function{
return function (event:Event):void{ endBornDrag();};
}
// ドラッグ
private function startBornDrag(x:int, y:int):void{
_dragIdX = x;
_dragIdY = y;
}
private function endBornDrag():void{
_dragIdX = -1;
_dragIdY = -1;
}
// private function debugInit():void{
// var x:int, y:int;
// for (x = 0; x < _w; x++){
// _debugDisplayList[x] = [];
// for (y = 0; y < _h; y++){
// var sprite:Sprite = new Sprite();
// var g:Graphics = sprite.graphics;
// var radius:Number = 5;
// g.lineStyle(0, 0xff0000, 1);
// g.beginFill(0xff0000, 0.3);
// g.drawCircle(0, 0, radius);
// g.endFill();
// g.moveTo(0, 0);
// g.lineTo(radius*2, 0);
// _debugDisplayList[x][y] = sprite;
// _debugLayer.addChild(sprite);
// }
// }
// }
// private function debugDraw():void{
// var x:int, y:int;
// for (x = 0; x < _w; x++){
// for (y = 0; y < _h; y++){
// var particle:Particle = _particleList[x][y];
// if (particle == null) continue;
// var sprite:Sprite = _debugDisplayList[x][y];
// sprite.x = particle.x;
// sprite.y = particle.y;
// sprite.rotation = particle.radian * _TO_DEGREE;
// }
// }
// }
}
}
import com.sony.jp.felica.FeliCaCloseReaderWriterRequest;
import com.sony.jp.felica.FeliCaCloseReaderWriterResponse;
import com.sony.jp.felica.FeliCaControl;
import com.sony.jp.felica.FeliCaOpenReaderWriterAutoRequest;
import com.sony.jp.felica.FeliCaOpenReaderWriterAutoResponse;
import com.sony.jp.felica.FeliCaPollingAndGetCardInformationRequest;
import com.sony.jp.felica.FeliCaPollingAndGetCardInformationResponse;
import com.sony.jp.felica.FeliCaSessionRequest;
import com.sony.jp.felica.FeliCaSessionResponse;
import com.sony.jp.felica.NFCType3TagRequest;
import com.sony.jp.felica.NFCType3TagResponse;
import com.sony.jp.felica.error.FeliCaAccessError;
import com.sony.jp.felica.event.FeliCaStatusEvent;
import com.sony.jp.felica.event.OpenStatusEvent;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.TimerEvent;
import flash.utils.Timer;
class Particle
{
public var x:Number = 0; // 位置
public var y:Number = 0;
public var vx:Number = 1990; // 速度
public var vy:Number = 0;
public var ax:Number = -50; // 加速度=力 TOTO:最後まで意味無かったら消す
public var ay:Number = 0;
public var radian:Number = 0; // 向き
public var vr:Number = 0; // 向き速度
public var color:uint = 0x000000; // パーティクルの色。右下の枠の色
public var connect:Array = [true, true, true, true]; // パーティクルの接続状態を毎回チェックしなくていいように、保持しておく
}
class DotMap // ドットのカラー情報元
{
public var w:uint = 16;
public var h:uint = 13;
public var pallet:Array = []; // カラーパレット。ゼロ番は透過色予定:uint
public var strPallet:Array = []; // :String
public var strMap:String = "";
public var map:Array = []; // ピクセルマップ:int
function DotMap(data:String){
init(data);
readMap();
}
protected function init(data:String):void{
w = 16;
h = 13;
//pallet = [0x000000, 0xFF0000,0xDC143C,0xB22222,0x800000,0x8B0000,0xA52A2A,0xA0522D,0x8B4513,0xCD5C5C,0xBC8F8F,0xF08080,0xFA8072,0xE9967A,0xFF7F50,0xFF6347,0xF4A460,0xFFA07A,0xCD853F,0xD2691E,0xFF4500,0xFFA500,0xFF8C00,0xD2B48C,0xFFDAB9,0xFFE4C4,0xFFE4B5,0xFFDEAD,0xF5DEB3,0xDEB887,0xB8860B,0xDAA520,0xFFD700,0xFFFF00,0xFAFAD2,0xEEE8AA,0xF0E68C,0xBDB76B,0x7CFC00,0xADFF2F,0x7FFF00,0x00FF00,0x32CD32,0x9ACD32,0x808000,0x6B8E23,0x556B2F,0x228B22,0x006400,0x008000,0x2E8B57,0x3CB371,0x8FBC8F,0x90EE90,0x98FB98,0x00FF7F,0x00FA9A,0x008080,0x008B8B,0x20B2AA,0x66CDAA,0x5F9EA0,0x4682B4,0x7FFFD4,0xB0E0E6,0xAFEEEE,0xADD8E6,0xB0C4DE,0x87CEEB,0x87CEFA,0x48D1CC,0x40E0D0,0x00CED1,0x00FFFF,0x00FFFF,0x00BFFF,0x1E90FF,0x6495ED,0x4169E1,0x0000FF,0x0000CD,0x000080,0x00008B,0x191970,0x483D8B,0x6A5ACD,0x7B68EE,0x9370DB,0x9932CC,0x9400D3,0x8A2BE2,0xBA55D3,0xDDA0DD,0xE6E6FA,0xD8BFD8,0xDA70D6,0xEE82EE,0x4B0082,0x8B008B,0x800080,0xC71585,0xFF1493,0xFF00FF,0xFF00FF,0xFF69B4,0xDB7093,0xFFB6C1,0xFFC0CB,0xFFE4E1,0xFFEBCD,0xFFFFE0,0xFFF8DC,0xFAEBD7,0xFFEFD5,0xFFFACD,0xF5F5DC,0xFAF0E6,0xFDF5E6,0xE0FFFF,0xF0F8FF,0xF5F5F5,0xFFF0F5,0xFFFAF0,0xF5FFFA,0xF8F8FF,0xF0FFF0,0xFFF5EE,0xFFFFF0,0xF0FFFF,0xFFFAFA,0xFFFFFF,0xDCDCDC,0xD3D3D3,0xC0C0C0,0xA9A9A9,0x778899,0x708090,0x808080,0x696969,0x2F4F4F];
//strPallet =["B", "0", "1","2","3","4","5","6","7","8","9",":",";","<","A","@","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","]","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","¡","¢","£","¤","²","³","µ","¶","»","À","Á","Â","Ã","Ä","Å","Æ","Ç","ÈF","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ","Ò","Ó","Ô","Õ","Ö","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß","à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï","ð","ñ","ò","ó","ô","õ","ö","ø","ù","ú","û","ü","ý","þ","B"];
pallet = [ 0x000000
,0x0000ff
,0x0033ff
,0x0066ff
,0x0099ff
,0x00ccff
,0x00ffff
,0x000099
,0x009999
,0x00cc99
,0x00ff99
,0x000099
,0x003399
,0x006699
,0x3300ff
,0x3333ff
,0x3366ff
,0x3399ff
,0x33ccff
,0x33ffff
,0x330099
,0x333399
,0x336699
,0x339999
,0x33cc99
,0x33ff99
,0x330033
,0x333333
,0x336633
,0x339900
,0x33cc00
,0x33ff00
,0x6600ff
,0x6633ff
,0x6666ff
,0x6699ff
,0x66ccff
,0x66ffff
,0x660066
,0x663366
,0x666666
,0x669966
,0x66cc66
,0x66ff66
,0x990099
,0x993399
,0x996699
,0x999999
,0x99cc99
,0x99ff99
,0x990000
,0x993300
,0x996600
,0x999900
,0x99cc00
,0x99ff00
,0xcc00ff
,0xcc33ff
,0xcc66ff
,0xcc99ff
,0xccccff
,0xccffff
,0xcc0066
,0xcc3366
,0xcc6666
,0xcc9966
,0xcccc66
,0xccff66
,0xff00ff
,0xff33ff
,0xff66ff
,0xff99ff
,0xffccff
,0xffffff
,0xff0000
,0xff3300
,0xff6600
,0xff9900
,0xffcc00
,0xffff00
,0xFFCC66
,0xFFFF99
,0x00FF00
,0x00CC00
,0x009900
,0x006600
,0x003300
,0x00FF33
,0x009933
,0x666666
,0x999999
,0xCCCCCC
,0x000001];
strPallet =[
"!",
"#",
"$",
"%",
"&",
"'",
"(",
")",
",",
"-",
".",
"/",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
":",
";",
"<",
"=",
">",
"?",
"@",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"[",
"\\",
"]",
"^",
"_",
"`",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"*",
"+",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"{",
"|",
"}",
"~"];
strMap = data + "";
}
public function readMap():void{
for (var i:int; i<w*h; i++){
map.push(strPallet.indexOf(strMap.substr(i, 1)));
}
}
public function isDot(x:int, y:int):Boolean{
if (x < 0 || y < 0 || w <= x || h <= y) return false;
if (map[x + y*w] == 0) return false;
return true;
}
public function getColor(x:int, y:int):uint{
if (x < 0 || y < 0 || w <= x || h <= y) return 0;
return pallet[map[x + y*w]];
}
}
class WonderflFelica extends EventDispatcher{
// FeliCaProxy との通信を行うコントロールクラス
private var fc:FeliCaControl = new FeliCaControl();
private var out:String = "";
private var par:PuyoDot3 = null;
private var isBegin:Boolean = false;
private var t:Timer = new Timer(1000);
private var restartTimer:Timer = new Timer(300);
public function doFeliCa(p:PuyoDot3 = null):void
{
isBegin = p != null;
if (p) {
par = p;
par.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_COMPLETE, onReadData);
// リスナー登録
fc.addEventListener(OpenStatusEvent.OPEN_COMPLETE, onOpenComplete);
fc.addEventListener(OpenStatusEvent.OPEN_FAILURE, onOpenFailure);
fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_COMPLETE, onFeliCaAccessComplete);
fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_FAILURE, onFeliCaAccessFailure);
fc.addEventListener(FeliCaStatusEvent.FELICA_ACCESS_PARAMETER_ERROR, onFeliCaAccessParameterError);
}
// FeliCaProxy の認証
// wonderflの中ではこのキーをお使いください wonderfl外では使用できません
// use this Standard key in wonderfl, it doesn't work outside wonderfl
fc.open(10250,"__FELICA_STANDARD_KEY__", "");
//fc.open(10250);
}
private function onReadData(event:FeliCaStatusEvent):void {
par.dotData = out;
par.init(isBegin);
out = "";
t.addEventListener(TimerEvent.TIMER, onTimerEventHandler);
t.start();
}
private function onTimerEventHandler(event:TimerEvent):void {
t.stop();
t.removeEventListener(TimerEvent.TIMER, onTimerEventHandler);
doFeliCa();
}
private function onRestartInit(event:TimerEvent):void {
restartTimer.stop();
restartTimer.removeEventListener(TimerEvent.TIMER, onRestartInit);
doFeliCa(par);
}
public function get data():String {
return out;
}
// FeliCaProxy との認証完了時
private function onOpenComplete(evt:OpenStatusEvent):void
{
//displayMessage("FeliCaProxy との認証に成功しました。");
// リーダ/ライタの専有
//RwLock();
RwOpen();
}
// FeliCaProxy との認証処理でエラー発生時
private function onOpenFailure(evt:OpenStatusEvent):void
{
var error:Error = evt.object as Error;
FeliCaProxyClose();
//displayMessage( "FeliCaProxy との相互認証に失敗しました。\n" +
// " ERROR : (" + error.errorID + ") " + error.message);
}
// FeliCa アクセス成功時
private function onFeliCaAccessComplete(evt:FeliCaStatusEvent):void
{
if (evt.object is FeliCaSessionResponse)
{
var session:FeliCaSessionResponse = evt.object as FeliCaSessionResponse;
// リーダ/ライタの専有
if (session.type == FeliCaSessionResponse.HOLD)
{
//displayMessage("リーダ/ライタの専有しました。");
// リーダ/ライタのオープンを実行
RwOpen();
}
// リーダ/ライタの開放
else
{
//displayMessage("リーダ/ライタの専有を開放しました。");
// FeliCaProxy の切断
FeliCaProxyClose();
}
}
else if (evt.object is FeliCaOpenReaderWriterAutoResponse)
{
//displayMessage("リーダ/ライタのオープンに成功しました。");
// FeliCa を検出するために、Polling の実行
Polling();
}
else if (evt.object is FeliCaPollingAndGetCardInformationResponse)
{
var response:FeliCaPollingAndGetCardInformationResponse = evt.object as FeliCaPollingAndGetCardInformationResponse;
readFeliCaData();
// リーダ/ライタのクローズを実行
}
else if (evt.object is FeliCaCloseReaderWriterResponse)
{
//displayMessage("リーダ/ライタのクローズに成功しました。");
// リーダ/ライタ専有の開放
RwUnlock();
} else if (evt.object is NFCType3TagResponse) {
var r:NFCType3TagResponse = evt.object as NFCType3TagResponse;
if (r.type == NFCType3TagResponse.READ) {
trace("読み込み完了");
var readData:String = r.data;
var nextData:uint = 2;
if (readData != null && readData != "") {
for (var i:uint=0; i < readData.length; i +=nextData) {
var c:uint = uint("0x" + readData.substring(i, (i + nextData)));
out +=String.fromCharCode(c);
}
trace("data =>" + out);
par.dispatchEvent(
new FeliCaStatusEvent(FeliCaStatusEvent.FELICA_ACCESS_COMPLETE, evt.object));
}
RwClose();
restartTimer.stop();
restartTimer.removeEventListener(TimerEvent.TIMER, onRestartInit);
} else if (r.type == NFCType3TagResponse.WRITE) {
trace("書き込み完了");
RwClose();
}
}
}
// FeliCa アクセス失敗時
private function onFeliCaAccessFailure(evt:FeliCaStatusEvent):void
{
var errorMsg:String;
if (evt.object is FeliCaAccessError)
{
var error1:FeliCaAccessError = evt.object as FeliCaAccessError;
}
else if (evt.object is Error)
{
var error2:Error = evt.object as Error;
errorMsg = " ERROR : (" + error2.errorID + ") " + error2.message;
}
// FeliCaProxy の切断
FeliCaProxyClose();
}
// FeliCa アクセスパラメータ設定エラー発生時
private function onFeliCaAccessParameterError(evt:FeliCaStatusEvent):void
{
var error:Error = evt.object as Error;
// FeliCaProxy の切断
FeliCaProxyClose();
}
// FeliCaProxy の切断
private function FeliCaProxyClose():void
{
fc.close();
if (isBegin) {
restartTimer.addEventListener(TimerEvent.TIMER, onRestartInit);
restartTimer.start();
} else {
t.addEventListener(TimerEvent.TIMER, onTimerEventHandler);
t.start();
}
}
// リーダ/ライタの専有を実行
private function RwLock():void
{
// リーダ/ライタを専有する為の情報の設定
var request:FeliCaSessionRequest = new FeliCaSessionRequest();
request.type = FeliCaSessionRequest.HOLD; // リーダ・ライタ専有要求
request.lockTimeout = 10; // 専有(Lock)するまでのタイムアウト時間(秒)
request.unlockTimeout = 60; // 専有(Lock)してから開放(Unlock)するまでの見込み時間(秒)
// FeliCaProxyは、このunlockTimeout時間経過した場合自動でR/W開放を行う。
// リーダ/ライタ専有を実行
fc.access(request);
}
// リーダ/ライタ専有の開放を実行
private function RwUnlock():void
{
// リーダ/ライタ専有を開放する為の情報の設定
var request:FeliCaSessionRequest = new FeliCaSessionRequest();
request.type = FeliCaSessionRequest.RELEASE; // リーダ・ライタ開放要求
// リーダ/ライタ専有開放を実行
fc.access(request);
}
// リーダ/ライタのオープンを実行
private function RwOpen():void
{
// [open_reader_writer_auto] コマンドを実行
fc.access(new FeliCaOpenReaderWriterAutoRequest());
}
// FeliCa を検出するために、Polling の実行
private function Polling():void
{
// [polling_and_get_card_information] コマンドを実行する為の情報の設定
var request:FeliCaPollingAndGetCardInformationRequest = new FeliCaPollingAndGetCardInformationRequest();
request.systemCode = "FFFF"; // ポーリングするシステムコード
// [polling_and_get_card_information] コマンドを実行
fc.access(request);
}
// リーダ/ライタのクローズを実行
private function RwClose():void
{
// [close_reader_writer] コマンドを実行
fc.access(new FeliCaCloseReaderWriterRequest());
}
private function readFeliCaData():void {
// NFC Type3 Tag のデータを読み込みする為の情報の設定
var request:NFCType3TagRequest = new NFCType3TagRequest();
request.type = NFCType3TagRequest.READ; // NFC Type3 Tag データを読み込み要求
// NFC Type3 Tag データの読み込みを実行
fc.access(request);
}
}