I need to make my enemy sprites defined in drawGrid function move, I would like them to move to the edge of the grid (horizontally) and once reaching the end of the grid, they move down a certain amount and begin moving the opposite horizontal direction. (Like the aliens in space invaders.)
I have tried to move them to no avail.
import pygame
pygame.init()
window = pygame.display.set_mode((650, 630))
pygame.display.set_caption("PeaShooters")
avatar = pygame.image.load('Sprite 1 Red.png')
enemy1 = pygame.image.load('Sprite 3 Red.png')
enemy2 = pygame.image.load('Sprite 3 Yellow.png')
background = pygame.image.load('Bg.jpg')
white = (255, 255, 255)
class player(object):
def __init__(self, x, y, width, height, shots):
self.x = 300
self.y = 500
self.width = 40
self.height = 60
self.vel = shots
def drawGrid():
window.blit(background, (0,0))
window.blit(enemy1, (en.x, en.y))
window.blit(enemy1, (200, en.y))
window.blit(enemy1, (100, en.y))
window.blit(enemy1, (400, en.y))
window.blit(enemy1, (500, en.y))
window.blit(enemy1, (en.x, en.y))
window.blit(enemy2, (50, 200))
window.blit(enemy2, (150, 200))
window.blit(enemy2, (250, 200))
window.blit(enemy2, (350, 200))
window.blit(enemy2, (450, 200))
window.blit(enemy2, (530, 200))
window.blit(avatar, (av.x, av.y))
pygame.draw.line(window, white, [50,50], [50, 600], 5)
pygame.draw.line(window, white, [50,50], [600, 50], 5)
pygame.draw.line(window, white, [600,600], [600, 50], 5)
pygame.draw.line(window, white, [50,600], [600, 600], 5)
pygame.draw.line(window, white, [50,450], [600, 450], 5)
for bullet in bullets:
bullet.draw(window)
pygame.display.update()
class shots(object):
def __init__(self, x, y, radius, colour):
self.x = x
self.y = y
self.radius = radius
self.colour = colour
self.vel = shots
def draw(self, window):
pygame.draw.circle(window, self.colour, (self.x,self.y), self.radius)
class enemy(object):
def __init__(self, x, y, width, height, end):
self.x = x
self.y = y
self.width = width
self.height = height
self.end = end
self.path = [self. x, self.end]
self.vel = 4
def draw(self,window):
self.move()
def move(self):
pass
av = player(300, 500, 40, 60, 9)
en = enemy(300, 100, 40, 60, 500)
bullets = []
running = True
while running:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
for bullet in bullets:
if bullet.y < 600 and bullet.y > 70:
bullet.y -= 8
else:
bullets.pop(bullets.index(bullet))
keys = pygame.key.get_pressed()
if keys[pygame.K_w] and av.y > 440:
av.y -= av.vel
if keys[pygame.K_a] and av.x > 65:
av.x -= av.vel
if keys[pygame.K_s] and av.y < 535:
av.y += av.vel
if keys[pygame.K_d] and av.x < 530:
av.x += av.vel
if keys[pygame.K_SPACE]:
if len(bullets) < 5:
bullets.append(shots(round(av.x + av.width//2), round(av.y + av.height//2), 6, (0,0,0)))
drawGrid()
window.blit(enemy, (en.x, en.y))
window.blit(avatar, (x,y))
pygame.quit()
I expect the enemies to move, in the way I have described but they do not move at all.
Here are a few things I would do to get yourself closer to the game you are looking for:
Right now you create 1 enemy here: en = enemy(300, 100, 40, 60, 500)
and just throw enemy images at the screen in a bunch of places. To really make use of the Enemy
class, I would do something like this:
enemiesList = []
for i in range (MAX_ENEMIES_I_WANT):
enemiesList.append(enemy(300, 100*i, 40, 60, 500))
Note: you will need to define where you place your enemies differently if you want them to fall into a certain shape. For the traditional space invaders you can loop twice, once for y coordinates, once for x.
Instead of doing things the way you have them now, I would add a blitToScreen()
method in your Enemy class. Something like:
def BlitToScreen(self,screen):
screen.blit(self.sprite, self.x, self.y)
Then, blitting all of your enemies to screen becomes two lines:
for e in enemiesList:
e.BlitToScreen(window)
If you have a frame
number it will look something like this:
tomove = [0,0]
if(frame%100 == 99):
tomove[0] += 50 # Move down
else if(frame/100%2 == 0):
tomove[1] +=50 # Move right
else:
tomove[1] -=50 # Move left
for e in enemies:
e.x += tomove[0]
e.y += tomove[1]
Hopefully this is helpful for you!
@Hoog's answer mostly covers the basics of what's wrong with the OP's code, and how to get it working.
However the OP really should consider using the PyGame sprite class for each "enemy" object (well, all objects actually). Yes , it's a bit more work to setup initially, but it provides so much extra (pre-optimised) functionality that you would otherwise have to code. This takes some of the tedious work out of the programming, and allows you to spend more time coding up an interesting game.
It's fairly trivial to convert the existing objects to Sprites:
class Enemy( pygame.sprite.Sprite ):
def __init__( self, bitmap, x, y, end=None ):
pygame.sprite.Sprite.__init__( self )
self.image = bitmap
self.rect = bitmap.get_rect()
self.rect.x = x
self.rect.y = y
self.vel = 4
self.end = end
def update():
# TODO - handle any sort of sprite movement
Create a bunch of sprites, as per @Hoog's suggestion, except use a Sprite Group to hold them:
enemy_image1 = pygame.image.load('Sprite 3 Red.png')
enemy_image2 = pygame.image.load('Sprite 3 Yellow.png')
...
enemies_list = pygame.sprite.Group()
for j in range( ENEMY_LINE_COUNT ):
for i in range( ENEMY_PER_LINE_COUNT ):
enemy_x = 50 + ( i * 30 )
enemy_y = 50 + ( j * 40 )
enemies_list.append( Enemy( enemy_image1, enemy_x, enemy_y ) )
The Moving and Drawing can then be handled easily in your main loop, using the abilities (and ease) of the Sprite Group:
while running:
...
enemies_list.update() # re-position the sprites
enemies_list.draw( window ) # draw the entire sprite-group to the window
...
The Sprite Group .update()
call (in the main loop) will call the Enemy.update()
function for every sprite contained in the group.
This brings us to the movement part of your question. Let's think about how Space Invaders move - Right to Left, Down, Left to Right, Down, More Speed, repeat ... This kind of sounds like a program to me ;)
So I propose to control movement, write a program that each invader follows:
# In Enemy.__init__() ~
self.move_program = 'rrrrrrrrrrrrrdllllllllllllds' #TODO - make better
self.move_cursor = 0
Where each letter of the self.move_program
effects the movement at each 'tick'. This leads us to the sprite's .update()
function:
# In Enemy class ~
def update( self ):
move_instruction = self.move_program[ self.move_cursor ]
self.move_cursor += 1
# If the movement program has ended, restart
if ( self.move_cursor == len( self.move_program ) ):
self.move_cursor = 0
# Interpret the movement instruction
if ( instruction == 'r' ): # right
self.rect.x = self.rect.x + 10
elif ( instruction == 'l' ): # left
self.rect.x = self.rect.x - 10
elif ( instruction == 'd' ): # down
self.rect.y = self.rect.y + 10
elif ( instruction == 's' ): # speedup
self.vel += 1
Obviously you can have any sort of instructions you like. Different sets of instructions could be given to different sprites as part of the constructor.
Putting the game projectiles and player(s) into sprites will allow the code to easily find collisions, etc. but that's another answer.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.