forked from: ぷよっとしたスライム。png画像から作る版。
forked from ぷよっとしたスライム。png画像から作る版。 (diff: 402)
import flash.events.*; import flash.filters.*; import flash.geom.*; import flash.text.*; import flash.utils.*;
♥0 |
Line 438 |
Modified 2011-03-21 18:19:38 |
MIT License
archived:2017-03-09 23:12:31
| (replaced)
ActionScript3 source code
/**
* Copyright Akiyah ( http://wonderfl.net/user/Akiyah )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/5V6o
*/
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
public class PuyoDot3 extends Sprite {
//private var _rect:Rectangle = new Rectangle(0, 0, PuyoDot.STAGE_W, PuyoDot.STAGE_H);
//private var _point:Point = new Point();
private var _displayLayer:Bitmap;
// ビットマップ
private var _clearBitmap:BitmapData = new BitmapData(PuyoDot.STAGE_W, PuyoDot.STAGE_H, true, 0x00000000);
private var _displayBitmap:BitmapData = new BitmapData(PuyoDot.STAGE_W, PuyoDot.STAGE_H);
private var bmd:BitmapData;
private var loader:Loader = new Loader();
Security.loadPolicyFile("http://assets.wonderfl.net/crossdomain.xml");
private var puyoDot:PuyoDot = new PuyoDot();
public function PuyoDot3() {
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadDone);
loader.load(new URLRequest("http://assets.wonderfl.net/images/related_images/e/e1/e1b1/e1b1a2d1ea3db94a33f5eb77daaf9125081062b7"));
}
private function loadDone(e:Event):void {
bmd = new BitmapData(loader.width,loader.height,true,0x000000);
bmd.draw(loader);
init();
}
private function init():void {
_displayLayer = new Bitmap(_displayBitmap);
addChild(_displayLayer);
puyoDot.init(new MapSlime(), drawParticles);
// フレームの処理を登録
addEventListener(
Event.ENTER_FRAME,
function (event:Event):void{
puyoDot.frame(mouseX, mouseY)
});
// マウスドラッグ
this.stage.addEventListener(MouseEvent.MOUSE_DOWN,
function(e:Event):void {
puyoDot.startBornDrag(mouseX, mouseY);
});
this.stage.addEventListener(MouseEvent.MOUSE_UP,
function(e:Event):void {
puyoDot.endBornDrag();
});
}
private var _drawShape:Shape = new Shape();
public function drawParticles(particleList:Array, dotMap:DotMap, _h:int, _w:int):void{
var g:Graphics = _drawShape.graphics;
g.clear();
var x:int, y:int;
var n:int = 17;
//g.lineStyle(1, 0x000000, 0.1);
for (y = 0; y < _h-1; y++){
for (x = 0; x < _w-1; x++){
if(!dotMap.isDot(x, y)) continue; // ドットが無いなら描画省略
drawSquare(g, bmd, new Point(x*n,y*n), n,
particleList[x][y].getPoint(),
particleList[x+1][y].getPoint(),
particleList[x][y+1].getPoint(),
particleList[x+1][y+1].getPoint());
}
}
_displayBitmap.copyPixels(_clearBitmap,
new Rectangle(0, 0, PuyoDot.STAGE_W, PuyoDot.STAGE_H),
new Point(0, 0));
_displayBitmap.draw(_drawShape);
}
private function drawSquare(g:Graphics, bmd:BitmapData, start:Point, len:Number,
p0:Point, p1:Point, p2:Point, p3:Point):void{
var a:Triangle;
var b:Triangle;
a = new Triangle(start,
start.add(new Point(len, 0)),
start.add(new Point(0, len)));
b = new Triangle(p0, p1, p2);
drawTriangle(g, bmd, Triangle.transformMatrix(a, b), b);
a = new Triangle(start.add(new Point(len, 0)),
start.add(new Point(len, len)),
start.add(new Point(0, len)));
b = new Triangle(p1, p3, p2);
drawTriangle(g, bmd, Triangle.transformMatrix(a, b), b);
}
private function drawTriangle(g:Graphics, bmd:BitmapData,
m:Matrix, b:Triangle):void{
g.beginBitmapFill(bmd, m);
g.moveTo(b.p0.x, b.p0.y);
g.lineTo(b.p1.x, b.p1.y);
g.lineTo(b.p2.x, b.p2.y);
g.lineTo(b.p0.x, b.p0.y);
g.endFill();
}
}
}
import flash.geom.Point;
import flash.geom.Matrix;
class PuyoDot {
public static const STAGE_W:uint = 465;
public static const STAGE_H:uint = 465;
// パーティクル
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 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;
private var _dotMap:DotMap;
private var drawFunction:Function;
public function init(dotMap:DotMap, drawFunction:Function):void { // ここから開始
this._dotMap = dotMap;
this.drawFunction = drawFunction;
_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++) {
_particleList[x] = [];
for (y = 0; y < _h; y++) {
particle = new 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);
particle.x = tmpBaceX + _particleDistance * x + Math.random()*3;
particle.y = tmpBaceY + _particleDistance * y;
_particleList[x][y] = particle;
}
}
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]; // 上上
}
}
}
// ドラッグ
public function startBornDrag(mouseX:int, mouseY:int):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;
if (Math.pow(particle.x - mouseX, 2) + Math.pow(particle.y - mouseY, 2) < Math.pow(_particleDistance*0.8, 2)) {
_dragIdX = x;
_dragIdY = y;
return;
}
}
}
}
public function endBornDrag():void{
_dragIdX = -1;
_dragIdY = -1;
}
// フレーム挙動
public function frame(mouseX:Number, mouseY:Number):void{
for (var i:int=0; i<_DERIVATION; i++){
rotate();
force(mouseX, mouseY);
move();
}
drawFunction(_particleList, _dotMap, _h, _w);
//main.drawPparticles(_particleList, _dotMap, _h, _w); // 描画処理
}
// ボーンの向きを決定する
public 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;
}
public function force(mouseX:Number, mouseY:Number):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);
}
public 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;
}
}
}
}
}
class Particle {
public var x:Number = 0; // 位置
public var y:Number = 0;
public var vx:Number = 0; // 速度
public var vy:Number = 0;
public var ax:Number = 0; // 加速度=力 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]; // パーティクルの接続状態を毎回チェックしなくていいように、保持しておく
public function getPoint():Point {
return new Point(x, y);
}
}
class DotMap {
public var w:uint = 16;
public var h:uint = 16;
public var pallet:Array = []; // カラーパレット。ゼロ番は透過色予定:uint
public var strPallet:Array = []; // :String
public var strMap:String = "";
public var map:Array = []; // ピクセルマップ:int
function DotMap() {
init();
readMap();
}
protected function init():void {
w = 16; // 16くらいが妥当。あんまり多すぎると自重で潰れるし、重い
h = 16;
pallet = [0x000000, 0xDC2900, 0xFFA53B, 0x8B7300]; // 一応何色でも可能
strPallet = ["_", "○", "□", "■"];
strMap =
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■"+
"■■■■■■■■■■■■■■■■";
}
private 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 MapSlime extends DotMap {
override protected function init():void{
w = 16;
h = 16;
pallet = [0x000000, 0xffffff];
strPallet = ["_", "w"];
strMap =
"________________"+
"_______ww_______"+
"_______ww_______"+
"______wwww______"+
"______wwww______"+
"____wwwwwwww____"+
"__wwwwwwwwwwww__"+
"_wwwwwwwwwwwwww_"+
"wwwwwwwwwwwwwwww"+
"wwwwwwwwwwwwwwww"+
"wwwwwwwwwwwwwwww"+
"wwwwwwwwwwwwwwww"+
"wwwwwwwwwwwwwwww"+
"_wwwwwwwwwwwwww_"+
"__wwwwwwwwwwww__"+
"____wwwwwwww____"+
"";
}
}
class Triangle {
public var p0:Point;
public var p1:Point;
public var p2:Point;
function Triangle(p0:Point, p1:Point, p2:Point) {
this.p0 = p0;
this.p1 = p1;
this.p2 = p2;
}
public function matrix():Matrix {
return new Matrix(
p1.x - p0.x, p1.y - p0.y,
p2.x - p0.x, p2.y - p0.y);
}
public static function transformMatrix(a:Triangle, b:Triangle):Matrix {
var ma : Matrix = a.matrix();
ma.invert();
var mb : Matrix = b.matrix();
var m : Matrix = new Matrix();
m.translate(-a.p0.x, -a.p0.y);
m.concat(ma);
m.concat(mb);
m.translate(b.p0.x, b.p0.y);
return m;
}
}