-
Notifications
You must be signed in to change notification settings - Fork 12
/
myHero.py
2276 lines (2144 loc) · 112 KB
/
myHero.py
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
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
"""
myHero.py:
Define Hero class, as well as bullets, and superpower managers.
"""
import pygame
# 在myHero模块中,load、flip和collide_mask三个函数使用很频繁,这里导入这两个函数以方便使用(enemy同样)
from pygame.image import load
from pygame.transform import flip
from pygame.sprite import collide_mask
from random import random, randint, choice
import math
import enemy
from mapElems import ChestContent # will be used in Javelin class
from props import *
from database import GRAVITY, DMG_FREQ, RANGE
from util import InanimSprite, HPBar
from util import getPos, rot_center, generateShadow, getCld
# ==========================================================
# ====================== Hero Object =======================
# ==========================================================
class Hero(InanimSprite):
# some properties of hero
name = "knight"
heroNo = 0
gender = "Male"
health = 960
full = 960
arrow = 12
fruit = 1
speed = 3 # 英雄用于计算的移动速度(可因某些因素而减慢)
shootNum = 1 # 用于指示每次射击射出的投掷物数量(某些英雄可能不同,默认为1)
arrowCnt = 12 # 指示弹药容量上限,注意和shootCnt区分开(shootCnt是动画计时)
imgIndx = 0
status = "left"
activeProps = [] # 动态存储所有生效中的道具的列表。
suspendedProps = [] # 因为切换塔楼而被挂起的道具列表。
coins = 0
k1 = 0 # 一阶跳的标志
k2 = 0 # 二阶跳的标志
aground = True # indicate whether hero is on the ground
gravity = 1
shootCnt = 0 # 射击时更换图片过程的计数
hitBack = 0 # 受伤击退效果,受伤时将此值设置为击退像素(仅在水平方向上)
wpPos = [0,0,0] # weapon相对于hero的位置比例:pos[0]表示x坐标比例,pos[1]表示y坐标比例,pos[2]表示层级,0表示weapon在self下层,1表示weapon在self上层。
hitFeedIndx = 0
checkList = None # spriteGroup that stores wall or supply sprites used for checking collide
preyList = [] # A list to store info of the killed or damaged enemy by this hero. Can be added by checkImg() or hero's bullet. Can be taken by the model loop.
eventList = [] # A list to store events info such as getItem.
talk = [] # Pair: [txt, cnt]
trapper = None # 指向当前导致英雄减速、无法跳跃状态的对象,将引用挂在这里
shootSnd = None
jmpSnd = None
image = None
rect = None
mask = None
shad = None # 阴影
shadRect = None
imgSwt = 8 # 行走时图片的切换频率。对于大部分英雄为8,某些英雄可能需要更快切换
infected = -1 # 可取3个值:-1表示健康;0表示正在感染(感染效果);1表示已感染
freezeCnt = 0 # 当前被冰冻减速的倒计时
bldColor = (255,10,10,210)
jpCnt = 0
font = None
lgg = 0
onlayer = 0 # indicate which layer hero is. only can be even number
# Img Buffer: 以下是hero的库信息部分,保存易被修改的hero的原始信息。
# 这部分在__init__时设置完成后,不允许再被修改。当需要恢复被改变的属性时,可以从这里读取恢复。
oriSpd = 3 # 指示hero正常的移动速度
oriImgLeftList = [] # hero的行走图片列表
oriImgRightList = []
oriImgJumpLeft = None
oriImgJumpRight = None
oriImgHittedLeft = None
oriImgHittedRight = None
oriWeaponR = {}
oriWpJumpLeft = None
oriWpJumpRight = None
# constructor of hero
def __init__(self, VHero, dmgReduction, font, lgg, keyDic=None, cate="hero"):
InanimSprite.__init__(self, cate)
self.status = "left"
self.imgIndx = 0
self.kNum = 13 # 单阶段跳跃的计算总次数(从离地到抵达最高点的次数,单向上升过程)
self.speed = 3
self.imgSwt = 8
self.interactiveList = ["chest","specialWall","hostage","door","exit","merchant"]
self.superPowerFull = 3200 # 超级技能充满所需值
if VHero.no == 0:
self.name = "knight"
self.push = 7
self.weight = 2
self.talkDic = { "ammoOut":("Arrow's running out.","弓箭用完了。"), "shoot":("Watch out!","看箭!"),
"fullCharge":("Ready to wreck!","准备毁灭!"), "underCharge":("Still need to charge...","还需要充能……"),
"hitted":("Ouch!","呃啊!"), "wait":("Next step...","下一步应该……"), "follower":("","") }
# 只保留left方向下的位置数据,根据hero的状态进行区分。right方向下,保持第二项不变,第一项用1去减即可。第三项只可取0或1。
self.oriWeaponR = {"normal":[ (0.68,0.77,1), (0.63,0.75,1), (0.58,0.73,1), (0.63,0.75,1), (0.58,0.73,1) ],
"shoot":[ (0.1,0.62,1), (0.28,0.74,1), (0.5,0.8,1) ], "jump":(0.68,0.68,1), "superPower":(0.53,0.5,1)}
self.gender = "Male"
elif VHero.no == 1:
self.name = "princess"
self.push = 6
self.weight = 1
self.talkDic = { "ammoOut":("No more powder...","没有火药了……"), "shoot":("Taste this!","尝尝这个!"),
"fullCharge":("Lock and load!","炮火已上膛!"), "underCharge":("Why not stay beautiful?","为什么不多漂亮一会儿呢?"),
"hitted":("Ah!","啊!"), "wait":("I wonder...","我想……"), "follower":("Feel safer with you.","有你在感觉安全多了。") }
self.oriWeaponR = { "normal":[ (0.35,0.72,1), (0.35,0.74,1), (0.35,0.72,1), (0.35,0.74,1), (0.35,0.72,1) ],
"shoot":[ (0.35,0.6,1), (0.35,0.58,1), (0.35,0.58,1) ], "jump":(0.12,0.82,0), "superPower":(0.2,0.65,1)}
self.gender = "Female"
elif VHero.no == 2:
self.name = "prince"
self.push = 8
self.weight = 3
self.talkDic = { "ammoOut":("I need javelins!.","我需要掷枪!"), "shoot":("Get away!","滚开!"),
"fullCharge":("Crush them!","碾碎它们!"), "underCharge":("My pony needs a rest.","我的马儿还需要休息。"),
"hitted":("Errr!","呃!"), "wait":("Pony's tired?","马儿累了吗?"), "follower":("Can you on earth do this?","你到底行不行啊?") }
self.oriWeaponR = {"normal":[ (0.4,0.7,1), (0.42,0.69,1), (0.39,0.68,1), (0.42,0.69,1), (0.39,0.68,1) ],
"shoot":[ (0.39,0.76,1), (0.41,0.72,1), (0.43,0.7,1) ], "jump":(0.64,0.48,1), "superPower":(0.64,0.48,1)}
self.kNum += 1
self.gender = "Male"
elif VHero.no == 3:
self.name = "wizard"
self.push = 6
self.weight = 2
self.talkDic = { "ammoOut":("Fire don't reply.","火元素无法召出了。"), "shoot":("Burn...","灼烧吧……"),
"fullCharge":("I feel the lightning...","我已感受到了雷电……"), "underCharge":("Calm down, and feel the nature.","冷静下来,才能感受自然。"),
"hitted":("Ouch!","呃啊!"), "wait":("Need to ponder...","需要思考一下……"), "follower":("I'll follow you, kid.","我会紧跟着,孩子。") }
self.oriWeaponR = {"normal":[ (0.09,0.64,0), (0.08,0.62,0), (0.09,0.66,0), (0.1,0.62,0), (0.09,0.66,0) ],
"shoot":[ (0.53,0.64,1), (0.49,0.67,1), (0.44,0.78,0) ], "jump":(0.08,0.64,0), "superPower":(0.5,0.45,1)}
self.gender = "Male"
elif VHero.no == 4:
self.name = "huntress"
self.push = 6
self.weight = 1
self.talkDic = { "ammoOut":("Need a rest!","得休息一下。"), "shoot":("Penetrating!","穿刺一切!"),
"fullCharge":("Boomerang on the way.","骨镖已就绪。"), "underCharge":("If my dog is here...","要是我的狗狗在这的话……"),
"hitted":("That hurts!","好痛!"), "wait":("Miss my hound...","想念我的猎犬了……"), "follower":("You are as brave as my hound!","你和我的猎犬一样勇敢!") }
self.oriWeaponR = {"normal":[ (0.7,0.6,0), (0.7,0.6,0), (0.7,0.62,0), (0.7,0.6,0), (0.7,0.62,0) ],
"shoot":[ (0.7,0.6,0), (0.68,0.62,0), (0.66,0.61,0) ], "jump":(0.69,0.64,0), "superPower":(0.53,0.48,0)}
self.gender = "Female"
elif VHero.no == 5:
self.name = "priest"
self.push = 6
self.weight = 1
self.talkDic = { "ammoOut":("There's no forever power.","没有力量是永恒的。"), "shoot":("For Holy light!","为了圣光!"),
"fullCharge":("The Good is about to arrive.","大善即将到来。"), "underCharge":("It needs time to prove pious and kind.","证明虔诚和善良需要时间。"),
"hitted":("Ahhh!","啊!"), "wait":("God leads me...","上帝会指引我……"), "follower":("Are you the angle from the heaven?","你是来自天堂的天使吗?") }
self.oriWeaponR = {"normal":[ (0.27,0.82,0), (0.28,0.82,0), (0.36,0.78,0), (0.28,0.82,0), (0.22,0.77,0) ],
"shoot":[ (0.28,0.8,0), (0.22,0.75,0), (0.16,0.64,0) ], "jump":(0.12,0.62,1), "superPower":(0.16,0.64,0)}
self.gender = "Female"
elif VHero.no == 6:
self.name = "king"
self.push = 8
self.weight = 2
self.talkDic = { "ammoOut":("Reloading now!","正在填装!"), "shoot":("Power of King!","国王的力量!"),
"fullCharge":("It's time to call my fighters!","是时候召唤我的战士们了!"), "underCharge":("What a previledge to see a king playing!","观赏国王展示,真是至高的荣耀!"),
"hitted":("Doc!","医官!"), "wait":("What to do...","接下来怎么做……"), "follower":("I promise you'll be promoted when we get out!","我保证,回去后给你升官!") }
self.oriWeaponR = {"normal":[ (0.05,0.45,0), (0.04,0.44,0), (0.04,0.46,0), (0.04,0.44,0), (0.04,0.46,0) ],
"shoot":[ (0.08,0.55,1), (0.1,0.53,1), (0.12,0.5,0) ], "jump":(0.04,0.46,0), "superPower":(0.05,0.45,0)}
self.shootNum = 5
self.serv = None
self.gender = "Male"
elif VHero.no == -1:
self.name = "servant"
self.push = 6
self.weight = 1
self.talkDic = { "ammoOut":("No more powder...","没有火药了……"), "shoot":("Fuck off!","滚吧!"),
"fullCharge":("Fight!","战斗!"), "underCharge":("Still need to charge...","还需要充能……"),
"hitted":("Ah!","啊!"), "wait":("My honor to stand with you.","很荣幸能和您并肩作战。"),
"follower":("","") }
self.oriWeaponR = { "normal":[ (0.13,0.82,1), (0.22,0.81,1), (0.2,0.8,1), (0.24,0.83,1), (0.2,0.8,1) ],
"shoot":[ (0.1,0.64,1), (0.12,0.63,1), (0.12,0.63,1) ], "jump":(0.16,0.74,0), "superPower":(0.53,0.5,1)}
self.gender = "Female"
self.rDamage = VHero.dmg
self.arrowCnt = VHero.cnt
self.critR = round(VHero.crit/100, 2) # 转化为0-1之间的数
self.stunR = 0
self.oriSpd = self.speed
self.heroNo = VHero.no
if keyDic:
self.keyDic = keyDic
# About the bag: -------------------------------------------
self.bagpack = Bagpack()
self.activeProps = []
self.coins = 0
self.gems = 0
self.expInc = 0
self.arrow = self.arrowCnt
self.jpCnt = 0
self.dmgReducDic = {
"basic":dmgReduction, "physical":1, "fire":1, "corrosive":1, "freezing":1, "holy":1
} # 调节游戏难度所引起的受伤减少,为百分比。1表示原伤害。
self.respondKeyDic = {
"leftKey": lambda delay: self.moveX( delay, "left" ),
"rightKey": lambda delay: self.moveX( delay, "right" )
} # 定义需要连续响应键盘按键的键名和对应的函数列表
self.ammoCircle = pygame.transform.smoothscale( load("image/ammoCircle.png"), (40, 40) )
self.lumi = 0 # 明亮半径:在mist中将会起作用
self.hitBack = 0
self.spurtCanvas = None
self.checkList = pygame.sprite.Group()
self.preyList = []
self.eventList = []
self.weaponR = self.oriWeaponR
self.font = font[lgg]
self.lgg = lgg
self.doom = False
# About HP:---------------------------
self.health = self.full = VHero.hp
self.loading = self.LDFull = 180
self.heal_bonus = 1
self.bar = HPBar(self.full, barOffset=12, color="green")
# About SuperPower: ----------------------------------------
self.superPowerCnt = 0 # 超级技能当前能量值
self.superPowerFull = VHero.superPowerFull # 超级技能充满所需值
self.superPowerCast = 0 # 超级技能释放后图片停留计时
self.superPowerBar = HPBar(self.superPowerFull, blockVol=450, barOffset=2, color="yellow")
self.superPowerManager = None
if VHero.no>=0:
spicon = load(f"image/{self.name}/superPowerIcon.png").convert_alpha()
self.superPowerIcon = pygame.transform.smoothscale( spicon, (spicon.get_width()//2, spicon.get_height()//2) )
# 初始化hero的图片库------------------------------------
self.oriImgLeftList = [ load("image/"+self.name+"/heroLeft0.png").convert_alpha(),
load("image/"+self.name+"/heroLeft2.png").convert_alpha(), load("image/"+self.name+"/heroLeft1.png").convert_alpha(),
load("image/"+self.name+"/heroLeft2.png").convert_alpha(), load("image/"+self.name+"/heroLeft3.png").convert_alpha() ]
self.oriImgRightList = [ flip(self.oriImgLeftList[0], True, False),
flip(self.oriImgLeftList[1], True, False), flip(self.oriImgLeftList[2], True, False),
flip(self.oriImgLeftList[3], True, False), flip(self.oriImgLeftList[4], True, False) ]
self.oriImgJumpLeft = load("image/"+self.name+"/jumpLeft.png").convert_alpha()
self.oriImgJumpRight = flip(self.oriImgJumpLeft, True, False)
self.oriImgHittedLeft = load("image/"+self.name+"/hittedLeft.png").convert_alpha()
self.oriImgHittedRight = flip(self.oriImgHittedLeft, True, False)
self.oriWpJumpLeft = load("image/"+self.name+"/wpJump.png").convert_alpha()
self.oriWpJumpRight = flip(self.oriWpJumpLeft, True, False)
self.imgLib = {
"leftList": self.oriImgLeftList,
"rightList": self.oriImgRightList,
"weaponLeft": load("image/"+self.name+"/weapon.png").convert_alpha(),
"weaponRight": flip(load("image/"+self.name+"/weapon.png").convert_alpha(), True, False),
"wpMoveLeft": load("image/"+self.name+"/wpMove.png").convert_alpha(),
"wpMoveRight": flip(load("image/"+self.name+"/wpMove.png").convert_alpha(), True, False),
"shootLeftList": [ load("image/"+self.name+"/shootLeft0.png").convert_alpha(),
load("image/"+self.name+"/shootLeft1.png").convert_alpha(),
load("image/"+self.name+"/shootLeft2.png").convert_alpha() ],
"shootRightList": [ flip(load("image/"+self.name+"/shootLeft0.png").convert_alpha(), True, False),
flip(load("image/"+self.name+"/shootLeft1.png").convert_alpha(), True, False),
flip(load("image/"+self.name+"/shootLeft2.png").convert_alpha(), True, False) ],
"wpAttLeft": [ load("image/"+self.name+"/wpAtt0.png").convert_alpha(),
load("image/"+self.name+"/wpAtt1.png").convert_alpha(),
load("image/"+self.name+"/wpAtt2.png").convert_alpha() ],
"wpAttRight": [ flip(load("image/"+self.name+"/wpAtt0.png").convert_alpha(), True, False),
flip(load("image/"+self.name+"/wpAtt1.png").convert_alpha(), True, False),
flip(load("image/"+self.name+"/wpAtt2.png").convert_alpha(), True, False) ],
"superPowerLeft": load("image/"+self.name+"/superPower.png").convert_alpha(),
"superPowerRight": flip(load("image/"+self.name+"/superPower.png").convert_alpha(), True, False),
"wpSuperPowerLeft": load("image/"+self.name+"/wpSuperPower.png").convert_alpha(),
"wpSuperPowerRight": flip(load("image/"+self.name+"/wpSuperPower.png").convert_alpha(), True, False),
"jumpLeft": self.oriImgJumpLeft,
"jumpRight": self.oriImgJumpRight,
"wpJumpLeft": self.oriWpJumpLeft,
"wpJumpRight": self.oriWpJumpRight,
"hittedLeft": self.oriImgHittedLeft,
"hittedRight": self.oriImgHittedRight,
"infShootLeft": load("image/stg3/dead"+self.gender+"Vomit.png").convert_alpha(),
"infShootRight": flip(load("image/stg3/dead"+self.gender+"Vomit.png").convert_alpha(), True, False),
"infLeftList": [load("image/stg3/dead"+self.gender+"Wait.png").convert_alpha(),
load("image/stg3/dead"+self.gender+"1.png").convert_alpha(), load("image/stg3/dead"+self.gender+"0.png").convert_alpha(),
load("image/stg3/dead"+self.gender+"1.png").convert_alpha(), load("image/stg3/dead"+self.gender+"2.png").convert_alpha() ],
"infRightList": [flip(load("image/stg3/dead"+self.gender+"Wait.png").convert_alpha(), True, False),
flip(load("image/stg3/dead"+self.gender+"1.png").convert_alpha(), True, False),
flip(load("image/stg3/dead"+self.gender+"0.png").convert_alpha(), True, False),
flip(load("image/stg3/dead"+self.gender+"1.png").convert_alpha(), True, False),
flip(load("image/stg3/dead"+self.gender+"2.png").convert_alpha(), True, False) ]
}
# generate shadows
self.shadLib = {}
for each in self.imgLib:
if isinstance(self.imgLib[each],list):
self.shadLib[each] = []
for img in self.imgLib[each]:
self.shadLib[each].append( generateShadow(img) )
else:
self.shadLib[each] = generateShadow(self.imgLib[each])
# initialize the position of hero ------------------------------
self.setImg("leftList", 0)
self.mask = pygame.mask.from_surface(self.image)
self.rect = self.image.get_rect()
# Initialize the melee weapon of the hero ----------------------
self.weapon = enemy.Ajunction( self.imgLib["weaponLeft"], getPos(self, self.weaponR["normal"][0][0], self.weaponR["normal"][0][1]) )
self.wpPos = [ self.weaponR["normal"][0][0], self.weaponR["normal"][0][1], self.weaponR["normal"][0][2] ] # 初始化为normal[0]
# Jump dust imgs -----------------------------------------------
self.dustList = [load("image/stg2/alarm5.png").convert_alpha(), load("image/stg2/alarm4.png").convert_alpha(),
load("image/stg2/alarm3.png").convert_alpha(), load("image/stg2/alarm2.png").convert_alpha(),
load("image/stg2/alarm1.png").convert_alpha(), load("image/stg2/alarm0.png").convert_alpha()]
self.brand = load("image/"+self.name+"/brand.png").convert_alpha()
self.jmpPos = [0,0]
self.jmpInfo = ()
self.jmpCap = (1+self.kNum)*self.kNum //2 # 单次跳跃的上升距离,将在初始化时计算得出
self.jmpSnd = pygame.mixer.Sound("audio/"+self.name+"/jump.wav")
self.oriJmpSnd = self.jmpSnd
self.shootSnd = pygame.mixer.Sound("audio/"+self.name+"/shoot.wav")
self.oriShootSnd = self.shootSnd
self.fruitSnd = pygame.mixer.Sound("audio/eatFruit.wav")
self.injureSnd = pygame.mixer.Sound("audio/injure"+self.gender+".wav")
# infection related
self.infSnd = pygame.mixer.Sound("audio/infect"+self.gender+".wav")
self.infJmp = pygame.mixer.Sound("audio/infJump"+self.gender+".wav")
self.coinSnd = pygame.mixer.Sound("audio/coin.wav")
self.reloadSnd = pygame.mixer.Sound("audio/reload.wav")
self.vomiSnd = pygame.mixer.Sound("audio/vomiSplash.wav")
# 开场语
if self.category=="hero":
VHero.voice.play(0)
self.superPowerVoice = pygame.mixer.Sound("audio/"+self.name+"/superPowerVoice.wav")
# 用于重置本元素的位置至所给塔楼的初始位置
def resetPosition(self, tower, tag="p1", layer="-1", side="left"):
if side=="left":
pos_x = tower.boundaries[0]-tower.blockSize
elif side=="right":
pos_x = tower.boundaries[1]+tower.blockSize
elif side=="center":
pos_x = sum(tower.boundaries)//2
if tag=="p1":
pos_x = pos_x-10
elif tag=="p2":
pos_x = pos_x+10
self.rect.left = pos_x-self.rect.width//2
self.rect.bottom = tower.getTop( str(layer) )-12
def jump(self, keyLine):
self.aground = False
# 一段跳
if (self.k2==0):
if (self.k1==1): # 一段跳刚开始时,获取起跳时的位置
if random()<0.33:
self.jmpSnd.play(0)
self.jpCnt = 12
self.jmpPos[0] = self.rect.left + self.rect.width//2
self.jmpPos[1] = self.rect.bottom
self.rect.bottom -= (self.kNum-self.k1)
self.k1 = (self.k1+1)%(self.kNum+1)
# 二段跳
else:
self.rect.bottom -= (self.kNum-self.k2)
self.k2 = (self.k2+1)%(self.kNum+1)
while ( getCld(self, self.checkList, ["sideWall","baseWall","blockStone"]) ): # 如果和参数中的物体重合,则回退1高度
self.rect.bottom += 1 # 循环+1,直到不再和任何物体重合为止,跳出循环
self.k1 = self.k2 = 0
if ( self.rect.bottom <= keyLine ):
self.shiftLayer(2, None)
def moveX(self, delay, to):
# 运动过程中,可取index为[1,2,3,4] 分别对应运动的四张帧图(0为静止)
if not (delay % self.imgSwt ):
self.imgIndx += 1
if self.imgIndx >= len(self.imgLib["leftList"]):
self.imgIndx = 1
if to=="left":
self.status = "left"
self.rect.left -= self.speed
self._checkMove( back=-self.speed )
elif to=="right":
self.status = "right"
self.rect.left += self.speed
self._checkMove( back=self.speed )
def fall(self, keyLine, newLine, heightList, GRAVITY):
self.rect.bottom += self.gravity # 尝试将自身纵坐标减去重力值
# 获得所有碰撞了的物体对象,并针对每一个碰撞了的item执行相应的响应动作
for item in pygame.sprite.spritecollide(self, self.checkList, False, collide_mask):
if item.category in self.interactiveList:
item.interact(self)
while getCld(self, self.checkList, ["lineWall","baseWall","specialWall","sideWall","blockStone","house"]):
if self.gravity>4: # 速度过大,造成扬灰效果
self.jpCnt = 12
self.jmpPos[0] = self.rect.left + self.rect.width//2
self.jmpPos[1] = self.rect.bottom
# 如果和参数中的物体重合,则回退1高度
self.rect.bottom -= 1 # 循环-1,直到不再和任何物体重合为止,跳出循环
self.aground = True # 这两个值反复设置没有关系,只要循环结束后保证两个值分别为true和1即可
self.gravity = 0
if (self.gravity<GRAVITY):
self.gravity += 1
self.renewCheckList(newLine) # 更新self.checkList(跳跃函数中不必更新,只有这里需要更新)
# 判断是否要向下调整层数.
if ( self.rect.top >= keyLine ):
self.shiftLayer(-2, heightList)
def shiftLayer(self, to, heightList):
if to<0:
# 下跳则检查:在最底层不能下跳;# 若英雄高度超过所在行的高度-跳跃距离的一半,则不能下跳(这是为了防止过快连跳)。
if (self.onlayer<=0) or ( self.rect.bottom < heightList[str(self.onlayer)]-self.jmpCap//2 ):
return
self.onlayer += to
self.aground = False
def shoot(self, tower, spurtCanvas=None):
#if (self.shootCnt > 0): # couldn't shoot too fast! Hero mustn't be shooting.
# return
if self.infected>0: # infect situation.
self.shootSnd.play(0)
self.vomiSnd.play(0)
self.shootCnt = 40
return
if (self.arrow > 0):
self.shootSnd.play()
if random() <= 0.2:
self.talk = [self.talkDic["shoot"][self.lgg], 60]
if self.status=="left":
self.hitBack = self.push-self.weight
pos = getPos(self, 0, 0.54)
xspd = [-1,-2,-3]
else:
self.hitBack = -(self.push-self.weight)
pos = getPos(self, 1, 0.54)
xspd = [1,2,3]
# make ammo object
if self.name == "knight":
arrow = Ammo( self, pos, [8,0], category="bullet", bldNum=6, push=6 )
tower.allElements["mons1"].add(arrow)
elif self.name == "princess":
arrow = Ammo( self, pos, [8,0], category="bullet", bldNum=8, push=7 )
tower.allElements["mons1"].add(arrow)
if spurtCanvas: # bullet特效
spurtCanvas.addSpatters( 5, (1,2), (12,14,16), (255,255,0), pos, False, xspd=xspd, yspd=[-1,0,1] )
elif self.name == "prince":
arrow = Javelin( self, pos )
tower.allElements["mons1"].add(arrow)
elif self.name == "wizard":
arrow = Fireball( self, pos )
tower.allElements["mons1"].add(arrow)
elif self.name == "huntress":
arrow = Dart( self, pos )
tower.allElements["mons1"].add(arrow)
elif self.name == "priest":
arrow = HolyLight( self, pos )
tower.allElements["mons1"].add(arrow)
elif self.name == "king":
spdList = ( [7,2],[8,1],[8,0],[8,-1],[7,-2] )
for i in range(0, self.shootNum):
arrow = Ammo( self, pos, spdList[i], category="bullet", bldNum=4, push=4, duration=RANGE["SHORT"] )
tower.allElements["mons1"].add(arrow)
if spurtCanvas: # bullet打出特效
spurtCanvas.addSpatters( 5, (1,2), (12,14,16), (255,255,0), pos, False, xspd=xspd, yspd=[-1,0,1] )
self.arrow -= 1
elif self.arrow<=0:
self.talk = [self.talkDic["ammoOut"][self.lgg], 60]
self.reloadSnd.play()
self.shootCnt = 18
def castSuperPower(self, canvas):
if self.superPowerCnt<self.superPowerFull: # not fully charged yet
self.talk = [self.talkDic["underCharge"][self.lgg], 60]
return False
self.superPowerVoice.play(0)
canvas.addHalo( "holyHalo", 240 )
if self.name=="knight":
self.superPowerManager = SuperPowerManagerKnight(self)
elif self.name=="princess":
self.superPowerManager = SuperPowerManagerPrincess(self)
elif self.name=="prince":
self.superPowerManager = SuperPowerManagerPrince(self)
elif self.name=="wizard":
self.superPowerManager = SuperPowerManagerWizard(self)
elif self.name=="huntress":
self.superPowerManager = SuperPowerManagerHuntress(self)
elif self.name=="priest":
self.superPowerManager = SuperPowerManagerPriest(self)
elif self.name=="king":
self.superPowerManager = SuperPowerManagerKing(self)
self.superPowerCnt = 0
self.superPowerCast = 30
def chargeSuperPower(self, amount):
if self.superPowerCnt==self.superPowerFull:
return
self.superPowerCnt += amount
if self.superPowerCnt > self.superPowerFull:
self.superPowerCnt = self.superPowerFull
pygame.mixer.Sound("audio/knight/superPowerCast.wav").play(0)
self.talk = [self.talkDic["fullCharge"][self.lgg], 90]
if self.spurtCanvas:
self.spurtCanvas.addSpatters( 12, [3,5,7], [36,42,48], (255,200,100,240), getPos(self,0.5,0.5), False )
def checkImg(self, delay, tower, heroes, key_pressed, spurtCanvas):
"""
A pipeline to do the following checks and operations:
1. calculate img cnts and select correct image
2. respond to the player's ongoing keydown event
3. check hero's state: freeze, trapped, hitback, infection, etc.
4. manage hero's bagpack
5. check and run props & superPowers
"""
if self.health<=0:
return 0
# 画起跳的灰尘
if self.jpCnt > 0:
self.jpCnt -= 1
self.dustRect = self.dustList[ self.jpCnt//2 ].get_rect()
self.dustRect.left = self.jmpPos[0] - self.dustRect.width // 2
self.dustRect.bottom = self.jmpPos[1]
self.jmpInfo = ( self.dustList[ self.jpCnt//2 ], self.dustRect )
else:
self.jmpInfo = ()
# Check when hero is shooting an arrow.
if ( self.shootCnt > 0 ) and (self.infected<=0):
if not ( self.shootCnt % 6 ): # Cnt每次等于6的倍数的时候就更换一次图片
indx = len(self.imgLib["shootLeftList"]) - self.shootCnt//6 # 指示图片序号的临时变量。工作原理:Cnt=18的时候,imgIndx应该为0;同理,Cnt=12,imgIndx=1;Cnt=6,indx=3。
if self.status == "left":
rht = self.rect.right
btm = self.rect.bottom
self.setImg("shootLeftList",indx)
self.rect = self.image.get_rect() # 获取新的图片的rect
self.rect.right = rht
self.rect.bottom = btm
self.weapon.updateImg( self.imgLib["wpAttLeft"][indx] ) # weapon的图片序号和wIndx图片序号保持同步。
self.wpPos[0] = self.weaponR["shoot"][indx][0]
elif self.status == "right":
lft = self.rect.left
btm = self.rect.bottom
self.setImg("shootRightList",indx)
self.rect = self.image.get_rect()
self.rect.left = lft
self.rect.bottom = btm
self.weapon.updateImg( self.imgLib["wpAttRight"][indx] )
self.wpPos[0] = 1 - self.weaponR["shoot"][indx][0]
self.wpPos[1] = self.weaponR["shoot"][indx][1]
self.wpPos[2] = self.weaponR["shoot"][indx][2]
self.shootCnt -= 1
# Check when hero is jumping in the air. Note that the statement "elif" makes that hero's image will be whiping when he whip even in the air.
elif not self.aground:
if self.status == "left":
self.setImg("jumpLeft")
self.weapon.updateImg( self.imgLib["wpJumpLeft"] )
self.wpPos[0] = self.weaponR["jump"][0]
elif self.status == "right":
self.setImg("jumpRight")
self.weapon.updateImg( self.imgLib["wpJumpRight"] )
self.wpPos[0] = 1 - self.weaponR["jump"][0]
self.wpPos[1] = self.weaponR["jump"][1]
self.wpPos[2] = self.weaponR["jump"][2]
# Check when hero is suffering damage.
elif self.hitFeedIndx > 0:
if (self.status=="right"):
self.setImg("hittedRight")
else:
self.setImg("hittedLeft")
self.hitFeedIndx -= 1
# Check when hero is casting superPower.
elif self.superPowerCast>0: # 刚刚施放技能的0.5s内,有施放图片
self.superPowerCast -= 1
if (self.status=="right"):
self.setImg("superPowerRight")
self.weapon.updateImg( self.imgLib["wpSuperPowerRight"] )
self.wpPos[0] = 1 - self.weaponR["superPower"][0]
else:
self.setImg("superPowerLeft")
self.weapon.updateImg( self.imgLib["wpSuperPowerLeft"] )
self.wpPos[0] = self.weaponR["superPower"][0]
self.setRect()
self.wpPos[1] = self.weaponR["superPower"][1]
self.wpPos[2] = self.weaponR["superPower"][2]
# If hero is not shooting, not jumping and not hurting, he should only be in normal status (static and walking).
else:
if self.status == "left":
self.setImg("leftList",self.imgIndx)
# Check whether hero is moving. Different pic for moving and standing.
if self.imgIndx==0:
self.weapon.updateImg( self.imgLib["weaponLeft"] )
else:
self.weapon.updateImg( self.imgLib["wpMoveLeft"] )
self.wpPos[0] = self.weaponR["normal"][self.imgIndx][0]
elif self.status == "right":
self.setImg("rightList",self.imgIndx)
if self.imgIndx==0:
self.weapon.updateImg( self.imgLib["weaponRight"] )
else:
self.weapon.updateImg( self.imgLib["wpMoveRight"] )
self.wpPos[0] = 1 - self.weaponR["normal"][self.imgIndx][0]
self.wpPos[1] = self.weaponR["normal"][self.imgIndx][1]
self.wpPos[2] = self.weaponR["normal"][self.imgIndx][2]
if not delay% 120 and random()<0.24:
self.talk = [self.talkDic["wait"][self.lgg], 60]
# Always renew the position of the weapon.
self.weapon.updatePos( getPos(self, self.wpPos[0], self.wpPos[1]) )
if self.category=="hero":
for key_name in self.respondKeyDic:
if key_pressed[ self.keyDic[key_name] ]: # 若被摁下,则call该匿名函数
if key_name=="shootKey":
self.respondKeyDic[key_name](tower.monsters)
else:
self.respondKeyDic[key_name](delay)
# Specifically, if not running, set the imgIndx to zero.
if self.imgIndx>0 and not key_pressed[self.keyDic["leftKey"]] and not key_pressed[self.keyDic["rightKey"]]:
self.imgIndx = 0
# deal freezeCnt
if self.freezeCnt > 0:
self.freezeCnt -= 1
else:
self.speed = self.oriSpd # 解冻
# deal stuck if there is a trapper in effect.
if self.trapper:
if not collide_mask(self, self.trapper):
self.trapper = None
else:
self.speed = self.oriSpd-2
# 处理击退位移,如果值不为0的话。
if abs(self.hitBack)>0:
if self.hitBack>0:
realBack = min(self.hitBack, 6)
self.hitBack -= 1
elif self.hitBack<0:
realBack = max(self.hitBack, -6)
self.hitBack += 1
self.rect.left += realBack
self._checkMove( back=realBack )
# deal infection
if self.infected == 0:
self.infected = 1
spurtCanvas.addSpatters( 12, [3, 4, 5], [12,14,16], (10,10,10,240), getPos(self, 0.5, 0.5), True )
elif self.infected>0:
if self.shootCnt > 0:
self.shootCnt -= 1
if self.status == "left":
rht = self.rect.right
btm = self.rect.bottom
self.setImg("infShootLeft")
self.rect = self.image.get_rect() # 获取新的图片的rect
self.rect.right = rht
self.rect.bottom = btm
elif self.status == "right":
lft = self.rect.left
btm = self.rect.bottom
self.setImg("infShootRight")
self.rect = self.image.get_rect()
self.rect.left = lft
self.rect.bottom = btm
# 每2次刷新均吐出1个vomi
if not self.shootCnt%2:
spdX = 9-self.shootCnt//8
if self.status == "left":
spd = [ -spdX, 0 ]
startX = 0.2
elif self.status == "right":
spd = [ spdX, 0 ]
startX = 0.8
spurtCanvas.addAirAtoms(self, 1, getPos(self, startX, 0.5),
spd, tower.monsters, "corrosive", btLine=self.rect.bottom)
vib = 0
# Renew Props.
for prop in self.activeProps[::-1]:
if prop.propName == "blastingCap":
prop.fall( delay, tower.getTop(prop.onlayer), tower.groupList, GRAVITY )
if prop.work(tower.monsters, tower.groupList["0"], spurtCanvas):
vib = max(vib,12)
elif prop.propName == "torch":
prop.work(tower.monsters, spurtCanvas) # 溅射的火星对范围内敌人造成伤害
elif prop.propName == "battleTotem":
if not prop.checkExposion(spurtCanvas): # 检查摧毁
tracker = prop.run([self], spurtCanvas)
if tracker:
tower.allElements["mons1"].add( tracker )
elif prop.propName == "rustedHorn":
if prop.work(tower.monsters, heroes):
vib = max(vib,8)
elif prop.propName == "defenseTower":
if prop not in heroes:
heroes.append(prop)
self.activeProps.remove(prop)
else: # Normal Durable prop.
prop.work()
# 超级技能。
if self.superPowerManager:
if self.superPowerManager.run(delay, tower, heroes, spurtCanvas): # 生效阶段,震动屏幕
vib = max(vib,6)
return vib
def shiftTower(self, tower, oper="suspend"):
""" oper='suspend' or 'rejoin' """
if oper=="suspend": # 将老tower中的activeprop转为挂起。NOTE:Props 自己会记住owner。
for prop in self.activeProps[::-1]:
if prop.propName in ["blastingCap","battleTotem"]:
self.activeProps.remove(prop)
tower.suspendedProps.append(prop)
elif oper=="rejoin": # 将新tower中被挂起的prop转入active
for prop in tower.suspendedProps[::-1]:
if prop.user==self:
tower.suspendedProps.remove(prop)
self.activeProps.append(prop)
def reload(self, delay, spurtCanvas):
# Check loading listener: When ammos run out and loading is full
if self.arrow==0 and self.loading==self.LDFull:
self.loading = 0
self.reloadSnd.play(0)
# when loading is not full: Reloading...
elif self.loading<self.LDFull:
self.loading += 1
if self.loading==self.LDFull:
self.arrow = self.arrowCnt
self.reloadSnd.play(0)
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (100,100,210,240), getPos(self, 0.5, 0.5), False )
def useItem(self, spurtCanvas):
if self.bagpack.bagPt<0:
return ("You don't have items in bagpack!","你的背包中没有道具!")
curName = self.bagpack.bagBuf[self.bagpack.bagPt]
if curName == "fruit":
if self.infected>=0:
return ("Can't eat fruit when infected.","感染时无法使用。")
elif self.health == self.full:
return ("Your HP is full at the time.","当前你的体力值已满。")
else:
self.fruitSnd.play(0)
self.bagpack.decItem("fruit")
self.recover(100)
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (100,255,100,240), getPos(self, 0.5, 0.5), False )
elif curName == "loadGlove":
if (self.loading>=self.LDFull-1):
return ("No need for loading at the time.","当前无需填装。")
elif self.infected>=0:
return ("Can't eat fruit when infected.","感染时无法使用。")
else:
self.fruitSnd.play(0)
self.bagpack.decItem("loadGlove")
self.loading = self.LDFull-1
#spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (100,100,210,240), getPos(self, 0.5, 0.5), False )
elif curName == "medicine":
if self.infected <=0 and self.health == self.full:
return ("You are neither infected nor injured.","你既未感染,也未受伤。")
else:
self.fruitSnd.play(0)
self.bagpack.decItem("medicine")
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (100,100,255,240), getPos(self, 0.5, 0.5), False )
if self.infected <= 0:
# 未感染,回复体力
self.recover(100)
else:
# 感染,治愈:恢复image和相关属性值
self.infected = -1
self.imgLib["leftList"] = self.oriImgLeftList
self.imgLib["rightList"] = self.oriImgRightList
self.imgLib["jumpLeft"] = self.oriImgJumpLeft
self.imgLib["jumpRight"] = self.oriImgJumpRight
self.imgLib["hittedLeft"] = self.oriImgHittedLeft
self.imgLib["hittedRight"] = self.oriImgHittedRight
self.imgIndx = 0
self.weaponR = self.oriWeaponR
self.jmpSnd = self.oriJmpSnd
self.shootSnd = self.oriShootSnd
elif curName == "blastingCap":
self.fruitSnd.play(0)
self.bagpack.decItem("blastingCap")
cap = BlastingCap(self, [-4, -7], self.onlayer) if self.status=="left" else BlastingCap(self, [4, -7], self.onlayer)
self.activeProps.append( cap )
elif curName == "battleTotem":
# 首先检查是否可以放置图腾
wall = None
wallList = []
for aWall in self.checkList: # 由于spriteGroup不好进行索引/随机选择操作,因此将其中的sprite逐个存入列表中存储
# 筛选出当前所在的行砖
if aWall.category in ("lineWall","specialWall","baseWall") and aWall.coord[1]==self.onlayer-1:
wallList.append(aWall)
if aWall.rect.left<getPos(self,0.5,0)[0]<aWall.rect.right: # 可以落到下一行上,有砖接着
wall = aWall
if (not wallList) or (not wall): # 不能放置图腾,取消效果
return ("Please place the totem on the ground!","请将图腾放置于地面!")
self.fruitSnd.play(0)
self.bagpack.decItem("battleTotem")
totem = BattleTotem(self, wall, self.onlayer)
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], totem.themeColor, getPos(totem, 0.5, 0.5), False )
self.activeProps.append( totem )
elif curName == "defenseTower":
ok = False
# 检查是否可以放置防御塔
for wall in DefenseTower.siteWalls:
if (wall.rect.left<getPos(self,0.5,0)[0]<wall.rect.right) and (wall.coord[1]==self.onlayer-1):
if wall.tower:
return ("The site has a existing Defense Tower.","该基座已有一个防御塔。")
else:
# 玩家处于sitewall上,且该砖空余,则可以放置
self.fruitSnd.play(0)
self.bagpack.decItem("defenseTower")
tow = DefenseTower(getPos(wall,0.5,0)[0], wall.rect.top, self.onlayer, self.font, self.lgg, self)
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (120,240,120), getPos(tow, 0.5, 0.5), False )
self.activeProps.append( tow )
wall.tower = tow
ok = True
break
if not ok: # 不能放置防御塔,取消效果
return ("Please place the tower on the ground!","请将防御塔放置于基座上!")
# Create the enduring prop and put it in the activeList.
elif curName == "torch":
if self.infected >= 0:
return ("Can't eat fruit when infected.","感染时无法使用。")
elif self.oneInEffect("torch"):
return ("You have a torch working.","你已经有一个火炬在照明。")
else:
self.bagpack.decItem("torch")
self.activeProps.append( Torch(self) )
elif curName == "copter":
if self.oneInEffect("copter"):
return ("You have a copter working.","你已经装有一个竹蜻蜓。")
else:
self.bagpack.decItem("copter")
self.activeProps.append( Copter(self) )
elif curName == "pesticide":
if self.oneInEffect("pesticide"):
return ("You are holding another pesticide spray.","你正持有另一个杀虫喷雾器。")
else:
self.bagpack.decItem("pesticide")
self.activeProps.append( Pesticide(self) )
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (100,140,40,240), getPos(self, 0.5, 0.5), False )
elif curName == "herbalExtract":
if self.health == self.full:
return ("Your HP is full at the time.","当前你的体力值已满。")
else:
self.fruitSnd.play(0)
self.bagpack.decItem("herbalExtract")
self.activeProps.append( HerbalExtract(self) )
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (80,240,160,240), getPos(self, 0.5, 0.5), False )
elif curName == "simpleArmor":
if self.oneInEffect("simpleArmor"):
return ("You have equiped a armor.","你已经装备了一件简易机甲。")
else:
self.bagpack.decItem("simpleArmor")
self.activeProps.append( SimpleArmor(self) )
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (100,140,40,240), getPos(self, 0.5, 0.5), False )
elif curName == "missleGun":
if self.oneInEffect("missleGun"):
return ("You are holding another missle gun.","你正持有另一个火箭炮。")
else:
self.bagpack.decItem("missleGun")
self.activeProps.append( MissleGun(self) )
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (100,140,40,240), getPos(self, 0.5, 0.5), False )
elif curName == "cooler":
if self.oneInEffect("cooler"):
return ("You are under the effect of another cooler.","你已有一个清凉饮料在生效。")
else:
self.fruitSnd.play(0)
self.bagpack.decItem("cooler")
self.activeProps.append( Cooler(self) )
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (255,255,160,240), getPos(self, 0.5, 0.5), False )
elif curName == "alcohol":
if self.oneInEffect("alcohol"):
return ("You are under the effect of another alcohol.","你已有一个烈酒在生效。")
else:
self.fruitSnd.play(0)
self.bagpack.decItem("alcohol")
self.activeProps.append( Alcohol(self) )
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (255,160,160,240), getPos(self, 0.5, 0.5), False )
elif curName == "toothRing":
if self.oneInEffect("toothRing"):
return ("You are under the effect of another toothRing.","你已有一个龙牙之戒在生效。")
else:
self.fruitSnd.play(0)
self.bagpack.decItem("toothRing")
self.activeProps.append( ToothRing(self) )
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (180,0,100,240), getPos(self, 0.5, 0.5), False )
elif curName == "shieldSpell":
if self.oneInEffect("shieldSpell"):
return ("You are under the effect of another shield spell.","你已有一个护盾法术在生效。")
else:
self.fruitSnd.play(0)
self.bagpack.decItem("shieldSpell")
self.activeProps.append( ShieldSpell(self) )
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (255,255,160,240), getPos(self, 0.5, 0.5), False )
elif curName == "rustedHorn":
if self.oneInEffect("rustedHorn"):
return ("You are under the effect of another rusted horn.","你已有一个生锈的号角在生效。")
else:
self.bagpack.decItem("rustedHorn")
self.activeProps.append( RustedHorn(self) )
spurtCanvas.addSpatters( 12, [3, 4, 5], [16,20,24], (255,210,160,240), getPos(self, 0.5, 0.5), False )
def oneInEffect(self, propName): # 检测是否有正在生效的某类用品
for prop in self.activeProps:
if prop.propName == propName:
return prop
return None
def renewCheckList(self, new, clear=False): # 动态调节checkList内的检测砖块,以减轻负担
if clear==True:
self.checkList.empty()
else:
rmvList = ["lineWall","specialWall","house"]#,"baseWall"]
for each in self.checkList:
if each.category in rmvList:
self.checkList.remove(each)
for each in new:
self.checkList.add(each)
def hitted(self, damage, pushed, dmgType):
if self.health<=0:
return
# 检查伤害减轻效果
damage *= self.dmgReducDic["basic"]
damage *= self.dmgReducDic[dmgType]
self.health -= damage
# Do if hero is dead
if (self.health <= 0):
self.health = 0
self.doom = True
self.infected = 1 # 借用此flag,不再绘制武器
if self.category == "hero":
self.spurtCanvas.addHalo("deadHalo", 180)
# Change dead image
self.image = load(f"image/{self.name}/defeat.png").convert_alpha()
if self.status=="right":
self.image = flip(self.image, True, False)
self.setRect()
return True
self.hitFeedIndx = 6
if pushed>0: # 向右击退
self.hitBack = max( pushed-self.weight, 0 )
elif pushed<0: # 向左击退
self.hitBack = min( pushed+self.weight, 0 )
# 若本对象是玩家操控的英雄而非AI,则对整个频幕进行渲染反馈。
if self.category == "hero":
self.spurtCanvas.addHalo( "hitHalo", 180 )
# 音效
if self.injureSnd.get_num_channels()==0:
self.injureSnd.play(0)
# 以下是硬直效果,取消所有的英雄射箭、二段跳行为
self.shootCnt = self.k2 = 0
if random()<0.1:
self.talk = [self.talkDic["hitted"][self.lgg], 60]
def recover(self, heal):
if self.health<=0:
return
#self.spurtCanvas.addSpatters(8, (2,3,4), (20,22,24), (10,240,10), getPos(self,0.5,0.4) )
self.health += heal * self.heal_bonus
if (self.health > self.full):
self.health = self.full
def freeze(self, decre):
self.freezeCnt = 120
if self.speed == self.oriSpd:
self.speed = self.oriSpd - decre
self.spurtCanvas.addHalo( "frzHalo", 160 )
def infect(self):
self.infSnd.play(0)
self.infected = 0 # 置为0,以指示受到感染的瞬间
self.torchCnt = 0 # 如果感染时有火炬,则将之熄灭
self.imgLib["leftList"] = self.imgLib["infLeftList"]
self.imgLib["rightList"] = self.imgLib["infRightList"]
self.imgIndx = 0
self.imgLib["jumpLeft"] = self.imgLib["infLeftList"][0]
self.imgLib["jumpRight"] = self.imgLib["infRightList"][0]
#self.imgLib["wpJumpLeft"] = self.imgLib["wpHideLeft"]
#self.imgLib["wpJumpRight"] = self.imgLib["wpHideRight"]
self.imgLib["hittedLeft"] = self.imgLib["infLeftList"][1]
self.imgLib["hittedRight"] = self.imgLib["infRightList"][1]
# sound
self.jmpSnd = self.infJmp
self.shootSnd = self.infSnd
def reportHit(self, mons):
if mons.hitted( 20, 0, "corrosive" )==True:
self.preyList.append( (getPos(mons,0.5,0.5), mons.bldColor, 0, mons.category, mons.coin, False) )
def paint(self, screen):
# 画阴影
shadRect = self.rect.copy()
shadRect.left -= 8
screen.blit(self.shad, shadRect)
#按层级顺序画weapon和self
if self.infected>0:
screen.blit( self.image, self.rect )
else:
if self.wpPos[2]==0:
screen.blit( self.weapon.image, self.weapon.rect )
screen.blit( self.image, self.rect )
elif self.wpPos[2]==1: