Note: this series of tutorials are full-length, bottomless holes. If you cannot understand them, please start from Chapter 1. click the following link to the document directory.
Http://blog.csdn.net/lufy_legend/article/details/8888787
I apologize to a netizen and agree that the article updated last week will be delayed for a week. This section will introduce the automatic combat system.
Let's take a look at the effect preview:
The so-called automatic combat system means that no operation is required from the start to the end of the battle. In fact, the outcome of the automatic combat is determined at the beginning of the battle, the battle screen is only used to display or play back the battle process. This combat mode is of low development cost and is suitable for office workers because it does not require long operation, therefore, this combat method is widely used in browser games, such as the "Fairy Tales", such as the "Thirty-six Plan", and then the "Three Kingdoms". For standalone games, this method is not desirable, but my script is not necessarily used as a standalone, and some friends are eager to have a combat system, I will simply implement this battle here, and I will spend a lot of time explaining the traditional RPG turn-based combat method. Of course, it will take some time to complete even a fully automated battle. What I want to explain below is far from enough. So the title of this article is "automatic combat of the combat system (I) ", when other functions in the game are relatively complete, I will continue to improve this part of content.
Because automatic combat itself is already boring. If there is no flower in all kinds of brilliant skill pictures, it will be boring. Although this time I am only talking about it, it cannot be too simple, add special effects to characters, such as Liu Bei.
"Peo1": {"Index": 1, "Name": "Liu Bei", "Lv": 1, "Exp": 0, "HP": 200, "MP": 20, "MaxHP": 200, "MaxMP": 20, "Force": 78, "Intelligence": 76, "Command": 72, "Agile ": 74, "Luck": 100, "Face": 1, "R": 1, "RRect": [,], "S": 1, "SRect ": [, 64, 64], "SWidth": 64, "SHeight": 64, "Introduction": "Liu Bei is Shi hanzhao Lidi, word Xuande, descendants of Han Zhongshan Jing Wang Liu Sheng, the founding emperor of Shu Han in the Three Kingdoms period. "," Skill ": 1}
I added the Skill attribute to the character above, and then added a new configuration file skill. json.
Https://github.com/lufylegend/lsharp/blob/3.7/script/initialization/skill.json
Then, read the configuration file from the beginning.
Https://github.com/lufylegend/lsharp/blob/3.7/index.html
To display the stunt properties, You need to modify the CharacterProperty. js file. When you switch to the capability attribute interface, add the stunt and the code will not be pasted.
Https://github.com/lufylegend/lsharp/blob/3.7/Libraries/character/CharacterProperty.js
The final result is as follows:
Next, I encountered a small problem. I couldn't find a suitable image for the character's combat purposes. This time, I still used images in the form of "Cao Zhuan Chuan. To enable the previously created Character. js and Action. js can be used universally. I added attributes such as SRect, SWidth, and SHeight to the Character settings to distinguish the battlefield image from Character. js and Action. js settings.
In the plot, when displaying characters, in order to quickly display the game screen, each character's action is first pre-displayed with a static black image. After reading the corresponding picture, will switch to the read image, but to the combat image. Actions such as attacks and injuries are not coordinated if they are still images. Therefore, I have prepared the following set of images.
It corresponds to the following set of images
Then, you need to modify the Character. js and Action. js files according to the settings in the Character setting file. The Code is as follows.
Https://github.com/lufylegend/lsharp/blob/3.7/Libraries/character/Character.js
Https://github.com/lufylegend/lsharp/blob/3.7/Libraries/character/Action.js
Next, enter the battlefield, and prepare the controllers, models, and views.
Https://github.com/lufylegend/lsharp/blob/3.7/Controllers/BattlemapController.js
Https://github.com/lufylegend/lsharp/blob/3.7/Models/BattlemapModel.js
Https://github.com/lufylegend/lsharp/blob/3.7/Views/BattlemapView.js
Let's take a look at it and explain it a little bit.
Controller
BattlemapController.prototype.construct=function(){var self = this;LMvc.keepLoading(true);self.dataLoad();};BattlemapController.prototype.dataLoad = function(){var self = this;self.model.dataLoad(self.outcomeLoad);};
Model
BattlemapModel. prototype. dataLoad = function (callback) {var self = this; // start to read the battlefield map file var urlloader = new LURLLoader (); urlloader. parent = self; urlloader. addEventListener (LEvent. COMPLETE, function (event) {self. data = JSON.parse(event.tar get. data); callback. apply (self. controller, []) ;}); urlloader. load (". /script/battles/S "+ LRPGObject. battleIndex + ". ls "+ (LGlobal. traceDebug? ("? "+ (New Date (). getTime ():" ")," text ");};
This part reads the battlefield configuration file and saves it to the model.
The configuration file is as follows:
{"enemys":[{"index":3,"lv":"1"},{"index":4,"lv":"1"}],"win":{"exp":1234,"money":1000}}
Enemys indicates the enemy's combatants, and win indicates the rewards obtained after the victory of the battle.
Continue reading, Controller
BattlemapController.prototype.outcomeLoad = function(){var self = this;self.model.outcomeLoad(self.imagesLoad);};
Model
BattlemapModel.prototype.outcomeLoad=function(callback){var self = this,i,self_arms,enemy_arms,characterData,member,obj;self.load_effect = [];self.arms = [];self.actions = [];self.self_arms = [];self.enemy_arms = [];var self_arms_coordinate = [{"x":200,"y":240},{"x":100,"y":140},{"x":100,"y":340},{"x":300,"y":140},{"x":300,"y":340}];for(i=0;i<LRPGObject.memberList.length;i++){obj = {"chara":LRPGObject.memberList[i],"action":"stand","direction":"right","coordinate":self_arms_coordinate[i],"hert":0,"self":true};self.arms.push(obj);self.self_arms.push(obj);}self_arms_coordinate = [{"x":600,"y":240},{"x":500,"y":140},{"x":500,"y":340},{"x":700,"y":140},{"x":700,"y":340}];for(i=0;i<self.data.enemys.length;i++){characterData = LMvc.datalist["chara"]["peo"+self.data.enemys[i]["index"]];member = new MemberData(characterData,self.data.enemys[i]["lv"]);obj = {"chara":member,"action":"stand","direction":"left","coordinate":self_arms_coordinate[i],"hert":0,"self":false};self.arms.push(obj);self.enemy_arms.push(obj);}self.arms.sort(function(a,b){return b.chara.morale() - a.chara.morale();}); var result = false;i=0;while(!result){result = self._battleLoop();i++;}self.actions.push({"type":"over","result":LGlobal.script.scriptArray.varList["OutcomeBattle"]});callback.apply(self.controller,[]);};
This is the focus at the beginning. This is the calculation process of automatic combat. First, we will obtain our combatants and enemy combatants, among which our combatants will obtain from our team, stored in the array according to certain coordinates. In actual browser games, there are usually complex operations such as arrays. At this time, the coordinates here are determined by the arrays, I omitted the array and other settings, and directly prepared a coordinate group.
After saving the participants to the array, call the self. _ battleLoop function to loop the personnel in the Array Based on the character's speed and decide whether to use special effects or other actions. Here I take the character's morale attribute as a speed.
The following describes how to perform automatic combat.
BattlemapModel. prototype. _ battleLoop = function () {var self = this, I, j; for (I = 0; I <self. arms. length; I ++) {var data = self. arms [I]; var chara = data. chara; if (data. hert> chara. hp () continue; var skill = chara. skill (); var count = 1; var targets = []; var addition = 1; if (skill) {var skillData = LMvc. datalist ["skill"] ["skill" + chara. skill ()]; if (skillData & Math. random () <(skillData. probability/100) {var isAddEff Ect = false; for (j = 0; j <self. load_cmdt.length; j ++) {if (self. load_effect [j] = skillData. effect) {isAddEffect = true; break ;}} if (! IsAddEffect) self. load_cmdt.push (skillData. effect); self. actions. push ({"type": "effect", "effect": skillData. effect, "charaIndex": chara. index ()}); if (skillData. type = 1) {var mytargets = self. _ getTargets (data. self, skillData. count); self. actions. push ({"type": "addHp", "chara": []}); for (j = 0; j <mytargets. length; j ++) {mytargets [j]. hert-= skillData. HP; if (mytargets [j]. hert <0) mytargets [j]. hert = 0; self. actions [se Lf. actions. length-1]. chara. push ({"index": mytargets [j]. chara. index (), "num": skillData. HP});}/* self. actions. push ({"type": "action", "chara": []}); for (j = 0; j> mytargets. length; j ++) {self. actions [self. actions. length-1]. chara. push ({"index": mytargets [j]. chara. index (), "action": "stand"});} */} else if (skillData. type = 0) {addition = skillData. addition/100; count = skillData. count ;}} self. actions. push ({"type":" Ction "," chara ": [{" index ": chara. index (), "action": "attack"}]}); var dielist = []; var hertlist = []; var standlist = []; targets = self. _ getTargets (! Data. self, count); for (j = 0; j <targets. length; j ++) {var num = self. _ getHertValue (chara, targets [j]. chara) * addition >>> 0; hertlist. push ({"index": targets [j]. chara. index (), "action": "hert", "num": num}); standlist. push ({"index": targets [j]. chara. index (), "action": "stand", "num": num}); // self. actions [self. actions. length-1]. chara. push ({"index": targets [j]. chara. index (), "action": "hert", "num": num}); targets [j]. hert + = num; if (targets [j]. hert> = targets [j]. chara. hp () {dielist. push ({"index": targets [j]. chara. index ()}) ;}} self. actions. push ({"type": "action", "chara": hertlist}); self. actions. push ({"type": "action", "chara": [{"index": chara. index (), "action": "stand"}]}); self. actions. push ({"type": "action", "chara": standlist}); if (dielist. length> 0) {self. actions. push ({"type": "die", "chara": dielist});} if (self. _ getOutcome (data. self) {return true ;}} return false ;};/* calculate the attack damage value */BattlemapModel. prototype. _ getHertValue = function (attChara, hertChara) {var r; // obtain the attacker's attack strength and grade var attLv = attChara. lv (); var attAttack = attChara. attack (); // obtain the defender's defensive strength var hertDefense = hertChara. defense (); // calculate the attack damage value if (attAttack> hertDefense) {r = attLv + 25 + (attAttack-hertDefense)/2 ;} else {r = attLv + 25-(hertDefense-attAttack)/2;} if (r <1) r = 1; r = (110-Math.random () * 20) * r/100) >>> 0; if (r <1) r = 1; return r ;}; BattlemapModel. prototype. _ getTargets = function (value, count) {var self = this, arms, I, result = []; if (value) {arms = self. self_arms;} else {arms = self. enemy_arms;} for (I = 0; I <arms. length; I ++) {if (arms [I]. hert> arms [I]. chara. hp () continue; result. push (arms [I]);} result. sort (function (a, B) {return Math. random ()> 0.5;}); return result. slice (0, count) ;}; BattlemapModel. prototype. _ getOutcome = function (value) {var self = this, arms, I, result = []; if (value) {arms = self. enemy_arms;} else {arms = self. self_arms;} for (I = 0; I <arms. length; I ++) {if (arms [I]. hert> arms [I]. chara. hp () continue; return false;} if (value) {LGlobal. script. scriptArray. varList ["OutcomeBattle"] = 1;} else {LGlobal. script. scriptArray. varList ["OutcomeBattle"] = 0;} return true ;};
Because I used the outcomeLoad Function
while(!result){result = self._battleLoop();i++;}
Therefore, when self. _ battleLoop returns false, the loop continues until true is returned, indicating that the battle is over.
When repeating each character, first determine whether the character has been killed, as shown below:
if(data.hert > chara.hp())continue;
If the attack is not killed, the person starts the attack and determines whether to launch a stunt attack before the attack. Therefore, the person first gets the stunt.
var skill = chara.skill();
Then judge whether the stunt is launched.
if(skill){var skillData = LMvc.datalist["skill"]["skill"+chara.skill()];if(skillData && Math.random() < (skillData.Probability/100)){......}}
After each attack is complete, use _ getOutcome to determine whether all the people in the target camp are killed, so as to determine whether the battle is over,
if(self._getOutcome(data.self)){return true;}
Take a closer look at the code in _ battleLoop. You will find that every operation instruction is saved to the actions array, and each instruction has
"action","addHp","effect","die","over"
You can also think of these commands as a script. When the combat animation is finally displayed, these commands are parsed in the Controller to convert them into animations.
After the automatic Combat Command is generated, the Controller reads other corresponding files and calls the view to display the screen.
After the battle starts, the Controller begins to parse the combat commands saved in the model.
BattlemapController.prototype.checkAction=function(){var self = this;var action = self.model.getAction();if(action){switch(action.type){case "action":self.runAction(action);break;case "addHp":self.runAddHp(action);break;case "effect":self.runEffect(action);break;case "die":self.runDie(action);break;case "over":self.battleOver(action.result);break;}}};
Action indicates that the action changes, addHp indicates adding blood, effect indicates a stunt animation, die indicates that the military is killed, and over indicates that the combat is over.
For detailed analysis of each instruction, check the following code.
Https://github.com/lufylegend/lsharp/blob/3.7/Controllers/BattlemapController.js
This is basically the case for automatic combat. The following shows how to enter the battle screen.
Prepare the following script.
Function characterclick3 (); if (@ task1010 = 1); RPGTalk. set (3, 0, is Guan Yu's service okay ?); Else; RPGTalk. set (1, 0, young man, can you help me pick up soap ?); RPGTalk. set (3, 0, are you entertaining me ?); RPGTalk. set (1, 0, yes, young man, can you help me pick up soap ?); RPGTalk. set (3, 0. If you can win me, I will ask Guan Yu to help you pick up soap .); RPGTalk. set (, let's get started !); // Enter the battle. The parameter battle configuration file No. RPGBattle. start (1); if (@ OutcomeBattle = 1); RPGTalk. set (3, 0, beat me, then Guan Yu will be with you .); RPGTalk. set (2, 0. It's a cat. What is it about me !?); RPGMember. add (2); Var. set (task1010, 1); RPGMessageBox. show (Guan Yu joins the team .); Else; RPGTalk. set (3, 0, you can help me pick up soap .); RPGTalk. set (1, 0, this...); endif; endfunction;
This is a process of finding the foundation of Liu Bei. You can see the expected combat screen. You only need the following script.
// Enter the battle. The parameter battle configuration file No. RPGBattle. start (1 );
The parsing part of the script is as follows:
LRPGBattleScript = function(){};LRPGBattleScript.analysis=function(value){var start = value.indexOf("(");var end = value.indexOf(")");switch(value.substr(0,start)){case "RPGBattle.start":var params = value.substring(start+1,end).split(",");LRPGObject.RPGMap.showBattle.apply(LRPGObject.RPGMap,params);break;default:LGlobal.script.analysis();}};
In other words, the combat system is very important. Here is just a demonstration of one of the methods. Let's talk about it later.
Okay. Let's take a look at Liu Bei and test the link.
Http://lufylegend.com/demo/test/lsharp/rpg-lsharp-07/index.html
Finally, download the Code:
Https://github.com/lufylegend/lsharp/archive/3.7.zip
Notice: The next section will return to the plot section and show you how to use the scripts to control the characters in the picture freely. This is a prerequisite for the task system.
Game script design and development articles
Http://blog.csdn.net/lufy_legend/article/details/8888787
This chapter is here. Welcome to continue to follow my blog
Reprinted Please note: