forked from bubububaoshe/bubububaoshe.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
note.txt
612 lines (514 loc) · 28.7 KB
/
note.txt
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
setting for a pack:
26 cards
6-7 cards per season
try event delegation
destroy: remove controllers
当前进度:
未完成:特殊牌选择/存储
1. 存储内容:
[玩家的特殊牌库] USER_SPECIAL_REPO : qqxspecials
[玩家的上轮特殊牌选择] model.player1.specialIDs : qqxspecialpicks
不存储的内容:
对方的特殊牌库和特殊牌选择
对方为AI时,根据设置和玩家的选择随机选择正确的特殊牌
2. 特殊牌选择原则:
[同一玩家不可选择同名特殊牌]
[不同玩家可选择同名特殊牌]
[不同玩家可选择同id特殊牌]
也就是说玩家选择特殊牌是独立的
AI特殊牌处理:
根据设置随机产生AI特殊牌
算简化的处理,但我也很想做成三国杀3v3选将那样啊。。。
那么目前来说,让玩家选择自己的特殊牌就好了。
[记得处理的小问题:infobanner gradient not working on ios safari]
当前进度:
完成:[特殊牌][程序逻辑整理]
未完成:[卡牌信息][特殊牌发放][特殊牌存储][特殊牌选择]
卡牌信息先做吧:
3个可能位置:
考虑到可能重用,每个部分都搞一个function生成对应的div
1. 主界面(done)
hand1, pool, hand0.faceup
右侧 hoverinfobox 那个位置
显示内容:[名字:基础分]/[可形成组合的卡牌](即使是特殊牌也只显示这些)
2. 特殊牌仓库界面
左侧整条
显示内容:[名字*后缀]/[角色尬诗]/[技能]*n
3. 明牌堆界面
右侧整条
显示内容:
特殊牌:同上
普通牌:[名字]/[角色尬诗]/[可组队卡牌] (然而普通牌的角色尬诗我没录。。。)
附加:
明牌界面:
已禁用卡牌黑化(disabled, swapped&noswap)
已失效技能标注(disabled)
尽量用hover/active完成,不要再listener了。。。
特殊牌:
id:普通角色名首字母+游戏代数+字母
e.g.,如果存在3张沈夜特殊牌,则分别为sy2a,sy2b,sy2c
假设:
1.swaptrick, copytrick交换后必然无效。(否则可能死循环)
这两个技能自带交换后无效技能
1.1 swaptrick没有除“交换后无效”之外的其它功能
2.copytrick,unnamedbantrick只触发一次。(即使在触发时无可作用对象)
2.1 但namedbantrick永远锁定对方XDD
3.copytrick不能copy copytrick哈哈。
哈哈哈错了,copy才应该是最早用的,因为copy可能引发其他任何技能。给除copy以外的技能搞一个clone吧。
obtain整体流程
preObtain: copy?/swap? (一旦引发从头preobtain)
inObtain:
model.obtain
(次序分先后因为这里被ban是namedban不会引发reveal了)
ban
user reveal?(flip card)
view.obtain: actions, combos
postObtain:
deal
end or next obtain
(info banner disappear upon user clicks)
当前进度:
[基本完成特殊牌功能][未实现复制特殊牌和禁用]
来做禁用[BanTrick]!跟SwapTrick差不多啦!跟CopyTrick更像~
BanTrick:
禁用对象仅限对方已入手的珍稀牌
可禁用的技能:ComboTrick, CharTrick
不可禁用的技能:RevealTrick, DealTrick, SwapTrick, NoswapTrick(noswap = true)
两类:
[a]无指定对象:理解为可以选定禁用角色,理解为只在第一次入手时触发(交换重新入手不触发)
获得后[addTableChar完成后]后触发,选择禁用对象(如有),最终会导致对方recalculate。禁用对方后禁用自己的这个技能。
处理序列:model.obtain -> controller.selectBan -> model.banChar -> player.recalculate
[b]指定对象:理解为只禁用对方角色
对方获得对应卡牌时触发,获得时即禁用,不会导致recalculate
处理序列:player.addChar -> char.disable (意外的简单)
-由于两种机制完全不一样,所以实现为两个Class: UnnamedBanTrick, NamedBanTrick(name)
-卡牌列表里需要加入新的状态:已禁用
禁用的两种可能:
-[交换后技能无效]的角色被交换
-被BanTrick禁用
CopyTrick:
就算它可以选定禁用角色吧,全技能可复制。
测试角色:艄公,
------------------------------------------
-基本数据结构
-嵌入游戏
-完善数据结构
-技能处理
-存取卡牌信息
-扩展技能
技能实现序列:
[翻牌][影响发牌][组合加分][友方角色加分][换牌][换牌后无效]
未实现:
[禁用][复制]
特殊牌库:全局
玩家特殊牌:cookie存储
----------------------------------------------------------------------
* 一阶段支持的技能种类:
[计分作用类]
组合加分
卡牌加分
[即时作用类]
翻牌
影响发牌
* 二阶段支持的技能种类:
交换牌、交换后技能无效
* 暂不支持的技能种类:
禁用珍稀牌(游戏里看起来没实现嘛)
----------------------------------------------------------------------
沈夜*紫微 : sy2a
天命难解此中局,神血护佑心魔曲。
4分
1. 下一回合一定出现一个流月城角色
2. 随机翻开对手手牌两张
----------------------------------------------------------------------
悭臾*水虺 : qy1a
榣山水湄遇长琴,通天彻地为知音。
4分
1. 自身能组成的组合每个增加10分
2. 随机翻开对手手牌一张
----------------------------------------------------------------------
百里屠苏*黑猫 : blts1b
眼底无故人,世事冷如铁。谁与长相约,眉间刺新血。
6分
1.若古剑焚寂在公共卡池中,则下一回合一定出现古剑焚寂。
2.桃花幻梦的分数增加30分。
----------------------------------------------------------------------
风晴雪*凤曦 : fqx1a
好向寒节报花信,春风一脉动幽都。
4分
1. 百里屠苏的分数增加15分。
----------------------------------------------------------------------
闻人羽*天罡 : wry2b
天罡夜枕绿沉枪,\n敌血尚温金甲凉。
6分
1.蓝衫偃师记 + 30
2.被交换后卡牌技能无效。
----------------------------------------------------------------------
乐无异*偃师 : ywy2b
金刚力士舞灵木,\n墨意非攻定乾坤。
6分
1.随机翻开对手手牌三张
2.被交换后卡牌技能无效。
----------------------------------------------------------------------
夏夷则*太华 : xyz2a
江山倦夜眠孤客,\n红堕沾衣冷血痕。
4分
1.蓝衫偃师记 + 20
----------------------------------------------------------------------
沈曦*魔化 : sx2a
稚童新衫犹未裁,\n一点红痕一世哀。
4分
1. 翻牌 2
----------------------------------------------------------------------
谢衣*初七 : xy2a
霜刃初试驱长夜,\n破云开天相决绝。
4分
1. 烈山遗族 + 20
2. 翻牌 1
----------------------------------------------------------------------
陵越*掌门 : ly1a
任侠为道守仙门,\n见素抱朴未忘沉。
4分
1. 交换对方任意一张牌。
2. 被交换后卡牌技能无效。
----------------------------------------------------------------------
华月*魔化 : hy2a
戾天狂歌琴声啸,\n朔雪为刃止喧嚣。
4分
1. 交换对方任意一张牌。
2. 被交换后卡牌技能无效。
----------------------------------------------------------------------
欧阳少恭*蓬莱 : oysg1a
偏有漏长惊永夜,\n梦魂又觉第几生。
4分
1. 禁用对方任意一张珍稀牌的技能
2. 芳华如梦 + 20
----------------------------------------------------------------------
夏夷则*鲛人 : xyz2b
沧海遗珠鲛人泪,\n遗骨托生帝王脉。
6分
1. 禁用对方任意一张珍稀牌的技能
2. 随机翻开对手手牌2张
----------------------------------------------------------------------
清和真人*温留 : qhzr2a
赤血丹心照夙昔,\n殊途与归执道心。
4分
1. 禁止夏夷则珍稀牌的技能
2. 温茶相待的分数增加30分
----------------------------------------------------------------------
红玉*道服 : hy1a
霜雪凝精神,\n桃花铸肌骨。\n还报一寸心,\n愿同尘与土。
4分
1. 复制对方任意一张珍稀牌的技能
2. 被交换后卡牌技能无效
----------------------------------------------------------------------
乐无异*捐毒 : ywy2a
长安年少重游侠,\n抱酒弹铗杏花阴。
4分
1. 复制对方任意一张珍稀牌的技能
2. 被交换后卡牌技能无效
不明觉厉的CSS Transition:
在js里调用clientWidth一定能触发transition(据说会令css reflow,有资源消耗)
游戏规则:
初始:
[选择特殊卡]
手牌10,卡池8
每人每轮:
重新洗牌直到任一季节卡牌小于5张
[a]判断是否可选:可选跳转[b];不可选跳转[c]
+[b]可选:
选牌,手牌-1,卡池-1
卡池补牌,卡池+1
结果:手牌-1, 卡池不变
+判断:手牌>0跳转[a],手牌为0,结束跳转[e]
+[c]不可选:
+判断:卡池<=9跳转[d],卡池=10,卡池重组:卡池8,跳转[a]
+[d]选牌入卡池,手牌-1,卡池+1
手牌补牌,手牌+1
结果:手牌不变,卡池+1,跳转[a]
[e]结束:计分
---------------------------------------
重构轻量级服务器计划
1 开局、选牌
2 非珍稀牌事件(洗牌等等)
每添加一件新事件时修改之处亦是跟随消息的流向:
a) 从当前玩家 -> 服务器 的 程序,通常是把card中的递归结构去掉,只留牌的ID
b) 服务器端收消息,进行最小的必要的状态记录,并发给另一玩家
c) 另一玩家收到后的处理
3 珍稀牌事件
这里可能比之前要更复杂一些
4 然后完成重新开局事件
5 玩家掉线后由AI接管?
现在在步骤2
---------------------------------------
是从model开始传递信息还是应该从controller开始传递信息?
从一个方面看,似乎model被重复利用的次数多些,但controller更接近“AI玩家的动作”,所以各有各的好
从另一个方面看,model中的一些事件会被被动触发,比如redeal,所以不得不从model中开始传消息
---------------------------------------
时间轴
【登陆服务器阶段】
玩家 服务器
设定头像与昵称 |
按下"连接" |
| |
| 连上了服务器 |
|------------------------>|
| |
| Info_OnlinePlayerCount |
| Info_MyPlayerId |
|<------------------------|
| |
| nickname, avataridx |
|------------------------>|
| |
现在就算是在线了 |
可以找人或是随机组队 |
【双方匹配阶段】
//TODO split server to middleware ( this ) & server ( CRUD backend, register server )
1. 玩家 ----> 服务器 'connect' 表示登陆;服务器会记下该玩家
2. 玩家 <---- 服务器 'Info_OnlinePlayerCount' 附带当前人数
'Info_MyPlayerId' 附带该玩家的ID(用于指定ID组人)
(2 可以接 3 或是接 5,看是想指定人组队还是随机组队)
3. 玩家1 ---> 服务器 'Match_ReadyToMatch' 表示开始匹配
玩家1 <--- 服务器 'Match_ReadyToMatchAck',提示玩家等待匹配
服务器这时会寻找同样开始匹配了的玩家
玩家1&2 <- 服务器 'Match_FoundMatch' 如果找到了的话就给两个玩家都传回这个
(3 接 4 或者当任一玩家取消匹配时,通知双方取消匹配,回到第 3 步开头)
4. 玩家1 ---> 服务器 'Match_ConfirmMatch' 表示确定匹配。谁先确定谁就是先手,不过也可以交换。
玩家2 <--- 服务器 'Match_OtherPlayerConfirmed' 服务器会通知玩家2按确定
玩家2 ---> 服务器 'Match_ConfirmMatch'
玩家1&2 <- 服务器 'Match_GameSetupDefensive & gameToken' 传给后手玩家
'Match_GameSetupOffensive & gameToken' 传给先手玩家
+----------------------------------------------------------+
| B |
+--------------+----------------------------------------------------------+
|A如何称呼B? | 服务器 服务器 自己 自己 |
| | 先手 后手 眼中的 眼中的 眼中的 眼中的 |
| | 自己 对方 自己 对方 |
+-------------------------------------------------------------------------+
| | 先手 | player1 player0 player1 player0 player1 player0|
| A | 后手 | player0 player1 player0 player1 player1 player0|
| | 服务器 | player1 player0 N/A N/A N/A N/A |
+-------------------------------------------------------------------------+
玩家侧的程序中以rank表示先后手(也就是服务器看玩家的编号),1为先手,0为后手。
5. 玩家1 ---> 服务器 'Match_InvitePlayer' 带欲组队的玩家ID
|
| 服务器会找一找有没有这个玩家
玩家1&2 <----+ 'Match_FoundMatch' 如果找到了的话就跳到4,视为“找到了匹配”
玩家1 <------+ 'Match_InvalidInvitation' 如果没找到就告知此ID对应的玩家不存在
(双方选择特殊牌阶段)
6. 先手玩家 ---> 服务器 'Match_SetupComplete' 带选好的特殊牌和发牌结果(先手玩家调用model.setup(),但是略过对方的特殊牌的view的初始化部分,后手先不调用)
后手玩家 ---> 服务器 'Match_SetupComplete' 带选好的特殊牌
当两名玩家都选好之后
先手玩家 <--- 服务器 'Match_GameInitOffensive' 带后手玩家所选的特殊牌
| 此时先手玩家要补全对方的特殊牌初始化部分,fixup
后手玩家 <------' 'Match_GameInitDefensive' 带先手玩家所选的特殊牌和发牌结果(snapshot)
此时后手玩家再调用与model.setup()相当的部分,但是用snapshot代替Deck.removeRandom()
然后后手玩家再调用对方的特殊牌的view的初始化部分,fixup
(对局结束结算后)
7. 先手玩家 & 后手玩家 ---> 服务器(CRUD) 发送对局结果与过程信息
(总共的Tricks类别)
ComboTrick 不影响对战模式 :悭臾、百里屠苏、欧阳少恭、
RevealTrick 不影响对战模式 :怪臾、
DealTrick 不影响对战模式 :百里屠苏、
CharTrick 不影响对战模式 :风晴雪、
SwapTrick 需要controller选择一个对象、作用于table :陵越、
UnnamedBanTrick 需要controller选择一个对象、作用于table :欧阳少恭、
CopyTrick 需要controller选择一个对象、作用于table :红玉、
(开局时的牌桌状态同步)
先手玩家 后手玩家
按"开始游戏" |
发牌 |
| |
|送出发好的牌池 |
|已方的合并了特殊牌的手牌 |送出己方的特殊牌的选择
|已方的特殊牌选择 |
|(因为合并在player.init中做了)|
| |
`-------. .-----------------'
| |
| |
| |
V V
+--------------------+
|"双方都选好了特殊牌"|
| 的barrier |
+--------------------+
| |
.-------' `--------.
| |
| |
V V
Player0 Player0
Special Special
Fixup Fixup
这个是view的修补 这个也是view的修补
(每一回合的过程)
【 回 合 开 始 】
+--------+ +----------+ +--------+
|当前玩家| |服务器消息| |对方玩家|
+--------+ +----------+ +--------+
| | |
| | |
|"[第X回合]该你出牌了" | "[第X回合]对方出牌"|
|<-------------------------+-------------------------------->|
| |
v 等待|
controller.obtain() 对方|
| 行动|
| |
| 有可能触发一些特殊牌的技能 |
| 选择会开新线程需要与主线程同步 |
| |
+--> controller.selectCopy()-. |
| | |
| | 按顺序记下所做出的选择 |
+--> controller.selectBan()--+ 在barrier之后一起发给对方 |
| | |
| | |
+--> controller.selectSwap()-+ |
| | |
| .--------------------------' |
,' | |
| V |
[--+---+---当前玩家的Barrier-----] |
| | 此回合中的入手、选择特殊牌目标信息|
`, `--------------------------------------------------------->|
| |
. . .|. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | .
. | | .
. | 此处可能有组合获得的动画。 | .
. | | .
. . .|. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | .
| |
| |
controller.postObtain() |
| |
V |
model.dealOne() |
| | |
| | |
| | 发出的牌的ID|此时
| `-------------------------------------------------------->|才可
| * * * * * * * * * * * |行动=unblock
| * 对方看到的obtain、 * |
如果同一季节超过6张 * dealOne和redeal * |
则洗牌redeal * 都是按顺序的 * |
| | * 因为websocket是TCP * |
| | * * * * * * * * * * * 洗牌后的公共牌池|
| `-------------------------------------------------------->|
| |
checkMatch1() |
| |
`------. ,------------------------------------------------'
| |
| | 服务器看到当前玩家的dealOne和
| | 对方的opponentObtain都完成后才宣告
| ,' 回合结束
V |
[--------+------------------服务器上的Barrier-----------------]
`.
| 【 下 一 回 合 开 始 】
|
,-----------+------------------------------------------------.
| |
| |
| V
"[第X回合]对方出牌" "[第X回合]该你出牌了"
| |
| |
| V
| 从controller.obtain()
| 开始循环往复
| |
V V
在单机版中,上面所有的函数调用都是一次完成。
而在对战时,得由多个消息进行驱动。
一种方法是,在当前玩家侧,记下所有的消息,然后一起回放。
另一种方法是,在对方玩家侧把函数都改写为可重入的,然后每次接收到消息就再调用一回目前所在步骤的函数。
似乎第一种方法弄起来比较简单
【游戏结束与重新开局】
如果双方都选择继续下一局则继续,不然双方都返回主菜单
---------------------------------------
--- debug记录 ---
问题:当玩家1打出乐无异・偃师却因没有作用对象而失效时,玩家2执行opponentObtain时处理CopyTrick的方法是:
解答:走target=null的分支,所以应该可以在command buffer为空时将target设为null
这个问题今天又出现了,其实应该把“CopyTrick没选择目标”的情况也记录在命令列表中的。
发现bug:barrier的嵌套顺序
问题现象:打出乐无异但是选取对象中只有一张失效了的陵越,点完后再次出现选择界面,但却误以为barrier已到(是否可能连续出现两次选择目标的界面?)
解答:是可以连续出现两次选择界面,解决方法是把DecrementBarrier移到controller.handleCopies的下方,这样barrier的处理才正确(因为后者可能会增加barrier的计数器,而barrier一到0就会让服务器认为回合结束,所以要让后者把前者包起来。)
发现:重新开局时后手变先手时可能导致complete_specials变成[undefined]不知道是怎么回事
发现bug:对方弃牌(model.opponentDiscard)中忘记加入toSpecial了。会引发以下问题:
一方打出[闻人羽・天罡]&[安陆],对方出错"subjects[i] is null]在tricks.js:25
此时subjects = [ null, 安陆 ], objects = [ null, null ]。
此subjects是obtainVector的chars=[handChar, poolChar]成员,所以在初始化对方的obtainVector时把handChar给弄成null了。
因为收到的对方的手牌ID是wry2b=闻人羽・天罡,该牌由之前的discard操作置换而来。
而在另一个玩家的视角中,对方的闻人羽还没有变成特殊牌。
-----------【redeal()与dealOne()之间的data race】---------------------
此bug简单的触发方法:在opponentObtain中,强制触发model.redeal()。这样就能撞车导致BOOM。
此bug发生的原因是将单机版直接不经思索直接套用到对战版中发生的。因为在单机版中有以下流程:
・P1 obtain
・如有必要,洗牌 \________.----> 这两步在opponentObtain()中
・P2 obtain /
・如有必要,洗牌 ----> 这一步在checkMatch1()中
而因为在改装为对战版的过程中opponentObtain()时已经知道了对方会拿什么牌,所以洗牌就不能放在opponentObtain中,而是放在每个玩家的obtain最后。因为每个玩家都会obtain,所以也和单人版一样,每次行动后都会如果有必要的话就洗牌。
也就是这样:
・P1 obtain
・如有必要,洗牌 ----> 这一步在P1的postObtain()中
・P2 obtain
・如有必要,洗牌 ----> 这一步在P2的postObtain()中
此bug的一种现象:一方打完了禺期,禺期已经在其table中,而另一方却发牌发出了禺期,导致无法将禺期从repository中移到pool中,引发char.card is undefined错误
再仔细看会发现bug:有一张牌无故消失;1号玩家桌上一共有52张牌,2号玩家一共只有51张。
出现于controller.opponentObtain处。
从日志中看到,在对方的opponentObtain之后,牌数就从52减到了51。因为opponentObtain没有执行完,拿取完第一张牌时会发现第二张没有了。
有时候出现了这个Bug游戏还能继续正确运行,有时候就不行了。
从bug现场可以看到之两个玩家看到的事件顺序颠倒:
Player10 vs Player9
服务器看到的顺序 Player10看到的顺序 Player9看到的顺序
・P9 发牌 [古剑晗光] ・P9 发牌 [古剑晗光] ・P9 发牌 [古剑晗光]
・P10 入手 [方兰生]和[凤来] ・P10 入手 [方兰生]和[凤来] ・P10 入手 [方兰生] 和 [凤来]
・P9 洗牌 ・P10 发牌 [古剑焚寂] ・P9 洗牌
・P10 发牌 [古剑焚寂] ・P9 洗牌 ・P10 发牌 [古剑焚寂]
Player9出现了错误,因为Player9洗了牌,古剑焚寂已经在pool中,它的view无法在repo中找到。
----------------------------------------------------------------------
自动测试开局时也可能导致问题,不过这应该和以上那些个问题都无关系。
------------------------------------
一些其它的愿望单・・・
- 页面上聊天?
- 掉线提示或接管或再次登上继续玩
- 回放?(就像Win XP里的蜘蛛纸牌一样能复现一个牌局
- 持久化的牌局(就是退了app再开还是这一局)
------------------------------------
新Bug:在手机浏览器上会卡顿然后狂发牌。
通过连接FireFox WebIDE可以发现:
TypeError: combo is undefined[Learn More] view.js:456:11
notifyOppoCombo view.js:456
nextFunc view.js:480
delayedFunc controller.js:5
另一个新bug:在手机的chrome/opera(似乎只影响Chrome内核的浏览器)上,一收到组合牌通知就会导致Websocket超时并退出。
经过查找,似乎是因为在自己出牌时进入combosound()之后却没有播放音频,似乎所有的timer都停止了一般。
(会不会是与promise的用法有关?……)
更新:在新的上游commit下此碧油唧已被修复
新Bug:两边同时redeal()的话,就会不同步,效果似乎等于双方交换牌局
原因:新commit中的redeal会导致data race
修理方法:自己redeal时,服务器也把自己redeal的结果传回来一份
-------------------------------------
断线重连必要功能之一:从快照恢复
恢复过程:玩家游戏的编号,恢复局的token,服务器告知该玩家是先手还是后手,并送回snapshot
断线重连恢复快照后无法选中牌 ---> 修复方法:view.hand1.addController(controller.activate)
重连过程
1. 断线玩家给服务器送[Game_RequestSnapshot, 游戏ID, 先后手]
2. 服务器收到请求,进入Game.RestoreSnapshot,向断线玩家送回(Game_RestoreGameState, 初始时的快照, 动作序列)。快照与动作序列已经按照玩家的先后手作了调整,1表示玩家,2表示其对手。
3. 断线玩家收到之后,在本地进行回放
4. 回放完成时,向服务器送回[Game_SnapshotRestored]
5. 服务器向两方重发回合开始消息[Game_SelfTurn 或 Game_OpponentTurn](如果对方还在线的话。要是对方不在线(就是说两个玩家都掉线了)就不发)
6. 向已在线的玩家再发Room_PlayerReconnected,提示“对方已上线”
-------------------------------------
新bug:
因为现在允许玩家掉线,而不巧的是用了“将Game.player[0或1]设为null”的方式标记玩家掉线,所以引起了数据竞争,导致所有用到Game.player0或1的地方都会因为null而出错…所以加入了null检查。
null变为非null的条件是掉线的玩家重新连上来;连上来后游戏应该就会照样继续的。
2019-02-23: 把view.blockGame()延后至postObtainDealOne之后
自动显示与隐藏两名玩家的头像
鼠标移入与移出手牌:Card.constructor
打出的牌后自动显示头像:view.obtain
修复:在断线重连时将玩家信息也取回