「チェインフレーション(Chain Inflation)」
半自動的に連鎖が起こり続けるパズルゲーム 操作方法(How To Play) ・ブロックをタッチ(Touch : Block) ・ブロックの模様の変更(Change : Pattern) ルール ・ブロックを縦か横に3つ並べると消える エフェクト(パーティクル) ・以下のコードを参考に作成 ・http://wonderfl.net/c/g9s1/ 比較用(あとで追加) ・Android版(Air) ・https://play.google.com/store/apps/details?id=air.showohealer.game.airprototype
♥10 |
Line 433 |
Modified 2012-05-31 13:06:07 |
MIT License
archived:2017-03-07 09:24:45
| (replaced)
ActionScript3 source code
/**
* Copyright o_healer ( http://wonderfl.net/user/o_healer )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/qNgu
*/
/*
「チェインフレーション(Chain Inflation)」
・半自動的に連鎖が起こり続けるパズルゲーム
操作方法(How To Play)
・ブロックをタッチ(Touch : Block)
・ブロックの模様の変更(Change : Pattern)
ルール
・ブロックを縦か横に3つ並べると消える
エフェクト(パーティクル)
・以下のコードを参考に作成
・http://wonderfl.net/c/g9s1/
比較用(あとで追加)
・Android版(Air)
・https://play.google.com/store/apps/details?id=air.showohealer.game.airprototype
*/
package {
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.text.*;
import flash.ui.*;
import net.wonderfl.utils.WonderflAPI;
[SWF(width="465", height="465", frameRate="30", backgroundColor="0x000000")]
public class ChainInflation extends Sprite {
//==Const==
//画面の大きさ
static public const VIEW_W:int = 465;
static public const VIEW_H:int = 465;
//ブロックを並べる数
static public const BLOCK_NUM_X:int = 9;//7;//14;
static public const BLOCK_NUM_Y:int = 8;//6;//12;
//ブロックの大きさ
static public const BLOCK_W:int = 48;//64;//32;
//制限時間
static public const TIME_LIMIT:Number = 30;
//パーティクルの数
static public const PARTICLE_NUM_PER_BLOCK:int = 10;
static public const PARTICLE_NUM:int = PARTICLE_NUM_PER_BLOCK * BLOCK_NUM_X * BLOCK_NUM_Y;
//初期配置
static public const TYPE_ARR:Array = [
//
[
[0,1,0,1],
[1,0,1,0],
[0,1,0,1],
[1,0,1,0],
],
//
[
[0,1,0,1],
[1,1,0,0],
[0,0,1,1],
[1,0,1,0],
],
];
//==Var==
//Pseudo Singleton
static public var Instance:ChainInflation;
//Layer
public var m_Layer_BG:Sprite = new Sprite();
public var m_Layer_Block:Sprite = new Sprite();
public var m_Layer_Particle:Sprite = new Sprite();
//ブロック
public var m_Block:Vector.<Vector.<Block> >;
//パーティクル
public var m_Particle:Vector.<Particle>;
public var m_BitmapData_Particle:BitmapData;
public var m_BitmapData_Glow:BitmapData;
public var m_Mtx_Glow:Matrix;
//テキスト
public var m_Text_Score:TextField = new TextField();
public var m_Text_Time:TextField = new TextField();
//タイマー
public var m_RestTimer:Number = TIME_LIMIT;
public var m_TimerUpdateFlag:Boolean = false;//最初のタッチまでは更新しない
//スコア
public var m_Score:int = 0;
//==Function==
//Init
public function ChainInflation():void{
//Pseudo Singleton
{
Instance = this;
}
//stageを参照できるようになってから初期化する(イベントリスナの追加や画面の大きさの取得のため)
if(stage != null){
Init();
}else{
addEventListener(
Event.ADDED_TO_STAGE,//ステージに追加されたら
function(e:Event):void{
Init();
}
);
}
}
public function Init():void{
var i:int;
//Static Init
{
Block.StaticInit();
ScoreWindowLoader.init(this, new WonderflAPI(loaderInfo.parameters));
}
//BG
{
//主にwonderfl用
addChild(new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000)));
}
//Layer
{
addChild(m_Layer_BG);
addChild(m_Layer_Block);
addChild(m_Layer_Particle);
m_Layer_Block.x = (VIEW_W - BLOCK_W * BLOCK_NUM_X) / 2;
m_Layer_Particle.x = m_Layer_Block.x;
}
//Block
{
m_Block = new Vector.<Vector.<Block> >(BLOCK_NUM_Y);
for(var yy:int = 0; yy < BLOCK_NUM_Y; ++yy){
m_Block[yy] = new Vector.<Block>(BLOCK_NUM_X);
for(var xx:int = 0; xx < BLOCK_NUM_X; ++xx){
var block:Block = new Block();
block.SetType(TYPE_ARR[0][yy % 4][xx % 4]);
block.x = xx * BLOCK_W;
block.y = yy * BLOCK_W;
m_Layer_Block.addChild(block);
m_Block[yy][xx] = block;
}
}
}
//Particle
{
m_Particle = new Vector.<Particle>(PARTICLE_NUM);
for(i = 0; i < PARTICLE_NUM; ++i){
m_Particle[i] = new Particle();
}
}
//
{
m_BitmapData_Particle = new BitmapData(VIEW_W, VIEW_H, true, 0x00000000);
m_Layer_Particle.addChild(new Bitmap(m_BitmapData_Particle));
m_BitmapData_Glow = new BitmapData(VIEW_W/4, VIEW_H/4, false, 0x000000);
var bmp_glow:Bitmap = new Bitmap(m_BitmapData_Glow, PixelSnapping.NEVER, true);
bmp_glow.scaleX = bmp_glow.scaleY = 4;
bmp_glow.blendMode = BlendMode.ADD;
m_Layer_Particle.addChild(bmp_glow);
m_Mtx_Glow = new Matrix(0.25, 0, 0, 0.25, 0,0);
}
//Text
{
m_Text_Score.selectable = false;
m_Text_Score.autoSize = TextFieldAutoSize.LEFT;
m_Text_Score.defaultTextFormat = new TextFormat('Verdana', 24, 0xFFFFFF, true);
m_Text_Score.text = "";
m_Text_Score.filters = [new GlowFilter(0x00FFFF,1.0, 8,8)];
m_Text_Score.x = 12;
m_Text_Score.y = VIEW_H - 32;
addChild(m_Text_Score);
//Reset
AddScore(0);
}
{
m_Text_Time.selectable = false;
m_Text_Time.autoSize = TextFieldAutoSize.LEFT;
m_Text_Time.defaultTextFormat = new TextFormat('Verdana', 24, 0xFFFFFF, true);
m_Text_Time.text = "Time : " + TIME_LIMIT;
m_Text_Time.filters = [new GlowFilter(0x00FFFF,1.0, 8,8)];
m_Text_Time.x = VIEW_W - m_Text_Time.textWidth - 12;
m_Text_Time.y = VIEW_H - 32;
addChild(m_Text_Time);
}
//Touch
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
}
//Update
{
addEventListener(Event.ENTER_FRAME, Update);
}
//OnEnd
{
addEventListener(Event.REMOVED_FROM_STAGE, Finish);
}
}
//Finish
public function Finish(e:Event):void{
removeEventListener(Event.ADDED_TO_STAGE, Init);
removeEventListener(Event.ENTER_FRAME, Update);
removeEventListener(Event.REMOVED_FROM_STAGE, Finish);
}
//Update
public function Update(e:Event=null):void{
var DeltaTime:Number = 1.0 / stage.frameRate;
if(Update_Timer(DeltaTime)){
return;
}
Check_Vanish();
Update_Block(DeltaTime);
Update_Particle(DeltaTime);
}
//Update : Timer
public function Update_Timer(in_DeltaTime:Number):Boolean{
if(! m_TimerUpdateFlag){
return false;
}
if(m_RestTimer <= 0){
return true;
}
m_RestTimer -= in_DeltaTime;
if(m_RestTimer <= 0){
//Time Up
m_Text_Time.text = "Time Up!!";
ScoreWindowLoader.show(m_Score);
return true;
}
m_Text_Time.text = "Time : " + int(m_RestTimer + 0.999999);
return false;
}
//Update : CheckVanish
public function Check_Vanish():void{
var last_type:int;
var connect_count:int;
var i:int;
var xx:int;
var yy:int;
var block:Block;
//横のつながりのチェック
for(yy = 0; yy < BLOCK_NUM_Y; ++yy){
last_type = -1;
connect_count = 0;
for(xx = 0; xx < BLOCK_NUM_X; ++xx){
block = m_Block[yy][xx];
if(block.m_Mode != Block.MODE_FALL){
if(block.m_Type == last_type){
++connect_count;
//3つ以上並んでたら消す
if(3 == connect_count){
for(i = xx-2; i <= xx; ++i){
//m_Block[yy][i].Vanish();
Vanish(i, yy);
}
}
if(3 < connect_count){
//m_Block[yy][xx].Vanish();
Vanish(xx, yy);
}
}else{
//つながってない
last_type = block.m_Type;
connect_count = 1;
}
}else{
//つながってない
last_type = -1;
connect_count = 0;
}
}
}
//縦のつながりのチェック
//- 下からチェックしていき、空間があればそれ以降はチェックしない(落下中のやつはムシ)
for(xx = 0; xx < BLOCK_NUM_X; ++xx){
last_type = -1;
connect_count = 0;
for(yy = BLOCK_NUM_Y-1; 0 <= yy; --yy){
block = m_Block[yy][xx];
if(block.m_Mode != Block.MODE_FALL){
if(block.m_Type == last_type){
++connect_count;
//3つ以上並んでたら消す
if(3 == connect_count){
for(i = yy+2; yy <= i; --i){
//m_Block[i][xx].Vanish();
Vanish(xx, i);
}
}
if(3 < connect_count){
//m_Block[yy][xx].Vanish();
Vanish(xx, yy);
}
}else{
//つながってない
last_type = block.m_Type;
connect_count = 1;
}
}else{
//つながってない
break;//以降はムシ
}
}
}
}
//Do Vanish
public function Vanish(in_X:int, in_Y:int):void{
if(m_Block[in_Y][in_X].m_Mode != Block.MODE_WAIT){
return;
}
m_Block[in_Y][in_X].Vanish();
//Effect
var particle_offset:int = (in_Y + in_X * BLOCK_NUM_Y) * PARTICLE_NUM_PER_BLOCK;
for(var i:int = 0; i < PARTICLE_NUM_PER_BLOCK; ++i){
var particle:Particle = m_Particle[particle_offset + i];
var offset_x:Number = BLOCK_W/2 - Math.random() * BLOCK_W;
var offset_y:Number = BLOCK_W/2 - Math.random() * BLOCK_W;
// particle.m_X = in_X * BLOCK_W + offset_x;
// particle.m_Y = in_Y * BLOCK_W + offset_y;
particle.m_X = in_X * BLOCK_W + BLOCK_W/2;
particle.m_Y = in_Y * BLOCK_W + BLOCK_W/2;
particle.m_VX = offset_x * 10;
particle.m_VY = offset_y * 10;
//particle.m_Color =
}
}
//Update : Block
public function Update_Block(in_DeltaTime:Number):void{
var xx:int;
var yy:int;
var i:int;
var block:Block;
//Update
for(yy = 0; yy < BLOCK_NUM_Y; ++yy){
for(xx = 0; xx < BLOCK_NUM_X; ++xx){
block = m_Block[yy][xx];
block.Update(in_DeltaTime);
//Check : Fall End
if(block.m_Mode == Block.MODE_FALL && yy * BLOCK_W <= block.y){
block.y = yy * BLOCK_W;
block.ChangeMode(Block.MODE_WAIT);
}
}
}
//Check Fall
for(xx = 0; xx < BLOCK_NUM_X; ++xx){
var fall_flag:Boolean = false;
for(yy = BLOCK_NUM_Y-1; 0 <= yy; --yy){
block = m_Block[yy][xx];
if(block.IsEndVanish()){
fall_flag = true;
//1マスずつ落下させる
//- Indexだけ先にズラす
for(i = yy; 0 < i; --i){
m_Block[i][xx] = m_Block[i-1][xx];
}
block.y = m_Block[0][xx].y - BLOCK_W;
m_Block[0][xx] = block;
block.SetType(int(Block.TYPE_NUM * Math.random()));
block.ChangeMode(Block.MODE_FALL);
++yy;
continue;
}
if(fall_flag){
if(block.m_Mode == Block.MODE_WAIT){
block.ChangeMode(Block.MODE_FALL);
}
}
}
}
}
//Particle
public function Update_Particle(in_DeltaTime:Number):void{
//パーティクルを1ドットずつ描く
m_BitmapData_Particle.fillRect(m_BitmapData_Particle.rect, 0x00000000);
m_BitmapData_Particle.lock();
for(var i:int = 0; i < PARTICLE_NUM; ++i){
var particle:Particle = m_Particle[i];
//Coord
particle.m_X += particle.m_VX * in_DeltaTime;
particle.m_Y += particle.m_VY * in_DeltaTime;
//Set
m_BitmapData_Particle.setPixel32(particle.m_X, particle.m_Y, particle.m_Color);
}
m_BitmapData_Particle.unlock();
//
m_BitmapData_Glow.fillRect(m_BitmapData_Glow.rect, 0x000000);
m_BitmapData_Glow.draw(m_BitmapData_Particle, m_Mtx_Glow);
}
//Touch
private function OnMouseDown(e:MouseEvent):void{
m_TimerUpdateFlag = true;
for(var yy:int = 0; yy < BLOCK_NUM_Y; ++yy){
for(var xx:int = 0; xx < BLOCK_NUM_X; ++xx){
var block:Block = m_Block[yy][xx];
if(block.HitCheck(mouseX, mouseY)){
block.FlipType();
return;
}
}
}
}
//Add : Score
public function AddScore(in_Val:int):void{
m_Score += in_Val;
m_Text_Score.text = "Score : " + m_Score;
}
}
}
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.system.*;
import flash.ui.*;
import net.wonderfl.utils.WonderflAPI;
class Block extends Sprite
{
//==Const==
//Size
static public const BLOCK_W:int = ChainInflation.BLOCK_W;
//Time
static public const VANISH_TIME:Number = 0.5;
//
static public const MAX_SCALE:Number = 2;
//
static public const FALL_VY:Number = BLOCK_W * 7.0;
//Type
static public var s_TypeIter:int = 0;
static public const TYPE_SQUARE :int = s_TypeIter++;
static public const TYPE_DIAMOND:int = s_TypeIter++;
static public const TYPE_NUM :int = s_TypeIter;
//Mode
static public var s_ModeIter:int = 0;
static public const MODE_WAIT :int = s_ModeIter++;
static public const MODE_VANISH :int = s_ModeIter++;
static public const MODE_FALL :int = s_ModeIter++;
//==Var==
//Type
public var m_Type:int = 0;
//Mode
public var m_Mode:int = 0;
public var m_ModeTimer:Number = 0;
//Graphic
public var m_Bitmap:Bitmap = new Bitmap();
public var m_SclRoot:Sprite = new Sprite();
static public var s_BitmapData:Vector.<BitmapData>;
//==Function==
//Static Init
static public function StaticInit():void{
//Graphic
{
s_BitmapData = new Vector.<BitmapData>(TYPE_NUM);
var shape:Shape = new Shape();
var g:Graphics = shape.graphics;
for(var i:int = 0; i < TYPE_NUM; ++i){
g.clear();
//Frame
g.lineStyle(2, 0x000000, 1.0);
g.drawRect(0,0,BLOCK_W,BLOCK_W);
//Icon
var rad:Number = BLOCK_W * 40/100;
var theta:Number = i * Math.PI/4;
var color:uint = (i == 0)? 0x00DDFF: 0x00FFDD;
g.lineStyle(3, color, 1.0);
g.moveTo(BLOCK_W/2 + rad * Math.cos(theta + Math.PI*0/2), BLOCK_W/2 + rad * Math.sin(theta + Math.PI*0/2));
g.lineTo(BLOCK_W/2 + rad * Math.cos(theta + Math.PI*1/2), BLOCK_W/2 + rad * Math.sin(theta + Math.PI*1/2));
g.lineTo(BLOCK_W/2 + rad * Math.cos(theta + Math.PI*2/2), BLOCK_W/2 + rad * Math.sin(theta + Math.PI*2/2));
g.lineTo(BLOCK_W/2 + rad * Math.cos(theta + Math.PI*3/2), BLOCK_W/2 + rad * Math.sin(theta + Math.PI*3/2));
g.lineTo(BLOCK_W/2 + rad * Math.cos(theta + Math.PI*4/2), BLOCK_W/2 + rad * Math.sin(theta + Math.PI*4/2));
//Apply
s_BitmapData[i] = new BitmapData(BLOCK_W, BLOCK_W, false, 0xEEEEEE);
s_BitmapData[i].draw(shape);
}
}
}
//Init
public function Block(){
//Graphic
{
m_Bitmap.x = -BLOCK_W/2;
m_Bitmap.y = -BLOCK_W/2;
m_SclRoot.x = BLOCK_W/2;
m_SclRoot.y = BLOCK_W/2;
m_SclRoot.addChild(m_Bitmap);
addChild(m_SclRoot);
}
}
//Set : Type
public function SetType(in_Type:int):void{
//Param
m_Type = in_Type;
//Change Graphic
m_Bitmap.bitmapData = s_BitmapData[m_Type];
}
//Flip : Type
public function FlipType():void{
if(m_Mode != MODE_WAIT){
return;
}
//Flip
m_Type = 1 - m_Type;
//Change Graphic
m_Bitmap.bitmapData = s_BitmapData[m_Type];
}
//Set : Mode
public function ChangeMode(in_Mode:int):void{
m_Mode = in_Mode;
m_ModeTimer = 0;
m_SclRoot.scaleX = m_SclRoot.scaleY = 1;
this.alpha = 1;
}
//Touch
public function HitCheck(in_X:int, in_Y:int):Boolean{
return (this.x <= in_X && in_X < this.x + BLOCK_W && this.y <= in_Y && in_Y < this.y + BLOCK_W);
}
//消す処理
public function Vanish():void{
if(m_Mode != MODE_WAIT){
return;
}
//Mode
ChangeMode(MODE_VANISH);
//++score
ChainInflation.Instance.AddScore(1);
}
//
public function IsEndVanish():Boolean{
return (m_Mode == MODE_VANISH) && (VANISH_TIME <= m_ModeTimer);
}
//Update
public function Update(in_DeltaTime:Number):void{
m_ModeTimer += in_DeltaTime;
switch(m_Mode){
case MODE_WAIT:
break;
case MODE_VANISH:
m_SclRoot.scaleX = m_SclRoot.scaleY = Lerp(1, MAX_SCALE, m_ModeTimer/VANISH_TIME);
this.alpha = 1 - m_ModeTimer/VANISH_TIME;
break;
case MODE_FALL:
this.y += FALL_VY * in_DeltaTime;
break;
}
}
//Utility
public function Lerp(in_Src:Number, in_Dst:Number, in_Ratio:Number):Number{
return (in_Src * (1 - in_Ratio)) + (in_Dst * in_Ratio);
}
}
class Particle
{
//==Var==
//Coord
public var m_X:int = -1;
public var m_Y:int = -1;
public var m_VX:int = 0;
public var m_VY:int = 0;
//Color
public var m_Color:uint = 0xFFFFFFFF;
}
//*
//bkzenさんのコードを利用
//@see http://wonderfl.net/c/cuY4
//@see http://wonderfl.net/c/kYyY
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 Chain Inflation [score: %SCORE%] #wonderfl";
public static function init(top: DisplayObjectContainer, api: WonderflAPI): 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));
}
public static function show( score: int): void
{
var window: DisplayObject = _content.makeScoreWindow(_api, score, "Chain Inflation", 1, TWEET);
// var close: Function = function(e: Event): void
// {
// window.removeEventListener(Event.CLOSE, close);
// closeHandler();
// }
// window.addEventListener(Event.CLOSE, close);
_top.addChild(window);
}
}
//*/