EXPLOSION_RADIUS = RADIUS * 10
POWER = 75
- BOMB_IMAGE = pygame.transform.scale(pygame.image.load("assets/bomb.png").convert_alpha(),
- (RADIUS * 2, RADIUS * 2)).convert_alpha()
+ BOMB_IMAGE = pygame.image.load("assets/bomb.png").convert_alpha()
+ BOMB_TXT = Texture.from_surface(renderer, BOMB_IMAGE)
EXPLOSIONS = [
[
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch1/File1.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch1/File2.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch1/File3.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch1/File4.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch1/File5.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch1/File6.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha()
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch1/File1.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch1/File2.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch1/File3.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch1/File4.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch1/File5.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch1/File6.png"))
],
[
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File1.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File2.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File3.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File4.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File5.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File6.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha()
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File1.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File2.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File3.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File4.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File5.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File6.png"))
],
[
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File1.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File2.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File3.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File4.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File5.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha(),
- pygame.transform.scale(pygame.image.load(f"assets/explosion/Punch2/File6.png"),
- (EXPLOSION_RADIUS * 2, EXPLOSION_RADIUS * 2)).convert_alpha()
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File1.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File2.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File3.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File4.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File5.png")),
+ Texture.from_surface(renderer, pygame.image.load(f"assets/explosion/Punch2/File6.png"))
],
]
+
EXPLOSION_TIME = 500
explosion_sound_effects = [
def __init__(self):
super().__init__()
self.radius = self.RADIUS
+ self.image = self.BOMB_IMAGE
self.exploded = False
+
self.exploded_frame_timer = 0
- self.image = self.BOMB_IMAGE
self.explosion_frame = 0
- self.explosion = random.choice(self.EXPLOSIONS)
+
+ self.explosion_txt = random.choice(self.EXPLOSIONS)
def update(self, delta):
super().update(delta)
if self.exploded:
self.exploded_frame_timer += delta
- if self.exploded_frame_timer >= self.EXPLOSION_TIME / len(self.explosion):
+ if self.exploded_frame_timer >= self.EXPLOSION_TIME / len(self.explosion_txt):
self.exploded_frame_timer = 0
- self.explosion_frame = min(len(self.explosion) - 1, self.explosion_frame + 1)
- self.image = self.explosion[self.explosion_frame]
- if self.explosion_frame == len(self.explosion) - 1:
+ self.explosion_frame = min(len(self.explosion_txt) - 1, self.explosion_frame + 1)
+ if self.explosion_frame == len(self.explosion_txt) - 1:
return True
def explode(self, fruits, bombs, effects, depth=0):
if self in bombs:
if not self.exploded:
- self.image = self.explosion[0]
+ self.image = self.explosion_txt[0]
if depth == 0:
pygame.mixer.Sound.play(random.choice(self.explosion_sound_effects))
self.exploded = True
for fruit in fruits:
fruit.velocity += (fruit.position - self.position).normalize() * self.POWER
for effect in effects:
- if isinstance(effect, SplitEffect):
- effect.velocity += (effect.position - self.position).normalize() * self.POWER
+ effect.velocity += (effect.position - self.position).normalize() * self.POWER
for bomb in bombs:
if not bomb.exploded:
- bomb.explode(fruits, bombs, effects,depth+1)
+ bomb.explode(fruits, bombs, effects, depth + 1)
- def draw(self, surf):
+ def draw(self):
if self.exploded:
- surf.blit(self.image, self.image.get_rect(
- topleft=(self.position.x - self.EXPLOSION_RADIUS, self.position.y - self.EXPLOSION_RADIUS)))
+ self.explosion_txt[self.explosion_frame].draw(None, pygame.Rect(self.position.x - self.EXPLOSION_RADIUS,
+ self.position.y - self.EXPLOSION_RADIUS,
+ self.EXPLOSION_RADIUS * 2,
+ self.EXPLOSION_RADIUS * 2))
else:
- # pygame.draw.circle(surf, BLACK, self.position, self.radius)
if self.position.y - self.radius <= HEIGHT:
- rotated_image = pygame.transform.rotate(self.image, self.angle)
- new_rect = rotated_image.get_rect(center=self.image.get_rect(
- topleft=(self.position.x - self.radius, self.position.y - self.radius)).center)
- self.width, self.height = new_rect.size
- surf.blit(rotated_image, new_rect.topleft)
+ self.BOMB_TXT.draw(None, pygame.Rect(self.position.x - self.radius, self.position.y - self.radius,
+ self.radius * 2, self.radius * 2), self.angle,
+ (self.radius, self.radius))
self.position = pygame.Vector2(position)
self.velocity = pygame.Vector2(0, -100)
self.time = self.LIFE_TIME
- self.combo = combo
+ self.combo = f"x{combo}"
self.text_surface = font_large.render(self.combo, True, DARK_GRAY)
+ self.text_txt = Texture.from_surface(renderer, self.text_surface)
def update(self, delta):
self.position += self.velocity * delta / 1000
if self.time <= 0:
return True
- def draw(self, surf):
- surf.blit(self.text_surface, self.position)
+ def draw(self):
+ self.text_txt.draw(None, self.position - pygame.Vector2(self.text_surface.get_width() / 2,
+ self.text_surface.get_height() / 2))
-import pygame
-
from setup import *
def __init__(self, position, radius, color=None):
self.position = pygame.Vector2(position)
+
self.radius = radius * lerp(self.RADIUS_RANGE[0], self.RADIUS_RANGE[1], random.random())
- self.time = self.LIFE_TIME
- self.frame_timer = 0
+
+ self.life_time = 0
self.current_frame = 0
- self.angle = 0
- self.frames = [
- pygame.transform.rotate(pygame.transform.scale(frame, (int(self.radius * 2), int(self.radius * 2))),
- self.angle) for frame in random.choice(self.blood_frames)]
+
+ self.surf_frames = random.choice(self.blood_frames)
+
if color is None:
color = random.choice(EFFECT_COLORS)
- else:
- color = color
- for frame in self.frames:
+
+ for frame in self.surf_frames:
px_array = pygame.PixelArray(frame)
px_array.replace(pygame.Color(250, 3, 35), pygame.Color(color))
px_array.close()
+ self.frame_txt = [Texture.from_surface(renderer, frame) for frame in self.surf_frames]
+
def update(self, delta):
- self.time -= delta
- self.frame_timer += delta
- if self.frame_timer >= self.LIFE_TIME / len(self.frames):
- self.frame_timer = 0
+ self.life_time += delta
+
+ if self.life_time >= self.LIFE_TIME / len(self.surf_frames) * (self.current_frame + 1):
self.current_frame += 1
- if self.time <= 0:
+
+ if self.life_time >= self.LIFE_TIME:
return True
- def draw(self, surf):
- if self.time > 0:
- surf.blit(self.frames[self.current_frame], (self.position.x - self.radius, self.position.y - self.radius))
- # pygame.draw.circle(surf, BLACK, self.position, self.radius)
+ def draw(self):
+ if self.life_time < self.LIFE_TIME:
+ self.frame_txt[self.current_frame].draw(None, pygame.Rect(self.position.x - self.radius,
+ self.position.y - self.radius,
+ self.radius * 2, self.radius * 2))
class BloodSplatter:
LIFE_TIME = 4000
FADE_TIME = 1000
- RADIUS_RANGE = [3, 3.75]
+ RADIUS_RANGE = [2, 2.75]
+ ANGLE_OFFSET = 35
blood_frames = [
- pygame.transform.rotate(pygame.image.load(
- "assets/effects/splatter/bloodslash1.png"),
- -35).convert_alpha(),
- pygame.transform.rotate(pygame.image.load(
- "assets/effects/splatter/bloodslash2.png"),
- -35).convert_alpha()
+ pygame.image.load("assets/effects/splatter/bloodslash1.png").convert_alpha(),
+ pygame.image.load("assets/effects/splatter/bloodslash2.png").convert_alpha()
]
LIGHT_COLOR1 = pygame.Color(110, 110, 110)
LIGHT_COLOR2 = pygame.Color(83, 83, 83)
DARK_COLOR2 = pygame.Color(74, 74, 74)
-
color_frames = [dict(), dict()]
for c in EFFECT_COLORS:
for i, f in enumerate(blood_frames):
px_array.close()
color_frames[i][c] = c_f
-
def __init__(self, position, radius, angle, color=None):
self.position = pygame.Vector2(position)
+
self.radius = radius * lerp(self.RADIUS_RANGE[0], self.RADIUS_RANGE[1], random.random())
- self.time = self.LIFE_TIME
- self.fade_time = self.FADE_TIME
self.angle = angle
+
+ self.life_time = self.LIFE_TIME
+ self.fade_time = self.FADE_TIME
+
img_index = random.randint(0, len(self.blood_frames) - 1)
- # self.frame = pygame.transform.rotate(
- # pygame.transform.scale(self.blood_frames[img_index], (int(self.radius * 2), int(self.radius * 2))),
- # self.angle)
self.alpha = 255
if color is None:
color = random.choice(EFFECT_COLORS)
- self.frame = pygame.transform.rotate(
- pygame.transform.scale(self.color_frames[img_index][color], (int(self.radius * 2), int(self.radius * 2))),
- self.angle)
-
- # px_array = pygame.PixelArray(self.frame)
- # px_array.replace(self.LIGHT_COLOR1 if img_index == 0 else self.LIGHT_COLOR2, pygame.Color(color))
- # px_array.replace(self.DARK_COLOR1 if img_index == 0 else self.DARK_COLOR2, pygame.Color(darken(color, 0.875)))
- # px_array.close()
+ self.frame = Texture.from_surface(renderer, self.color_frames[img_index][color])
def update(self, delta):
- if self.time > 0:
- self.time -= delta
+ if self.life_time > 0:
+ self.life_time -= delta
else:
self.fade_time -= delta
- if self.fade_time <= 0 and self.time <= 0:
+ if self.fade_time <= 0 and self.life_time <= 0:
return True
- if self.time <= 0:
- self.alpha = int(lerp(0, 255, self.fade_time / self.FADE_TIME))
- def draw(self, surf):
+ if self.life_time <= 0:
+ self.alpha = int(lerp(0, 255, self.fade_time / self.FADE_TIME))
+ self.frame.alpha = self.alpha
- self.frame.set_alpha(self.alpha)
- surf.blit(self.frame, (self.position.x - self.radius, self.position.y - self.radius))
+ def draw(self):
+ self.frame.draw(None, pygame.Rect(self.position.x - self.radius,
+ self.position.y - self.radius,
+ self.radius * 2, self.radius * 2),
+ self.angle + self.ANGLE_OFFSET, origin=(self.radius, self.radius))
class SplitEffect:
random.random()) / 100 + pygame.Vector2(normal_velocity)
self.acceleration = pygame.Vector2(0, self.gravity)
- # self.angle = lerp(-45, 45, random.random())
self.angle = 0
self.direction = random.choice([-1, 1])
- # self.angle = 0
- # self.direction = 0
-
- self.frame = frame
- self.width, self.height = self.frame.get_size()
+ self.frame = Texture.from_surface(renderer, frame)
+ self.width, self.height = self.frame.width, self.frame.height
def update(self, delta):
self.velocity += self.acceleration * delta / 1000
self.position += self.velocity * delta / 1000
+
self.angle += 360 * delta / 1000 / 10 * self.direction
if self.position.y - self.height / 2 > HEIGHT:
return True
- def draw(self, surf):
- rotated_image, position = rotate_center(self.frame, self.angle, self.position)
- self.width, self.height = rotated_image.get_size()
- surf.blit(rotated_image, position)
+ def draw(self):
+ self.frame.draw(None, pygame.Rect(self.position.x - self.width / 2,
+ self.position.y - self.height / 2,
+ self.width, self.height),
+ self.angle, origin=(self.width / 2, self.height / 2))
+ self.width, self.height = self.frame.width, self.frame.height
@staticmethod
def find_normals(v):
return pygame.Vector2(-v.y, v.x), pygame.Vector2(v.y, -v.x)
@staticmethod
- def should_split(image, angle, image_position, mouse_position, mouse_direction):
- img, img_pos = rotate_center(image.copy(), angle, image_position)
+ def should_split(image, angle, image_position, mouse_position, mouse_direction, radius):
+ img, img_pos = rotate_center(pygame.transform.scale(image.copy(), (radius * 2, radius * 2)), angle,
+ image_position)
img_pos += pygame.Vector2(img.get_size()) / 2
if mouse_direction.x == 0:
mouse_direction.x += 0.0001
return False
@staticmethod
- def split_image(image, angle, image_position, mouse_position, mouse_direction):
- img, img_pos = rotate_center(image.copy(), angle, image_position)
+ def split_image(image, angle, image_position, mouse_position, mouse_direction, radius):
+ img, img_pos = rotate_center(pygame.transform.scale(image.copy(), (radius * 2, radius * 2)), angle,
+ image_position)
+
+
img_pos += pygame.Vector2(img.get_size()) / 2
if mouse_direction.x == 0:
mouse_direction.x += 0.0001
t1 = (- mp.x) / mouse_direction.x
p1 = mp + t1 * mouse_direction
- t2 = (img.get_width() - mp.x) / mouse_direction.x
- p2 = mp + t2 * mouse_direction
-
p3 = (p1 - rot_center).rotate(-a) + rot_center
- p4 = (p2 - rot_center).rotate(-a) + rot_center
half1 = img.subsurface(pygame.Rect(0, 0, img.get_width(), clamp(p3.y, 0, img.get_height())))
half2 = img.subsurface(pygame.Rect(0, clamp(p3.y, 0, img.get_height()), img.get_width(),
clamp(img.get_height() - p3.y, 0, img.get_height())))
p5 = half1.get_rect().center - rot_center
- pos1 = (p5).rotate(a) + img_pos
+ pos1 = p5.rotate(a) + img_pos
p6 = half2.get_rect().center - rot_center + pygame.Vector2(0, clamp(p3.y, 0, img.get_height()))
- pos2 = (p6).rotate(a) + img_pos
+ pos2 = p6.rotate(a) + img_pos
r_half1 = pygame.transform.rotate(half1, -a)
r_half2 = pygame.transform.rotate(half2, -a)
class SlashEffect:
- SLASH = [pygame.image.load(f"assets/effects/sword_slashes/White_Slash_Thin/File{i}.png").convert_alpha() for i in
- range(1, 7)]
- GROUP_SLASH = [pygame.image.load(f"assets/effects/sword_slashes/White_Group_Slashes/File{i}.png").convert_alpha()
- for i in
- range(1, 21)]
+ SLASH_SURFS = [pygame.image.load(f"assets/effects/sword_slashes/White_Slash_Thin/File{i}.png").convert_alpha()
+ for i in range(1, 7)]
LIFETIME = 600
- def __init__(self, position, angle, combo=False):
+ def __init__(self, position, angle):
self.position = pygame.Vector2(position)
self.angle = angle
- self.is_combo = combo
-
self.time = 0
- self.frame = 0
-
- # if self.is_combo:
- # self.slash_frames = [pygame.transform.rotate(frame, self.angle) for frame in self.GROUP_SLASH]
- # else:
- # self.slash_frames = [pygame.transform.rotate(frame, self.angle) for frame in self.SLASH]
- if self.is_combo:
- self.slash_frames = self.GROUP_SLASH
- else:
- self.slash_frames = [pygame.transform.rotate(frame, self.angle) for frame in self.SLASH]
+ self.current_frame = 0
+
+ self.slash_frames = [Texture.from_surface(renderer, frame) for frame in self.SLASH_SURFS]
def update(self, delta):
self.time += delta
- if self.time >= self.LIFETIME / len(self.SLASH):
+ if self.time >= self.LIFETIME / len(self.SLASH_SURFS):
self.time = 0
- self.frame += 1
- if self.frame >= len(self.SLASH):
+ self.current_frame += 1
+ if self.current_frame >= len(self.SLASH_SURFS):
return True
- def draw(self, surf):
-
- frame = self.slash_frames[self.frame]
- surf.blit(frame, frame.get_rect(center=self.position))
+ def draw(self):
+ frame = self.slash_frames[self.current_frame]
+ frame.draw(None, self.position - pygame.Vector2(frame.width, frame.height) / 2, self.angle)
class FadeInEffect:
def __init__(self, fade_time=500):
self.fade_time = fade_time
- self.surf = pygame.Surface((WIDTH, HEIGHT))
+ self.surf = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
self.surf.fill(BLACK)
self.time = self.fade_time
self.alpha = 255
+ self.txt = Texture.from_surface(renderer, self.surf)
+
def update(self, delta):
self.time -= delta
return True
self.alpha = int(lerp(0, 255, self.time / self.fade_time))
- def draw(self, surf):
- self.surf.set_alpha(self.alpha)
- surf.blit(self.surf, (0, 0))
+ def draw(self):
+ self.txt.alpha = self.alpha
+ self.txt.draw(None, (0, 0))
class FadeOutEffect:
self.fade_time = fade_time
self.max_alpha = max_alpha
- self.surf = pygame.Surface((WIDTH, HEIGHT))
+ self.surf = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
self.surf.fill(BLACK)
self.time = 0
self.alpha = 0
+ self.txt = Texture.from_surface(renderer, self.surf)
+
def update(self, delta):
self.time += delta
if self.time >= self.fade_time:
return True
self.alpha = int(lerp(0, self.max_alpha, self.time / self.fade_time))
- def draw(self, surf):
- self.surf.set_alpha(self.alpha)
- surf.blit(self.surf, (0, 0))
+ def draw(self):
+ self.txt.alpha = self.alpha
+ self.txt.draw(None, (0, 0))
class Fruit:
- RADIUS_RANGE = [60 * SCALE.x, 100 * SCALE.x] # [25, 50]
+ RADIUS_RANGE = [60 * SCALE.x, 100 * SCALE.x]
HORIZONTAL_SPAWN_RANGE = [max(RADIUS_RANGE), WIDTH - max(RADIUS_RANGE)]
VERTICAL_SPAWN_RANGE = [HEIGHT + max(RADIUS_RANGE), HEIGHT * 2 + max(RADIUS_RANGE)]
HORIZONTAL_TARGET_RANGE = [WIDTH / 5.5, WIDTH * 4.5 / 5.5]
GRAVITY = 275 * SCALE.y
- HEADS = [
+ FRUITS = [
pygame.image.load(f"assets/fruits/{file}").convert_alpha() for file in os.listdir('assets/fruits/')
]
- OUTLINE_WIDTH = 3
def __init__(self):
self.radius = lerp(self.RADIUS_RANGE[0], self.RADIUS_RANGE[1], random.random())
self.position = pygame.Vector2(
lerp(self.HORIZONTAL_SPAWN_RANGE[0], self.HORIZONTAL_SPAWN_RANGE[1], random.random()),
lerp(self.VERTICAL_SPAWN_RANGE[0], self.VERTICAL_SPAWN_RANGE[1], random.random()))
- self.acceleration = pygame.Vector2(0, self.GRAVITY)
- # self.previous_position = self.position
+ self.acceleration = pygame.Vector2(0, self.GRAVITY)
dy = self.target.y - self.position.y
dx = self.target.x - self.position.x
t = (-2 / self.GRAVITY * dy) ** 0.5
self.velocity = pygame.Vector2(dx / t, -(-2 * self.GRAVITY * dy) ** 0.5)
- self.image = pygame.transform.scale(random.choice(self.HEADS), (self.radius * 2, self.radius * 2))
+
self.angle = lerp(0, 360, random.random())
self.direction = random.choice([-1, 1])
self.width, self.height = (self.radius * 2, self.radius * 2)
+
+ self.image = random.choice(self.FRUITS)
self.fruit_txt = Texture.from_surface(renderer, self.image)
def update(self, delta):
- # self.previous_position = self.position.copy() - self.velocity / 1000 * 30
self.velocity += self.acceleration * delta / 1000
self.position += self.velocity * delta / 1000
self.angle += 360 * delta / 1000 / 10 * self.direction
- def get_rect(self):
- return pygame.Rect(self.position - pygame.Vector2(self.radius / 2, self.radius / 2),
- pygame.Vector2(self.radius, self.radius))
-
def draw(self):
if self.position.y - self.radius <= HEIGHT:
- self.fruit_txt.draw(None, self.position - pygame.Vector2(self.radius,self.radius), angle=self.angle, origin=None)
+ self.fruit_txt.draw(None, pygame.Rect(self.position - pygame.Vector2(self.radius, self.radius),
+ (self.radius * 2, self.radius * 2)),
+ angle=-self.angle, origin=(self.radius, self.radius))
-import pygame
-
-from bomb import Bomb
-from combo_counter import ComboCounter
-from effect import BloodEffect, SplitEffect, SlashEffect, FadeInEffect, FadeOutEffect, BloodSplatter
-from fruit import Fruit
from player import Player
+from fruit import Fruit
+from effect import BloodEffect, SplitEffect, SlashEffect, FadeInEffect, FadeOutEffect, BloodSplatter
+from combo_counter import ComboCounter
+from bomb import Bomb
+from rect import Rect
from setup import *
class Game:
BOMB_CHANCE = 0
- EFFECT_COUNT_PER_FRUIT = 20
- EFFECT_COUNT_PER_BOMB = 0
+
COMBO_TIME = 250
GAME_OVER_TIME = 2000
WAVE_COOLDOWN = 500
BACKGROUND.blit(dark_background_tile, (x * WIDTH / tile_cols, y * HEIGHT / tile_rows))
else:
BACKGROUND.blit(background_tile, (x * WIDTH / tile_cols, y * HEIGHT / tile_rows))
+ BACKGROUND = Texture.from_surface(renderer, BACKGROUND)
+
bass_sound_effect = pygame.mixer.Sound("assets/sounds/sub-bass-4-secondsssss-6241.wav")
bass_sound_effect.set_volume(0.1)
slash_sounds = [pygame.mixer.Sound(f"assets/sounds/Swishes/long-medium-swish-44324.wav"),
pygame.mixer.Sound(f"assets/sounds/Swishes/swish-sound-94707.wav"),
]
- HIGHSCORE_FILE = "highscore.txt"
+ HIGH_SCORE_FILE = "high_score.txt"
def __init__(self):
self.player = Player()
+
self.fruits = [Fruit()]
self.bombs = []
+
self.effects = [
- [], # Blood splatter
- [], # Blood splash
- [], # Split Effect
- [], # slash effect
- [FadeInEffect(fade_time=1000)] # Fade in/fade out effects
+ [], # Blood splatter
+ [], # Blood splash
+ [], # Split Effect
+ [], # slash effect
+ [FadeInEffect(fade_time=1000)] # Fade in/fade out effects
]
+
self.combo_counters = []
- self.wave = 10
+
self.score = 0
+
self.time_since_last_hit = 0
self.current_combo = 0
+ self.wave = 100
self.cleared_wave = True
self.wave_cooldown_timer = 0
self.game_over_time = 0
try:
- with open(self.HIGHSCORE_FILE, "r") as f:
- self.highscore = int(f.read())
+ with open(self.HIGH_SCORE_FILE, "r") as f:
+ self.high_score = int(f.read())
except:
- self.highscore = 0
+ self.high_score = 0
self.music_started = False
if pygame.mixer.music.get_busy():
pygame.mixer.music.fadeout(500)
- background_music = pygame.mixer.music.load(
- "assets/sounds/Of Far Different Nature - Friendly Trap (CC-BY).ogg")
+ pygame.mixer.music.load("assets/sounds/Of Far Different Nature - Friendly Trap (CC-BY).ogg")
pygame.mixer.music.set_volume(0.25)
pygame.mixer.music.play(-1)
self.music_started = True
+ self.score_surf = font.render(f"SCORE {self.score}", True, WHITE)
+ self.score_txt = Texture.from_surface(renderer, self.score_surf)
+
+ self.combo_surf = font.render(f"COMBO x{self.current_combo}", True, WHITE)
+ self.combo_txt = Texture.from_surface(renderer, self.combo_surf)
+
+ self.high_score_surf = font.render(f"BEST {self.high_score}", True, WHITE)
+ self.high_score_txt = Texture.from_surface(renderer, self.high_score_surf)
+
+ self.title_surf = font_large.render("GAME OVER", True, WHITE)
+
+ self.subtitle_surf = font.render(f"HIGH SCORE {self.high_score}", True, WHITE)
+
+ self.game_over_surf = pygame.Surface((max(self.title_surf.get_width(), self.subtitle_surf.get_width()),
+ self.title_surf.get_height() + self.subtitle_surf.get_height()))
+ self.game_over_surf.fill(GRAY)
+ self.game_over_surf.blit(self.title_surf, self.title_surf.get_rect(
+ center=(self.game_over_surf.get_width() / 2, self.title_surf.get_height() / 2)))
+ self.game_over_surf.blit(self.subtitle_surf, self.subtitle_surf.get_rect(
+ center=(
+ self.game_over_surf.get_width() / 2,
+ self.title_surf.get_height() + self.subtitle_surf.get_height() / 2)))
+ self.game_over_txt = Texture.from_surface(renderer, self.game_over_surf)
+
+ self.r1 = Rect(self.game_over_surf.get_rect(center=(WIDTH / 2, HEIGHT / 2)).inflate(50, 50), GRAY, 10)
+ self.r2 = Rect(self.game_over_surf.get_rect(center=(WIDTH / 2, HEIGHT / 2)).inflate(50, 50), BLACK, 10, 5)
+
def update(self, delta):
for event in pygame.event.get():
- if event.type == pygame.QUIT:
+ if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE):
+ if self.score > self.high_score:
+ self.high_score = self.score
+ with open(self.HIGH_SCORE_FILE, "w") as f:
+ f.write(str(self.high_score))
return COMMAND_EXIT
- if event.type == pygame.KEYUP:
- if event.key == pygame.K_ESCAPE:
- return COMMAND_EXIT
- elif event.key == pygame.K_m:
+ elif event.type == pygame.KEYUP:
+ if event.key == pygame.K_m:
if pygame.mixer.music.get_busy():
pygame.mixer.music.pause()
else:
pygame.mixer.music.unpause()
if not self.music_started:
- background_music = pygame.mixer.music.load(
- "assets/sounds/Of Far Different Nature - Friendly Trap (CC-BY).ogg")
+ pygame.mixer.music.load("assets/sounds/Of Far Different Nature - Friendly Trap (CC-BY).ogg")
pygame.mixer.music.set_volume(0.25)
pygame.mixer.music.play(-1)
self.music_started = True
+
if not self.game_over:
self.player.update(delta)
else:
self.game_over_time += delta
if self.game_over_time > self.GAME_OVER_TIME:
return COMMAND_START
- hits = []
+ hits = []
for fruit in self.fruits:
fruit.update(delta)
+
hit_status = self.player.hits(fruit)
- if hit_status and SplitEffect.should_split(fruit.image, fruit.angle, fruit.position, self.player.previous_mouse_pos, self.player.mouse_direction):
+ if hit_status and SplitEffect.should_split(fruit.image, fruit.angle, fruit.position,
+ self.player.previous_mouse_pos,
+ self.player.mouse_direction, fruit.radius):
hits.append((fruit, self.player.mouse_direction, self.player.previous_mouse_pos))
- fr = fruit.get_rect()
- if ((not -fruit.width < fr.x < WIDTH + fruit.width) or fr.y - fr.height > HEIGHT) and fruit.velocity.y > 0:
+ if (((not -fruit.radius * 2 < fruit.position.x < WIDTH + fruit.radius * 2) or
+ fruit.position.y - fruit.radius * 2 > HEIGHT) and fruit.velocity.y > 0):
self.fruits.remove(fruit)
self.cleared_wave = False
+
self.time_since_last_hit += delta
if self.time_since_last_hit < self.COMBO_TIME:
self.score += self.current_combo
+ self.score_surf = font.render(f"SCORE {self.score}", True, WHITE)
+ self.score_txt = Texture.from_surface(renderer, self.score_surf)
+ self.high_score_surf = font.render(f"BEST {self.high_score}", True, WHITE)
+ self.high_score_txt = Texture.from_surface(renderer, self.high_score_surf)
else:
self.current_combo = 0
+ self.combo_surf = font.render(f"COMBO x{self.current_combo}", True, WHITE)
+ self.combo_txt = Texture.from_surface(renderer, self.combo_surf)
for hit, mouse_direction, mouse_position in hits:
-
color = random.choice(EFFECT_COLORS)
- self.effects[0].append(
- BloodSplatter(hit.position, hit.radius, determine_angle(hit.position, hit.position + mouse_direction),color))
- self.effects[1].append(BloodEffect(hit.position, hit.radius,lighten(color, 0.15)))
+ self.effects[0].append(BloodSplatter(hit.position, hit.radius,
+ determine_angle(hit.position, hit.position + mouse_direction),
+ color))
+ self.effects[1].append(BloodEffect(hit.position, hit.radius, lighten(color, 0.15)))
- half1, half2, pos1, pos2 = SplitEffect.split_image(hit.image, hit.angle, hit.position, mouse_position, mouse_direction)
+ half1, half2, pos1, pos2 = SplitEffect.split_image(hit.image, hit.angle, hit.position, mouse_position,
+ mouse_direction, hit.radius)
- n1, n2 = SplitEffect.find_normals(mouse_direction.normalize())
- c = 100
- self.effects[2].append(SplitEffect(pos1, half1, hit.velocity, n1 * c))
- self.effects[2].append(SplitEffect(pos2, half2, hit.velocity, n2 * c))
+ n1, n2 = SplitEffect.find_normals(mouse_direction.normalize() * 5)
+ self.effects[2].append(SplitEffect(pos1, half1, hit.velocity, n1))
+ self.effects[2].append(SplitEffect(pos2, half2, hit.velocity, n2))
pygame.mixer.Sound.play(random.choice(self.slash_sounds))
self.score += 1
+ self.score_surf = font.render(f"SCORE {self.score}", True, WHITE)
+ self.score_txt = Texture.from_surface(renderer, self.score_surf)
+ self.high_score_surf = font.render(f"BEST {self.high_score}", True, WHITE)
+ self.high_score_txt = Texture.from_surface(renderer, self.high_score_surf)
+
if self.time_since_last_hit < self.COMBO_TIME:
self.current_combo += 1
+ self.combo_surf = font.render(f"COMBO x{self.current_combo}", True, WHITE)
+ self.combo_txt = Texture.from_surface(renderer, self.combo_surf)
if self.current_combo > 1:
- self.combo_counters.append(ComboCounter(hit.position, f"x{self.current_combo + 1}"))
- self.effects[3].append(SlashEffect(hit.position, hit.angle, combo=False))
- else:
- self.effects[3].append(SlashEffect(hit.position, hit.angle))
+ self.combo_counters.append(ComboCounter(hit.position, self.current_combo + 1))
+ self.effects[3].append(SlashEffect(hit.position, hit.angle))
self.time_since_last_hit = 0
if hit in self.fruits:
effect_status = effect.update(delta)
if effect_status:
layer.remove(effect)
+
for combo in self.combo_counters:
combo_status = combo.update(delta)
if combo_status:
for bomb in self.bombs:
bomb_status = bomb.update(delta)
-
if self.player.hits(bomb):
bomb.explode(self.fruits, self.bombs, self.effects[2])
- self.game_over = True
- self.player.sliced_points.clear()
- pygame.mixer.Sound.play(self.bass_sound_effect)
- self.effects[4].append(FadeOutEffect(fade_time=self.GAME_OVER_TIME, max_alpha=20))
- if self.score > self.highscore:
- self.highscore = self.score
- with open(self.HIGHSCORE_FILE, "w") as f:
- f.write(str(self.highscore))
+ self.set_game_over()
+
if bomb_status:
self.bombs.remove(bomb)
continue
- br = bomb.get_rect()
- if ((not -bomb.width < br.x < WIDTH + bomb.width) or br.y - br.height > HEIGHT) and bomb.velocity.y > 0:
+ if (((not -bomb.radius * 2 < bomb.position.x < WIDTH + bomb.radius * 2) or
+ bomb.position.y - bomb.radius * 2 > HEIGHT) and bomb.velocity.y > 0):
self.bombs.remove(bomb)
if len(self.fruits) == 0 and len(self.bombs) == 0 and not self.game_over:
else:
self.fruits.append(Fruit())
- def draw(self, surf):
+ def set_game_over(self):
+ self.game_over = True
- screen.blit(self.BACKGROUND, (0, 0))
+ self.player.sliced_points.clear()
+ pygame.mixer.Sound.play(self.bass_sound_effect)
+ self.effects[4].append(FadeOutEffect(fade_time=self.GAME_OVER_TIME, max_alpha=20))
- text_surf = font.render(f"SCORE {self.score}", True, WHITE)
- surf.blit(text_surf, (7, 0))
- text_surf2 = font.render(f"COMBO x{max(1, self.current_combo)}", True, WHITE)
- surf.blit(text_surf2, text_surf2.get_rect(center=(WIDTH / 2, text_surf.get_height() / 2)))
- # text_surf2 = font.render(f"TIME SINCE LAST HIT {round(self.time_since_last_hit / 1000, 1)}", True, BLACK)
- # surf.blit(text_surf2, (WIDTH - text_surf2.get_width(), text_surf.get_height()))
+ if self.score > self.high_score:
+ self.high_score = self.score
+ with open(self.HIGH_SCORE_FILE, "w") as f:
+ f.write(str(self.high_score))
+
+ self.subtitle_surf = font.render(f"HIGH SCORE {self.high_score}", True, WHITE)
+
+ def draw(self):
+ self.BACKGROUND.draw(None, (0, 0))
+
+ self.score_txt.draw(None, (7, 0))
+ self.combo_txt.draw(None, (WIDTH / 2 - self.combo_txt.width / 2, 0))
+ self.high_score_txt.draw(None, (WIDTH - self.high_score_txt.width - 7, 0))
for effect in self.effects[0]:
- effect.draw(surf)
+ effect.draw()
for effect in self.effects[1]:
- effect.draw(surf)
+ effect.draw()
for bomb in self.bombs:
- bomb.draw(surf)
+ bomb.draw()
for effect in self.effects[2]:
- effect.draw(surf)
+ effect.draw()
for fruit in self.fruits:
- fruit.draw(surf)
+ fruit.draw()
for effect in self.effects[3]:
- effect.draw(surf)
+ effect.draw()
for combo in self.combo_counters:
- combo.draw(surf)
- self.player.draw(surf)
+ combo.draw()
+ self.player.draw()
for effect in self.effects[4]:
- effect.draw(surf)
+ effect.draw()
+
if self.game_over:
- title = font_large.render("GAME OVER", True, WHITE)
- subtitle = font.render(f"HIGHSCORE {self.highscore}", True, WHITE)
- game_over_surf = pygame.Surface(
- (max(title.get_width(), subtitle.get_width()), title.get_height() + subtitle.get_height()))
- game_over_surf.fill(GRAY)
- game_over_surf.blit(title, title.get_rect(center=(game_over_surf.get_width() / 2, title.get_height() / 2)))
- game_over_surf.blit(subtitle, subtitle.get_rect(
- center=(game_over_surf.get_width() / 2, title.get_height() + subtitle.get_height() / 2)))
-
- pygame.draw.rect(surf, GRAY, game_over_surf.get_rect(center=(WIDTH / 2, HEIGHT / 2)).inflate(50, 50),
- border_radius=10)
- pygame.draw.rect(surf, BLACK, game_over_surf.get_rect(center=(WIDTH / 2, HEIGHT / 2)).inflate(50, 50), 5,
- border_radius=10)
- surf.blit(game_over_surf, game_over_surf.get_rect(center=(WIDTH / 2, HEIGHT / 2)))
\ No newline at end of file
+ self.r1.draw()
+ self.r2.draw()
+ self.game_over_txt.draw(None, (
+ WIDTH / 2 - self.game_over_txt.width / 2, HEIGHT / 2 - self.game_over_txt.height / 2))
-# from game import Game
+from game import Game
from menu import Menu
from setup import *
-
FPS = 60
clock = pygame.time.Clock()
delta = clock.tick(FPS)
renderer.clear()
-
status = scene.update(delta)
scene.draw()
- fps_text = font.render(f"FPS {int(clock.get_fps())}", True, WHITE)
- fps_text_txt = Texture.from_surface(renderer, fps_text)
- fps_text_txt.draw(None, (WIDTH - fps_text.get_width() - 7, 0))
+ fps_text = font_small.render(f"FPS: {clock.get_fps():.0f}", True, DARK_GRAY)
+ fps_txt = Texture.from_surface(renderer, fps_text)
+ fps_txt.draw(None, pygame.Vector2(10, 75))
renderer.present()
if status == COMMAND_EXIT:
is_running = False
- # elif status == COMMAND_START:
- # scene = Game()
- # elif status == COMMAND_MENU:
- # scene = Menu()
+ elif status == COMMAND_START:
+ scene = Game()
+ elif status == COMMAND_MENU:
+ scene = Menu()
pygame.quit()
self.fruit = Fruit()
self.fruit.position = pygame.Vector2(WIDTH / 2, HEIGHT * 1.5 / 2.5)
self.fruit.angle = 0
- self.fruit.image = pygame.transform.scale(pygame.image.load("assets/fruits/58.png"),
- (self.fruit.radius * 2, self.fruit.radius * 2))
+ self.fruit.image = pygame.image.load("assets/fruits/58.png")
+ self.fruit.fruit_txt = Texture.from_surface(renderer, self.fruit.image)
+
# Effects
self.effects = []
# Rect textures
self.tutorial_surface_pos = (
- WIDTH / 2, HEIGHT * 2 / 3 + self.tutorial_surface.get_height() / 2 + self.fruit.get_rect().height + 30)
+ WIDTH / 2, HEIGHT * 2 / 3 + self.tutorial_surface.get_height() / 2 + self.fruit.radius + 30)
self.r1 = Rect(self.tutorial_surface.get_rect(center=self.tutorial_surface_pos).inflate(25, 25), DARK_GRAY, 10)
self.r2 = Rect(self.tutorial_surface.get_rect(center=self.tutorial_surface_pos).inflate(25, 25), BLACK, 10, 5)
hit_status = self.player.hits(self.fruit) # Check if player hits fruit
# Check if fruit should split
if hit_status and SplitEffect.should_split(self.fruit.image, self.fruit.angle, self.fruit.position,
- self.player.previous_mouse_pos, self.player.mouse_direction):
+ self.player.previous_mouse_pos, self.player.mouse_direction,
+ self.fruit.radius):
# Split fruit
color = random.choice(EFFECT_COLORS)
n1, n2 = SplitEffect.find_normals(self.player.mouse_direction.normalize() * 5)
- self.effects.append(BloodEffect(self.fruit.position, self.fruit.radius, lighten(color, 0.15)))
- half1, half2, pos1, pos2 = SplitEffect.split_image(self.fruit.image, self.fruit.angle,
- self.fruit.position, self.player.previous_mouse_pos,
- self.player.mouse_direction)
self.effects.append(BloodSplatter(self.fruit.position, self.fruit.radius,
determine_angle(self.fruit.position,
self.fruit.position + self.player.mouse_direction),
color))
+ self.effects.append(BloodEffect(self.fruit.position, self.fruit.radius, lighten(color, 0.15)))
+ half1, half2, pos1, pos2 = SplitEffect.split_image(self.fruit.image, self.fruit.angle,
+ self.fruit.position, self.player.previous_mouse_pos,
+ self.player.mouse_direction, self.fruit.radius)
self.effects.append(SplitEffect(pos1, half1, pygame.Vector2(0, 0), n1))
self.effects.append(SplitEffect(pos2, half2, pygame.Vector2(0, 0), n2))
-import pygame
-
from setup import *
self.display_image = self.IMAGE.copy()
self.position = pygame.Vector2(0, 0)
-
def update(self, delta):
pressed = pygame.mouse.get_pressed()
if pressed[0]:
self.lines.clear()
if len(self.sliced_points) > 1:
for i in range(len(self.sliced_points) - 1):
- self.lines.append((pygame.Vector2(self.sliced_points[i][0]), pygame.Vector2(self.sliced_points[i + 1][0])))
+ self.lines.append(
+ (pygame.Vector2(self.sliced_points[i][0]), pygame.Vector2(self.sliced_points[i + 1][0])))
for i, val in enumerate(self.sliced_points):
pos, time = val
for i in range(len(self.sliced_points) - 1):
renderer.draw_line(self.sliced_points[i][0], self.sliced_points[i + 1][0])
renderer.draw_line(self.previous_mouse_pos, self.previous_mouse_pos - self.mouse_direction)
-
if pos1.x == pos2.x:
pos2.x += 0.0001
a = math.degrees(math.atan((pos2.y - pos1.y) / (pos2.x - pos1.x)))
- return -a
-
-
-
-
+ return a
+++ /dev/null
-import pygame
-from pygame._sdl2 import Window, Renderer, Texture
-
-class App:
-
- def __init__(self):
- pygame.init()
-
- self.clock = pygame.time.Clock()
- self.display = pygame.display.set_mode((1366, 768))
- self.window = Window.from_display_module()
- self.renderer = Renderer(self.window)
- self.renderer.draw_color = (255, 0, 0, 255)
-
- a_surface = pygame.image.load('image.png')
- self.an_image = Texture.from_surface(self.renderer, a_surface)
-
- def run(self):
- while True:
-
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- pygame.quit()
- raise SystemExit
-
- self.renderer.clear()
- self.an_image.draw(None, (20, 20))
- self.renderer.present()
- self.clock.tick(60)
-
-
-app = App()
-app.run()
\ No newline at end of file