From 07606b648f3df543d636bae8fd65699b7cb7ea66 Mon Sep 17 00:00:00 2001 From: Kayla Date: Fri, 23 Aug 2024 01:24:48 -0400 Subject: [PATCH 1/3] formatting --- scenes/jackdefense/scripts/util.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scenes/jackdefense/scripts/util.py b/scenes/jackdefense/scripts/util.py index a256388..2ed3f4d 100644 --- a/scenes/jackdefense/scripts/util.py +++ b/scenes/jackdefense/scripts/util.py @@ -1,13 +1,17 @@ import pygame import random -class Deck(): + +class Deck: def __init__(self): self.deck: list[str] = ["basic", "fire"] - def get_deck(self,): + def get_deck( + self, + ): return self.deck.copy() - def draw_from_deck(self,): + def draw_from_deck( + self, + ): return random.choices(self.deck) - From cbd0d84cc053696f81d3a991ee904085763e01dc Mon Sep 17 00:00:00 2001 From: Kayla Date: Fri, 23 Aug 2024 01:25:16 -0400 Subject: [PATCH 2/3] sparks and particles on projectiles and projectile collisions --- scenes/jackninjas/jackninjas.py | 38 +++++++++----- scenes/jackninjas/scripts/entities.py | 74 +++++++++++++++++++++------ scenes/jackninjas/scripts/spark.py | 26 ++++++++++ scenes/jackninjas/scripts/tilemap.py | 2 +- 4 files changed, 111 insertions(+), 29 deletions(-) create mode 100644 scenes/jackninjas/scripts/spark.py diff --git a/scenes/jackninjas/jackninjas.py b/scenes/jackninjas/jackninjas.py index 0b05de3..2e8c2c6 100644 --- a/scenes/jackninjas/jackninjas.py +++ b/scenes/jackninjas/jackninjas.py @@ -8,6 +8,7 @@ from .scripts.tilemap import Tilemap from .scripts.clouds import Clouds from .scripts.particle import Particle +from .scripts.spark import Spark class JackNinjas(Scene): @@ -20,6 +21,7 @@ def __init__(self, game): self.clock = pygame.time.Clock() self.play_music("sounds/ambience.wav") + self.movement = [False, False] self.assets = { "decor": load_images("tiles/decor"), @@ -51,18 +53,15 @@ def __init__(self, game): self.clouds = Clouds(self.assets["clouds"], count=16) self.player = Player(self, (75, 75), (8, 15)) - self.tilemap = Tilemap(self, tile_size=16) - try: - self.tilemap.load("assets/jackninjas/map.json") - except FileNotFoundError: - pass - self.movement = [False, False] + self.load_level(0) + - # setup our pseudo camera - self.scroll = [0, 0] + def load_level(self, map_id): + self.tilemap.load("assets/jackninjas/maps/" + str(map_id) + '.json') + # setup leaf spawners self.leaf_spawners = [] for tree in self.tilemap.extract([("large_decor", 2)], keep=True): @@ -80,6 +79,9 @@ def __init__(self, game): self.projectiles = [] self.particles = [] + self.sparks = [] + # setup our pseudo camera + self.scroll = [0, 0] def perform_quit(self): pygame.quit() @@ -168,17 +170,26 @@ def draw(self): self.display.blit(img, (projectile[0][0] - img.get_width() / 2 - render_scroll[0], projectile[0][1] - img.get_height() / 2 - render_scroll[1])) if self.tilemap.solid_check(projectile[0]): self.projectiles.remove(projectile) + for i in range(4): + self.sparks.append(Spark(projectile[0], random.random() - 0.5 + (math.pi if projectile[1] > 0 else 0), 2 + random.random())) elif projectile[2] > 360: self.projectiles.remove(projectile) elif abs(self.player.dashing) < 50: # fast part of dash is over if self.player.rect().collidepoint(projectile[0]): self.projectiles.remove(projectile) + for i in range(30): + angle = random.random() * math.pi + speed = random.random() * 5 + self.sparks.append(Spark(self.player.rect().center, angle, 2 + random.random())) + self.particles.append(Particle(self, 'particle', self.player.rect().center, velocity=(math.cos(angle + math.pi) * speed * 0.5, math.sin(angle * math.pi) * speed * 0.5), frame = random.randint(0, 7))) + + for spark in self.sparks.copy(): + kill = spark.update() + spark.render(self.display, offset = render_scroll) + if kill: + self.sparks.remove(spark) - - # update and draw our player - self.player.render(self.display, offset=render_scroll) - # spawn leaf particles for rect in self.leaf_spawners: if random.random() * 50000 < rect.width * rect.height: @@ -205,6 +216,9 @@ def draw(self): if kill: self.particles.remove(particle) + # update and draw our player + self.player.render(self.display, offset=render_scroll) + # FRAME COMPLETE # we finished drawing our frame, lets render it to the screen and # get our input events ready for the next frame and sleep for a bit diff --git a/scenes/jackninjas/scripts/entities.py b/scenes/jackninjas/scripts/entities.py index 6cd157f..e1104f9 100644 --- a/scenes/jackninjas/scripts/entities.py +++ b/scenes/jackninjas/scripts/entities.py @@ -3,6 +3,7 @@ import pygame from .particle import Particle from scene import Scene +from .spark import Spark GRAVITY = 0.1 MAX_FALL_SPEED = 5 @@ -117,56 +118,97 @@ def __init__(self, scene: Scene, pos, size): def update(self, tilemap, movement=(0, 0)): if self.walking: - if tilemap.solid_check((self.rect().centerx + (-7 if self.flip else 7), self.pos[1] + 23)): - if (self.collisions["left"] or self.collisions["right"]): + if tilemap.solid_check( + (self.rect().centerx + (-7 if self.flip else 7), self.pos[1] + 23) + ): + if self.collisions["left"] or self.collisions["right"]: self.flip = not self.flip else: - movement = (movement[0] - 0.5 if self.flip else movement[0] + 0.5, movement[1]) + movement = ( + movement[0] - 0.5 if self.flip else movement[0] + 0.5, + movement[1], + ) else: self.flip = not self.flip self.walking = max(0, self.walking - 1) if not self.walking: - dis = (self.scene.player.pos[0] - self.pos[0], self.scene.player.pos[1] - self.pos[1]) + dis = ( + self.scene.player.pos[0] - self.pos[0], + self.scene.player.pos[1] - self.pos[1], + ) # check if the player is in range vertically - if abs(dis[1]) < 16: + if abs(dis[1]) < 16: # check if we are facing the player shoot = False shoot_mul = 1 shoot_offset = 7 shoot_speed = 1.5 + + # determine if we shoot if self.flip and dis[0] < 0: shoot = True shoot_mul = -1 elif not self.flip and dis[0] > 0: shoot = True - + + # take the shot if shoot: + start_timer = 0 self.scene.projectiles.append( - [[self.rect().centerx + shoot_offset * shoot_mul, self.rect().centery], shoot_speed * shoot_mul, 0] + [ + [ + self.rect().centerx + shoot_offset * shoot_mul, + self.rect().centery, + ], + shoot_speed * shoot_mul, + start_timer, + ] ) - - - # self.game.projectiles + for i in range(4): + self.scene.sparks.append( + Spark( + self.scene.projectiles[-1][0], + random.random() + - 0.5 + + (0 if shoot_mul == 1 else math.pi), + 2 + random.random(), + ) + ) + + # .projectiles elif random.random() < 0.01: self.walking = random.randint(30, 120) super().update(tilemap, movement) if movement[0] != 0: - self.set_action('run') + self.set_action("run") else: - self.set_action('idle') + self.set_action("idle") - def render(self, surf, offset=(0,0)): - super().render(surf=surf,offset=offset) + def render(self, surf, offset=(0, 0)): + super().render(surf=surf, offset=offset) if self.flip: - surf.blit(pygame.transform.flip(self.scene.assets['gun'], True, False), (self.rect().centerx - 4 - self.scene.assets['gun'].get_width() - offset[0], self.rect().centery - offset[1])) + surf.blit( + pygame.transform.flip(self.scene.assets["gun"], True, False), + ( + self.rect().centerx + - 4 + - self.scene.assets["gun"].get_width() + - offset[0], + self.rect().centery - offset[1], + ), + ) else: - surf.blit(self.scene.assets['gun'], (self.rect().centerx + 4 - offset[0], self.rect().centery - offset[1])) + surf.blit( + self.scene.assets["gun"], + (self.rect().centerx + 4 - offset[0], self.rect().centery - offset[1]), + ) + class Player(PhysicsEntity): def __init__(self, scene: Scene, pos, size): diff --git a/scenes/jackninjas/scripts/spark.py b/scenes/jackninjas/scripts/spark.py new file mode 100644 index 0000000..6771346 --- /dev/null +++ b/scenes/jackninjas/scripts/spark.py @@ -0,0 +1,26 @@ +import math + +import pygame + +class Spark: + def __init__(self, pos, angle, speed): + self.pos = list(pos) + self.angle = angle + self.speed = speed + + def update(self): + self.pos[0] += math.cos(self.angle) * self.speed + self.pos[1] += math.sin(self.angle) * self.speed + + self.speed = max(0, self.speed - 0.1) + return not self.speed + + def render(self, surf, offset=(0, 0)): + render_points = [ + (self.pos[0] + math.cos(self.angle) * self.speed * 3 - offset[0], self.pos[1] + math.sin(self.angle) * self.speed * 3 - offset[1]), + (self.pos[0] + math.cos(self.angle + math.pi * 0.5) * self.speed * 0.5 - offset[0], self.pos[1] + math.sin(self.angle + math.pi * 0.5) * self.speed * 0.5 - offset[1]), + (self.pos[0] + math.cos(self.angle + math.pi) * self.speed * 3 - offset[0], self.pos[1] + math.sin(self.angle + math.pi) * self.speed * 3 - offset[1]), + (self.pos[0] + math.cos(self.angle - math.pi * 0.5) * self.speed * 0.5 - offset[0], self.pos[1] + math.sin(self.angle - math.pi * 0.5) * self.speed * 0.5 - offset[1]), + ] + + pygame.draw.polygon(surf, (255, 255, 255), render_points) \ No newline at end of file diff --git a/scenes/jackninjas/scripts/tilemap.py b/scenes/jackninjas/scripts/tilemap.py index 63d0847..37cd529 100644 --- a/scenes/jackninjas/scripts/tilemap.py +++ b/scenes/jackninjas/scripts/tilemap.py @@ -79,7 +79,7 @@ def load(self, path): data = json.load(f) self.tilemap = data["tilemap"] self.tile_size = data["tile_size"] - self.offgrid_tiles = data["offgrid_tiles"] + self.offgrid_tiles = data["offgrid"] def autotile(self): for loc in self.tilemap: From 768e9a449e58deb08b344c0c25eb7994a8b1f208 Mon Sep 17 00:00:00 2001 From: Kayla Date: Tue, 27 Aug 2024 18:41:43 -0400 Subject: [PATCH 3/3] start of userinterface --- .../entities/player/kayla_idle/0.aseprite | Bin 0 -> 1077 bytes .../images/entities/player/kayla_idle/0.png | Bin 0 -> 420 bytes scenes/jackdefense/jackdefensegameboard.py | 35 +++++++++-- scenes/jackdefense/scripts/util.py | 56 ++++++++++++++++++ scenes/jackninjas/jackninjaseditor.py | 1 + scenes/jackninjas/scripts/entities.py | 3 +- scenes/jackninjas/scripts/tilemap.py | 7 +++ utils.py | 55 ++++++++++++++++- 8 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 assets/jackninjas/images/entities/player/kayla_idle/0.aseprite create mode 100644 assets/jackninjas/images/entities/player/kayla_idle/0.png diff --git a/assets/jackninjas/images/entities/player/kayla_idle/0.aseprite b/assets/jackninjas/images/entities/player/kayla_idle/0.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..3acc44807e0621e070f8a7681d789750f4e79c68 GIT binary patch literal 1077 zcmb`F>q`_-9EQ)DtFcN+E$Ld(pleBy<*mGQQHvHN`mh;f7Lh5UR%EiIg3*Uk$S#nS zUBoQ2q6`CF%S&Y!5E8LWjapNw&8!ef?c%yLJtr#r13Jq*?EGe!Gw<_GxT_HTl^WqC z6n+{ZL<+~`G6{_wa@}ik_#gjSrwHNrto^mCmgmmma94h9`Ohwo85k7P@5#D(HglFk^|J(2=TZEIlSgK(%X4}!jVtDw;w z4QD8doQKIf1Ghew^9#LD>285noHnSkg!nPq3?1Ef;Ft0eIGB+Qo8r&I+^B;vCUhe- z`h`KiIleGtQ6S8Um3uW>Owe|DCmic2g|GTQ!kYSLu&B5i?zS9*@d?Q=G*V`XGls&X z;0So!Y=#Y%4EVuX0pAYDcdNfY0S}$G!_CL;K~w%==%2O$h8&XVwpGg~pX_OXZQtHN zd&hOya;pfI7swrR(>B2^8`i?ONSVTDFunZ(2sk>OY5qNZ)9T{%{WFdc2SF0 zq+%4ExI`otQHVd}VGeCLLm0MDg(oCo2tBw#3|3Hr4`g5h4LCpm>4{EmLX()dWF;sm ziAcVAGM>WM{CAOCxQq2Wa#Qyy!EKyq6(L-3pt}6I$5YG^Ii)u{Vs#IfdTF0l9jWzL zzAfQm;MAZz?f$a%q%mFIwX$Tp$M(XAV$ZJTt3&pHlz6k_Xx56NQz@S91DSgoi+fIN z3?IvB@xA+^()MKJOlA7A>IIipj@)Rksq3@$CV5*Lyq)(469->rcTRg0>o}m6J-VG1 zIXvETx+!(#aAIpo)w}ewnG^YidsUzBTWXgKwVwNGohTSJ4bR`z`FvedUHFNH_oD|a QuScWQs@0lLorN=g0w&;mE&u=k literal 0 HcmV?d00001 diff --git a/assets/jackninjas/images/entities/player/kayla_idle/0.png b/assets/jackninjas/images/entities/player/kayla_idle/0.png new file mode 100644 index 0000000000000000000000000000000000000000..77dabd6463e636d26934e6666eb56ae304d50c54 GIT binary patch literal 420 zcmV;V0bBlwP)Px$UP(kjR7iF6A*aT%|)&64>fBg6shI$MET$*ti!UAJ7h%5d#;pD`pmw|zS zfx!oj4>!Pslat}h_wNjI*;wI{a_?R;tXnmOK{haz;qm&}5JB%)6a$!$IXp}#T%rKn zKU);E{@?idlVKtYGl~n)!O^cDQNn=YKqTGGXaH+Ez~&NcX#lGWWM$RG%fBrzUW(EeN+z10O%`lg+|7T$MiI#*;BLy_vfR`^HK^Vf) z41s(icx^rX_9<=`z--56Gd3{{0|@#1_wSz!zg|3q8v_r-U%!4Zii^t;)Qk>@&d%60 z6Kw!4%|sc1s~o^;06Z$uG{3`AHo^dk>1=EqC|UZ~uOE!~#4%hz4gdf_D3z9mucx8_ O0000= e["spawn_delay"]) or (e["total_count"] != e["remaining"] and e["frame_count"] >= e["spawn_cd"]): + self.enemy_list[e_type]["frame_count"] = 0 + self.enemy_group.add(Enemy(self.game, "basic", self.path)) + else: self.enemy_list[e_type]["frame_count"] += 1 + + self.enemy_group.update() + self.enemy_group.draw(self.background) + if pygame.K_ESCAPE in self.game.just_pressed: self.game.scene_push = "GameSelect" diff --git a/scenes/jackdefense/scripts/util.py b/scenes/jackdefense/scripts/util.py index a256388..41101ef 100644 --- a/scenes/jackdefense/scripts/util.py +++ b/scenes/jackdefense/scripts/util.py @@ -1,5 +1,7 @@ import pygame import random +from scene import Scene +from utils import * class Deck(): def __init__(self): @@ -11,3 +13,57 @@ def get_deck(self,): def draw_from_deck(self,): return random.choices(self.deck) +class Enemy(pygame.sprite.Sprite, Scene): + def __init__(self, game, e_type, path): + super().__init__(game) + pygame.sprite.Sprite.__init__() + + self.image, self.rect = self.load_png("opengameart-jeton-bleu.png") + + self.image = pygame.transform.scale(self.image, (8, 8)) + self.rect = self.image.get_rect() + + self.path = path + self.pos = path[0]["pos"] + + # direction is represented as a tuple (x_dir, y_dir) + # and will be 0 for no change, 1 or -1 for change + self.direction: tuple[int, int] = path[1]["direction"] + self.moving_to: tuple[int, int] = path[1]["pos"] + + self.health: int = 0 + self.speed: int = 0 + + match e_type: + case "basic": + self.health = 1000 + self.speed = 5 + print('Initializing basic enemy') + + def update(self): + # check for collision with bullets + + # update our movement + dx = 0 + dy = 0 + new_rect = self.rect.copy() + + # confirm we're not moving past our target in the x direction + if abs(new_rect.x + dx) < abs(self.moving_to[0]): + dx = self.direction[0] * self.speed + else: dx = self.moving_to[0] - new_rect.x + + # and again for y + if abs(new_rect.y + dy) < abs(self.moving_to[1]): + dy = self.direction[1] * self.speed + else: dy = self.moving_to[1] - new_rect.y + + # and finally move our sprite + new_rect.x += dx + new_rect.y += dy + self.rect = new_rect + + # check for collision with end + if self.rect.collidepoint(self.moving_to): + print('Enemy reached end!') + pygame.sprite.Sprite.kill(self) diff --git a/scenes/jackninjas/jackninjaseditor.py b/scenes/jackninjas/jackninjaseditor.py index 14258a2..516830b 100644 --- a/scenes/jackninjas/jackninjaseditor.py +++ b/scenes/jackninjas/jackninjaseditor.py @@ -2,6 +2,7 @@ from scene import Scene from .scripts.utils import load_images from .scripts.tilemap import Tilemap +from utils import Button class JackNinjasEditor(Scene): diff --git a/scenes/jackninjas/scripts/entities.py b/scenes/jackninjas/scripts/entities.py index 71e18f9..9728a04 100644 --- a/scenes/jackninjas/scripts/entities.py +++ b/scenes/jackninjas/scripts/entities.py @@ -246,7 +246,8 @@ def update(self, tilemap, movement=(0, 0)): # create a particle effect particle_angle = random.random() * math.pi * 2 # radians particle_speed = random.random() * 0.5 + 0.5 - particle_velocity = [math.cos(particle_angle) * particle_speed, math.sin(particle_angle) * particle_speed] + particle_velocity = [abs(self.dashing) / self.dashing * random.random() * 3, 0] + # particle_velocity = [math.cos(particle_angle) * particle_speed, math.sin(particle_angle) * particle_speed] self.scene.particles.append( Particle( self.scene, diff --git a/scenes/jackninjas/scripts/tilemap.py b/scenes/jackninjas/scripts/tilemap.py index c330395..154ded0 100644 --- a/scenes/jackninjas/scripts/tilemap.py +++ b/scenes/jackninjas/scripts/tilemap.py @@ -82,6 +82,13 @@ def load(self, path): self.tile_size = data["tile_size"] self.offgrid_tiles = data["offgrid_tiles"] + def generative_load(self, path): + with open(path, "r") as f: + data = json.load(f) + self.tilemap = data["tilemap"] + self.tile_size = data["tile_size"] + self.offgrid_tiles = data["offgrid_tiles"] + def autotile(self): for loc in self.tilemap: tile = self.tilemap[loc] diff --git a/utils.py b/utils.py index 50b930c..45ed1bc 100644 --- a/utils.py +++ b/utils.py @@ -48,6 +48,50 @@ def draw_grid(surf, tile_size = 16, color = (242,245,255)): pygame.draw.line(surf, color, (0, x * tile_size), (width, x * tile_size)) pygame.draw.line(surf, color, (x * tile_size, 0), (x * tile_size, height)) +class UserInterface(): + def __init__( + self, + screen, + pos: tuple[int, int] = (0, 0), + size: tuple[int, int] = None, + growth_dir: tuple[int, int] = (0, 1), # default menu expansion direction, used as a tuple for control in both directions + gap: int = 4, # default number of pixels between each item + ): + self.screen = screen + self.image = make_surface(size) + self.pos = pos + + self.growth_dir = growth_dir + self.gap = gap + + self.items: dict = { + + } + + def add_item(self, item, draw = True, path = None,): + if path: + if path not in self.items.keys(): + self.screen.log("ERROR: Path not found!") + return + self.items[path][item] = { + "draw": draw + } + else: + self.items[item] = {} + + # Removes specified element path from our list and returns the element + def remove_item(self, path): + return self.items[path].pop() + + def toggle_draw(self, item): + item["draw"] = !(item["draw"].) + + def update(): + pass + + def render(): + pass + class Button(): def __init__( self, @@ -110,7 +154,7 @@ def make_text( surf_text.get_width() + strokeThickness * 3, surf_text.get_height() + strokeThickness * 3, ) - surface = self.make_transparent_surface(size) + surface = make_transparent_surface(size) # blit the stroke text to the surface for i in range(strokeThickness * 2 + 1): @@ -344,7 +388,16 @@ def blit_outline(source: pygame.Surface, target: pygame.Surface, dest: tuple): target.blit(mask, (x, y - 1)) target.blit(mask, (x, y + 1)) +def make_surface(self, size) -> pygame.Surface: + """an alias for make_transparent_surface + + Returns: + pygame.Surface: a transparent surface + """ + return self.make_transparent_surface(size) +def make_transparent_surface(size) -> pygame.Surface: + return pygame.Surface(size, pygame.SRCALPHA, 32).convert_alpha() # test our utilities if ran directly if __name__ == "__main__": # test the Seed class