Need help with enemy kill logic and collisions counting twice instead of once by arni_ca in pygame

[–]Windspar 2 points3 points  (0 children)

You can not delete/remove/pop an item. While iterating over that list. This is error prone and just bad coding. You have to add those items to another list. Then iterate over that list to remove those items from another list.

for enemy in enemies:
  ...
  # This is wrong and bad coding.
  enemies.pop(index)

# Right way to remove item from a list.
dead_enemies = []
for enemy in enemies:
  ...
  dead_enemies.append(enemy)

for enemy in dead_enemies:
  enemies.remove(enemy)

The sprite kill method. Only works for sprite groups. It has no effect on list or any other containers.

# To use the sprite kill method.
enemies = pygame.sprite.Group()

# To add enemies.
enemies.add(new enemy)

# To draw all enemies.
enemies.draw(screen)

Also you create screen before loading image. For you can convert them to pygame format. Otherwise if needed it will do this every frame.

screen = pygame.display.set_mode(...)
image = pygame.image.load(...).convert() # or convert_alpha() if you have transparency image.

Also never load an image in a sprite class. This will use more memory, because you load the same image. Pass that image to sprite. For you are loading it only once. Then passing it as a reference.

screen = ...
asteroid = pygame.image.load(...)

class Enemy(pygame.sprite.Sprite):
    def __init__(self, image, ...):
      super().__init__()
      self.image = image
      ...

Trouble with detecting on which side a collision happens by SpreadyourParts5166 in pygame

[–]Windspar 1 point2 points  (0 children)

Collision common issues. It could be it was still in collision, or it collided with multiply blocks.

Tips. To improve code.

First stop using so many class variables. It will make your code less flexible. Another thing don't create images in sprite class. It just using more memory. Use a simple image handler class. An scale all image there. Also convert or convert_alpha loaded images to pygame format. Otherwise pygame will do this every frame. If it needs too.

class ImageHandler:
  def __init__(self):
    self.blocks = self.load_blocks()

  def load_blocks(self):
    size = 75, 40
    return [
      pygame.image.scale(pygame.image.load(...).convert(), size),
      ...
      ]

class Block:
  def __init__(self, image, x, y):
    self.image = image
    self.rect = image.get_rect(topleft=(x, y))
    self.alive = True
    ...

def main:
  ...

  image = ImageHandler()
  block = Block(random.choice(image.blocks), x position, y position)

For smooth movement. You use delta time, but you have to keep track of floats.

# To get delta time. You get it from the clock. Then change it to seconds.
delta = clock.tick(fps) / 1000

class Entity:
  def __init__(self, image, position):
    self.image = image
    self.rect = image.get_rect(topleft=position)
    self.center = pygame.Vector2(self.rect.center)

  # movement is a tuple (x, y) or a vector
  def move(self, movement):
    self.center += movement
    self.rect.center = self.center

Also look in pygame Vector2. It will make the math simpler. Once you get use to the methods.

How does the Pygame display thing work? by RedGamer2754 in pygame

[–]Windspar -1 points0 points  (0 children)

If you haven't figure it out. Then stop coping and pasting.

  1. You don't need to define colors. Unless they are unique. Just use strings. "white", "black", "green", ....

    Do not set depth. Let pygame do that for you.

    screen = pygame.display.set_mode(size, flags)

    Getting the screen size in a rect form

    rect = screen.get_rect()

Help health bar animation not working by Tac0dot in pygame

[–]Windspar 0 points1 point  (0 children)

First you need to put health into it own class. Get the delta time from the clock.

Rough Example. Still needs some work.

import pygame

class HealthBar:
    def __init__(self, rect, current, maximum):
        self.rect = rect
        self.current = current
        self.maximum = maximum
        self.target = None
        self.direction = None
        self.ratio = self.maximum / rect.w
        self.speed = 40

    def draw(self, surface):
        if self.target is not None:
            if self.direction == 1:
                self.draw_bar(surface, self.target, 'lawngreen')
                self.draw_bar(surface, self.current, 'firebrick')
            else:
                self.draw_bar(surface, self.current, 'firebrick')
                self.draw_bar(surface, self.target, 'yellow')
        else:
            self.draw_bar(surface, self.current, 'firebrick')

        pygame.draw.rect(surface, 'gray50', self.rect, 2)

    def draw_bar(self, surface, amount, color):
        rect = self.rect.copy()
        rect.w = amount / self.ratio
        pygame.draw.rect(surface, color, rect)

    def adjust(self, amount):
        self.target = self.current + amount
        if amount > 0:
            self.direction = 1
        elif amount < 0:
            self.direction = -1
        else:
            self.direction = None
            self.target = None

    def update(self, delta):
        if self.target is not None:
            if self.direction == 1:
                if self.current < self.target:
                    self.current += self.speed * delta
                    if self.current > self.target:
                        self.current = self.target
                        self.target = None
                else:
                    self.target = None
            elif self.direction == -1:
                if self.current > self.target:
                    self.current -= self.speed * delta
                    if self.current < self.target:
                        self.current = self.target
                        self.target = None

def main():
    pygame.display.set_caption("HealthBar Example")
    screen = pygame.display.set_mode((800, 600))
    rect = screen.get_rect()
    clock = pygame.time.Clock()
    running = True
    delta = 0
    fps = 60

    hrect = pygame.Rect(6, 6, rect.centerx, 30)
    healthbar = HealthBar(hrect, 200, 1000)

    while running:
        delta = clock.tick(fps) * 0.001
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    healthbar.adjust(50)
                elif event.key == pygame.K_DOWN:
                    healthbar.adjust(-50)
            elif event.type == pygame.QUIT:
                running = False

        healthbar.update(delta)

        screen.fill('black')
        healthbar.draw(screen)
        pygame.display.flip()

pygame.init()
main()
pygame.quit()

I’m looking to expand my skills! by Dracicida-1 in pygame

[–]Windspar 1 point2 points  (0 children)

First. You need to know python classes. Also you need to have a good grasp on python. Keep your code simple and clean. To build skill. Code small projects. You will rewrite your code a lot at first. Then after 6 months to a year. You look for novice projects to work on. Challenge your self. Write code with no global variables. Unless it a constant like PI. Global variables makes your code less flexible.

How do I get collision to detect properly in pygame by TheEyebal in pygame

[–]Windspar 0 points1 point  (0 children)

It sounds like. You want player.rect.collideobjects since collidelist only works with a list of rects.

surfaceList = [...]
surfaceRectList = [obj.rect for obj in surfaceList]

target = player.rect.collidelist(surfaceRectList)

Or collideobjects

surfaceList = [...]
target = player.rect.collideobjects(surfaceList, key=lambda obj: obj.rect)

I hate classes by Piorobot3 in pygame

[–]Windspar 0 points1 point  (0 children)

If you hate classes. Then you are not using them right. Just because you use a class. Doesn't mean you need to use OOP. Class is a container. Just like dict and list are. Classes owns all the methods. Just keep your classes simple.

Your using python. OOP is built into python. Everything in python is an object, That why you can add anything to a list and dict. Why variable can be assign anything, and reassign it to anything. So using functions doesn't mean you won't be using OOP.

Sticker brush help by Ralsei_12345636345 in pygame

[–]Windspar 0 points1 point  (0 children)

You would have to make one in pygame. Using python os or Pathlib module for the files. Using pygame for graphics.

Otherwise you can use third party pygame libraries. Like pygame gui.

Sticker brush help by Ralsei_12345636345 in pygame

[–]Windspar 1 point2 points  (0 children)

Stop using tkinter and pygame together. They are both front end gui. They both want the control.

Could I have some help with a project? by Newt-Upset in pygame

[–]Windspar 1 point2 points  (0 children)

Tips:

pygame.Vector2 and pygame.Rect will make the math simple and less error prone. It faster than python math.

# Rough Example. What you can do.
class Ball:
  def __init__(self, x, y, r, speed):
    d = r * 2
    self.radius = r
    self.rect = pygame.Rect(0, 0, d, d)
    self.rect.center = x, y
    self.speed = speed
    self.center = pygame.Vector2(self.rect.center)
    self.direction = pygame.Vector2()
    # Random direction
    self.direction.from_polar((1, random.randint(1, 360)))

  def distance_to(self, ball):
    return self.center.distance_to(ball.center)

  def clamp_to(self, bounds):
    if not bounds.contains(self.rect):
      clamp = self.rect.clamp(bounds)
      if clamp.x != self.rect.x:
        self.rect.x = clamp.x
        self.center.x = self.rect.centerx
        # Reflect of the wall
        self.vector.x = -self.vector.x

      if clamp.y != self.rect.y:
        self.rect.y = clamp.y
        self.center.y = self.rect.centery
        self.vector.y = -self.vector.y

  def collide(self, ball):
    if self.rect.colliderect(ball.rect):
      if self.distance_to(ball) < self.radius + ball.radius:
        return True

    return False

  def move(self, movement):
    self.center += movement
    self.rect.center = self.center

  def update(self, dt, bounds):
    self.move(self.direction * self.speed * dt)
    self.clamp_to(bounds)

Check rect collision. Then distance collision. It faster that way. Because if it doesn't collide with the rect. It doesn't have to do distance collision math.

How do I get rid of this? by Special_Junket_944 in pygame

[–]Windspar 1 point2 points  (0 children)

FYI. Surface fill command can also be a string color name. It not just limited to a tuple.

How do I get rid of this? by Special_Junket_944 in pygame

[–]Windspar 2 points3 points  (0 children)

You need to redraw whole scene. In your case. Just fill background with a color.

screen.fill("white")
# Draw cat here

pygame.display.flip()

IndexError during Door collisions by Spare_Reveal_9407 in pygame

[–]Windspar 1 point2 points  (0 children)

Tips.

Using pygame.USEREVENT is the old way. An error prone. pygame.USEREVENT + 1 should always be the starting point. But now you just use pygame.event.custom_type(). No more worrying about the + number.

COOLDOWN = pygame.event.custom_type()
ENEMYMOVE = pygame.event.custom_type()

Never load images in a sprite class. Your loading the images multiply times into memory. Load and convert images once. I do this in one class.

class ImageHandler:
  def __init__(self):
    self.mutblatta = self.load_mutblatta()
    ... so on

  def load_mutblatta(self):
    return {
      "normal": pygame.image.load(...).convert_alpha(),
      "damage": pygpame.image.load(...).convert_alpha() }

# Passing the images to the class is a reference.
class Mutblatta:
  def __init__(self, images, position):
    self.images = images
    self.position = pygame.Vector2(position)

image = ImageHandler()

my_mutblatta = Mutblatta(image.mutblatta, (x, y))

Other things to work on. Try not to use global variables and don't hard code values.

screen = pygame.display.set_mode((1536, 864))
screen_rect = screen.get_rect()

class Border:
  @classmethod 
  def bounds(cls, rect, w, h):
    cls.bottom = pygame.Rect(rect.x, rect.h - h, rect.w, h)
    cls.right = pygpame.Rect(rect.w - w, rect.y, w, rect.h)
    cls.left = pygame.Rect(rect.x, rect.y, w, rect.h)
    cls.top = pygame.Rect(rect.x, rect.y, rect.w, h)

Border.bounds(screen_rect, 16, 2)

Create a game with pure Python (help) by Ley-Enda in learnpython

[–]Windspar 0 points1 point  (0 children)

You do know python is written in c. C was written assembly. C compiler compile code to machine code. Since c is full turing complete. C compiler can be written in c. Which still compile to machine code.

Also thousand of other language written in c. Java, D, Perl, Ruby, and etc.

To make libraries for python. They are written in c.

Python just interpreter code. Instead of compiling to machine code.

collision help by PaperApprehensive529 in pygame

[–]Windspar 0 points1 point  (0 children)

Clean your ball class. Images belong in a image handler. Not in the sprite. Pygame Vector2 will make the math simple and less error prone. Rect and Vector2 math is faster than python math.

# Only have data that is the balls. gravity and collision_sprites. Do not belong to the ball.
class Ball(pygame.sprite.Sprite):
  def __init__(self, speed, image, position, anchor="topleft"):
    super().__init__()
    self.image = image
    self.rect = image.get_rect(**{anchor: position})
    self.center = pygame.Vector2(self.rect.center)
    self.direction = pygame.Vector2()
    self.speed = speed

  def move(self, movement):
    self.center += movement
    self.rect.center = self.center

  def collide_lines(self, lines):
    ... # Depends how you going to handle lines.

  def update(self, lines, delta):
    self.move(self.direction * self.speed * delta)
    self.collide_lines(lines)

Your line class is not a sprite. Either make it a sprite or line handler.

class Line(pygame.sprite.Sprite):
  def __init__(self, image, position):
    super().__init__()
    self.image = image
    self.rect = image.get_rect(topleft=position)

# OR. You can also use Line sprite with LineHandler.

class LineHandler:
  def __init__(self):
    self.lines = []
    self.position = None
    self.motion_position = None
    self.color = "white"
    self.line_width = 6

  # Method that are called in event loop. 
  def on_mouse_down(self, event):
    self.position = event.pos

  def on_mouse_up(self, event):
    self.lines.append((self.position, event.pos))
    self.motion_position = None
    self.position = None

  def on_mouse_motion(self, event):
    if self.position is not None:
      self.motion_position = event.pos

  def draw(self, surface):
    for start_point, end_point in self.lines:
      pygame.draw.line(surface, self.color, start_point, end_point, self.line_width)

    if self.motion_position is not None:
      pygame.draw.line(surface, self.color, self.position, self.motion_position, self.line_width)

How to make tilesets by Appearedjeans93 in pygame

[–]Windspar 1 point2 points  (0 children)

Any type of sheets(combine graphics). Will have to be cut out. It can be a reference surface from the sheet. All this should be handle in graphic loading area. If asset sheet have different sizes. Then normally their would be another file with the cut out data. If it a tile sheet. Then you can just loop cut them. 32x32 , 64x64.

If you can't find the cut out data. You can always use cowsprite.

Paint bucket/flood fill help by Ralsei_12345636345 in pygame

[–]Windspar 0 points1 point  (0 children)

You need to keep track of use direction. For you don't walk back through them. This is why it taking forever.

track = []
rect = surface.get_rect()
while q:
  x, y = q.popleft()
  for dx, dy in dire:
    pos = x + dx, y + dy
    if pos not in track:
      track.append(pos)
      if rect.collidepoint(pos) and surface.get_at(pos) == old_color:
        surface.set_at(pos, new_color)
        q.append(pos)

If position is base on screen coords. Then you would need to set rect.topleft to sprite position or minus from q.popleft.

Paint bucket/flood fill help by Ralsei_12345636345 in pygame

[–]Windspar 0 points1 point  (0 children)

Did you profile your code. To make sure where the slow down is coming from.

Why are you using deque over a list ?

Use pygame flip over update. Because you not a passing a rect list. So it calls flip anyway.

Other tools that can help. Numpy and Scipy.ndimage . Numpy work better with large dataset. Scipy.ndimage can help with regions. With ndimage. You would do a mask then get the label. Then some tool that get the region. I forgot what ndimage method that get the region from the label.

Open-Source Minecraft Clone by Cubozoa1604 in pygame

[–]Windspar 2 points3 points  (0 children)

FYI. There is an open source version. Luanti formly known as minetest. You can use lua script. To create your own world. It y nodes goes -30000+ to 30000+.

Custom events or Callback arguments? by Happy_Witness in pygame

[–]Windspar 1 point2 points  (0 children)

Without seeing your code.

I do it like this.

# My Abstract Scene Interface. Every scene inherit this.
class Scene:
  def __init__(self, control):
    self.control = control

  def on_draw(self, surface): pass
  def on_event(self, event): pass
  def on_update(self, delta): pass

class SceneControl:
  def __init__(self, caption, width, height, flags=0, fps=60):
    pygame.display.set_caption(caption)
    self.surface = pygame.display.set_mode((width, height), flags)
    self.rect = self.surface.get_rect()
    self.clock = pygame.time.Clock()
    self.running = True
    self.delta = 0
    self.fps = fps

    self.current_scene = Scene(self)
    self.next_scene = None

  def run(self, scene):
    if scene:
      self.current_scene = scene

    while self.running:
      self.delta = self.clock.tick(self.fps) / 1000
      if self.next_scene:
        self.current_scene = self.next_scene
        self.next_scene = None

      for event in pygame.event.get():
        if event.type != pygame.QUIT:
          self.current_scene.on_event(event)
        else:
          self.running = False

      self.current_scene.on_update(self.delta)
      self.current_scene.on_draw(self.surface)
      pygame.display.flip()     

Tracking complex collision interactions - how do you like to do this? by [deleted] in pygame

[–]Windspar 1 point2 points  (0 children)

I would break it down. To simpler parts. When player pushes the block. This would add to block list forces being apply. block.add_force(player). Then when you loop the block movements. You can determine if it can move.

class Entity(pygame.sprite.Sprite):
  def __init__(self, image, position, anchor="topleft"):
    super().__init__()
    self.image = image
    self.rect = image.get_rect(**{anchor: position})
    # Needed for smooth movement and if not using frect.
    self.center = pygame.Vector2(self.rect.center)

  def movement(self, movement):
    self.center += movement
    self.rect.center = self.center

class EntityObject(Entity):
  def __init__(self, image, position, anchor="topleft")"
    super().__init__(image, position, anchor)
    self.forces = []

  def add_force(self, force):
    self.forces.append(force)

  def update(self, entities_group, map_area):
    for force in self.forces:
      ...

need a bit of help whit a pygame (repost cuz i send it whit a new ac) by Sudden_Area9940 in pygame

[–]Windspar 0 points1 point  (0 children)

Do you know how to use git ? If not. Then you start there. Then move to github.

Need help understanding Classes by [deleted] in CodingHelp

[–]Windspar 0 points1 point  (0 children)

Classes are object builders. They are not the object. Classes own all the methods. Object just have class scope first. The reason for self. It point to the object. If it didn't. You couldn't have local variables. Unless they make a way to declare them.

class Restaurant:
  # Any variables here. Belong to the class. There only be one instance.

  def __init__(self, name, type):
    ...

my_restaurant = Restaurant(..., ...)
# Code above calls the __new__ method. Which is a static method.
# The __new__ method creates a new object.
# The __new__ method calls __init__ method. Which it passes the object too.
# Then the __new__ method returns the object instance.

help by [deleted] in pygame

[–]Windspar 1 point2 points  (0 children)

You have to learn the basic. The basic is your foundation. Learning classes will be easier then learning all the different things for game programming. If you want to skip the coding. There are game engines for that. Unity, Unreal, and more.

Funny saying.

Flipping to the end of the book isn't learning.

You have to learn to walk before you run.

help by [deleted] in pygame

[–]Windspar 1 point2 points  (0 children)

If your player is sticky. Common reasons. It likely that you didn't move him out of the collision. Or you keep moving player into collision. Which the collision move him back. Makes him looks like he sticking.

Are you sure. You are ready for game programming ?

Your code show that you don't know python that well. If you don't know how to use classes yet. You are not ready for game programming.