Skip to content

Commit aa8a672

Browse files
committed
init
0 parents  commit aa8a672

40 files changed

+2545
-0
lines changed

ChessPieces/Chess_bd.png

1.23 KB
Loading

ChessPieces/Chess_bl.png

1.9 KB
Loading

ChessPieces/Chess_kd.png

2.43 KB
Loading

ChessPieces/Chess_kl.png

2.23 KB
Loading

ChessPieces/Chess_nd.png

1.48 KB
Loading

ChessPieces/Chess_nl.png

1.83 KB
Loading

ChessPieces/Chess_pd.png

797 Bytes
Loading

ChessPieces/Chess_pl.png

1.26 KB
Loading

ChessPieces/Chess_qd.png

2.21 KB
Loading

ChessPieces/Chess_ql.png

2.58 KB
Loading

ChessPieces/Chess_rd.png

725 Bytes
Loading

ChessPieces/Chess_rl.png

933 Bytes
Loading

Images/Chess_bd.png

1.23 KB
Loading

Sounds/Move.mp3

3.35 KB
Binary file not shown.

Tunes/CantinaBandSource.mp3

2.51 MB
Binary file not shown.

Tunes/ElevatorMusic.mp3

3.89 MB
Binary file not shown.

Tunes/Nocturne.mp3

5.14 MB
Binary file not shown.

Tunes/TheOnlyThingTheyFearIsYou.mp3

6.3 MB
Binary file not shown.

Tunes/tunes.mp3

2.84 MB
Binary file not shown.

UI.py

+278
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
# Dependencies
2+
import pygame
3+
from vectors import PointWithinRectangle
4+
5+
# Object Classes
6+
7+
class Connection():
8+
# Connection Class is used to represent an event Connection
9+
# EventList refers to the list of Connections for an event that the Connection will be in
10+
11+
def __init__(self, EventList, Function):
12+
self.EventList = EventList
13+
self.Function = Function
14+
15+
def Disconnect(self):
16+
self.EventList.remove(self)
17+
18+
class UIObject(): # EventDrivenObject + special methods
19+
# UIObject contains base components of all UIObjects including Form which contains UIObjects
20+
Events = tuple(["OnPropertyChange"]) # Default UI Events
21+
22+
def __init__(self):
23+
self.__dict__["Callbacks"] = {} # Callbacks contains Connections for events
24+
25+
self.Active = True # Elements are activated by default (so are rendered, process events)
26+
27+
self.AddEvents(UIObject.Events) # This AddEvents function is called at all __init__ levels if the class has events to add
28+
29+
def __setattr__(self, PropertyName, PropertyValue): # intercepts setting values for event-handling
30+
OldValue = None
31+
32+
if hasattr(self, PropertyName):
33+
OldValue = getattr(self, PropertyName)
34+
35+
self.__dict__[PropertyName] = PropertyValue # set value
36+
37+
# note that we do not need a check for Callbacks as __init__ is called before this func
38+
self.Fire("OnPropertyChange", PropertyName, OldValue, PropertyValue) # event fire (PropertyName, OldValue, NewValue)
39+
40+
def Warn(self, Message): # Used to make specific prints for the object
41+
print("UIObject [" + self.__class__.__name__ + "] WARNING: " + Message)
42+
43+
def AddEvents(self, EventNames): # Similar to builder design pattern, you can add more events at stages
44+
for EventName in EventNames:
45+
if not (EventName in self.Callbacks):
46+
self.Callbacks[EventName] = []
47+
else:
48+
self.Warn(F"{EventName} is already an event!")
49+
50+
def Connect(self, EventName, Function): # Create Connection to an event in the object
51+
if EventName in self.Callbacks:
52+
CallbackConnection = Connection(self.Callbacks[EventName], Function)
53+
self.Callbacks[EventName].append(CallbackConnection)
54+
return CallbackConnection
55+
else:
56+
self.Warn(F"{EventName} is not an event!")
57+
58+
def Fire(self, EventName, *args, **kwargs): # Used to signal an event happening: passed arguments to ALL current Connections
59+
if EventName in self.Callbacks:
60+
for Connection in self.Callbacks[EventName]:
61+
Connection.Function(self, *args, **kwargs) # CallbackData[0] is a Function
62+
else:
63+
self.Warn(F"{EventName} is not an event!")
64+
65+
def ProcessEvents(self, Events): # All UIObjects have this but there is no default processing (that does something)
66+
pass
67+
68+
def Render(self, Screen): # No default rendering protocol for all objects
69+
pass
70+
71+
class Form(UIObject):
72+
# Form Object is a container for visual UIObjects: switching between forms changes the UIObjects rendered on screen
73+
Events = tuple(["OnLoad"])
74+
75+
CurrentForm = None # This class-wide property is used at the end (see # Current Form Behaviour)
76+
77+
def __init__(self, Name):
78+
super().__init__()
79+
80+
self.Name = Name
81+
self.Active = False # disabled until set as current form; to prevent unwanted rendering and processing in between form switches
82+
self.Entities = []
83+
84+
self.AddEvents(Form.Events)
85+
86+
def SetAsCurrentForm(self, PreviousForm):
87+
pygame.display.set_caption("Chess - " + self.Name)
88+
89+
self.Connect("OnLoad", SetAsCurrentForm)
90+
91+
def AddEntity(self, Entity):
92+
self.Entities.append(Entity)
93+
94+
def ProcessEvents(self, Events):
95+
for Entity in self.Entities:
96+
if Entity.Active:
97+
Entity.ProcessEvents(Events)
98+
99+
def Render(self, Screen):
100+
Screen.fill(self.BackgroundColour)
101+
102+
for Entity in self.Entities:
103+
if Entity.Active:
104+
Entity.Render(Screen)
105+
106+
class App(Form):
107+
# Special kind of form which contains an app that controls rendering and processing (used for ChessGame which has rendering and processing in itself)
108+
# It essentially combines the power of a unique app and a form by rendering/processing form elements on top
109+
110+
Events = tuple(["EventProcessed"])
111+
112+
def __init__(self, Name, RenderFunction=Form.Render, ProcessFunction=Form.ProcessEvents):
113+
super().__init__(Name)
114+
115+
self.RenderFunction = RenderFunction
116+
self.EventFunction = ProcessFunction
117+
118+
self.AddEvents(App.Events)
119+
120+
def Render(self, Screen):
121+
self.RenderFunction(self, Screen)
122+
123+
for Entity in self.Entities: # The order means form elements are rendered on top of the app
124+
if Entity.Active:
125+
Entity.Render(Screen)
126+
127+
def ProcessEvents(self, Events):
128+
self.Fire("EventProcessed", self.EventFunction(self, Events))
129+
130+
for Entity in self.Entities:
131+
if Entity.Active:
132+
Entity.ProcessEvents(Events)
133+
134+
class Box(UIObject):
135+
# Used as a rectangle container for subclasses TextLabel, ImageLabel
136+
Events = ("OnClick","OnMouseEnter", "OnMouseLeave")
137+
138+
def __init__(self):
139+
super().__init__()
140+
141+
# External Variables
142+
self.BackgroundColour = (255,255,255)
143+
self.BackgroundEnabled = True
144+
self.Size = (100,100)
145+
self.Position = (100,100)
146+
147+
#Internal Variables
148+
self.Rectangle = pygame.Rect(100,100,100,100)
149+
self.MouseIn = False
150+
151+
self.OutlineSize = 0
152+
self.OutlineColour = (29,20,20)
153+
self.OutlineRectangle = self.Rectangle
154+
155+
self.AddEvents(Box.Events)
156+
157+
def UpdatePosition(Object, PropertyName, OldValue, NewValue): # Updates the Internal variable dependent on other variables
158+
if PropertyName == "Position":
159+
self.Rectangle = pygame.Rect(NewValue[0], NewValue[1], self.Rectangle.width, self.Rectangle.height)
160+
elif PropertyName == "Size":
161+
self.Rectangle = pygame.Rect(self.Rectangle.left, self.Rectangle.top, NewValue[0], NewValue[1])
162+
163+
def UpdateOutline(Object, PropertyName, OldValue, NewValue): # Similar to UpdatePosition
164+
if (PropertyName == "Size") or (PropertyName == "Position") or (PropertyName == "OutlineSize") or (PropertyName == "OutlineColour"):
165+
Left = self.Rectangle.left - self.OutlineSize
166+
Top = self.Rectangle.top - self.OutlineSize
167+
Width = self.Rectangle.width + (self.OutlineSize * 2)
168+
Height = self.Rectangle.height + (self.OutlineSize * 2)
169+
170+
self.OutlineRectangle = pygame.Rect(Left, Top, Width, Height) # OutlineRectangle rendered underneath with dimensions of box plus some padding for the outline to be visible
171+
172+
self.Connect("OnPropertyChange", UpdatePosition)
173+
self.Connect("OnPropertyChange", UpdateOutline)
174+
175+
def ProcessEvents(self, Events):
176+
MousePosition = pygame.mouse.get_pos()
177+
178+
if PointWithinRectangle(MousePosition[0], MousePosition[1], self.Rectangle.left, self.Rectangle.top, self.Rectangle.width, self.Rectangle.height):
179+
if not self.MouseIn:
180+
self.MouseIn = True
181+
self.Fire("OnMouseEnter")
182+
elif self.MouseIn:
183+
self.MouseIn = False
184+
self.Fire("OnMouseLeave")
185+
186+
for Event in Events:
187+
if Event.type == pygame.MOUSEBUTTONDOWN:
188+
if self.Rectangle.collidepoint(Event.pos): # does the same thing as PointWithinRectangle
189+
self.Fire("OnClick", Event)
190+
191+
def Render(self, Screen):
192+
if self.OutlineSize > 0:
193+
pygame.draw.rect(Screen, self.OutlineColour, self.OutlineRectangle)
194+
195+
if self.BackgroundEnabled:
196+
pygame.draw.rect(Screen, self.BackgroundColour, self.Rectangle)
197+
198+
class TextLabel(Box):
199+
# A form of box with text overlayed
200+
Events = tuple([])
201+
202+
def __init__(self):
203+
super().__init__()
204+
205+
self.TextSize = 32
206+
self.FontName = "freesansbold.ttf"
207+
208+
self.Text = ""
209+
self.TextColour = (0,0,0)
210+
211+
self.Font = pygame.font.Font(self.FontName, self.TextSize)
212+
213+
self.AddEvents(TextLabel.Events)
214+
215+
def UpdateFont(Object, PropertyName, OldValue, NewValue):
216+
if (PropertyName == "TextSize") or (PropertyName == "FontName"):
217+
self.Font = pygame.font.Font(self.FontName, self.TextSize) # Font object is a container controlling TextSize + Font
218+
self.PrepareFontToRender()
219+
elif (PropertyName == "Text") or (PropertyName == "TextColour") or (PropertyName == "BackgroundColour") or (PropertyName == "Rectangle"):
220+
self.PrepareFontToRender()
221+
222+
self.Connect("OnPropertyChange", UpdateFont)
223+
224+
def PrepareFontToRender(self): # Font object -> object that can be drawn to screen
225+
self.FontToRender = self.Font.render(self.Text, True, self.TextColour, self.BackgroundColour) # creates an object similar to a rectangle
226+
FontRectangle = self.FontToRender.get_rect()
227+
228+
self.AlignedX = self.Rectangle.left + (self.Rectangle.width - FontRectangle.width)/2 # align text with background box
229+
self.AlignedY = self.Rectangle.top + (self.Rectangle.height - FontRectangle.height)/2
230+
231+
def Render(self, Screen):
232+
Box.Render(self, Screen)
233+
234+
Screen.blit(self.FontToRender, (self.AlignedX, self.AlignedY, self.Rectangle.width, self.Rectangle.height))
235+
236+
class ImageLabel(Box):
237+
# Box with an image overlayed
238+
Events = tuple([])
239+
240+
def __init__(self):
241+
super().__init__()
242+
243+
self.ImageSource = None
244+
self.Image = None
245+
246+
self.AddEvents(ImageLabel.Events)
247+
248+
def UpdateImage(self, PropertyName, OldValue, NewValue):
249+
if PropertyName == "ImageSource":
250+
self.Image = pygame.image.load("Images\\" + self.ImageSource)
251+
self.Image = pygame.transform.scale(self.Image, self.Rectangle.size)
252+
253+
self.Connect("OnPropertyChange", UpdateImage)
254+
255+
def Render(self, Screen):
256+
Box.Render(self, Screen)
257+
Screen.blit(self.Image, self.Position)
258+
259+
# Current Form Behaviour
260+
261+
def SetCurrentForm(FormToSet): # Only one form enabled at a time
262+
if Form.CurrentForm:
263+
Form.CurrentForm.Active = False
264+
265+
FormToSet.Fire("OnLoad", Form.CurrentForm)
266+
267+
FormToSet.Active = True
268+
Form.CurrentForm = FormToSet
269+
270+
# Update and Render can be called by the event loop in the main code file
271+
272+
def Update(Events):
273+
if Form.CurrentForm and Form.CurrentForm.Active:
274+
Form.CurrentForm.ProcessEvents(Events)
275+
276+
def Render(Screen):
277+
if Form.CurrentForm and Form.CurrentForm.Active:
278+
Form.CurrentForm.Render(Screen)

__pycache__/UI.cpython-310.pyc

8.93 KB
Binary file not shown.

__pycache__/ai.cpython-310.pyc

4.19 KB
Binary file not shown.

__pycache__/chessgame.cpython-310.pyc

3.77 KB
Binary file not shown.

__pycache__/game.cpython-310.pyc

12.1 KB
Binary file not shown.

__pycache__/music.cpython-310.pyc

2.86 KB
Binary file not shown.

__pycache__/physics.cpython-310.pyc

997 Bytes
Binary file not shown.

__pycache__/pieces.cpython-310.pyc

11.9 KB
Binary file not shown.

__pycache__/rendering.cpython-310.pyc

3.08 KB
Binary file not shown.

__pycache__/sound.cpython-310.pyc

597 Bytes
Binary file not shown.

__pycache__/vectors.cpython-310.pyc

1.58 KB
Binary file not shown.

0 commit comments

Comments
 (0)