3

I made a little Space Invaders like game, everything is good except that I feel like my enemies I programmed move too fast. If I make their movement speed under 1 such as 0.5, they won't even move. Is there a way I can make the movement even slower?

Here is the code for my enemy unit:

import math


WINDOW = pygame.display.set_mode((800, 900))


class Enemy (pygame.sprite.Sprite):

    def __init__(self):
        super(). __init__ ()
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((20,20))
        self.image.fill((255,0,0))
        pygame.draw.circle(self.image,(COLOUR4), (10,10),10)
        self.rect=self.image.get_rect()
        self.rect.center=(0,0)
        self.dx=2
        self.dy=1

    def update(self):
        self.rect.centery += self.dy


for i in range (100):
    enemy = Enemy()
    enemy.rect.x=random.randrange(750)
    enemy.rect.y=random.randrange(100)
    enemy_list.add(enemy)
    all_sprites_list.add(enemy)
skrx
  • 19,980
  • 5
  • 34
  • 48
  • Your indentation is wrong, please can you fix it so that it's clear what your code is doing? Thank you! – ash Jun 14 '18 at 15:06

1 Answers1

1

The problem is that pygame.Rects can only have ints as their coordinates and floats get truncated. If you want floating point values as the velocities, you have to store the actual position as a separate attribute (or two as in the first example below), add the velocity to it every frame and then assign the new position to the rect.

class Enemy(pygame.sprite.Sprite):

    def __init__(self, pos):  # You can pass the position as a tuple, list or vector.
        super().__init__()
        self.image = pygame.Surface((20, 20))
        self.image.fill((255, 0, 0))
        pygame.draw.circle(self.image, (COLOUR4), (10, 10), 10)
        # The actual position of the sprite.
        self.pos_x = pos[0]
        self.pos_y = pos[1]
        # The rect serves as the blit position and for collision detection.
        # You can pass the center position as an argument.
        self.rect = self.image.get_rect(center=(self.pos_x, self.pos_y))
        self.dx = 2
        self.dy = 1

    def update(self):
        self.pos_x += self.dx
        self.pos_y += self.dy
        self.rect.center = (self.pos_x, self.pos_y)

I recommend using vectors, since they are more versatile and concise.

from pygame.math import Vector2

class Enemy(pygame.sprite.Sprite):

    def __init__(self, pos):
        # ...
        self.pos = Vector2(pos)
        self.velocity = Vector2(2, 1)

    def update(self):
        self.pos += self.velocity
        self.rect.center = self.pos
skrx
  • 19,980
  • 5
  • 34
  • 48
  • I've never really used Vectors. Do I have to make Vector 2 a variable? – Simon Bye-Lock Jun 15 '18 at 14:07
  • `Vector2` is a class which you can import from the `pygame.math` module. You can also write `pygame.math.Vector2(2, 1)` to create a new vector instance. If you don't know how classes work, I recommend reading the chapters 12 and 13 of [Program Arcade Games](http://programarcadegames.com/index.php?chapter=introduction_to_classes&lang=en#section_12). If you want to learn more about vectors in general, you could check out [khanacademy.org](https://www.khanacademy.org/math/linear-algebra). – skrx Jun 15 '18 at 15:32