forked from: KATAMARU? OR NOT
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zCEY
*/
// forked from beinteractive's KATAMARU? OR NOT
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.PixelSnapping;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.display.Graphics;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import com.bit101.components.Label;
public class KatamaruOrNot extends Sprite
{
private static const ZERO:Point = new Point(0, 0);
private static const STATE_INPUT:uint = 0;
private static const STATE_SHOT:uint = 1;
private static const STATE_GAMEOVER:uint = 2;
public function KatamaruOrNot()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.quality = StageQuality.LOW;
var sw:Number = stage.stageWidth;
var sh:Number = stage.stageHeight;
_ballBackground = new Sprite();
_ballBackground.x = sw / 2;
_ballBackground.y = sh / 2 - 80;
_ballBackground.graphics.clear();
_ballBackground.graphics.lineStyle(0, 0xcccccc);
_ballBackground.graphics.drawCircle(0, 0, 100);
addChild(_ballBackground);
_ballLayer = new Sprite();
_ballLayer.x = sw / 2;
_ballLayer.y = sh / 2 - 80;
addChild(_ballLayer);
_shotLayer = new Sprite();
addChild(_shotLayer);
_particleLayer = new Sprite();
addChild(_particleLayer);
_ballsBitmapData = new BitmapData(sw, sh, true, 0x00000000);
_ballsBitmapData.lock();
_shotBitmapData = new BitmapData(sw, sh, true, 0x00000000);
_shotBitmapData.lock();
_ballsBitmapDataMatrix = new Matrix();
_scoreField = new Label(this, 5, 3);
_titleField = new Label(this, 0, 3, 'KATAMARU? OR NOT');
_titleField.autoSize = true;
new Label(this, 5, (sh - (21 + 14 * 3)), '[SPACEKEY]: SHOOT');
new Label(this, 5, (sh - (21 + 14 * 2)), 'KATAMATTA: +20');
new Label(this, 5, (sh - (21 + 14 * 1)), 'KATAMARANAI: -10');
new Label(this, 5, (sh - (21 + 14 * 0)), 'HAMIDETA: GAMEOVER');
startGame();
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
addEventListener(Event.ENTER_FRAME, initialEnterFrameHandler);
}
private var _ballBackground:Sprite;
private var _ballLayer:Sprite;
private var _shotLayer:Sprite;
private var _particleLayer:Sprite;
private var _scoreField:Label;
private var _titleField:Label;
private var _shotBall:KatamariBall;
private var _ballsBitmapData:BitmapData;
private var _shotBitmapData:BitmapData;
private var _ballsBitmapDataMatrix:Matrix;
private var _shotAngle:Number;
private var _shotAngleCounter:Number;
private var _particles:Array = [];
private var _isSpaceDown:Boolean = false;
private var _nowState:uint;
private var _score:int;
private function initialEnterFrameHandler(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, initialEnterFrameHandler);
_titleField.x = stage.stageWidth - (_titleField.width + 5);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private var deb : Label;
private function startGame():void
{
while (_ballLayer.numChildren > 0) {
_ballLayer.removeChild(_ballLayer.getChildAt(0));
}
_ballLayer.addChild(new KatamariBall(40));
_shotBall = null;
_score = 0;
deb = new Label(this, 5, 30);
_algo = Algorithm.algo(Sprite(_ballLayer.getChildAt(0)).graphics, deb, this);
_t = 0;
_p = 0;
startInput();
}
private function startInput():void
{
_nowState = STATE_INPUT;
_shotAngleCounter = 0;
_shotBall = new KatamariBall();
_shotBall.x = stage.stageWidth / 2;
_shotBall.y = stage.stageHeight - 30;
_shotLayer.addChild(_shotBall);
}
private function keyDownHandler(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.SPACE) {
_isSpaceDown = true;
}
}
private function keyUpHandler(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.SPACE) {
_isSpaceDown = false;
}
}
private var _algo : Array;
private var _t : int;
private var _p : int;
private function enterFrameHandler(e:Event):void
{
updateParticles();
if (_nowState == STATE_GAMEOVER) {
_scoreField.text = 'GAMEOVER: ' + _score;
if (_isSpaceDown) {
_isSpaceDown = false;
startGame();
}
return;
}
_ballLayer.rotation += 2;
_ballBackground.rotation = _ballLayer.rotation;
if (_nowState == STATE_INPUT) {
var bx:Number = stage.stageWidth / 2;
var by:Number = stage.stageHeight;
_shotAngle = (150 - Math.sin(_shotAngleCounter) * 120) / 360 * Math.PI;
_shotAngleCounter += Math.PI / 60;
_shotBall.x = bx + Math.cos(_shotAngle) * 50;
_shotBall.y = by - Math.sin(_shotAngle) * 50;
_shotLayer.graphics.clear();
_shotLayer.graphics.lineStyle(0, 0xcccccc);
_shotLayer.graphics.drawCircle(bx, by, 50);
_shotLayer.graphics.lineStyle(0, 0x333333);
_shotLayer.graphics.moveTo(bx, by);
_shotLayer.graphics.lineTo(_shotBall.x, _shotBall.y);
if (_isSpaceDown) {
_nowState = STATE_SHOT;
_shotBall.positionX = _shotBall.x;
_shotBall.positionY = _shotBall.y;
_shotBall.velocityX = Math.cos(_shotAngle) * 18;
_shotBall.velocityY = Math.sin(_shotAngle) * -18;
}else{
if(_p < _algo.length && _t == _algo[_p] - 1){
dispatchEvent(new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 0, Keyboard.SPACE));
_t = 0;
_p++;
}else{
_t++;
}
}
}
if (_nowState == STATE_SHOT) {
dispatchEvent(new KeyboardEvent(KeyboardEvent.KEY_UP, true, false, 0, Keyboard.SPACE));
moveBall(_shotBall);
_ballsBitmapDataMatrix.identity();
_ballsBitmapDataMatrix.rotate(_ballLayer.rotation / 360 * Math.PI * 2);
_ballsBitmapDataMatrix.translate(_ballLayer.x, _ballLayer.y);
_ballsBitmapData.fillRect(_ballsBitmapData.rect, 0x00000000);
_ballsBitmapData.draw(_ballLayer, _ballsBitmapDataMatrix);
_shotBitmapData.fillRect(_shotBitmapData.rect, 0x00000000);
_shotBitmapData.draw(_shotLayer);
if (_ballsBitmapData.hitTest(ZERO, 128, _shotBitmapData, ZERO, 128)) {
_shotLayer.removeChild(_shotBall);
var p:Point = _ballLayer.globalToLocal(new Point(_shotBall.x, _shotBall.y));
_shotBall.x = p.x;
_shotBall.y = p.y;
_ballLayer.addChild(_shotBall);
var l:Number = Math.sqrt(p.x * p.x + p.y * p.y);
for (var i:uint = 0; i < 4; ++i) {
var particle:KatamariBall = new KatamariBall(2 + Math.random() * 3, _shotBall.color + 30 + 360 / 4 * i);
var ppos:Point = _ballLayer.localToGlobal(new Point(p.x * ((l - 10) / l), p.y * ((l - 10) / l)));
particle.positionX = ppos.x;
particle.positionY = ppos.y;
particle.velocityX = (Math.random() * 16 + 2) - 9;
particle.velocityY = Math.random() * -9 - 4;
_particleLayer.addChild(particle);
_particles.push(particle);
}
_score += 20;
if (l > 90) {
_nowState = STATE_GAMEOVER;
_isSpaceDown = false;
}
else {
startInput();
}
}
if (_shotBall != null && isOut(_shotBall)) {
_shotLayer.removeChild(_shotBall);
_shotBall = null;
_score -= 10;
startInput();
}
}
_scoreField.text = 'SCORE: ' + _score;
}
private function updateParticles():void
{
for (var i:int = 0; i < _particles.length; ++i) {
var particle:KatamariBall = _particles[i] as KatamariBall;
moveBall(particle);
if (isOut(particle)) {
_particleLayer.removeChild(particle);
_particles.splice(i, 1);
--i;
}
}
}
private function moveBall(ball:KatamariBall):void
{
ball.positionX += ball.velocityX;
ball.positionY += ball.velocityY;
ball.velocityY += 0.45;
ball.x = ball.positionX;
ball.y = ball.positionY;
}
private function isOut(ball:KatamariBall):Boolean
{
return ball.positionX < -30 || ball.positionX > stage.stageWidth + 30 || ball.positionY < -30 || ball.positionY > stage.stageHeight + 30;
}
}
}
import flash.display.Sprite;
import flash.display.Graphics;
import frocessing.color.ColorHSV;
class KatamariBall extends Sprite
{
public function KatamariBall(size:Number = 20, color:Number = NaN)
{
var g:Graphics = graphics;
var radius:Number = size;
var d:Number = size / 5;
var resolution:Number = 10;
if (isNaN(color)) {
color = Math.random() * 360;
}
_color = color;
g.clear();
g.beginFill(new ColorHSV(color, 0.8, 1.0).value);
g.moveTo(Math.cos(0) * radius, Math.sin(0) * radius);
for (var i:uint = 1; i < resolution; ++i) {
var angle:Number = Math.PI * 2 / resolution * i;
var r:Number = radius + (Math.random() * d - d / 2);
g.lineTo(Math.cos(angle) * r, Math.sin(angle) * r);
}
g.endFill();
cacheAsBitmap = true;
blendMode = 'multiply';
}
private var _color:Number;
public var positionX:Number = 0;
public var positionY:Number = 0;
public var velocityX:Number = 0;
public var velocityY:Number = 0;
public function get color():uint
{
return _color;
}
}
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.utils.getTimer;
import com.bit101.components.Label;
class Algorithm
{
private static var _ballLayer : Sprite;
private static var _shot : KatamariBall;
private static var _field : Sprite;
private static var _deb : Label;
private static var _vtimes : Array;
private static var _fakes : Array;
private static var _debs : Sprite;
public static function algo(ballg : Graphics, deb : Label, debs : Sprite) : Array
{
_deb = deb;
_debs = debs;
_ballLayer = new Sprite();
var ball : Sprite = new Sprite();
ball.graphics.copyFrom(ballg);
_ballLayer.addChild(ball);
_ballLayer.x = 465 / 2;
_ballLayer.y = 465 / 2 - 80;
_shot = makeFakeBall();
_field = new Sprite();
_field.addChild(_ballLayer);
_field.addChild(_shot);
_ballsBitmapData = new BitmapData(45, 45, true, 0x00000000);
_ballsBitmapData.lock();
_shotBitmapData = new BitmapData(45, 45, true, 0x00000000);
_shotBitmapData.lock();
_shotBitmapDataMatrix = new Matrix();
_shotBitmapDataMatrix.translate(22, 22);
_shotBitmapData.draw(_shot, _shotBitmapDataMatrix);
_ballsBitmapDataMatrix = new Matrix();
_fakes = new Array(30);
for(i = 0;i < 30;i++)_fakes[i] = makeFakeBall();
_p = new Point();
var s : int = getTimer();
_vtimes = enumValidTime();
var max : Array = [];
for(var i : int = 0;i < 30;i++){
var a : Array = dfs(25);
if(max.length < a.length)max = a;
if(max.length >= 20)break;
}
var g : int = getTimer();
deb.text += "" + (g - s) + " ms\n";
deb.text += "" + max.length + "\t" + _vtimes.length + "\n";
/*
deb.text += "" + max + "\n";
*/
return max;
}
private static var _f : Boolean = false;
private static function dfs(depth : int) : Array
{
if(depth == 0){
/*
if(!_f){
_ballsBitmapDataMatrix.identity();
_ballsBitmapDataMatrix.rotate(_ballLayer.rotation / 360 * Math.PI * 2);
_ballsBitmapDataMatrix.translate(_ballLayer.x, _ballLayer.y);
var bmd : BitmapData = new BitmapData(465, 465, true, 0x00000000);
bmd.draw(_ballLayer, _ballsBitmapDataMatrix);
_debs.addChild(new Bitmap(bmd));
_f = true;
}
*/
return [];
}
var orot : int = _ballLayer.rotation;
var onc : int = _ballLayer.numChildren;
var maxa : Array = [];
for(var i : int = 0;i <= (25 - depth) / 3;i++){
var ret : Array = [];
var t : int = _vtimes[int(Math.random() * _vtimes.length)];
stepToShot(t);
var res : Array = stepToHit();
if(res != null){
if(res[0] == 1){
// _deb.text += "" + res[1] + "\n";
ret = dfs(depth - 1);
ret.unshift(t);
}else if(res[0] == 2){
ret.unshift(t);
}
}
// 元の状態に戻す
if(_ballLayer.numChildren > onc)_ballLayer.removeChildAt(_ballLayer.numChildren - 1);
_ballLayer.rotation = orot;
if(ret.length > maxa.length)maxa = ret;
}
return maxa;
}
private static function makeFakeBall() : KatamariBall
{
var ret : KatamariBall = new KatamariBall();
var g:Graphics = ret.graphics;
var radius:Number = 22;
var resolution:Number = 10;
g.clear();
g.beginFill(new ColorHSV(Math.random() * 360, 0.8, 1.0).value);
g.moveTo(Math.cos(0) * radius, Math.sin(0) * radius);
for (var i:uint = 1; i < resolution; ++i) {
var angle:Number = Math.PI * 2 / resolution * i;
var r:Number = radius;
g.lineTo(Math.cos(angle) * r, Math.sin(angle) * r);
}
g.endFill();
return ret;
}
private static function stepToShot(t : int) : void
{
_ballLayer.rotation += 2 * t;
var shotAngle : Number = (150 - Math.sin(Math.PI / 60 * t) * 120) / 360 * Math.PI;
_shot.x = 465 / 2 + Math.cos(shotAngle) * 50;
_shot.y = 465 - Math.sin(shotAngle) * 50;
_shot.velocityX = Math.cos(shotAngle) * 18;
_shot.velocityY = Math.sin(shotAngle) * -18;
_shot.positionX = _shot.x;
_shot.positionY = _shot.y;
}
private static var _ballsBitmapDataMatrix:Matrix;
private static var _shotBitmapDataMatrix:Matrix;
private static var _ballsBitmapData : BitmapData;
private static var _shotBitmapData : BitmapData;
private static const ZERO:Point = new Point(0, 0);
private static var _p : Point;
// 0 : no hit
// 1 : hit
// 2 : hit but gameover
private static function stepToHit() : Array
{
for(var t : int = 0;;t++){
_shot.positionX += _shot.velocityX;
_shot.positionY += _shot.velocityY;
_shot.velocityY += 0.45;
_shot.x = _shot.positionX;
_shot.y = _shot.positionY;
_p.x = _shot.x;
_p.y = _shot.y;
var p:Point = _ballLayer.globalToLocal(_p);
// var p:Point = _ballLayer.globalToLocal(new Point(_shot.x, _shot.y));
// var l:Number = Math.sqrt(p.x * p.x + p.y * p.y);
var l : Number = p.length;
if(l < 120){
_ballsBitmapDataMatrix.identity();
_ballsBitmapDataMatrix.rotate(_ballLayer.rotation / 360 * Math.PI * 2);
_ballsBitmapDataMatrix.translate(_ballLayer.x - _shot.x + 22, _ballLayer.y - _shot.y + 22);
_ballsBitmapData.fillRect(_ballsBitmapData.rect, 0x00000000);
_ballsBitmapData.draw(_ballLayer, _ballsBitmapDataMatrix);
// _shotBitmapDataMatrix.identity();
// _shotBitmapDataMatrix.translate(_shot.x, _shot.y);
// _shotBitmapData.fillRect(_shotBitmapData.rect, 0x00000000);
// _shotBitmapData.draw(_shot, _shotBitmapDataMatrix);
if (_ballsBitmapData.hitTest(ZERO, 128, _shotBitmapData, ZERO, 128)) {
_ballLayer.rotation += 2; // XXX
if(l > 90){
return [2, t];
}else{
var k : KatamariBall = _fakes[_ballLayer.numChildren - 1];
k.x = p.x;
k.y = p.y;
_ballLayer.addChild(k);
return [1, t];
}
}
}
if (isOut(_shot)) {
return [0, t];
}
_ballLayer.rotation += 2;
}
return null;
}
private static function enumValidTime() : Array
{
var ret : Array = [];
for(var t : int = 0;t < 240;t++){ // 2往復以内。本当は3往復までOKだけど長い
var shotAngle : Number = (150 - Math.sin(Math.PI / 60 * t) * 120) / 360 * Math.PI;
var x : Number = 465 / 2 + Math.cos(shotAngle) * 50;
var y : Number = 465 - Math.sin(shotAngle) * 50;
var vx : Number = Math.cos(shotAngle) * 18;
var vy : Number = Math.sin(shotAngle) * -18;
var l : Number = Number.MAX_VALUE;
var prevl : Number = Number.MAX_VALUE;
while(prevl >= l){
prevl = l;
x += vx;
y += vy;
vy += 0.45;
l = (465 / 2 - x) * (465 / 2 - x) + (465 / 2 - 80 - y) * (465 / 2 - 80 - y);
if(l < 90 * 90){
ret.push(t);
break;
}
}
}
return ret;
}
private static function isOut(ball:KatamariBall):Boolean
{
// return ball.positionX < -30 || ball.positionX > 465 + 30 || ball.positionY < -30 || ball.positionY > 465 + 30;
return ball.positionX < 0 || ball.positionX > 465 || ball.positionY > 465 + 30;
}
}