diff --git a/src/client/haxe/ru/m/tankz/render/RenderItem.hx b/src/client/haxe/ru/m/tankz/render/RenderItem.hx index b628935..aaf5229 100644 --- a/src/client/haxe/ru/m/tankz/render/RenderItem.hx +++ b/src/client/haxe/ru/m/tankz/render/RenderItem.hx @@ -233,11 +233,24 @@ class BulletItem extends BitmapItem { } -class EagleItem extends BitmapItem { +class EagleItem extends RenderItem { + private var eagleView:Bitmap; + private var protectView:Animate; private var death:Bool; private var protected:Bool; + public function new(value:Eagle) { + super(value); + view = new Sprite(); + eagleView = new Bitmap(); + view.addChild(eagleView); + protectView = AnimateBundle.tankProtect(); + protectView.visible = false; + view.addChild(protectView); + redraw(); + } + override public function update():Void { super.update(); var d = value.death; @@ -249,8 +262,8 @@ class EagleItem extends BitmapItem { } } - override private function getImage():String { - var suffix = value.death ? '-death' : value.protect.active ? '-protected' : ''; + private function getImage():String { + var suffix = value.death ? '-death' : ''; return 'resources/image/eagle/eagle${suffix}.png'; } @@ -259,7 +272,16 @@ class EagleItem extends BitmapItem { if (!value.color.zero) { image = BitmapUtil.colorize(image, value.color); } - view.bitmapData = image; + eagleView.bitmapData = image; + if (value.protect.active) { + protectView.x = (image.width - protectView.frames[0].image.width) / 2; + protectView.y = (image.height - protectView.frames[0].image.height) / 2; + protectView.playing = true; + protectView.visible = true; + } else { + protectView.playing = false; + protectView.visible = false; + } } } diff --git a/src/client/haxe/ru/m/tankz/sound/SoundManager.hx b/src/client/haxe/ru/m/tankz/sound/SoundManager.hx index 1b2b7a3..c3f230d 100644 --- a/src/client/haxe/ru/m/tankz/sound/SoundManager.hx +++ b/src/client/haxe/ru/m/tankz/sound/SoundManager.hx @@ -1,12 +1,14 @@ package ru.m.tankz.sound; -import openfl.media.Sound; +import flash.events.Event; +import flash.media.Sound; +import flash.media.SoundChannel; +import flash.media.SoundTransform; import openfl.utils.Assets; import ru.m.tankz.core.EntityType; import ru.m.tankz.engine.Engine; import ru.m.tankz.Type; - class SoundManager { private static var TAG(default, never):String = 'SoundManager'; @@ -16,23 +18,68 @@ class SoundManager { private static var type:String = 'ogg'; #end - public function new() {} + public var volume(default, set):Float = 1; + public var mute(default, set):Bool = false; + + private var channels:Array; + private var transform:SoundTransform; + + public function new() { + channels = []; + updateSoundTransform(); + } + + private function updateSoundTransform():Void { + transform = new SoundTransform(mute ? 0 : volume); + for (channel in channels) { + channel.soundTransform = transform; + } + } + + private function set_volume(value:Float):Float { + if (volume != value) { + volume = value; + updateSoundTransform(); + } + return volume; + } + + private function set_mute(value:Bool):Bool { + if (mute != value) { + mute = value; + updateSoundTransform(); + } + return mute; + } public function play(id:String):Void { //L.d(TAG, 'play: ${id}'); var sound:Sound = Assets.getSound('resources/sounds/${id}.${type}'); if (sound != null) { - sound.play(); + var channel = sound.play(0, 0, transform); + channel.addEventListener(Event.SOUND_COMPLETE, onSoundComplete); + channels.push(channel); } else { L.w(TAG, 'Sound "${id}" not found'); } } + public function stopAll():Void { + for (channel in channels) { + channel.stop(); + } + channels = []; + } + + private function onSoundComplete(event:Event):Void { + channels.remove(event.currentTarget); + } + public function onSpawn(entity:EntityType):Void { switch entity { - case EntityType.BULLET(_.tank.playerId.team => 'human'): + case BULLET(_.tank.playerId.team => 'human'): play('shot'); - case EntityType.BONUS(_): + case BONUS(_): play('bonus_add'); case _: } @@ -40,11 +87,11 @@ class SoundManager { public function onChange(entity:EntityType, change:EntityChange):Void { switch [entity, change] { - case [EntityType.TANK(_), EntityChange.HIT]: + case [TANK(_), HIT]: play('bullet_hit'); - //case [EntityType.TANK(_), EntityChange.LIVE_UP]: + //case [TANK(_), LIVE_UP]: // play('live'); - case [EntityType.EAGLE(_), EntityChange.DEATH(_)]: + case [EAGLE(_), DEATH(_)]: play('boom_player'); case _: } @@ -52,7 +99,7 @@ class SoundManager { public function onCollision(entity:EntityType, with:EntityType):Void { switch [entity, with] { - case [EntityType.BULLET(_), EntityType.CELL(cell)]: + case [BULLET(_), CELL(cell)]: //play('bullet_wall'); case _: } @@ -60,9 +107,9 @@ class SoundManager { public function onDestroy(entity:EntityType, ?playerId:PlayerId):Void { switch entity { - case EntityType.TANK(_): + case TANK(_): play('boom_bot'); - case EntityType.BONUS(_): + case BONUS(_): play('bonus_get'); case _: } diff --git a/src/client/haxe/ru/m/tankz/view/ClientView.hx b/src/client/haxe/ru/m/tankz/view/ClientView.hx index 7bf4caf..40484b6 100644 --- a/src/client/haxe/ru/m/tankz/view/ClientView.hx +++ b/src/client/haxe/ru/m/tankz/view/ClientView.hx @@ -1,27 +1,40 @@ package ru.m.tankz.view; +import haxework.view.IView; import flash.events.KeyboardEvent; import flash.ui.Keyboard; import haxework.resources.IResources; import haxework.view.frame.FrameSwitcher; +import ru.m.tankz.sound.SoundManager; @:template class ClientView extends FrameSwitcher { @:provide var resources:IResources; @:provide var switcher:FrameSwitcher; + @:provide var soundManager:SoundManager; public function init():Void { resources.text.put('version', '${Const.VERSION}'); switcher = this; + onSwitch.connect(onFrameSwitch); } public function launch():Void { content.stage.stageFocusRect = false; content.stage.addEventListener(KeyboardEvent.KEY_UP, function(event:KeyboardEvent):Void { - if (event.keyCode == Keyboard.ESCAPE) { - change(StartFrame.ID); + switch event.keyCode { + case Keyboard.ESCAPE: + change(StartFrame.ID); + case Keyboard.M: + soundManager.mute = !soundManager.mute; } }); change(StartFrame.ID); } + + private function onFrameSwitch(frame:IView):Void { + if (frame.id == StartFrame.ID) { + soundManager.stopAll(); + } + } } diff --git a/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx b/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx index 938e3a7..b1c9941 100644 --- a/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/common/GameFrame.hx @@ -21,7 +21,7 @@ class GameFrame extends GroupView { private var panel(get, null):IGamePanel; @:provide var network:NetworkManager; - @:provide var sound:SoundManager; + @:provide var soundManager:SoundManager; @:provide var state:GameState; @:provide("result") var result:GameState; @:provide var switcher:FrameSwitcher; @@ -45,7 +45,7 @@ class GameFrame extends GroupView { private function start(state:GameState):Void { game = new Game(state.type); game.engine.connect(render); - game.engine.connect(sound); + game.engine.connect(soundManager); game.connect(this); if (panel != null) { game.connect(panel); @@ -55,7 +55,7 @@ class GameFrame extends GroupView { timer.run = updateEngine; content.addEventListener(Event.ENTER_FRAME, _redraw); render.draw(game.engine); - sound.play('start'); + soundManager.play('start'); } private function stop():Void { diff --git a/src/client/resources/image/eagle/eagle-protected.png b/src/client/resources/image/eagle/eagle-protected.png deleted file mode 100644 index 0b593f8..0000000 Binary files a/src/client/resources/image/eagle/eagle-protected.png and /dev/null differ diff --git a/src/client/resources/image/eagle/eagle.png b/src/client/resources/image/eagle/eagle.png index f646334..9e3190d 100644 Binary files a/src/client/resources/image/eagle/eagle.png and b/src/client/resources/image/eagle/eagle.png differ diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 9a52c2b..115f518 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -303,8 +303,8 @@ class Game extends GameDispatcher { private function spawnBonus(?type:BonusType):Void { var bonusConfig:BonusConfig = type != null ? config.getBonus(type) : config.bonuses[Math.floor(Math.random() * config.bonuses.length)]; var bonus = new Bonus(bonusConfig); - bonus.rect.x = Math.random() * engine.map.width; - bonus.rect.y = Math.random() * engine.map.height; + bonus.rect.x = Math.round(Math.random() * engine.map.width / engine.map.cellWidth) * engine.map.cellWidth; + bonus.rect.y = Math.round(Math.random() * engine.map.height/ engine.map.cellHeight) * engine.map.cellHeight; engine.spawn(bonus); }