-
Notifications
You must be signed in to change notification settings - Fork 2
/
player.py
197 lines (167 loc) · 6.85 KB
/
player.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
import os
import time
from pathlib import Path
from typing import Optional
import pygame
import lib.elfTypes as elfTypes
from lib.animation import Iter, StopIteration
from lib.sprite import Sprite
from lib.spritesheet import Spritesheet
class PlayerCharacter(Sprite):
rect: elfTypes.Rect
sprite_sheet: Spritesheet
def __init__(self, x: int, y: int, img_path: Optional[Path] = None):
img_path = img_path or Path(os.path.join(
"animations", "ELF ANIMATIONS.png"))
super().__init__(x, y, img_path,)
self.max_speed = 1000
self.direction = 0
# These are specific to ELF ANIMATION.PNG
self.sprite_width = 31
self.sprite_height = 31
# top_padding apparent gap at top of file that is uneven with gaps
# between rows of images I could be setting sprite_[width/height] wrong
# but those should be even you'd think
self.top_padding = 4.5
# rect is the pygame.Rect dimension of individual sprites in your
# spritesheet defaults to top left corner of sheet
self.rect = (0, 0, self.sprite_width, self.sprite_height)
self.loadBreathingAnimation()
self.loadJumpAnimation()
self.loadWalkAnimation()
def loadBreathingAnimation(self, ):
self.breath_images = self.scaleImages(
self.sprite_sheet.loadStrip(self.rect, 0, 1, 4)
)
self.breath_iter = Iter(self.breath_images, True)
self.sprite = self.breath_iter.next()
self.breathing = True
def loadJumpAnimation(self, ):
self.jump_sound = pygame.mixer.Sound(os.path.join(
'sounds', 'Retro_8-Bit_Game-Jump_Lift_TakeOff_06.wav'))
self.jump_idx = 0
self.jumping = False
self.jump_images = self.scaleImages(
self.sprite_sheet.loadStrip(self.rect, 1, 2, 4))
self.jump_iter = Iter(self.jump_images)
def loadWalkAnimation(self, ):
self.walk_sound = pygame.mixer.Sound(os.path.join(
'sounds', 'one-foot-step.wav'))
self.walking = False
self.walk_images = self.scaleImages(
self.sprite_sheet.loadStrip(self.rect, 3, 1, 4))
self.walk_iter = Iter(self.walk_images, True)
# This function will handle any play state changes that need to occur before
# the playert animation changes.
def breakForAnimation(self, ):
self.breathing = False
# This function should be called when a particular animation cycle has
# completed
def resetBreathingAnimation(self, ):
self.breathing = True
self.sprite = self.breath_iter.next()
def breath(self):
# assumes character as already been positioned in idx 0 in __init__.
# Perhaps not good coupling of the two functions.
self.sprite = self.breath_iter.next()
def _calcVelocity(self):
# do all velocity calculations with positive numbers to keep it simple
# the "direction" modifier will convert it to `-` if needed
velocity = abs(self.velocity)
if self.accelerating:
print("Accellerating")
t = time.time() - self.move_start_time
velocity = (t * self.acceleration)
else:
print("Decelerating")
t = time.time() - self.move_stopped_time
velocity = velocity - (t * self.deceleration)
# don't be slower than 0 and don't be faster than max
velocity = min(max(0, velocity), self.max_speed)
return velocity * self.direction
# Don't care which direction as we can only be accelerating
# in one direction so which ever one has a moving start time
# that's the time we want
def getMovingTime(self):
t = time.time() - self.last_move_time
print("t: %s" % t)
return t
def calculateLocation(self) -> elfTypes.Location:
return tuple(
((self.velocity * self.getMovingTime()) + self.x_pos, self.y_pos)
)
# Initialize the move but don't do it twice
def startMove(self):
if self.move_start_time == 0:
self.move_start_time = time.time()
self.move_stopped_time = 0
self.last_move_time = time.time()
self.walking = True
self.accelerating = True
# Initialize the stop but don't do it twice
def stopMove(self):
if self.move_stopped_time == 0:
self.move_start_time = 0
self.move_stopped_time = time.time()
self.accelerating = False
def walk(self):
print("walking")
self.velocity = self._calcVelocity()
print("self.velocity: %s" % self.velocity)
self.location = self.calculateLocation()
print("self.location: %s, %s" % self.location)
self._setXY()
self.last_move_time = time.time()
print("self.last_move_time: %s" % self.last_move_time)
if self.velocity == 0:
self.stopWalk()
# completely stop the character
def stopWalk(self,):
self.direction = 0
self.walking = False
self.resetBreathingAnimation()
def jump(self,):
# assumes character as already been positioned in idx 0 in __init__.
# Perhaps not good coupling of the two functions.
if not self.jumping:
self.jump_sound.play()
self.breakForAnimation()
self.jumping = True
try:
self.sprite = self.jump_iter.next()
except StopIteration:
self.jumping = False
self.resetBreathingAnimation()
# print("self.y_pos: %s" %self.y_pos)
# print("self.jump_idx: %s" %self.jump_idx)
# def move(self, direction: int, max_height: int):
# # Y increase as you go down so to move UP on the
# # screen you must decrement Y
# if direction > 0:
# self.y_pos -= self.SPEED
# elif direction < 0:
# self.y_pos += self.SPEED
# if self.y_pos >= max_height - self.btm_buffer:
# self.y_pos = max_height - self.btm_buffer
# def collisionDetected(self, other_body):
# if (self.y_pos + self.height) < other_body.y_pos:
# return False
# elif self.y_pos > (other_body.y_pos + other_body.height):
# return False
# if self.x_pos > (other_body.x_pos + other_body.width):
# return False
# elif (self.x_pos + self.width) < other_body.x_pos:
# return False
# return True
# class EnemyCharacter(GameObject):
# SPEED = 5
# def __init__(self, x, y):
# # How many spaces to move per move
# super().__init__(x, y, os.path.join("imgs", "enemy.png"))
# def move(self, screen_width, multiplier=1):
# if self.x_pos <= 20:
# self.SPEED = abs(self.SPEED)
# if self.x_pos >= (screen_width - self.right_buffer):
# self.SPEED = -abs(self.SPEED)
# self.x_pos += self.SPEED
# # def detect_colision(self)