forked from elliott005/ninjaSouls
-
Notifications
You must be signed in to change notification settings - Fork 1
/
NPC.py
227 lines (203 loc) · 13.4 KB
/
NPC.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
import os
import pygame, math, random
from globals import *
SQRT2 = math.sqrt(2)
spriteSheetVillager2Idle = pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Characters/Villager2/SeparateAnim/Idle.png").convert_alpha()
spriteSheetVillager2Walk = pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Characters/Villager2/SeparateAnim/Walk.png").convert_alpha()
spriteSheetVillager3Idle = pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Characters/Villager3/SeparateAnim/Idle.png").convert_alpha()
spriteSheetVillager3Walk = pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Characters/Villager3/SeparateAnim/Walk.png").convert_alpha()
spriteSheetVillager4Idle = pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Characters/Villager4/SeparateAnim/Idle.png").convert_alpha()
spriteSheetVillager4Walk = pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Characters/Villager4/SeparateAnim/Walk.png").convert_alpha()
spriteSheetCat = pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Animals/Cat/SpriteSheet.png").convert_alpha()
spriteSize = mapTileSize.x
class NPC(pygame.sprite.Sprite):
animationsByName = {
"Villager2": {
"idle": {
"down": [pygame.transform.scale(spriteSheetVillager2Idle.subsurface(pygame.Rect(spriteSize * 0, spriteSize * 0, spriteSize, spriteSize)), size)],
"up": [pygame.transform.scale(spriteSheetVillager2Idle.subsurface(pygame.Rect(spriteSize * 1, spriteSize * 0, spriteSize, spriteSize)), size)],
"left": [pygame.transform.scale(spriteSheetVillager2Idle.subsurface(pygame.Rect(spriteSize * 2, spriteSize * 0, spriteSize, spriteSize)), size)],
"right": [pygame.transform.scale(spriteSheetVillager2Idle.subsurface(pygame.Rect(spriteSize * 3, spriteSize * 0, spriteSize, spriteSize)), size)],
"max": 1,
"speed": 0
},
"walk": {
"down": [pygame.transform.scale(spriteSheetVillager2Walk.subsurface(pygame.Rect(spriteSize * 0, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"up": [pygame.transform.scale(spriteSheetVillager2Walk.subsurface(pygame.Rect(spriteSize * 1, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"left": [pygame.transform.scale(spriteSheetVillager2Walk.subsurface(pygame.Rect(spriteSize * 2, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"right": [pygame.transform.scale(spriteSheetVillager2Walk.subsurface(pygame.Rect(spriteSize * 3, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"max": 4,
"speed": 3
},
"face": pygame.transform.scale(pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Characters/Villager2/Faceset.png"), (128, 128))
},
"Villager3": {
"idle": {
"down": [pygame.transform.scale(spriteSheetVillager3Idle.subsurface(pygame.Rect(spriteSize * 0, spriteSize * 0, spriteSize, spriteSize)), size)],
"up": [pygame.transform.scale(spriteSheetVillager3Idle.subsurface(pygame.Rect(spriteSize * 1, spriteSize * 0, spriteSize, spriteSize)), size)],
"left": [pygame.transform.scale(spriteSheetVillager3Idle.subsurface(pygame.Rect(spriteSize * 2, spriteSize * 0, spriteSize, spriteSize)), size)],
"right": [pygame.transform.scale(spriteSheetVillager3Idle.subsurface(pygame.Rect(spriteSize * 3, spriteSize * 0, spriteSize, spriteSize)), size)],
"max": 1,
"speed": 0
},
"walk": {
"down": [pygame.transform.scale(spriteSheetVillager3Walk.subsurface(pygame.Rect(spriteSize * 0, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"up": [pygame.transform.scale(spriteSheetVillager3Walk.subsurface(pygame.Rect(spriteSize * 1, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"left": [pygame.transform.scale(spriteSheetVillager3Walk.subsurface(pygame.Rect(spriteSize * 2, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"right": [pygame.transform.scale(spriteSheetVillager3Walk.subsurface(pygame.Rect(spriteSize * 3, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"max": 4,
"speed": 3
},
"face": pygame.transform.scale(pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Characters/Villager3/Faceset.png"), (128, 128))
},
"Villager4": {
"idle": {
"down": [pygame.transform.scale(spriteSheetVillager4Idle.subsurface(pygame.Rect(spriteSize * 0, spriteSize * 0, spriteSize, spriteSize)), size)],
"up": [pygame.transform.scale(spriteSheetVillager4Idle.subsurface(pygame.Rect(spriteSize * 1, spriteSize * 0, spriteSize, spriteSize)), size)],
"left": [pygame.transform.scale(spriteSheetVillager4Idle.subsurface(pygame.Rect(spriteSize * 2, spriteSize * 0, spriteSize, spriteSize)), size)],
"right": [pygame.transform.scale(spriteSheetVillager4Idle.subsurface(pygame.Rect(spriteSize * 3, spriteSize * 0, spriteSize, spriteSize)), size)],
"max": 1,
"speed": 0
},
"walk": {
"down": [pygame.transform.scale(spriteSheetVillager4Walk.subsurface(pygame.Rect(spriteSize * 0, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"up": [pygame.transform.scale(spriteSheetVillager4Walk.subsurface(pygame.Rect(spriteSize * 1, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"left": [pygame.transform.scale(spriteSheetVillager4Walk.subsurface(pygame.Rect(spriteSize * 2, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"right": [pygame.transform.scale(spriteSheetVillager4Walk.subsurface(pygame.Rect(spriteSize * 3, spriteSize * y, spriteSize, spriteSize)), size) for y in range(0, 4)],
"max": 4,
"speed": 3
},
"face": pygame.transform.scale(pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Characters/Villager4/Faceset.png"), (128, 128))
},
"Cat": {
"idle": {
"down": [pygame.transform.scale(spriteSheetCat.subsurface(pygame.Rect(spriteSize * 0, spriteSize * 0, spriteSize, spriteSize)), size)],
"up": [pygame.transform.scale(spriteSheetCat.subsurface(pygame.Rect(spriteSize * 0, spriteSize * 0, spriteSize, spriteSize)), size)],
"left": [pygame.transform.scale(spriteSheetCat.subsurface(pygame.Rect(spriteSize * 0, spriteSize * 0, spriteSize, spriteSize)), size)],
"right": [pygame.transform.scale(spriteSheetCat.subsurface(pygame.Rect(spriteSize * 0, spriteSize * 0, spriteSize, spriteSize)), size)],
"max": 1,
"speed": 0
},
"walk": {
"down": [pygame.transform.scale(spriteSheetCat.subsurface(pygame.Rect(spriteSize * x, spriteSize * 0, spriteSize, spriteSize)), size) for x in range(0, 2)],
"up": [pygame.transform.scale(spriteSheetCat.subsurface(pygame.Rect(spriteSize * x, spriteSize * 0, spriteSize, spriteSize)), size) for x in range(0, 2)],
"left": [pygame.transform.scale(spriteSheetCat.subsurface(pygame.Rect(spriteSize * x, spriteSize * 0, spriteSize, spriteSize)), size) for x in range(0, 2)],
"right": [pygame.transform.scale(spriteSheetCat.subsurface(pygame.Rect(spriteSize * x, spriteSize * 0, spriteSize, spriteSize)), size) for x in range(0, 2)],
"max": 2,
"speed": 2
},
"face": pygame.transform.scale(pygame.image.load(os.path.dirname(__file__) + "/assets/NinjaAdventure/Actor/Animals/Cat/Faceset.png"), (128, 128))
}
}
def __init__(self, pos, size, name, groups) -> None:
super().__init__(groups)
self.rect = pygame.Rect(pos, size)
self.name = name
self.animations = self.animationsByName[self.name]
self.animation = "idle"
self.currentFrame = 0.0
self.direction = "down"
self.velocity = pygame.math.Vector2(0, 0)
self.maxSpeed = 100
self.acceleration = 200
self.friction = 1000
self.image = self.animations[self.animation][self.direction][math.floor(self.currentFrame)]
if self.name == "Villager2":
self.dialogue = [
"bla, bla, bla",
"..."
]
elif self.name == "Villager3":
self.dialogue = [
"Hello adventurer!",
"It's dangerous to go alone!",
"..."
]
elif self.name == "Villager4":
self.dialogue = [
"hello there!",
"This is a shop!",
"..."
]
elif self.name == "Cat":
self.dialogue = [
"meow",
"meow meow meow!",
"*purr*"
]
else:
self.dialogue = ["..."]
self.numTalk = 0
self.startPos = pygame.math.Vector2(self.rect.topleft)
self.targetDistance = 400
self.target = pygame.math.Vector2(self.startPos.x + random.randint(-self.targetDistance, self.targetDistance), self.startPos.y + random.randint(-self.targetDistance, self.targetDistance))
self.timers = {
"walkMax": Timer(3, True),
"rest": Timer(random.randint(10, 50) / 10)
}
def update(self, dt, walls, talking):
if not talking:
if (pygame.math.Vector2(self.rect.topleft).distance_to(self.target) < self.maxSpeed * dt or not self.timers["walkMax"].active) and not self.timers["rest"].active:
self.target = pygame.math.Vector2(self.startPos.x + random.randint(-self.targetDistance, self.targetDistance), self.startPos.y + random.randint(-self.targetDistance, self.targetDistance))
self.timers["rest"].start(random.randint(10, 50) / 10)
if not self.timers["rest"].active:
input = pygame.math.Vector2(1, 0).rotate(pygame.math.Vector2(1, 0).angle_to(self.target - pygame.math.Vector2(self.rect.topleft)))
else:
input = pygame.math.Vector2(0, 0)
else:
input = pygame.math.Vector2(0, 0)
self.handleAcceleration(dt, input)
self.move(dt, walls)
self.updateAnimations(dt, input)
self.image = self.animations[self.animation][self.direction][math.floor(self.currentFrame)]
wasActive = self.timers["walkMax"].active
for timer in self.timers:
self.timers[timer].update(dt)
if not self.timers["rest"].active and not self.timers["walkMax"].active and not wasActive:
self.timers["walkMax"].start()
def handleAcceleration(self, dt, input):
if input.y:
if self.velocity.y != 0 and sign(self.velocity.y) != sign(input.y):
self.velocity.y = clamp(self.velocity.y + self.friction * dt * input.y, 0, self.velocity.y)
else:
self.velocity.y = pygame.math.clamp(self.velocity.y + self.acceleration * dt * input.y, -self.maxSpeed, self.maxSpeed)
else:
self.velocity.move_towards_ip(pygame.math.Vector2(self.velocity.x, 0), self.friction * dt)
if input.x:
if self.velocity.x != 0 and sign(self.velocity.x) != sign(input.x):
self.velocity.x = clamp(self.velocity.x + self.friction * dt * input.x, 0, self.velocity.x)
else:
self.velocity.x = pygame.math.clamp(self.velocity.x + self.acceleration * dt * input.x, -self.maxSpeed, self.maxSpeed)
else:
self.velocity.move_towards_ip(pygame.math.Vector2(0, self.velocity.y), self.friction * dt)
if input.x != 0 and input.y != 0 and self.velocity.length():
self.velocity.scale_to_length(self.velocity.length() - self.acceleration * dt / SQRT2)
def move(self, dt, walls):
if self.velocity.length() != 0:
moveBy = self.velocity.normalize() * min(self.velocity.length(), self.maxSpeed) * dt
movedRect = self.rect.move(moveBy.x, 0)
if movedRect.collidelist(walls) == -1:
self.rect = movedRect
movedRect = self.rect.move(0, moveBy.y)
if movedRect.collidelist(walls) == -1:
self.rect = movedRect
def updateAnimations(self, dt, input):
if input.x or input.y:
self.changeAnimation("walk")
if input.x < 0.0:
self.direction = "left"
elif input.x > 0.0:
self.direction = "right"
if input.y < -0.5:
self.direction = "up"
elif input.y > 0.5:
self.direction = "down"
else:
self.changeAnimation("idle")
self.currentFrame += dt * self.animations[self.animation]["speed"]
if self.currentFrame >= self.animations[self.animation]["max"]:
self.currentFrame = 0.0
def changeAnimation(self, anim):
if anim != self.animation:
self.animation = anim
self.currentFrame = 0.0