某魔法少女のオンラインゲームのインキュベータテスト
release version (完成版)
http://wonderfl.net/c/3VrR
[controls]
Arrow: movement (矢印キー: 移動)
z: attack (攻撃)
x: reload (リロード)
c: swap weapon (武器切り替え)
/**
* Copyright o8que ( http://wonderfl.net/user/o8que )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/9Odl
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.geom.Rectangle;
import flash.utils.Timer;
import net.user1.logger.Logger;
import net.user1.reactor.Reactor;
import net.wonderfl.utils.WonderflAPI;
/* import ore.orelib.assets.Artist;
import ore.orelib.commons.Assets;
import ore.orelib.commons.GeomPool;
import ore.orelib.commons.Input;
import ore.orelib.commons.Preloader;
import ore.orelib.commons.TileSheet;
import ore.orelib.commons.UnionStats;
import ore.orelib.data.Const;
import ore.orelib.scenes.IScene;
import ore.orelib.scenes.TitleScene;
*/
[SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "0x000000")]
public class Main extends Sprite {
private var _reactor:Reactor;
private var _synchronizer:Timer;
private var _api:WonderflAPI;
private var _scene:IScene;
private var _timestamp:Number;
public function Main() {
// Reactorの初期設定
_reactor = new Reactor();
_reactor.getConnectionMonitor().setHeartbeatFrequency(1000);
_reactor.getConnectionMonitor().setConnectionTimeout(5000);
_reactor.getConnectionMonitor().setAutoReconnectFrequency(5000);
_reactor.getLog().setLevel(Logger.FATAL);
//_reactor.getLog().setLevel(Logger.DEBUG);
var stats:UnionStats = new UnionStats(_reactor);
stats.y = 465 - stats.height;
stats.alpha = 0.8;
stage.addChild(stats);
// Reactor接続、各アセット読み込み
var preloader:Preloader = new Preloader(this);
preloader.addReactorConnectionRequest(_reactor);
preloader.addLoaderRequest(Const.IMAGE_URL);
preloader.addFontLoaderRequest(Const.FONT);
preloader.addEventListener(Event.COMPLETE, initialize);
preloader.load();
}
private function initialize(event:Event):void {
var preloader:Preloader = event.currentTarget as Preloader;
preloader.removeEventListener(event.type, arguments.callee);
// 画像アセットの登録
var sheet:TileSheet = new TileSheet(preloader.loaders[Const.IMAGE_URL]);
Assets.images["characters"] = sheet.blit(new Rectangle(0, 0, 16, 16), 3, 6);
Assets.images["weapons"] = sheet.blit(new Rectangle(48, 0, 32, 24), 3, 4);
Assets.images["background"] = Artist.createBackground();
Assets.images["actorShadow"] = Artist.createActorShadow();
Assets.images["muzzleFlashes"] = Artist.createMuzzleFlashes(10);
Assets.images["bloods"] = Artist.createBloods(10);
// 静的クラスの初期化
Input.setup(stage);
GeomPool.setup(5);
// サーバーとの同期
synchronize();
_synchronizer = new Timer(30000, 0);
_synchronizer.addEventListener(TimerEvent.TIMER, synchronize);
_synchronizer.start();
_api = new WonderflAPI(root.loaderInfo.parameters);
_scene = new TitleScene(this);
_timestamp = _reactor.getServer().getServerTime();
addEventListener(Event.ENTER_FRAME, update);
}
private function synchronize(event:TimerEvent = null):void {
if (_reactor.isReady()) { _reactor.getServer().syncTime(); }
}
private function update(event:Event):void {
var serverTime:Number = _reactor.getServer().getServerTime();
_scene.update(serverTime, Math.max(0, serverTime - _timestamp));
_timestamp = serverTime;
Input.record();
}
public function changeScene(scene:IScene):void { _scene = scene; }
public function get reactor():Reactor { return _reactor; }
public function get api():WonderflAPI { return _api; }
}
}
//package ore.orelib.scenes {
import flash.events.IEventDispatcher;
//public
interface IScene extends IEventDispatcher {
function update(serverTime:Number, elapsedTime:int):void;
}
//}
//package ore.orelib.scenes {
import com.bit101.components.PushButton;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.filters.BevelFilter;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import net.user1.reactor.ReactorEvent;
import net.user1.reactor.Room;
import net.user1.reactor.RoomEvent;
import net.user1.reactor.RoomManagerEvent;
import net.user1.reactor.UpdateLevels;
/* import ore.orelib.commons.TextBuilder;
import ore.orelib.data.Const;
import ore.orelib.data.SaveData;
*/
//public
class TitleScene extends Sprite implements IScene {
private var _main:Main;
private var _nameInput:TextField;
private var _buttons:Vector.<PushButton>;
private static const NUM_ROOMS:int = 1;
public function TitleScene(main:Main) {
_main = main;
_main.addChild(this);
addChild(
new TextBuilder().align(TextBuilder.CENTER).autoSize()
.font(Const.FONT, 0, 400).fontColor(0xFFFFFF).fontSize(50)
.pos(0, 100).size(465, 132).build("全ほ連")
);
addChild(_nameInput = createNameInput());
_buttons = new Vector.<PushButton>(NUM_ROOMS, true);
for (var i:int = 0; i < NUM_ROOMS; i++) {
_buttons[i] = new PushButton(this, 182, 310 + 30 * i, "join (0)", startPlaying);
}
_main.reactor.addEventListener(ReactorEvent.READY, enableToJoin);
_main.reactor.addEventListener(ReactorEvent.CLOSE, disableToJoin);
(_main.reactor.isReady()) ? enableToJoin() : disableToJoin();
}
private function createNameInput():TextField {
var result:TextField = new TextField();
result.x = 142; result.y = 270;
result.width = 180; result.height = 20;
result.defaultTextFormat = new TextFormat("_sans", 14, 0x000000, null, null, null, null, null, TextFormatAlign.CENTER);
result.background = true; result.backgroundColor = 0xFFFFFF;
result.filters = [new BevelFilter(1, 225, 0xC0C0C0, 1, 0x404040, 1, 1, 1)];
result.maxChars = 12;
result.selectable = true;
result.type = TextFieldType.INPUT;
result.text = SaveData.instance.player.name || "魔法少女" + _main.reactor.self().getClientID() + "番";
return result;
}
private function startPlaying(event:MouseEvent):void {
SaveData.instance.player.name = _nameInput.text || "魔法少女" + _main.reactor.self().getClientID() + "番";
// 各リスナの削除
_main.reactor.removeEventListener(ReactorEvent.READY, enableToJoin);
_main.reactor.removeEventListener(ReactorEvent.CLOSE, disableToJoin);
_main.reactor.getRoomManager().stopWatchingForRooms(String(_main.api.appID) + ".game");
_main.reactor.getRoomManager().removeEventListener(RoomManagerEvent.ROOM_ADDED, roomAddedHandler);
for (var i:int = 0; i < NUM_ROOMS; i++) {
var room:Room = _main.reactor.getRoomManager().getRoom(String(_main.api.appID) + ".game." + i);
if (room) { room.removeEventListener(RoomEvent.OCCUPANT_COUNT, roomClientCountHandler); }
}
_main.removeChild(this);
_main.changeScene(new PlayingScene(_main, _buttons.indexOf(event.currentTarget as PushButton)));
}
/** サーバーと正常に接続されている場合に、ゲーム参加を可能する */
private function enableToJoin(event:ReactorEvent = null):void {
_main.reactor.getRoomManager().watchForRooms(String(_main.api.appID) + ".game");
_main.reactor.getRoomManager().addEventListener(RoomManagerEvent.ROOM_ADDED, roomAddedHandler);
for (var i:int = 0; i < NUM_ROOMS; i++) {
_buttons[i].enabled = true;
_buttons[i].label = "join (0)";
}
}
/** 新しい部屋が作成されたら監視する */
private function roomAddedHandler(event:RoomManagerEvent):void {
var room:Room = event.getRoom();
var roomID:int = int(room.getSimpleRoomID());
if (roomID >= NUM_ROOMS) { return; }
// 部屋の参加人数のみを監視する
var updateLevels:UpdateLevels = new UpdateLevels();
updateLevels.clearAll();
updateLevels.occupantCount = true;
room.addEventListener(RoomEvent.OCCUPANT_COUNT, roomClientCountHandler, false, 0, true);
room.observe(String(_main.api.apiKey), updateLevels);
}
/** 参加者人数が変わったら更新する */
private function roomClientCountHandler(event:RoomEvent):void {
for (var i:int = 0; i < NUM_ROOMS; i++) {
var room:Room = _main.reactor.getRoomManager().getRoom(String(_main.api.appID) + ".game." + i);
var numClients:int = (room) ? room.getNumOccupants() : 0;
_buttons[i].label = "join (" + numClients + ")";
}
}
/** サーバーとの接続が切れた場合に、ゲーム参加不能にする */
private function disableToJoin(event:ReactorEvent = null):void {
for (var i:int = 0; i < NUM_ROOMS; i++) {
_buttons[i].enabled = false;
_buttons[i].label = "connecting...";
}
}
public function update(serverTime:Number, elapsedTime:int):void { }
}
//}
//package ore.orelib.scenes {
import com.bit101.components.PushButton;
import flash.display.Sprite;
import flash.events.MouseEvent;
import net.user1.reactor.Room;
import net.user1.reactor.RoomSettings;
import net.user1.reactor.UpdateLevels;
/* import ore.orelib.actors.EffectManager;
import ore.orelib.actors.EnemyManager;
import ore.orelib.actors.FriendManager;
import ore.orelib.assets.PlayingView;
import ore.orelib.data.Const;
import ore.orelib.logic.Host;
import ore.orelib.logic.Player;
*/
//public
class PlayingScene extends Sprite implements IScene {
private var _main:Main;
private var _room:Room;
private var _view:PlayingView;
private var _player:Player;
private var _host:Host;
private var _friends:FriendManager;
private var _enemies:EnemyManager;
private var _effects:EffectManager;
private var _isPlaying:Boolean;
public function PlayingScene(main:Main, roomNo:int) {
_main = main;
_main.addChild(this);
var roomSettings:RoomSettings = new RoomSettings();
roomSettings.password = String(_main.api.apiKey);
_room = _main.reactor.getRoomManager().createRoom(String(_main.api.appID) + ".game." + roomNo, roomSettings);
addChild(_view = new PlayingView());
_friends = new FriendManager(_room);
_enemies = new EnemyManager(_room);
_effects = new EffectManager(_view);
_player = new Player(_room, _main.reactor.self());
_host = new Host(_room, _main.reactor);
_view.setupHUD(_player);
addChild(_view.createChatWindow(String(_main.api.appID) + ".chat." + roomNo, _main.reactor));
stage.focus = null;
_room.join(String(_main.api.apiKey), new UpdateLevels());
_room.stopObserving();
_isPlaying = true;
}
public function update(serverTime:Number, elapsedTime:int):void {
if (!_isPlaying) { return; }
_player.update(elapsedTime, _enemies, (stage.focus == null));
_host.update(serverTime, elapsedTime);
_friends.update(elapsedTime);
_enemies.update(serverTime, elapsedTime, _host.isHost);
_effects.update();
_view.update(_player, _host);
// 接続が切れるか、QBの契約ノルマが達成されたらゲームオーバー
if (!_main.reactor.isReady() || _host.numContracts >= Const.FIELD_QB_QUOTA) { onGameover(); }
}
private function onGameover():void {
_isPlaying = false;
_room.leave();
_player.removeEventListeners();
_host.removeEventListeners();
_view.removeEventListeners();
_friends.removeEventListeners();
_enemies.removeEventListeners();
_effects.removeEventListeners();
_view.setupGameoverDisplay(new PushButton(null, 182, 300, "leave", leaveWorld), _main.reactor.isReady());
}
private function leaveWorld(event:MouseEvent):void {
_main.removeChild(this);
_main.changeScene(new TitleScene(_main));
}
}
//}
//package ore.orelib.logic {
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.ui.Keyboard;
import net.user1.reactor.Attribute;
import net.user1.reactor.AttributeEvent;
import net.user1.reactor.IClient;
import net.user1.reactor.Room;
/* import ore.orelib.actors.Enemy;
import ore.orelib.actors.EnemyManager;
import ore.orelib.actors.Friend;
import ore.orelib.commons.EventManager;
import ore.orelib.commons.GeomPool;
import ore.orelib.commons.Input;
import ore.orelib.data.Const;
import ore.orelib.data.PlayerData;
import ore.orelib.data.PlayerStatus;
import ore.orelib.data.SaveData;
import ore.orelib.data.WeaponSmith;
import ore.orelib.events.ActorEvent;
import ore.orelib.events.EffectEvent;
*/
//public
class Player {
private var _room:Room;
private var _self:IClient;
// プレイヤーのステータス・装備
private var _status:PlayerStatus;
private var _equip:PlayerEquipment;
private var _hp:int;
private var _invincibleCount:int;
private var _recoverCount:int;
private var _recoverTime:int;
// プレイヤーのビュー
private var _view:Friend;
private var _playerBounds:Rectangle;
private var _posSendCount:int;
// 撃退数
private var _killCount:int;
public static const BOUNDS_HALF_WIDTH:int = 10;
public static const BOUNDS_HEIGHT:int = 28;
public function Player(room:Room, self:IClient) {
_room = room;
_self = self;
var playerData:PlayerData = SaveData.instance.player;
var primary:Weapon = WeaponSmith.createWeaponFromData(SaveData.instance.inventory[playerData.primaryWeaponIndex]);
var secondary:Weapon = WeaponSmith.createWeaponFromData(SaveData.instance.inventory[playerData.secondaryWeaponIndex]);
_status = new PlayerStatus(
Math.min(Math.max(10, playerData.status.str + primary.strBonus + secondary.strBonus), 200),
Math.min(Math.max(10, playerData.status.vit + primary.vitBonus + secondary.vitBonus), 200),
Math.min(Math.max(10, playerData.status.dex + primary.dexBonus + secondary.dexBonus), 200),
Math.min(Math.max(10, playerData.status.luc + primary.lucBonus + secondary.lucBonus), 200)
);
_equip = new PlayerEquipment(primary, secondary);
_hp = _status.vit;
_invincibleCount = Const.PLAYER_INVINCIBLE_TIME_ON_RECOVER;
_recoverCount = 0;
_recoverTime = Const.PLAYER_RECOVER_TIME * _status.vit / 100;
_view = new Friend(
playerData.name,
Const.FIELD_SIZE,
Const.FIELD_SIZE * Math.random(),
Const.PLAYER_SPEED * _status.dex / 100,
_hp,
_status.vit,
playerData.characterID,
primary.id
);
_self.setAttribute(Friend.ATTR_NAME, playerData.name);
_self.setAttribute(Friend.ATTR_X, _view.x.toFixed(0));
_self.setAttribute(Friend.ATTR_Y, _view.y.toFixed(0));
_self.setAttribute(Friend.ATTR_SPEED, _view.speed.toFixed(0));
_self.setAttribute(Friend.ATTR_HP, _hp.toString());
_self.setAttribute(Friend.ATTR_MAXHP, _status.vit.toString());
_self.setAttribute(Friend.ATTR_CHARACTER, playerData.characterID.toString());
_self.setAttribute(Friend.ATTR_WEAPON, primary.id.toString());
EventManager.instance.dispatchEvent(new ActorEvent(ActorEvent.ADD, _view, _view.overlay));
_playerBounds = new Rectangle(
_view.x - Player.BOUNDS_HALF_WIDTH,
_view.y - Player.BOUNDS_HEIGHT,
Player.BOUNDS_HALF_WIDTH * 2,
Player.BOUNDS_HEIGHT
);
_posSendCount = Const.PLAYER_POS_SEND_INTERVAL;
_killCount = 0;
_room.addEventListener(AttributeEvent.UPDATE, onKillEnemy);
}
private function onKillEnemy(event:AttributeEvent):void {
var attr:Attribute = event.getChangedAttr();
var idAndName:Array = attr.name.split(".");
if (idAndName[1] != Enemy.ATTR_HP) { return; }
if (int(attr.value) <= 0) {
_room.deleteAttribute(idAndName[0] + "." + Enemy.ATTR_STATUS);
_room.deleteAttribute(idAndName[0] + "." + Enemy.ATTR_HP);
_room.deleteAttribute(idAndName[0] + "." + Enemy.ATTR_SPAWN_X);
if (int(attr.oldValue) > 0) {
_killCount++;
}
}
}
private function changeHp(value:int):void {
if (value <= 0) {
_invincibleCount = _recoverTime;
_recoverCount = _recoverTime;
} else if (value < _hp) {
_invincibleCount = Const.PLAYER_INVINCIBLE_TIME_ON_DAMAGED;
}
_hp = Math.max(0, value);
_view.changeHp(_hp);
_self.setAttribute(Friend.ATTR_HP, _hp.toString());
}
public function update(elapsedTime:int, enemies:EnemyManager, isControllable:Boolean):void {
_equip.update(elapsedTime);
if (_invincibleCount > 0) { _invincibleCount -= elapsedTime; }
if (_recoverCount > 0) {
_recoverCount -= elapsedTime;
if (_recoverCount <= 0) {
changeHp(_status.vit);
_invincibleCount = Const.PLAYER_INVINCIBLE_TIME_ON_RECOVER;
}
}
if (isControllable) { processInput(elapsedTime, enemies); }
_view.update(elapsedTime);
_posSendCount -= elapsedTime;
if (_posSendCount < 0) {
_posSendCount += Const.PLAYER_POS_SEND_INTERVAL;
_self.setAttribute(Friend.ATTR_X, _view.x.toFixed(0));
_self.setAttribute(Friend.ATTR_Y, _view.y.toFixed(0));
}
if (_invincibleCount <= 0) {
var collidingEnemies:Vector.<Enemy> = enemies.acquireCollidingEnemies(_playerBounds);
if (collidingEnemies.length > 0) {
changeHp(_hp - collidingEnemies[0].str);
}
}
}
private function processInput(elapsedTime:int, enemies:EnemyManager):void {
if (_recoverCount > 0) { return; }
move(elapsedTime);
if (_equip.isSwapping()) { return; }
if (Input.key.isPressed(Input.C)) {
_equip.swap();
_view.swapWeapon(_equip.currentWeapon.id);
_self.setAttribute(Friend.ATTR_WEAPON, _equip.currentWeapon.id.toString());
return;
}
if (_equip.isReloading()) { return; }
if (Input.key.isPressed(Input.X) && !_equip.isAmmoFull()) {
_equip.reload(_status);
return;
}
if (Input.key.isDown(Input.Z)) {
if (_equip.isAmmoEmpty()) {
_equip.reload(_status);
} else if (_equip.canAttack()) {
var range:int = _equip.attack(_room, _view.x, _view.y, _status, enemies);
_view.attack(_equip.currentWeapon.id, range);
_room.sendMessage(Friend.MESSAGE_ATTACK, false, null, _equip.currentWeapon.id.toString(), range.toString());
EventManager.instance.dispatchEvent(new EffectEvent(
EffectEvent.ATTACK_WEAPON,
_view.x, _view.y,
{ id: _equip.currentWeapon.id, range: range }
));
}
}
}
private function move(elapsedTime:int):void {
var delta:Number = _view.speed * elapsedTime / 1000;
var velocity:Point = GeomPool.point(0, 0);
if (Input.key.isDown(Keyboard.LEFT)) { velocity.x -= delta; }
if (Input.key.isDown(Keyboard.RIGHT)) { velocity.x += delta; }
if (Input.key.isDown(Keyboard.UP)) { velocity.y -= delta; }
if (Input.key.isDown(Keyboard.DOWN)) { velocity.y += delta; }
if (velocity.x || velocity.y) {
velocity.normalize(delta);
_view.moveTo(
Math.min(Math.max(0, _view.x + velocity.x), Const.FIELD_SIZE),
Math.min(Math.max(0, _view.y + velocity.y), Const.FIELD_SIZE)
);
_playerBounds.x = _view.x - Player.BOUNDS_HALF_WIDTH;
_playerBounds.y = _view.y - Player.BOUNDS_HEIGHT;
}
}
public function removeEventListeners():void {
_room.removeEventListener(AttributeEvent.UPDATE, onKillEnemy);
}
public function get characterID():int { return int(_self.getAttribute(Friend.ATTR_CHARACTER)); }
public function get hp():int { return _hp; }
public function get maxHp():int { return _status.vit; }
public function get hpRate():Number { return _hp / _status.vit; }
public function get ammo():int { return _equip.currentWeaponAmmo; }
public function get maxAmmo():int { return _equip.currentWeapon.maxAmmo; }
public function get hpGaugeRate():Number {
return (_recoverCount > 0) ? 1 - (_recoverCount / _recoverTime) : _hp / _status.vit;
}
public function get ammoGaugeRate():Number { return _equip.ammoGaugeRate; }
}
//}
//package ore.orelib.logic {
import net.user1.reactor.Room;
/* import ore.orelib.actors.EnemyManager;
import ore.orelib.actors.Friend;
import ore.orelib.data.Const;
import ore.orelib.data.PlayerStatus;
*/
//public
class PlayerEquipment {
private var _currentWeapon:Weapon;
private var _currentWeaponAmmo:int;
private var _theOtherWeapon:Weapon;
private var _theOtherWeaponAmmo:int;
private var _attackCount:int;
private var _reloadCount:int;
private var _swapCount:int;
private var _reloadTime:int;
public function PlayerEquipment(primary:Weapon, secondary:Weapon) {
_currentWeapon = primary;
_currentWeaponAmmo = primary.maxAmmo;
_theOtherWeapon = secondary;
_theOtherWeaponAmmo = secondary.maxAmmo;
_attackCount = _reloadCount = _swapCount = 0;
_reloadTime = 1;
}
public function update(elapsedTime:int):void {
if (_attackCount > 0) {
_attackCount -= elapsedTime;
}
if (_reloadCount > 0) {
_reloadCount -= elapsedTime;
if (_reloadCount <= 0) { _currentWeaponAmmo = _currentWeapon.maxAmmo; }
}
if (_swapCount > 0) {
_swapCount -= elapsedTime;
}
}
public function attack(room:Room, x:int, y:int, status:PlayerStatus, enemies:EnemyManager):int {
// if(isAmmoEmpty()) reload()
// if(canAttack() && !isReloading() && !isSwapping())
var range:int = _currentWeapon.attack(room, x, y, status, enemies);
_currentWeaponAmmo--;
_attackCount = _currentWeapon.attackRate;
return range;
}
public function reload(status:PlayerStatus):void {
// if(!isAmmoFull() && !isReloading() && !isSwapping())
_attackCount = 0;
_reloadCount = _reloadTime = _currentWeapon.reloadRate * 100 / status.dex;
}
public function swap():void {
// if(!isSwapping())
var tempWeapon:Weapon = _currentWeapon;
var tempWeaponAmmo:int = _currentWeaponAmmo;
_currentWeapon = _theOtherWeapon;
_currentWeaponAmmo = _theOtherWeaponAmmo;
_theOtherWeapon = tempWeapon;
_theOtherWeaponAmmo = tempWeaponAmmo;
_attackCount = _reloadCount = 0;
_swapCount = Const.PLAYER_SWAP_TIME;
}
public function isAmmoEmpty():Boolean { return _currentWeaponAmmo <= 0; }
public function isAmmoFull():Boolean { return _currentWeaponAmmo == _currentWeapon.maxAmmo; }
public function canAttack():Boolean { return _attackCount <= 0; }
public function isReloading():Boolean { return _reloadCount > 0; }
public function isSwapping():Boolean { return _swapCount > 0; }
public function get currentWeapon():Weapon { return _currentWeapon; }
public function get currentWeaponAmmo():int { return _currentWeaponAmmo; }
public function get ammoGaugeRate():Number {
return (_reloadCount > 0) ? 1 - (_reloadCount / _reloadTime) : _currentWeaponAmmo / _currentWeapon.maxAmmo;
}
}
//}
//package ore.orelib.logic {
import flash.geom.Rectangle;
import net.user1.reactor.Room;
/* import ore.orelib.actors.Enemy;
import ore.orelib.actors.EnemyManager;
import ore.orelib.data.Const;
import ore.orelib.data.PlayerStatus;
import ore.orelib.data.WeaponSmith;
*/
//public
class Weapon {
private var _id:int;
private var _name:String;
private var _buffs:String;
private var _minDamage:int;
private var _randDamage:int;
private var _attackRate:int;
private var _reloadRate:int;
private var _ammo:int;
private var _criticalRate:int;
private var _knockback:int;
private var _bonus:PlayerStatus;
private var _range:int;
private var _penetration:int;
public function Weapon(
id:int, name:String, buffs:String,
minDamage:int, randDamage:int,
attackRate:int, reloadRate:int, ammo:int,
criticalRate:int, knockback:int, bonus:PlayerStatus,
range:int, penetration:int
) {
_id = id;
_name = name;
_buffs = buffs;
_minDamage = minDamage;
_randDamage = randDamage;
_attackRate = attackRate;
_reloadRate = reloadRate;
_ammo = ammo;
_criticalRate = criticalRate;
_knockback = knockback;
_bonus = bonus;
_range = range;
_penetration = penetration;
}
public function attack(room:Room, x:int, y:int, status:PlayerStatus, enemies:EnemyManager):int {
var attackType:int = WeaponSmith.acquireAttackTypeOf(_id);
var bounds:Rectangle;
var collidingEnemies:Vector.<Enemy>;
var i:int, enemy:Enemy, collidingEnemiesLength:int;
var range:int = 0;
switch(attackType) {
case Const.ATTACKTYPE_SHOOTING:
{
bounds = new Rectangle(x - 508, y - 16, 500, 1);
collidingEnemies = enemies.acquireCollidingEnemies(bounds);
collidingEnemiesLength = collidingEnemies.length;
range = 500;
for (i = 0; i < collidingEnemiesLength; i++) {
enemy = collidingEnemies[i];
// 敵との距離に応じてダメージを減衰させる
var distX:int = x - 8 - collidingEnemies[i].x;
var distMultiplier:Number = (distX < _range) ? 1
: (distX < _range * 2) ? 1 - 0.9 * (distX - _range) / _range
: 0.1;
collidingEnemies[i].damaged(room, calculateDamage(status, distMultiplier), _knockback);
// 貫通しなかったら終了
if (i >= _penetration) { range = distX; break; }
}
break;
}
case Const.ATTACKTYPE_EXPLOSIVE:
{
bounds = new Rectangle(x - 508, y - 16, 500, 1);
collidingEnemies = enemies.acquireCollidingEnemies(bounds);
range = 500;
if (collidingEnemies.length == 0) { break; }
// 一番先頭の敵の頭を爆心地にする
enemy = collidingEnemies[0];
var halfRange:Number = _range / 2;
bounds = new Rectangle(enemy.x + 16 - halfRange, y - 16 - halfRange, _range, _range);
collidingEnemies = enemies.acquireCollidingEnemies(bounds);
collidingEnemiesLength = collidingEnemies.length;
range = (x - 8) - (enemy.x + 16);
for (i = 0; i < collidingEnemiesLength; i++) {
collidingEnemies[i].damaged(room, calculateDamage(status), _knockback);
}
break;
}
case Const.ATTACKTYPE_MELEE:
{
bounds = new Rectangle(x - 8 - _range, y - 40, _range, 40);
collidingEnemies = enemies.acquireCollidingEnemies(bounds);
collidingEnemiesLength = collidingEnemies.length;
range = _range;
for (i = 0; i < collidingEnemiesLength; i++) {
collidingEnemies[i].damaged(room, calculateDamage(status), _knockback);
}
break;
}
default: { break; }
}
return range;
}
private function calculateDamage(status:PlayerStatus, distMultiplier:Number = 1):int {
var baseDamage:int = _minDamage + int(_randDamage * distMultiplier * Math.random());
var crits:Boolean = (int(100 * Math.random()) < _criticalRate * (status.luc / 100));
return baseDamage * (status.str / 100) * ((crits) ? 10 : 1);
}
public function get id():int { return _id; }
public function get name():String { return _name; }
public function get buffs():String { return _buffs; }
public function get minDamage():int { return _minDamage; }
public function get randDamage():int { return _randDamage; }
public function get maxDamage():int { return _minDamage + _randDamage; }
public function get attackRate():int { return _attackRate; }
public function get reloadRate():int { return _reloadRate; }
public function get maxAmmo():int { return _ammo; }
public function get criticalRate():int { return _criticalRate; }
public function get knockback():int { return _knockback; }
public function get strBonus():int { return _bonus.str; }
public function get vitBonus():int { return _bonus.vit; }
public function get dexBonus():int { return _bonus.dex; }
public function get lucBonus():int { return _bonus.luc; }
public function get range():int { return _range; }
public function get penetration():int { return _penetration; }
}
//}
//package ore.orelib.logic {
import net.user1.reactor.Attribute;
import net.user1.reactor.AttributeEvent;
import net.user1.reactor.Reactor;
import net.user1.reactor.Room;
import net.user1.reactor.RoomEvent;
import net.user1.reactor.RoomManagerEvent;
import net.user1.reactor.Status;
/* import ore.orelib.actors.Enemy;
import ore.orelib.data.Const;
*/
//public
class Host {
private var _room:Room;
private var _reactor:Reactor;
private var _startTime:Number;
private var _playTime:int;
private var _spawnTimeCount:int;
private var _spawnUniqueCount:int;
public static const ATTR_HOST:String = "h";
public static const ATTR_HOST_CANDIDACY:String = "i";
public static const ATTR_START_TIME:String = "t";
public static const ATTR_NUM_CONTRACTS:String = "c";
public function Host(room:Room, reactor:Reactor) {
_room = room;
_reactor = reactor;
_startTime = _playTime = 0;
_spawnTimeCount = _spawnUniqueCount = 0;
_reactor.getRoomManager().addEventListener(RoomManagerEvent.CREATE_ROOM_RESULT, initialize);
_room.addEventListener(RoomEvent.REMOVE_OCCUPANT, removeOccupantHandler);
_room.addEventListener(AttributeEvent.UPDATE, attributeUpdateHandler);
_room.addEventListener(AttributeEvent.DELETE, attributeDeleteHandler);
}
private function initialize(event:RoomManagerEvent):void {
if (event.getRoomID() != _room.getRoomID()) { return; }
_reactor.getRoomManager().removeEventListener(RoomManagerEvent.CREATE_ROOM_RESULT, initialize);
if(event.getStatus() != Status.SUCCESS) { return; }
_room.setAttribute(Host.ATTR_HOST, _reactor.self().getClientID());
_room.setAttribute(Host.ATTR_START_TIME, _reactor.getServer().getServerTime().toString());
_room.setAttribute(Host.ATTR_NUM_CONTRACTS, "0");
}
private function removeOccupantHandler(event:RoomEvent):void {
/**
* 1. 退室者が出た際、ホストがいないなら、ホストに立候補する
* 2. 立候補には退室者IDを送信する
* 3. attributeUpdateHandlerで、最初に立候補したのが自分なら自分がホストになる
*/
if (!_room.clientIsInRoom(_room.getAttribute(Host.ATTR_HOST))) {
_room.setAttribute(Host.ATTR_HOST_CANDIDACY, event.getClientID());
}
}
private function attributeUpdateHandler(event:AttributeEvent):void {
var attr:Attribute = event.getChangedAttr();
switch(attr.name) {
case Host.ATTR_START_TIME:
{
_startTime = Number(attr.value);
break;
}
// 最初に立候補したのが自分なら自分がホストになる
case Host.ATTR_HOST_CANDIDACY:
{
if (attr.byClient && attr.byClient.isSelf()) {
_room.setAttribute(Host.ATTR_HOST, _reactor.self().getClientID());
}
break;
}
default: { break; }
}
}
private function attributeDeleteHandler(event:AttributeEvent):void {
// 自分がホストでないなら終了
if (!isHost) { return; }
var attr:Attribute = event.getChangedAttr();
var idAndProp:Array = attr.name.split(".");
// HPがある状態で削除(契約成立)なら、契約数を増やす
if (idAndProp[1] == Enemy.ATTR_HP && int(attr.oldValue) > 0) {
_room.setAttribute(Host.ATTR_NUM_CONTRACTS, "%v+1", true, false, true);
}
}
public function update(serverTime:Number, elapsedTime:int):void {
if (_startTime > 0) { _playTime = serverTime - _startTime; }
// 自分がホストでないなら終了
if (!isHost) { return; }
// 敵の生成
_spawnTimeCount += elapsedTime;
var spawnTime:int = Math.max(50, 1500 - 150 * wave);
if (_spawnTimeCount > spawnTime) {
_spawnTimeCount -= spawnTime;
var enemyID:String = _reactor.self().getClientID() + ("000" + _spawnUniqueCount).substr(-3);
_spawnUniqueCount++;
Enemy.spawn(_room, enemyID, 100, 10, 40, serverTime);
}
}
public function removeEventListeners():void {
_room.removeEventListener(RoomEvent.REMOVE_OCCUPANT, removeOccupantHandler);
_room.removeEventListener(AttributeEvent.UPDATE, attributeUpdateHandler);
_room.removeEventListener(AttributeEvent.DELETE, attributeDeleteHandler);
}
public function get isHost():Boolean { return _room.getAttribute(Host.ATTR_HOST) == _reactor.self().getClientID(); }
public function get wave():int { return (_startTime > 0) ? int(_playTime / Const.FIELD_WAVE_TIME) + 1 : 1; }
public function get numContracts():int { return int(_room.getAttribute(Host.ATTR_NUM_CONTRACTS)); }
}
//}
//package ore.orelib.actors {
import flash.display.BitmapData;
//public
interface IActor {
function draw(target:BitmapData):void;
function get depth():Number;
}
//}
//package ore.orelib.actors {
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.filters.GlowFilter;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.text.TextField;
/* import ore.orelib.anim.ArmAnim;
import ore.orelib.anim.BodyAnim;
import ore.orelib.anim.WeaponAnim;
import ore.orelib.commons.Assets;
import ore.orelib.commons.EventManager;
import ore.orelib.commons.GeomPool;
import ore.orelib.commons.TextBuilder;
import ore.orelib.data.Const;
import ore.orelib.data.WeaponSmith;
import ore.orelib.events.EffectEvent;
*/
//public
class Friend implements IActor {
// 移動関連
private var _currentPosition:Point;
private var _destPosition:Point;
private var _speed:int;
private var _velocityPerMs:Point;
// 描画関連
private var _nameLabel:TextField;
private var _hp:int;
private var _maxHp:int;
private var _body:BodyAnim;
private var _arm:ArmAnim;
private var _weapon:WeaponAnim;
private var _worldTrans:Matrix;
private var _effectColorOffset:int;
public static const ATTR_NAME:String = "n";
public static const ATTR_X:String = "x";
public static const ATTR_Y:String = "y";
public static const ATTR_SPEED:String = "s";
public static const ATTR_HP:String = "h";
public static const ATTR_MAXHP:String = "m";
public static const ATTR_CHARACTER:String = "c";
public static const ATTR_WEAPON:String = "w";
public static const MESSAGE_ATTACK:String = "a";
public function Friend(
name:String, x:Number, y:Number, speed:int,
hp:int, maxHp:int, characterID:int, weaponID:int
) {
_currentPosition = new Point(x, y);
_destPosition = new Point(x, y);
_speed = speed;
_velocityPerMs = new Point(0, 0);
_nameLabel = new TextBuilder()
.align(TextBuilder.CENTER)
.filters([new GlowFilter(0x000000, 1, 2, 2, 8)])
.font(Const.FONT, -400, 400).fontColor(0xFFFFFF).fontSize(10)
.size(140, 20).build(name);
_hp = hp;
_maxHp = maxHp;
_body = new BodyAnim(characterID);
if (_hp <= 0) { _body.transition(BodyAnim.RECOVER); }
_arm = new ArmAnim();
_weapon = new WeaponAnim(weaponID);
_worldTrans = new Matrix();
_effectColorOffset = 0;
}
/** 目的位置を更新する */
public function moveTo(x:Number, y:Number):void {
_destPosition.x = x;
_destPosition.y = y;
var angle:Number = Math.atan2(_destPosition.y - _currentPosition.y, _destPosition.x - _currentPosition.x);
_velocityPerMs.x = _speed * Math.cos(angle) / 1000;
_velocityPerMs.y = _speed * Math.sin(angle) / 1000;
}
/** 攻撃モーションを行う */
public function attack(weaponID:int, range:int = 0):void {
var attackTypeID:int = WeaponSmith.acquireAttackTypeOf(weaponID);
_arm.transition((attackTypeID == Const.ATTACKTYPE_MELEE) ? ArmAnim.SWING : ArmAnim.RECOIL);
}
/** 武器変更モーションを行う */
public function swapWeapon(weaponID:int):void {
_arm.transition(ArmAnim.SWAP);
_weapon.transition(weaponID);
}
/** 残りHPに応じた更新を行う */
public function changeHp(value:int):void {
if (value <= 0) {
_body.transition(BodyAnim.RECOVER);
// 休憩エフェクトはここ
} else if (value < _hp) {
_effectColorOffset = 300;
EventManager.instance.dispatchEvent(new EffectEvent(
EffectEvent.DAMAGED_ACTOR,
_currentPosition.x,
_currentPosition.y,
{ num: _hp - value, isEnemy: false }
));
} else if (value > _hp) {
_body.transition(BodyAnim.IDLE);
// 復帰エフェクトはここ
}
_hp = value;
}
public function update(elapsedTime:int):void {
if (_hp > 0) {
if (!_currentPosition.equals(_destPosition)) {
var diff:Point = GeomPool.point(_destPosition.x - _currentPosition.x, _destPosition.y - _currentPosition.y);
var delta:Point = GeomPool.point(_velocityPerMs.x * elapsedTime, _velocityPerMs.y * elapsedTime);
if ((diff.x * diff.x + diff.y * diff.y) < (delta.x * delta.x + delta.y * delta.y)) {
_currentPosition.x = _destPosition.x;
_currentPosition.y = _destPosition.y;
}else {
_currentPosition.x += delta.x;
_currentPosition.y += delta.y;
}
_body.transition(BodyAnim.RUN);
}else {
_body.transition(BodyAnim.IDLE);
}
}
_worldTrans.tx = int(_currentPosition.x + Const.FIELD_OFFSET_X);
_worldTrans.ty = int(_currentPosition.y + Const.FIELD_OFFSET_Y);
_nameLabel.x = _worldTrans.tx - 70;
_nameLabel.y = _worldTrans.ty - 50;
_body.update(elapsedTime, _worldTrans);
_arm.update(elapsedTime, _body.worldTrans);
_weapon.update(elapsedTime, _arm.worldTrans);
_effectColorOffset = Math.max(0, _effectColorOffset - 60);
}
public function draw(target:BitmapData):void {
var effect:ColorTransform = GeomPool.colorTransform(1, 1, 1, 1, _effectColorOffset, _effectColorOffset, _effectColorOffset);
target.draw(Assets.images["actorShadow"], GeomPool.matrix(1, 0, 0, 1, _worldTrans.tx - 14, _worldTrans.ty - 4));
if (_hp > 0) {
_weapon.draw(target, effect);
_arm.draw(target, effect);
}
_body.draw(target, effect);
target.fillRect(GeomPool.rectangle(_worldTrans.tx - 16, _worldTrans.ty - 34, 32, 1), 0xFFCC0000);
target.fillRect(GeomPool.rectangle(_worldTrans.tx - 16, _worldTrans.ty - 34, 32 * _hp / _maxHp, 1), 0xFF00FF00);
}
public function get x():Number { return _currentPosition.x; }
public function get y():Number { return _currentPosition.y; }
public function get speed():int { return _speed; }
public function get overlay():DisplayObject { return _nameLabel; }
public function get depth():Number { return _currentPosition.y; }
}
//}
//package ore.orelib.actors {
import flash.utils.Dictionary;
import net.user1.reactor.Attribute;
import net.user1.reactor.IClient;
import net.user1.reactor.Room;
import net.user1.reactor.RoomEvent;
/* import ore.orelib.commons.EventManager;
import ore.orelib.events.ActorEvent;
import ore.orelib.events.EffectEvent;
*/
//public
class FriendManager {
private var _room:Room;
private var _friendList:Dictionary;
public function FriendManager(room:Room) {
_room = room;
_friendList = new Dictionary();
_room.addEventListener(RoomEvent.ADD_OCCUPANT, addOccupantHandler);
_room.addEventListener(RoomEvent.REMOVE_OCCUPANT, removeOccupantHandler);
_room.addEventListener(RoomEvent.UPDATE_CLIENT_ATTRIBUTE, updateClientAttrHandler);
_room.addMessageListener(Friend.MESSAGE_ATTACK, attackFriendHandler);
}
/** プレイヤーが入室した際の処理 */
private function addOccupantHandler(event:RoomEvent):void {
var client:IClient = event.getClient();
if (client.isSelf()) { return; }
var friend:Friend = new Friend(
client.getAttribute(Friend.ATTR_NAME),
Number(client.getAttribute(Friend.ATTR_X)),
Number(client.getAttribute(Friend.ATTR_Y)),
int(client.getAttribute(Friend.ATTR_SPEED)),
int(client.getAttribute(Friend.ATTR_HP)),
int(client.getAttribute(Friend.ATTR_MAXHP)),
int(client.getAttribute(Friend.ATTR_CHARACTER)),
int(client.getAttribute(Friend.ATTR_WEAPON))
);
_friendList[client.getClientID()] = friend;
EventManager.instance.dispatchEvent(new ActorEvent(ActorEvent.ADD, friend, friend.overlay));
}
/** プレイヤーが退室した際の処理 */
private function removeOccupantHandler(event:RoomEvent):void {
var friend:Friend = _friendList[event.getClientID()];
delete _friendList[event.getClientID()];
EventManager.instance.dispatchEvent(new ActorEvent(ActorEvent.REMOVE, friend, friend.overlay));
}
/** プレイヤーの属性が更新された際の処理 */
private function updateClientAttrHandler(event:RoomEvent):void {
var client:IClient = event.getClient();
if (client.isSelf()) { return; }
var friend:Friend = _friendList[client.getClientID()];
var attr:Attribute = event.getChangedAttr();
switch(attr.name) {
// 位置の更新
case Friend.ATTR_X:
case Friend.ATTR_Y:
{
friend.moveTo(
Number(client.getAttribute(Friend.ATTR_X)),
Number(client.getAttribute(Friend.ATTR_Y))
);
break;
}
// 残りHPの更新
case Friend.ATTR_HP:
{
friend.changeHp(int(attr.value));
break;
}
// 使用武器の変更
case Friend.ATTR_WEAPON:
{
friend.swapWeapon(int(attr.value));
break;
}
default: { break; }
}
}
/** プレイヤーが攻撃を行った際の処理 */
private function attackFriendHandler(from:IClient, weaponID:String, range:String):void {
var friend:Friend = _friendList[from.getClientID()];
friend.attack(int(weaponID), int(range));
EventManager.instance.dispatchEvent(new EffectEvent(
EffectEvent.ATTACK_WEAPON,
friend.x, friend.y,
{ id: int(weaponID), range: int(range) }
));
}
public function update(elapsedTime:int):void {
for each(var friend:Friend in _friendList) {
friend.update(elapsedTime);
}
}
public function removeEventListeners():void {
_room.removeEventListener(RoomEvent.ADD_OCCUPANT, addOccupantHandler);
_room.removeEventListener(RoomEvent.REMOVE_OCCUPANT, removeOccupantHandler);
_room.removeEventListener(RoomEvent.UPDATE_CLIENT_ATTRIBUTE, updateClientAttrHandler);
_room.removeMessageListener(Friend.MESSAGE_ATTACK, attackFriendHandler);
}
}
//}
//package ore.orelib.actors {
import flash.display.BitmapData;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import net.user1.reactor.Room;
/* import ore.orelib.anim.BodyAnim;
import ore.orelib.commons.Assets;
import ore.orelib.commons.EventManager;
import ore.orelib.commons.GeomPool;
import ore.orelib.data.Const;
import ore.orelib.events.EffectEvent;
*/
//public
class Enemy implements IActor {
private var _id:String;
private var _hp:int;
private var _maxHp:int;
private var _str:int;
// 移動関連
private var _currentPosition:Point;
private var _vx:int;
private var _spawnPosition:Point;
private var _spawnTime:Number;
private var _bounds:Rectangle;
// 描画関連
private var _body:BodyAnim;
private var _worldTrans:Matrix;
private var _effectColorOffset:int;
public static const BOUNDS_HALF_WIDTH:int = 14;
public static const BOUNDS_HEIGHT:int = 20;
public static const ATTR_STATUS:String = "s"; // maxHp,str,spawnY,vx,spawnTime
public static const ATTR_HP:String = "h";
public static const ATTR_SPAWN_X:String = "x";
public static function spawn(room:Room, id:String, hp:int, str:int, vx:int, time:Number):void {
room.setAttribute(id + "." + Enemy.ATTR_HP, hp.toString());
room.setAttribute(id + "." + Enemy.ATTR_SPAWN_X, Const.FIELD_LFET_BOUND.toString());
room.setAttribute(id + "." + Enemy.ATTR_STATUS,
hp.toString() + "," +
str.toString() + "," +
int(Const.FIELD_SIZE * Math.random()) + "," +
vx.toString() + "," +
time.toString()
);
}
public function Enemy(id:String, status:String, hp:String, spawnX:String) {
var statusArray:Array = status.split(",");
_id = id;
_hp = (hp) ? int(hp) : int.MAX_VALUE;
_maxHp = statusArray[0];
_str = statusArray[1];
_currentPosition = new Point(int(spawnX), statusArray[2]);
_vx = statusArray[3];
_spawnPosition = new Point(int(spawnX), statusArray[2]);
_spawnTime = statusArray[4];
_bounds = new Rectangle(
_currentPosition.x - Enemy.BOUNDS_HALF_WIDTH,
_currentPosition.y - Enemy.BOUNDS_HEIGHT,
Enemy.BOUNDS_HALF_WIDTH * 2,
Enemy.BOUNDS_HEIGHT
);
_body = new BodyAnim(Const.CHARACTER_QB);
_body.transition(BodyAnim.RUN);
_worldTrans = new Matrix();
_worldTrans.ty = int(_currentPosition.y + Const.FIELD_OFFSET_Y);
_effectColorOffset = 0;
}
/** HP変更,ノックバック: プレイヤーが直接ダメージを与える際に呼ぶ */
public function damaged(room:Room, amount:int, knockback:int):void {
_effectColorOffset = 300;
EventManager.instance.dispatchEvent(new EffectEvent(EffectEvent.DAMAGED_ACTOR,
_currentPosition.x,
_currentPosition.y,
{ num: amount, isEnemy: true }
));
room.setAttribute(_id + "." + Enemy.ATTR_HP, "%v-" + amount, true, false, true);
_hp -= amount;
if (knockback > 0) {
_spawnPosition.x -= knockback;
room.setAttribute(_id + "." + Enemy.ATTR_SPAWN_X, "%v-" + knockback, true, false, true);
}
}
/** HP変更: サーバーから更新メッセージを受け取った際に呼ぶ */
public function changeHp(value:int, oldValue:int, bySelf:Boolean):void {
if (_hp != int.MAX_VALUE && !bySelf) {
_effectColorOffset = 300;
EventManager.instance.dispatchEvent(new EffectEvent(EffectEvent.DAMAGED_ACTOR,
_currentPosition.x,
_currentPosition.y,
{ num: oldValue - value, isEnemy: true }
));
}
if (value < _hp) { _hp = value; }
}
/** ノックバック: サーバーからの更新メッセージを受け取った際に呼ぶ */
public function changeSpawnX(spawnX:int):void {
_spawnPosition.x = spawnX;
}
public function update(serverTime:Number, elapsedTime:int):void {
var lifeTime:Number = serverTime - _spawnTime;
_currentPosition.x = _spawnPosition.x + _vx * lifeTime / 1000;
_worldTrans.tx = int(_currentPosition.x + Const.FIELD_OFFSET_X);
_bounds.x = _currentPosition.x - Enemy.BOUNDS_HALF_WIDTH;
_bounds.y = _currentPosition.y - Enemy.BOUNDS_HEIGHT;
_body.update(elapsedTime, _worldTrans);
_effectColorOffset = Math.max(0, _effectColorOffset - 60);
}
public function draw(target:BitmapData):void {
var effect:ColorTransform = GeomPool.colorTransform(1, 1, 1, 1, _effectColorOffset, _effectColorOffset, _effectColorOffset);
target.draw(Assets.images["actorShadow"], GeomPool.matrix(1, 0, 0, 1, _worldTrans.tx - 14, _worldTrans.ty - 4));
_body.draw(target, effect);
var hpRate:Number = Math.min(Math.max(0, _hp), _maxHp) / _maxHp;
target.fillRect(GeomPool.rectangle(_worldTrans.tx - 16, _worldTrans.ty - 28, 32, 1), 0xFFCC0000);
target.fillRect(GeomPool.rectangle(_worldTrans.tx - 16, _worldTrans.ty - 28, 32 * hpRate, 1), 0xFF00FF00);
}
public function get id():String { return _id; }
public function get isAlive():Boolean { return _hp > 0; }
public function get str():int { return _str; }
public function get x():Number { return _currentPosition.x; }
public function get y():Number { return _currentPosition.y; }
public function get bounds():Rectangle { return _bounds; }
public function get depth():Number { return _currentPosition.y; }
}
//}
//package ore.orelib.actors {
import flash.geom.Rectangle;
import flash.utils.Dictionary;
import net.user1.reactor.Attribute;
import net.user1.reactor.AttributeEvent;
import net.user1.reactor.Room;
/* import ore.orelib.commons.EventManager;
import ore.orelib.data.Const;
import ore.orelib.events.ActorEvent;
*/
//public
class EnemyManager {
private var _room:Room;
private var _enemyList:Dictionary;
public function EnemyManager(room:Room) {
_room = room;
_enemyList = new Dictionary();
_room.addEventListener(AttributeEvent.UPDATE, attributeUpdateHandler);
_room.addEventListener(AttributeEvent.DELETE, attributeDeleteHandler);
}
private function attributeUpdateHandler(event:AttributeEvent):void {
var attr:Attribute = event.getChangedAttr();
var idAndName:Array = attr.name.split(".");
var enemy:Enemy;
switch(idAndName[1]) {
// 敵の出現
case Enemy.ATTR_STATUS:
{
enemy = new Enemy(
idAndName[0],
attr.value,
_room.getAttribute(idAndName[0] + "." + Enemy.ATTR_HP),
_room.getAttribute(idAndName[0] + "." + Enemy.ATTR_SPAWN_X)
);
_enemyList[idAndName[0]] = enemy;
EventManager.instance.dispatchEvent(new ActorEvent(ActorEvent.ADD, enemy));
break;
}
// HPの変化(HP0でサーバーから削除は、撃破したクライアントのPlayerクラスで行う)
case Enemy.ATTR_HP:
{
enemy = _enemyList[idAndName[0]];
var bySelf:Boolean = (attr.byClient && attr.byClient.isSelf());
if (enemy) { enemy.changeHp(int(attr.value), int(attr.oldValue), bySelf); }
break;
}
// ノックバック
case Enemy.ATTR_SPAWN_X:
{
enemy = _enemyList[idAndName[0]];
if (enemy) { enemy.changeSpawnX(int(attr.value)); }
break;
}
default: { break; }
}
}
private function attributeDeleteHandler(event:AttributeEvent):void {
var idAndName:Array = event.getChangedAttr().name.split(".");
if (idAndName[1] != Enemy.ATTR_STATUS) { return; }
var enemy:Enemy = _enemyList[idAndName[0]];
if (enemy) { deleteEnemy(enemy); }
}
private function deleteEnemy(enemy:Enemy):void {
delete _enemyList[enemy.id];
EventManager.instance.dispatchEvent(new ActorEvent(ActorEvent.REMOVE, enemy));
}
public function update(serverTime:Number, elapsedTime:int, isHost:Boolean):void {
for each(var enemy:Enemy in _enemyList) {
// 撃破されていたら削除して次へ
if (!enemy.isAlive) {
deleteEnemy(enemy);
// 死亡エフェクトはここ
continue;
}
enemy.update(serverTime, elapsedTime);
// 自分がホストで、敵が画面右端に到達していたらサーバーから削除
if (isHost && enemy.x > Const.FIELD_RIGHT_BOUND) {
deleteEnemy(enemy);
_room.deleteAttribute(enemy.id + "." + Enemy.ATTR_STATUS);
_room.deleteAttribute(enemy.id + "." + Enemy.ATTR_HP);
_room.deleteAttribute(enemy.id + "." + Enemy.ATTR_SPAWN_X);
}
}
}
/** 引数で与えた境界と衝突している敵のリストを取得する */
public function acquireCollidingEnemies(bounds:Rectangle):Vector.<Enemy> {
var result:Vector.<Enemy> = new Vector.<Enemy>();
for each(var enemy:Enemy in _enemyList) {
var enemyBounds:Rectangle = enemy.bounds;
if (
bounds.top < enemyBounds.bottom &&
bounds.bottom > enemyBounds.top &&
bounds.left < enemyBounds.right &&
bounds.right > enemyBounds.left
) {
result.push(enemy);
}
}
result.sort(compareXOfEnemy);
return result;
}
private function compareXOfEnemy(a:Enemy, b:Enemy):Number {
return (a.x < b.x) ? 1 : -1; // xが大きい順に並べる
}
public function removeEventListeners():void {
_room.removeEventListener(AttributeEvent.UPDATE, attributeUpdateHandler);
_room.removeEventListener(AttributeEvent.DELETE, attributeDeleteHandler);
}
}
//}
//package ore.orelib.actors {
import flash.display.DisplayObject;
import flash.filters.GlowFilter;
import flash.text.TextField;
/* import ore.orelib.commons.TextBuilder;
import ore.orelib.data.Const;
*/
//public
class PopUp {
private var _text:TextField;
private var _frameCount:int;
public function PopUp() {
_text =
new TextBuilder().align(TextBuilder.CENTER)
.filters([new GlowFilter(0x440000, 1, 2, 2, 8)])
.font(Const.FONT, -400, 400).fontSize(12)
.size(50, 20).build("0");
_frameCount = 0;
}
public function initialize(x:Number, y:Number, num:int, isEnemy:Boolean):void {
_text.x = x - 25 + Const.FIELD_OFFSET_X;
_text.y = y - 20 + Const.FIELD_OFFSET_Y;
_text.text = num.toString();
_text.textColor = (isEnemy) ? 0xFFCC44 : 0xFF8888;
_text.alpha = 1;
_frameCount = 0;
}
public function update():void {
_frameCount++;
_text.y -= 3;
_text.alpha -= 0.05;
}
public function get overlay():DisplayObject { return _text; }
public function get exists():Boolean { return _frameCount <= 10; }
}
//}
//package ore.orelib.actors {
import flash.display.BitmapData;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.geom.Matrix;
/* import ore.orelib.assets.PlayingView;
import ore.orelib.commons.Assets;
import ore.orelib.commons.EventManager;
import ore.orelib.commons.GeomPool;
import ore.orelib.data.Const;
import ore.orelib.data.WeaponSmith;
import ore.orelib.events.EffectEvent;
*/
//public
class EffectManager {
private var _view:PlayingView
private var _shape:Shape;
private var _popUpList:Vector.<PopUp>;
private var _popUpPool:Vector.<PopUp>;
public function EffectManager(view:PlayingView) {
_view = view;
_shape = new Shape();
_popUpList = new Vector.<PopUp>();
_popUpPool = new Vector.<PopUp>();
EventManager.instance.addEventListener(EffectEvent.ATTACK_WEAPON, attackWeaponHandler);
EventManager.instance.addEventListener(EffectEvent.DAMAGED_ACTOR, damagedActorHandler);
}
private function attackWeaponHandler(event:EffectEvent):void {
var attackType:int = WeaponSmith.acquireAttackTypeOf(event.option.id);
var g:Graphics = _shape.graphics; g.clear();
switch(attackType) {
case Const.ATTACKTYPE_SHOOTING:
{
var color:uint;
switch(event.option.id) {
case Const.WEAPON_ROSEBOW: { color = 0xFF00FF; break; }
case Const.WEAPON_BLACKBOW: { color = 0xFF00FF; break; }
case Const.WEAPON_PISTOL: { addMuzzleFlash(event.x, event.y, 20); /*fallthrough*/ }
case Const.WEAPON_MASKET: { addMuzzleFlash(event.x, event.y, 36); /*fallthrough*/ }
case Const.WEAPON_MINIMI: { addMuzzleFlash(event.x, event.y, 38); /*fallthrough*/ }
default: { color = 0xFFFF00 + uint(0x88 * Math.random()); break; }
}
var matrix:Matrix = GeomPool.matrix();
matrix.createGradientBox(event.option.range, 1);
g.beginGradientFill(GradientType.LINEAR, [color, color], [1, 0], [0, 255], matrix);
g.drawRect(0, 0, event.option.range, 1);
g.endFill();
_view.effect.draw(_shape, GeomPool.matrix(1, 0, 0, 1,
int(event.x - 8 - event.option.range + Const.FIELD_OFFSET_X),
int(event.y - 20 + int(9 * Math.random()) + Const.FIELD_OFFSET_Y)
));
break;
}
case Const.ATTACKTYPE_EXPLOSIVE:
{
}
case Const.ATTACKTYPE_MELEE:
{
g.beginFill(0xFFFFFF);
g.moveTo(event.x, event.y - 40);
g.curveTo(
event.x - 8 - event.option.range,
event.y - 40,
event.x - 8 - event.option.range,
event.y + 10
);
g.lineTo(event.x - event.option.range + 9, event.y);
g.curveTo(
event.x - 8 - event.option.range,
event.y - 40,
event.x,
event.y - 40
);
g.endFill();
_view.effect.draw(_shape, GeomPool.matrix(1, 0, 0, 1, Const.FIELD_OFFSET_X, Const.FIELD_OFFSET_Y));
break;
}
default: { break; }
}
}
private function addMuzzleFlash(x:int, y:int, offsetX:int):void {
var muzzleFlashes:Vector.<BitmapData> = Assets.images["muzzleFlashes"];
_view.effect.draw(muzzleFlashes[int(muzzleFlashes.length * Math.random())],
GeomPool.matrix(1, 0, 0, 1,
int(x - offsetX - 32 + Const.FIELD_OFFSET_X),
int(y - 35 + int(7 * Math.random()) + Const.FIELD_OFFSET_Y)
)
);
}
private function damagedActorHandler(event:EffectEvent):void {
var popUp:PopUp = (_popUpPool.length) ? _popUpPool.pop() : new PopUp();
popUp.initialize(event.x, event.y, event.option.num, event.option.isEnemy);
_popUpList.push(popUp);
_view.overlay.addChild(popUp.overlay);
if (event.option.isEnemy) {
/*
var bloods:Vector.<BitmapData> = Assets.images["bloods"];
_view.effect.draw(bloods[int(bloods.length * Math.random())],
GeomPool.matrix(1, 0, 0, 1,
int(event.x - 16 + Const.FIELD_OFFSET_X),
int(event.y - 28 + Const.FIELD_OFFSET_Y)
)
);*/
}
}
public function update():void {
for (var i:int = _popUpList.length - 1; i >= 0; i--) {
var popUp:PopUp = _popUpList[i];
popUp.update();
if (!popUp.exists) {
_view.overlay.removeChild(popUp.overlay);
_popUpList.splice(_popUpList.indexOf(popUp), 1);
_popUpPool.push(popUp);
}
}
}
public function removeEventListeners():void {
EventManager.instance.removeEventListener(EffectEvent.ATTACK_WEAPON, attackWeaponHandler);
EventManager.instance.removeEventListener(EffectEvent.DAMAGED_ACTOR, damagedActorHandler);
}
}
//}
//package ore.orelib.anim {
import flash.display.BitmapData;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
//public
interface IAnim {
function transition(state:int):void;
function update(elapsedTime:int, parentWorldTrans:Matrix):void;
function draw(target:BitmapData, effect:ColorTransform = null, blendMode:String = null):void;
function get worldTrans():Matrix;
}
//}
//package ore.orelib.anim {
import flash.display.BitmapData;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
//public
class AbstractAnim implements IAnim {
protected var _image:BitmapData;
protected var _state:int;
protected var _frameCount:int;
protected var _timeCount:int;
protected var _worldTrans:Matrix;
public function AbstractAnim() {
_image = null;
_state = 0;
_frameCount = _timeCount = 0;
_worldTrans = new Matrix();
}
public function transition(state:int):void {
if (_state != state) {
_state = state;
_frameCount = _timeCount = 0;
}
}
public function update(elapsedTime:int, parentWorldTrans:Matrix):void {
_frameCount++;
_timeCount += elapsedTime;
_worldTrans.identity();
_worldTrans.concat(parentWorldTrans);
}
public function draw(target:BitmapData, effect:ColorTransform = null, blendMode:String = null):void {
var smoothing:Boolean = (_worldTrans.b != 0 || _worldTrans.c != 0);
target.draw(_image, _worldTrans, effect, blendMode, null, smoothing);
}
public final function get worldTrans():Matrix { return _worldTrans; }
}
//}
//package ore.orelib.anim {
import flash.geom.Matrix;
/* import ore.orelib.commons.Assets;
*/
//public
class BodyAnim extends AbstractAnim implements IAnim {
private var _imageIndex:int;
private var _imageOffset:int;
public static const IDLE:int = 0;
public static const RUN:int = 1;
public static const RECOVER:int = 2;
public function BodyAnim(characterID:int) {
_imageIndex = characterID;
_imageOffset = 0;
}
public override function update(elapsedTime:int, parentWorldTrans:Matrix):void {
_frameCount++;
_worldTrans.identity();
_worldTrans.translate( -8, -16);
_worldTrans.scale(2, 2);
_worldTrans.concat(parentWorldTrans);
switch(_state) {
case BodyAnim.RUN:
{
_imageOffset = (_frameCount % 10 < 5) ? 1 : 0;
break;
}
case BodyAnim.RECOVER:
{
_imageOffset = 2;
break;
}
default:
{
_imageOffset = 0;
break;
}
}
_image = Assets.images["characters"][_imageIndex + _imageOffset];
}
}
//}
//package ore.orelib.anim {
import flash.display.BitmapData;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
/* import ore.orelib.commons.Assets;
import ore.orelib.data.Const;
*/
//public
class ArmAnim extends AbstractAnim implements IAnim {
private var _angle:Number;
public static const HOLD:int = 0;
public static const SWING:int = 1;
public static const RECOIL:int = 2;
public static const SWAP:int = 3;
public function ArmAnim() {
_image = Assets.images["characters"][17];
}
public override function update(elapsedTime:int, parentWorldTrans:Matrix):void {
_frameCount++;
_timeCount += elapsedTime;
switch(_state) {
case ArmAnim.SWING:
{
_angle = (_frameCount > 2) ? -75 : 75;
if (_frameCount > 4) { transition(ArmAnim.HOLD); }
break;
}
case ArmAnim.RECOIL:
{
_angle = 3;
if (_frameCount > 1) { transition(ArmAnim.HOLD); }
break;
}
case ArmAnim.SWAP:
{
_angle = 45;
if (_timeCount > Const.PLAYER_SWAP_TIME) { transition(ArmAnim.HOLD); }
break;
}
default:
{
_angle = 0;
break;
}
}
_worldTrans.identity();
_worldTrans.translate( -8, -8);
if (_angle != 0) { _worldTrans.rotate(_angle * Const.DEGREES_TO_RADIANS); }
_worldTrans.translate(6, 10);
_worldTrans.concat(parentWorldTrans);
}
}
//}
//package ore.orelib.anim {
import flash.geom.Matrix;
/* import ore.orelib.commons.Assets;
import ore.orelib.data.Const;
*/
//public
class WeaponAnim extends AbstractAnim implements IAnim {
public function WeaponAnim(weaponID:int) {
_state = weaponID;
_image = Assets.images["weapons"][_state];
}
public override function update(elapsedTime:int, parentWorldTrans:Matrix):void {
_timeCount += elapsedTime;
_worldTrans.identity();
//_worldTrans.translate( -16, -16);
_worldTrans.translate( -11, -8);
//_worldTrans.translate(5, 8);
_worldTrans.concat(parentWorldTrans);
if (_timeCount > 200) {
_image = Assets.images["weapons"][_state];
}
}
}
//}
//package ore.orelib.events {
import flash.display.DisplayObject;
import flash.events.Event;
/* import ore.orelib.actors.IActor;
*/
//public
class ActorEvent extends Event {
private var _actor:IActor;
private var _overlay:DisplayObject;
public static const ADD:String = "actor_add";
public static const REMOVE:String = "actor_remove";
public function ActorEvent(type:String, actor:IActor, overlay:DisplayObject = null) {
super(type);
_actor = actor;
_overlay = overlay;
}
public override function clone():Event { return new ActorEvent(type, _actor, _overlay); }
public override function toString():String { return formatToString("ActorEvent", "type", "actor", "overlay"); }
public function get actor():IActor { return _actor; }
public function get overlay():DisplayObject { return _overlay; }
}
//}
//package ore.orelib.events {
import flash.events.Event;
//public
class EffectEvent extends Event {
private var _x:int;
private var _y:int;
private var _option:Object;
public static const ATTACK_WEAPON:String = "effect_attack_weapon";
public static const DAMAGED_ACTOR:String = "effect_damaged_enemy";
public function EffectEvent(type:String, x:int, y:int, option:Object = null) {
super(type);
_x = x;
_y = y;
_option = option;
}
public override function clone():Event { return new EffectEvent(type, _x, _y, _option); }
public override function toString():String { return formatToString("EffectEvent", "type", "x", "y"); }
public function get x():int { return _x; }
public function get y():int { return _y; }
public function get option():Object { return _option; }
}
//}
//package ore.orelib.assets {
import com.bit101.components.PushButton;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.filters.GlowFilter;
import net.user1.reactor.Reactor;
/* import ore.orelib.actors.IActor;
import ore.orelib.commons.EventManager;
import ore.orelib.commons.GeomPool;
import ore.orelib.commons.MiniChat;
import ore.orelib.commons.TextBuilder;
import ore.orelib.data.Const;
import ore.orelib.data.SaveData;
import ore.orelib.events.ActorEvent;
import ore.orelib.logic.Host;
import ore.orelib.logic.Player;
*/
//public
class PlayingView extends Sprite {
private var _actorList:Vector.<IActor>;
private var _ground:BitmapData;
private var _screen:BitmapData;
private var _effect:BitmapData;
private var _overlay:Sprite;
private var _hud:HUD;
public function PlayingView() {
_actorList = new Vector.<IActor>();
addChild(new Bitmap(_ground = Artist.createBackground()));
addChild(new Bitmap(_screen = new BitmapData(465, 465, true, 0x00FFFFFF)));
addChild(new Bitmap(_effect = new BitmapData(465, 465, true, 0x00FFFFFF)));
addChild(_overlay = new Sprite());
EventManager.instance.addEventListener(ActorEvent.ADD, addActorHandler);
EventManager.instance.addEventListener(ActorEvent.REMOVE, removeActorHandler);
}
public function setupHUD(player:Player):void {
addChild(_hud = new HUD(player));
}
public function createChatWindow(roomID:String, reactor:Reactor):MiniChat {
var result:MiniChat = new MiniChat(
roomID,
{
logSize: 7,
defaultUserName: SaveData.instance.player.name,
draggable: false,
minimizable: false,
renamable: false,
reactor: reactor
}
);
result.x = 465 - result.width;
result.y = -20;
return result;
}
public function setupGameoverDisplay(leaveButton:PushButton, isReactorReady:Boolean):void {
var disp:Sprite = new Sprite();
disp.graphics.beginFill(0x000000, 0.8);
disp.graphics.drawRect(0, 0, 465, 465);
disp.graphics.endFill();
addChild(disp);
var gameoverReason:String = (isReactorReady)
? "QBがノルマを達成しちゃいました!\nこの世界は破滅です。"
: "接続がタイムアウトしました。";
disp.addChild(
new TextBuilder().align(TextBuilder.CENTER)
.filters([new GlowFilter(0x000000, 1, 2, 2, 8)])
.font(Const.FONT, -400, 400).fontColor(0xFFFFFF).fontSize(24)
.pos(0, 150).size(465, 100).build(gameoverReason)
);
disp.addChild(leaveButton);
}
private function addActorHandler(event:ActorEvent):void {
_actorList.push(event.actor);
if (event.overlay) { _overlay.addChild(event.overlay); }
}
private function removeActorHandler(event:ActorEvent):void {
if (event.overlay) { _overlay.removeChild(event.overlay); }
_actorList.splice(_actorList.indexOf(event.actor), 1);
}
public function update(player:Player, host:Host):void {
_actorList.sort(compareDepthOfActor);
_screen.lock();
_screen.fillRect(GeomPool.rectangle(0, 0, 465, 465), 0x00FFFFFF);
for each(var actor:IActor in _actorList) {
actor.draw(_screen);
}
_screen.unlock();
_effect.colorTransform(GeomPool.rectangle(0, 0, 465, 465), GeomPool.colorTransform(1, 1, 1, 0.8));
_hud.update(player, host);
}
private function compareDepthOfActor(a:IActor, b:IActor):Number {
return (a.depth > b.depth) ? 1 : -1; // depthが小さい順に並べる
}
public function removeEventListeners():void {
EventManager.instance.removeEventListener(ActorEvent.ADD, addActorHandler);
EventManager.instance.removeEventListener(ActorEvent.REMOVE, removeActorHandler);
}
public function get ground():BitmapData { return _ground; }
public function get effect():BitmapData { return _effect; }
public function get overlay():Sprite { return _overlay; }
}
//}
//package ore.orelib.assets {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.text.TextField;
/* import ore.orelib.commons.Assets;
import ore.orelib.commons.TextBuilder;
import ore.orelib.data.Const;
import ore.orelib.data.SaveData;
import ore.orelib.logic.Host;
import ore.orelib.logic.Player;
*/
//public
class HUD extends Sprite {
private var _characterFace:Bitmap;
private var _borders:Shape;
private var _nameLabel:TextField;
private var _hpSlashLabel:TextField;
private var _ammoSlashLabel:TextField;
private var _hpLabel:TextField;
private var _maxHpLabel:TextField;
private var _ammoLabel:TextField;
private var _maxAmmoLabel:TextField;
private var _waveLabel:TextField;
private var _quotaLabel:TextField;
private var _gaugeGradientBox:Matrix;
public function HUD(player:Player) {
var bmd:BitmapData = new BitmapData(48, 48, true, 0xFF404040);
bmd.draw(Assets.images["characters"][player.characterID + 1], new Matrix(4, 0, 0, 4, -4, 4));
_characterFace = new Bitmap(bmd);
_characterFace.x = 13;
_characterFace.y = 6;
addChild(_characterFace);
addChild(_borders = new Shape());
var builder:TextBuilder = new TextBuilder()
.filters([new GlowFilter(0x000000, 1, 2, 2, 8)])
.font(Const.FONT, -400, 400).fontColor(0xFFFFFF).fontSize(12);
addChild(_nameLabel = builder.autoSize().pos(70, 5).size(150, 25).build(SaveData.instance.player.name));
builder.autoSize(false);
builder.align(TextBuilder.CENTER);
addChild(_hpSlashLabel = builder.pos(178, 24).size(10, 16).build("/"));
addChild(_ammoSlashLabel = builder.pos(178, 39).size(10, 16).build("/"));
builder.align(TextBuilder.RIGHT);
addChild(_hpLabel = builder.pos(153, 24).size(25, 16).build(player.hp.toString()));
addChild(_ammoLabel = builder.pos(153, 39).size(25, 16).build(player.ammo.toString()));
builder.align(TextBuilder.LEFT);
addChild(_maxHpLabel = builder.pos(188, 24).size(25, 16).build(player.maxHp.toString()));
addChild(_maxAmmoLabel = builder.pos(188, 39).size(25, 16).build(player.maxAmmo.toString()));
builder.autoSize();
addChild(builder.pos(24, 60).size(74, 30).build("Wave:"));
addChild(builder.pos(110, 60).size(98, 30).build("契約ノルマ:"));
builder.align(TextBuilder.RIGHT).fontSize(18);
addChild(_waveLabel = builder.pos(24, 60).size(74, 30).build("1"));
addChild(_quotaLabel = builder.pos(110, 60).size(98, 30).build(Const.FIELD_QB_QUOTA.toString()));
_gaugeGradientBox = new Matrix();
_gaugeGradientBox.createGradientBox(150, 8);
drawGauge(1, 1);
drawBorders(0xFFFFFF);
}
private function drawGauge(hpRate:Number, ammoRate:Number):void {
var g:Graphics = graphics;
g.clear();
g.beginFill(0xC00000);
g.drawRoundRect(69, 31, 150, 8, 8, 8);
g.endFill();
g.beginGradientFill(GradientType.LINEAR, [0x004000, 0x00FF00], [1, 1], [0, 255], _gaugeGradientBox);
g.drawRoundRect(69, 31, 150 * hpRate, 8, 8, 8);
g.endFill();
g.beginFill(0x000000);
g.drawRoundRect(69, 46, 150, 8, 8, 8);
g.endFill();
g.beginGradientFill(GradientType.LINEAR, [0x800000, 0xFFC000], [1, 1], [0, 255], _gaugeGradientBox);
g.drawRoundRect(69, 46, 150 * ammoRate, 8, 8, 8);
g.endFill();
}
private function drawBorders(color:uint):void {
var g:Graphics = _borders.graphics;
g.clear();
g.lineStyle(2, color);
g.drawRoundRect(13, 6, 48, 48, 8, 8);
g.drawRoundRect(69, 31, 150, 8, 8, 8);
g.drawRoundRect(69, 46, 150, 8, 8, 8);
}
public function update(player:Player, host:Host):void {
var borderColor:uint = (player.hpRate <= 0) ? 0xFF0000 : (player.hpRate < 0.3) ? 0xFFFF00 : 0xFFFFFF;
_hpLabel.text = player.hp.toString();
_ammoLabel.text = player.ammo.toString();
_maxAmmoLabel.text = player.maxAmmo.toString();
_waveLabel.text = host.wave.toString();
_quotaLabel.text = Math.max(0, (Const.FIELD_QB_QUOTA - host.numContracts)).toString();
drawGauge(player.hpGaugeRate, player.ammoGaugeRate);
drawBorders(borderColor);
_nameLabel.textColor = borderColor;
_hpSlashLabel.textColor = borderColor;
_ammoSlashLabel.textColor = borderColor;
_hpLabel.textColor = borderColor;
_ammoLabel.textColor = borderColor;
_maxHpLabel.textColor = borderColor;
_maxAmmoLabel.textColor = borderColor;
}
}
//}
//package ore.orelib.assets {
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.filters.BlurFilter;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
//public
class Artist {
public static function createBackground():BitmapData {
var result:BitmapData = new BitmapData(465, 465, true, 0x00FFFFFF);
drawSky(result);
drawBuildings(result);
drawFog(result);
drawGround(result);
return result;
}
private static function drawSky(target:BitmapData):void {
var sp:Sprite = new Sprite();
var matrix:Matrix = new Matrix();
matrix.createGradientBox(865, 400, Math.PI / 2, -200, -200);
sp.graphics.beginGradientFill(GradientType.RADIAL, [0x000000, 0x707050, 0xFFFFFF], [1, 1, 1], [0, 128, 255], matrix);
sp.graphics.drawRect(0, 0, 465, 155);
sp.graphics.endFill();
var noise:BitmapData = new BitmapData(465, 155, true, 0x00FFFFFF);
noise.perlinNoise(155, 31, 8, 0, false, false);
sp.filters = [new DisplacementMapFilter(noise, new Point(), BitmapDataChannel.RED, BitmapDataChannel.GREEN, 31, 93, DisplacementMapFilterMode.CLAMP)];
target.draw(sp);
}
private static function drawBuildings(target:BitmapData):void {
var near:BitmapData = new BitmapData(465, 155, true, 0x00FFFFFF);
var far:BitmapData = near.clone();
near.fillRect(new Rectangle(0, 55, 10, 100), 0xFF000000);
near.fillRect(new Rectangle(100, 75, 50, 80), 0xFF000000);
near.fillRect(new Rectangle(300, 55, 50, 100), 0xFF000000);
near.fillRect(new Rectangle(450, 75, 15, 80), 0xFF000000);
far.fillRect(new Rectangle(0, 140, 465, 15), 0xFF000000);
far.fillRect(new Rectangle(0, 115, 50, 40), 0xFF000000);
far.fillRect(new Rectangle(160, 115, 30, 40), 0xFF000000);
far.fillRect(new Rectangle(250, 125, 30, 30), 0xFF000000);
far.fillRect(new Rectangle(400, 105, 30, 50), 0xFF000000);
var noise:BitmapData = new BitmapData(465, 155, true, 0x00FFFFFF);
noise.perlinNoise(20, 50, 8, 0, false, false);
near.applyFilter(near, near.rect, new Point(), new DisplacementMapFilter(noise, new Point(), 0, BitmapDataChannel.GREEN, 0, 20, DisplacementMapFilterMode.CLAMP));
near.applyFilter(near, near.rect, new Point(), new BlurFilter(4, 4));
far.applyFilter(far, far.rect, new Point(), new DisplacementMapFilter(noise, new Point(), 0, BitmapDataChannel.GREEN, 0, 20, DisplacementMapFilterMode.CLAMP));
far.applyFilter(far, far.rect, new Point(), new BlurFilter(8, 8));
target.draw(far);
target.draw(near);
}
private static function drawFog(target:BitmapData):void {
var sp:Sprite = new Sprite();
var matrix:Matrix = new Matrix();
matrix.createGradientBox(465, 155, Math.PI / 2, 0, 0);
sp.graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0xFFFFFF], [0, 1], [128, 255], matrix);
sp.graphics.drawRect(0, 0, 465, 155);
sp.graphics.endFill();
var noise:BitmapData = new BitmapData(465, 155, true, 0x00FFFFFF);
noise.perlinNoise(155, 31, 8, 0, false, false);
sp.filters = [new DisplacementMapFilter(noise, new Point(), 0, BitmapDataChannel.GREEN, 0, 31, DisplacementMapFilterMode.CLAMP)];
target.draw(sp);
}
private static function drawGround(target:BitmapData):void {
var sp:Sprite = new Sprite();
var matrix:Matrix = new Matrix();
matrix.createGradientBox(1465, 620, Math.PI / 2, -500, -310);
sp.graphics.beginGradientFill(GradientType.RADIAL, [0xF0F0F0, 0x303030], [1, 1], [0, 255], matrix);
sp.graphics.drawRect(0, 0, 465, 310);
sp.graphics.endFill();
target.draw(sp, new Matrix(1, 0, 0, 1, 0, 155));
}
public static function createActorShadow():BitmapData {
var result:BitmapData = new BitmapData(28, 8, true, 0x00FFFFFF);
var sp:Sprite = new Sprite();
sp.graphics.beginFill(0x000000, 0.5);
sp.graphics.drawEllipse(2, 2, 24, 4);
sp.graphics.endFill();
sp.filters = [new BlurFilter(4, 4)];
result.draw(sp);
return result;
}
public static function createMuzzleFlashes(num:int):Vector.<BitmapData> {
var result:Vector.<BitmapData> = new Vector.<BitmapData>(num, true);
for (var i:int = 0; i < result.length; i++) {
result[i] = createMuzzleFlash(i);
}
return result;
}
private static function createMuzzleFlash(seed:int):BitmapData {
var result:BitmapData = new BitmapData(32, 32, true, 0x00FFFFFF);
var noise:BitmapData = result.clone();
noise.perlinNoise(4, 4, 4, seed, false, true, BitmapDataChannel.RED | BitmapDataChannel.GREEN);
var sp:Sprite = new Sprite();
var g:Graphics = sp.graphics;
g.beginFill(0xFFFFFF);
g.drawEllipse(22, 4, 8, 24);
g.endFill();
g.beginFill(0xFFFFFF);
g.moveTo(2, 16); g.lineTo(26, 10); g.lineTo(26, 22); g.lineTo(2, 16);
g.endFill();
g.beginFill(0xFFFFFF);
g.moveTo(12, 4); g.lineTo(26, 8); g.lineTo(26, 16); g.lineTo(12, 4);
g.moveTo(12, 28); g.lineTo(26, 24); g.lineTo(26, 16); g.lineTo(12, 28);
g.endFill();
result.draw(sp);
result.applyFilter(result, result.rect, new Point(), new DisplacementMapFilter(
noise, new Point(), BitmapDataChannel.RED, BitmapDataChannel.GREEN,
4, 16, DisplacementMapFilterMode.CLAMP
));
result.applyFilter(result, result.rect, new Point(), new GlowFilter(0xFFCC00, 1, 4, 4));
return result;
}
public static function createBloods(num:int):Vector.<BitmapData> {
var result:Vector.<BitmapData> = new Vector.<BitmapData>(num, true);
for (var i:int = 0; i < result.length; i++) {
result[i] = createBlood(i);
}
return result;
}
private static function createBlood(seed:int):BitmapData {
var result:BitmapData = new BitmapData(32, 32, true, 0x00FFFFFF);
var noise:BitmapData = result.clone();
noise.perlinNoise(4, 4, 4, seed, false, true, BitmapDataChannel.RED | BitmapDataChannel.GREEN);
var sp:Sprite = new Sprite();
var g:Graphics = sp.graphics;
g.beginFill(0x880000);
g.drawCircle(16, 16, 12);
g.drawCircle(16, 16, 10);
g.endFill();
result.draw(sp);
result.applyFilter(result, result.rect, new Point(), new DisplacementMapFilter(
noise, new Point(), BitmapDataChannel.RED, BitmapDataChannel.GREEN,
32, 32, DisplacementMapFilterMode.CLAMP
));
return result;
}
}
//}
//package ore.orelib.commons {
import com.bit101.components.ProgressBar;
import flash.display.DisplayObjectContainer;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.utils.Dictionary;
import net.user1.reactor.Reactor;
import net.user1.reactor.ReactorEvent;
import net.wonderfl.utils.FontLoader;
[Event(name = "complete", type = "flash.events.Event")]
//public
class Preloader extends EventDispatcher {
private var _progressBar:ProgressBar;
private var _reactor:Reactor;
private var _loaders:Dictionary;
private var _fonts:Vector.<String>;
public function Preloader(parent:DisplayObjectContainer) {
_progressBar = new ProgressBar(parent, 182, 227);
_progressBar.maximum = 0;
_reactor = null;
_loaders = new Dictionary();
_fonts = new Vector.<String>();
}
public function addReactorConnectionRequest(reactor:Reactor):void {
_reactor = reactor;
}
public function addLoaderRequest(...urls):void {
for each(var url:String in urls) {
_loaders[url] = new Loader();
}
}
public function addFontLoaderRequest(...fontNames):void {
for each(var fontName:String in fontNames) {
_fonts.push(fontName);
}
}
public function load():void {
if (_reactor) {
_reactor.addEventListener(ReactorEvent.READY, onLoaded);
_reactor.connect("tryunion.com", 80);
_progressBar.maximum++;
}
for (var url:String in _loaders) {
var loader:Loader = _loaders[url];
loader.contentLoaderInfo.addEventListener(Event.INIT, onLoaded);
loader.load(new URLRequest(url), new LoaderContext(true));
_progressBar.maximum++;
}
for each(var fontName:String in _fonts) {
var fontLoader:FontLoader = new FontLoader();
fontLoader.addEventListener(Event.COMPLETE, onLoaded);
fontLoader.load(fontName);
_progressBar.maximum++;
}
if (_progressBar.maximum == 0) { onLoaded(); }
function onLoaded(event:Event = null):void {
if (event) { event.currentTarget.removeEventListener(event.type, arguments.callee); }
if (++_progressBar.value >= _progressBar.maximum) {
_progressBar.parent.removeChild(_progressBar);
dispatchEvent(new Event(Event.COMPLETE));
}
}
}
public function get loaders():Dictionary { return _loaders; }
}
//}
//package ore.orelib.commons {
import flash.utils.Dictionary;
//public
class Assets {
public static var images:Dictionary = new Dictionary();
}
//}
//package ore.orelib.commons {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.geom.Matrix;
import flash.geom.Rectangle;
/** 読み込んだ画像をクリッピングして、新しい BitmapData クラスを作成します。 */
//public
class TileSheet {
private var _source:BitmapData;
public function TileSheet(loader:Loader) {
_source = Bitmap(loader.content).bitmapData;
}
public function clip(rect:Rectangle):BitmapData {
var result:BitmapData = new BitmapData(rect.width, rect.height, true, 0x00FFFFFF);
var matrix:Matrix = new Matrix();
matrix.translate( -rect.x, -rect.y);
result.draw(_source, matrix);
return result;
}
public function blit(first:Rectangle, cols:int, rows:int):Vector.<BitmapData> {
var result:Vector.<BitmapData> = new Vector.<BitmapData>();
for (var row:int = 0; row < rows; row++) {
for (var col:int = 0; col < cols; col++) {
var left:Number = col * first.width + first.x;
var top:Number = row * first.height + first.y;
result.push(clip(new Rectangle(left, top, first.width, first.height)));
}
}
result.fixed = true;
return result;
}
}
//}
//package ore.orelib.commons {
import flash.display.Stage;
/** 入力状態を取得するクラスです。 */
//public
class Input {
private static var _key:KeyWatcher;
private static var _mouse:MouseWatcher;
public static function setup(stage:Stage):void {
_key = new KeyWatcher(stage);
_mouse = new MouseWatcher(stage);
}
public static function record():void {
_key.record();
_mouse.record();
}
public static function get key():KeyWatcher { return _key; }
public static function get mouse():MouseWatcher { return _mouse; }
public static const NUM_0:uint = 48; public static const NUM_1:uint = 49;
public static const NUM_2:uint = 50; public static const NUM_3:uint = 51;
public static const NUM_4:uint = 52; public static const NUM_5:uint = 53;
public static const NUM_6:uint = 54; public static const NUM_7:uint = 55;
public static const NUM_8:uint = 56; public static const NUM_9:uint = 57;
public static const A:uint = 65; public static const B:uint = 66; public static const C:uint = 67;
public static const D:uint = 68; public static const E:uint = 69; public static const F:uint = 70;
public static const G:uint = 71; public static const H:uint = 72; public static const I:uint = 73;
public static const J:uint = 74; public static const K:uint = 75; public static const L:uint = 76;
public static const M:uint = 77; public static const N:uint = 78; public static const O:uint = 79;
public static const P:uint = 80; public static const Q:uint = 81; public static const R:uint = 82;
public static const S:uint = 83; public static const T:uint = 84; public static const U:uint = 85;
public static const V:uint = 86; public static const W:uint = 87; public static const X:uint = 88;
public static const Y:uint = 89; public static const Z:uint = 90;
}
//}
//package ore.orelib.commons {
import flash.display.Stage;
import flash.events.KeyboardEvent;
/** キーボード入力状態を監視します。 */
//public
class KeyWatcher {
private var _currentStates:Vector.<Boolean>;
private var _previousStates:Vector.<Boolean>;
public function KeyWatcher(stage:Stage) {
_currentStates = new Vector.<Boolean>(256, true);
_previousStates = new Vector.<Boolean>(256, true);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
}
private function keyDownHandler(event:KeyboardEvent):void { _currentStates[event.keyCode] = true; }
private function keyUpHandler(event:KeyboardEvent):void { _currentStates[event.keyCode] = false; }
public function record():void {
for (var i:int = 0; i < 256; i++) {
_previousStates[i] = _currentStates[i];
}
}
public function isDown(keycode:uint):Boolean { return _currentStates[keycode]; }
public function isPressed(keycode:uint):Boolean { return !_previousStates[keycode] && _currentStates[keycode]; }
}
//}
//package ore.orelib.commons {
import flash.display.Stage;
import flash.events.MouseEvent;
/** マウス左ボタン入力状態を監視します。 */
//public
class MouseWatcher {
private var _currentState:Boolean;
private var _previousState:Boolean;
public function MouseWatcher(stage:Stage) {
_currentState = false;
_previousState = false;
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
private function mouseDownHandler(event:MouseEvent):void { _currentState = true; }
private function mouseUpHandler(event:MouseEvent):void { _currentState = false; }
public function record():void {
_previousState = _currentState;
}
public function isDown():Boolean { return _currentState; }
public function isPressed():Boolean { return !_previousState && _currentState; }
}
//}
//package ore.orelib.commons {
import flash.errors.IllegalOperationError;
import flash.events.EventDispatcher;
/** グローバルなイベント処理を行うためのクラスです。 */
//public
class EventManager extends EventDispatcher {
private static var _instance:EventManager;
private static var _allowsInstantiation:Boolean;
public static function get instance():EventManager {
if (!_instance) {
_allowsInstantiation = true;
_instance = new EventManager();
_allowsInstantiation = false;
}
return _instance;
}
public function EventManager() {
if (!_allowsInstantiation) { throw new IllegalOperationError("EventManager class is a Singleton!"); }
}
}
//}
//package ore.orelib.commons {
import flash.geom.Point;
import flash.text.AntiAliasType;
import flash.text.GridFitType;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
/** 複雑な設定の flash.text.TextField クラスの生成を単純化します。 */
//public
class TextBuilder {
private var _align:String;
private var _autoSize:Boolean;
private var _bold:Boolean;
private var _filters:Array;
private var _fontName:String;
private var _sharpness:Number;
private var _thickness:Number;
private var _fontColor:uint;
private var _fontSize:int;
private var _position:Point;
private var _size:Point;
public static const LEFT:String = "left";
public static const RIGHT:String = "right";
public static const CENTER:String = "center";
public function TextBuilder() {
_align = TextBuilder.LEFT;
_autoSize = _bold = false;
_filters = [];
_fontName = null;
_sharpness = _thickness = 0;
_fontColor = 0x000000;
_fontSize = 12;
_position = new Point(0, 0);
_size = new Point(100, 100);
}
public function align(value:String):TextBuilder { _align = value; return this; }
public function autoSize(enabled:Boolean = true):TextBuilder { _autoSize = enabled; return this; }
public function bold(enabled:Boolean = true):TextBuilder { _bold = enabled; return this; }
public function filters(value:Array):TextBuilder { _filters = value; return this; }
public function font(name:String, sharpness:Number = 0, thickness:Number = 0):TextBuilder {
_fontName = name;
_sharpness = sharpness; _thickness = thickness;
return this;
}
public function fontColor(value:uint):TextBuilder { _fontColor = value; return this; }
public function fontSize(value:int):TextBuilder { _fontSize = value; return this; }
public function pos(x:Number, y:Number, relative:Boolean = false):TextBuilder {
_position.x = ((relative) ? _position.x : 0) + x;
_position.y = ((relative) ? _position.y : 0) + y;
return this;
}
public function size(width:Number, height:Number):TextBuilder {
_size.x = width;
_size.y = height;
return this;
}
public function build(text:String):TextField {
var tf:TextField = new TextField();
var format:TextFormat = new TextFormat(_fontName, _fontSize, _fontColor, _bold);
if (_fontName) {
tf.embedFonts = true;
tf.antiAliasType = AntiAliasType.ADVANCED;
tf.gridFitType = (_align == TextBuilder.LEFT) ? GridFitType.PIXEL : GridFitType.SUBPIXEL;
tf.sharpness = _sharpness;
tf.thickness = _thickness;
}
tf.x = _position.x;
tf.width = _size.x;
tf.height = _size.y;
if (_autoSize) {
switch(_align) {
case TextBuilder.LEFT: { tf.autoSize = TextFieldAutoSize.LEFT; break; }
case TextBuilder.RIGHT: { tf.autoSize = TextFieldAutoSize.RIGHT; break; }
case TextBuilder.CENTER: { tf.autoSize = TextFieldAutoSize.CENTER; break; }
}
}else {
switch(_align) {
case TextBuilder.LEFT: { format.align = TextFormatAlign.LEFT; break; }
case TextBuilder.RIGHT: { format.align = TextFormatAlign.RIGHT; break; }
case TextBuilder.CENTER: { format.align = TextFormatAlign.CENTER; break; }
}
}
tf.defaultTextFormat = format;
tf.text = text;
tf.y = _position.y + ((_autoSize) ? Math.max(0, int((_size.y - (tf.textHeight + 4)) / 2)) : 0);
tf.filters = _filters.concat();
tf.mouseEnabled = tf.selectable = false;
return tf;
}
public function clone():TextBuilder {
return new TextBuilder().align(_align).autoSize(_autoSize).bold(_bold).filters(_filters)
.font(_fontName, _sharpness, _thickness).fontColor(_fontColor).fontSize(_fontSize)
.pos(_position.x, _position.y).size(_size.x, _size.y);
}
}
//}
//package ore.orelib.commons {
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
/** flash.geom パッケージ内クラスのインスタンスを再利用するためのクラスです。 */
//public
class GeomPool {
private static var _colorTransforms:Vector.<ColorTransform>;
private static var _matrices:Vector.<Matrix>;
private static var _points:Vector.<Point>;
private static var _rectangles:Vector.<Rectangle>;
private static var _colorTransformsIndex:int;
private static var _matricesIndex:int;
private static var _pointsIndex:int;
private static var _rectanglesIndex:int;
public static function setup(capacity:int):void {
capacity = Math.max(1, capacity);
_colorTransforms = new Vector.<ColorTransform>(capacity, true);
_matrices = new Vector.<Matrix>(capacity, true);
_points = new Vector.<Point>(capacity, true);
_rectangles = new Vector.<Rectangle>(capacity, true);
for (var i:int = 0; i < capacity; i++) {
_colorTransforms[i] = new ColorTransform();
_matrices[i] = new Matrix();
_points[i] = new Point();
_rectangles[i] = new Rectangle();
}
_colorTransformsIndex = _matricesIndex = _pointsIndex = _rectanglesIndex = 0;
}
public static function colorTransform(
redMultiplier:Number = 1, greenMultiplier:Number = 1, blueMultiplier:Number = 1, alphaMultiplier:Number = 1,
redOffset:Number = 0, greenOffset:Number = 0, blueOffset:Number = 0, alphaOffset:Number = 0
):ColorTransform {
var result:ColorTransform = _colorTransforms[_colorTransformsIndex++];
if (_colorTransformsIndex >= _colorTransforms.length) { _colorTransformsIndex = 0; }
result.redMultiplier = redMultiplier;
result.greenMultiplier = greenMultiplier;
result.blueMultiplier = blueMultiplier;
result.alphaMultiplier = alphaMultiplier;
result.redOffset = redOffset;
result.greenOffset = greenOffset;
result.blueOffset = blueOffset;
result.alphaOffset = alphaOffset;
return result;
}
public static function matrix(a:Number = 1, b:Number = 0, c:Number = 0, d:Number = 1, tx:Number = 0, ty:Number = 0):Matrix {
var result:Matrix = _matrices[_matricesIndex++];
if (_matricesIndex >= _matrices.length) { _matricesIndex = 0; }
result.a = a;
result.b = b;
result.c = c;
result.d = d;
result.tx = tx;
result.ty = ty;
return result;
}
public static function point(x:Number = 0, y:Number = 0):Point {
var result:Point = _points[_pointsIndex++];
if (_pointsIndex >= _points.length) { _pointsIndex = 0; }
result.x = x;
result.y = y;
return result;
}
public static function rectangle(x:Number = 0, y:Number = 0, width:Number = 0, height:Number = 0):Rectangle {
var result:Rectangle = _rectangles[_rectanglesIndex++];
if (_rectanglesIndex >= _rectangles.length) { _rectanglesIndex = 0; }
result.x = x;
result.y = y;
result.width = width;
result.height = height;
return result;
}
}
//}
//package ore.orelib.commons {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.utils.Timer;
import net.user1.reactor.Reactor;
import net.user1.reactor.Statistics;
//public
class UnionStats extends Sprite {
private var _reactor:Reactor;
private var _fpsCount:int;
private var _timer:Timer;
private var _fps:TextField, _stageFps:TextField;
private var _mem:TextField, _peakMem:TextField;
private var _ping:TextField;
private var _recv:TextField, _peakRecv:TextField;
private var _send:TextField, _peakSend:TextField;
private var _msg:TextField, _peakMsg:TextField;
public function UnionStats(reactor:Reactor) {
_reactor = reactor;
_reactor.enableStatistics();
_fpsCount = 0;
addEventListener(Event.ENTER_FRAME, function(event:Event):void { _fpsCount++; } );
_timer = new Timer(1000, 0);
_timer.addEventListener(TimerEvent.TIMER, update);
_timer.start();
graphics.beginFill(0x404040);
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
graphics.lineStyle(1, 0xFFFFFF, 1, true, "normal", "none", "bevel");
graphics.moveTo(5, 34);
graphics.lineTo(95, 34);
addChild(createTextField("FPS ", 0, 0, 30, TextFieldAutoSize.LEFT));
addChild(createTextField("Mem ", 0, 16, 30, TextFieldAutoSize.LEFT));
addChild(createTextField("Ping ", 0, 36, 30, TextFieldAutoSize.LEFT));
addChild(createTextField("Down ", 0, 52, 30, TextFieldAutoSize.LEFT));
addChild(createTextField("Up ", 0, 68, 30, TextFieldAutoSize.LEFT));
addChild(createTextField("Msg ", 0, 84, 30, TextFieldAutoSize.LEFT));
addChild(_fps = createTextField("0", 30, 0, 30, TextFieldAutoSize.RIGHT));
addChild(_mem = createTextField("0", 30, 16, 30, TextFieldAutoSize.RIGHT));
addChild(_recv = createTextField("0", 30, 52, 30, TextFieldAutoSize.RIGHT));
addChild(_send = createTextField("0", 30, 68, 30, TextFieldAutoSize.RIGHT));
addChild(_msg = createTextField("0", 30, 84, 30, TextFieldAutoSize.RIGHT));
addChild(createTextField("/", 60, 0, 7, TextFieldAutoSize.CENTER));
addChild(createTextField("/", 60, 16, 7, TextFieldAutoSize.CENTER));
addChild(_ping = createTextField("0", 30, 36, 70, TextFieldAutoSize.CENTER));
addChild(createTextField("/", 60, 52, 7, TextFieldAutoSize.CENTER));
addChild(createTextField("/", 60, 68, 7, TextFieldAutoSize.CENTER));
addChild(createTextField("/", 60, 84, 7, TextFieldAutoSize.CENTER));
addChild(_stageFps = createTextField("0", 67, 0, 30, TextFieldAutoSize.LEFT));
addChild(_peakMem = createTextField("0", 67, 16, 30, TextFieldAutoSize.LEFT));
addChild(_peakRecv = createTextField("0", 67, 52, 30, TextFieldAutoSize.LEFT));
addChild(_peakSend = createTextField("0", 67, 68, 30, TextFieldAutoSize.LEFT));
addChild(_peakMsg = createTextField("0", 67, 84, 30, TextFieldAutoSize.LEFT));
}
private function update(event:TimerEvent):void {
_fps.text = _fpsCount.toString();
_fpsCount = 0;
if (stage) { _stageFps.text = stage.frameRate.toString(); }
if (!_reactor.isReady()) { return; }
_ping.text = _reactor.self().getPing().toString();
var stats:Statistics = _reactor.getStatistics();
_mem.text = stats.getTotalMemoryMB().toFixed(2);
_recv.text = stats.getKBReceivedPerSecond().toFixed(2);
_send.text = stats.getKBSentPerSecond().toFixed(2);
_msg.text = stats.getMessagesPerSecond().toString();
_peakMem.text = stats.getPeakMemoryMB().toFixed(2);
_peakRecv.text = stats.getPeakKBReceivedPerSecond().toFixed(2);
_peakSend.text = stats.getPeakKBSentPerSecond().toFixed(2);
_peakMsg.text = stats.getPeakMessagesPerSecond().toString();
}
private function createTextField(text:String, x:int, y:int, width:int, autoSize:String):TextField {
var result:TextField = new TextField();
result.x = x;
result.width = width;
result.autoSize = autoSize;
result.defaultTextFormat = new TextFormat("_sans", 9, 0xFFFFFF, true);
result.text = text;
result.y = y;
result.mouseEnabled = result.selectable = false;
return result;
}
}
//}
//package ore.orelib.commons {
import com.bit101.components.PushButton;
import com.bit101.components.Style;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BevelFilter;
import flash.filters.DropShadowFilter;
import flash.net.SharedObject;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import net.user1.logger.Logger;
import net.user1.reactor.IClient;
import net.user1.reactor.Reactor;
import net.user1.reactor.ReactorEvent;
import net.user1.reactor.Room;
import net.user1.reactor.RoomEvent;
import net.user1.reactor.UpdateLevels;
//public
class MiniChat extends Sprite {
private var _so:SharedObject;
private var _isReactorShared:Boolean;
private var _reactor:Reactor;
private var _roomID:String;
private var _room:Room;
private var _messageLogSize:int;
private var _messages:Vector.<String>;
// ステータスバー
private var _statusBar:TextField;
private var _minimizeButton:PushButton;
// ウインドウ
private var _window:Sprite;
private var _messageDisplay:TextField;
private var _nameInput:TextField;
private var _messageInput:TextField;
private var _sendButton:PushButton;
/**
* ミニチャットウインドウを作成します。表示リストに追加されているかどうかで、自動的に接続・切断を行います。
* @param roomID チャットルームのIDです。他と被らないような名前を設定して下さい。
* @param args 任意で指定する引数です。
* "logSize" 表示するメッセージの数を指定します。初期値は5です。指定数に応じて、ウインドウの高さが調整されます。
* "textColor" 上部ステータスバーの文字の色を指定します。
* "backgroundColor" 上部ステータスバーの背景の色を指定します。
* "defaultUserName" デフォルトの参加者の名前を指定します。指定しない場合、"名無し"または前回参加時の名前になります。
* "initiallyMinimized" 最初に最小化された状態にするかどうかを指定します。初期値はfalseです。
* "draggable" ドラッグ可能にするかどうかを指定します。初期値はtrueです。
* "minimizable" 最小化可能にするかどうかを指定します。初期値はtrueです。falseの場合、最小化ボタンは表示されません。
* "renamable" 名前変更可能にするかどうかを指定します。初期値はtrueです。falseの場合、名前入力欄は表示されません。
* "reactor" メッセージ通信に、指定したReactorを使用するようにします。指定した場合、自動的な接続・切断は無効になります。
*/
public function MiniChat(roomID:String, args:Object = null) {
_so = SharedObject.getLocal("MiniChat");
if (!_so.data.name) { _so.data.name = "名無し"; }
if (!args) { args = { }; }
var logSize:int = ("logSize" in args) ? args["logSize"] : 5;
var textColor:uint = ("textColor" in args) ? args["textColor"] : 0xFFFFFF;
var backgroundColor:uint = ("backgroundColor" in args) ? args["backgroundColor"] : 0x404040;
var defaultUserName:String = ("defaultUserName" in args) ? args["defaultUserName"] : _so.data.name;
var initiallyMinimized:Boolean = ("initiallyMinimized" in args) ? args["initiallyMinimized"] : false;
var draggable:Boolean = ("draggable" in args) ? args["draggable"] : true;
var minimizable:Boolean = ("minimizable" in args) ? args["minimizable"] : true;
var renamable:Boolean = ("renamable" in args) ? args["renamable"] : true;
_isReactorShared = ("reactor" in args) ? true : false;
_reactor = (_isReactorShared) ? args["reactor"] : new Reactor();
_roomID = roomID;
_messageLogSize = Math.max(1, logSize);
_messages = new Vector.<String>();
// MinimalcompsのStyleを一時保存してから変更する
var tempEmbedFonts:Boolean = Style.embedFonts;
var tempFontName:String = Style.fontName;
var tempFontSize:Number = Style.fontSize;
Style.embedFonts = false;
Style.fontName = "_sans";
Style.fontSize = 10;
// UIの作成
addChild(_statusBar = createStatusBar(draggable, textColor, backgroundColor));
if (minimizable) { addChild(_minimizeButton = createMinimizeButton()); }
_messageDisplay = createMessageDisplay(logSize);
_window = createWindow(_messageDisplay.height);
addChild(_window);
_window.addChild(_messageDisplay);
_nameInput = createInputText(1, _window.height - 19, 50, 8, defaultUserName);
if (renamable) {
_window.addChild(_nameInput);
_window.addChild(_messageInput = createInputText(51, _window.height - 19, 150, 50, ""));
}else {
_window.addChild(_messageInput = createInputText(1, _window.height - 19, 200, 50, ""));
}
_window.addChild(_sendButton = createSendButton(_window.height - 19));
// MinimalcompsのStyleを元に戻す
Style.embedFonts = tempEmbedFonts;
Style.fontName = tempFontName;
Style.fontSize = tempFontSize;
if (initiallyMinimized) { minimize(); }
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true);
addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler, false, 0, true);
}
private function createStatusBar(draggable:Boolean, textColor:uint, backgroundColor:uint):TextField {
var result:TextField = new TextField();
result.width = 232; result.height = 20;
var format:TextFormat = new TextFormat("_sans", 10, textColor);
format.align = TextFormatAlign.CENTER;
result.defaultTextFormat = format;
result.background = true; result.backgroundColor = backgroundColor;
result.filters = [new BevelFilter(1, 45, 0xFFFFFF, 0.8, 0x000000, 0.8, 1, 1)];
result.mouseEnabled = result.selectable = false;
if (draggable) {
result.mouseEnabled = true;
result.addEventListener(MouseEvent.MOUSE_DOWN, startDragHandler);
result.addEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
}
return result;
}
private function startDragHandler(event:MouseEvent):void { startDrag(); }
private function stopDragHandler(event:MouseEvent):void { stopDrag(); }
private function createMinimizeButton():PushButton {
var result:PushButton = new PushButton(null, 215, 3, "-", minimize);
result.width = result.height = 14; result.draw();
return result;
}
private function createWindow(messageDisplayHeight:int):Sprite {
var result:Sprite = new Sprite();
result.y = 20;
result.graphics.beginFill(0x808080, 0.5);
result.graphics.drawRect(0, 0, 232, messageDisplayHeight + 20);
result.graphics.endFill();
return result;
}
private function createMessageDisplay(logSize:int):TextField {
var result:TextField = new TextField();
result.width = 232;
result.defaultTextFormat = new TextFormat("_sans", 10, 0xFFFFFF);
result.filters = [new DropShadowFilter(1, 45, 0x404040, 1, 1, 1)];
result.mouseEnabled = result.selectable = false;
for (var i:int = 0; i < logSize; i++) { result.appendText(i + "\n"); }
result.height = result.textHeight + 4; result.text = "";
return result;
}
private function createInputText(x:int, y:int, width:int, maxChars:int, text:String):TextField {
var result:TextField = new TextField();
result.x = x; result.y = y;
result.width = width; result.height = 18;
result.defaultTextFormat = new TextFormat("_sans", 10, 0x000000);
result.background = true; result.backgroundColor = 0xFFFFFF;
result.filters = [new BevelFilter(1, 225, 0xC0C0C0, 1, 0x404040, 1, 1, 1)];
result.maxChars = maxChars;
result.selectable = true;
result.type = TextFieldType.INPUT;
result.text = text;
return result;
}
private function createSendButton(y:int):PushButton {
var result:PushButton = new PushButton(null, 201, y, "送信", sendMessage);
result.width = 30; result.height = 18; result.draw();
return result;
}
private function addedToStageHandler(event:Event):void {
_reactor.addEventListener(ReactorEvent.READY, joinRoom);
_reactor.addEventListener(ReactorEvent.CLOSE, leaveRoom);
leaveRoom();
if (_isReactorShared) {
if (_reactor.isReady()) { joinRoom(); }
} else {
_reactor.getConnectionMonitor().setAutoReconnectFrequency(5000);
_reactor.getLog().setLevel(Logger.FATAL);
_reactor.connect("tryunion.com", 80);
}
}
private function removedFromStageHandler(event:Event):void {
_reactor.removeEventListener(ReactorEvent.READY, joinRoom);
_reactor.removeEventListener(ReactorEvent.CLOSE, leaveRoom);
leaveRoom();
if (!_isReactorShared) { _reactor.disconnect(); }
}
private function joinRoom(event:ReactorEvent = null):void {
var updateLevels:UpdateLevels = new UpdateLevels();
updateLevels.clearAll();
updateLevels.occupantCount = updateLevels.roomMessages = true;
_room = _reactor.getRoomManager().createRoom(_roomID);
_room.addEventListener(RoomEvent.OCCUPANT_COUNT, roomOccupantCountHandler);
_room.addMessageListener("CHAT_MESSAGE", receiveMessage);
_room.join(null, updateLevels);
_sendButton.enabled = true;
}
private function roomOccupantCountHandler(event:RoomEvent):void {
_statusBar.text = "現在の閲覧者数 " + _room.getNumOccupants() + "人";
}
private function leaveRoom(event:ReactorEvent = null):void {
if (_room) {
_room.removeEventListener(RoomEvent.OCCUPANT_COUNT, roomOccupantCountHandler);
_room.removeMessageListener("CHAT_MESSAGE", receiveMessage);
_room.leave();
}
_statusBar.text = "サーバーに接続中...";
_sendButton.enabled = false;
}
private function sendMessage(event:MouseEvent):void {
if (_messageInput.text == "") { return; }
_room.sendMessage("CHAT_MESSAGE", true, null, _nameInput.text, _messageInput.text);
_so.data.name = _nameInput.text;
_messageInput.text = "";
stage.focus = null;
}
private function receiveMessage(from:IClient, senderName:String, messageText:String):void {
_messages.push(senderName + ": " + messageText);
if (_messages.length > _messageLogSize) { _messages.shift(); }
_messageDisplay.text = "";
var messagesLength:int = _messages.length;
for (var i:int = 0; i < messagesLength; i++) {
_messageDisplay.appendText(_messages[i] + "\n");
}
}
private function minimize(event:MouseEvent = null):void {
_window.visible = !_window.visible;
if (_minimizeButton) { _minimizeButton.label = (_window.visible) ? "-" : "+"; }
}
}
//}
//package ore.orelib.data {
import flash.errors.IllegalOperationError;
import flash.net.registerClassAlias;
import flash.net.SharedObject;
//public
class SaveData {
private var _so:SharedObject;
private static var _instance:SaveData;
private static var _allowsInstantiation:Boolean;
public static function get instance():SaveData {
if (!_instance) {
_allowsInstantiation = true;
_instance = new SaveData();
_allowsInstantiation = false;
}
return _instance;
}
public function SaveData() {
if (!_allowsInstantiation) { throw new IllegalOperationError("SaveData class is a Singleton!"); }
registerClassAlias("ore.orelib.data.PlayerData", PlayerData);
registerClassAlias("ore.orelib.data.PlayerStatus", PlayerStatus);
registerClassAlias("ore.orelib.data.WeaponData", WeaponData);
_so = SharedObject.getLocal("SaveData");
if (!_so.data.player) {
_so.data.player = new PlayerData();
_so.data.inventory = WeaponSmith.createInitialEquipment();
}
}
public function get player():PlayerData { return _so.data.player; }
public function get inventory():Array { return _so.data.inventory; }
}
//}
//package ore.orelib.data {
//public
class PlayerData {
public var name:String = "";
public var characterID:int = Const.CHARACTER_HOMURA;
public var level:int = 1;
public var exp:Number = 0;
public var statusPoints:int = 2;
public var status:PlayerStatus = new PlayerStatus(100, 100, 100, 100);
public var primaryWeaponIndex:int = 0;
public var secondaryWeaponIndex:int = 1;
}
//}
//package ore.orelib.data {
//public
class PlayerStatus {
public var str:int;
public var vit:int;
public var dex:int;
public var luc:int;
public function PlayerStatus(str:int = 0, vit:int = 0, dex:int = 0, luc:int = 0) {
this.str = str;
this.vit = vit;
this.dex = dex;
this.luc = luc;
}
}
//}
//package ore.orelib.data {
//public
class WeaponData {
public var id:int = 0;
public var prefix:int = 0;
public var prefixLevel:int = 0;
public var base:int = 0;
public var baseLevel:int = 0;
}
//}
//package ore.orelib.data {
/* import ore.orelib.logic.Weapon;
*/
//public
class WeaponSmith {
/**
* 0. requirementScore
* 1. baseMinDamage
* 2. baseRandDamage
* 3. multDamage
* 4. addMinDamage
* 5. addRandDamage
* 6. baseAttackRate
* 7. multAttackRate
* 8. baseReloadRate
* 9. multReloadRate
* 10. baseAmmo
* 11. addAmmo
* 12. criticalRate
* 13. knockback
* 14. strBonus
* 15. vitBonus
* 16. dexBonus
* 17. lucBonus
* 18. baseRange
* 19. multRange
* 20. penetration
*/
private static const WEAPONS:Array = [
{
baseName: "ピストル",
mods: [
[0, 15, 15, 0, 0, 0, 100, 0, 1500, 0, 100, 0, 0, 1, 0, 0, 0, 0, 100, 0, 10]
]
},
null,
{
baseName: "ミニミ",
mods:[
[0, 8, 32, 0, 0, 0, 100, 0, 2500, 0, 50, 0, 3, 0, 0, 0, 0, 0, 150, 0, 1]
]
},
null,
null,
null,
null,
null,
{
baseName: "ゴルフクラブ",
mods: [
[0, 45, 25, 0, 0, 0, 500, 0, 500, 0, 1, 0, 15, 10, 0, 0, 0, 0, 36, 0, 0]
]
},
null,
null,
null
];
public static function createWeaponFromData(data:WeaponData):Weapon {
var name:String = WEAPONS[data.id].baseName;
var mods:Array = WEAPONS[data.id].mods[0];
var buffs:String = "";
if (mods[3] > 0) { buffs += "ダメージ +" + mods[3] + "%\n"; }
if (mods[4] > 0) { buffs += "最小ダメージ +" + mods[4] + "\n"; }
if (mods[5] > 0) { buffs += "最大ダメージ +" + mods[5] + "\n"; }
if (mods[7] > 0) { buffs += "攻撃速度 +" + mods[7] + "%\n"; }
if (mods[9] > 0) { buffs += "リロード速度 +" + mods[9] + "%\n"; }
if (mods[11] > 0) { buffs += "装弾数 +" + mods[11] + "\n"; }
if (mods[12] > 0) { buffs += "命中時 " + mods[12] + "% の確率でクリティカル\n"; }
if (mods[13] > 0) { buffs += "命中時ノックバック +" + mods[13] + "\n"; }
if (mods[14] > 0) { buffs += "魔力ボーナス +" + mods[14] + "\n"; }
if (mods[15] > 0) { buffs += "体力ボーナス +" + mods[15] + "\n"; }
if (mods[16] > 0) { buffs += "敏捷ボーナス +" + mods[16] + "\n"; }
if (mods[17] > 0) { buffs += "幸運ボーナス +" + mods[17] + "\n"; }
if (mods[19] > 0) { buffs += "範囲 +" + mods[19] + "%\n"; }
if (mods[20] > 0) { buffs += "貫通力 +" + mods[20] + "\n"; }
return new Weapon(
data.id,
name,
buffs,
(mods[1] * (100 + mods[3]) / 100) + mods[4],
(mods[2] * (100 + mods[3]) / 100) + mods[5],
mods[6] * (100 + mods[7]) / 100,
mods[8] * (100 + mods[9]) / 100,
mods[10] + mods[11],
mods[12],
mods[13],
new PlayerStatus(mods[14], mods[15], mods[16], mods[17]),
mods[18] + mods[19],
mods[20]
);
}
public static function createInitialEquipment():Array {
var result:Array = [];
var primary:WeaponData = new WeaponData();
primary.id = Const.WEAPON_MINIMI;
var secondary:WeaponData = new WeaponData();
secondary.id = Const.WEAPON_GOLFCLUB;
result.push(primary, secondary);
return result;
}
public static function acquireAttackTypeOf(weaponID:int):int {
switch(weaponID) {
case Const.WEAPON_PIPEBOMB:
case Const.WEAPON_RPG7:
{
return Const.ATTACKTYPE_EXPLOSIVE;
}
case Const.WEAPON_GOLFCLUB:
case Const.WEAPON_METALBAT:
case Const.WEAPON_SABER:
case Const.WEAPON_SPEAR:
{
return Const.ATTACKTYPE_MELEE;
}
case Const.WEAPON_PISTOL:
case Const.WEAPON_MASKET:
case Const.WEAPON_MINIMI:
case Const.WEAPON_ROSEBOW:
case Const.WEAPON_BLACKBOW:
case Const.WEAPON_EXTINGUISHER:
default:
{
return Const.ATTACKTYPE_SHOOTING;
}
}
}
}
//}
//package ore.orelib.data {
//public
class Const {
// プレイフィールドの設定
public static const FIELD_SIZE:int = 300;
public static const FIELD_OFFSET_X:int = 100;
public static const FIELD_OFFSET_Y:int = 165;
public static const FIELD_LFET_BOUND:int = -130;
public static const FIELD_RIGHT_BOUND:int = 370;
public static const FIELD_WAVE_TIME:int = 30000; //(ms)
public static const FIELD_QB_QUOTA:int = 50;
// プレイヤーの基礎値
public static const PLAYER_SPEED:Number = 60; //(px/s)
public static const PLAYER_SWAP_TIME:int = 500; //(ms)
public static const PLAYER_INVINCIBLE_TIME_ON_DAMAGED:int = 250; //(ms)
public static const PLAYER_INVINCIBLE_TIME_ON_RECOVER:int = 2000; //(ms)
public static const PLAYER_RECOVER_TIME:int = 20000; //(ms)
public static const PLAYER_POS_SEND_INTERVAL:int = 250; //(ms)
// キャラクターのID
public static const CHARACTER_MADOKA:int = 0;
public static const CHARACTER_HOMURA:int = 3;
public static const CHARACTER_SAYAKA:int = 6;
public static const CHARACTER_MAMI:int = 9;
public static const CHARACTER_KYOKO:int = 12;
public static const CHARACTER_QB:int = 15;
// 武器のID
public static const WEAPON_PISTOL:int = 0;
public static const WEAPON_MASKET:int = 1;
public static const WEAPON_MINIMI:int = 2;
public static const WEAPON_ROSEBOW:int = 3;
public static const WEAPON_BLACKBOW:int = 4;
public static const WEAPON_EXTINGUISHER:int = 5;
public static const WEAPON_PIPEBOMB:int = 6;
public static const WEAPON_RPG7:int = 7;
public static const WEAPON_GOLFCLUB:int = 8;
public static const WEAPON_METALBAT:int = 9;
public static const WEAPON_SABER:int = 10;
public static const WEAPON_SPEAR:int = 11;
// 武器攻撃タイプのID
public static const ATTACKTYPE_SHOOTING:int = 0;
public static const ATTACKTYPE_EXPLOSIVE:int = 1;
public static const ATTACKTYPE_MELEE:int = 2;
public static const DEGREES_TO_RADIANS:Number = Math.PI / 180;
public static const IMAGE_URL:String = "http://assets.wonderfl.net/images/related_images/2/25/254f/254f80e0e624453eb301e9ac682271758303c507";
public static const FONT:String = "Azuki";
}
//}