I am doing a python crash course exercise 14-2, I know drawing a single rectangle would be enough for this quiz but instead of "Create a rectangle at the right edge of the screen that moves up and down at a steady rate", I want to do some practice on Sprite so I created a series of rectangles on that right edge.
While the rectangles could be successfully generated in static, if I put my update codes into function, it seems all the rectangles are overlapped and falling like a single rectangle.
Here is the code:
#main.py
import pygame
from pygame.sprite import Group
import game_function as gf
from setting import Settings
from target import Target
def run_game():
pygame.init()
settings = Settings()
canvas = pygame.display.set_mode((settings.canvas_width,settings.canvas_height))
target = Target(canvas, settings)
targets = Group()
gf.create_targets(canvas,settings,targets)
while True:
gf.update_canvas(canvas,settings, targets)
gf.check_events()
targets.draw(canvas)
targets.update()
run_game()
#setting.py
class Settings():
def __init__(self):
self.canvas_width = 1200
self.canvas_height = 900
self.canvas_bg_color = (100,111,158)
self.target_width = 50
self.target_height = 80
self.target_color = (255, 0, 0)
self.target_move_speed = 0.5
#game_function.py
import sys
from random import randint
import pygame
from target import Target
def check_events():
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
pass
elif event.type == pygame.KEYUP:
pass
def update_canvas(canvas, settings, targets):
canvas.fill(settings.canvas_bg_color)
for target in targets.sprites():
target.target_draw()
pygame.display.flip()
def get_number_of_rows(canvas, settings):
target = Target(canvas, settings)
number_of_rows = int(settings.canvas_height / (2 * target.rect.height))
return number_of_rows
def create_a_target(canvas, row_number, settings, targets):
target = Target(canvas, settings)
target.rect.y = target.rect.height + 2 * target.rect.height * row_number
targets.add(target)
def create_targets(canvas,settings,targets):
number_of_rows = get_number_of_rows(canvas, settings)
for row_number in range(randint(1, number_of_rows)):
create_a_target(canvas,row_number,settings,targets)
print(len(targets)) # i put a len()here to ensure targets are successfully added to sprites.
#target.py
import pygame
from pygame.sprite import Sprite
class Target(Sprite):
def __init__(self, canvas, settings):
super(Target, self).__init__()
self.settings = settings
self.canvas = canvas
self.canvas_rect = canvas.get_rect()
self.image = pygame.Surface(
[self.settings.target_width, self.settings.target_height])
self.rect = self.image.get_rect()
self.rect.right = self.canvas_rect.right
self.rect.y = self.rect.height
self.y = float(self.rect.y)
def update(self):
#pass
self.y += (self.settings.target_move_speed)
#self.rect.y += (self.settings.target_move_speed)
self.rect.y = self.y
def target_draw(self):
pygame.draw.rect(self.canvas, self.settings.target_color, self.rect)
The target.py the tricky part and puzzles me.
If comment the contents in def update(): and leaves a pass there, the static canvas could be successfully generated(more than one rectangle), as the picture shows:
If I remove self.y = float(self.rect.centery) and self.rect.y = self.y and put
self.rect.y += (self.settings.target_move_speed) in def updates()
the blocks drops, only if the target_move_speed is an integer.
And finally, if I leave the codes as shown above, more than 1 rectangles (as indicated by print(len(targets))) drop but the rectangles are overlapped with each other, making them look like a single rectangle.
Can anyone point out what i am missing in my codes?
Thanks very much.