简体   繁体   中英

pygame rect doesn't change position while i give it a new position and update it

okay so i'm fairly new to programming and i'm making a game based on the arcade game alien invasion. but i want to make an intro with moving text to show credits at the start because it's fun and good practice to learn. but i cant seem to make it work. i want the text to fly from the side of the screen to middle stop there then fly away again

so here is the function that draws the texts.

from Settings import *
import sys

class TextsObjects:
def __init__(self):
    self.setting = Settings()
    self.intro_settings = IntroSettings()

    self.display_intro_1 = DisplayText(
        self.intro_settings.intro_text_1,
        self.intro_settings.intro_text_1_pos_x,
        self.intro_settings.intro_text_1_pos_y,
        self.intro_settings.font_size,
        self.setting.light_grey
        )

    self.display_intro_2 = DisplayText(
        self.intro_settings.intro_text_2,
        self.intro_settings.intro_text_2_pos_x,
        self.intro_settings.intro_text_2_pos_y,
        self.intro_settings.font_size,
        self.setting.light_grey
        )

    self.display_intro_title = DisplayText(
        self.intro_settings.intro_text_title,
        self.intro_settings.intro_text_title_pos_x,
        self.intro_settings.intro_text_title_pos_y,
        self.intro_settings.font_size,
        self.setting.light_grey)


class Intro:
    def __init__(self, screen, setting):
        self.screen = screen
        self.setting = setting
        self.i_setting = IntroSettings()
        self.intro_text = TextsObjects()
        self.clock = pygame.time.Clock()
        self.speed = 50 * setting.time
        self.screen_c_left = setting.screen_width / 2 - self.speed / 2
        self.screen_c_right = setting.screen_width / 2 + self.speed / 2

    def intro_update(self):
        # reset the background so you don't get multiple drawings onscreen
        self.screen.fill(self.setting.dark_blueish)

        if 0 <= self.i_setting.intro_text_1_pos_x <= \
                self.setting.screen_width:

            # Draw the first text
            self.intro_text.display_intro_1.draw_me_with_shadow(
                    self.screen)

        if self.screen_c_left < self.i_setting.intro_text_2_pos_x < \
                self.screen_c_right:

            # Draw the second text
            self.intro_text.display_intro_2.draw_me_with_shadow(
                self.screen)

        pygame.display.update()

    def show_intro(self):
        self.i_setting.intro_text_1_pos_x += self.speed
        # show the intro for self.intro_time amount of time
        for frames in range(0, self.setting.fps * 3):
            # test for events
            for event in pygame.event.get():
                print(event)
                # when the window is closed stop the game loop
                if event.type == pygame.QUIT:
                    sys.exit()

            self.intro_update()
            self.setting.clock.tick(self.setting.fps)

and here are the classes that are relevant:

class Settings:
    def __init__(self):

        # screen size
        self.screen_width = 800
        self.screen_height = 500

        # set clock and fps
        self.clock = pygame.time.Clock()
        self.fps = 60
        # calculate the seconds in every frame
        self.time = 1 / self.fps

    class IntroSettings:
        def __init__(self):
            self.setting = Settings()
            self.font_size = 100
            self.timer_font_size = 10

            self.intro_text_1_pos_x = (self.setting.screen_width / 2) - 100
            self.intro_text_1_pos_y = \
                (self.setting.screen_height / 2 - self.font_size)
            self.intro_text_1 = "A game by:"

            self.intro_text_2_pos_x = (self.setting.screen_width / 2)
            self.intro_text_2_pos_y = \
                (self.setting.screen_height / 2 + self.font_size)
            self.intro_text_2 = "Mark Olieman"

            self.intro_text_title_pos_x = (self.setting.screen_width / 2)
            self.intro_text_title_pos_y = (self.setting.screen_height + self.font_size)
            self.intro_text_title = "Alien Invasion!"

            self.intro_text_timer_pos_x = 20
            self.intro_text_timer_pos_y = 20

            self.speed = -2


    class DisplayText:
        def __init__(self, text, pos_x, pos_y, font_size, text_color):

            self.font = pygame.font.Font("freesansbold.ttf", font_size)

            self.text_surf = self.font.render(text, True, text_color)
            self.text_rect = self.text_surf.get_rect()
            self.text_rect.center = (pos_x, pos_y)

            self.shadow_color = (0, 0, 0)

            self.text_surf_shadow = self.font.render(text, True, self.shadow_color)
            self.text_rect_shadow = self.text_surf.get_rect()
            self.text_rect_shadow.center = (pos_x + 10, pos_y + 5)

        def draw_me(self, screen):
            screen.blit(self.text_surf, self.text_rect)

        def draw_me_with_shadow(self, screen):
            screen.blit(self.text_surf_shadow, self.text_rect_shadow)
            screen.blit(self.text_surf, self.text_rect)

i am sorry for the amount of code but because i don't know where the problem lies i want you guys to have all the relevant information so at last here is my main game loop

import pygame
from Settings import *
from Entities import *
from Game_functions import *
from Menu import *

# make the modules available
setting = Settings()

screen = pygame.display.set_mode((setting.screen_width, setting.screen_height))
pygame.display.set_caption("Alien Invasion, By Mark Olieman")

intro = Intro(screen, setting)
player = Player(screen, setting)
bullet = Bullet(screen, setting, player)
intro_set = IntroSettings()

# initizialize pygame
pygame.init()
pygame.mixer.init()

# initizialize the screen and set a caption


# function to start gaming
def gaming():
    bullets = pygame.sprite.Group()
    intro.show_intro()
    intro_set.intro_text_1_pos_x += intro.speed
    print(intro_set.intro_text_1_pos_x)
    # Game Loop
    while True:
        # check events and make actions happen
        events(bullets, player, screen, setting)

        # update everything and draw bullets
        update(player, setting, bullets, screen)

        # update screen at certain fps
        pygame.display.update()
        setting.clock.tick(setting.fps)


# Start the game
gaming()

# Stop the game
pygame.quit()

I found two mistakes in Intro.show_intro()

  1. you add speed before loop but you have to do it inside loop

  2. you add speed to self.i_setting.intro_text_1_pos_x but you have to add

    self.intro_text.display_intro_1.text_rect.x += self.speed self.intro_text.display_intro_1.text_rect_shadow.x += self.speed

Correct version which moves text (and shadow) "A game by:"

def show_intro(self):

    #self.i_setting.intro_text_1_pos_x += self.speed

    # show the intro for self.intro_time amount of time
    for frames in range(0, self.setting.fps * 3):
        # test for events
        for event in pygame.event.get():
            print(event)
            # when the window is closed stop the game loop
            if event.type == pygame.QUIT:
                sys.exit()

        # you have to add speed inside loop
        #self.i_setting.intro_text_1_pos_x += self.speed
        self.intro_text.display_intro_1.text_rect.x += self.speed
        self.intro_text.display_intro_1.text_rect_shadow.x += self.speed

        self.intro_update()
        self.setting.clock.tick(self.setting.fps)

There can be another problem - rect.x can keep only integer values but speed has value 0.83 so when you add 0.83 then it can be rounded to 1 so it may move faster then you expect - or it can move too far (or may move not so smooth as you expected). If speed will be smaller then 0.5 then it may even round it to 0 so it will not move.

You may have to keep position in separated values as float values, change them and copy to rect.x only before drawing.


Full code which I run in one file - I removed some imports and elements which I hadn't (ie, Player )

import sys

class TextsObjects:
    def __init__(self):
        self.setting = Settings()
        self.intro_settings = IntroSettings()

        self.display_intro_1 = DisplayText(
            self.intro_settings.intro_text_1,
            self.intro_settings.intro_text_1_pos_x,
            self.intro_settings.intro_text_1_pos_y,
            self.intro_settings.font_size,
            self.setting.light_grey
            )

        self.display_intro_2 = DisplayText(
            self.intro_settings.intro_text_2,
            self.intro_settings.intro_text_2_pos_x,
            self.intro_settings.intro_text_2_pos_y,
            self.intro_settings.font_size,
            self.setting.light_grey
            )

        self.display_intro_title = DisplayText(
            self.intro_settings.intro_text_title,
            self.intro_settings.intro_text_title_pos_x,
            self.intro_settings.intro_text_title_pos_y,
            self.intro_settings.font_size,
            self.setting.light_grey)


class Intro:
    def __init__(self, screen, setting):
        self.screen = screen
        self.setting = setting
        self.i_setting = IntroSettings()
        self.intro_text = TextsObjects()
        self.clock = pygame.time.Clock()
        self.speed = 150 * setting.time
        print(self.speed)
        self.screen_c_left = setting.screen_width / 2 - self.speed / 2
        self.screen_c_right = setting.screen_width / 2 + self.speed / 2

    def intro_update(self):
        # reset the background so you don't get multiple drawings onscreen
        self.screen.fill(self.setting.dark_blueish)

        if 0 <= self.i_setting.intro_text_1_pos_x <= self.setting.screen_width:

            # Draw the first text
            self.intro_text.display_intro_1.draw_me_with_shadow(self.screen)

        if self.screen_c_left < self.i_setting.intro_text_2_pos_x < self.screen_c_right:

            # Draw the second text
            self.intro_text.display_intro_2.draw_me_with_shadow(self.screen)

        pygame.display.update()

    def show_intro(self):
        #self.i_setting.intro_text_1_pos_x += self.speed

        # show the intro for self.intro_time amount of time
        for frames in range(0, self.setting.fps * 3):
            # test for events
            for event in pygame.event.get():
                print(event)
                # when the window is closed stop the game loop
                if event.type == pygame.QUIT:
                    sys.exit()

            #self.i_setting.intro_text_1_pos_x += self.speed
            self.intro_text.display_intro_1.text_rect.x += self.speed
            self.intro_text.display_intro_1.text_rect_shadow.x += self.speed

            self.intro_update()
            self.setting.clock.tick(self.setting.fps)


class Settings:
    def __init__(self):

        # screen size
        self.screen_width = 800
        self.screen_height = 500

        # set clock and fps
        self.clock = pygame.time.Clock()
        self.fps = 60
        # calculate the seconds in every frame
        self.time = 1 / self.fps

        self.light_grey = (128,128,128)
        self.dark_blueish = (0,0,255)

class IntroSettings:
    def __init__(self):
        self.setting = Settings()
        self.font_size = 100
        self.timer_font_size = 10

        self.intro_text_1_pos_x = (self.setting.screen_width / 2) - 100
        self.intro_text_1_pos_y = \
            (self.setting.screen_height / 2 - self.font_size)
        self.intro_text_1 = "A game by:"

        self.intro_text_2_pos_x = (self.setting.screen_width / 2)
        self.intro_text_2_pos_y = \
            (self.setting.screen_height / 2 + self.font_size)
        self.intro_text_2 = "Mark Olieman"

        self.intro_text_title_pos_x = (self.setting.screen_width / 2)
        self.intro_text_title_pos_y = (self.setting.screen_height + self.font_size)
        self.intro_text_title = "Alien Invasion!"

        self.intro_text_timer_pos_x = 20
        self.intro_text_timer_pos_y = 20

        self.speed = -2


class DisplayText:
    def __init__(self, text, pos_x, pos_y, font_size, text_color):

        self.font = pygame.font.Font("freesansbold.ttf", font_size)

        self.text_surf = self.font.render(text, True, text_color)
        self.text_rect = self.text_surf.get_rect()
        self.text_rect.center = (pos_x, pos_y)

        self.shadow_color = (0, 0, 0)

        self.text_surf_shadow = self.font.render(text, True, self.shadow_color)
        self.text_rect_shadow = self.text_surf.get_rect()
        self.text_rect_shadow.center = (pos_x + 10, pos_y + 5)

    def draw_me(self, screen):
        screen.blit(self.text_surf, self.text_rect)

    def draw_me_with_shadow(self, screen):
        screen.blit(self.text_surf_shadow, self.text_rect_shadow)
        screen.blit(self.text_surf, self.text_rect)

import pygame
#from Entities import *
#from Game_functions import *
#from Menu import *

# initizialize pygame
pygame.init()
pygame.mixer.init()

# make the modules available
setting = Settings()

screen = pygame.display.set_mode((setting.screen_width, setting.screen_height))
pygame.display.set_caption("Alien Invasion, By Mark Olieman")

intro = Intro(screen, setting)
#player = Player(screen, setting)
#bullet = Bullet(screen, setting, player)
intro_set = IntroSettings()

# initizialize the screen and set a caption


# function to start gaming
def gaming():
    bullets = pygame.sprite.Group()
    intro.show_intro()
    intro_set.intro_text_1_pos_x += intro.speed
    print(intro_set.intro_text_1_pos_x)
    # Game Loop
    while True:
        # check events and make actions happen
        #events(bullets, player, screen, setting)

        # update everything and draw bullets
        #update(player, setting, bullets, screen)

        # update screen at certain fps
        pygame.display.update()
        setting.clock.tick(setting.fps)

# Start the game
gaming()

# Stop the game
pygame.quit()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM