The code works fine when you first load the game the two rectangles are there but when the player moves, the enemy rectangle disappears.
EXTENSION I am trying to get the enemy class to move up and down constantly without any keys needed to be pressed.
import pygame
import os
import random
from pygame.locals import * # Constants
import math
import sys
import random
pygame.init()
screen=pygame.display.set_mode((1280,720)) #(length,height)
screen_rect=screen.get_rect()
background = pygame.Surface(screen.get_size())
background = pygame.image.load('stage.png').convert()
screen.blit(background, (0, 0))
class Player(pygame.sprite.Sprite):
def __init__(self):
self.rect = pygame.draw.rect(screen, (0,0,128), (50,560,50,25)) #(colour)(x-position,y-position,width,height)
self.dist = 100
def draw_rect(self,x,y): # This is my code which should make the player move
screen.blit(background, (0, 0)) #If this isn't included then when the rectangle moves it's old positon will still be on the screen
self.rect = self.rect.move(x*self.dist, y*self.dist); pygame.draw.rect(screen, (0, 0, 128), self.rect)
pygame.display.update()
def handle_keys(self): # code to make the character move when the arrow keys are pressed
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
self.draw_rect(-0.05,0)
elif keys[K_RIGHT]:
self.draw_rect(0.05,0)
elif keys[K_UP]:
self.draw_rect(0,-0.05)
elif keys[K_DOWN]:
self.draw_rect(0,0.05)
elif keys[K_SPACE]:
self.draw_rect(0.05,-0.05)
if self.rect.right > 1280:
self.rect.right = 1280
if self.rect.left < 0:
self.rect.left = 0
if self.rect.bottom > 720:
self.rect.bottom = 720
if self.rect.top < 0:
self.rect.top = 0
class Enemy(pygame.sprite.Sprite): # the enemy class which works fine
def __init__(self):
x = random.randint(50,450)
self.rect = pygame.draw.rect(screen, (128,0,0), (300,x,50,25))
player = Player()
enemy = Enemy()
def main(): #my main loop
running = True
while running:
player.handle_keys()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.flip() #updates the whole screen
if __name__ == '__main__': main()
you are only drawing the sprites when the class is instatiated in the __init__()
you need to be drawing them every loop in the main()function right before pygame.display.flip()
as things are right now, neither the player nor the enemy should display beyond the first frame
You have to clear the screen every frame - you can do this by blitting the background - and draw the sprites afterwards. Separate the movement from the drawing code so that you can blit the sprites after the screen has been cleared.
class Player(pygame.sprite.Sprite):
def __init__(self):
self.rect = pygame.draw.rect(screen, (0,0,128), (50,560,50,25))
self.dist = 100
# Separate the movement and the drawing.
def move(self, x, y):
self.rect = self.rect.move(x*self.dist, y*self.dist)
def draw(self, screen):
pygame.draw.rect(screen, (0, 0, 128), self.rect)
def handle_keys(self):
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
self.move(-0.05,0)
elif keys[K_RIGHT]:
self.move(0.05,0)
elif keys[K_UP]:
self.move(0,-0.05)
elif keys[K_DOWN]:
self.move(0,0.05)
elif keys[K_SPACE]:
self.move(0.05,-0.05)
if self.rect.right > 1280:
self.rect.right = 1280
if self.rect.left < 0:
self.rect.left = 0
if self.rect.bottom > 720:
self.rect.bottom = 720
if self.rect.top < 0:
self.rect.top = 0
class Enemy(pygame.sprite.Sprite):
def __init__(self):
self.x = random.randint(50,450) # x is now an attribute.
def draw(self, screen):
self.rect = pygame.draw.rect(screen, (128,0,0), (300, self.x, 50, 25))
def main():
clock = pygame.time.Clock() # A clock to limit the frame rate.
player = Player()
enemy = Enemy()
running = True
while running:
player.handle_keys()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Clear the screen every frame by blitting the background.
screen.blit(background, (0, 0))
# Then draw the enemy and the player.
enemy.draw(screen)
player.draw(screen)
pygame.display.flip()
clock.tick(60) # Limit the frame rate to 60 FPS.
I also recommend checking out how sprite groups work, then you can get rid of the draw methods and can just call sprite_group.draw(screen) to draw every contained sprite. Here's a tutorial.
Related
Im new to python and im currently making a simple pygame but I can not grasp the concept of sprites. I want to replace the moving block with a player icon that I created.
Do I need to make a group just for one object or is there a way just to add the player without any groups?
from pygame import sprite
import pygame, sys
from pygame.locals import*
from pynput.keyboard import Key, Controller
class Player(pygame.sprite.Sprite):
def __init__(self, picture_path):
super().__init__()
self.image = pygame.image.load(picture_path)
self.rect = self.image.get_rect()
def main():
pygame.init()
DISPLAY=pygame.display.set_mode((1280,720),0,32)
pygame.display.set_caption('Der Sammler')
WHITE=(255,255,255)
BLUE=(0,0,255)
DISPLAY.fill(WHITE)
x = 0
y = 0
velocity1 = 0
acceleration = 0.1
velocity = pygame.Vector2()
velocity.xy = 3, 0
player = Player("player.png")
while True:
pygame.draw.rect(DISPLAY, BLUE, (x,y,50,50))
x += velocity.x
if x+ 50 > DISPLAY.get_width():
velocity.x = -3
if x < 0:
velocity.x = 3
pressed_keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
DISPLAY.fill((255, 255, 255))
pygame.draw.rect(DISPLAY,BLUE, (x,y, 50, 50))
y += velocity1
velocity1 += acceleration
if pressed_keys[pygame.K_SPACE]:
velocity1 = -3
pygame.display.update()
pygame.time.delay(10)
main()
Add an update method to Player and put the movement and gravity algorithm in that method:
class Player(pygame.sprite.Sprite):
def __init__(self, picture_path):
super().__init__()
self.image = pygame.image.load(picture_path)
self.rect = self.image.get_rect()
self.velocity = pygame.Vector2(3, 0)
self.acceleration = 0.1
def update(self, dispaly):
pressed_keys = pygame.key.get_pressed()
self.rect.x += self.velocity.x
if self.rect.right >= dispaly.get_width():
self.velocity.x = -3
if self.rect.left < 0:
self.velocity.x = 3
self.rect.y += self.velocity.y
self.velocity.y += self.acceleration
if pressed_keys[pygame.K_SPACE]:
self.velocity.y = -3
Add the player to a pygame.sprite.Group:
sprites = pygame.sprite.Group(player)
Call sprites.update() and sprites.draw() in the application loop to update the position of the player and to move the player:
while True:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
sprites.update(DISPLAY)
DISPLAY.fill((255, 255, 255))
sprites.draw(DISPLAY)
pygame.display.update()
Also see How can I add objects to a "pygame.sprite.Group()"?.
Complete example:
import pygame, sys
from pygame.locals import*
class Player(pygame.sprite.Sprite):
def __init__(self, picture_path):
super().__init__()
self.image = pygame.image.load(picture_path)
self.rect = self.image.get_rect()
self.velocity = pygame.Vector2(3, 0)
self.acceleration = 0.1
def update(self, dispaly):
pressed_keys = pygame.key.get_pressed()
self.rect.x += self.velocity.x
if self.rect.right >= dispaly.get_width():
self.velocity.x = -3
if self.rect.left < 0:
self.velocity.x = 3
self.rect.y += self.velocity.y
self.velocity.y += self.acceleration
if pressed_keys[pygame.K_SPACE]:
self.velocity.y = -3
if self.rect.bottom > dispaly.get_height():
self.rect.bottom = dispaly.get_height()
self.velocity.y = 0
def main():
pygame.init()
DISPLAY=pygame.display.set_mode((1280,720),0,32)
pygame.display.set_caption('Der Sammler')
clock = pygame.time.Clock()
WHITE=(255,255,255)
BLUE=(0,0,255)
DISPLAY.fill(WHITE)
player = Player("player.png")
sprites = pygame.sprite.Group(player)
while True:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
sprites.update(DISPLAY)
DISPLAY.fill((255, 255, 255))
sprites.draw(DISPLAY)
pygame.display.update()
clock.tick(100)
main()
IDK why my player.move() is not working here's my main class:
import pygame
from player import *
pygame.init()
WIDTH, HEIGHT = 900, 600
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("MyGame!")
FPS = 60
player_x = 500
player_y = 500
PLAYER_WIDTH = 60
PLAYER_HEIGHT = 60
PLAYER_VEL = 5
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
keys_pressed = pygame.key.get_pressed()
player_rect = pygame.Rect(player_x, player_y, PLAYER_WIDTH, PLAYER_HEIGHT)
player = Player(player_rect, BLACK, WIN, keys_pressed, PLAYER_VEL)
def draw_window():
WIN.fill(WHITE)
pygame.display.update()
def main():
run = True
clock = pygame.time.Clock()
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
draw_window()
player.move()
player.draw_player()
pygame.display.update()
pygame.quit()
if __name__ == '__main__':
main()
and here's my other class called player.py that the move function is not working:
import pygame
class Player(object):
def __init__(self, player, color, surface, keys_pressed, vel):
self.player = player
self.color = color
self.surface = surface
self.keys_pressed = keys_pressed
self.vel = vel
def draw_player(self):
pygame.draw.rect(self.surface, self.color, self.player)
pygame.display.update()
def move(self):
if self.keys_pressed[pygame.K_a]:
self.player.x -= self.vel
if self.keys_pressed[pygame.K_d]:
self.player.x += self.vel
I tried putting the player = Player(...) before the main function.
But whatever I tried, it doesn't seem to work and this is my first time posting a question on stackoverflow. This problem also happened alot in the past so thanks if you helped me out.
pygame.key.get_pressed() returns a sequence with the state of each key. If a key is held down, the state for the key is 1, otherwise 0. The contents of the keys_pressed list don't magically change when the state of the keys changes. keys_pressed is not tied to the keys. You need to get the new state of the keys in every frame:
class Player(object):
# [...]
def move(self):
# get current state of the keys
self.keys_pressed = pygame.key.get_pressed()
if self.keys_pressed[pygame.K_a]:
self.player.x -= self.vel
if self.keys_pressed[pygame.K_d]:
self.player.x += self.vel
When the game first starts both the player and the enemy appear but when the player moves the enemy disappears.
import pygame
import os
import random
from pygame.locals import * # Constants
import math
import sys
import random
pygame.init()
screen=pygame.display.set_mode((1280,720)) #(length,height)
screen_rect=screen.get_rect()
background = pygame.Surface(screen.get_size())
background.fill((255,255,255)) # fill the background white
White = (255,255,255)
screen.blit(background, (0, 0))
class Player(pygame.sprite.Sprite):
def __init__(self):
self.rect = pygame.draw.rect(screen, (0,0,128), (50,560,50,25)) #(colour)(x-position,y-position,width,height)
self.dist = 100
def draw_rect(self,x,y): # This is my code which should make the player move
screen.blit(background, (0, 0)) #If this isn't included then when the rectangle moves it's old positon will still be on the screen
self.rect = self.rect.move(x*self.dist, y*self.dist); pygame.draw.rect(screen, (0, 0, 128), self.rect)
pygame.display.update()
def handle_keys(self): # code to make the character move when the arrow keys are pressed
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
self.draw_rect(-0.05,0)
elif keys[K_RIGHT]:
self.draw_rect(0.05,0)
elif keys[K_UP]:
self.draw_rect(0,-0.05)
elif keys[K_DOWN]:
self.draw_rect(0,0.05)
elif keys[K_SPACE]:
self.draw_rect(0.4,-0.9)
if self.rect.right > 1280: # These are to stop the player from going out of the boundary
self.rect.right = 1280
if self.rect.left < 0:
self.rect.left = 0
if self.rect.bottom > 720:
self.rect.bottom = 720
if self.rect.top < 0:
self.rect.top = 0
The movement of the player works perfectly fine.
class Enemy(pygame.sprite.Sprite): # the enemy class which works fine
def __init__(self):
x = random.randint(50,450)
self.rect = pygame.draw.rect(screen, (128,0,0), (300,x,50,25))
The enemy just spawns at a random place and should still appear when the player moves around. I tried to do something but it didn't work.
clock = pygame.time.Clock() # A clock to limit the frame rate.
player = Player()
enemy = Enemy()
def main(): #my main loop
running = True
while running:
player.handle_keys()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
clock.tick(60) # Limit the frame rate to 60 FPS.
pygame.display.flip() #updates the whole screen
if __name__ == '__main__': main()
It's because you draw the Rect of the enemy only once: in the __init__ function of Enemy. Also, you do a lot of drawing in different places of the Player class, like clearing the screen. Stop doing that.
You already subclass Sprite, so use this class as intended. Sprites have an image and rect that defines how they look like and where they are, and you add them to a Group that takes care of calling their update function and drawing them to the screen.
Your code should look like this:
import pygame
import random
from pygame.locals import * # Constants
pygame.init()
screen=pygame.display.set_mode((1280,720)) #(length,height)
screen_rect=screen.get_rect()
background = pygame.Surface(screen.get_size())
background.fill((255,255,255)) # fill the background white
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50,25))
self.image.fill((0,0,128))
self.rect = self.image.get_rect(topleft=(50,560))
self.dist = 100
def update(self): # code to make the character move when the arrow keys are pressed
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
self.rect.move_ip(-1,0)
elif keys[K_RIGHT]:
self.rect.move_ip(1,0)
elif keys[K_UP]:
self.rect.move_ip(0,-1)
elif keys[K_DOWN]:
self.rect.move_ip(0,1)
self.rect.clamp_ip(screen_rect)
class Enemy(pygame.sprite.Sprite): # the enemy class which works fine
def __init__(self):
super().__init__()
x = random.randint(50,450)
self.image = pygame.Surface((50,25))
self.image.fill((128,0,0))
self.rect = self.image.get_rect(topleft=(300, x))
clock = pygame.time.Clock() # A clock to limit the frame rate.
player = Player()
enemy = Enemy()
sprites = pygame.sprite.Group(player, enemy)
def main(): #my main loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
sprites.update()
screen.blit(background, (0, 0))
sprites.draw(screen)
clock.tick(60) # Limit the frame rate to 60 FPS.
pygame.display.flip() #updates the whole screen
if __name__ == '__main__':
main()
I am building a football game (american) that has a Player class move an image by the keyboard in one program:
import pygame
import os
import random
black = (0,0,0)
white = (255,255,255)
red = (255, 0, 0)
green = (0, 100, 0)
# This class represents the bar at the bottom that the player controls
class Player(object):
def __init__(self):
self.image = pygame.image.load("player_one.png").convert()
self.image.set_colorkey(white)
self.width = 15
self.height = 15
self.x = 940
self.y = 240
def handle_keys(self):
key = pygame.key.get_pressed()
if key[pygame.K_DOWN]:
if self.y < 470:
self.y += self.height
elif key[pygame.K_UP]:
if self.y > 0:
self.y -= self.height
if key[pygame.K_RIGHT]:
if self.x < 940:
self.x += self.width
elif key[pygame.K_LEFT]:
if self.x > 0:
self.x -= self.width
def draw(self, surface):
surface.blit(self.image, (self.x, self.y))
pygame.init()
screen = pygame.display.set_mode((1000, 500))
player = Player()
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
player.handle_keys()
screen.fill(green)
for x in range(60,940,35):
pygame.draw.line(screen, white, [x, 0], [x, 500], 1)
player.draw(screen)
pygame.display.update()
clock.tick(20)
And another program that displays the enemy randomly on a background image when any key is pressed they change position:
import random
import pygame
WHITE = (255,255,255)
BLACK = (0 ,0 ,0 )
#----------------------------------------------------------------------
class Enemy():
def __init__(self, image, x=0, y=0):
self.image = pygame.image.load(image).convert()
self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
#------------
def draw(self, screen):
screen.blit(self.image, self.rect)
#------------
def update(self):
# here change randomly positon
self.rect.topleft = random.randint(60,220+1), random.randint( 0, 475+1)
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((1400,500))
self.background = pygame.image.load("GameField1.png").convert()
self.multi_enemies = []
self.players = []
# create 3 enemies 0...2
for i in range(0,3):
enemy = Enemy("enemy_"+str(i)+".png")
enemy.update() # set random position on start
self.multi_enemies.append(enemy)
#------------
def run(self):
clock = pygame.time.Clock()
RUNNING = True
while RUNNING:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
# changes position when key is pressed
for enemy in self.multi_enemies:
enemy.update()
for player in self.players:
player.handle_keys()
# --- updates ----
# place for updates
# --- draws ---
self.screen.fill(BLACK)
self.screen.blit(self.background, self.background.get_rect())
for enemy in self.multi_enemies:
enemy.draw(self.screen)
pygame.display.update()
pygame.display.flip()
# --- FPS ---
clock.tick(20)
# --- quit ---
pygame.quit()
#----------------------------------------------------------------------
Game().run()
First - Thank you for the people who helped me get this far. Second - I need to combine the Player class to the second program. I need to add collision detection so that if the player makes it to the left end zone his Score increases +7 and he goes back to the start. Also, if the player runs into an Enemy then he goes back to the start. I want the game to be on a 2 min timer so the goal is to score as much within the timeframe before the game ends.
I know a lot of people are going to recommend Sprites and I expect that but could you please provide code/explanation. Attached are my images.
I split code into 3 files Player.py, Enemy.py and Game.py
Player.py
I add restart() to set start position at new game and game restart
In handle_event I use event (to check keys) so I could check mouse events and other events if I have to - it is more universal.
handle_event return True/False if player was moved or not.
.
import pygame
#----------------------------------------------------------------------
class Player(object):
def __init__(self, surface_rect):
self.surface_rect = surface_rect
self.image = pygame.image.load("player_one.png").convert()
self.image.set_colorkey( (255,255,255) )
self.rect = self.image.get_rect() # you get image width, height
self.move_x = 15
self.move_y = 15
self.restart()
#------------
def restart(self):
self.rect.x = 940
self.rect.y = 240
#------------
def handle_events(self, event):
player_moves = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
if self.rect.bottom < self.surface_rect.bottom: #470
self.rect.y += self.move_y
player_moves = True
elif event.key == pygame.K_UP:
if self.rect.top > self.surface_rect.top:
self.rect.y -= self.move_y
player_moves = True
elif event.key == pygame.K_RIGHT:
if self.rect.right < self.surface_rect.right:
self.rect.x += self.move_x
player_moves = True
elif event.key == pygame.K_LEFT:
if self.rect.left > self.surface_rect.left:
self.rect.x -= self.move_x
player_moves = True
print "(debug): player: x, y:", self.rect.x, self.rect.y
return player_moves
#------------
def draw(self, surface):
surface.blit(self.image, self.rect)
#----------------------------------------------------------------------
Enemy.py
nothing is changed
import pygame
import random
#----------------------------------------------------------------------
class Enemy():
def __init__(self, image, x=0, y=0):
self.image = pygame.image.load(image).convert()
self.image.set_colorkey( (255,255,255) )
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
#------------
def draw(self, screen):
screen.blit(self.image, self.rect)
#------------
def update(self):
# here change randomly positon
self.rect.topleft = random.randint(60, 220+1), random.randint(0, 475+1)
#----------------------------------------------------------------------
Game.py
best part :) try to figure out what is going on in code ;)
collision detect - it could be use pygame.sprite.Sprite, pygame.sprite.Group, etc.
score for player and enemies
time counting
game over - backspace restart game after game over
.
import random
import pygame
from Player import *
from Enemy import *
WHITE = (255,255,255)
BLACK = (0 ,0 ,0 )
RED = (255,0 ,0 )
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((1400,500))
self.background = pygame.image.load("GameField1.png").convert()
self.enemies = []
#self.players = []
self.player = Player(self.screen.get_rect())
# create 3 enemies 0...2
for i in range(3):
enemy = Enemy("enemy_"+str(i)+".png")
enemy.update() # set random position on start
self.enemies.append(enemy)
self.font = pygame.font.SysFont("", 32)
self.gameover_text = self.font.render("GAME OVER", -1, RED)
self.gameover_rect = self.gameover_text.get_rect(center=self.screen.get_rect().center)
self.restart()
#------------
def restart(self):
self.player_score = 0
self.enemies_score = 0
#self.play_time = 2*60 # 2minutes * 60 seconds
self.play_time = 30 # 30 seconds for fast test
self.change_time = pygame.time.get_ticks() + 1000 # 1s
self.player.restart()
#------------
def update_time(self):
print "(debug): time:", self.change_time, pygame.time.get_ticks()
if pygame.time.get_ticks() >= self.change_time:
self.change_time += 1000 # 1s
self.play_time -= 1
return self.play_time <= 0 # GAME OVER ?
#------------
def draw_score(self, surface):
surface_rect = surface.get_rect()
self.player_score_text = self.font.render(str(self.player_score) + " :Player", -1, WHITE)
self.player_score_rect = self.player_score_text.get_rect(right=surface_rect.right-10, top=10)
surface.blit(self.player_score_text, self.player_score_rect)
self.enemies_score_text = self.font.render("Enemy: " + str(self.enemies_score), -1, WHITE)
self.enemies_score_rect = self.enemies_score_text.get_rect(left=surface_rect.left+10, top=10)
surface.blit(self.enemies_score_text, self.enemies_score_rect)
print "(debug): render scores:", self.player_score, self.player_score_rect, self.enemies_score, self.enemies_score_rect
#------------
def draw_time(self, surface):
surface_rect = surface.get_rect()
time_str = "%02d:%02d" % (self.play_time/60, self.play_time%60)
self.time_text = self.font.render(time_str, -1, RED )
self.time_rect = self.time_text.get_rect(centerx=surface_rect.centerx, top=10)
surface.blit(self.time_text, self.time_rect)
print "(debug): render time:", self.play_time, self.time_rect, (self.play_time/60, self.play_time%60), time_str
#------------
def run(self):
clock = pygame.time.Clock()
RUNNING = True
GAME_OVER = False
while RUNNING:
# --- events ---
PLAYER_MOVES = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
if event.key == pygame.K_BACKSPACE:
if GAME_OVER:
GAME_OVER = False
self.restart()
# player moves
if not GAME_OVER:
PLAYER_MOVES = self.player.handle_events(event)
# --- updates ----
if PLAYER_MOVES and not GAME_OVER:
# changes position when key is pressed
for enemy in self.enemies:
enemy.update()
# check collisions
collision = False
for enemy in self.enemies:
if pygame.sprite.collide_rect(self.player, enemy):
collision = True
break # first collision and I don't check rest enemies
if collision:
self.enemies_score += 7
print "(debug): game: collision:", self.player_score, self.enemies_score
self.player.restart()
# check touchdown
if self.player.rect.left <= 100:
self.player_score += 7
print "(debug): game: touchdown:", self.player_score, self.enemies_score
self.player.restart()
if not GAME_OVER:
GAME_OVER = self.update_time()
# --- draws ---
self.screen.fill(BLACK)
self.screen.blit(self.background, self.background.get_rect())
self.player.draw(self.screen)
for enemy in self.enemies:
enemy.draw(self.screen)
self.draw_time(self.screen)
self.draw_score(self.screen)
if GAME_OVER:
self.screen.blit(self.gameover_text, self.gameover_rect)
pygame.display.update()
# --- FPS ---
clock.tick(20)
#----------------------------------------------------------------------
Game().run()
I'm a little confused as to what you are asking, I hope this will answer all your questions:
First of all wouldn't the enemies "teleport" to random locations each time they update? I'm not sure what you are trying to achieve but it should be better if you randomize their location on init (where you set their x and y to 0 ) and on the update you should create some Artificial Intelligence (like following the hero? )
class Enemy():
def __init__(self, image):
self.image = pygame.image.load(image).convert()
self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = random.randint(60,220+1)
self.rect.centery = random.randint( 0, 475+1)
#------------
def draw(self, screen):
screen.blit(self.image, self.rect)
#------------
def update(self, heroX, heroY):
#Make enemies follow hero (for example)
if heroX > self.rect.centerx
self.rect.centerx += 10; #10 is example value, set the one you like!
else if heroX < self.rect.centerx
self.rect.centerx -= 10;
#Do the same for y
#------------
def reset(self): #This is called when hero scores, or enemies touch hero (and you want to reset hero to starting point and enemies)
self.rect.centerx = random.randint(60,220+1)
self.rect.centery = random.randint( 0, 475+1)
Just make sure to pass player's x and y when you update the enemy.
About collision, there is a simple algorithm that goes like that: If you have objectA and objectB they only collide if objectA.right > objectB.left && objectA.left < objectB.right , combine top and bottoms the same way and you are done
if (player.right > enemy.left && player.left < enemy.right && player.bottom > enemy.top && player.top < enemy.bottom)
player.reset()
enemy.reset()
apply this algorithm once for each enemy (and hero, if there are more than one)
About the timer, you already have a timer to limit frames, you can use that to count seconds inside the game and create limits (use your imagination!)
I would recommend sprites! I'm not going to tell you everything because figuring game programming out is half the fun!
First of all, you could set pygame groups up, like
player_list = pygame.sprite.Group()
player_list.add(player)
for player and enemy, and test a collision between them both using pygame.sprite.spritecollide and maybe something similar for your left zone of the pitch..
Then as furas mentioned, just copy or import player class. :)
Also, I would suggest pygame.time.get_ticks() for your timer, although you can do it other ways..
The rest is down to you! I hope this helped in some way, ask any questions if you don't understand!
I have done this on a phone so if someone wants to edit it for all the codey bits that'd be great :)
I am working on a game in pygame, so far the player can walk around, 50 blue blocks spawn randomly on the screen and the player can walk around and shoot them, but there is one problem the player can only shoot up, I want the player to shoot towards the mouse but am having some trouble getting it to do this.
this is my code
import pygame
from pygame import *
import random
black = ( 0, 0, 0)
white = ( 255, 255, 255)
red = ( 255, 0, 0)
blue = ( 0, 0, 255)
player_x, player_y = 0, 0
move_player_x, move_player_y = 0, 0
class Block(pygame.sprite.Sprite):
def __init__(self, color):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20, 15])
self.image.fill(color)
self.rect = self.image.get_rect()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([20,20])
self.image.fill(red)
self.rect = self.image.get_rect()
def update(self):
pos = pygame.mouse.get_pos()
self.rect.x = player_x
self.rect.y = player_y
class Bullet(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([4, 10])
self.image.fill(black)
self.rect = self.image.get_rect()
def update(self):
self.rect.y -= 5
pygame.init()
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width,screen_height])
all_sprites_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
for i in range(50):
block = Block(blue)
block.rect.x = random.randrange(screen_width)
block.rect.y = random.randrange(350)
block_list.add(block)
all_sprites_list.add(block)
player = Player()
all_sprites_list.add(player)
done = False
clock = pygame.time.Clock()
score = 0
player.rect.y = 370
# -------- Main Program Loop -----------
while not done:
# --- Event Processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
if event.type== pygame.KEYDOWN:
if event.key==K_a:
move_player_x=-1
elif event.key==K_d:
move_player_x=+1
elif event.key==K_w:
move_player_y=-1
elif event.key==K_s:
move_player_y=+1
if event.type== pygame.KEYUP:
if event.key==K_a:
move_player_x=0
elif event.key==K_d:
move_player_x=0
elif event.key==K_w:
move_player_y=0
elif event.key==K_s:
move_player_y=0
# --- Game logic
all_sprites_list.update()
player_x += move_player_x
player_y += move_player_y
for bullet in bullet_list:
block_hit_list = pygame.sprite.spritecollide(bullet, block_list, True)
for block in block_hit_list:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
score += 1
print( score )
if bullet.rect.y < -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
screen.fill(white)
all_sprites_list.draw(screen)
pygame.display.flip()
clock.tick(20)
pygame.quit()
so there the code, any help is much appreciated
here is what i came up with, I changed some code from an RPG me and a friend are making
Change your bullet class code to this:
class Bullet(pygame.sprite.Sprite):
def __init__(self, mouse, player):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([4, 10])
self.image.fill(black)
self.mouse_x, self.mouse_y = mouse[0], mouse[1]
self.player = player
self.rect = self.image.get_rect()
def update(self):
speed = 4.
range = 200
distance = [self.mouse_x - self.player[0], self.mouse_y - self.player[1]]
norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
direction = [distance[0] / norm, distance[1 ] / norm]
bullet_vector = [direction[0] * speed, direction[1] * speed]
self.rect.x -= bullet_vector[0]
self.rect.y -= bullet_vector[1]
now it takes the players pos and the mouse click pos as arguments for the class
the math is a bit confusing but it basically take the vector from the two points and gets a direction and sends the bullet that way
when you create a new bullet instance call it like this:
bullet = Bullet(pygame.mouse.get_pos(), [player.rect.x, player.rect.y])
that way the class gets the two points when the mouse button is clicked!
when you run it you may notice that the bullet goes in the opposite direction of the mouse click thought that would add some challenge. You can change it if you need
P.S. the speed variable can be adjusted! Oh, and the math module needs to be imported