简客-记忆

抽象的才是永恒的

0%

源码的安装一般由3个步骤组成:配置(configure)、编译(make)、安装(make install)。

Configure是一个可执行脚本,它有很多选项,在待安装的源码路径下使用命令./configure –help输出详细的选项列表。

其中–prefix选项是配置安装的路径,如果不配置该选项,安装后可执行文件默认放在/usr/local/bin,库文件默认放在/usr/local/lib,配置文件默认放在/usr/local/etc,其它的资源文件放在/usr/local/share,比较凌乱。

如果配置–prefix,如:

1
./configure --prefix=/usr/local/test

可以把所有资源文件放在/usr/local/test的路径中,不会杂乱。

1
2
3
4
5
./configure --prefix=/usr/local/test
make 编译(时间有点久)
make check 检测编译(时间有点久,一般可不选)
sudo make install 安装
xxx —version 检测是否安装成功

用了—prefix选项的另一个好处是卸载软件或移植软件。当某个安装的软件不再需要时,只须简单的删除该安装目录,就可以把软件卸载得干干净净;移植软件只需拷贝整个目录到另外一个机器即可(相同的操作系统)。

当然要卸载程序,也可以在原来的make目录下用一次make uninstall,但前提是make文件指定过uninstall。

make check 效果(以protocol为例)

wer

过程图

WechatIMG929

duoji

注意点

  • 1、当arduino的软件打开时,无法同时使用https://ide.makeblock.com里的连接设备

说明

之前使用的是别人的框架,里面一些东西都帮你“框”好了,没法增进自己对cocos框架的了解,也不利于cocos框架的升级

自己重新按照官方文档写游戏,当随着游戏复杂度的提升,一些规范需要得到约定,方便后续的拓展和维护。

面向事件开发

目前游戏的整个机制已 “面向事件开发”为主。

    graph LR

    仙剑出鞘游戏--> 事件总线G

    事件总线G-->  场景1-服务器选择
    事件总线G-->  场景2-玩家基地界面
    事件总线G-->  场景3-游戏操作界面

    场景1-服务器选择 -->  ...
    场景2-玩家基地界面 -->  ....

    场景3-游戏操作界面 -->  游戏逻辑-gameLogic
    场景3-游戏操作界面 -->  background
    游戏逻辑-gameLogic -->  GameHUD

    游戏逻辑-gameLogic -->  飞剑管理-flyingswordController

    游戏逻辑-gameLogic -->  敌方管理-enemyController

    飞剑管理-flyingswordController --> 飞剑-flyingsword
    飞剑管理-flyingswordController --> 辅助准心-supportCross
    飞剑管理-flyingswordController --> 剑法-swordmagic

    敌方管理-enemyController --> 敌方单位-enemyItem

    GameHUD --> 头像ui
    GameHUD --> 金币ui
    GameHUD --> 体力ui

说明

之前的剑阵盘的设计,主要是飞剑碰到剑阵节点,后反弹。
目前来说反弹操作,主要有以下几个缺点:

  • 1、操作上会让玩家时刻绷紧神经,不利于休闲游戏。
  • 2、看上去有点像乒乓球,不符合游戏审美
  • 3、每次加快飞剑速度,只会增加玩家负担

采用回旋设计的好处:

  • 1、操作上有一个时间缓存,适合休闲操作
  • 2、回旋操作,类似控制飞剑的调整操作,符合审美
  • 3、可改变每次的飞剑速度,可增加飞剑属性的多样化

主要代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
<?php

namespace App\HttpController\Common\Logic;

use EasySwoole\ORM\AbstractModel;
// use EasySwoole\Http\Request;
class BaseLogic extends AbstractModel
{
// 操作状态
const MODEL_INSERT = 1; // 插入模型数据
const MODEL_UPDATE = 2; // 更新模型数据
const MODEL_BOTH = 3; // 包含上面两种方式
const MUST_VALIDATE = 1; // 必须验证
const EXISTS_VALIDATE = 0; // 表单存在字段则验证
const VALUE_VALIDATE = 2; // 表单值不为空则验证

public $data = [];
public $old_data = []; // public才会根据协程清除
public $tmp_data = []; // public才会根据协程清除
public $request_user = [];
public $request_user_id = 0;

public $patchValidate = false; // 是否批处理验证

public $handle_sence;
public $scene_id; // 未兼容老版本,此字段与handle_sence相同

protected $handle_field_arr = [];
protected $handle_logs = [];
protected $cur_sence_field;
protected $allow_fields;
protected $db_allow_fields;

//修改插入后自动完成
protected $logic_auto = array();
protected $logic_validate = array();

public function init($request){
$this->request_user = $request->getAttribute('request_user');
$this->request_user_id = (int)$this->request_user['id'];
return $this;
}

public function request_user_id(){
return $this->request_user_id;
}

public function getRequestUser(){
return $this->request_user;
}

public function getError(){
return $this->error;
}

public function getSaveData(){
return $this->data;
}

public function getOldData(){
return $this->old_data;
}

public function run($post_data,$handle_sence){
$this->data = null;
$this->data = $post_data;
$this->handle_sence = $handle_sence;
$this->scene_id = $handle_sence;
$cur_sence_field = $this->handle_field_arr[$handle_sence];
if(trim($cur_sence_field) == "*"){
$this->db_allow_fields = array_keys($this->schemaInfo()->getColumns());
$this->allow_fields = $this->db_allow_fields;
}else{
$this->db_allow_fields = array_keys($this->schemaInfo()->getColumns());
$this->allow_fields = array_filter(explode(",",$cur_sence_field));
foreach ($this->data as $key => $value) {
if(!in_array($key,$this->allow_fields)){
unset($this->data[$key]);
unset($post_data[$key]);
}
}
}
// 数据自动验证-前
if(!$this->_beforeAutoValidation($post_data,$handle_sence)) return false;
// 数据自动验证
if(!$this->_autoValidation($post_data,$handle_sence)) return false;
// 数据自动验证-后
if(!$this->_afterAutoValidation($post_data,$handle_sence)) return false;
// 创建完成对数据进行自动处理
$this->_logic_auto_fill($post_data);

if(count($this->data) == 0){
$this->error = "无修改内容项";
return false;
}
return true;
}

protected function _autoValidation($data, $handle_sence){
// 属性验证
if(isset($this->logic_validate)) { // 如果设置了数据自动验证则进行数据验证
if($this->patchValidate) { // 重置验证错误信息
$this->error = array();
}
foreach($this->logic_validate as $key=>$val) {
// 验证因子定义格式
// array(field,rule,message,condition,type,when,params)
// 判断是否需要执行验证
if(empty($val[5]) || ( $val[5]== self::MODEL_BOTH && $handle_sence < 3 ) || $val[5]== $handle_sence ) {
if(0==strpos($val[2],'{%') && strpos($val[2],'}'))
// 支持提示信息的多语言 使用 {%语言定义} 方式
$val[2] = L(substr($val[2],2,-1));
$val[3] = isset($val[3])?$val[3]:self::EXISTS_VALIDATE;
$val[4] = isset($val[4])?$val[4]:'regex';
// 判断验证条件
switch($val[3]) {
case self::MUST_VALIDATE: // 必须验证 不管表单是否有设置该字段
if(false === $this->_validationField($data,$val))
return false;
break;
case self::VALUE_VALIDATE: // 值不为空的时候才验证
if('' != trim($data[$val[0]]))
if(false === $this->_validationField($data,$val))
return false;
break;
default: // 默认表单存在该字段就验证
if(isset($data[$val[0]]))
if(false === $this->_validationField($data,$val))
return false;
}
}
}
// 批量验证的时候最后返回错误
if(!empty($this->error)) return false;
}
return true;
}

/**
* 验证表单字段 支持批量验证
* 如果批量验证返回错误的数组信息
* @access protected
* @param array $data 创建数据
* @param array $val 验证因子
* @return boolean
*/
protected function _validationField($data,$val) {
if($this->patchValidate && isset($this->error[$val[0]]))
return ; //当前字段已经有规则验证没有通过
if(false === $this->_validationFieldItem($data,$val)){
if($this->patchValidate) {
$this->error[$val[0]] = $val[2];
}else{
$this->error = $val[2];
return false;
}
}
return ;
}

/**
* 根据验证因子验证字段
* @access protected
* @param array $data 创建数据
* @param array $val 验证因子
* @return boolean
*/
protected function _validationFieldItem($data,$val) {
if(!isset($data[$val[0]])){
$this->error = "缺少必要的提交字段:".$val[0];
return;
}
if(false === $data[$val[0]] ) unset($data[$val[0]]);
switch(strtolower(trim($val[4]))) {
case 'function':// 使用函数进行验证
case 'callback':// 调用方法进行验证
$args = isset($val[6])?(array)$val[6]:array();
if(is_string($val[0]) && strpos($val[0], ','))
$val[0] = explode(',', $val[0]);
if(is_array($val[0])){
// 支持多个字段验证
foreach($val[0] as $field)
$_data[$field] = $data[$field];
array_unshift($args, $_data);
}else{
array_unshift($args, $data[$val[0]]);
}
if('function'==$val[4]) {
return call_user_func_array($val[1], $args);
}else{
return call_user_func_array(array(&$this, $val[1]), $args);
}
default: // 检查附加规则
return false;
}
}

protected function _beforeAutoValidation($data, $handle_sence){
// 因为像orderdetail常在foreach中添加,故此处最好有个初始化。(如特殊情况不需要的,请复写该方法)
$this->tmp_data = null;
$this->old_data = null;
$this->error = null;
return true;
}

protected function _afterAutoValidation($data, $handle_sence) {
if(defined('IS_DEMO') && IS_DEMO == true){
$this->error = "当前系统为演示demo系统,无法进行增删改";
return false;
}
return true;
}

private function _logic_auto_fill($data){
if(isset($this->logic_auto)) {
foreach ($this->logic_auto as $auto){
if($auto[2] == $this->handle_sence){
if(empty($auto[3])) $auto[3] = 'string';
switch(trim($auto[3])) {
case 'function': // 使用函数进行填充 字段的值作为参数
case 'callback': // 使用回调方法
$args = isset($auto[4])?(array)$auto[4]:array();
if(isset($data[$auto[0]])) {
array_unshift($args,$data[$auto[0]]);
}
if('function'==$auto[3]) {
if($auto[1] == 'time'){
// 部分函数不需要 参数
$data[$auto[0]] = call_user_func_array($auto[1],[]);
}else{
$data[$auto[0]] = call_user_func_array($auto[1], $args);
}
}else{
$data[$auto[0]] = call_user_func_array(array(&$this,$auto[1]), $args);
}
break;
case 'string':
default: // 默认作为字符串填充
$data[$auto[0]] = $auto[1];
}
if(isset($data[$auto[0]]) && false === $data[$auto[0]] ) unset($data[$auto[0]]);

if(isset($data[$auto[0]])){
if(in_array($auto[0],$this->db_allow_fields)){
$this->data[$auto[0]] = $data[$auto[0]];
}
}
}
}
}
}
}

主要代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

public setCurLevel(cur_level){
this.cur_level = cur_level
console.log('setCurLevel'+this.cur_level)
}

public getCurLevel(){
return this.cur_level;
}

public getAllMissionData(){
let alldata = [
{
mission:1,
mission_name:'新手大陆',
is_open:1,
is_pass:1,
data:[
{
level:1,
is_open:1,
is_pass:1,
step:1,
x:110,
y:22,
},
{
level:2,
is_open:1,
is_pass:1,
step:2,
x:220,
y:33,
},
]
},
{
mission:2,
mission_name:'老手大陆',
is_open:1,
is_pass:1,
data:[
{
level:11,
is_open:1,
is_pass:1,
step:1,
},
{
level:12,
is_open:1,
is_pass:1,
step:2,
},
]
}
]
return alldata
}

public getCurMissionData(mission){
let alldata = this.getAllMissionData()
let data : mission
alldata.forEach( (item) => {
if(item.mission == mission){
data = item
}
} )
console.log('getCurMissionData')
console.log(data)
return data
}



public getMissionLevelData(){
let alldata = [
{
level:1,
data:[
{
x:11,
y:22,
type:'box',
hp:1
},
{
x:22,
y:33,
type:'box',
hp:1
}
]
}
]
return alldata
}

public getCurMissionLevelData(level){
let alldata = this.getMissionLevelData()
let data = {}
alldata.forEach( (item) => {
if(item.level == level){
data = item
}
} )
console.log('getCurMissionLevelData')
console.log(data)
}

主要涉及的cocos函数

暂无

主要代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { G } from "../G";

const {ccclass, property} = cc._decorator;

@ccclass
export default class uiController extends cc.Component {

@property(cc.Label)
label: cc.Label = null;

@property
text: string = 'hello';


@property({type:cc.Node,tooltip:"mission1"})
mission1: cc.Node = null;

@property({type:cc.Node,tooltip:"mission2"})
mission2: cc.Node = null;

@property({type:cc.Node,tooltip:"返回到大地图"})
backMap: cc.Node = null;

@property({type:cc.Node,tooltip:"返回Home"})
backHome: cc.Node = null;

@property({type:cc.Node,tooltip:"世界地图"})
allMissionMap: cc.Node = null;

@property({type:cc.Node,tooltip:"当前地图"})
curMissionMap: cc.Node = null;

@property({type:cc.Node,tooltip:"levelContent"})
levelContent: cc.Node = null;

@property({type:cc.Prefab,tooltip:"关卡"})
levelItemPref: cc.Prefab = null;

// LIFE-CYCLE CALLBACKS:

// onLoad () {}
init(){
G.getAllMissionData()
}

start () {
this.mission1.on(cc.Node.EventType.TOUCH_END,this.mission1_touch,this)
this.mission2.on(cc.Node.EventType.TOUCH_END,this.mission2_touch,this)
this.backMap.on(cc.Node.EventType.TOUCH_END,this.backMapTouch,this)
this.backHome.on(cc.Node.EventType.TOUCH_END,this.backHomeTouch,this)

let cur_mission_val = 1;
this.goUserMission(cur_mission_val)

}

goUserMission(cur_mission_val){
// 显示当前地图的节点
this.curMissionMap.active = true
// this.curMissionMap.scale = 1.5; // todo 修改背景图就可以
// 隐藏世界地图
this.allMissionMap.active = false


this.addLevelToList(cur_mission_val)
}
addLevelToList(cur_mission_val){
this.levelContent.removeAllChildren()

let missionData :mission = G.getCurMissionData(cur_mission_val)
this.curMissionMap.getChildByName('mission_name_label').getComponent(cc.Label).string = missionData.mission_name
missionData.data.forEach( (item,index) => {
let newLevel = cc.instantiate(this.levelItemPref);
let level_obj = newLevel.getComponent('mission_level')
level_obj.level = item.level
newLevel.y = -20*(index+1)
newLevel.getComponent(cc.Label).string = "第"+(item.level)+'关'
this.levelContent.addChild(newLevel)
})
}

mission1_touch(){
this.goUserMission(1)
}

mission2_touch(){
this.goUserMission(2)
}

backMapTouch(){
// 隐藏当前地图的节点
this.curMissionMap.active = false
this.curMissionMap.scale = 1; // todo 修改背景图就可以
// 显示世界地图
this.allMissionMap.active = true
}
backHomeTouch(){
G.goHome()
}

// update (dt) {}
}

主要涉及的cocos函数

1、this.node.getChildByName

在子节点中查找相应名称的节点

2、cc.instantiate

克隆指定的任意类型的对象,或者从 Prefab 实例化出新节点。

3、this.node.addChild

添加子节点

4、this.node.removeAllChildren

移除所有子节点

主要代码

在飞剑飞完后判断

1
2
3
4
5
6
7
8
9
10
11
12
13

isGameOver(){
this.mFeiJian.getComponent("feijian").is_flying = false
if(this.gameData.guaiwu_num <= 0){
this.gameController.emit('game__win__thislevel')
return
}
if(this.gameData.remain_num <= 0 ){
this.gameController.emit('game__loss__thislevel')
return
}

}

主要涉及的cocos函数

无新函数