Как мне легко изменить функциональность моего кода? - PullRequest
2 голосов
/ 10 февраля 2020

Я хочу сделать свою игру "go back" в главном меню, и мне было интересно, могу ли я использовать функцию окна игры "изнутри" так, чтобы она создала "сброс". По сути, если бы мой спрайт столкнулся с надписью «игра окончена», я бы хотел нажать кнопку «назад», а если бы я снова нажал «играть», то я бы показал «сброшенную» игру, где «таймер», «астероид» «корабль» возвращается к началу, как будто я снова играю в новую игру.

Мне также было интересно, значат ли какие-либо из предоставленных мне ошибок что-либо для моей проблемы сейчас ??

Код / игра в основном работает. У него просто нет цели «сброса».

Вот ошибки:

"C:\Users\Myke Sustento\AppData\Local\Programs\Python\Python38-32\python.exe" "B:/PROGRAMMING RELATED/PYTHON PROJECTS/FINAL.py"
B:/PROGRAMMING RELATED/PYTHON PROJECTS/FINAL.py:261: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if bullet_state is "fire":
B:/PROGRAMMING RELATED/PYTHON PROJECTS/FINAL.py:322: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if bullet_state is "ready":
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
B:/PROGRAMMING RELATED/PYTHON PROJECTS/FINAL.py:171: DeprecationWarning: an integer is required (got type float).  Implicit conversion to integers using __int__ is deprecated, and may be removed in a future version of Python.
  display.blit(ammoboximg,(x,y))
Traceback (most recent call last):
  File "B:/PROGRAMMING RELATED/PYTHON PROJECTS/FINAL.py", line 374, in <module>
    gamewindow()
  File "B:/PROGRAMMING RELATED/PYTHON PROJECTS/FINAL.py", line 315, in gamewindow
    gamewindow()
  File "B:/PROGRAMMING RELATED/PYTHON PROJECTS/FINAL.py", line 315, in gamewindow
    gamewindow()
  File "B:/PROGRAMMING RELATED/PYTHON PROJECTS/FINAL.py", line 315, in gamewindow
    gamewindow()
  File "B:/PROGRAMMING RELATED/PYTHON PROJECTS/FINAL.py", line 330, in gamewindow
    keys = pygame.key.get_pressed()
pygame.error: video system not initialized

Process finished with exit code 1

Вот весь код:

# initialization of pygame
import pygame
import random
import math


pygame.init()
# creating the display
display = pygame.display.set_mode((500, 500))

# title & icon
spaceship = pygame.image.load("Space Blitz Sprites/spaceship.png")
pygame.display.set_icon(spaceship)
pygame.display.set_caption("SpaceBlitz")

# main menu sprites
spaceblitz = pygame.image.load("Space Blitz Sprites/spaceblitz.png")
play = pygame.image.load("Space Blitz Sprites/play.png")
howtoplay = pygame.image.load("Space Blitz Sprites/howtoplay.png")
about = pygame.image.load("Space Blitz Sprites/about.png")
quit = pygame.image.load("Space Blitz Sprites/quit.png")

# inside main menu
instruction = pygame.image.load("Space Blitz Sprites/instruction.png")
back = pygame.image.load("Space Blitz Sprites/back.png")
aboutdev = pygame.image.load("Space Blitz Sprites/aboutdev.png")

# main menu music
music = pygame.mixer.music.load("Space Blitz Sprites/mountaintrails.mp3")

# PlayerSpriteMovement
playerimg = pygame.image.load("Space Blitz Sprites/spaceship.png")
playerX = 250
playerY = 400
velocity = 3
clock = pygame.time.Clock()

# Bullet
bulletimg = pygame.image.load("Space Blitz Sprites/bullet.png")
bulletX = 0
bulletY = playerY
bulletx_change = 0
bulletY_change = 8
bullet_state = "ready"
bullet_ammo = 5
bulletfont = pygame.font.Font('freesansbold.ttf', 16)
# Ammo Box
ammoboximg = pygame.image.load('Space Blitz Sprites/ammo.png')
ammoboxX = random.randint(0,468)
ammoboxY = random.randint(-1000,-800)
ammoboxY_change = -1.5

# Asteroid
asteroidimg = []
asteroidX = []
asteroidY = []
asteroidX_change = []
asteroidY_change = []
no_of_enemies = 40

def mainmenu():
    global menuselect
    global spaceblitz
    menu = True
    pygame.mixer.music.play(50)
    pygame.mixer.music.set_volume(0.2)
    while menu:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    pos = pygame.mouse.get_pos()
                    if start.collidepoint(pos):
                        menu = False
                        menuselect = 1
                        pygame.mixer.music.stop()
                    if controls.collidepoint(pos):
                        menu = False
                        menuselect = 2
                        pygame.mixer.music.stop()
                    if developer.collidepoint(pos):
                        menu = False
                        menuselect = 3
                        pygame.mixer.music.stop()
                    if exit.collidepoint(pos):
                        menu = False
                        menuselect = 4

        display.fill((0, 0, 0))
        display.blit(spaceblitz, (170,150))
        start = display.blit(play, (170,250))
        controls = display.blit(howtoplay, (170,300))
        developer = display.blit(about, (170,350))
        exit = display.blit(quit, (170,400))
        pygame.display.flip()
        pygame.display.update()

def controls():
    global menuselect
    global menu
    controls = True
    while controls:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    pos = pygame.mouse.get_pos()
                    if balik.collidepoint(pos):
                        controls = False
                        menu = True
                        menuselect = 0
        balik = display.blit(back, (0,450))
        display.blit(instruction, (0,0))
        pygame.display.flip()
        pygame.display.update()
        display.fill((0, 0, 0))

def developers():
    global menuselect
    global menu
    dev = True
    while dev:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    pos = pygame.mouse.get_pos()
                    if balik.collidepoint(pos):
                        dev = False
                        menu = True
                        menuselect = 0
        balik = display.blit(back, (0, 450))
        display.blit(aboutdev, (0, 0))
        pygame.display.flip()
        pygame.display.update()
        display.fill((0, 0, 0))

# Asteroid
for r in range(no_of_enemies):
    asteroidimg.append(pygame.image.load("Space Blitz Sprites/asteroid.png"))
    asteroidX.append(random.randint(-100, 500))
    asteroidY.append(random.randint(-300, -30))
    asteroidX_change.append(0)
    asteroidY_change.append(2)




# Game Over Text
overfont = pygame.font.Font('freesansbold.ttf',32)


# Sprite image
def player(x, y):
    display.blit(playerimg, (x, y))

def fire_bullet(x, y):
    global bullet_state
    if bullet_ammo > -1:
        bullet_state = "fire"
        display.blit(bulletimg, (x + 9, y + -7))
    else:
        bullet_state = "ready"

def ammobox(x,y):
    display.blit(ammoboximg,(x,y))

def AmBoxCollision(ammoboxX,ammoboxY,playerX,playerY):
    ammoboxdistance = math.sqrt((math.pow(ammoboxX - playerX, 2)) + (math.pow(ammoboxY - playerY, 2)))
    if ammoboxdistance < 27:
        return True
    else:
        return False

def ammo():
    global bullet_ammo
    global ammo_decrease
    ammo_decrease = 1
    bullet_ammo -= ammo_decrease



def asteroid(x, y, r):
    display.blit(asteroidimg[r], (x, y))




def BulCollision(asteroidX, asteroidY, bulletX, bulletY):
    buldistance = math.sqrt((math.pow(bulletX - asteroidX, 2)) + (math.pow(bulletY - asteroidY, 2)))
    if buldistance < 27:
        return True
    else:
        return False
def PlayCollision(asteroidX, asteroidY, playerX, playerY):
    playdistance = math.sqrt((math.pow(playerX - asteroidX, 2)) + (math.pow(playerY - asteroidY, 2)))
    if playdistance < 27:
        return True
    else:
        return False
def gameover_screen():
    overtext = overfont.render("GAME OVER",True,(255,255,255))
    display.blit(overtext, (150,250))

# mainloop
def gamewindow():
    global menuselect
    global playerX
    global playerY
    global velocity
    global clock
    global bulletX
    global bulletY
    global bulletY_change
    global bullet_state
    global asteroidX
    global asteroidY
    global asteroidY_change
    global no_of_enemies
    global ammoboxX
    global ammoboxY
    global ammoboxY_change
    global dev
    global menu
    global bullet_ammo
    global ammo_decrease
    global passed_time
    font = pygame.font.Font(None, 54)
    font_color = pygame.Color('white')
    start_time = pygame.time.get_ticks()
    run_timer = True
    running = True

    while running:
        clock.tick(60)
        display.fill((0, 0, 0))
        AmmoBoxCollision = AmBoxCollision(ammoboxX,ammoboxY,playerX,playerY)
        if AmmoBoxCollision:
            ammoboxY = random.randint(-1000, -800)
            ammoboxX = random.randint(0, 468)
            if bullet_ammo <= 4 and bullet_ammo > -1:
                bullet_ammo += 1
            if bullet_ammo == -1:
                bullet_ammo +=2


        if bullet_ammo == -1 or bullet_ammo == 0:
            bullet_text = bulletfont.render("Ammo:%d" % bullet_ammo, True, (0, 0, 0))
            display.blit(bullet_text, (10, 468))
            noammo = bulletfont.render("NO AMMO",True,(255,255,255))
            display.blit(noammo,(10,468))
        else:
            bullet_text = bulletfont.render("Ammo:%d" % bullet_ammo, True, (255, 255, 255))
            display.blit(bullet_text, (10, 468))

        if bullet_state is "fire":
            fire_bullet(bulletX, bulletY)
            bulletY -= bulletY_change

        if bulletY <= 0:
            bulletY = playerY
            bullet_state = "ready"

        for r in range(no_of_enemies):
            asteroid(asteroidX[r], asteroidY[r], r)
            asteroidY[r] += asteroidY_change[r]
            if asteroidY[r] >= 500:
                asteroidY[r] = random.randint(-300, -30)
                asteroidX[r] = random.randint(-100, 500)

            Bulletcollision = BulCollision(asteroidX[r], asteroidY[r], bulletX, bulletY)
            if Bulletcollision:
                bulletY = playerY
                bullet_state = "ready"
                asteroidX[r] = random.randint(-100, 500)
                asteroidY[r] = random.randint(-300, -30)

            # Game over
            PlayerCollision = PlayCollision(asteroidX[r], asteroidY[r], playerX, playerY)

            if PlayerCollision:
                for j in range(no_of_enemies):
                    asteroidY_change[j] = 0
                    asteroidY[j] = random.randint(-300, -30)
                    asteroidX[j] = random.randint(-100, 500)
                    asteroidY_change[j] = 2

                velocity = 0
                bulletY_change = 0
                bulletY = 600
                ammoboxY_change = 0
                run_timer = False
                gameover_screen()
                playerX = 250
                playerY = 400
                velocity = 3


        # movement
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()

            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    pos = pygame.mouse.get_pos()
                    if balik.collidepoint(pos):
                        running = False
                        menu = True
                        menuselect = 0


            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    if bullet_ammo <= 5 and bullet_ammo > -1:
                        if bullet_state is "ready":
                            bulletX = playerX
                            bulletY = playerY
                            fire_bullet(bulletX, bulletY)
                            ammo()


        # player movement
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            playerX -= velocity

        if keys[pygame.K_RIGHT]:
            playerX += velocity

        if keys[pygame.K_DOWN]:
            playerY += velocity

        if keys[pygame.K_UP]:
            playerY -= velocity

        # Border
        if playerX <= 0:
            playerX = 0
        elif playerX >= 468:
            playerX = 468
        if playerY <= 0:
            playerY = 0
        elif playerY >= 468:
            playerY = 468

        if ammoboxY > 500:
            ammoboxY = random.randint(-1000,-800)
            ammoboxX = random.randint(0,468)
        ammobox(ammoboxX,ammoboxY)
        ammoboxY -= ammoboxY_change

        if run_timer:
            current_time = pygame.time.get_ticks()
            passed_time = current_time - start_time

        text = font.render(str(passed_time / 1000), True, font_color)
        display.blit(text, (50, 50))
        balik = display.blit(back, (350, 450))
        player(playerX, playerY)
        pygame.display.update()

mainmenu()
while True:
        if menuselect == 0:
            mainmenu()
        elif menuselect == 1:
            gamewindow()
        elif menuselect == 2:
            controls()
        elif menuselect == 3:
            developers()
        elif menuselect == 4:
            pygame.quit()

Вот где я хотел бы поставить кнопку сброса (либо в PlayerCollision, либо в balik.collidepoint (pos))

        if PlayerCollision:
            for j in range(no_of_enemies):
                asteroidY_change[j] = 0
                asteroidY[j] = random.randint(-300, -30)
                asteroidX[j] = random.randint(-100, 500)
                asteroidY_change[j] = 2

            velocity = 0
            bulletY_change = 0
            bulletY = 600
            ammoboxY_change = 0
            run_timer = False
            gameover_screen()
            playerX = 250
            playerY = 400
            velocity = 3


    # movement
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                pos = pygame.mouse.get_pos()
                if balik.collidepoint(pos):
                    running = False
                    menu = True
                    menuselect = 0


        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                if bullet_ammo <= 5 and bullet_ammo > -1:
                    if bullet_state is "ready":
                        bulletX = playerX
                        bulletY = playerY
                        fire_bullet(bulletX, bulletY)
                        ammo()

Извините, если задаю много вопросов. Это мой первый код в python (или программировании в целом), так что я не знаю, как работает большинство вещей. Кроме того, код представляет собой смесь моего кода и кода моего товарища по группе, поэтому половина кода в этой программе мне незнакома. Советы по будущей практике кодирования высоко ценятся, но я просто хочу закончить свою игру прямо сейчас, поэтому я хотел бы закончить текущую (и последнюю) проблему, с которой я столкнулся.

1 Ответ

2 голосов
/ 10 февраля 2020

Как вы говорите, вы только начали и учитесь. Отлично! Вы только что столкнулись с проблемой, из которой вы можете многому научиться: добавление новых функций . Как правило, этот вопрос лучше подходит для обмена стеками обзора кода , но я думаю, что он также подходит и здесь.

Так в чем именно проблема? Вы говорите, что хотите вернуть игру «go назад» в главное меню. Вы предлагаете реализацию, за которой (как мне кажется) трудно следовать, и выполняете кучу кода, который, я уверен, работает, но трудно (для меня) прочитать. Я, честно говоря, считаю очень впечатляющим, сколько вы смогли написать, тем более что вы впервые пишете код!


На мой взгляд, ваша настоящая проблема не в том, как "go назад "скорее это то, как сделать ваш код исправимым / обновляемым. Очень хороший урок для изучения. Есть несколько причин, по которым ваш текущий код трудно обновить:

  • Весь ваш код находится в одном файле, что затрудняет навигацию
  • У вас есть глобальные переменные, которые могут быть сложными для отслеживания
  • Вы используете много жестко закодированных значений, которые трудно изменить / отслеживать

Почему это проблема? Если вы хотите что-то изменить, вы не можете найти, где что-то изменить, потому что вы ничего не можете найти, потому что везде так много кода. Затем, как только вы найдете это, вы не можете действительно знать, что все из-за глобальных переменных. Наконец, жестко закодированные значения не позволяют узнать, все ли вы исправили или забыли число, вызывающее ошибку (например, вы хотите сделать экран в два раза больше, изменить все размеры изображения, но забыть обновить скорость).


Итак, как вы можете это изменить?

Что ж, сначала попробуйте разделить ваш код, чтобы было легче найти вещи. Мне нравится помещать вещи в такие папки:

my_project/
    main.py
    .gitignore
    core/
        game_mechanics/
            player.py
            bullet.py
            asteroid.py
        game_setup/
            main_menu.py
            run_game.py
    config/
        config.yaml
    utils/
        read_config.py
    tests/
        test1.py
        test2.py

Это может показаться пугающим, поэтому давайте пробежимся мимо всего, что есть:

Main.py : ваш главный файл, который вы запускаете. Это выглядит примерно так:

from example_file import example_function

def main(config):
    while True:
        settings = main_menu()
        play_game(settings)

if __name__ == '__main__':
    config = load_config()
    main(config)

Когда вы запускаете main.py, он загружает конфигурацию, а затем запускает основные компоненты. Этот файл должен быть очень коротким, чтобы легко было понять, что происходит. Вот, например, вы получаете настройки от запуска main_menu() и затем играете в игру, используя эти настройки. Когда игра выйдет, снова появится главное меню.

Далее будет файл .gitignore , который вам понадобится, если вы используете git. Если вы не знаете, что это такое, или вы должны использовать Google, это сделает вашу жизнь намного проще.

В папке core есть все основные функции, указанные c к игре. Это где вы положили большую часть вашего кода. Важно разбить его на логические файлы, чтобы вы могли легко найти, что и куда.

В папке utils есть функции утилит, которые вы захотите разделить между проектами.

В папке config вы можете сохранить настройки. Он должен содержать все «числовые или буквенные значения», которые вы используете, таким образом, вам не нужно go через свой код везде менять вручную номер (и, возможно, забыть один), а вместо этого передавать его.

Это решает вашу проблему с необходимостью найти где что находится. Все заказано красиво, и вы можете легко найти это. Если вы хотите изменить большие функции (например, добавить новое меню), вы можете сделать это в основном файле, который легко сделать.


Следующая проблема - использование глобальных переменных. У вас их довольно много, и это затрудняет отслеживание того, какая ценность является чем. Это может быть понятно для вас, но представьте, что когда вы вернетесь через год и значения изменятся «случайно», как вы узнаете, что и где меняется?

Вместо этого попробуйте передать вещи своим функциям следующим образом:

def square_n(n):
    return n * n 

a = 5
a_squared = square_n(a)

Это значительно облегчает чтение того, что и где происходит.


Наконец, как уже упоминалось ранее, жестко закодированные значения сильно затрудняют обновление. Возьмите пример с удвоением размера экрана. Вы делаете все в два раза больше, но забыли удвоить один компонент скорости (потому что вы его пропустили). Это может быть «странная ошибка», которая требует времени для исправления. Вместо этого попробуйте сохранить все эти значения в вашей конфигурации и передать их, как показано выше. Это выглядело бы примерно так:

def print_hello_world_n_times(n):
    for i in range(n):
        print("hello world")

config = load_config()
# config = {'a': 5, 'b': 10}
a = config['a']
print_hello_world_n_times(a)

Извините, я не буду давать вам решение для копирования-вставки вашей проблемы. Я думаю, что для вас гораздо полезнее самостоятельно реструктурировать свой код, а затем посмотреть, насколько проще изменить его функциональность.

Успех!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...