[AS3] flixelの弾幕デモ

2012/08/3

こんにちは。きんくまです。

この間のF-siteの用にflixelでつくった弾幕ゲームのデモを少し修正できたのでアップします。
デモのときは、iPadで使えるようにキーボード操作でなく、タッチ操作にしてました。

■あそびかた
キーボードの上下左右で操作。3回やられたらゲームオーバー。
クリアしてもループするだけです。すみません、、。

あれ? ブラウザでみると、けっこうカクつきますね。
swfそのまま見ると、もうちっとなめらかなんだけど。

 
ソースコードも書いておきます。
flixelが面倒なことをやってくれてるので、わりと短め?なのかな。
自機爆発のビットマップデータはflixelについてたflixelのロゴデータですw

shooting_demo.as


package
{	
	import flash.events.Event;
	
	import org.flixel.FlxGame;

	[SWF(width="480", height="640", backgroundColor="#000000", frameRate="60")]
	
	public class shooting_demo extends FlxGame
	{
		public function shooting_demo()
		{
			super(480 * 0.5, 640 * 0.5, MenuState,2, 60, 60);
		}
		
		override protected function create(FlashEvent:Event):void
		{
			super.create(FlashEvent);
		}
	}
}

MenuState.as

package
{
	import org.flixel.FlxButton;
	import org.flixel.FlxG;
	import org.flixel.FlxState;
	import org.flixel.FlxText;
	
	public class MenuState extends FlxState
	{
		private var _firstChar:FlxText;
		private var _title:FlxText;
		private var _startButton:FlxButton;
		
		public function MenuState()
		{
			super();
		}
		
		public override function create():void
		{
			super.create();
			FlxG.mouse.show();
			_startButton = new FlxButton(FlxG.width * 0.5 - 40, 160, "START", onStartClick);
			add(_startButton);			
			
			_title = new FlxText(54,90,200,"hooting!!");
			_title.size = 28;
			add(_title);
			
			_firstChar = new FlxText(27,80,40,"S");
			_firstChar.color = 0xFFFFCC33;
			_firstChar.size = 46;
			add(_firstChar);
		}
		
		public override function destroy():void
		{
			super.destroy();
			_startButton = null;
			_title = null;
		}
		
		private function onStartClick():void
		{
			FlxG.mouse.hide();
			FlxG.switchState(new PlayState());
		}
	}
}

PlayState.as

package
{
	import flashx.textLayout.elements.BreakElement;
	
	import org.flixel.FlxEmitter;
	import org.flixel.FlxG;
	import org.flixel.FlxGroup;
	import org.flixel.FlxPoint;
	import org.flixel.FlxSprite;
	import org.flixel.FlxState;
	import org.flixel.FlxText;
	import org.flixel.FlxTilemap;
	
	public class PlayState extends FlxState
	{
		private var _player:FlxSprite;
		private var _enemy:FlxSprite;
		private var _bullets:FlxGroup;
		private var _enemyBullets:FlxGroup;
		private var _shotCnt:int = 0;
		private var _enemyShotCnt:int = 0;
		private var _enemyHealthBar:FlxSprite;
		private var _enemyHelathBarBase:FlxSprite;
		private var _enemyShootOffsetRad:Number = 0;
		private var _scoreTxt:FlxText;
		private var _score:int;
		private var _isGameOver:Boolean = false;
		private var _gameOverText:FlxText;
		private var _pressZkeyText:FlxText;
		private const MAX_ENEMY_HEALTH:int = 100;
		private const PLAYER_MAX_HEALTH:int = 3;
		private var _playerExplosion:FlxEmitter;
		
		[Embed(source="org/flixel/data/logo.png")] private var LogoBmd:Class;
		
		override public function create():void
		{
			_player = new FlxSprite(FlxG.width * 0.5, FlxG.height - 50);
			_player.makeGraphic(8,8,0xffff0000);
			_player.maxVelocity.x = 120;
			_player.maxVelocity.y = 120;
			_player.drag.x = _player.maxVelocity.x * 4;
			_player.drag.y = _player.maxVelocity.y * 4;
			_player.health = PLAYER_MAX_HEALTH;
			_player.immovable = true;
			add(_player);
			
			_enemy = new FlxSprite(FlxG.width * 0.5, 40);
			_enemy.makeGraphic(30,8,0xff00ff00);
			_enemy.health = MAX_ENEMY_HEALTH;
			_enemy.velocity.y = 0;
			_enemy.acceleration.y = 0;
			_enemy.immovable = true;
			_enemy.acceleration.x = 10;
			_enemy.maxVelocity.x = 100;
			add(_enemy);
			
			
			var i:int;
			_bullets = new FlxGroup();
			for(i = 0; i < 60; i++){
				var bullet:FlxSprite = new FlxSprite(100,100);
				bullet.makeGraphic(2,5,0xffffffff);
				bullet.exists = false;
				_bullets.add(bullet);
			}
			add(_bullets);
			
			_enemyBullets = new FlxGroup();
			for(i = 0; i < 300; i ++){
				var enemyBullet:FlxSprite = new FlxSprite(100,100);
				enemyBullet.makeGraphic(4,4,0xffffff00);
				enemyBullet.exists = false;
				enemyBullet.immovable = true;
				_enemyBullets.add(enemyBullet);
			}
			add(_enemyBullets);
			
			_enemyHelathBarBase = new FlxSprite(10,20);
			_enemyHelathBarBase.makeGraphic(FlxG.width -20,3,0xffffffff);
			add(_enemyHelathBarBase);
			
			_enemyHealthBar = new FlxSprite(10,20);
			_enemyHealthBar.makeGraphic((FlxG.width - 20), 3, 0xffff0000);
			add(_enemyHealthBar);
			
			_scoreTxt = new FlxText(10, 2, 100);
			add(_scoreTxt);
			
			_score = 0;
			
			_gameOverText = new FlxText(80, 120, 100, "GAME OVER");
			_gameOverText.size = 24;
			_gameOverText.visible = false;
			add(_gameOverText);
			
			_pressZkeyText = new FlxText(88,200, 120, "PRESS Z KEY");
			_pressZkeyText.size = 8;
			_pressZkeyText.visible = false;
			add(_pressZkeyText);
			
			_playerExplosion = new FlxEmitter(FlxG.width * 0.5, FlxG.height * 0.5);
			_playerExplosion.setSize(30,30);
			_playerExplosion.setXSpeed(-300,300);
			_playerExplosion.setYSpeed(-300,300);
			_playerExplosion.setRotation(-720,720);
			_playerExplosion.makeParticles(LogoBmd,650,32,true,0);
			add(_playerExplosion);
		}
		
		override public function update():void
		{
			var bullet:FlxSprite;
			_player.acceleration.x = 0;
			_player.acceleration.y = 0;
			
			if(!_player.exists && FlxG.keys.Z){
				_gameOverText.visible = false;
				_pressZkeyText.visible = false;
				_player.health = PLAYER_MAX_HEALTH;
				_player.exists = true;
			}
			
			if(FlxG.keys.RIGHT){
				_player.acceleration.x = _player.maxVelocity.x *3;
			}
			if(FlxG.keys.LEFT){
				_player.acceleration.x = -_player.maxVelocity.x * 3;
			}
			if(FlxG.keys.UP){
				_player.acceleration.y = -_player.maxVelocity.y *3;
			}
			if(FlxG.keys.DOWN){
				_player.acceleration.y = _player.maxVelocity.y *3;
			}
			
			if(_player.exists && _shotCnt > 2){
				for each(bullet in _bullets.members){
					if(!bullet.exists){
						bullet.x = _player.x + 3;
						bullet.y = _player.y;
						bullet.velocity.x = 0;
						bullet.velocity.y = -200;
						bullet.exists = true;
						_shotCnt = 0;
						break;
					}else{
						
					}
				}
			}else{
				_shotCnt++;
			}
			
			var enemyBullet:FlxSprite;
			var enemyBulletShoootCnt:int = 0;
			var enemyBulletRad:Number;
			var direction:Number = 90;
			var enmbulletMax:int = 8;
			var dRad:Number = Math.PI * (enmbulletMax - 1) * 2 / 180.0;
			var currentRad:Number = Math.PI * direction / 180.0 - dRad * (enmbulletMax-1) * 0.5 + Math.sin(_enemyShootOffsetRad) * 0.5;
			var enmBulletVelocity:Number = 50;
			if(_enemyShotCnt > 15){
				for each(enemyBullet in _enemyBullets.members){
					if(!enemyBullet.exists){
						enemyBullet.x = _enemy.width * 0.5 + _enemy.x;
						enemyBullet.y = _enemy.height + _enemy.y;
						enemyBullet.velocity.x = Math.cos(currentRad) * enmBulletVelocity;
						enemyBullet.velocity.y = Math.sin(currentRad) * enmBulletVelocity;
						currentRad += dRad;
						enemyBulletShoootCnt++;
						enemyBullet.exists = true;
						if(enemyBulletShoootCnt >= enmbulletMax){
							break;
						}
					}
				}
				_enemyShotCnt = 0;
				_enemyShootOffsetRad += 0.2;
				if(_enemyShootOffsetRad > Math.PI * 2){
					_enemyShootOffsetRad -= Math.PI * 2;
				}
			}else{
				_enemyShotCnt++;
			}
			
			super.update();
			
			for each(bullet in _bullets.members){
				if(bullet.exists && bullet.y < 0){
					bullet.exists = false;
					bullet.velocity.y = 0;
				}
			}
			for each(enemyBullet in _enemyBullets.members){
				if(enemyBullet.exists){
					if(enemyBullet.y > FlxG.height
						|| enemyBullet.y < 0
						|| enemyBullet.x < 0
						|| enemyBullet.x > FlxG.width){
						enemyBullet.exists = false;
						enemyBullet.velocity.x = 0;
						enemyBullet.velocity.y = 0;
					}
				}
			}
			
			var enemyMoveMaxX:int = 20;
			var enemyHalfW:int = _enemy.width * 0.5;
			if(_enemy.x + enemyHalfW < enemyMoveMaxX){
				_enemy.velocity.x = 0;
				_enemy.acceleration.x = 10;
				_enemy.x = enemyMoveMaxX - enemyHalfW;
			}
			if(_enemy.x + enemyHalfW > FlxG.width - enemyMoveMaxX){
				_enemy.velocity.x = 0;
				_enemy.acceleration.x = -10;
				_enemy.x = FlxG.width - enemyMoveMaxX - enemyHalfW;
			}
			
			FlxG.overlap(_enemy, _bullets, onEnemyWithBulletsOverlap);
			FlxG.overlap(_player, _enemyBullets, onPlayerWithEnemyBulletsOverlap);
			
			updateEnemyHealthBar();
			
			if(_player.x < 0){
				_player.x = 0;
			}
			if(_player.x > FlxG.width){
				_player.x = FlxG.width;
			}
			if(_player.y < 0){
				_player.y = 0;
			}
			if(_player.y > FlxG.height){
				_player.y = FlxG.height;
			}
			
			_scoreTxt.text = 'SCORE: ' + _score.toString();
		}
		
		private function updateEnemyHealthBar():void
		{
			var barScale:Number = _enemy.health / MAX_ENEMY_HEALTH;
			if(barScale * (FlxG.width - 20) >= 1){
				_enemyHealthBar.makeGraphic((FlxG.width - 20) * barScale, 3, 0xffff0000);
				_enemyHealthBar.exists = true;
			}else{
				_enemyHealthBar.exists = false;
			}
		}
		
		override public function destroy():void
		{
			super.destroy();
			_player = null;
		}
		
		private function onEnemyWithBulletsOverlap(enemy:FlxSprite, bullet:FlxSprite):void
		{
			enemy.health -= 1;
			enemy.velocity.y = 0;
			enemy.acceleration.y = 0;
			enemy.flicker(0.2);
			bullet.exists = false;
			if(enemy.health < 0){
				enemy.health = MAX_ENEMY_HEALTH;
				enemy.x = 40;
				enemy.y = 40;
				_score += 100000;
			}
			_score += 100;
		}
		
		private function onPlayerWithEnemyBulletsOverlap(player:FlxSprite, enemyBullet:FlxSprite):void
		{
			if(_player.flickering){
				return;
			}
			
			_player.health--;
			_player.flicker(1.0);
			enemyBullet.exists = false;
			if(_player.health <= 0){
				_player.kill();
				_playerExplosion.x = _player.x;
				_playerExplosion.y = _player.y;
				_playerExplosion.start(true, 3);
				_gameOverText.visible = true;
				_pressZkeyText.visible = true;
			}
		}
	}
}
LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る