I'll eventually need to add collisions and gamification, but right now I'm having trouble just getting it set up.
I had a previous mess of a thread about it where I just rambled to myself:
viewtopic.php?f=8&t=66363&sid=a078c6ea3 ... 5fd5c927f3
I'm going to close that thread to simplify things to this thread with just one question:
how do I get this game loop working? My mess of code was refactored by a kind redditor, but I still needed to get the update and draw methods working, and I haven't had any luck so far. The window just immediately closes, so there's something wrong with my game loop.
So, here's where my code currently stands:
SnowlyRoller.py:
Code: Select all
import pygame
import spritesheet
import itertools
from pygame.locals import (
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
)
class Game:
def __init__(self) -> None:
self.window_surface = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Snowly Roller")
self.x = 500.0
self.y = 500.0
self.fps = 60
self.clock = pygame.time.Clock()
self.init_time = pygame.time.get_ticks()
self.player = spritesheet.Player()
self.snowball = spritesheet.Snowball()
self.terrain = spritesheet.Terrain()
self.grass = pygame.image.load('images/Grass.png')
self.g = Game()
def setup_background(self):
self.window_surface.blit(self.terrain.land_list[self.terrain.landframe], (162, 90))
brick_width, brick_height = self.terrain.land_list[self.terrain.landframe].get_width(), self.terrain.land_list[self.terrain.landframe].get_height()
for self.x,self.y in itertools.product(range(0,1920+1,brick_width), range(0,1080+1,brick_height)):
self.window_surface.blit(self.terrain.land_list[self.terrain.landframe], (self.x, self.y))
return
def run(self):
running = True
while running:
# # drawing stuff
# self.window_surface.blit(self.grass, (0, 0))
# self.setup_background()
# self.window_surface.blit(self.player.animation_list[self.player.action][self.player.frame], (self.x, y))
# self.window_surface.blit(self.snowball.snow_list[self.snowball.frame], (self.x + self.snowball.x, y + self.snowball.y))
# handling events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP or event.key == pygame.K_DOWN:
self.player.is_moving = False
self.player.frame = 0
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
if event.key == K_UP:
self.player.action = 1
self.player.frame = 0
self.snowball.x = 17
self.snowball.y = -12
if event.key == K_LEFT:
self.player.action = 2
self.player.frame = 0
self.snowball.x = -22
self.snowball.y = 23
if event.key == K_DOWN:
self.player.action = 3
self.player.frame = 0
self.snowball.x = 22
self.snowball.y = 62
if event.key == K_RIGHT:
self.player.action = 0
self.player.frame = 0
self.snowball.x = 65
self.snowball.y = 24
elif event.type == QUIT:
running = False
key_pressed_is = pygame.key.get_pressed()
if key_pressed_is[K_LEFT] and self.x > 200:
self.x -= 10
self.player.is_moving = True
if key_pressed_is[K_RIGHT] and self.x < 1640:
self.x += 10
self.player.is_moving = True
if key_pressed_is[K_UP] and y > 100:
self.y -= 10
self.player.is_moving = True
if key_pressed_is[K_DOWN] and y < 880:
self.y += 10
self.player.is_moving = True
current_time = pygame.time.get_ticks()
if current_time - self.init_time >= self.player.animation_cooldown:
if self.player.is_moving:
self.player.frame += 1
self.snowball.frame += 1
self.init_time = current_time
if self.player.frame >= len(self.player.animation_list[self.player.action]):
self.player.frame = 0
if self.snowball.frame >= len(self.snowball.snow_list):
self.snowball.frame = 0
self.update() # calling update method
self.window_surface.blit(self.grass, (0, 0))
self.setup_background()
self.draw()
self.clock.tick(self.fps)
pygame.display.update()
return
# pygame.quit()
def update(self):
self.player.update()
self.snowball.update()
self.terrain.update()
# This function should be called for every loop through the main game loop.
# It should tell every object to update itself.
# You may end up needing to pass variables to the objects for them to update properly. For instance, player inputs.
return
def draw(self):
self.player.draw(self.window_surface)
self.snowball.draw(self.window_surface)
self.terrain.draw(self.window_surface)
# This function should be called every loop through the main game loop.
# This should tell every object to draw itself.
# You may have to pass the surface you want objects to draw themselves on to.
return
if __name__ == "__main__":
SCREEN_WIDTH, SCREEN_HEIGHT = 1920, 1080
pygame.init()
Game()
g.run()
spritesheet.py:
Code: Select all
import pygame
pygame.init()
players = []
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.sprite_sheet_surface = pygame.image.load('images/master.png').convert_alpha()
self.rect = self.sprite_sheet_surface.get_rect()
self.is_moving = False
self.step_counter = 0
self.animation_cooldown = 125
self.action = 0
self.animation_list = []
self.animation_steps = [12, 12, 12, 12]
self.frame = 0
self.load_animation_list()
players.append(self)
def get_image(self, frame, width, height, scale, colour):
image = pygame.Surface((width, height)).convert_alpha()
image.blit(self.sprite_sheet_surface, (0, 0), ((frame * width), 0, width, height))
self.rect = (self.sprite_sheet_surface, (0, 0), ((frame * width), 0, width, height))
image = pygame.transform.scale(image, (width * scale, height * scale))
image.set_colorkey(colour)
return image
def load_animation_list(self):
for animation in self.animation_steps:
temp_img_list = []
for _ in range(animation):
temp_img_list.append(self.get_image(self.step_counter, 32, 32, 3, (0, 0, 0)))
self.step_counter += 1
self.animation_list.append(temp_img_list)
return
def update(self):
# self.x += self.velocity[0]
# self.y += self.velocity[1]
self.rect = self.sprite_sheet_surface.get_rect()
self.draw()
# This is where the code for updating the indices for the player should live.
return
def draw(self):
window_surface.blit(pygame.transform.scale(self.animation_list[self.action][self.frame], (96, 96)), (self.rect.x, self.rect.y))
# This is where the player should be drawing itself onto the surface.
# You may need to have the game pass the main window surface here as a variable.
return
snowballs = []
class Snowball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.sprite_sheet_surface = pygame.image.load('images/snowball.png').convert_alpha()
self.rect = self.sprite_sheet_surface.get_rect()
self.x = 65
self.y = 24
self.spheresize = 0.1
self.frame = 0
self.snow_list = []
self.snow_steps = 5
self.load_animation_list()
snowballs.append(self)
def get_image(self, frame, width, height, scale, colour):
image = pygame.Surface((width, height)).convert_alpha()
image.blit(self.sprite_sheet_surface, (0, 0), ((frame * width), 0, width, height))
self.rect = (self.sprite_sheet_surface, (0, 0), ((frame * width), 0, width, height))
image = pygame.transform.scale(image, (width * scale, height * scale))
image.set_colorkey(colour)
return image
def load_animation_list(self):
for snow in range(self.snow_steps):
self.snow_list.append(self.get_image(snow, 416, 450, self.spheresize, (0, 0, 0)))
return
def update(self):
self.rect = self.sprite_sheet_surface.get_rect()
self.draw()
return
def draw(self):
window_surface.blit(self.snow_list[self.frame], (self.x, self.y))
return
terrains = []
class Terrain(pygame.sprite.Sprite):
def __init__(self):
self.sprite_sheet_surface = pygame.image.load('images/land.png').convert_alpha()
self.rect = self.sprite_sheet_surface.get_rect()
self.landframe = 0
self.land_list = []
self.land_steps = 9
self.load_animation_list()
terrains.append(self)
def get_image(self, frame, width, height, colour):
image = pygame.Surface((width, height)).convert_alpha()
image.blit(self.sprite_sheet_surface, (0, 0), ((frame * width), 0, width, height))
image.set_colorkey(colour)
return image
def load_animation_list(self):
for land in range(self.land_steps):
self.land_list.append(self.get_image(land, 150, 180, (0, 0, 0)))
return
def update(self):
self.rect = self.sprite_sheet_surface.get_rect()
pass
def draw(self):
brick_width, brick_height = self.land_list[self.landframe].get_width(), self.land_list[self.landframe].get_height()
for x, y in itertools.product(range(0, surface.get_width()+1, brick_width), range(0, surface.get_height()+1, brick_height)):
tile_rect = pygame.Rect(x, y, brick_width, brick_height)
surface.blit(self.land_list[self.landframe], tile_rect)
self.tile_rects.append(tile_rect)
return
Thanks in advance to anybody who has insight or advice into my issue!
I've definitely learned a lot through this process, and was able to solve a lot of the issues that have come up on my own, but I feel like I've been spinning my wheels on just getting these rects set up and working.
Edit: Added g.run() to the if condition at the end... now it opens! ...but then is frozen on a black screen. So, still something wrong with the loop.