forked from InfoProjekt/game
Compare commits
No commits in common. "fb3ba25b897509a2f6e2ab4edd308e2f6458de8d" and "74abed824da4819602aa2fb964e720e05376e25b" have entirely different histories.
fb3ba25b89
...
74abed824d
23 changed files with 678 additions and 734 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 607 B |
Binary file not shown.
|
Before Width: | Height: | Size: 4.3 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 497 B |
Binary file not shown.
|
Before Width: | Height: | Size: 326 B |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
711
classes.py
711
classes.py
|
|
@ -1,6 +1,5 @@
|
|||
import pygame
|
||||
import random
|
||||
# from viecher import Skeleton, Zombie
|
||||
|
||||
pygame.font.init()
|
||||
fonts = {
|
||||
|
|
@ -198,14 +197,12 @@ class Scene(GameObjects):
|
|||
self.update()
|
||||
|
||||
def update(self, change:int=None, objects=None):
|
||||
obj = self.level[self.current_level].update(change, objects)
|
||||
self.level[self.current_level].update(change, objects)
|
||||
self.background = self.level[self.current_level].background
|
||||
"""if isinstance(self.objects, list):
|
||||
for obj in self.objects[0] + self.objects[1] + self.objects[2]:
|
||||
obj.update()"""
|
||||
|
||||
return obj
|
||||
|
||||
def draw(self, screen):
|
||||
"""if isinstance(self.objects, list):
|
||||
for obj in self.objects[0] + self.objects[1] + self.objects[2] + self.objects[3]:
|
||||
|
|
@ -219,25 +216,15 @@ class Scene(GameObjects):
|
|||
class Stage(GameObjects):
|
||||
def __init__(self, name: str, _type: str, bg, objects: list, WIDTH, HEIGHT, stage:str, rooms:list) -> None:
|
||||
super().__init__(name, _type, bg, objects, WIDTH, HEIGHT)
|
||||
self.WIDTH = WIDTH
|
||||
self.HEIGHT = HEIGHT
|
||||
self.stage = stage
|
||||
self.rooms = rooms
|
||||
self.current = 0
|
||||
self.sortRooms(WIDTH)
|
||||
for room in self.rooms:
|
||||
if room.id == self.current:
|
||||
room.objectCreation(WIDTH, HEIGHT)
|
||||
|
||||
def update(self, target, objects):
|
||||
if target is not None:
|
||||
self.current = int(target)
|
||||
for room in self.rooms:
|
||||
if room.id == self.current:
|
||||
obj = room.objectCreation(self.WIDTH, self.HEIGHT)
|
||||
self.background = room.background
|
||||
return obj
|
||||
|
||||
self.current = target
|
||||
|
||||
for room in self.rooms:
|
||||
if room.id == self.current:
|
||||
room.update(objects)
|
||||
|
|
@ -278,6 +265,7 @@ class Stage(GameObjects):
|
|||
room.exits.append([rooms[i + 2].id, rooms[i + 2].type])
|
||||
|
||||
for room in self.rooms:
|
||||
print(str(room.id) + str(room.exits))
|
||||
room.createDoors(WIDTH)
|
||||
|
||||
class Room(GameObjects):
|
||||
|
|
@ -288,9 +276,9 @@ class Room(GameObjects):
|
|||
self.doors = []
|
||||
if self.type == 'normal' or self.type == 'boss':
|
||||
self.locked = True
|
||||
#self.objectCreation(WIDTH, HEIGHT)
|
||||
else:
|
||||
self.locked = False
|
||||
[self.objects[4].append(wall) for wall in self.genWalls(WIDTH, HEIGHT)]
|
||||
|
||||
def genWalls(self, WIDTH, HEIGHT):
|
||||
walls = []
|
||||
|
|
@ -303,7 +291,7 @@ class Room(GameObjects):
|
|||
def createDoors(self, WIDTH):
|
||||
if not self.type == 'boss':
|
||||
if len(self.exits) == 1:
|
||||
self.doors.append(Door(f'door{self.id}', self.exits[0][1], random.randint(64, round(WIDTH * 0.75)), self.exits[0][0]))
|
||||
self.doors.append(Door(f'door{self.id}', self.exits[0][1], random.randint(64, round(WIDTH * 0.75)), 4, self.exits[0][0]))
|
||||
elif len(self.exits) == 2:
|
||||
self.doors.append(Door(f'door{self.id}', self.exits[0][1], random.randint(64, round(WIDTH * 0.45)), self.exits[0][0]))
|
||||
self.doors.append(Door(f'door{self.id}', self.exits[1][1], random.randint(round(WIDTH * 0.5), round(WIDTH * 0.9)), self.exits[1][0]))
|
||||
|
|
@ -314,27 +302,10 @@ class Room(GameObjects):
|
|||
|
||||
self.objects.append(self.doors)
|
||||
|
||||
def objectCreation(self, WIDTH, HEIGHT):
|
||||
if self.type != 'boss':
|
||||
self.objects[1] = [Skeleton('skeleton', random.randint(40, 60), random.randint(50, WIDTH - 50), random.randint(50, HEIGHT - 50), 5, 1, 1, 2, 200) for i in range(0,random.randint(2, 5))] + [Zombie('zombie', random.randint(40, 60), random.randint(50, WIDTH-50), random.randint(50, HEIGHT-50), 5, 1, 1, 1, 25) for i in range(0,random.randint(2, 5))]
|
||||
npcs = [NPC('vivi', 100, 'people/vivi.png', 0, 400, 600),
|
||||
NPC('fairy', 100, 'people/fairy.png', 0, 200, 200)]
|
||||
rand = random.randint(0, 30)
|
||||
if rand <= 25 and rand >= 15:
|
||||
self.objects[2] = [random.choice(npcs)]
|
||||
else:
|
||||
self.objects[1] = [Boss('reddy', 40, WIDTH / 2 - 16, HEIGHT /2 - 32, 50, 0.1, 1, 5, 5000)]
|
||||
self.objects[4] = [wall for wall in self.genWalls(WIDTH, HEIGHT)]
|
||||
return self.objects
|
||||
|
||||
|
||||
def update(self, objects):
|
||||
if objects is not None:
|
||||
self.objects = objects
|
||||
if not self.objects[1]:
|
||||
if self.type == 'boss':
|
||||
print('yeahhh, you killed the boss')
|
||||
self.objects[0][0].level.level = 100
|
||||
self.locked = False
|
||||
for door in self.doors:
|
||||
door.update(False)
|
||||
|
|
@ -378,672 +349,4 @@ class Door(GameObjects):
|
|||
screen.blit(self.background, self.rect)
|
||||
|
||||
def update(self, islocked=True):
|
||||
self.locked = islocked
|
||||
|
||||
|
||||
|
||||
#Viecher
|
||||
vec = pygame.math.Vector2
|
||||
fps = 60
|
||||
|
||||
class Objects():
|
||||
def __init__(self, name, ms, sprite, x, y) -> None:
|
||||
self.name = name
|
||||
self.speed = ms
|
||||
with open(f'art/images/{sprite}') as i:
|
||||
self.sprite = pygame.transform.scale2x(pygame.image.load(i))
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.hidden = False
|
||||
self.rect = pygame.Rect(self.x, self.y, self.sprite.get_width(), self.sprite.get_height())
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
self.rect.x, self.rect.y = self.x, self.y
|
||||
screen.blit(self.sprite, self.rect)
|
||||
#pygame.draw.rect(screen, '#ef0120', self.rect, 2)
|
||||
|
||||
class NPC(Objects):
|
||||
def __init__(self, name, ms, sprite, convo_scene, x, y) -> None:
|
||||
super().__init__(name, ms, sprite, x, y)
|
||||
self.talking = False
|
||||
self.hidden = False
|
||||
self.conversation = Convo(self, convo_scene)
|
||||
self.lastUpdate = pygame.time.get_ticks()
|
||||
|
||||
def talk(self, objects):
|
||||
self.talking = True
|
||||
objects[0][0].talking = True
|
||||
|
||||
def draw(self, screen):
|
||||
super().draw(screen)
|
||||
if self.talking:
|
||||
self.conversation.draw(screen)
|
||||
|
||||
def update(self, keys, objects):
|
||||
if self.name == 'oldlady':
|
||||
if self.conversation.convo_scene == 0 and 'rat' in objects[0][0].killed and objects[1]==[]:
|
||||
self.conversation.convo_scene = 1
|
||||
if self.lastUpdate + 200 < pygame.time.get_ticks():
|
||||
if self.talking:
|
||||
self.conversation.update(keys, objects)
|
||||
self.lastUpdate = pygame.time.get_ticks()
|
||||
else:
|
||||
touches = pygame.sprite.spritecollideany(self, objects[0])
|
||||
if touches is not None and keys[pygame.K_f] and isinstance(touches, MainCharacter):
|
||||
self.talk(objects)
|
||||
self.lastUpdate = pygame.time.get_ticks()
|
||||
|
||||
|
||||
class Convo(Label):
|
||||
def __init__(self, npc, convo_scene, text='', x = 140, y = 600, width = 1000, height = 100, font='simple', font_size = 20) -> None:
|
||||
super().__init__(x, y, width, height, text, font, font_size)
|
||||
self.convo_act=0
|
||||
self.npc = npc
|
||||
self.convo_scene = convo_scene
|
||||
self.convos = [
|
||||
['oldlady', 0, ['There are so many rats here.', 'I wish someone would to something against that.','An experienced fighter could kill them.', 'For them it only takes a mouseclick.']],
|
||||
['oldlady', 1, ['Oh, did you kill all the rats?', 'You must be the chosen one!', 'It would be nice if you would go and talk to the village elder.']],
|
||||
['elder', 0, ['Who are you?', 'You want to help us?', 'We have a serious problem with monsters.', 'One day they appeared out of nowhere and started attacking.', 'When you jump into the portal over there,', 'You will be send to a place with monsters.', 'PLEASE help us!']],
|
||||
['elder', 1, ['Who are you?', 'You want to help us?', 'We have a serious problem with monsters.', 'One day they appeared out of nowhere and started attacking.', 'When you jump into the portal over there,', 'You will be send to a place with monsters.', 'PLEASE help us!']],
|
||||
['vivi', 0, ['Wer bist du denn?', 'Aber du kannst gerne aus dem Fenster springen, solange es nicht in meinem Unterricht ist.']]
|
||||
]
|
||||
|
||||
def draw(self, screen):
|
||||
self.text = self.findConversation()[2][self.convo_act]
|
||||
super().draw(screen)
|
||||
|
||||
|
||||
def findConversation(self):
|
||||
for convo in self.convos:
|
||||
if convo[0] == self.npc.name and convo[1] == self.convo_scene:
|
||||
return convo
|
||||
return ['ERROR']
|
||||
|
||||
def update(self, keys, objects):
|
||||
if keys[pygame.K_f]:
|
||||
convo = self.findConversation()
|
||||
if self.convo_act + 1 < len(convo[2]):
|
||||
self.text = convo[2][self.convo_act]
|
||||
self.convo_act += 1
|
||||
else:
|
||||
if convo[0] == 'oldlady':
|
||||
if convo[1] == 0:
|
||||
for i in range(0,5):
|
||||
objects[1].append(Rat('rat', random.randint(150,250), 800, 400+i*20, 1, 1, 1, 100, 25))
|
||||
elif convo[1] == 1:
|
||||
objects[0][0].level.level = 50
|
||||
while 'rat' in objects[0][0].killed: objects[0][0].killed.remove('rat')
|
||||
elif convo[0] == 'elder':
|
||||
if convo[1] == 0:
|
||||
objects[4].append(Obstacle('portal', 'interactable', 'art/images/background/portal.png', False, 700, 300))
|
||||
self.convo_scene += 1
|
||||
elif convo[0] == 'vivi':
|
||||
objects[0][0].health.health = 0
|
||||
self.convo_act = 0
|
||||
self.npc.talking = False
|
||||
objects[0][0].talking = False
|
||||
|
||||
|
||||
class Fighter(Objects):
|
||||
def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr) -> None:
|
||||
super().__init__(name, ms, sprite, x, y)
|
||||
self.health = health
|
||||
self.damage = damage
|
||||
self.level = level
|
||||
self.attack_speed = asp
|
||||
self.attack_range = atr
|
||||
self.lastHurt = pygame.time.get_ticks()
|
||||
self.lastAttack = pygame.time.get_ticks()
|
||||
self.hurtCooldown = 0
|
||||
|
||||
|
||||
class MainCharacter(Fighter):
|
||||
def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr, killed=[]) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr)
|
||||
self.book = Book(0, 0, [], None, None)
|
||||
self.talking = False
|
||||
self.level = Level(1000, 38, 150, 40, level, f'will to live: {level}%', 'simple', 20)
|
||||
self.health = Hearts(health, sprite=['fullheart.png', 'fullheart.png', 'fullheart.png', 'fullheart.png', 'fullheart.png'], x=900, y=50, hurtCooldown=self.hurtCooldown)
|
||||
self.thinks = Thinks(self.x + 20, self.y - 50, 150, 100, 'brr I\'m freezing')
|
||||
self.freezing = True
|
||||
self.killed = killed # amount of mobs that were killed
|
||||
self.load_frames(f'art/images/people/oldmanwalk.png', f'art/images/people/oldmanattack.png')
|
||||
self.current_frame = 0
|
||||
self.animation_speed = 0.1
|
||||
self.last_frame_update = pygame.time.get_ticks()
|
||||
self.rect = pygame.Rect(x, y, self.walk_frames[0].get_width(), self.walk_frames[0].get_height())
|
||||
self.is_attacking = False
|
||||
|
||||
def load_frames(self, walk_sprite_sheet, attack_sprite_sheet):
|
||||
self.walk_frames = self.load_animation_frames(walk_sprite_sheet, frame_width=40, frame_height=66)
|
||||
self.attack_frames = self.load_animation_frames(attack_sprite_sheet, frame_width=66, frame_height=64) # Adjust frame width and height as needed
|
||||
|
||||
def load_animation_frames(self, sprite_sheet, frame_width, frame_height):
|
||||
sprite_sheet = pygame.transform.scale2x(pygame.image.load(sprite_sheet))
|
||||
animation_frames = []
|
||||
if frame_width == 40:
|
||||
frames_coordinates = [
|
||||
(frame_width, 0),
|
||||
(frame_width*2, 0),
|
||||
(frame_width*3, 0),
|
||||
(frame_width*4, 0),
|
||||
(frame_width*5, 0),
|
||||
(frame_width*6, 0),
|
||||
(frame_width*7, 0),
|
||||
(frame_width*8, 0),
|
||||
]
|
||||
else:
|
||||
frames_coordinates = [
|
||||
(frame_width, 0),
|
||||
(frame_width*2, 0),
|
||||
(frame_width*3, 0),
|
||||
(frame_width*4, 0),
|
||||
(frame_width*5, 0),
|
||||
(frame_width*6, 0)
|
||||
]
|
||||
for x, y in frames_coordinates:
|
||||
frame = pygame.Surface((frame_width, frame_height), pygame.SRCALPHA)
|
||||
frame.blit(sprite_sheet, (0, 0), (x, y, frame_width, frame_height))
|
||||
animation_frames.append(frame)
|
||||
return animation_frames
|
||||
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
current_time = pygame.time.get_ticks()
|
||||
if self.is_attacking:
|
||||
animation_frames = self.attack_frames
|
||||
else:
|
||||
animation_frames = self.walk_frames
|
||||
|
||||
if current_time - self.last_frame_update > self.animation_speed * 1000:
|
||||
self.current_frame = (self.current_frame + 1) % len(animation_frames)
|
||||
self.last_frame_update = current_time
|
||||
current_frame_image = animation_frames[self.current_frame]
|
||||
screen.blit(current_frame_image, (self.x, self.y))
|
||||
|
||||
self.rect.x, self.rect.y = self.x, self.y
|
||||
self.health.draw(screen)
|
||||
self.level.draw(screen)
|
||||
self.book.draw(screen)
|
||||
#pygame.draw.rect(screen, '#e900fa', self.rect, 2)
|
||||
if self.thinks.hidden == False:
|
||||
self.thinks.draw(screen, self.x + 20, self.y - 100)
|
||||
|
||||
def hurt(self, damage, objects):
|
||||
if not self.talking:
|
||||
self.health.hurt(damage)
|
||||
|
||||
def obstacle_interaction(self, objects):
|
||||
if len(objects) <= 5:
|
||||
objects.append([])
|
||||
touches = pygame.sprite.spritecollideany(self, objects[4] + objects[5])
|
||||
if touches is not None:
|
||||
if touches.name == 'fireplace':
|
||||
self.freezing = False
|
||||
elif touches.name == 'portal' and self.level.level != 1:
|
||||
return 'play'
|
||||
elif touches.name == 'house' and self.level.level != 1:
|
||||
self.x = 500
|
||||
self.y = 400
|
||||
return 'house'
|
||||
elif 'wall' in touches.name:
|
||||
return 'wall'
|
||||
elif isinstance(touches, Door):
|
||||
if not touches.locked:
|
||||
return f'door-{touches.target}'
|
||||
else:
|
||||
return True
|
||||
|
||||
def walk(self, keys, objects):
|
||||
moveto = vec(0, 0)
|
||||
if keys[pygame.K_w] or keys[pygame.K_UP]:
|
||||
moveto += vec(0, -1)
|
||||
if keys[pygame.K_a] or keys[pygame.K_LEFT]:
|
||||
moveto += vec(-1, 0)
|
||||
if keys[pygame.K_s] or keys[pygame.K_DOWN]:
|
||||
moveto += vec(0, 1)
|
||||
if keys[pygame.K_d] or keys[pygame.K_RIGHT]:
|
||||
moveto += vec(1, 0)
|
||||
if not moveto == vec(0, 0):
|
||||
moveto.scale_to_length(self.speed)
|
||||
|
||||
self.x += moveto[0] / fps
|
||||
self.y += moveto[1] / fps
|
||||
touches = pygame.sprite.spritecollideany(self, objects[4])
|
||||
if touches is not None and not isinstance(touches, Weapons):
|
||||
if isinstance(touches, Obstacle):
|
||||
if not touches.collision:
|
||||
# print(touches.name)
|
||||
return
|
||||
if touches.type == 'wall':
|
||||
if touches.name == 'wall_l':
|
||||
self.x += (2 + (self.x - touches.rect.x))
|
||||
elif touches.name == 'wall_r':
|
||||
self.x -= (2 + self.rect.width - (touches.rect.x - self.x))
|
||||
if touches.name == 'wall_t':
|
||||
self.y += (2 + (self.y - touches.rect.y))
|
||||
elif touches.name == 'wall_b':
|
||||
self.y -= (2 + self.rect.height - (touches.rect.y - self.y))
|
||||
return
|
||||
|
||||
|
||||
if self.x <= touches.rect.x: self.x -= (self.rect.width - (touches.rect.x - self.x))
|
||||
elif self.x > touches.rect.x: self.x += (self.rect.width - (self.x - touches.rect.x - touches.rect.width * 0.7))
|
||||
#if self.y <= touches.y: pass
|
||||
#elif self.y > touches.y: pass
|
||||
#self.x -= moveto[0] * 2 / fps
|
||||
#self.y -= moveto[1] * 2 / fps
|
||||
|
||||
"""
|
||||
if self.x <= 32:
|
||||
self.x = 33
|
||||
elif self.x >= objects[3][0].width - 32:
|
||||
self.x = objects[3][0].width - 32 - self.rect.width + 1
|
||||
if self.y <= 32:
|
||||
self.y = 33
|
||||
elif self.y >= objects[3][0].height - 32:
|
||||
self.y = objects[3][0].height - 32 - self.rect.height + 1
|
||||
"""
|
||||
|
||||
def attack(self, obj, mouse):
|
||||
if self.lastAttack + self.attack_speed * 1000 < pygame.time.get_ticks():
|
||||
moveto = mouse - vec(self.x, self.y)
|
||||
if self.book.current_sp == 'fireball':
|
||||
weapon = Fireball('fb1', 100, self.x, self.y, moveto, 5)
|
||||
elif self.book.current_sp == 'windslash':
|
||||
weapon = Windslash('ws1', 100, self.x, self.y, moveto, 10)
|
||||
else:
|
||||
weapon = Punch('punch', 100, self.x, self.y, moveto, 1, Mobs, life_ticks=500)
|
||||
obj[3].append(weapon)
|
||||
self.lastAttack = pygame.time.get_ticks()
|
||||
if not self.is_attacking:
|
||||
self.current_frame = 0
|
||||
self.is_attacking = True
|
||||
|
||||
def update(self, keys, mouse, objects):
|
||||
if not self.talking:
|
||||
is_moving = False
|
||||
if keys[pygame.K_w] or keys[pygame.K_UP] or keys[pygame.K_a] or keys[pygame.K_LEFT] or keys[pygame.K_s] or keys[pygame.K_DOWN] or keys[pygame.K_d] or keys[pygame.K_RIGHT]:
|
||||
is_moving = True
|
||||
if is_moving:
|
||||
self.walk(keys, objects)
|
||||
self.is_attacking = False
|
||||
else:
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_frame_update > self.animation_speed * 1000:
|
||||
self.current_frame = (self.current_frame + 1) % len(self.walk_frames)
|
||||
self.last_frame_update = current_time
|
||||
if not self.is_attacking:
|
||||
self.current_frame = 0
|
||||
if pygame.mouse.get_pressed()[0]:
|
||||
self.attack(objects, vec(mouse))
|
||||
if self.is_attacking:
|
||||
if self.current_frame == len(self.attack_frames) - 1:
|
||||
self.is_attacking = False
|
||||
self.current_frame = 0
|
||||
self.thinks.update(objects, self)
|
||||
if self.health.health <= 0:
|
||||
return 'village'
|
||||
else:
|
||||
return self.obstacle_interaction(objects)
|
||||
|
||||
class Hearts():
|
||||
def __init__(self, health, sprite, x, y, hurtCooldown) -> None:
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.health = health
|
||||
self.lastHurt = pygame.time.get_ticks()
|
||||
self.hurtCooldown = hurtCooldown
|
||||
self.hidden = False
|
||||
self.sprite=[]
|
||||
for parts in sprite:
|
||||
with open(f'art/images/main_attributes/{parts}') as i:
|
||||
self.sprite.append(pygame.image.load(i))
|
||||
self.rect = []
|
||||
for each in self.sprite:
|
||||
self.rect.append(pygame.Rect(self.x, self.y, each.get_width(), each.get_height()))
|
||||
|
||||
def hurt(self,damage):
|
||||
if self.lastHurt + self.hurtCooldown < pygame.time.get_ticks():
|
||||
self.health -= damage
|
||||
self.lastHurt = pygame.time.get_ticks()
|
||||
self.update()
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
for i in range(0, 5):
|
||||
self.rect[i].x, self.rect[i].y = self.x + i * 20, self.y
|
||||
screen.blit(self.sprite[i], self.rect[i])
|
||||
|
||||
def update(self):
|
||||
sprite = []
|
||||
for i in range(0, 5):
|
||||
if round(self.health) >= 4 + 4 * i:
|
||||
sprite.append('fullheart.png')
|
||||
elif round(self.health) == 3 + 4 * i:
|
||||
sprite.append('dreiviertelheart.png')
|
||||
elif round(self.health) >= 2 + 4 * i:
|
||||
sprite.append('halfheart.png')
|
||||
elif round(self.health) >= 1 + 4 * i:
|
||||
sprite.append('viertelheart.png')
|
||||
elif round(self.health) <= 4 * i:
|
||||
sprite.append('noheart.png')
|
||||
self.sprite = []
|
||||
for parts in sprite:
|
||||
with open(f'art/images/main_attributes/{parts}') as i:
|
||||
self.sprite.append(pygame.image.load(i))
|
||||
|
||||
|
||||
class Level(Label):
|
||||
def __init__(self, x, y, width, height, level, text, font='simple', font_size=20, font_color='#1e90ff', sprite='label.png') -> None:
|
||||
super().__init__(x, y, width, height, text, font, font_size, font_color, sprite)
|
||||
self.level = level
|
||||
def draw(self, screen):
|
||||
self.text = f'will to live: {self.level}%'
|
||||
super().draw(screen)
|
||||
|
||||
class Thinks(Label):
|
||||
def __init__(self, x, y, width, height, text, font='simple', font_size=15, font_color='#000000', sprite='thinks.png') -> None:
|
||||
super().__init__(x, y, width, height, text, font, font_size, font_color, sprite)
|
||||
self.scene = 0
|
||||
|
||||
def draw(self, screen, x, y):
|
||||
if self.hidden:
|
||||
return
|
||||
self.x = x
|
||||
self.y = y
|
||||
super().draw(screen)
|
||||
|
||||
def update(self, objects, main):
|
||||
if not self.hidden:
|
||||
if self.scene == 0 and not main.freezing:
|
||||
self.scene = 1
|
||||
self.hidden = True
|
||||
elif self.scene == 1 and main.talking:
|
||||
self.scene = 2
|
||||
self.hidden = True
|
||||
if self.scene == 1:
|
||||
touches = pygame.sprite.spritecollideany(main, objects[2])
|
||||
if touches is not None and isinstance(touches, NPC):
|
||||
self.text = 'I should press \"f\"'
|
||||
self.hidden = False
|
||||
else:
|
||||
self.hidden = False
|
||||
self.text = 'the lady over there'
|
||||
|
||||
class Book():
|
||||
def __init__(self, x, y, spells, current_spell, current_shield) -> None:
|
||||
with open(f'art/images/main_attributes/book.png') as i:
|
||||
self.sprite = pygame.image.load(i)
|
||||
self.sprite = pygame.transform.scale(self.sprite, (1280, 720))
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.hidden = False
|
||||
self.rect = pygame.Rect(self.x, self.y, self.sprite.get_width(), self.sprite.get_height())
|
||||
self.sp_list = spells
|
||||
self.current_sp = current_spell
|
||||
self.text_left = ["Dear User, ", "in case you fell on the ground too hard,", "here is a quick reminder:",
|
||||
"You are a homeless person. One cold day","you went to the library to warm up yourself.",
|
||||
"There you got bored and found and opened me.", "This lead to you being thrown into this world.",
|
||||
"But you can find a way out of here again."]
|
||||
self.text_right = ["This book will help you to survive.", "You can open and close me when pressing e.",
|
||||
"Click on a picture to choose your spell.",
|
||||
"Talk to fairies to unlock new spells!"]
|
||||
self.buttons=[]
|
||||
self.buttons_y = 400
|
||||
self.buttons_x = 800
|
||||
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
self.rect.x, self.rect.y = self.x, self.y
|
||||
screen.blit(self.sprite, self.rect)
|
||||
text_left_y = 100
|
||||
text_right_y = 100
|
||||
for text in self.text_left:
|
||||
label = Label(100, text_left_y, 500, 50, text, font_color='#000000', sprite='empty.png')
|
||||
label.draw(screen)
|
||||
text_left_y += 50
|
||||
for text in self.text_right:
|
||||
label = Label(680, text_right_y, 500, 50, text, font_color='#000000', sprite='empty.png')
|
||||
label.draw(screen)
|
||||
text_right_y += 50
|
||||
for button in self.buttons:
|
||||
button.update(screen)
|
||||
|
||||
def addspell(self, spell):
|
||||
if spell not in self.sp_list:
|
||||
self.sp_list.append(spell)
|
||||
self.current_sp = spell
|
||||
self.buttons.append(Button(self.buttons_x, self.buttons_y, 58, 50, f'{spell}_icon.png', 'medieval', 23, attributes=[spell], onclickFunction=self.update_spell))
|
||||
self.buttons_y += 100
|
||||
|
||||
def update_spell(self, spell):
|
||||
self.current_sp = spell
|
||||
|
||||
def update(self):
|
||||
pass
|
||||
|
||||
class Mobs(Fighter):
|
||||
def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr, drops) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr)
|
||||
self.drops = drops * (self.level / 2)
|
||||
|
||||
def chase(self, obj):
|
||||
x = obj[0][0].x
|
||||
y = obj[0][0].y
|
||||
moveto = vec(x, y) - vec(self.x, self.y)
|
||||
if not (moveto).length() <= self.attack_range:
|
||||
moveto.scale_to_length(self.speed)
|
||||
self.x += moveto[0] / fps
|
||||
self.y += moveto[1] / fps
|
||||
touches = pygame.sprite.spritecollideany(self, obj[4])
|
||||
if touches is not None and not isinstance(touches, Weapons):
|
||||
if isinstance(touches, Obstacle):
|
||||
if not touches.collision:
|
||||
return
|
||||
if touches.type == 'wall':
|
||||
if touches.name == 'wall_l':
|
||||
self.x += (2 + (self.x - touches.rect.x))
|
||||
elif touches.name == 'wall_r':
|
||||
self.x -= (2 + self.rect.width - (touches.rect.x - self.x))
|
||||
if touches.name == 'wall_t':
|
||||
self.y += (2 + (self.y - touches.rect.y))
|
||||
elif touches.name == 'wall_b':
|
||||
self.y -= (2 + self.rect.height - (touches.rect.y - self.y))
|
||||
|
||||
if self.x <= touches.rect.x: self.x -= (self.rect.width - (touches.rect.x - self.x))
|
||||
elif self.x > touches.rect.x: self.x += (self.rect.width - (self.x - touches.rect.x - touches.rect.width * 0.66))
|
||||
else:
|
||||
self.attack(moveto, obj)
|
||||
|
||||
|
||||
def hurt(self, damage, objects):
|
||||
self.health -= damage
|
||||
if self.health <= 0:
|
||||
objects[0][0].killed.append(self.name)
|
||||
self.hidden = True
|
||||
objects[1].remove(self)
|
||||
|
||||
|
||||
def update(self, obj):
|
||||
self.chase(obj)
|
||||
|
||||
|
||||
class Skeleton(Mobs):
|
||||
def __init__(self, name, ms, x, y, health, damage, level, asp, atr, sprite = 'people/skeleton.png', drops=0) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr, drops)
|
||||
|
||||
def attack(self, moveto, obj):
|
||||
if self.lastAttack + self.attack_speed * 1000 < pygame.time.get_ticks():
|
||||
obj[3].append(Arrow("arrow", 200, self.x, self.y, moveto, self.damage))
|
||||
self.lastAttack = pygame.time.get_ticks()
|
||||
|
||||
|
||||
class Zombie(Mobs):
|
||||
def __init__(self, name, ms, x, y, health, damage, level, asp, atr, sprite_sheet='people/zombiewalk.png', drops=0) -> None:
|
||||
super().__init__(name, ms, sprite_sheet, x, y, health, damage, level, asp, atr, drops)
|
||||
self.load_frames(f'art/images/{sprite_sheet}')
|
||||
self.current_frame = 0
|
||||
self.animation_speed = 250
|
||||
self.last_frame_update = pygame.time.get_ticks()
|
||||
self.hidden = False
|
||||
self.rect = pygame.Rect(x, y, 40, 64)
|
||||
|
||||
def load_frames(self, sprite_sheet):
|
||||
sprite_sheet = pygame.transform.scale2x(pygame.image.load(sprite_sheet).convert_alpha())
|
||||
frame_width = 40
|
||||
frame_height = 64
|
||||
frames_coordinates = [(40, 0),(80, 0),(120, 0),(160, 0),(200, 0),(240, 0),(280, 0), (320, 0)]
|
||||
self.animation_frames = []
|
||||
for x, y in frames_coordinates:
|
||||
frame = pygame.Surface((frame_width, frame_height), pygame.SRCALPHA)
|
||||
frame.blit(sprite_sheet, (0, 0), (x, y, frame_width, frame_height))
|
||||
self.animation_frames.append(frame)
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
current_time = pygame.time.get_ticks()
|
||||
if current_time - self.last_frame_update > self.animation_speed:
|
||||
self.current_frame = (self.current_frame + 1) % len(self.animation_frames)
|
||||
self.last_frame_update = current_time
|
||||
|
||||
current_frame_image = self.animation_frames[self.current_frame]
|
||||
screen.blit(current_frame_image, (self.x, self.y))
|
||||
|
||||
self.rect.topleft = (self.x, self.y)
|
||||
#pygame.draw.rect(screen, '#ef0120', self.rect, 2)
|
||||
|
||||
|
||||
def attack(self, moveto, obj):
|
||||
if self.lastAttack + self.attack_speed * 1000 < pygame.time.get_ticks():
|
||||
obj[3].append(Punch('punch', 100, self.x, self.y, moveto, self.damage, MainCharacter))
|
||||
self.lastAttack = pygame.time.get_ticks()
|
||||
|
||||
class Rat(Mobs):
|
||||
def __init__(self, name, ms, x, y, health, damage, level, asp, atr, sprite='people/rat.png', drops=0) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr, drops)
|
||||
|
||||
def attack(self, moveto, obj):
|
||||
if self.lastAttack + self.attack_speed * 1000 < pygame.time.get_ticks():
|
||||
obj[3].append(Punch('punch', 100, self.x, self.y, moveto, self.damage, MainCharacter))
|
||||
self.lastAttack = pygame.time.get_ticks()
|
||||
|
||||
class Boss(Mobs):
|
||||
def __init__(self, name, ms, x, y, health, damage, level, asp, atr, sprite='people/reddy.png', drops=0) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr, drops)
|
||||
|
||||
def attack(self, moveto, obj):
|
||||
if self.lastAttack + self.attack_speed * 1000 < pygame.time.get_ticks():
|
||||
obj[3].append(RedBlob("blob", 50, self.x, self.y, moveto, self.damage))
|
||||
self.lastAttack = pygame.time.get_ticks()
|
||||
|
||||
def hurt(self, damage, objects, ticks):
|
||||
if ticks > 1000:
|
||||
damage /= 2
|
||||
self.health -= damage
|
||||
if self.health <= 0:
|
||||
objects[0][0].killed.append(self.name)
|
||||
self.hidden = True
|
||||
objects[1].remove(self)
|
||||
|
||||
|
||||
class Weapons(Objects):
|
||||
def __init__(self, name, ms, sprite, x, y, moveto, damage, life_ticks) -> None:
|
||||
super().__init__(name, ms, sprite, x, y)
|
||||
self.moveto = moveto
|
||||
self.damage = damage
|
||||
self.life_ticks= life_ticks
|
||||
self.spawn_tick = pygame.time.get_ticks()
|
||||
pos = vec(1,0)
|
||||
angle = pos.angle_to(moveto)
|
||||
|
||||
self.sprite = pygame.transform.rotate(self.sprite, -angle)
|
||||
|
||||
def die(self, objects, kills):
|
||||
touches = pygame.sprite.spritecollideany(self, objects[0] + objects[1])
|
||||
if kills == Mobs:
|
||||
if touches is not None and isinstance(touches, Boss):
|
||||
touches.hurt(self.damage, objects, self.life_ticks)
|
||||
self.hidden = True
|
||||
if self in objects[3]:
|
||||
objects[3].remove(self)
|
||||
return
|
||||
|
||||
if touches is not None and isinstance(touches, kills):
|
||||
touches.hurt(self.damage, objects)
|
||||
self.hidden = True
|
||||
if self in objects[3]:
|
||||
objects[3].remove(self)
|
||||
|
||||
def move(self, objects):
|
||||
self.moveto.scale_to_length(self.speed)
|
||||
self.x += self.moveto[0] / fps
|
||||
self.y += self.moveto[1] / fps
|
||||
if pygame.time.get_ticks() - self.spawn_tick > self.life_ticks:
|
||||
self.hidden = True
|
||||
objects[3].remove(self)
|
||||
|
||||
class Spells(Weapons):
|
||||
def __init__(self, name, ms, sprite, x, y, moveto, damage, life_ticks) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
|
||||
class Fireball(Spells):
|
||||
def __init__(self, name, ms, x, y, moveto, damage, sprite = 'weapons/fireball.png', life_ticks=5000) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
|
||||
def update(self, objects):
|
||||
self.move(objects)
|
||||
self.die(objects, Mobs)
|
||||
|
||||
class Windslash(Spells):
|
||||
def __init__(self, name, ms, x, y, moveto, damage, sprite = 'weapons/windslash.png', life_ticks=1000) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
|
||||
def update(self, objects):
|
||||
self.move(objects)
|
||||
self.die(objects, Mobs)
|
||||
|
||||
def move(self, objects):
|
||||
super().move(objects)
|
||||
self.moveto = self.moveto.rotate(5)
|
||||
|
||||
class RedBlob(Spells):
|
||||
def __init__(self, name, ms, x, y, moveto, damage, sprite = 'weapons/redblob.png', life_ticks=50000) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
|
||||
|
||||
def die(self, objects, kills):
|
||||
touches = pygame.sprite.spritecollideany(self, objects[0] + objects[1])
|
||||
if touches is not None and isinstance(touches, kills):
|
||||
touches.hurt(self.damage, objects)
|
||||
|
||||
def update(self, objects):
|
||||
self.move(objects)
|
||||
self.die(objects, MainCharacter)
|
||||
|
||||
|
||||
class Arrow(Weapons):
|
||||
def __init__(self, name, ms, x, y, moveto, damage, sprite = 'weapons/arrow.png', life_ticks=5000) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
|
||||
def update(self, objects):
|
||||
self.move(objects)
|
||||
self.die(objects, MainCharacter)
|
||||
|
||||
|
||||
class Punch(Weapons):
|
||||
def __init__(self, name, ms, x, y, moveto, damage, kills, sprite = 'weapons/empty.png', life_ticks=100) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
self.kills = kills
|
||||
|
||||
def update(self, objects):
|
||||
self.move(objects)
|
||||
self.die(objects, self.kills)
|
||||
self.locked = islocked
|
||||
41
main.py
41
main.py
|
|
@ -4,14 +4,11 @@ import json
|
|||
import time
|
||||
import random
|
||||
from classes import *
|
||||
# from viecher import *
|
||||
from pygame import mixer
|
||||
from viecher import *
|
||||
fps = 60
|
||||
|
||||
def setUp(config):
|
||||
pygame.init()
|
||||
mixer.music.load('audio/music/thebritons(1.1).mp3')
|
||||
mixer.music.play(-1)
|
||||
if config["fullscreen"]:
|
||||
screen = pygame.display.set_mode(config["res"], pygame.FULLSCREEN)
|
||||
else:
|
||||
|
|
@ -20,7 +17,7 @@ def setUp(config):
|
|||
pygame.display.set_caption('Between The Pages')
|
||||
with open('art/images/icon.png', 'r') as i:
|
||||
pygame.display.set_icon(pygame.image.load(i))
|
||||
return screen, clock, True, False, "startscreen.png", []
|
||||
return screen, clock, True, True, "startscreen.png", []
|
||||
|
||||
def readConfig():
|
||||
with open('config.json', 'r') as c:
|
||||
|
|
@ -39,10 +36,9 @@ def genRooms(WIDTH, HEIGHT, type:str, objects:list):
|
|||
room_backgrounds = [f'art/images/background/{type}{i}.png' for i in range(1)]
|
||||
rooms = [
|
||||
Room(type, 'normal', room_backgrounds[random.randint(0, 0)], [objects[0], objects[1], objects[2], objects[3], objects[4] + [room_objects[random.randint(0, 0)] for i in range(0, random.randint(0, 1))]], WIDTH - 64, HEIGHT - 64, j)
|
||||
for j in range(random.randint(1, 1))
|
||||
for j in range(random.randint(5, 10))
|
||||
]
|
||||
rooms.append(Room(type, 'boss', room_backgrounds[random.randint(0, 0)], [objects[0], objects[1], [], [], objects[4] + [room_objects[random.randint(0, 0)] for i in range(0, random.randint(0, 1))]], WIDTH - 64, HEIGHT - 64, 88))
|
||||
#rooms = [Room(type, 'boss', room_backgrounds[random.randint(0, 0)], [objects[0], objects[1], [], [], objects[4] + [room_objects[random.randint(0, 0)] for i in range(0, random.randint(0, 1))]], WIDTH - 64, HEIGHT - 64, 88)]
|
||||
#rooms =Room(type, 'normal', room_backgrounds[random.randint(0, 4)], [objects[0], objects[1], objects[2], [room_objects[random.randint(0, len(room_objects) - 1)] for i in range(0, random.randint(0, 1))]], WIDTH - 64, HEIGHT - 64, [True, True, True, True], j)
|
||||
|
||||
return rooms
|
||||
|
|
@ -59,9 +55,6 @@ def play(screen, clock, running, background, isblack, WIDTH, HEIGHT):
|
|||
level.append(Stage('blau', 'normal', None, [], WIDTH, HEIGHT, 'blue', rooms))
|
||||
scene = Scene('test', 'normal', None, None, WIDTH, HEIGHT, level)
|
||||
freeze = False #Gameplay is freezed in certain situations
|
||||
tbc = Label(WIDTH / 2 - 128, HEIGHT / 2 - 32, 256, 32, "To be continued", "damaged", 30, '#ffffff', 'empty.png')
|
||||
tbc_tick = 0
|
||||
objects = scene.getObjects()
|
||||
|
||||
while running:
|
||||
screen.fill('#000000')
|
||||
|
|
@ -78,15 +71,9 @@ def play(screen, clock, running, background, isblack, WIDTH, HEIGHT):
|
|||
bg = pygame.transform.scale(bg, (WIDTH, HEIGHT))
|
||||
# fill the screen with an image to clear the screen
|
||||
screen.blit(bg, (0, 0))
|
||||
"""
|
||||
if isblack:
|
||||
if tbc_tick == 0:
|
||||
tbc_tick = pygame.time.get_ticks()
|
||||
elif tbc_tick + 5000 <= pygame.time.get_ticks():
|
||||
quitGame()
|
||||
tbc.draw(screen)
|
||||
|
||||
elif not freeze:
|
||||
"""
|
||||
if not freeze:
|
||||
objects = scene.getObjects()
|
||||
screen.blit(scene.background, (32, 32))
|
||||
target = None
|
||||
|
||||
|
|
@ -100,8 +87,6 @@ def play(screen, clock, running, background, isblack, WIDTH, HEIGHT):
|
|||
for thing in objects[0]:
|
||||
thing.book.hidden = not freeze
|
||||
result = thing.update(pygame.key.get_pressed(), pygame.mouse.get_pos(), objects)
|
||||
if objects[0][0].level.level >= 100:
|
||||
isblack = True
|
||||
if isinstance(result, str):
|
||||
if result == 'village':
|
||||
village(screen, clock, running, background, isblack, WIDTH, HEIGHT)
|
||||
|
|
@ -109,9 +94,6 @@ def play(screen, clock, running, background, isblack, WIDTH, HEIGHT):
|
|||
play(screen, clock, running, background, isblack, WIDTH, HEIGHT)
|
||||
elif 'door-' in result:
|
||||
target = result.split('-')[1]
|
||||
objects[0][0].level.level += 25
|
||||
objects = scene.update(target, objects)
|
||||
#play(screen, clock, running, background, isblack, WIDTH, HEIGHT)
|
||||
else:
|
||||
thing.draw(screen)
|
||||
else:
|
||||
|
|
@ -126,7 +108,6 @@ def play(screen, clock, running, background, isblack, WIDTH, HEIGHT):
|
|||
npc.draw(screen)
|
||||
|
||||
objects[0][0].book.addspell('windslash')
|
||||
objects[0][0].book.addspell('fireball')
|
||||
scene.update(target, objects)
|
||||
scene.draw(screen)
|
||||
|
||||
|
|
@ -143,8 +124,8 @@ def village(screen, clock, running, background, isblack, WIDTH, HEIGHT):
|
|||
main = [herbert]
|
||||
mobs = []
|
||||
weapons = []
|
||||
others = [ Obstacle('fireplace', 'interactable', 'art/images/background/fireplace.png', False, 200, 500),
|
||||
Obstacle('house', 'Interactable', 'art/images/background/house.png', False, 500, 150, WIDTH=180, HEIGHT=160)]
|
||||
others = [Obstacle('fireplace', 'interactable', 'art/images/background/fireplace.png', False, 200, 500),
|
||||
Obstacle('house', 'Interactable', 'art/images/background/house.png', False, 500, 150, WIDTH=180, HEIGHT=160)]
|
||||
npcs = [NPC('oldlady', 100, 'people/oldlady.png', 0, 200, 200)]
|
||||
objects = [main, mobs, npcs, weapons, others]
|
||||
room = Room('village', 'village', 'art/images/background/village.png', objects, WIDTH - 64, HEIGHT - 64, 0)
|
||||
|
|
@ -214,7 +195,7 @@ def house(screen, clock, running, background, isblack, WIDTH, HEIGHT):
|
|||
mobs = []
|
||||
weapons = []
|
||||
others = []
|
||||
npcs = [NPC('elder', 100, 'people/dorfaelteste.png', 0, 200, 200)]
|
||||
npcs = [NPC('elder', 100, 'people/reddy.png', 0, 200, 200)]
|
||||
objects = [main, mobs, npcs, weapons, others]
|
||||
room = Room('house', 'house', 'art/images/background/insideHouse.png', objects, WIDTH - 64, HEIGHT - 64, 0)
|
||||
freeze = False #Gameplay is freezed in certain situations
|
||||
|
|
@ -315,7 +296,7 @@ def options(screen, clock, running, background, isblack, WIDTH, HEIGHT):
|
|||
|
||||
def menu(screen, clock, running, background, isblack, WIDTH, HEIGHT):
|
||||
objects = []
|
||||
objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2, 160, 64, 'textbox.png', 'medieval', 48, "Play", play, attributes=[screen, clock, running, background, isblack, WIDTH, HEIGHT]))
|
||||
objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2, 160, 64, 'textbox.png', 'medieval', 48, "Play", village, attributes=[screen, clock, running, background, isblack, WIDTH, HEIGHT]))
|
||||
#objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2 - 72, 160, 64, 'textbox.png', 'medieval', 48, "Options", uwu))
|
||||
objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2 + 72, 160, 64, 'textbox.png', 'medieval', 48, "Exit game", quitGame))
|
||||
while running:
|
||||
|
|
@ -405,7 +386,7 @@ def main():
|
|||
#objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2, 160, 64, 'textbox.png', 'medieval', 48, "Options", uwu))
|
||||
#objects.append(Button(WIDTH / 2 - 80, HEIGHT / 2 + 72, 160, 64, 'textbox.png', 'medieval', 48, "Exit game", quitGame))
|
||||
menu(screen, clock, running, background, isblack, WIDTH, HEIGHT)
|
||||
#test(screen, clock, running, background, isblack, WIDTH, HEIGHT)
|
||||
test(screen, clock, running, background, isblack, WIDTH, HEIGHT)
|
||||
|
||||
"""while running:
|
||||
for event in pygame.event.get():
|
||||
|
|
|
|||
660
viecher.py
660
viecher.py
|
|
@ -0,0 +1,660 @@
|
|||
import pygame as pg
|
||||
from classes import *
|
||||
from main import *
|
||||
import random
|
||||
|
||||
vec = pg.math.Vector2
|
||||
fps = 60
|
||||
|
||||
|
||||
pg.font.init()
|
||||
fonts = {
|
||||
'medieval': 'medieval.ttf',
|
||||
'minecraft': 'Minecraft Evenings.otf',
|
||||
'3dpixel': '3D-Pixel.ttf',
|
||||
'8bit': '8bitlim.ttf',
|
||||
'8bito': '8blimro.ttf',
|
||||
'arcade': 'ARCADECLASSIC.ttf',
|
||||
'modern_game': 'astron boy video.otf',
|
||||
'modern': 'astron boy.otf',
|
||||
'wonder': 'Beyond Wonderland.ttf',
|
||||
'curved': 'Digitag.ttf',
|
||||
'simple': 'DisposableDroidBB.ttf',
|
||||
'rounded': 'dpcomic.ttf',
|
||||
'playfull': 'Endalian Script.ttf',
|
||||
'blocky': 'FREAKSOFNATURE.ttf',
|
||||
'catchy': 'Future TimeSplitters.otf',
|
||||
'simple_wide': 'Halo3.ttf',
|
||||
'simple_fat': 'INVASION2000.ttf',
|
||||
'very_gamy': 'ka1.ttf',
|
||||
'simple_round': 'Karma Suture.otf',
|
||||
'mono': 'manaspc.ttf',
|
||||
'damaged': 'Merchant Copy.ttf',
|
||||
'big_natural': 'MorialCitadel.TTF',
|
||||
'spacy': 'nasalization-rg.otf',
|
||||
'sci-fi': 'neuropol.otf',
|
||||
'hollow_big_edge': 'papercut.ttf',
|
||||
'space_shuttle': 'pdark.ttf',
|
||||
'thin': 'PixelFJVerdana12pt.ttf',
|
||||
'random': 'Seattle Avenue.ttf',
|
||||
'pixel': 'yoster.ttf'
|
||||
}
|
||||
|
||||
class Objects():
|
||||
def __init__(self, name, ms, sprite, x, y) -> None:
|
||||
self.name = name
|
||||
self.speed = ms
|
||||
with open(f'art/images/{sprite}') as i:
|
||||
self.sprite = pg.transform.scale2x(pg.image.load(i))
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.hidden = False
|
||||
self.rect = pg.Rect(self.x, self.y, self.sprite.get_width(), self.sprite.get_height())
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
self.rect.x, self.rect.y = self.x, self.y
|
||||
screen.blit(self.sprite, self.rect)
|
||||
pg.draw.rect(screen, '#ef0120', self.rect, 2)
|
||||
|
||||
class NPC(Objects):
|
||||
def __init__(self, name, ms, sprite, convo_scene, x, y) -> None:
|
||||
super().__init__(name, ms, sprite, x, y)
|
||||
self.talking = False
|
||||
self.hidden = False
|
||||
self.conversation = Convo(self, convo_scene)
|
||||
self.lastUpdate = pg.time.get_ticks()
|
||||
|
||||
def talk(self, objects):
|
||||
self.talking = True
|
||||
objects[0][0].talking = True
|
||||
|
||||
def draw(self, screen):
|
||||
super().draw(screen)
|
||||
if self.talking:
|
||||
self.conversation.draw(screen)
|
||||
|
||||
def update(self, keys, objects):
|
||||
if self.name == 'oldlady':
|
||||
if self.conversation.convo_scene==0 and 'rat' in objects[0][0].killed and objects[1]==[]:
|
||||
self.conversation.convo_scene=1
|
||||
if self.lastUpdate + 200 < pg.time.get_ticks():
|
||||
if self.talking:
|
||||
self.conversation.update(keys, objects)
|
||||
self.lastUpdate = pg.time.get_ticks()
|
||||
else:
|
||||
touches = pg.sprite.spritecollideany(self, objects[0])
|
||||
if touches is not None and keys[pg.K_f] and isinstance(touches, MainCharacter):
|
||||
self.talk(objects)
|
||||
self.lastUpdate = pg.time.get_ticks()
|
||||
|
||||
|
||||
class Convo(Label):
|
||||
def __init__(self, npc, convo_scene, text='', x = 140, y = 600, width = 1000, height = 100, font='simple', font_size = 20) -> None:
|
||||
super().__init__(x, y, width, height, text, font, font_size)
|
||||
self.convo_act=0
|
||||
self.npc = npc
|
||||
self.convo_scene = convo_scene
|
||||
self.convos = [
|
||||
['oldlady', 0, ['There are so many rats here.', 'I wish someone would to something against that.','An experienced fighter could kill them.', 'For them it only takes a mouseclick.']],
|
||||
['oldlady', 1, ['Oh, did you kill all the rats?', 'You must be the chosen one!', 'It would be nice if you would go and talk to the village elder.']],
|
||||
['elder', 0, ['Who are you?', 'You want to help us?', 'We have a serious problem with monsters.', 'One day they appeared out of nowhere and started attacking.', 'When you jump into the portal over there,', 'You will be send to a place with monsters.', 'PLEASE help us!']],
|
||||
['elder', 1, ['Who are you?', 'You want to help us?', 'We have a serious problem with monsters.', 'One day they appeared out of nowhere and started attacking.', 'When you jump into the portal over there,', 'You will be send to a place with monsters.', 'PLEASE help us!']]
|
||||
]
|
||||
|
||||
def draw(self, screen):
|
||||
self.text = self.findConversation()[2][self.convo_act]
|
||||
super().draw(screen)
|
||||
|
||||
|
||||
def findConversation(self):
|
||||
for convo in self.convos:
|
||||
if convo[0] == self.npc.name and convo[1] == self.convo_scene:
|
||||
return convo
|
||||
return ['ERROR']
|
||||
|
||||
def update(self, keys, objects):
|
||||
if keys[pg.K_f]:
|
||||
convo = self.findConversation()
|
||||
if self.convo_act+1 < len(convo[2]):
|
||||
self.text = convo[2][self.convo_act]
|
||||
self.convo_act += 1
|
||||
else:
|
||||
if convo[0] == 'oldlady':
|
||||
if convo[1] == 0:
|
||||
for i in range(0,5):
|
||||
objects[1].append(Rat('rat', random.randint(150,250), 800, 400+i*20, 1, 1, 1, 100, 25))
|
||||
elif convo[1] == 1:
|
||||
objects[0][0].level.level = 5
|
||||
while 'rat' in objects[0][0].killed: objects[0][0].killed.remove('rat')
|
||||
if convo[0] == 'elder':
|
||||
if convo[1] == 0:
|
||||
objects[4].append(Obstacle('portal', 'interactable', 'art/images/background/portal.png', False, 700, 300))
|
||||
self.convo_scene += 1
|
||||
self.convo_act = 0
|
||||
self.npc.talking = False
|
||||
objects[0][0].talking = False
|
||||
|
||||
|
||||
class Fighter(Objects):
|
||||
def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr) -> None:
|
||||
super().__init__(name, ms, sprite, x, y)
|
||||
self.health = health
|
||||
self.damage = damage
|
||||
self.level = level
|
||||
self.attack_speed = asp
|
||||
self.attack_range = atr
|
||||
self.lastHurt = pg.time.get_ticks()
|
||||
self.lastAttack = pg.time.get_ticks()
|
||||
self.hurtCooldown = 0
|
||||
|
||||
|
||||
class MainCharacter(Fighter):
|
||||
def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr, killed=[]) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr)
|
||||
self.book = Book(0, 0, [], None, None)
|
||||
self.talking = False
|
||||
self.level = Level(1000, 38, 150, 40, level, f'will to live: {level}%', 'simple', 20)
|
||||
self.health = Hearts(health, sprite=['fullheart.png', 'fullheart.png', 'fullheart.png', 'fullheart.png', 'fullheart.png'], x=900, y=50, hurtCooldown=self.hurtCooldown)
|
||||
self.thinks = Thinks(self.x + 20, self.y - 50, 150, 100, 'brr I\'m freezing')
|
||||
self.freezing = True
|
||||
self.killed = killed # amount of mobs that were killed
|
||||
self.load_frames(f'art/images/people/oldmanwalk.png', f'art/images/people/oldmanattack.png')
|
||||
self.current_frame = 0
|
||||
self.animation_speed = 0.1
|
||||
self.last_frame_update = pg.time.get_ticks()
|
||||
self.rect = pg.Rect(x, y, self.walk_frames[0].get_width(), self.walk_frames[0].get_height())
|
||||
self.is_attacking = False
|
||||
|
||||
def load_frames(self, walk_sprite_sheet, attack_sprite_sheet):
|
||||
self.walk_frames = self.load_animation_frames(walk_sprite_sheet, frame_width=40, frame_height=64)
|
||||
self.attack_frames = self.load_animation_frames(attack_sprite_sheet, frame_width=66, frame_height=64) # Adjust frame width and height as needed
|
||||
|
||||
def load_animation_frames(self, sprite_sheet, frame_width, frame_height):
|
||||
sprite_sheet = pg.transform.scale2x(pg.image.load(sprite_sheet))
|
||||
animation_frames = []
|
||||
if frame_width == 40:
|
||||
frames_coordinates = [
|
||||
(frame_width, 0),
|
||||
(frame_width*2, 0),
|
||||
(frame_width*3, 0),
|
||||
(frame_width*4, 0),
|
||||
(frame_width*5, 0),
|
||||
(frame_width*6, 0),
|
||||
(frame_width*7, 0),
|
||||
(frame_width*8, 0),
|
||||
]
|
||||
else:
|
||||
frames_coordinates = [
|
||||
(frame_width, 0),
|
||||
(frame_width*2, 0),
|
||||
(frame_width*3, 0),
|
||||
(frame_width*4, 0),
|
||||
(frame_width*5, 0),
|
||||
(frame_width*6, 0)
|
||||
]
|
||||
for x, y in frames_coordinates:
|
||||
frame = pg.Surface((frame_width, frame_height), pg.SRCALPHA)
|
||||
frame.blit(sprite_sheet, (0, 0), (x, y, frame_width, frame_height))
|
||||
animation_frames.append(frame)
|
||||
return animation_frames
|
||||
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
current_time = pg.time.get_ticks()
|
||||
if self.is_attacking:
|
||||
animation_frames = self.attack_frames
|
||||
else:
|
||||
animation_frames = self.walk_frames
|
||||
|
||||
if current_time - self.last_frame_update > self.animation_speed * 1000:
|
||||
self.current_frame = (self.current_frame + 1) % len(animation_frames)
|
||||
self.last_frame_update = current_time
|
||||
current_frame_image = animation_frames[self.current_frame]
|
||||
screen.blit(current_frame_image, (self.x, self.y))
|
||||
|
||||
self.rect.x, self.rect.y = self.x, self.y
|
||||
self.health.draw(screen)
|
||||
self.level.draw(screen)
|
||||
self.book.draw(screen)
|
||||
pg.draw.rect(screen, '#e900fa', self.rect, 2)
|
||||
if self.thinks.hidden == False:
|
||||
self.thinks.draw(screen, self.x + 20, self.y - 100)
|
||||
|
||||
def hurt(self, damage, objects):
|
||||
if not self.talking:
|
||||
self.health.hurt(damage)
|
||||
|
||||
def obstacle_interaction(self, objects):
|
||||
if len(objects) <= 5:
|
||||
objects.append([])
|
||||
touches = pg.sprite.spritecollideany(self, objects[4] + objects[5])
|
||||
if touches is not None:
|
||||
if touches.name == 'fireplace':
|
||||
self.freezing = False
|
||||
elif touches.name == 'portal' and self.level.level != 1:
|
||||
return 'play'
|
||||
elif touches.name == 'house' and self.level.level != 1:
|
||||
self.x = 500
|
||||
self.y = 400
|
||||
return 'house'
|
||||
elif 'wall' in touches.name:
|
||||
return 'wall'
|
||||
elif isinstance(touches, Door):
|
||||
if not touches.locked:
|
||||
return f'door-{touches.target}'
|
||||
else:
|
||||
return True
|
||||
|
||||
def walk(self, keys, objects):
|
||||
moveto = vec(0, 0)
|
||||
if keys[pg.K_w] or keys[pg.K_UP]:
|
||||
moveto += vec(0, -1)
|
||||
if keys[pg.K_a] or keys[pg.K_LEFT]:
|
||||
moveto += vec(-1, 0)
|
||||
if keys[pg.K_s] or keys[pg.K_DOWN]:
|
||||
moveto += vec(0, 1)
|
||||
if keys[pg.K_d] or keys[pg.K_RIGHT]:
|
||||
moveto += vec(1, 0)
|
||||
if not moveto == vec(0, 0):
|
||||
moveto.scale_to_length(self.speed)
|
||||
|
||||
self.x += moveto[0] / fps
|
||||
self.y += moveto[1] / fps
|
||||
touches = pg.sprite.spritecollideany(self, objects[4])
|
||||
if touches is not None and not isinstance(touches, Weapons):
|
||||
if isinstance(touches, Obstacle):
|
||||
if not touches.collision:
|
||||
# print(touches.name)
|
||||
return
|
||||
if touches.type == 'wall':
|
||||
if touches.name == 'wall_l':
|
||||
self.x += (2 + (self.x - touches.rect.x))
|
||||
elif touches.name == 'wall_r':
|
||||
self.x -= (2 + self.rect.width - (touches.rect.x - self.x))
|
||||
if touches.name == 'wall_t':
|
||||
self.y += (2 + (self.y - touches.rect.y))
|
||||
elif touches.name == 'wall_b':
|
||||
self.y -= (2 + self.rect.height - (touches.rect.y - self.y))
|
||||
return
|
||||
|
||||
|
||||
if self.x <= touches.rect.x: self.x -= (self.rect.width - (touches.rect.x - self.x))
|
||||
elif self.x > touches.rect.x: self.x += (self.rect.width - (self.x - touches.rect.x - touches.rect.width * 0.7))
|
||||
#if self.y <= touches.y: pass
|
||||
#elif self.y > touches.y: pass
|
||||
#self.x -= moveto[0] * 2 / fps
|
||||
#self.y -= moveto[1] * 2 / fps
|
||||
|
||||
"""
|
||||
if self.x <= 32:
|
||||
self.x = 33
|
||||
elif self.x >= objects[3][0].width - 32:
|
||||
self.x = objects[3][0].width - 32 - self.rect.width + 1
|
||||
if self.y <= 32:
|
||||
self.y = 33
|
||||
elif self.y >= objects[3][0].height - 32:
|
||||
self.y = objects[3][0].height - 32 - self.rect.height + 1
|
||||
"""
|
||||
|
||||
def attack(self, obj, mouse):
|
||||
if self.lastAttack + self.attack_speed * 1000 < pg.time.get_ticks():
|
||||
moveto = mouse - vec(self.x, self.y)
|
||||
if self.book.current_sp == 'fireball':
|
||||
weapon = Fireball('fb1', 100, self.x, self.y, moveto, 5)
|
||||
elif self.book.current_sp == 'windslash':
|
||||
weapon = Windslash('ws1', 100, self.x, self.y, moveto, 10)
|
||||
else:
|
||||
weapon = Punch('punch', 100, self.x, self.y, moveto, 1, Mobs, life_ticks=500)
|
||||
obj[3].append(weapon)
|
||||
self.lastAttack = pg.time.get_ticks()
|
||||
if not self.is_attacking:
|
||||
self.current_frame = 0
|
||||
self.is_attacking = True
|
||||
|
||||
def update(self, keys, mouse, objects):
|
||||
if not self.talking:
|
||||
is_moving = False
|
||||
if keys[pg.K_w] or keys[pg.K_UP] or keys[pg.K_a] or keys[pg.K_LEFT] or keys[pg.K_s] or keys[pg.K_DOWN] or keys[pg.K_d] or keys[pg.K_RIGHT]:
|
||||
is_moving = True
|
||||
if is_moving:
|
||||
self.walk(keys, objects)
|
||||
self.is_attacking = False
|
||||
else:
|
||||
current_time = pg.time.get_ticks()
|
||||
if current_time - self.last_frame_update > self.animation_speed * 1000:
|
||||
self.current_frame = (self.current_frame + 1) % len(self.walk_frames)
|
||||
self.last_frame_update = current_time
|
||||
if not self.is_attacking:
|
||||
self.current_frame = 0
|
||||
if pg.mouse.get_pressed()[0]:
|
||||
self.attack(objects, vec(mouse))
|
||||
if self.is_attacking:
|
||||
if self.current_frame == len(self.attack_frames) - 1:
|
||||
self.is_attacking = False
|
||||
self.current_frame = 0
|
||||
self.thinks.update(objects, self)
|
||||
if self.health.health <= 0:
|
||||
return 'village'
|
||||
else:
|
||||
return self.obstacle_interaction(objects)
|
||||
|
||||
class Hearts():
|
||||
def __init__(self, health, sprite, x, y, hurtCooldown) -> None:
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.health = health
|
||||
self.lastHurt = pg.time.get_ticks()
|
||||
self.hurtCooldown = hurtCooldown
|
||||
self.hidden = False
|
||||
self.sprite=[]
|
||||
for parts in sprite:
|
||||
with open(f'art/images/main_attributes/{parts}') as i:
|
||||
self.sprite.append(pg.image.load(i))
|
||||
self.rect = []
|
||||
for each in self.sprite:
|
||||
self.rect.append(pg.Rect(self.x, self.y, each.get_width(), each.get_height()))
|
||||
|
||||
def hurt(self,damage):
|
||||
if self.lastHurt + self.hurtCooldown < pg.time.get_ticks():
|
||||
self.health -= damage
|
||||
self.lastHurt = pg.time.get_ticks()
|
||||
self.update()
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
for i in range(0, 5):
|
||||
self.rect[i].x, self.rect[i].y = self.x + i * 20, self.y
|
||||
screen.blit(self.sprite[i], self.rect[i])
|
||||
|
||||
def update(self):
|
||||
sprite = []
|
||||
for i in range(0, 5):
|
||||
if self.health >= 4 + 4 * i:
|
||||
sprite.append('fullheart.png')
|
||||
elif self.health == 3 + 4 * i:
|
||||
sprite.append('dreiviertelheart.png')
|
||||
elif self.health >= 2 + 4 * i:
|
||||
sprite.append('halfheart.png')
|
||||
elif self.health >= 1 + 4 * i:
|
||||
sprite.append('viertelheart.png')
|
||||
elif self.health <= 4 * i:
|
||||
sprite.append('noheart.png')
|
||||
self.sprite = []
|
||||
for parts in sprite:
|
||||
with open(f'art/images/main_attributes/{parts}') as i:
|
||||
self.sprite.append(pg.image.load(i))
|
||||
|
||||
|
||||
class Level(Label):
|
||||
def __init__(self, x, y, width, height, level, text, font='simple', font_size=20, font_color='#1e90ff', sprite='label.png') -> None:
|
||||
super().__init__(x, y, width, height, text, font, font_size, font_color, sprite)
|
||||
self.level = level
|
||||
def draw(self, screen):
|
||||
self.text = f'will to live: {self.level}%'
|
||||
super().draw(screen)
|
||||
|
||||
class Thinks(Label):
|
||||
def __init__(self, x, y, width, height, text, font='simple', font_size=15, font_color='#000000', sprite='thinks.png') -> None:
|
||||
super().__init__(x, y, width, height, text, font, font_size, font_color, sprite)
|
||||
self.scene = 0
|
||||
|
||||
def draw(self, screen, x, y):
|
||||
if self.hidden:
|
||||
return
|
||||
self.x = x
|
||||
self.y = y
|
||||
super().draw(screen)
|
||||
|
||||
def update(self, objects, main):
|
||||
if not self.hidden:
|
||||
if self.scene == 0 and not main.freezing:
|
||||
self.scene = 1
|
||||
self.hidden = True
|
||||
elif self.scene == 1 and main.talking:
|
||||
self.scene = 2
|
||||
self.hidden = True
|
||||
if self.scene == 1:
|
||||
touches = pg.sprite.spritecollideany(main, objects[2])
|
||||
if touches is not None and isinstance(touches, NPC):
|
||||
self.text = 'I should press \"f\"'
|
||||
self.hidden = False
|
||||
else:
|
||||
self.hidden = False
|
||||
self.text = 'the lady over there'
|
||||
|
||||
class Book():
|
||||
def __init__(self, x, y, spells, current_spell, current_shield) -> None:
|
||||
with open(f'art/images/main_attributes/book.png') as i:
|
||||
self.sprite = pg.image.load(i)
|
||||
self.sprite = pg.transform.scale(self.sprite, (1280, 720))
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.hidden = False
|
||||
self.rect = pg.Rect(self.x, self.y, self.sprite.get_width(), self.sprite.get_height())
|
||||
self.sp_list = spells
|
||||
self.current_sp = current_spell
|
||||
self.text_left = ["Dear User, ", "in case you fell on the ground too hard,", "here is a quick reminder:",
|
||||
"You are a homeless person. One cold day","you went to the library to warm up yourself.",
|
||||
"There you got bored and found and opened me.", "This lead to you being thrown into this world.",
|
||||
"But you can find a way out of here again."]
|
||||
self.text_right = ["This book will help you to survive.", "You can open and close me when pressing e.",
|
||||
"Click on a picture to choose your spell.",
|
||||
"Talk to fairies to unlock new spells!"]
|
||||
self.buttons=[]
|
||||
self.buttons_y = 400
|
||||
self.buttons_x = 800
|
||||
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
self.rect.x, self.rect.y = self.x, self.y
|
||||
screen.blit(self.sprite, self.rect)
|
||||
text_left_y = 100
|
||||
text_right_y = 100
|
||||
for text in self.text_left:
|
||||
label = Label(100, text_left_y, 500, 50, text, font_color='#000000', sprite='empty.png')
|
||||
label.draw(screen)
|
||||
text_left_y += 50
|
||||
for text in self.text_right:
|
||||
label = Label(680, text_right_y, 500, 50, text, font_color='#000000', sprite='empty.png')
|
||||
label.draw(screen)
|
||||
text_right_y += 50
|
||||
for button in self.buttons:
|
||||
button.update(screen)
|
||||
|
||||
def addspell(self, spell):
|
||||
if spell not in self.sp_list:
|
||||
self.sp_list.append(spell)
|
||||
self.current_sp = spell
|
||||
self.buttons.append(Button(self.buttons_x, self.buttons_y, 58, 50, f'{spell}_icon.png', 'medieval', 23, attributes=[spell], onclickFunction=self.update_spell))
|
||||
self.buttons_y += 100
|
||||
|
||||
def update_spell(self, spell):
|
||||
self.current_sp = spell
|
||||
|
||||
def update(self):
|
||||
pass
|
||||
|
||||
class Mobs(Fighter):
|
||||
def __init__(self, name, ms, sprite, x, y, health, damage, level, asp, atr, drops) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr)
|
||||
self.drops = drops * (self.level / 2)
|
||||
|
||||
def chase(self, obj):
|
||||
x = obj[0][0].x
|
||||
y = obj[0][0].y
|
||||
moveto = vec(x, y) - vec(self.x, self.y)
|
||||
if not (moveto).length() <= self.attack_range:
|
||||
moveto.scale_to_length(self.speed)
|
||||
self.x += moveto[0] / fps
|
||||
self.y += moveto[1] / fps
|
||||
touches = pg.sprite.spritecollideany(self, obj[4])
|
||||
if touches is not None and not isinstance(touches, Weapons):
|
||||
if isinstance(touches, Obstacle):
|
||||
if not touches.collision:
|
||||
return
|
||||
if touches.type == 'wall':
|
||||
if touches.name == 'wall_l':
|
||||
self.x += (2 + (self.x - touches.rect.x))
|
||||
elif touches.name == 'wall_r':
|
||||
self.x -= (2 + self.rect.width - (touches.rect.x - self.x))
|
||||
if touches.name == 'wall_t':
|
||||
self.y += (2 + (self.y - touches.rect.y))
|
||||
elif touches.name == 'wall_b':
|
||||
self.y -= (2 + self.rect.height - (touches.rect.y - self.y))
|
||||
|
||||
if self.x <= touches.rect.x: self.x -= (self.rect.width - (touches.rect.x - self.x))
|
||||
elif self.x > touches.rect.x: self.x += (self.rect.width - (self.x - touches.rect.x - touches.rect.width * 0.66))
|
||||
else:
|
||||
self.attack(moveto, obj)
|
||||
|
||||
|
||||
def hurt(self, damage, objects):
|
||||
self.health -= damage
|
||||
if self.health <= 0:
|
||||
objects[0][0].killed.append(self.name)
|
||||
self.hidden = True
|
||||
objects[1].remove(self)
|
||||
|
||||
|
||||
def update(self, obj):
|
||||
self.chase(obj)
|
||||
|
||||
|
||||
class Skeleton(Mobs):
|
||||
def __init__(self, name, ms, x, y, health, damage, level, asp, atr, sprite = 'people/skeleton.png', drops=0) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr, drops)
|
||||
|
||||
def attack(self, moveto, obj):
|
||||
if self.lastAttack + self.attack_speed * 1000 < pg.time.get_ticks():
|
||||
obj[3].append(Arrow("arrow", 200, self.x, self.y, moveto, self.damage))
|
||||
self.lastAttack = pg.time.get_ticks()
|
||||
|
||||
|
||||
class Zombie(Mobs):
|
||||
def __init__(self, name, ms, x, y, health, damage, level, asp, atr, sprite_sheet='people/zombiewalk.png', drops=0) -> None:
|
||||
super().__init__(name, ms, sprite_sheet, x, y, health, damage, level, asp, atr, drops)
|
||||
self.load_frames(f'art/images/{sprite_sheet}')
|
||||
self.current_frame = 0
|
||||
self.animation_speed = 250
|
||||
self.last_frame_update = pg.time.get_ticks()
|
||||
self.hidden = False
|
||||
self.rect = pg.Rect(x, y, 40, 64)
|
||||
|
||||
def load_frames(self, sprite_sheet):
|
||||
sprite_sheet = pg.transform.scale2x(pg.image.load(sprite_sheet).convert_alpha())
|
||||
frame_width = 40
|
||||
frame_height = 64
|
||||
frames_coordinates = [(40, 0),(80, 0),(120, 0),(160, 0),(200, 0),(240, 0),(280, 0), (320, 0)]
|
||||
self.animation_frames = []
|
||||
for x, y in frames_coordinates:
|
||||
frame = pg.Surface((frame_width, frame_height), pg.SRCALPHA)
|
||||
frame.blit(sprite_sheet, (0, 0), (x, y, frame_width, frame_height))
|
||||
self.animation_frames.append(frame)
|
||||
|
||||
def draw(self, screen):
|
||||
if self.hidden:
|
||||
return
|
||||
current_time = pg.time.get_ticks()
|
||||
if current_time - self.last_frame_update > self.animation_speed:
|
||||
self.current_frame = (self.current_frame + 1) % len(self.animation_frames)
|
||||
self.last_frame_update = current_time
|
||||
|
||||
current_frame_image = self.animation_frames[self.current_frame]
|
||||
screen.blit(current_frame_image, (self.x, self.y))
|
||||
|
||||
self.rect.topleft = (self.x, self.y)
|
||||
pg.draw.rect(screen, '#ef0120', self.rect, 2)
|
||||
|
||||
|
||||
def attack(self, moveto, obj):
|
||||
if self.lastAttack + self.attack_speed * 1000 < pg.time.get_ticks():
|
||||
obj[3].append(Punch('punch', 100, self.x, self.y, moveto, self.damage))
|
||||
self.lastAttack = pg.time.get_ticks()
|
||||
|
||||
class Rat(Mobs):
|
||||
def __init__(self, name, ms, x, y, health, damage, level, asp, atr, sprite='people/rat.png', drops=0) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, health, damage, level, asp, atr, drops)
|
||||
|
||||
|
||||
def attack(self, moveto, obj):
|
||||
if self.lastAttack + self.attack_speed * 1000 < pg.time.get_ticks():
|
||||
obj[3].append(Punch('punch', 100, self.x, self.y, moveto, self.damage, MainCharacter))
|
||||
self.lastAttack = pg.time.get_ticks()
|
||||
|
||||
class Weapons(Objects):
|
||||
def __init__(self, name, ms, sprite, x, y, moveto, damage, life_ticks) -> None:
|
||||
super().__init__(name, ms, sprite, x, y)
|
||||
self.moveto = moveto
|
||||
self.damage = damage
|
||||
self.life_ticks= life_ticks
|
||||
self.spawn_tick = pg.time.get_ticks()
|
||||
pos = vec(1,0)
|
||||
angle = pos.angle_to(moveto)
|
||||
|
||||
self.sprite = pg.transform.rotate(self.sprite, -angle)
|
||||
|
||||
def die(self, objects, kills):
|
||||
touches = pg.sprite.spritecollideany(self, objects[0] + objects[1])
|
||||
if touches is not None and isinstance(touches, kills):
|
||||
touches.hurt(self.damage, objects)
|
||||
self.hidden = True
|
||||
if self in objects[3]:
|
||||
objects[3].remove(self)
|
||||
|
||||
def move(self, objects):
|
||||
self.moveto.scale_to_length(self.speed)
|
||||
self.x += self.moveto[0] / fps
|
||||
self.y += self.moveto[1] / fps
|
||||
if pg.time.get_ticks() - self.spawn_tick > self.life_ticks:
|
||||
self.hidden = True
|
||||
objects[3].remove(self)
|
||||
|
||||
class Spells(Weapons):
|
||||
def __init__(self, name, ms, sprite, x, y, moveto, damage, life_ticks) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
|
||||
class Fireball(Spells):
|
||||
def __init__(self, name, ms, x, y, moveto, damage, sprite = 'weapons/fireball.png', life_ticks=5000) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
|
||||
def update(self, objects):
|
||||
self.move(objects)
|
||||
self.die(objects, Mobs)
|
||||
|
||||
class Windslash(Spells):
|
||||
def __init__(self, name, ms, x, y, moveto, damage, sprite = 'weapons/windslash.png', life_ticks=1000) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
|
||||
def update(self, objects):
|
||||
self.move(objects)
|
||||
self.die(objects, Mobs)
|
||||
|
||||
def move(self, objects):
|
||||
super().move(objects)
|
||||
self.moveto = self.moveto.rotate(5)
|
||||
|
||||
|
||||
class Arrow(Weapons):
|
||||
def __init__(self, name, ms, x, y, moveto, damage, sprite = 'weapons/arrow.png', life_ticks=5000) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
|
||||
def update(self, objects):
|
||||
self.move(objects)
|
||||
self.die(objects, MainCharacter)
|
||||
|
||||
|
||||
class Punch(Weapons):
|
||||
def __init__(self, name, ms, x, y, moveto, damage, kills, sprite = 'weapons/empty.png', life_ticks=100) -> None:
|
||||
super().__init__(name, ms, sprite, x, y, moveto, damage, life_ticks)
|
||||
self.kills = kills
|
||||
|
||||
def update(self, objects):
|
||||
self.move(objects)
|
||||
self.die(objects, self.kills)
|
||||
Loading…
Add table
Reference in a new issue