0

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:

static picture

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.

the falling blocks. The arrow in this pic is the result of print(len(targets)),indicating there are 5 blocks

Can anyone point out what i am missing in my codes?

Thanks very much.

0 Answers0