-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathClasses.py
2231 lines (1758 loc) · 133 KB
/
Classes.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
#Classes module for Compter Science project
#Purpose: To hold all of the classes that will be run in the game
#Created 01/08/2020 by Greg
#----------------------------------------------------------
import pygame
import os
import re
from Functions import *
import socket
import pickle
#import random
#import time
import threading
#import math
#----------------------------------------------------------
class Thread(object):
def __init__(self, Target,Parameters):
thread = threading.Thread(target=self.Run, args=(Target,Parameters,), daemon=True)#The comma after Parameters is required otherwise it will return a type error!!!
thread.start()
def Run(self,Target,Parameters):
print(Target)
Target(Parameters)
#----------------------------------------------------------
#----------------------------------------------------------
class Object():
def __init__(OBJECT, ID, Location, Team, Target, Level, Records, Mode, Index):#Object List: [Location]
#Complete List Of Atttributes: [Location,[Size_X,Size_Y],[Mode/control],Rect,State,Animations,Level,Stats,Team,UnitID]#OUT OF DATE FIX!!!
#------------------------------------------
#Sometimes error: Must re-create the game database because something goes wrong?
#print(Records[4][ID])
Stats= [int(x) for x in Records[4][ID][4].split(',')]
print(Stats, "STATS!!!")
OBJECT.__Attributes= {#The data that must be sent to each client each frame in order to output the correct image of the game!
#"Name": Records[4][ID][1],
"Location": Location,#Center of the object [x,y]
"Direction": 0,#Multiple of 45 #Used to display the unit's direction
"Size": [int(x) for x in Records[4][ID][2].split(',')],# [x,y]
"Mode": Mode,#Integer Changes how the unit behaves. Start in mode 2 to move to the target location
"Target": Target,# Target location that the sprite will move to when in mode 2
"Path": [],#Path to target location
"Threads": 0,#Keeps track of the number of threads a unit is currently running
"State": 0,# Integer 0: Idle, 1: Moving, 2: Attacking
"Animations": [[int(y) for y in x.split(',')] for x in Records[4][ID][3].split('.')],#[[List of numbers],[...],...] This corresponds to the image number to be blitted to the sprite layer in the IMAGES list #List of animations: 0: Idle, 1: Moving, 2: Attacking, 3: Damaged, 4: Dead
"Level": Level,#Integer Stats scale by StatX * (Level+Level-1)
"Stats": {#Stats contains a dictionary of the different stats #Precondition - All stats are integers
"Health": Stats[0],#Max health
"Attack": Stats[1],
"Cooldown": Stats[2],#Used to control how quickly a unit can attack #The maximum time left until the unit attacks again #Measured in frames
"Defence": Stats[3],
"Speed": Stats[4],
"Range": Stats[5],
"Multi-target": Stats[6],
"Exp": Stats[7]
},
"Current_Health": Stats[0],#Equal to Health stat
"Current_Exp": 0,
"Team": Team,# x
"Frame": 0,#Frame and Current_Frame are used to calculate which frame of animation should be playing!
"Current_Frame": 0,
#"Class": Attributes[9],# x #Unit/Building etc.
"ID": ID,#This will determine the type of attack the object will have
"Index": Index,#This is used to keep track of where in the all_Sprites group the unit is, which is also used to determine if it has been selected
"In_Range": [],#This will be used to determine which object will be attacked
"Attacked": False,#Used to change the behaviour of the unit when it's health is altered by another unit #True when it's health has been lowered!
"Attacking": [], #E.G.[[[],(0,0,0)]] # [[Location],(Colour)], ...] #List of locations used to draw lines to the sprite layer. Colours are the colour of the line that will be drawn #These are considered to be shots from the sprite
"Cooldown_Timer": Stats[2],#The remaining time (in frames) until the unit can attack again. #Also used to delay the deletion of the unit!#FIX!!! (MAYBE!!!)
"Functions": [int(x) for x in Records[4][ID][5].split(',')],#A list of the actions a unit can take.
"Invalid_Tiles": [int(x) for x in Records[4][ID][6].split(',')]#A list of all tiles that the unit can't travel on!
}
#print(OBJECT.__Attributes)
print("MADE OBJECT!!!")
if OBJECT!= Object:#If UnitID is not the ID for an Object. This prevents a crash when creating an object
print("NOT AN OBJECT!!!")
return OBJECT.__Attributes
#------------------------------------------
def Set_Attributes(OBJECT,Keys,Values):
Attacked=False
for x in range(len(Keys)):
#print(OBJECT.__Attributes[Keys[x]],Values[x])
if Keys[x]=="Health":#Check if the unit has been defeated
print(Values[x], "HEEEEEEEEEAAAAAAAAAAAALLLLLLLLLTTTTTHHHHHHHH!!!")
if Values[x]==0:
OBJECT.__Attributes["State"]=4#Dead #After the cooldown timer expires, the sprite will be deleted!
elif Values[x]<OBJECT.__Attributes["Current_Health"]:
Attacked=True
OBJECT.__Attributes[Keys[x]]=Values[x]
#Maybe improve to prevent abuse of this action?
elif Keys[x]=="State":#Check if the unit has begun to attack and prevent the unit from changing state when it has been defeated
if OBJECT.__Attributes["State"]!=4:
if Values[x]==2:#Attacking
OBJECT.__Attributes["Cooldown_Timer"]=0
elif Values[x]==3:
OBJECT.__Previous_State=OBJECT.__Attributes["State"]
OBJECT.__Attributes[Keys[x]]=Values[x]
#print(OBJECT.__Attributes["Cooldown_Timer"], "COOLDOWN!!!")
else:#Any other change that doesn't need validation
OBJECT.__Attributes[Keys[x]]=Values[x]
return Attacked
#Size of object!
def Position_Validation(OBJECT,Top_Left,Bottom_Right,Size,Location):
#Position validation (Makes sure the object isn't out of bounds!)
#------------------------------------------
Test=[[1,0],[1,0]]#reset speed to 0 if [0,x] #x indicates the side in which the object is out of bounds (-1=right/bottom side and 1=left/top side)!
#print(Top_Left,Bottom_Right)
Fix=[0,0]#Used to stop the camera from getting stuck at the edge of the screen by adding a constant value to 'fix' the problem of rounding for integers!
if Bottom_Right[0]>(SIZE[0]):#X_Co-ordinate
#print("BOTTOM RIGHT 0!!!",Bottom_Right)
Location[0]=(SIZE[0])-int(Size[0]/2)#Center of object
Test[0]=[0,-1]
Fix[0]=-0.25
#Attributes[1]=[0,0]#reset speed to 0
elif Top_Left[0]<0:
#print("TOP LEFT 0!!!")
Location[0]=0+int(Size[0]/2)+1
Test[0]=[0,1]
Fix[0]=-0.5
if Bottom_Right[1]>(SIZE[1]):#Y_Co-ordinate
#print("BOTTOM RIGHT 1!!!")
Location[1]=(SIZE[1])-int(Size[1]/2)
Test[1]=[0,-1]
Fix[1]=-0.25
elif Top_Left[1]<0:
#print("TOP LEFT 1!!!", Top_Left)
Location[1]=0+int(Size[1]/2)
Test[1]=[0,1]
Fix[1]=0.5
#------------------------------------------
return Location,Test,Fix
#----------------------------------------------------------
#----------------------------------------------------------
class Camera(Object,pygame.sprite.Sprite):
def __init__(self,Attributes):
#Complete List Of Atttributes: [Location,[Speed_X,Speed_Y],[Size_X,Size_Y],[Mode/control],Rect,State,Animations,Level,Stats,Team]
#List for Camera: [[Location_X,Location_Y],[Speed_X,Speed_Y],Accel]
#------------------------------------------
self.__Attributes= {
"Location": Attributes[0],#Top left of the camera
"Speed": Attributes[1], #[x,y]
"Acceleration": Attributes[2], #int
"Team": Attributes[3],
"Selected_List": [[[0,1],[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,8],[8,9],[9,0]], [],0,0],#[[[name,pointer],...],[Free space],start,current length] #circular Linked list #SHOULD start with the location of the selected units or at [0,0]
"Selected": 0,
"Start_Pos": [0,0],#Used to track and draw the selection box when right click is held down!
"End_Pos": [0,0]#Used to track and draw the selection box when right click is held down!
}
#Image of the whole camera overlay
#------------------------------------------
#MINI_MAP_SIZE=4 # Setting #The smaller the number (int) the bigger the size!
pygame.sprite.Sprite.__init__(self)
self.image=pygame.Surface((Settings["WIDTH"],Settings["HEIGHT"]))
self.image.convert_alpha()
self.image.set_colorkey((0,0,0))
self.image.set_alpha(150)
#Minimap #MINI_MAP_SIZE=4 # Setting #The smaller the number (int) the bigger the size!
#------------------------------------------
#Boarder for map!
self.image.fill((50,50,50,50),(self.__Attributes["Location"][0]+(Settings["WIDTH"]-(int(1/Settings["MINI_MAP_SIZE"])*Settings["WIDTH"]))-1,self.__Attributes["Location"][1],Settings["WIDTH"]//Settings["MINI_MAP_SIZE"],Settings["HEIGHT"]//Settings["MINI_MAP_SIZE"]))
#------------------------------------------
#Info bar #INFO_BAR_SIZE=4
#------------------------------------------
self.image.fill((255,255,255,255), (0,(Settings["HEIGHT"]-int(1/Settings["INFO_BAR_SIZE"]*Settings["HEIGHT"])),Settings["WIDTH"],Settings["HEIGHT"]))
#------------------------------------------
#Actions menu
#------------------------------------------
self.image.fill((255,255,255,255), (0,0,Settings["WIDTH"]//4,Settings["HEIGHT"]//4))
#------------------------------------------
#Range circle
#------------------------------------------
#Done in the update!
#------------------------------------------
#Selection box
#------------------------------------------
#Done in the update!
#------------------------------------------
#Rect/Camera Rect
#------------------------------------------
self.rect=pygame.Rect(self.__Attributes["Location"][0],self.__Attributes["Location"][1],Settings["WIDTH"],Settings["HEIGHT"])#self.image.get_rect()
#self.rect.topleft=self.__Attributes[0]
#self.rect.center=[self.__Attributes[0][0]+WIDTH//2,self.__Attributes[0][1]+HEIGHT//2]
#self.__Camera_Rect=pygame.Rect(self.__Attributes[0],self.__Attributes[1],WIDTH//Scale,HEIGHT//Scale)
#------------------------------------------
#print(self.__Attributes)
print("MADE CAMERA!!!")
def Get_Attributes(self):
#------------------------------------------
return self.__Attributes
#------------------------------------------
def update(self,Data,SUBSCREEN,Selected_Lists,IMAGES,Attributes,Records_Data):
#Data: [Key_State,Mouse_Pos (NOT adjusted), Mouse_Pos (adjusted),Mouse_State,Previous_Mouse_Pos (adjusted),Previous_Mouse_State]
#Adjustment to the Mouse_Pos etc in order to be relative to the game environment. [(Mouse_Pos[0]//Settings["SCALE"])+Camera_Attributes["Location"][0],(Mouse_Pos[1]//Settings["SCALE"])+Camera_Attributes["Location"][1]]
#How to unadjust the Mouse_Pos #[(self.__Attributes["Start_Pos"][0]-self.__Attributes["Location"][0])*Settings["SCALE"],(self.__Attributes["Start_Pos"][1]-self.__Attributes["Location"][1])*Settings["SCALE"]]
#Attributes contains: [ID,Location[0]//256,Location[0]%256,Location[1]//256,Location[1]%256,Direction,State,Level,Current_Health,Current_Exp,Current_Frame, [Null]] for each unit
#print(Attributes, "ATTRIBUTES!!!")
#print(Selected_Lists, "CAMERA LISTS!!!")
#Adjusted_Mouse_Pos=[(Data[1][0]//Settings["SCALE"])+Camera_Attributes["Location"][0],(Data[1][1]//Settings["SCALE"])+Camera_Attributes["Location"][1]]
#print(Sprite_Attributes, "ATTRIBUTES!!!")
self.image.fill((0,0,0))#Refresh the overlay
#Draw selection box
#------------------------------------------
#Calculate rect relative to the game environment based on moue input
if Data[3][2]==1:#Mouse_State[Right click]
if Data[5][2]==0:#Previous_Mouse_State[Right click]
self.__Attributes["Start_Pos"]= Data[2]
self.__Attributes["End_Pos"]= Data[2]#The End_Pos is always updated, since the calculations of which units are to be selected will be done by the server once the right click is no lnger held down!
#print(self.__Attributes["Start_Pos"],self.__Attributes["End_Pos"], "POSITIONS!!!")
#Validate position of rect to be drawn (Make sure it is inside the camera image)
#This is done to prevent the camera image from enlarging, which will slow down the game!!!
#This will use the unadjusted version of the mouse position
#The End_Pos will always be on-screen, so no validation is needed for this point
Start_Of_Rect=[int((self.__Attributes["Start_Pos"][0]-self.__Attributes["Location"][0])*Settings["SCALE"]),int((self.__Attributes["Start_Pos"][1]-self.__Attributes["Location"][1])*Settings["SCALE"])]
#print(Start_Of_Rect)
#print(abc)
if Start_Of_Rect[0]<0:#Left side of the screen
Start_Of_Rect[0]=0#This is adjusted outside of the game environment (Start and End Pos use the game environment's dimensions, but the camera image uses the normal screen dimensions)
elif Start_Of_Rect[0]>Settings["WIDTH"]:#Right side of the screen
Start_Of_Rect[0]=Settings["WIDTH"]
if Start_Of_Rect[1]<0:#Top of the screen
Start_Of_Rect[1]=0
elif Start_Of_Rect[1]>Settings["HEIGHT"]:#Bottom of the screen
Start_Of_Rect[1]=Settings["HEIGHT"]
#Draw rect
#The processing for the selection box will be done in the server!
#print(self.__Attributes["Start_Pos"],self.__Attributes["End_Pos"],Top_Left, "ATTTTTTTTTTR!!!")
#print(min(Top_Left[0],self.__Attributes["End_Pos"][0]),min(Top_Left[1],self.__Attributes["End_Pos"][1]),abs(Top_Left[0]-self.__Attributes["End_Pos"][0]),abs(Top_Left[1]-self.__Attributes["End_Pos"][1]), "RECT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
self.image.fill((150,150,150,255),(min(Start_Of_Rect[0],Data[1][0]),min(Start_Of_Rect[1],Data[1][1]),abs(Start_Of_Rect[0]-Data[1][0]),abs(Start_Of_Rect[1]-Data[1][1])))
#Current_Mouse_Pos
#------------------------------------------
#Check for Lock_On and Movement of the camera
#------------------------------------------
Return=self.Lock_On(Data[0],Selected_Lists[self.__Attributes["Team"]],Attributes)
print(Return)
if Return==False:#Do all of the things required when true inside this function!
#Move
#------------------------------------------
self.Move(Data[1])#Mouse_Pos
#------------------------------------------
else:
#Draw range circle
#------------------------------------------
#FIX!!! #Change to red when an enemy unit is in range!
#Gray if no enemy is within range, and red if there is at least one in range
print(self.__Attributes["Selected"], "Selected unit!!!")
Location=[(Attributes[Selected_Lists[self.__Attributes["Team"]][self.__Attributes["Selected"]]][1]*256)+Attributes[Selected_Lists[self.__Attributes["Team"]][self.__Attributes["Selected"]]][2],(Attributes[Selected_Lists[self.__Attributes["Team"]][self.__Attributes["Selected"]]][3]*256)+Attributes[Selected_Lists[self.__Attributes["Team"]][self.__Attributes["Selected"]]][4]]
Change=[0,0]
#Change the location of the range circle on the screen when the unit is near the edge of the map!
#print(Location)
if (Location[0]*Settings["SCALE"])<Settings["WIDTH"]//2:#x-axis
#print("Left side!!!")
Change[0]=(Settings["WIDTH"]//2)-(Location[0]*Settings["SCALE"])
elif ((SIZE[0]-(Location[0]))*Settings["SCALE"])<Settings["WIDTH"]//2:
#print("right side!!!")
Change[0]=(Settings["WIDTH"]//2)-((SIZE[0]-(Location[0]))*Settings["SCALE"])
if (Location[1]*Settings["SCALE"])<Settings["HEIGHT"]//2:#y-axis
#print("top!!!")
Change[1]=(Settings["HEIGHT"]//2)-(Location[1]*Settings["SCALE"])
elif ((SIZE[1]-(Location[1]))*Settings["SCALE"])<Settings["HEIGHT"]//2:
#print("Bottom!!!")
Change[1]=(Settings["HEIGHT"]//2)-((SIZE[1]-(Location[1]))*Settings["SCALE"])
#print(Change, "CHANGE!!!") #Radius of the circle #Range of selected unit: #ID of the selected_Unit #Value of range in Records_Data (each section is contained in 2 lists at the moment, therefore more indexes are needed!!!
pygame.draw.circle(self.image,(50,50,50,255),[(Settings["WIDTH"]//2)+14-Change[0],(Settings["HEIGHT"]//2)+14-Change[1]], int(Records_Data[Attributes[Selected_Lists[self.__Attributes["Team"]][self.__Attributes["Selected"]]][0]][3][0][5]),0)
#------------------------------------------
#Update Info bar #Max size of 8 units
#------------------------------------------
self.image.fill((200,200,200,255), (0,(Settings["HEIGHT"]-int(1/Settings["INFO_BAR_SIZE"]*Settings["HEIGHT"])),Settings["WIDTH"],Settings["HEIGHT"]))
print(len(Selected_Lists[self.__Attributes["Team"]]), "LENGTH!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
for x in range(len(Selected_Lists[self.__Attributes["Team"]])):
#Highlight the currently selected unit
if x ==self.__Attributes["Selected"]:
#Change the colour depending on the team of the unit
#FIX - Keep track of the different team colours for multi-player, then use this colour to determine this colour
#print(Attributes, "ATTRIBUTES!!!")#Doesn't yet contain the team
#print(abc)
#Colour=Colours[ Attributes[Selected_Lists[self.__Attributes["Team"]][x]] ["Team"]
self.image.fill((50,50,50,255),( int((Settings["WIDTH"]*((x%4)/5))), int(Settings["HEIGHT"]-((1/Settings["INFO_BAR_SIZE"])*Settings["HEIGHT"])+((x//4)*int(((1/Settings["INFO_BAR_SIZE"])*Settings["HEIGHT"])//2))), int((Settings["WIDTH"]*(1/5))), int(((1/Settings["INFO_BAR_SIZE"])*Settings["HEIGHT"])//2)))
###
print("LOOP:", x)
#Attributes contains: [ID,Location[0]//256,Location[0]%256,Location[1]//256,Location[1]%256,Direction,State,Level,Current_Health,Current_Exp,Current_Frame, [Null]] for each unit
#Image of the sprite #ID of Selected unit #State of selected unit #Current frame of selected unit
Image=pygame.transform.scale(IMAGES[int(Records_Data[Attributes[Selected_Lists[self.__Attributes["Team"]][x]][0]][2][Attributes[Selected_Lists[self.__Attributes["Team"]][x]][7]][Attributes[Selected_Lists[self.__Attributes["Team"]][x]][11]])], (Settings["WIDTH"]//20, int(Settings["HEIGHT"]*(0.25/Settings["INFO_BAR_SIZE"])) ))
Top_Left=[int((Settings["WIDTH"]*((x%4)/5))+Settings["WIDTH"]//10),int(Settings["HEIGHT"]-((1/Settings["INFO_BAR_SIZE"])*Settings["HEIGHT"])+((x//4)*int(((1/Settings["INFO_BAR_SIZE"])*Settings["HEIGHT"])//2))+int(Settings["HEIGHT"]*((1/Settings["INFO_BAR_SIZE"])))//16)]
Bottom_Right=[Top_Left[0]+Settings["WIDTH"]//20,Top_Left[1]+int(Settings["HEIGHT"]*(0.25/Settings["INFO_BAR_SIZE"]))]
#print(Top_Left,Bottom_Right)
self.image.blit(Image, (Top_Left[0],Top_Left[1]))
#Hp bar of the sprite
Split_Health=int((Attributes[Selected_Lists[self.__Attributes["Team"]][x]][9]/int(Records_Data[Attributes[Selected_Lists[self.__Attributes["Team"]][x]][0]][3][0][0])))#*((Settings["WIDTH"]//20)-1))#Split between drawing in different colours #Current health / #Health stat of the selected unit *Width of the bar ([ID][Stats][particular stat])
self.image.fill((50,50,50,50), (Top_Left[0]-1,Bottom_Right[1]+5, (Settings["WIDTH"]//20)+1,5) )
self.image.fill((0,255,0,255), (Top_Left[0],Bottom_Right[1]+6,Split_Health*((Settings["WIDTH"]//20)-1),3))
self.image.fill((255,0,0,255), (Top_Left[0]+Split_Health*((Settings["WIDTH"]//20)-1),Bottom_Right[1]+6,int((1-Split_Health)*((Settings["WIDTH"]//20)-1)),3))
#Exp bar of the sprite
Split_Exp=int((Attributes[Selected_Lists[self.__Attributes["Team"]][x]][10]/int(Records_Data[Attributes[Selected_Lists[self.__Attributes["Team"]][x]][0]][3][0][7])))#*((Settings["WIDTH"]//20)-1))#Split between drawing in different colours #Current health / #Health stat of the selected unit *Width of the bar ([ID][Stats][particular stat])
self.image.fill((50,50,50,50), (Top_Left[0]-1,Bottom_Right[1]+11, (Settings["WIDTH"]//20)+1,5) )
self.image.fill((0,0,255,255), (Top_Left[0],Bottom_Right[1]+12,Split_Exp*((Settings["WIDTH"]//20)-1),3))
self.image.fill((255,0,0,255), (Top_Left[0]+Split_Exp*((Settings["WIDTH"]//20)-1),Bottom_Right[1]+12,int((1-Split_Exp)*((Settings["WIDTH"]//20)-1)),3))
#Display the locked_on sprite's stats #FINISH!!!
#------------------------------------------
#Unit's stats circle
self.image.fill((150,150,150,255), (int(Settings["WIDTH"]*4/5), (Settings["HEIGHT"]-int(1/Settings["INFO_BAR_SIZE"]*Settings["HEIGHT"])),int(Settings["WIDTH"]*1/5),int(1/Settings["INFO_BAR_SIZE"]*Settings["HEIGHT"])))
pygame.draw.circle(self.image,(50,50,50,255),(int(Settings["WIDTH"]*9/10),(Settings["HEIGHT"]-int((1/2)*(1/Settings["INFO_BAR_SIZE"]*Settings["HEIGHT"])))),60)
#------------------------------------------
#------------------------------------------
#Update Actions menu
#------------------------------------------
self.image.fill((255,255,255,50), (0,0,Settings["WIDTH"]//4,Settings["HEIGHT"]//4))
#------------------------------------------
#------------------------------------------
#Update Minimap #MINI_MAP_SIZE=4 #INFO_BAR_SIZE=4 # Settings
#------------------------------------------
#Determining what to display as the minimap and where
RECT=pygame.Rect((Settings["WIDTH"]-int((1/Settings["MINI_MAP_SIZE"])*Settings["WIDTH"])),0,Settings["WIDTH"]//Settings["MINI_MAP_SIZE"],Settings["HEIGHT"]//Settings["MINI_MAP_SIZE"])
IMAGE=pygame.transform.scale(SUBSCREEN,(Settings["WIDTH"]//Settings["MINI_MAP_SIZE"],Settings["HEIGHT"]//Settings["MINI_MAP_SIZE"]))
#Boarder of the minimap
self.image.fill((50,50,50),((Settings["WIDTH"]-int((1/Settings["MINI_MAP_SIZE"])*Settings["WIDTH"])),0,Settings["WIDTH"]//Settings["MINI_MAP_SIZE"],Settings["HEIGHT"]//Settings["MINI_MAP_SIZE"]))
#The minimap
self.image.blit(IMAGE,RECT)#,special_flags=pygame.BLEND_RGBA_ADD)#((Settings["WIDTH"]-(int(1/Settings["MINI_MAP_SIZE"])*Settings["WIDTH"])),0))#RECT)
self.rect=pygame.Rect(0,0,Settings["WIDTH"],Settings["HEIGHT"])
#------------------------------------------
#Position validation
#------------------------------------------
#Makes sure the camera isn't out of bounds!
Return=Object.Position_Validation(self,self.__Attributes["Location"],[self.__Attributes["Location"][0]+(Settings["WIDTH"]/Settings["SCALE"]),self.__Attributes["Location"][1]+(Settings["HEIGHT"]/Settings["SCALE"])],[Settings["WIDTH"]//Settings["SCALE"],Settings["HEIGHT"]//Settings["SCALE"]],[self.__Attributes["Location"][0]+(Settings["WIDTH"]/(2*Settings["SCALE"])),self.__Attributes["Location"][1]+(Settings["HEIGHT"]/(2*Settings["SCALE"]))])
#print(Return)
self.__Attributes["Speed"]=[self.__Attributes["Speed"][0]*Return[1][0][0],self.__Attributes["Speed"][1]*Return[1][1][0]]
self.__Attributes["Location"]=[Return[0][0]-(Settings["WIDTH"]/(2*Settings["SCALE"]))+Return[2][0],Return[0][1]-(Settings["HEIGHT"]/(2*Settings["SCALE"]))+Return[2][1]]
#print("POSITION!!!", self.__Attributes["Location"],[self.__Attributes["Location"][0]+(Settings["WIDTH"]/Settings["SCALE"]),self.__Attributes["Location"][1]+(Settings["HEIGHT"]/Settings["SCALE"])])
#print("SPEED!!!", self.__Attributes[1])
#------------------------------------------
def Move(self,Mouse_Pos):#Use Object.Get_Attributes(self) to obtain the attributes for the camera!
Deceleration=1/Settings["SCALE"]#Setting #Make sure both the Accel and Decel are even numbers to prevent jittering of the camera!
#gradual decceleration until the camera stops moving
#------------------------------------------
if self.__Attributes["Speed"][0]>0:#SpeedX
self.__Attributes["Speed"][0]-=Deceleration
if self.__Attributes["Speed"][0]<0:
self.__Attributes["Speed"][0]=0
elif self.__Attributes["Speed"][0]<0:
self.__Attributes["Speed"][0]+=Deceleration
if self.__Attributes["Speed"][0]>0:
self.__Attributes["Speed"][0]=0
if self.__Attributes["Speed"][1]>0:#SpeedY
self.__Attributes["Speed"][1]-=Deceleration
if self.__Attributes["Speed"][1]<0:
self.__Attributes["Speed"][1]=0
elif self.__Attributes["Speed"][1]<0:
self.__Attributes["Speed"][1]+=Deceleration
if self.__Attributes["Speed"][1]>0:
self.__Attributes["Speed"][1]=0
#------------------------------------------
#Acceleration depending on mouse position
#------------------------------------------
if Mouse_Pos[0]>(Settings["WIDTH"]-50):#Move left (scroll camera right)
self.__Attributes["Speed"][0]+=self.__Attributes["Acceleration"]#self.Camera_Speedx-=Camera_Accel
#print("MOVE RIGHT!!!")
elif Mouse_Pos[0]<50:#Move right (scroll camera left)
self.__Attributes["Speed"][0]-=self.__Attributes["Acceleration"]#Camera_Speedx+=Camera_Accel
#print("MOVE LEFT!!!")
if Mouse_Pos[1]<50:#Move downwards (scroll camera downwards)
self.__Attributes["Speed"][1]-=self.__Attributes["Acceleration"]#Camera_Speedy-=Camera_Accel
#print("MOVE UP!!!")
elif Mouse_Pos[1]>(Settings["HEIGHT"]-50):#Move upwards (scroll camera upwards)
self.__Attributes["Speed"][1]+=self.__Attributes["Acceleration"]#Camera_Speedy+=Camera_Accel
#print("MOVE DOWN!!!")
#------------------------------------------
#Speed validation
#------------------------------------------
if self.__Attributes["Speed"][0]>Settings["MAX_CAMERA_SPEED"]:
self.__Attributes["Speed"][0]=Settings["MAX_CAMERA_SPEED"]
elif self.__Attributes["Speed"][0]<-Settings["MAX_CAMERA_SPEED"]:
self.__Attributes["Speed"][0]=-Settings["MAX_CAMERA_SPEED"]
if self.__Attributes["Speed"][1]>Settings["MAX_CAMERA_SPEED"]:
self.__Attributes["Speed"][1]=Settings["MAX_CAMERA_SPEED"]
elif self.__Attributes["Speed"][1]<-Settings["MAX_CAMERA_SPEED"]:
self.__Attributes["Speed"][1]=-Settings["MAX_CAMERA_SPEED"]
#------------------------------------------
#Move camera
#------------------------------------------
self.__Attributes["Location"][0]+=self.__Attributes["Speed"][0]#//Scale#
self.__Attributes["Location"][1]+=self.__Attributes["Speed"][1]#//Scale#
#print(self.__Attributes[0],"LOCATION")
#print(self.__Attributes[1], "SPEED")
#------------------------------------------
def Lock_On(self,Key_State,Selected_List,Attributes):
#Attributes contains: [ID,Location[0]//256,Location[0]%256,Location[1]//256,Location[1]%256,Direction,State,Level,Current_Health,Current_Exp,Current_Frame, [Null]] for each unit
#If any units are selected, then the unit in the position of the "Selected" attribute will be locked onto!
#If shift is held down, then no unit will be locked onto. This will be done so that the player can select a far away distance for the selected units to travel to!
Locked_On=False
#print(Selected_List, "SELECTED TEST!!!")
if len(Selected_List)>0:
self.__Attributes["Selected"]==self.__Attributes["Selected"]%len(Selected_List)
#Tab controls!!!
if Key_State[pygame.K_TAB]==1:
print("PRESSING TAB KEY!!! NOW PRESS 1-8!!!")
for x in range(8):#Selects the highest key that is pressed down in the event of multiple keys being pressed simultaneously
#print(x)
if Key_State[pygame.K_1+x]==1 and (x+1)<=len(Selected_List):#keys 1 through 0 inclusive on the keyboard [1,2,3,4,5,6,7,8,9,0]
self.__Attributes["Selected"]=x
#else:
# print("INVALID UNIT SELECTION!!!")
if Key_State[pygame.K_LSHIFT]==0 and Key_State[pygame.K_RSHIFT]==0:#Only lock on if shift isn't held down
#print(Attributes, "ATTRIBUTES!!!")
Location=[(Attributes[Selected_List[self.__Attributes["Selected"]]][1]*256)+Attributes[Selected_List[self.__Attributes["Selected"]]][2],(Attributes[Selected_List[self.__Attributes["Selected"]]][3]*256)+Attributes[Selected_List[self.__Attributes["Selected"]]][4]]
self.__Attributes["Location"]=[Location[0]-Settings["WIDTH"]/(2*Settings["SCALE"]),Location[1]-Settings["HEIGHT"]/(2*Settings["SCALE"])]#Location=Sprite's location adjusted so that it lies in the center of the screen!
self.__Attributes["Speed"]=[0,0]#Reset speed
#self.__Attributes["Acceleration"]=0
print("LOCKED ON!!!")
Locked_On=True
return Locked_On
def Display_Info(self,SPRITE):
print("HI")
#----------------------------------------------------------
#----------------------------------------------------------
class Sprite(Object,pygame.sprite.Sprite):
def __init__(SPRITE, ID, Location, Team, Target, Level, Records, Mode, Index):
#Complete List Of Atttributes: [Location,[Size_X,Size_Y],[Mode/control],Rect,State,Animations,Level,Stats,Team]
#---------------------------------------
SPRITE.__Attributes=Object.__init__(SPRITE, ID, Location, Team, Target, Level, Records, Mode, Index)
#print(SPRITE.__Attributes)
pygame.sprite.Sprite.__init__(SPRITE)
#---------------------------------------
#Image
#---------------------------------------
SPRITE.rect=pygame.Rect(SPRITE.__Attributes["Location"][0]-(SPRITE.__Attributes["Size"][0]//2),SPRITE.__Attributes["Location"][1]-(SPRITE.__Attributes["Size"][1]//2),SPRITE.__Attributes["Size"][0],SPRITE.__Attributes["Size"][1])
SPRITE.rect.center=(SPRITE.__Attributes["Location"][0],SPRITE.__Attributes["Location"][1])
#For testing purposes!!!
#---------------------------------------
#self.image=pygame.Surface((self.__Attributes[1][0],self.__Attributes[1][1]))
#self.image.fill((0,255,0))
#self.origional_image=self.image
#self.rect=self.image.get_rect()
#self.rect.center=self.__Attributes[0]
#print(SPRITE.__Attributes["Animations"])
#self.image=pygame.transform.scale(self.image,(self.__Attributes[1][0],self.__Attributes[1][1]))#change size of image
#SPRITE.image.set_colorkey(000,0)#make this colour (black) transparent using RGB values
#SPRITE.origional_image=SPRITE.image#Used for rotation
#---------------------------------------
print("MADE SPRITE!!!")
if SPRITE!=Sprite:
print("NOT A SPRITE!!!")
return SPRITE.__Attributes
def Get_Attributes(self):
#------------------------------------------
return self.__Attributes
#------------------------------------------
def Set_Attributes(self,Attributes,Values):
#------------------------------------------
self.__Attributes=Object.Set_Attributes(self,self.__Attributes,Attributes,Values)
#------------------------------------------
def update(SPRITE):
#Updates the frame of animation the sprite will display
#Makes sure the sprite is in-bounds
#Image
#---------------------------------------
SPRITE.__Attributes["Frame"]=(SPRITE.__Attributes["Frame"]+1)%Settings["FPS"]#use interpolation here!!!
SPRITE.__Attributes["Current_Frame"]=round((SPRITE.__Attributes["Frame"]/Settings["FPS"])*(len(SPRITE.__Attributes["Animations"][SPRITE.__Attributes["State"]])-1)) #the -1 is because list indexing starts at 0 rather than 1!!!
#---------------------------------------
#Position validation (Makes sure the sprite isn't out of bounds or on an invalid tile!)
#------------------------------------------ #Top left of the sprite
Return=Object.Position_Validation(SPRITE,[SPRITE.__Attributes["Location"][0]-(SPRITE.__Attributes["Size"][0]/2),SPRITE.__Attributes["Location"][1]-(SPRITE.__Attributes["Size"][1]/2)],[SPRITE.__Attributes["Location"][0]+(SPRITE.__Attributes["Size"][0]/2),SPRITE.__Attributes["Location"][1]+(SPRITE.__Attributes["Size"][1]/2)],SPRITE.__Attributes["Size"],SPRITE.__Attributes["Location"])
SPRITE.__Attributes["Location"]=Return[0] #Location adjusted for the sides of the screen
SPRITE.rect.center=(SPRITE.__Attributes["Location"][0],SPRITE.__Attributes["Location"][1])
#print(Return)
#------------------------------------------
#----------------------------------------------------------
#----------------------------------------------------------
class Unit(Sprite):
#self.Add_Sprite(Unit([[300,300],[5,5],[1,1],[0,0],0,[[0,0,0,0,1,1,1,1],[0,1,2,3,4,5,6,7]],1,[1,0,0,0,0,0,0,0],0,2,0,1]),0)
#list of animations (image numbers)
#Animations: 0. Idle, 1. Moving, 2. Attacking, 3. Getting hit(flash of white), 4. Building
def __init__(self, ID, Location, Team, Target, Level, Records, Mode, Index):
#Complete List Of Atttributes: [Location,[Size_X,Size_Y],[Mode/control],Rect,State,Animations,Level,Stats,Team]
#---------------------------------------
self.__Attributes=Sprite.__init__(self, ID, Location, Team, Target, Level, Records, Mode, Index)
print("UNIT ATTRIBUTES", self.__Attributes)
#self.image=pygame.transform.scale(self.image,(self.__Attributes["Size"][0],self.__Attributes["Size"][1]))#change size of image
#Attributes that shouldn't be altered by the player!
self.__Speed=[0,0]#Not the Unit's speed stat! Used to calculate the movement of the unit based on the speed stat (Which is the first value in self.__Attributes[8])!
self.__Previous_Location=[0,0]
self.__Reset=0#Reset from damaged animation
self.__Previous_State=0#State to return to after any damage has been taken
#if Attributes[9]!=2:#If the type is not a unit (E.G. using the Unit init function through inheritance)
# return self.__Attributes
#print(self.__Attributes)
#print(self.rect)
#---------------------------------------
def Get_Attributes(self):
#------------------------------------------
return self.__Attributes
#------------------------------------------
def Set_Attributes(self,Keys,Values):
#------------------------------------------
#print(Keys,Values)
#print(self.__Attributes)
Attacked=Object.Set_Attributes(self,Keys,Values)
self.__Attributes["Attacked"]=Attacked#Check to see if the unit has been attacked or not. This acts as a flag that will be reset in the Check_Attack method!
#------------------------------------------
#print(self.__Attributes)
def update(self,Data,Selected_Lists, Map_Data):
#A sprite will update based on its team's input
#The data is the data from each client
#Data: [Key_State, Mouse_Pos relative to the game environment, Mouse_State] for each client!
#print(Data)
#---------------------------------------
#Keystate=pygame.key.get_pressed()#This will be done in the game loop!
Return=self.Check_Mode(Data,Selected_Lists)
if type(Data[self.__Attributes["Team"]])!=int and self.__Attributes["State"]!=4:#If the sprite's team is not responding to the server, then an integer will be sent instead of the player's input. This means that the sprite doesn't need to check it's movement this frame!
self.Check_Movement(Data[self.__Attributes["Team"]],Map_Data)
self.Check_Attack(Data[self.__Attributes["Team"]][0])
self.Check_Stats()#Includes health and exp!
Sprite.update(self)#Includes updating the frames of animation along with the position validation
#print("TILE NUMBER!!!", Map_Data[0][self.__Attributes["Location"][1]//20][self.__Attributes["Location"][0]//20])
#[0], since the tiles will only change when animation is implemented, in which the additional tiles will have the same properties as those present on frame 0!
#REMEMBER the tiles in Map_Data are all held as strings NOT integers!!!
if Map_Data[0][self.__Attributes["Location"][1]//20][self.__Attributes["Location"][0]//20] in self.__Attributes["Invalid_Tiles"]:#FIX to include all invalid tiles for a particular sprite!!!
self.Move_Back()
print("Should have moved back!!!")
#---------------------------------------
def Check_Mode(self,Data,Selected_Lists):#Checks the mode of the sprite, along with resetting the damaged animation! #These are updated when the right click is held down!
#Data[x]: [Key_State, Mouse_Pos adjusted for the camera position, Mouse_State, Previous_Mouse_Pos, Previous_Mouse_State,Start_Pos,End_Pos] for team x
#Selected_Lists should be passed by reference!!!
#print(Data, "DATA!!!")
print(Selected_Lists, "SELECTED LISTS!!!")
#Change the animations of the sprites
#------------------------------------------
if self.__Attributes["State"]==3:#Damaged
self.__Reset+=1#Used to reset the animation to its previous state after 1 frame, making the sprite flash white
#print(self.__Reset, "RESET")
elif self.__Attributes["State"]==4:#Defeated
self.__Attributes["Cooldown_Timer"]-=1#Used to delete the unit
#print("COOLDOWN!!!", self.__Attributes["Cooldown_Timer"])
if self.__Reset>1:#If the unit was damaged the previous frame
self.__Attributes["State"]=self.__Previous_State
self.__Reset=0
#print(self.__Attributes["State"], "STATE!!!")
#self.__Attributes["State"]=0
#------------------------------------------
#Change the modes of the sprites
#------------------------------------------
for x in range(len(Data)):#x is the team number!
if type(Data[x])==int:#This must be done, since each input is processed, rather than just the input from the sprite's team!
#print("INVALID DATA FROM TEAM", x)
pass
else:
#Used to calculate whether a mouse press is inside the sprite
Left=self.__Attributes["Location"][0]-(self.__Attributes["Size"][0]//2)
Top=self.__Attributes["Location"][1]-(self.__Attributes["Size"][1]//2)
#Left click
#------------------------------------------
#Mouse_State[0]
if Data[x][2][0]==1:#If left mouse butten is pressed down
#Left click + Shift
#------------------------------------------
#Regardless of the mode, if selected and this is received by its team's camera, then the unit will change to mode 2
#Key_State[pygame.K_LSHIFT] etc.
if (Data[x][0][pygame.K_LSHIFT] or Data[x][0][pygame.K_RSHIFT])==True:
print("LEFT CLICK + SHIFT!!!")
print(Selected_Lists, "SELECTED LISTS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
if self.__Attributes["Index"] in Selected_Lists[x]:
print("YEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEES!!!")
print(bool(self.__Attributes["Team"]==x and self in Selected_Lists[x]))
if (self.__Attributes["Team"]==x and self in Selected_Lists[x]):
#If selected by its team's camera:
print("IT WORKS!!!")
#Change to mode 2
self.__Attributes["Mode"]=2
#print(Data[x], "DATA", x)
self.__Attributes["Target"]=Data[x][1]#Mouse position adjusted for camera position
print("TARGET", self.__Attributes["Target"], "LOCATION", self.__Attributes["Location"])
self.__Attributes["Path"]=[]#This will allow the unit to immediately change its target without ending up in the wrong location
print("CHANGE TO MODE 2!!!!")
#------------------------------------------
#CRASHES HERE!!!
#Just left click
#------------------------------------------
#This depends on the mode of the unit
else:
print("LEFT CLICKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK!!!", self.__Attributes["Mode"])
#If in mode 0 or 2
#------------------------------------------
#If inside the unit, change mode to mode 1 if on the same team
#Then, regardless of the team, deselect all of that team's units and select this unit by itself
print(Selected_Lists, "SELECTED LISTS")
print(self.__Attributes["Mode"], "MODE!!!")
print("TESTING:", Data[x][1], Left, Left+self.__Attributes["Size"][0])
#Check if the click is inside the unit
#Mouse_Pos[0] #Mouse_Pos[1]
if ((Data[x][1][0]*256)+Data[x][1][1]) in range(Left,(Left+self.__Attributes["Size"][0])) and ((Data[x][1][2]*256)+Data[x][1][3]) in range(Top,(Top+self.__Attributes["Size"][1])):
print("Team:", x, "pressed the left mouse button at", Data[x][1])
#print("TOP LEFT", Left,Top)
if self.__Attributes["Mode"]!=1:
#Change modes if the same team as the camera
if self.__Attributes["Team"]==x:
self.__Attributes["Mode"]=1
#reset movement if in mode 2
self.__Attributes["Target"]=[-1,-1]
self.__Attributes["Path"]=[]
#Remove all other selected units # Done in the server!!!
#Select the unit
#try:
Selected_Lists[x].append(self.__Attributes["Index"])
print("ADDED UNIT TO SELECTED LISTS!!!", Selected_Lists)
#except len(Selected_Lists[x])>8:#Return an error message if the length of the selected list is too long!
#print("Selected_List", x, "is full!!!")
#------------------------------------------
#If in mode 1
#------------------------------------------
#If outside the unit, change mode to mode 0 if on the same team
#Then, regardless of the team, deselect this unit
elif self.__Attributes["Mode"]==1:
print("MOOOOOOOOOOOOOOOOOODE 1!!!", Data[x][1], Left, Left+self.__Attributes["Size"][0], Top, Top+self.__Attributes["Size"][1])
#Change modes if the same team as the camera
if self.__Attributes["Team"]==x:
self.__Attributes["Mode"]=0
#De-select the unit
print(self.__Attributes["Mode"])
try:
Selected_Lists[x].remove(self.__Attributes["Index"])
except ValueError:#Return an error message if the length of the selected list is too long!
print("Selected_List", x, "doesn't contain this sprite!!!")
#------------------------------------------
#------------------------------------------
#Right click
#------------------------------------------#Finish11!!!
#If shift is held down, the camera will not lock onto any units!!!
#A rect box will be created by the client's camera whilst they hold down right click.
#Once they have released right click. The unit will check if its location is inside the boundaries between the start and end position
#If inside the rect, select the unit if the selected list is not full!
#This will be done on the client side except for when there is both a start and end position is present
#If right mouse butten has been held down and the sprite is in range of the rect created, then select it regardless of the mode or team
#Start of hold End of hold
Hold=[(Data[x][5][0]*256)+Data[x][5][1],(Data[x][5][2]*256)+Data[x][5][3],(Data[x][6][0]*256)+Data[x][6][1],(Data[x][6][2]*256)+Data[x][6][3]]#Locations of the selection box created when holding right click
#Mouse_State[1] #Previous_Mouse_State[1] #Start of hold[0],End of hold[0] #Start of hold[1],End of hold[1]
if (Data[x][2][2]==0 and Data[x][4][2]==1) and self.__Attributes["Location"][0] in range(int(min(Hold[0],Hold[2])), int(max(Hold[0],Hold[2]))) and self.__Attributes["Location"][1] in range(int(min(Hold[1],Hold[3])),int(max(Hold[1],Hold[3]))):
if len(Selected_Lists[x])<8:#If not full
Selected_Lists[x].append(self.__Attributes["Index"])
print("ADDED UNIT!!!")
#------------------------------------------
#------------------------------------------
def Check_Movement(self,Data,Map_Data):
#Data: [Key_State, Mouse_Pos, Mouse_State, Camera_Pos] for each client!
#print(Data)
#print(self.rect.center)
self.__Previous_Location=self.rect.center
#Mode 0
#---------------------------------------
#Do nothing
#---------------------------------------
#Mode 1
#---------------------------------------
#Move depending on the keyboard input
if self.__Attributes["Mode"]==1:#mode
#Movement speed
#---------------------------------------
#Stats[Speed] Key_State[pygame.K_RIGHT] etc.
self.__Speed[0]=self.__Attributes["Stats"]["Speed"]*((Data[0][pygame.K_RIGHT] or Data[0][pygame.K_d])-(Data[0][pygame.K_LEFT] or Data[0][pygame.K_a]))
#Upwards movement-downwards movement
self.__Speed[1]=self.__Attributes["Stats"]["Speed"]*((Data[0][pygame.K_DOWN] or Data[0][pygame.K_s])-(Data[0][pygame.K_UP] or Data[0][pygame.K_w]))
##---------------------------------------
#Direction
#---------------------------------------
Direction_x=90*((Data[0][pygame.K_RIGHT] or Data[0][pygame.K_d])-(Data[0][pygame.K_LEFT] or Data[0][pygame.K_a]))
Direction_y=45*((Data[0][pygame.K_DOWN] or Data[0][pygame.K_s])-(Data[0][pygame.K_UP] or Data[0][pygame.K_w]))
if Direction_x==90:
self.__Attributes["Direction"]=Direction_x+Direction_y
elif Direction_x==-90:
self.__Attributes["Direction"]=Direction_x-Direction_y
elif Direction_y!=0:#This should allow the sprite to face the same direction that it will travel in when no keys are pressed!
#downwards direction check
self.__Attributes["Direction"]=0-180*(Data[0][pygame.K_DOWN] or Data[0][pygame.K_s])
#print(self.__Attributes["Direction"])
#---------------------------------------
#---------------------------------------
#Mode 2
#---------------------------------------
elif self.__Attributes["Mode"]==2:
#print("THREADS:", self.__Attributes["Threads"])
#Decide what to do
#------------------------------------------
if self.__Attributes["Location"]==self.__Attributes["Target"]:
#Change to mode 0
self.__Attributes["Mode"]=0
#Reset threads attribute
self.__Attributes["Threads"]=0
#Reset the path attribute
self.__Attributes["Path"]=[]
elif len(self.__Attributes["Path"])==0:#If no threads or path and the current location isn't equal to the target location, then create a thread
if self.__Attributes["Threads"]==0:
#Create a shortest path
self.__Attributes["Threads"]+=1
print("SHORTEST PATH!!!")
Shortest_Path_Algorithm=Thread(self.Shortest_Path,Map_Data)
#Shortest_Path_Algorithm.start()#Automatically changes the path attribute of the unit, then resets the threads attribute
print(self.__Attributes["Path"], "Path in the main thread!!!")
print("HIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII")
else:#Move depending on the path created
print("PATH WHEN MOVING!!!", self.__Attributes["Path"])
self.__Attributes["Location"]=[self.__Attributes["Location"][0]+self.__Attributes["Path"][0][0],self.__Attributes["Location"][1]+self.__Attributes["Path"][0][1]]
del self.__Attributes["Path"][0]#remove index 0!!!
print(self.__Attributes["Path"], "PATH NOW!!!")
#------------------------------------------
#---------------------------------------
#---------------------------------------
#calculate movement (All modes)
#---------------------------------------
self.__Attributes["Location"]=[self.__Attributes["Location"][0]+self.__Speed[0],self.__Attributes["Location"][1]+self.__Speed[1]]
#self.rect.center=self.__Attributes[0]#Thhis will be done when calling the sprite update function!
#---------------------------------------
#move the rect (All modes)
#---------------------------------------
#The rect itself doesn't change!
self.rect.center=self.__Attributes["Location"][0],self.__Attributes["Location"][1]
#---------------------------------------
def Move_Back(self):#Return to previous location
#print(self.__Previous_Location,self.__Attributes["Location"])
self.rect.center=self.__Previous_Location
self.__Attributes["Location"]=[self.rect.center[0],self.rect.center[1]]
#print(self.rect.center,"UPDATED!")
def Check_Attack(self,Key_State):
#Key_State of the unit's team used in mode 1
#A check for any collisions will occur in the main game loop
#print(self.__Attributes["In_Range"])
#print(Key_State[pygame.K_SPACE], "SPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACE!!!")
if len(self.__Attributes["In_Range"])>0:
#Mode 0
#---------------------------------------
#If attacked, automatically attack back via cpu(switch to mode 2)
#Team checking will occur here
if self.__Attributes["Mode"]==0:
self.__Attributes["Mode"]=2
self.__Attributes["Target"]=self.__Attributes["Location"]#Make sure the unit doesn't move until the unit has checked its target in mode 2!
#---------------------------------------
#Mode 1
#---------------------------------------
#If space bar pressed, do attack animation and check the 1/4 circle radius for any other sprite from another team. If any collisions occur, set that unit's health to a lower ammount dependent on the attack stat etc
#The range circle will appear red#THIS WILL BE DONE BY THE CAMERA!!!
elif self.__Attributes["Mode"]==1:
if Key_State[pygame.K_SPACE]==1:# or (self.__Attributes["Mode"][0]==1 and self.__Attributes["Action"]=="Attack")):#NOT#Test for the right team will be done in the collision detection!
#Change to attack animation
#---------------------------------------
if self.__Attributes["State"] not in [2,3]:#If not already attacking, being damaged or dead
self.__Attributes["Cooldown_Timer"]=0
self.__Attributes["State"]=2#Attacking
#print(self.__Attributes["Cooldown_Timer"])
#---------------------------------------
#Function depends on the unitID of the unit!!!
#---------------------------------------
if self.__Attributes["ID"] in range(0,5) and self.__Attributes["Cooldown_Timer"]==0:#Attack the closest enemy
#for x in range(len(self.__Attributes["Multi-target"])):
x=0
y=0
while (y!=self.__Attributes["Stats"]["Multi-target"] and x<len(self.__Attributes["In_Range"])):
Attributes=self.__Attributes["In_Range"][x][1].Get_Attributes()
if Attributes["Team"]!=self.__Attributes["Team"] and Attributes["Current_Health"]>0:
Attributes["Current_Health"]-=(self.__Attributes["Stats"]["Attack"]-Attributes["Stats"]["Defence"])
if Attributes["Current_Health"]<0:
Attributes["Current_Health"]=0
self.__Attributes["In_Range"][x][1].Set_Attributes(["Stats","State"],[Attributes["Stats"],3])
#if Attributes["Stats"]["Health"]>0:#If the sprite isn't already defeated
self.__Attributes["Attacking"].append([Attributes["Location"],(0,0,254)])#Allows a line to be drawn from the center of the sprite to this sprite's location
print(Attributes["Stats"])
print(self.__Attributes["Attacking"], "ATTACKING!!! ATTRIBUTE TEST!!!")
y+=1
x+=1
elif self.__Attributes["ID"] in range(6,10):#Heal the closest ally
x=0
y=0
while (y!=self.__Attributes["Stats"]["Multi-target"] and x<len(self.__Attributes["In_Range"])):
Attributes=self.__Attributes["In_Range"][x][1].Get_Attributes()
if Attributes["Team"]==self.__Attributes["Team"] and Attributes["Current_Health"]>0:
Attributes["Current_Health"]-=(self.__Attributes["Stats"]["Attack"]-Attributes["Stats"]["Defence"])
self.__Attributes["In_Range"][x][1].Set_Attributes(["Stats"],[Attributes["Stats"]])
self.__Attributes["Attacking"].append([Attributes["Location"],(0,254,0)])
y+=1
x+=1
else:#TEST!!!
self.__Attributes["Attacking"]=[]#Prevents lines from being drawn whilst not attacking!
#pass#Any more extra functions go here!
#---------------------------------------
#Reset the cooldown timer if =0
if self.__Attributes["Cooldown_Timer"]==0:
self.__Attributes["Cooldown_Timer"]=self.__Attributes["Stats"]["Cooldown"]
#self.__Attributes["State"]=0#idle #
#Delete the unit if it has no health remaining
#Done when setting the attributes!!!
else:
self.__Attributes["Attacking"]=[]
if self.__Attributes["Cooldown_Timer"]==0:#reset state when not attacking!
self.__Attributes["State"]=0
#Check modes if not attacking
#---------------------------------------
#If damaged, the state will be forcefully changed to 3 (damaged)
#if self.__Attributes["Cooldown_Timer"]<0:
#if self.__Attributes["Stats"]["Health"]<=0:#This will be done in Check_Stats
# self.__Attributes["State"]=4
#else:#ALSO MOVEMENT TO CHANGE TO MODE 1 #FIX!!!
#self.__Attributes["State"]=0