-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodels.py
More file actions
296 lines (234 loc) · 10.1 KB
/
models.py
File metadata and controls
296 lines (234 loc) · 10.1 KB
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
"""
Models module for Alien Invaders
This module contains the model classes for the Alien Invaders game. Anything that you
interact with on the screen is model: the ship, the laser bolts, and the aliens.
Just because something is a model does not mean there has to be a special class for
it. Unless you need something special for your extra gameplay features, Ship and Aliens
could just be an instance of GImage that you move across the screen. You only need a new
class when you add extra features to an object. So technically Bolt, which has a velocity,
is really the only model that needs to have its own class.
With that said, we have included the subclasses for Ship and Aliens. That is because
there are a lot of constants in consts.py for initializing the objects, and you might
want to add a custom initializer. With that said, feel free to keep the pass underneath
the class definitions if you do not want to do that.
You are free to add even more models to this module. You may wish to do this when you
add new features to your game, such as power-ups. If you are unsure about whether to
make a new class or not, please ask on Piazza.
Author: Antony Kariuki, akk85
Date Completed: 12/03/2021
"""
from consts import *
from game2d import *
# PRIMARY RULE: Models are not allowed to access anything in any module other than
# consts.py. If you need extra information from Gameplay, then it should be
# a parameter in your method, and Wave should pass it as a argument when it
# calls the method.
class Ship(GImage):
"""
A class to represent the game ship.
At the very least, you want a __init__ method to initialize the ships dimensions.
These dimensions are all specified in consts.py.
You should probably add a method for moving the ship. While moving a ship just means
changing the x attribute (which you can do directly), you want to prevent the player
from moving the ship offscreen. This is an ideal thing to do in a method.
You also MIGHT want to add code to detect a collision with a bolt. We do not require
this. You could put this method in Wave if you wanted to. But the advantage of
putting it here is that Ships and Aliens collide with different bolts. Ships
collide with Alien bolts, not Ship bolts. And Aliens collide with Ship bolts, not
Alien bolts. An easy way to keep this straight is for this class to have its own
collision method.
However, there is no need for any more attributes other than those inherited by
GImage. You would only add attributes if you needed them for extra gameplay
features (like animation). If you add attributes, list them below.
LIST MORE ATTRIBUTES (AND THEIR INVARIANTS) HERE IF NECESSARY
"""
# GETTERS AND SETTERS (ONLY ADD IF YOU NEED THEM)
def getX(self):
"""
Returns the x-coordinate of this ship.
"""
return self.x
def getY(self):
"""
Returns the y-coordinate of this ship.
"""
return self.y
def setX(self, value):
"""
Sets the x-coordinate of this ship.
Parameter value: the new y-coordinate of the ship
Precondition: value is a number (int or float)
"""
self.x = value
def setY(self, value):
"""
Sets the y-coordinate of this ship.
Parameter value: the new y-coordinate of the ship
Precondition: value is a number (int or float)
"""
self.y = value
# INITIALIZER TO CREATE A NEW SHIP
def __init__(self):
"""
Initializes a new Ship object.
"""
super().__init__(x=GAME_WIDTH/2, y= SHIP_BOTTOM + SHIP_HEIGHT/2,
width=SHIP_WIDTH, height=SHIP_HEIGHT, source='ship.png')
# METHOD TO CHECK FOR COLLISIONS
def collides(self,bolt):
"""
Returns: True if the bolt was fired by the player and collides with the ship
Parameter bolt: The laser bolt to check
Precondition: bolt is of class Bolt
"""
x1 = bolt.getX() - BOLT_WIDTH/2
x2 = bolt.getX() + BOLT_WIDTH/2
y1 = bolt.getY() - BOLT_HEIGHT/2
y2 = bolt.getY() + BOLT_HEIGHT/2
if (self.contains((x1, y1)) or self.contains((x1,y2)) or
self.contains((x2,y1)) or self.contains((x2,y2))):
return True
return False
class Alien(GImage):
"""
A class to represent a single alien.
At the very least, you want a __init__ method to initialize the alien dimensions.
These dimensions are all specified in consts.py.
You also MIGHT want to add code to detect a collision with a bolt. We do not require
this. You could put this method in Wave if you wanted to. But the advantage of
putting it here is that Ships and Aliens collide with different bolts. Ships
collide with Alien bolts, not Ship bolts. And Aliens collide with Ship bolts, not
Alien bolts. An easy way to keep this straight is for this class to have its own
collision method.
However, there is no need for any more attributes other than those inherited by
GImage. You would only add attributes if you needed them for extra gameplay
features (like giving each alien a score value). If you add attributes, list
them below.
LIST MORE ATTRIBUTES (AND THEIR INVARIANTS) HERE IF NECESSARY
"""
# GETTERS AND SETTERS (ONLY ADD IF YOU NEED THEM)
def getX(self):
"""
Returns the x-coordinate of this alien.
"""
return self.x
def getY(self):
"""
Returns the y-coordinate of this alien.
"""
return self.y
def setX(self, value):
"""
Sets the x-coordinate of this alien.
Parameter value: the new y-coordinate of the ship
Precondition: value is a number (int or float)
"""
self.x = value
def setY(self, value):
"""
Sets the y-coordinate of this alien.
Parameter value: the new y-coordinate of the ship
Precondition: value is a number (int or float)
"""
self.y = value
# INITIALIZER TO CREATE AN ALIEN
def __init__(self,x,y,picture):
"""
Initializes a new Alien object with a center (x,y).
Parameter x: the x-coordinate of the center of the alien
Precondition: x is a number (int or float); 0 <= x <= GAME_WIDTH/2
Parameter y: the y-coordinate of the center of the alien
Precondition: y is a number (int or float); 0 <= y <= GAME_HEIGHT/2
Parameter picture: the image of the alien
Precondition: picture is a png file
"""
super().__init__(x=x, y=y, width=ALIEN_WIDTH, height=ALIEN_HEIGHT,
source=picture)
# METHOD TO CHECK FOR COLLISION (IF DESIRED)
def collides(self,bolt):
"""
Returns: True if the bolt was fired by the player and collides with this alien
Parameter bolt: The laser bolt to check
Precondition: bolt is of class Bolt
"""
x1 = bolt.getX() - BOLT_WIDTH/2
x2 = bolt.getX() + BOLT_WIDTH/2
y1 = bolt.getY() - BOLT_HEIGHT/2
y2 = bolt.getY() + BOLT_HEIGHT/2
if (self.contains((x1, y1)) or self.contains((x1,y2)) or
self.contains((x2,y1)) or self.contains((x2,y2))):
return True
return False
class Bolt(GRectangle):
"""
A class representing a laser bolt.
Laser bolts are often just thin, white rectangles. The size of the bolt is
determined by constants in consts.py. We MUST subclass GRectangle, because we
need to add an extra attribute for the velocity of the bolt.
The class Wave will need to look at these attributes, so you will need getters for
them. However, it is possible to write this assignment with no setters for the
velocities. That is because the velocity is fixed and cannot change once the bolt
is fired.
In addition to the getters, you need to write the __init__ method to set the starting
velocity. This __init__ method will need to call the __init__ from GRectangle as a
helper.
You also MIGHT want to create a method to move the bolt. You move the bolt by adding
the velocity to the y-position. However, the getter allows Wave to do this on its
own, so this method is not required.
INSTANCE ATTRIBUTES:
_velocity: The velocity in y direction [int or float]
LIST MORE ATTRIBUTES (AND THEIR INVARIANTS) HERE IF NECESSARY
"""
# GETTERS AND SETTERS (ONLY ADD IF YOU NEED THEM)
def getX(self):
"""
Returns the x-coordinate of this bolt.
"""
return self.x
def getY(self):
"""
Returns the y-coordinate of this bolt.
"""
return self.y
def getVel(self):
"""
Returns the velocity of this bolt.
"""
return self._velocity
def setX(self, value):
"""
Sets the x-coordinate of this bolt.
Parameter value: the new y-coordinate of the ship
Precondition: value is a number (int or float)
"""
self.x = value
def setY(self, value):
"""
Sets the y-coordinate of this bolt.
Parameter value: the new y-coordinate of the ship
Precondition: value is a number (int or float)
"""
self.y = value
# INITIALIZER TO SET THE VELOCITY
def __init__(self,x,y,velocity):
"""
Initializes a new Bolt object with a center (x,y).
Parameter x: the x-coordinate of the center of the bolt
Precondition: x is a number (int or float); 0 <= x <= GAME_WIDTH/2
Parameter y: the y-coordinate of the center of the bolt
Precondition: y is a number (int or float); 0 <= y <= GAME_HEIGHT/2
Parameter velocity: the velocity of the bolt
Precondition: velocity is a number (int or float)
"""
super().__init__(x=x, y=y, width = BOLT_WIDTH, height = BOLT_HEIGHT,
fillcolor = BOLT_COLOR)
self._velocity = velocity
# ADD MORE METHODS (PROPERLY SPECIFIED) AS NECESSARY
def isPlayerBolt(self):
"""
Returns True if this bolt is fired by the player.
Returns False, otherwise.
"""
if self._velocity > 0:
return True
return False