In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Hit&Blowゲーム

なんか落ちゲーの基本の動きを作ろうと思ってたらいつの間にかHit&Blowに…

エフェクトとかリトライとか点数とかそのうち付けたい…

================================
Hit&Blowのルール

・あらかじめcomが決めた色の組み合わせを当てるゲーム。
・一度の回答に付き、Hit数とBlow数を教えてくれる。
 (Hit = 色も位置もあっている)
 (Blow = 色はあってるが場所が違う)
・同じ色は2回以上使われません。
================================
Get Adobe Flash player
by ug24k8 23 Dec 2010
    Embed
/**
 * Copyright ug24k8 ( http://wonderfl.net/user/ug24k8 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/531n
 */

package  {

/*
    なんか落ちゲーの基本の動きを作ろうと思ってたらいつの間にかHit&Blowに…

    ================================
    Hit&Blowのルール

    ・あらかじめcomが決めた色の組み合わせを当てるゲーム。
    ・一度の回答に付き、Hit数とBlow数を教えてくれる。
     (Hit = 色も位置もあっている)
     (Blow = 色はあってるが場所が違う)
    ・同じ色は2回以上使われません。
    ================================


*/
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.ui.Mouse;

    [SWF(backgroundColor="0x000000", width="465", height="465", frameRate="30")]

    // ゲーム本体
    public class HitAndBlow extends Sprite {
        public static const STAGE_DATA:Array = [
                [4, 3],    [5, 3],    [5, 4], [6, 3], [6, 4], [6, 5],
        ];

        private var mPlayer:Player;
        private var mField:GameField;
        private var mRecord:RecordList;
        private var mCheckSwitch:CheckSwitch;
        private var mStateChecked:Boolean = false;
        private var mMessage:Message;

        private var mStage:uint;
        private var mAnswer:Array;

        // コンストラクタ
        public function HitAndBlow() {
            // フィールド登録
            mField = addChild(new GameField()) as GameField;
            mField.x = 150;
            mField.y = 15;

            // プレイヤー登録
            mPlayer = addChild(new Player()) as Player;
            mPlayer.y = stage.stageHeight * 0.9;

            // 履歴登録
            mRecord = addChild(new RecordList()) as RecordList;
            mRecord.x = 310;
            mRecord.y = 20;

            mCheckSwitch = addChild(new CheckSwitch()) as CheckSwitch;
            mCheckSwitch.x = 30;
            mCheckSwitch.y = mPlayer.y;

            // ステージ設定
            mAnswer = new Array();
            mStage = 0;
            createAnswer();
            mField.set_gamelevel(STAGE_DATA[mStage][0], STAGE_DATA[mStage][1]);

            // メッセージ追加
            mMessage = addChild(new Message()) as Message;
            mMessage.x = stage.stageWidth * 0.5;
            mMessage.y = stage.stageHeight * 0.5;

            // マウス非表示
            Mouse.hide();

            addEventListener(Event.ENTER_FRAME, onEnterFrame);
            stage.addEventListener(MouseEvent.CLICK, onMouseClick);

            mMessage.pop("Start!", 5000);
        }

        // 答え作成
        private function createAnswer():void {
            var i:int;
            var color_val:int = STAGE_DATA[mStage][0];
            mAnswer.splice(0);    // 全削除
            for (i = 0; i < color_val; ++i) mAnswer.push(i);
            shuffleList(mAnswer);
            trace(mAnswer);
        }

        // 毎フレーム処理
        private function onEnterFrame(evt:Event):void {
            if (mField.is_game_over) {
                mMessage.pop("Game Over!");
                removeEventListener(Event.ENTER_FRAME, arguments.callee);
            }

            // マウス位置をプレイヤーに反映
            mPlayer.target_x = stage.mouseX;

            if (mPlayer.hitTestObject(mCheckSwitch)) {
                if (mStateChecked == false) {
                    var i:int, j:int;
                    var correct:Boolean = false;
                    var block_set:DropBlockSet = mField.popCurrentBlock();

                    if (block_set) {
                        var hit_count:int = 0;
                        var blow_count:int = 0;
                        for (i = 0; i < block_set.block_size; ++i) {
                            var color:int = block_set.block_color(i);
                            for (j = 0; j < block_set.block_size; ++j) {
                                if (mAnswer[j] == color) {
                                    if (i == j) ++hit_count;
                                    else ++blow_count;

                                    break;
                                }
                            }
                        }

                        if (hit_count == block_set.block_size) {
                            // 正解~
                            correct = true;

                            mStage = Math.min(mStage + 1, STAGE_DATA.length - 1);
                            createAnswer();
                            mField.set_gamelevel(STAGE_DATA[mStage][0], STAGE_DATA[mStage][1]);
                            mField.addBonus(block_set.block_size);
                            mMessage.pop("All Hit", 1000);
                        }
                        else {
                            // ミスー
                            mField.addPenalty(1.0 - hit_count / block_set.block_size);
                            mMessage.pop(hit_count + " Hit  " + blow_count + " Blow", 1000);
                        }

                        mRecord.push_record(new Record(block_set, hit_count, blow_count, correct));
                    }
                    mStateChecked = true;
                }
            }
            else {
                mStateChecked = false;
            }
        }

        // マウスクリック
        private function onMouseClick(evt:MouseEvent):void {
            // 弾はフィールドに付けようそうしよう
            mField.addBullet(mPlayer.x, mPlayer.y);
        }

        private function shuffleList(list:Array):void {
            var n:Number = list.length;
            while (n--) {
                var i:Number = Math.floor(Math.random()*(n+1));
                var t:Number = list[n];
                list[n] = list[i];
                list[i] = t;
            }
        }
    }
}

import com.bit101.components.Text;
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.utils.Timer;

// Block-base
class BlockBase extends Shape {
    public static const COLOR_DATA:Array = [
            0xFF4444,     0x44444FF,    0x44FF44,
            0xFFFF44,    0xFF44FF,    0x44FFFF,
        ];

    public var mSize:int;

    // コンストラクタ
    public function BlockBase(size:int = 10) {
        mSize = size;
    }

    public function drawColorBox(color:uint):void {
        var block_size:uint = mSize - 1;
        graphics.clear();
        graphics.beginFill(COLOR_DATA[color]);
        graphics.lineStyle();
        graphics.drawRoundRect(
                    -block_size * 0.5, -block_size * 0.5,
                    block_size, block_size, block_size*0.6, block_size*0.6);
        graphics.endFill();
    }
}

// field
class GameField extends Sprite {
    public static const GRID_SIZE:uint = 30;
    public static const GRID_WIDTH:uint = 5;
    public static const GRID_HEIGHT:uint = 14;
    public static const BULLET_MAX_COUNT:uint = 3;
    public static const DROP_WAIT_TIME:uint = 1000;

    private var mCurrent:DropBlockSet;
    private var mBulletList:Sprite;        // 弾リスト代わり
    private var mDropTimer:Timer;
    private var mColor_val:int;
    private var mBlock_cout:int;
    private var mGameOver:Boolean;
    private var mDeadLine:Shape;
    private var mDeadPoint:Number;

    // コンストラクタ
    public function GameField() {
        var i:int;

        mGameOver = false;
        mDeadPoint = 0;

        // デッドライン描画
        mDeadLine = addChild(new Shape()) as Shape;
        mDeadLine.x = 0;
        mDeadLine.y = GRID_HEIGHT * GRID_SIZE;
        update_deadline();

        // 床描画
        graphics.lineStyle(1, 0x8080F0, 0.8);
        for (i = 0; i < GRID_WIDTH+1; ++i) {
            graphics.moveTo(i * GRID_SIZE, 0);
            graphics.lineTo(i * GRID_SIZE, GRID_SIZE * GRID_HEIGHT);
        }
        for (i = 0; i < GRID_HEIGHT+1; ++i) {
            graphics.moveTo(0, i * GRID_SIZE);
            graphics.lineTo(GRID_SIZE * GRID_WIDTH, i * GRID_SIZE);
        }

        mBulletList = new Sprite();
        addChild(mBulletList);

        // ドロップbox タイマー
        if (! mDropTimer) mDropTimer = new Timer(DROP_WAIT_TIME, 1);
        mDropTimer.addEventListener(TimerEvent.TIMER, requestDropBlock);
        mDropTimer.start();

        addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }

    public function get is_game_over():Boolean { return mGameOver; }
    
    public function set_gamelevel(color_val:int, block_cout:int):void {
        mColor_val = color_val;
        mBlock_cout = block_cout;
    }

    public function popCurrentBlock():DropBlockSet {
        var block_set:DropBlockSet = null;
        if (mCurrent) {
            DropBlockSet.recordLastBlock(mCurrent);
            block_set = mCurrent;
            removeChild(mCurrent);
            mCurrent = null;

            mDropTimer.reset();
            mDropTimer.start();
        }

        return block_set;
    }

    // ドロップボックスの投下
    private function requestDropBlock(evt:TimerEvent):void {
        if (mGameOver) return;

        if (mCurrent == null) {
            mCurrent = new DropBlockSet(mBlock_cout, mColor_val);
            mCurrent.x = ((GRID_WIDTH - mBlock_cout) * 0.5) * GRID_SIZE;
            addChild(mCurrent);
        }
    }

    public function addBullet(x:int, y:int):void {
        if (mGameOver) return;

        // 弾数制限つけようかしら?
        if (mBulletList.numChildren >= BULLET_MAX_COUNT) return;

        var pos:Point = mBulletList.globalToLocal(new Point(x, y));
        if (pos.x > 0 && pos.x < GRID_WIDTH * GRID_SIZE) {
            mBulletList.addChild(new Bullet(pos.x, pos.y));
        }
    }

    // ペナルティ追加ー
    public function addPenalty(pt:Number):void {
        mDeadPoint += pt;
        update_deadline();
    }

    // ボーナスによりペナルティ削除
    public function addBonus(pt:Number):void {
        mDeadPoint = Math.max(0, mDeadPoint - pt * 2);
        update_deadline();
    }

    // デッドライン更新
    private function update_deadline():void {
        mDeadLine.graphics.clear();
        mDeadLine.graphics.beginFill(0x00FFFF, 0.25);
        mDeadLine.graphics.drawRect(
            0, 0,
            GRID_SIZE * GRID_WIDTH,
            -(mDeadPoint * 0.4 + 1.2) * GRID_SIZE
        );
        mDeadLine.graphics.endFill();
    }


    // 毎フレーム処理
    private function onEnterFrame(evt:Event):void {
        var i:int;

        if (mCurrent) {
            // 弾チェック
            for (i = mBulletList.numChildren - 1; i >= 0; --i) {
                // 削除すると後ろがずれるので、後ろからやるわー
                var bullet:Bullet = mBulletList.getChildAt(i) as Bullet;
                if (! bullet) continue;        // 一応弾じゃない場合は無視る

                if ((bullet.y < 0) ||                        // 画面端なら消しとこう
                    (mCurrent.isHitBlock(bullet))) {        // ブロックにあたっても消しとこう
                    mBulletList.removeChild(bullet);
                }
            }

            // ゲームオーバーチェック
            if (mDeadLine.hitTestObject(mCurrent)) {
                removeChild(mCurrent);
                mCurrent = null;
                mGameOver = true;
            }
        }
    }
}

// MessageBoard
class Message extends Sprite {
    private var mText:TextField;
    private var mTimer:Timer;

    public function Message() {
        mText = addChild(new TextField()) as TextField;
        var text_format:TextFormat = new TextFormat()
        text_format.size = 20;
        text_format.color = 0xFFFFFF;
        text_format.align = TextFormatAlign.CENTER;
        mText.autoSize = TextFieldAutoSize.CENTER;
        mText.defaultTextFormat = text_format;
        mTimer = new Timer(1, 1);
        mTimer.addEventListener(TimerEvent.TIMER, function(evt:TimerEvent):void {
            visible = false;
        });
        mTimer.stop();
        visible = false;
    }

    public function pop(text:String, time:int = 0):void {
        mText.text = text;
        mText.x = -mText.width * 0.5;
        visible = true;

        if (time > 0) {
            mTimer.delay = time;
            mTimer.start();
        }
    }
}


// player
class Player extends Sprite {
    public var target_x:Number = 0;

    // コンストラクタ
    public function Player() {
        graphics.beginFill(0x800000);
        graphics.lineStyle(1, 0xFFFFFF, 0.5);
        graphics.moveTo(0, -10);
        graphics.lineTo(10, 10);
        graphics.lineTo(0, 5);
        graphics.lineTo(-10, 10);
        graphics.endFill();

        addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }

    // 毎フレーム処理
    private function onEnterFrame(evt:Event):void {
        x = (target_x - x) * 0.8 + x;
    }
}

class Bullet extends Shape {

    public const SPEED:int = -18;

    // コンストラクタ
    public function Bullet(x:int, y:int) {
        graphics.beginFill(0xFFFFFF);
        graphics.drawRoundRect(0, 0, 5, 10, 1, 2);
        graphics.endFill();

        this.x = x;
        this.y = y;

        addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }

    // 毎フレーム処理
    private function onEnterFrame(evt:Event):void {
        y += SPEED;
    }
}

// Drop Block
class DropBlock extends BlockBase {
    public var color:uint;
    public var color_var:uint;

    // コンストラクタ
    public function DropBlock(color_var:uint) {
        super(GameField.GRID_SIZE);
        this.color_var = Math.min(color_var, COLOR_DATA.length);
        color = Math.floor(Math.random() * this.color_var);

        drawColorBox(color);
    }

    // うたれた!?
    public function shot():void {
        color = (color + 1) % this.color_var;
        drawColorBox(color);
    }
}

// Drop Block の塊
class DropBlockSet extends Sprite {
    private static var sLastBlockList:Vector.<DropBlock>;
    private var mBlockList:Vector.<DropBlock>;
    private var mSpeed:Number;

    public function DropBlockSet(width:uint, color_var:uint, speed:Number = 0.4) {
        var i:int;
        if (sLastBlockList != null
            && sLastBlockList.length == width
            && sLastBlockList[0].color_var == color_var) {
            mBlockList = sLastBlockList.concat();    // 複製
        }else {
            mBlockList = new Vector.<DropBlock>();
            for (i = 0; i < width; ++i) {
                mBlockList.push(new DropBlock(color_var));
            }
            sLastBlockList = null;
        }
        mBlockList.forEach(
            function(item:DropBlock, index:int, vector:Vector.<DropBlock>):void {
                addChild(item);
                item.x = (index + 0.5)* GameField.GRID_SIZE;
                item.y = 0.5* GameField.GRID_SIZE;
            });

        mSpeed = speed;

        addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }

    public function isHitBlock(obj:DisplayObject):Boolean {
        var i:int;

        for (i = 0; i < mBlockList.length; ++i) {
            if ( mBlockList[i].hitTestObject(obj) ) {
                mBlockList[i].shot();
                return true;
            }
        }

        return false;
    }

    public function get block_size():int {
        return mBlockList.length;
    }

    public function block_color(index:int):uint {
        return mBlockList[index].color;
    }

    public static function recordLastBlock(blockset:DropBlockSet):void {
        sLastBlockList = blockset.mBlockList.concat();
    }


    // 毎フレーム処理
    private function onEnterFrame(evt:Event):void {
        y += mSpeed;
    }
}

// 記録
class Record extends Sprite {
    public const BLOCK_SIZE:uint = 12;

    public function Record(record:DropBlockSet, hit:int, blow:int, correct:Boolean = false) {
        var i:int;

        if (correct) {
            graphics.lineStyle(1, 0xFFa0a0, 0.6);
            graphics.drawRoundRect(0, 2, 100, 13, 10, 10);
        }

        for (i = 0; i < record.block_size; ++i) {
            var block:BlockBase = new BlockBase(BLOCK_SIZE - 1);
            block.drawColorBox(record.block_color(i));
            block.x = i * BLOCK_SIZE + 25;
            block.y = 9;
            addChild(block);
        }

        var hit_text:TextField = new TextField();
        hit_text.textColor = 0xFFFFFF;
        hit_text.text = hit.toString();
        hit_text.x = 5;
        hit_text.y = 0;
        addChild(hit_text);

        var blow_text:TextField = new TextField();
        blow_text.textColor = 0xFFFFFF;
        blow_text.text = blow.toString();
        blow_text.x = 84;
        blow_text.y = 0;
        addChild(blow_text);
    }
}

// 記録一覧
class RecordList extends Sprite {
    public const RECORD_MAX_SIZE:uint = 20;

    private var mRecordList:Vector.<Record> = new Vector.<Record>();

    public function RecordList() {
        var hit_text:TextField = addChild(new TextField()) as TextField;
        hit_text.text = "hit";
        hit_text.textColor = 0xFFFFFF;
        hit_text.x = 8;
        hit_text.y = 0;
        
        var blow_text:TextField = addChild(new TextField()) as TextField;
        blow_text.text = "blow";
        blow_text.textColor = 0xFFFFFF;
        blow_text.x = 90;
        blow_text.y = 0;
    }

    public function push_record(record:Record):void {
        var i:int;
        if (mRecordList.length >= RECORD_MAX_SIZE) {
            var old_record:Record = mRecordList.shift();
            removeChild(old_record);
        }

        mRecordList.push(record);
        record.x = 10;
        addChild(record);

        for (i = 0; i < mRecordList.length; ++i) {
            mRecordList[i].y = (mRecordList.length - i - 1) * 15 + 20;
        }
    }
}

// チェックスイッチ
class CheckSwitch extends Sprite {
    public function CheckSwitch() {
        graphics.lineStyle(2, 0x00FF00, 0.2);
        graphics.drawCircle(0, 0, 18);
        graphics.lineStyle(5, 0x00FF00, 0.4);
        graphics.drawCircle(0, 0, 8);
    }
}