forked from: DeviceGameSample
/**
* Copyright picana ( http://wonderfl.net/user/picana )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sZvo
*/
package {
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.display.Bitmap;
import flash.display.BitmapData
import flash.display.Graphics;
import flash.geom.Matrix;
import flash.events.Event;
[SWF(width=544, height=392, frameRate="30")]
public class Main extends Sprite {
private var field:Field;
public var player:Player;
private var enemy:Enemy;
public static const WIDTH:Number = 544;
public static const HEIGHT:Number = 392;
public var mainBitmapData:BitmapData
public function Main() {
// 最初にinitを呼び出す
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.scaleMode = StageScaleMode.EXACT_FIT;
// 画面の左上に合わせて表示する
stage.align = StageAlign.TOP_LEFT;
field = new Field(this);
addChild(field);
graphics.beginFill(0xaaaaaaaa);
graphics.drawRect(0, 0, WIDTH, HEIGHT);
// プレイヤー作成
player = new Player(171, 352);
// fieldに追加
field.addActor(player);
// 敵作成
enemy = new Enemy(171, 40, field);
// fieldに追加
field.addActor(enemy);
// カメラとマイクのデータを取得するためのクラス
var dm:DeviceManager = new DeviceManager();
dm.addEventListener(DeviceManagerEvent.POWER_CHANGE, powerChangeHnadler);
dm.start();
// カメラ映像の位置のセット
var video:Bitmap = addChild(new Bitmap(dm.nowBitmapData)) as Bitmap;
video.x = 352;
video.y = 10;
}
private function powerChangeHnadler(e:DeviceManagerEvent):void {
// 自機を動かす
player.move((e.rightPower - e.leftPower)/200);
// 一定以上の音量のときは弾発射
if (e.micPower > 3) {
field.nWay(BigBall, 3, Math.PI*3/2, Math.PI*1/12);
}
}
}
}
import flash.display.Sprite;
import flash.display.Graphics;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.Camera;
import flash.media.Video;
import flash.media.Microphone;
import flash.media.SoundTransform;
import flash.media.SoundMixer;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.events.EventDispatcher;
import flash.utils.Timer;
/*********************
* 自機、弾、敵を表示する *
*********************/
class Field extends Sprite {
public var fieldBitmapData:BitmapData;
private var actors:Array;
public static const FIELD_WIDTH:Number = 322;
public static const FIELD_HEIGHT:Number = 372;
private var main:Main;
public function Field(main:Main) {
this.main = main;
this.x = 10; this.y = 10;
actors = [];
fieldBitmapData = new BitmapData(FIELD_WIDTH, FIELD_HEIGHT, false, 0x000000);
var bitmap:Bitmap = new Bitmap(fieldBitmapData);
bitmap.blendMode = BlendMode.ADD;
addChild(new Bitmap(fieldBitmapData));
addEventListener(Event.ENTER_FRAME, enterFrameHandler)
}
private function enterFrameHandler(e:Event):void {
fieldBitmapData.fillRect(fieldBitmapData.rect, 0x000000);
var mtx:Matrix;
var index:int = 0;
// 自機、弾、敵をBitmapDataに描画
for each(var a:Actor in actors) {
// 死亡フラグ
if (a.die) {
actors.splice(index, 1);
}
a.update();
mtx = new Matrix();
mtx.translate(a.x, a.y);
fieldBitmapData.draw(a.view, mtx,null,BlendMode.ADD);
index++;
}
}
public function addActor(actor:Actor):void {
actors.push(actor);
}
public function nWay(bullet:Class, n:int, direction:Number, range:Number):void {
if (n > 1) {
for (var i:int = 0; i < n; i++) {
addBullet(new bullet(main.player.x, main.player.y, direction + range * (i/(n-1)-0.5)));
}
} else if (n == 1) {
addBullet(new bullet(main.player.x, main.player.y, direction));
}
}
public function addBullet(bullet:Bullet):void {
actors.push(bullet);
}
}
/*****************************
* Fieldに追加される何かの基本クラス *
*****************************/
class Actor {
public var color:uint;
public var x:Number;
public var y:Number;
public var vx:Number;
public var vy:Number;
public var view:Sprite;
public var die:Boolean = false;
public static var field:Field;
public function Actor(x:Number, y:Number) {
this.x = x;
this.y = y;
}
public function update():void { }
public function nWay(bullet:Class, n:int, direction:Number, range:Number):void {
if (n > 1) {
for (var i:int = 0; i < n; i++) {
field.addBullet(new bullet(x, y, direction + range * (i / (n - 1) - 0.5)));
}
} else if (n == 1) {
field.addBullet(new bullet(x, y, direction));
}
}
}
// 自機
class Player extends Actor {
public function Player(x:Number, y:Number) {
super(x,y);
view = new Sprite();
// view
var g:Graphics = view.graphics;
g.lineStyle(1,0xFFFFFF);
g.moveTo(10, 10);
g.lineTo(0, -10);
g.lineTo(-10, 10);
g.lineTo(10, 10);
}
public override function update():void {
}
public function move(value:Number):void {
x += value;
if (x < 10) x = 0;
else if (x > Field.FIELD_WIDTH-10) x = Field.FIELD_WIDTH-10;
}
}
class Enemy extends Actor {
private var t:Number;
// コンストラクタ
public function Enemy(x:Number, y:Number, field:Field) {
super(x,y);
view = new Sprite();
// view
var g:Graphics = view.graphics;
g.lineStyle(1,0xFFFFFF);
g.moveTo(-10, -10);
g.lineTo(0, 10);
g.lineTo(10, -10);
g.lineTo(-10, -10);
Actor.field = field;
t = 0;
}
public override function update():void {
t++;
// 攻撃開始
if (t > 10) {
if (!(t % 100)) {
nWay(GrainBullet2, 30, Math.PI * (t % 360) / 180, Math.PI * 2);
}
}
}
}
// 弾
class Bullet extends Actor {
public var direction:Number;
public var v:Number;
public function Bullet(x:Number, y:Number, direction:Number, v:Number) {
super(x, y);
this.direction = direction;
this.v = v;
}
public function checkDie():void {
if (!(x > 0 && x < Field.FIELD_WIDTH && y > 0 && y < Field.FIELD_HEIGHT)) {
die = true;
}
}
}
import flash.filters.GlowFilter;
import flash.filters.BlurFilter;
class GrainBullet1 extends Bullet {
public function GrainBullet1(x:Number, y:Number, direction:Number, v:Number = 3) {
super(x, y, direction, v);
color = Math.random() * 0xFFFFFF;
view = new Sprite();
var g:Graphics = view.graphics;
g.lineStyle(2, color);
g.drawCircle(0, 0, 2);
view.filters = [new BlurFilter(2,2,3)];
view.blendMode = BlendMode.ADD;
}
public override function update():void {
vx = Math.cos(direction) * v;
vy = -Math.sin(direction) * v;
x += vx;
y -= vy;
checkDie();
}
}
// 大玉
class BigBall extends Bullet {
public function BigBall(x:Number, y:Number, direction:Number, v:Number = 10.5) {
super(x, y, direction, v);
color = 0xff0000;
view = new Sprite();
var g:Graphics = view.graphics;
g.lineStyle(2, color);
g.drawCircle(0, 0, 5);
view.filters = [new BlurFilter(2,2,3)];
view.blendMode = BlendMode.ADD;
}
public override function update():void {
vx = Math.cos(direction) * v;
vy = -Math.sin(direction) * v;
x += vx;
y -= vy;
checkDie();
}
/*
public function hitTest():Boolean {
return Math.sqrt(Math.pow(player.x - x, 2) + Math.pow(player.y - y, 2)) < 10;
}
*/
}
/*
class BigBall1 extends BigBall {
public function BigBall1(x0:Number, y0:Number, d:Number, v:Number = 1) {
super(x0, y0, d);
vx = Math.cos(direction) * v;
vy = -Math.sin(direction) * v;
}
override public function update():void {
x += vx;
y += vy;
if (x < -10 || x > field.fieldWidth + 10 ||
y < -10 || y > field.fieldHeight + 10) {
dead = true;
}
}
}
*/
/************************
* 敵機の周りを回った後はじける *
************************/
class GrainBullet2 extends Bullet {
private var t:uint = 0;
public function GrainBullet2(x:Number, y:Number, direction:Number, v:Number = 4) {
super(x, y, direction, v);
color = 0x0000ff;
view = new Sprite();
var g:Graphics = view.graphics;
g.lineStyle(5, color);
g.drawCircle(0, 0, 10);
view.filters = [new BlurFilter(2,2,3)];
view.blendMode = BlendMode.ADD;
}
override public function update():void {
t++;
if (t < 300) {
direction += 0.06 - t * 0.0002;
x += Math.cos(direction*2) * v;
y -= Math.sin(direction*2) * v;
} else {
nWay(GrainBullet1, 6, t, Math.PI * 2);
die = true;
}
}
}
class DeviceManager extends EventDispatcher {
private var _camera:Camera;
private var _mic:Microphone;
private var _video:Video;
private var _timer:Timer;
private var _now:BitmapData;
private var _nowLeft:BitmapData;
private var _prevLeft:BitmapData;
private var _nowRight:BitmapData;
private var _prevRight:BitmapData;
private var _rectLeft:Rectangle;
private var _rectReght:Rectangle;
private var _zero:Point;
public function get nowBitmapData():BitmapData {
return _now;
}
public function DeviceManager() {
// camera
_camera = Camera.getCamera();
if (_camera == null) {
return
}
_mic = Microphone.getMicrophone();
if (_mic == null) {
return;
}
// 動画横幅・動画縦幅・フレームレート
_camera.setMode(160, 120, 40);
_video = new Video(_camera.width, _camera.height);
_video.attachCamera(_camera);
_now = new BitmapData(_camera.width, _camera.height);
_nowLeft = new BitmapData(_camera.width/2, _camera.height);
_prevLeft = new BitmapData(_camera.width/2, _camera.height);
_nowRight = new BitmapData(_camera.width/2, _camera.height);
_prevRight = new BitmapData(_camera.width/2, _camera.height);
// 左右分割のためのRectangle
_rectLeft = new Rectangle(0,0,_camera.width/2, _camera.height);
_rectReght = new Rectangle(_camera.width/2, 0, _camera.width/2, _camera.height);
_zero = new Point();
_mic.setLoopBack(true);
var stf:SoundTransform = SoundMixer.soundTransform;
stf.volume = 0;
SoundMixer.soundTransform = stf;
}
public function start():void {
_timer = new Timer(100);
_timer.addEventListener(TimerEvent.TIMER, timerHnadler);
_timer.start();
}
private function timerHnadler(e:TimerEvent):void {
var mtx:Matrix = new Matrix();
mtx.scale(-1,1);
mtx.translate(_camera.width, 0);
_now.draw(_video, mtx);
// left
_nowLeft.copyPixels(_now, _rectLeft, _zero);
// 前回との比較
_nowLeft.draw(_prevLeft, null, null, BlendMode.DIFFERENCE);
// 変更されたピクセルの数が取得できる
var l:uint = _nowLeft.threshold(_nowLeft, _nowLeft.rect, _zero, ">", 0xFF111111, 0xFFFFFFFF);
_prevLeft.copyPixels(_now, _rectLeft, _zero);
// right
_nowRight.copyPixels(_now, _rectReght, _zero);
// 前回との比較
_nowRight.draw(_prevRight, null, null, BlendMode.DIFFERENCE);
// 変更されたピクセルの数が取得できる
var r:uint = _nowRight.threshold(_nowRight, _nowRight.rect, _zero, ">", 0xFF111111, 0xFFFFFFFF);
_prevRight.copyPixels(_now, _rectReght, _zero);
var level:Number = _mic.activityLevel;
dispatchEvent(new DeviceManagerEvent(DeviceManagerEvent.POWER_CHANGE,
l,r, level));
}
}
class DeviceManagerEvent extends Event {
public static const POWER_CHANGE:String = "powerChange";
public var leftPower:Number;
public var rightPower:Number;
public var micPower:Number;
public function DeviceManagerEvent(type:String,
leftPower:Number = 0,
rightPower:Number = 0,
micPower:Number = 0,
bubbles:Boolean = false,
cancelabable:Boolean = false){
super(type, bubbles, cancelabable);
this.leftPower = leftPower;
this.rightPower = rightPower;
this.micPower = micPower;
}
}