pygame, sprites, and rects - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: Game Development (https://python-forum.io/forum-11.html) +--- Thread: pygame, sprites, and rects (/thread-40984.html) Pages:
1
2
|
pygame, sprites, and rects - menator01 - Oct-25-2023 Taking the following snippet, is it possible to create a pygame.Rect() and add it to a sprite group? Been looking for awhile and not really found anything. Maybe just tired. lol. In the following example, I can get func1 to display but, not sure how to add func2 to a sprites group. Any help would be great. import pygame import sys # Initiate pygame pygame.init() # Create some settings size = (1280, 720) screen = pygame.display.set_mode(size) pygame.display.set_caption('Shmup') clock = pygame.time.Clock() hud = pygame.sprite.Group() def func1(): arect = pygame.Rect(30,10,125,25) pygame.draw.rect(screen, 'green', arect) def func2(): arect = pygame.Rect(30, 35, 125, 25) hud.add(arect) while True: event = pygame.event.poll() if event.type == pygame.QUIT: sys.exit() hud.update() hud.draw(screen) func1() pygame.display.update() clock.tick(60) pygame.quit() RE: pygame, sprites, and rects - deanhystad - Oct-25-2023 Things in a sprite group must act like sprites. A sprite must have a rectangle attribute, not be a rectangle. A sprite must have an image (a surface), though I think you can get around that one by supplying your own update and draw methods. A function is not going to satisfy the requirements of being sprite-like. RE: pygame, sprites, and rects - Windspar - Oct-25-2023 (Oct-25-2023, 04:25 AM)menator01 Wrote: Taking the following snippet, is it possible to create a pygame.Rect() and add it to a sprite group? pygame.sprite.Group only except sprites. sprite = pygame.sprite.Sprite() # Sprite must have image and a rect variable. sprite.rect = pygame.Rect(30, 35, 125, 25) sprite.image = pygame.Surface(sprite.rect.size) sprite.image.fill('green') hud.add(sprite)When you learn classes. class MySprite(pygame.sprite.Sprite): def __init__(self, color, x, y, w, h): super().__init__() self.rect = pygame.Rect(x, y, w, h) self.image = pygame.Surface(self.rect.size) self.image.fill(color) hud.add(MySprite('green', 30, 35, 125, 25)) RE: pygame, sprites, and rects - menator01 - Oct-25-2023 I figured out how to do it but, took another route as I wasn't able to figure out how to make the bar decrease and change colors the lower it got. RE: pygame, sprites, and rects - deanhystad - Oct-26-2023 Something like this? import pygame import sys import math class StatusBar(pygame.sprite.Sprite): def __init__( self, rect=(0, 0, 100, 10), max_=1, min_=0, fg="white", bg="black", center=None, colormap=None, ): super().__init__() self.rect = pygame.Rect(rect) self.bar = pygame.Rect(0, 0, self.rect.width, self.rect.height) self.image = pygame.Surface(self.rect.size) self.colormap = dict(sorted(colormap.items())) if colormap else {} self.fg = fg self.bg = bg self.max = max_ self.min = min_ self.range = self.max - self.min self.center = center self._value = 0 @property def value(self): return self._value @value.setter def value(self, new_value): self._value = max(self.min, min(new_value, self.max)) def update(self): if self.center is None: self.bar.width = int( self.rect.width * (self.value - self.min) / (self.max - self.min) ) else: a = self.rect.width * (self._value - self.min) / self.range b = self.rect.width * (self.center - self.min) / self.range self.bar.x = min(a, b) self.bar.width = abs(a - b) self.image.fill(self.bg) fg = self.fg for value, color in self.colormap.items(): if value <= self._value: fg = color else: break pygame.draw.rect(self.image, fg, self.bar) pygame.init() screen = pygame.display.set_mode((220, 90)) b1 = StatusBar((10, 10, 200, 10), min_=-1) b2 = StatusBar( (10, 30, 200, 10), min_=-1, colormap={-1: "green", 0: "yellow", 0.5: "red"} ) b3 = StatusBar((10, 50, 200, 10), min_=-1, center=0) b4 = StatusBar( (10, 70, 200, 10), min_=-1, center=0, colormap={ -1: "red", -0.75: "orange", -0.5: "yellow", -0.25: "green", 0.25: "yellow", 0.5: "orange", 0.75: "red", }, ) group = pygame.sprite.Group() group.add((b1, b2, b3, b4)) clock = pygame.time.Clock() for i in range(1000): event = pygame.event.poll() if event.type == pygame.QUIT: sys.exit() b1.value = math.sin(math.radians(i)) b2.value = math.cos(math.radians(i)) b3.value = math.sin(math.radians(i)) b4.value = math.cos(math.radians(i)) group.update() group.draw(screen) pygame.display.update() clock.tick(60) pygame.quit() RE: pygame, sprites, and rects - menator01 - Oct-27-2023 @deanhystad That looks good. I will have to study the math module. I'm not really familiar with cos and sin. Your example will help a great deal. Thanks. RE: pygame, sprites, and rects - menator01 - Oct-28-2023 I've uploaded the files to git if anyone wants to check it out. Other than some unknown bugs I haven't come across yet, only thing left is for me too add the form to enter scores. https://github.com/menator01/shmup2 I've finished the re-write. The old script had everything in one file. The re-writes has modules that are imported. I broke down the classes into modules. Depending on what that class does. There still may be some bugs that I've not found. I've added some things too. On the powerups that fall, if you catch one (there are only two - laser and shield), icons will apprear in the bottom right of the game window. They will disappear when done. Example - if you catch the shield icon and it gets destroyed, the icon will disappear. The laser is a timed powerup. To keep them, just have to keep catching them when they fall. Requirements:
I welcome any feedback. I've changed the shmup.py. Added a couple variables to set the range of mobs spawned. Had it hard coded so to speak to 8 - 10 mobs. Now it just can be set the min_mob and max_mob right before the while loop starts. import pygame from modules import abient, pages, character, mysprites, display from modules.character import player_sprite, mob_sprite, weapon_sprite from modules.powerups import PowerUp, power_sprite, Shield, shield_sprite from modules.effects import Explosion import os from random import random, randrange # Initiate pygame pygame.init() # pygame clock clock = pygame.time.Clock() # Get the working directory path path = os.path.realpath(os.path.dirname(__file__)) # Setup screen window screen = pygame.display.set_mode((1280, 720)) pygame.display.set_caption('Shmup') # Background music and image music = abient.Music(path) bgimg = pygame.image.load(f'{path}/media/images/backgrounds/space.png') bgimg_rect = bgimg.get_rect() # Set some variables gameover = True doform = False # range of mobs to spawn min_mob = 10 max_mob = 15 # Start the game loop while True: # Start the background music if not pygame.mixer.music.get_busy(): music.play() # Display the background image screen.blit(bgimg, bgimg_rect) # Poll pygame events event = pygame.event.poll() # Ways to exit the game if event.type == pygame.QUIT: break # Has a key been pressed if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: break # Fire weapons if event.key == pygame.K_m: player.missile() # We don't want the laser to fire without catching the icon first if player.laser_fire: if event.key == pygame.K_l: player.laser() else: player.laser_fire = False # We are not playing yet. Go to start title page if gameover: pages.Title(screen) gameover = False player = character.Player(path) shield = Shield(path) # Create some starting mobs for i in range(randrange(min_mob, max_mob)): mob = character.Mob(path) # Used for displaying the three life ships col = 0 for i in range(3): ship = display.Hud(path, 1120+col) col += 60 ship.newship() # Is the game over? Do we need to go to the form if doform: pages.Form(screen, player) doform = False gameover = True # Statusbars - Displays the info across the top including the life ships display.StatusBar(screen, 100, 15, player.life, text='Life') display.StatusBar(screen, 100, 45, shield.strength, text='Shield') ship.hud_sprites.update() ship.hud_sprites.draw(screen) display.Score(screen, player.score) display.Tips(screen, 880, 680) # If player looses a life, remove ship from top for item in ship.hud_sprites: if len(ship.hud_sprites) > player.lives: ship.hud_sprites.remove(item) # Draw and update all the sprites mysprites.allsprites.update() mysprites.allsprites.draw(screen) # Having to keep these seperate from allsprites to detect collisions mob_sprite.update() mob_sprite.draw(screen) display.show_sprite.update() display.show_sprite.draw(screen) # Set weapon to True will get destroyed weapon = True # Loop through weapon_sprite if weapon type is laser, # set weapon to True. laser will not be destroyed for weapons in weapon_sprite: weapon = True if weapons.type == 'missile' else False # Check for weapon hitting mob weaponhits = pygame.sprite.groupcollide(weapon_sprite, mob_sprite, weapon, True) for weaponhit in weaponhits: character.Mob(path) player.score += int(mob.radius * random()) Explosion(path, weaponhit.rect.center) if random() > 0.8: PowerUp(path, weaponhit.rect.center) #Detect powerup hit powerhits = pygame.sprite.groupcollide(power_sprite, player_sprite, True, False) # Loop through the powerup and apply accordingly for powerhit in powerhits: # Caught a shield icon if powerhit.type == 'shield': for shield in shield_sprite: shield.kill() shield = Shield(path) shield.strength = 100 shield.raise_shield(player.rect.centerx, player.rect.top) show_shield = display.Show(path, 'shield.png', 1195, 690) display.show_sprite.add(show_shield) # Caught a partial heal icon if powerhit.type == 'heal': sound = pygame.mixer.Sound(f'{path}/media/sounds/partial_heal.wav') sound.set_volume(0.9) sound.play() if player.life == 100: player.score += int(player.life * random()) else: player.life += int(player.life * random()) if player.life > 100: player.life = 100 # Caught a laser icon if powerhit.type == 'laser': player.laser_timer = pygame.time.get_ticks() player.laser_fire = True laser = display.Show(path, 'laser2.png', 1165, 690) display.show_sprite.add(laser) # Caught a full heal icon if powerhit.type == 'fullheal': sound = pygame.mixer.Sound(f'{path}/media/sounds/full_heal.wav') sound.set_volume(0.9) sound.play() if player.life == 100: player.score += int(randrange(10, 50) * random()) else: player.life = 100 # Timer for laser. Laser ends after 10 seconds unless another # laser powerup is caught if player.laser_timer: if pygame.time.get_ticks() - player.laser_timer > 10000: player.laser_fire = False player.laser_timer = None # Laser end remove from icon from game screen for item in display.show_sprite: if item.type == 'laser2': item.kill() # Checking for mobs hitting the shield shieldhits = pygame.sprite.groupcollide(mob_sprite, shield_sprite, True, False) for shieldhit in shieldhits: mob = character.Mob(path) Explosion(path, shieldhit.rect.center) # Shield was hit, remove some of the strength shield.strength -= int(shield.radius *0.3) # Shield strength reached 0, remove it if shield.strength <= 1: shield.strength = 0 for item in shield_sprite: item.kill() shield.hidden = True # Lost shield remove icon from the game screen for item in display.show_sprite: if item.type == 'shield': item.kill() # Player takes hits from mobs ship_destroy = False if player.life <= 0: ship_destroy = True player.lives -= 1 player.life = 100 player.hide() player.laser_fire = False player.laser_timer = None display.show_sprite.empty() # If player looses all lifes, reset everything and go to form if player.lives <= 0 and not player.explosion.alive(): mysprites.allsprites.empty() display.show_sprite.empty() mob_sprite.empty() shield_sprite.empty() ship.hud_sprites.empty() doform = True # Detect if any mobs has hit the player. We need to create a newmob for the one killed mobhits = pygame.sprite.groupcollide(mob_sprite, player_sprite, True, False) for mobhit in mobhits: Explosion(path, mobhit.rect.center) player.life -= int(mobhit.radius) character.Mob(path) # Update the display pygame.display.update() clock.tick(60) pygame.quit() RE: pygame, sprites, and rects - Windspar - Oct-31-2023 Why are you using pygame.event.poll ? That does 1 event per frame. This will give you unwanted side effects. running = True while running: # Event Loop for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # Get Key States keys = pygame.key.get_pressed() if keys[pygame.K_m]: # Fire Missle. Would need a timer for a refresh rate. RE: pygame, sprites, and rects - menator01 - Oct-31-2023 Perhaps but, it satisfies the need for the game. I've not found any side effects yet. RE: pygame, sprites, and rects - Windspar - Nov-01-2023 You probably don't know what side effects it will cause. If you had more events trigger. You would notice lag on input. |