diff --git a/app/beamQuest/activeEvent/mob.js b/app/beamQuest/activeEvent/mob.js index d987d71..f2db42d 100644 --- a/app/beamQuest/activeEvent/mob.js +++ b/app/beamQuest/activeEvent/mob.js @@ -36,9 +36,12 @@ Mob.prototype.spawnMob_ = function(map) { for(var i = map.mobCount;i < map.maxMobCount; i++) { // TODO: mapごとに出現モンスターとか決める var position = this.randomPosition_(map); + var mobType = bq.Params.Entities.KAMUTARO; var mob = new mobModel({ - id: 'mob_kamuraro_' + map.id + '_' + i + '_' + timeStamp, - name: 'カム太郎', + id: mobType.id + '_' + map.id + '_' + i + '_' + timeStamp, + name: mobType.name, + hp: mobType.hp, + exp: mobType.exp, position: position }); entitiesStore.addMob(map, mob); diff --git a/app/beamQuest/listener/beam.js b/app/beamQuest/listener/beam.js index 93feb62..87aca1b 100644 --- a/app/beamQuest/listener/beam.js +++ b/app/beamQuest/listener/beam.js @@ -32,6 +32,12 @@ exports.listen = function(socket, io) { var newHp = newEntity.hp + damage; newEntity.hp = newHp; + // 攻撃を与えたユーザのIDをヘイトリストに突っ込む + // TODO: ヘイト値の導入 + if (!_.contains(newEntity.hateList, data.shooterId)) { + newEntity.hateList.push(data.shooterId); + } + io.sockets.emit('notify:beam:hit', { entity: newEntity, beamTag: data.tag, diff --git a/app/beamQuest/listener/entity.js b/app/beamQuest/listener/entity.js index f8e2ec4..fe21979 100644 --- a/app/beamQuest/listener/entity.js +++ b/app/beamQuest/listener/entity.js @@ -8,6 +8,7 @@ var Entity = function() { Entity.prototype.listen = function(socket, io) { this.socket_ = socket; this.io_ = io; + this.entitiesStore_ = require('beamQuest/store/entities'); }; /** @@ -28,6 +29,21 @@ Entity.prototype.popMob = function(mob) { Entity.prototype.kill = function(entity) { var data = {entity: entity.toJSON()}; this.io_.sockets.emit('notify:entity:kill', data); + _.each(entity.hateList, function(playerId) { + this.addExp(playerId, entity); + }.bind(this)); +}; + +/** + * entityのもつ経験値をplayerに与える + * @param {string} playerId + * @param {model.Entity} entity + */ +Entity.prototype.addExp = function(playerId, entity) { + var mapId = entity.position.mapId; + var player = this.entitiesStore_.getPlayerById(mapId, playerId); + player.exp += entity.exp; + player.socket.emit('user:status:exp:update', {exp: entity.exp}); }; diff --git a/app/beamQuest/model/mob.js b/app/beamQuest/model/mob.js index 3fc42e3..10ab834 100644 --- a/app/beamQuest/model/mob.js +++ b/app/beamQuest/model/mob.js @@ -13,6 +13,12 @@ var Mob = function(opt_data) { * @type {number} */ this.exp = this.data.exp || Mob.DEFAULT_EXP; + + /** + * ヘイトリスト + * @type {Array.} + */ + this.hateList = []; }; util.inherits(Mob, Entity); @@ -22,6 +28,7 @@ Mob.DEFAULT_EXP = 1; Mob.prototype.toJSON = function() { var json = Mob.super_.prototype.toJSON.apply(this); json.exp = this.exp; + json.hateList = this.hateList; return json; }; diff --git a/app/beamQuest/model/player.js b/app/beamQuest/model/player.js index 91de41b..7243768 100644 --- a/app/beamQuest/model/player.js +++ b/app/beamQuest/model/player.js @@ -14,6 +14,12 @@ var Player = function(opt_data) { /** @type {number} */ this.bp = this.data.bp || this.maxBp; + /** @type {number} */ + this.exp = this.data.exp || 0; + + /** @type {number} */ + this.lv = this.data.lv || 1; + /** @type {Socket} */ this.socket = this.data.socket || null; }; @@ -26,6 +32,8 @@ Player.prototype.toJSON = function() { var json = Player.super_.prototype.toJSON.apply(this); json.maxBp = this.maxBp; json.bp = this.bp; + json.exp = this.exp; + json.lv = this.lv; return json; }; diff --git a/app/beamQuest/params.js b/app/beamQuest/params.js index e3888c6..cde53e6 100644 --- a/app/beamQuest/params.js +++ b/app/beamQuest/params.js @@ -11,7 +11,7 @@ bq.Params = { Entities: { // Mobs - KAMUTARO: {hp: 100, atk: 10, exp: 10} + KAMUTARO: {id: 'mob_kamutaro', name: 'カム太郎', hp: 100, atk: 10, exp: 10} } }; diff --git a/app/beamQuest/store/entities.js b/app/beamQuest/store/entities.js index f1b88f5..00cce2a 100644 --- a/app/beamQuest/store/entities.js +++ b/app/beamQuest/store/entities.js @@ -1,5 +1,5 @@ -var mapStore = require('beamQuest/store/maps'), - entityListener = require('beamQuest/listener/entity'); +var mapStore = require('beamQuest/store/maps'); + /** * ゲーム内のEntityの状態を保持しておくクラス @@ -31,6 +31,7 @@ var Entities = function() { */ this.mapNpcs_ = {}; + this.entityListener_ = require('beamQuest/listener/entity'); this.init_(); }; @@ -57,6 +58,17 @@ Entities.prototype.addPlayer = function(mapId, player) { } }; +/** + * @param {number} mapId + * @param {string} playerId + * @return {model.Player} + */ +Entities.prototype.getPlayerById = function(mapId, playerId) { + if (this.mapPlayers_[mapId]) { + return this.mapPlayers_[mapId][playerId] || null; + } +}; + /** * @param {number} mapId * @param {model.Player} player @@ -75,7 +87,7 @@ Entities.prototype.addMob = function(map, mob) { if (!_.contains(mobs, mob.id)) { mobs[mob.id] = mob; map.mobCount++; - entityListener.popMob(mob); + this.entityListener_.popMob(mob); } }; @@ -156,7 +168,7 @@ Entities.prototype.updateMobStatus = function(mapId, mob) { if (target) { target = mob; if (target.hp < 0) { // 死 - entityListener.kill(mob); + this.entityListener_.kill(mob); this.removeMob(mapStore.getMapById(mapId), mob); } } diff --git a/public/cocos2d.js b/public/cocos2d.js index 519f8ba..15b2d00 100644 --- a/public/cocos2d.js +++ b/public/cocos2d.js @@ -28,6 +28,7 @@ 'js/src/model/playerMove.js', 'js/src/model/beamPos.js', 'js/src/model/chat.js', + 'js/src/model/mob.js', 'js/src/entityManager.js', 'js/src/socket/socket.js', diff --git a/public/js/src/config.js b/public/js/src/config.js index 17de7f6..734d1f9 100644 --- a/public/js/src/config.js +++ b/public/js/src/config.js @@ -20,6 +20,7 @@ var BQConfig = cc.Class.extend({ this.tags = { BASE_LAYER: 0, PLAYER: 100, + EXP_LABEL: 101, CHAT: 500, DEBUG_PING: 1000000 }; diff --git a/public/js/src/entity/entity.js b/public/js/src/entity/entity.js index 78c9cbd..de5307a 100644 --- a/public/js/src/entity/entity.js +++ b/public/js/src/entity/entity.js @@ -14,6 +14,7 @@ bq.entity.Entity = cc.Sprite.extend({ collideRect_: null, // 当たり判定の範囲 currentState:null, currentDirection:null, + model_: null, /** * @param {string} spriteFrameName *.plistのに設定されてるframeName @@ -39,6 +40,20 @@ bq.entity.Entity = cc.Sprite.extend({ this.collideRect_ = cc.rect(0, 0, bbox.width, bbox.height); }, + /** + * @param {bq.model.Model}model + */ + setModel: function(model) { + this.model_ = model; + }, + + /** + * @return {bq.model.Model} + */ + getModel: function() { + return this.model_; + }, + /** * Entityの頭上にキャラ名を表示する */ @@ -51,10 +66,18 @@ bq.entity.Entity = cc.Sprite.extend({ }, /** - * @return {cc.rect} + * 獲得経験値をポーンって出す + * @param {number} exp + * @private */ - getCollideRect: function() { - return this.collideRect_; + popExpLabel: function(exp) { + var label = bq.Label.createWithShadow(exp + 'exp', 18); + var pos = this.getPosition(); + var fadeOut = cc.FadeOut.create(1); + var moveTo = cc.MoveTo.create(1, cc.p(0, 40)); + label.runAction(cc.Spawn.create(fadeOut, moveTo)); + label.setPosition(pos.x, pos.y); + bq.baseLayer.addChild(label, bq.config.tags.EXP_LABEL); }, /** diff --git a/public/js/src/entityManager.js b/public/js/src/entityManager.js index 8c551d5..0944b96 100644 --- a/public/js/src/entityManager.js +++ b/public/js/src/entityManager.js @@ -162,13 +162,15 @@ bq.EntityManager = cc.Class.extend({ * @param {Object} mob */ createMob: function(mob) { - var x = mob.position.x; - var y = mob.position.y; + var mobModel = new bq.model.Mob(mob); + var x = mobModel.position.x; + var y = mobModel.position.y; var enemy_id = 1; var enemy = new bq.entity.Enemy(enemy_id); + enemy.setModel(mobModel); enemy.setPosition(cc.p(x, y)); bq.baseLayer.addChild(enemy, 50); - this.enemys_[mob.id] = enemy; + this.enemys_[mobModel.id] = enemy; } }); diff --git a/public/js/src/model/mob.js b/public/js/src/model/mob.js new file mode 100644 index 0000000..64e51da --- /dev/null +++ b/public/js/src/model/mob.js @@ -0,0 +1,33 @@ +bq.model.Mob = bq.model.extend({ + ctor: function(json) { + /** @type {string} */ + this.id; + + /** @type {string} */ + this.name; + + /** @type {number} */ + this.maxHp; + + /** @type {number} */ + this.hp; + + /** @type {number} */ + this.exp; + + /** @type {cc.p} */ + this.position; + + this._super(json); + }, + + /** @override */ + parse: function(json) { + this.id = json['id']; + this.name = json['name']; + this.maxHp = json['maxHp']; + this.hp = json['hp']; + this.exp = json['exp']; + this.position = cc.p(json['position'].x, json['position'].y); + } +}); \ No newline at end of file diff --git a/public/js/src/socket/socket.js b/public/js/src/socket/socket.js index fe4d62f..bfc006f 100644 --- a/public/js/src/socket/socket.js +++ b/public/js/src/socket/socket.js @@ -13,6 +13,9 @@ bq.Socket = cc.Class.extend({ initAfterLogin: function() { var entityManager = bq.EntityManager.getInstance(); + /** + * ブロードキャストされてきたやつ + */ // チャット受信 this.socket.on('notify:message', function (data) { var chatData = new bq.model.Chat(data); @@ -49,6 +52,16 @@ bq.Socket = cc.Class.extend({ this.socket.on('notify:entity:mob:pop', function(data) { entityManager.popMob(data); }); + + /** + * 1対1の通信 + */ + // 経験値貰ったよって + this.socket.on('user:status:exp:update', function(data) { + bq.player.popExpLabel(data.exp); + // TODO:システムメッセージに表示する。 + }); + }, /**