'Why is this code not making a grid of raindrops?
So, I need help with Pygame for Python 3.6. This is my first semester taking a programming class and, yeah, it's a homework assignment I need help with. I had the code working when my raindrops were static, but once I put movement in for some reason it only loads one row of them now. I need a grid of raindrops that move down the screen and loads a new row each time the bottom row disappears off the screen. And yes, there's probably an easier way than having all these modules, but that's how the book wants it done. Here's what I've got so far: raindropgame.py
import sys
import pygame
from pygame.sprite import Group
from settings import Settings
from raindrop import Raindrop
import game_functions as gf
def run_game():
# Initialize game and create a screen object.
pygame.init()
settings = Settings()
screen = pygame.display.set_mode((settings.screen_width,
settings.screen_height))
pygame.display.set_caption("13-3")
# Make raindrop group.
raindrops = Group()
# Create the raindrops.
gf.create_raindrops(settings, screen, raindrops)
# Start the main loop for the game.
while True:
gf.update_raindrops(raindrops)
gf.update_screen(settings, screen, raindrops)
# Watch for keyboard and mouse events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
run_game()
settings.py
class Settings():
"""A class to store all settings."""
def __init__(self):
"""Initialize the game's settings."""
# Screen settings
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (0, 0, 255)
# Raindrop settings
self.raindrop_speed_factor = 1
game_functions.py
import sys
import pygame
from raindrop import Raindrop
def update_screen(settings, screen, raindrops):
"""Update images on the screen and flip to the new screen."""
# Redraw the screen during each pass through the loop.
screen.fill(settings.bg_color)
raindrops.draw(screen)
# Make the most recently drawn screen visible.
pygame.display.flip()
def get_number_raindrops_x(settings, raindrop_width):
"""Determine the number of raindrops that fit in a row."""
available_space_x = settings.screen_width - 2 * raindrop_width
number_raindrops_x = int(available_space_x / (2 * raindrop_width))
return number_raindrops_x
def get_number_rows(settings, raindrop_height):
"""Determine the number of rows of raindrops that fit on the screen."""
available_space_y = settings.screen_height - (2 * raindrop_height)
number_rows = int(available_space_y / (2 * raindrop_height))
return number_rows
def create_raindrop(settings, screen, raindrops, raindrop_number, row_number):
"""Create a raindrop and place it in the row."""
raindrop = Raindrop(settings, screen)
raindrop_width = raindrop.rect.width
raindrop.x = raindrop_width + 2 * raindrop_width * raindrop_number
raindrop.rect.x = raindrop.x
raindrop.rect.y = raindrop.rect.height + 2 * raindrop.rect.height * row_number
raindrops.add(raindrop)
def create_raindrops(settings, screen, raindrops):
"""Create a full sky of raindrops."""
# Create a raindrop and find the number of raindrops in a row.
raindrop = Raindrop(settings, screen)
number_raindrops_x = get_number_raindrops_x(settings, raindrop.rect.width)
number_rows = get_number_rows(settings, raindrop.rect.height)
# Create the full sky of raindrops.
for row_number in range(number_rows):
for raindrop_number in range(number_raindrops_x):
create_raindrop(settings, screen, raindrops, raindrop_number, row_number)
def update_raindrops(raindrops):
"""Update the positions of all raindrops in sky."""
raindrops.update()
raindrop.py
import pygame
from pygame.sprite import Sprite
class Raindrop(Sprite):
"""A class to represent a single raindrop in the sky."""
def __init__(self, settings, screen):
"""Initialize the raindrop and set its starting position."""
super(Raindrop, self).__init__()
self.screen = screen
self.settings = settings
# Load the raindrop image and set its rect attribute.
self.image = pygame.image.load('images/raindrop.png')
self.rect = self.image.get_rect()
# Start each new raindrop near the top left of the screen.
self.rect.x = self.rect.width
self.rect.y = self.rect.height
self.y = float(self.rect.y)
def update(self):
"""Move raindrop down."""
self.y += self.settings.raindrop_speed_factor
self.rect.y = self.y
def blitme(self):
"""Draw the raindrop at its current location."""
self.screen.blit(self.image, self.rect)
Can anyone tell me what I've done wrong, and perhaps how to make it create a new row upon the bottom row leaving, 'cause I have no idea. :/
Solution 1:[1]
In create_raindrop()
, you need to change:
raindrop.rect.y = raindrop.rect.height + 2 * raindrop.rect.height * row_number
to:
raindrop.y = raindrop.rect.height + 2 * raindrop.rect.height * row_number
raindrop.rect.y = raindrop.y
Solution 2:[2]
In Raindrop.update()
you have to check position and change it.
If it leaves screen on the bottom
if self.rect.y >= self.setting.screen_height:
then you have to move it to the top
self.rect.y = 0
or
self.rect.top = 0
Or you can move event above top border
self.rect.bottom = 0
def update(self):
"""Move raindrop down."""
self.y += self.settings.raindrop_speed_factor
# if it leaves bottom border
if self.y >= self.settings.screen_height:
# then put above top border
self.y = -self.rect.height
self.rect.y = self.y
I would be good to create two rows above top row. At start they will be outside screen but when you move down then the they will fill top row before you move bottom row to the top.
# Create the full sky of raindrops.
for row_number in range(-2, number_rows):
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | gammazero |
Solution 2 |