Сделайте так, чтобы функция выполнялась при 2 или более нажатиях клавиш

Я новичок в Python, и мне нужна помощь. Как мне сделать так, чтобы функция выполнялась после 2 или более нажатий клавиш? Я пытаюсь сделать игру, используя черепаху, похожую на Minicraft (2D-игра с видом сверху), где вы можете использовать материалы, которые вы получаете из камня и дерева, для создания различных предметов. Код еще не закончен.

Код, с которым мне нужна помощь:

stone = turtle.Turtle()
stone.shape("circle")
stone.color("gray")
stone.penup()
stone.setposition(-220, 180)
stone.shapesize(stretch_wid=2, stretch_len=3)

def stonebreak():
    stone = turtle.Turtle ()
    stone.shape ("circle")
    stone.color ("gray")
    stone.penup ()
    stone.setposition (-220, 180)
    stone.shapesize (stretch_wid=2, stretch_len=3)
    stone.speed("slow")
    stone.hideturtle()
    stone = 0
    stone += 9
    stonestring = "Stone: %s" % stone
    penstone1.write (stonestring, False, align="left", font=("system", 15, "normal"))
    penstone1.clear()
    penstone1.write (stonestring, False, align="left", font=("system", 15, "normal"))


if isCollision(player, stone):
    wn.onkeypress(stonebreak, "space")
    stone.hideturtle()

Полный код:

import turtle
import random
import math
import time
turtle.tracer(5)
score = 0

# Turtles

wn = turtle.Screen()
wn.tracer(0)
wn.bgcolor("black")
wn.title("Catcher")
wn.setup(800, 600)


penwood1 = turtle.Turtle()
penwood1.penup()
penwood1.color("white")
penwood1.hideturtle()
penwood1.goto(-280, 275)
wood = 0
woodstring = "Wood: %s" %wood
penwood1.write(woodstring, False, align ="left", font = ("system", 15, "normal"))

penstone1 = turtle.Turtle()
penstone1.penup()
penstone1.color("white")
penstone1.hideturtle()
penstone1.goto(-200, 275)
stone = 0
stonestring = "Stone: %s" %stone
penstone1.write(stonestring, False, align ="left", font = ("system", 15, "normal"))

player = turtle. Turtle()
player.hideturtle()
player.color("white")
player.shape("triangle")
player.penup()
player.setheading(180)
player.setposition(180, 0)
player.showturtle()
player.penup()
player.speed(0)

pen = turtle.Turtle()
pen.color("white")
pen.shape("circle")
pen.hideturtle()
pen.penup()
pen.setposition(360, 275)
pen.pendown()
pen.setposition(360, -275)
pen.setposition(-360, -275)
pen.setposition(-360, 275)
pen.setposition(360, 275)
pen.shapesize(stretch_wid=3, stretch_len=3)


pen1 = turtle.Turtle()
pen1.color("white")
pen1.shape("circle")
pen1.hideturtle()
pen1.penup()
pen1.goto(-360, 275)
scorestring = "Score: %s" %score
pen1.write(scorestring, False, align = "left", font = ("system", 15, "normal"))


tree = turtle.Turtle()
tree.shape("circle")
tree.color("green")
tree.penup()
tree.setposition(200, 140)

stone1 = turtle.Turtle ()
stone1.shape ("circle")
stone1.color ("gray")
stone1.penup ()
stone1.setposition (-200, 140)
stone1.shapesize (stretch_wid=2, stretch_len=3)
stone1.speed ("slow")

stone = turtle.Turtle()
stone.shape("circle")
stone.color("gray")
stone.penup()
stone.setposition(-220, 180)
stone.shapesize(stretch_wid=2, stretch_len=3)

# ______________________________________________________
treedown = turtle.Turtle()
treedown.shape("circle")
treedown.color("green")
treedown.penup()
treedown.setposition(-250, -140)



# Movement features

def pleft():
    player.setheading(180)
    x = player.xcor()
    x -= 20
    if x < -360:
        x = - 360

    player.setx(x)

def pright():
    player.setheading(0)
    x = player.xcor()
    x += 20
    if x > 360:
        x = + 360

    player.setx(x)

def pdown():
    player.setheading(270)
    y = player.ycor()
    y -= 20
    if y < -275:
        y = - 275

    player.sety(y)

def pup():
    player.setheading(90)
    y = player.ycor()
    y += 20
    if y > 275:
        y = + 275

    player.sety(y)


wn.listen()
wn.onkeypress(pleft, "Left")
wn.onkeypress(pright, "Right")
wn.onkeypress(pup, "Up")
wn.onkeypress(pdown, "Down")



while True:
    wn.update()


    def treebreak():
        tree.speed("slow")
        tree.hideturtle()
        wood = 0
        wood += 2
        woodstring = "Wood: %s" % wood
        penwood1.write (woodstring, False, align="left", font=("system", 15, "normal"))
        penwood1.clear()
        penwood1.write (woodstring, False, align="left", font=("system", 15, "normal"))

        def treebbreak():
            treedown.speed ("slow")
            treedown.hideturtle ()
            wood = 2
            wood += 3
            woodstring = "Wood: %s" % wood
            penwood1.write (woodstring, False, align="left", font=("system", 15, "normal"))
            penwood1.clear ()
            penwood1.write (woodstring, False, align="left", font=("system", 15, "normal"))

        if player.xcor () == -240 and player.ycor () == -140:
            wn.onkeypress (treebbreak, "space")


    if player.xcor() == 180 and player.ycor() == 140:
        wn.onkeypress(treebreak, "space")

    if player.xcor() == 200 and player.ycor() == 120:
        wn.onkeypress(treebreak, "space")

    if player.xcor() == 200 and player.ycor() == 160:
        wn.onkeypress(treebreak, "space")

    if player.xcor() == 221 and player.ycor() == 141:
        wn.onkeypress(treebreak, "space")

    def isCollision(t1, t2):
        distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(),2)+math.pow(t1.ycor()-t2.ycor(),2))
        if distance < 25:
            return True
        else:
            return False

    def stonebreak():
        stone = turtle.Turtle ()
        stone.shape ("circle")
        stone.color ("gray")
        stone.penup ()
        stone.setposition (-220, 180)
        stone.shapesize (stretch_wid=2, stretch_len=3)
        stone.speed("slow")
        stone.hideturtle()
        stone = 0
        stone += 9
        stonestring = "Stone: %s" % stone
        penstone1.write (stonestring, False, align="left", font=("system", 15, "normal"))
        penstone1.clear()
        penstone1.write (stonestring, False, align="left", font=("system", 15, "normal"))


    if isCollision(player, stone):
        wn.onkeypress(stonebreak, "space")
        stone.hideturtle()

    def stone1break():
        stone1 = turtle.Turtle ()
        stone1.shape ("circle")
        stone1.color ("gray")
        stone1.penup ()
        stone1.setposition (-200, 140)
        stone1.shapesize (stretch_wid=2, stretch_len=3)
        stone1.speed("slow")
        stone1.hideturtle()
        stone = 0
        stone += 9
        stonestring = "Stone: %s" % stone
        penstone1.write (stonestring, False, align="left", font=("system", 15, "normal"))
        penstone1.clear()
        penstone1.write (stonestring, False, align="left", font=("system", 15, "normal"))


    if isCollision(player, stone1):
        wn.onkeypress(stone1break, "space")
        stone1.hideturtle()



wn.mainloop()

Я пытаюсь сделать так, чтобы вы получали материалы после 2 или более попаданий по целям.


person Community    schedule 19.07.2019    source источник
comment
Я бы сделал простой конечный автомат для камня. Нажатие пробела переместит ваш камень в следующее состояние (первое состояние равно исходному состоянию, второе состояние сломано). См. примеры реализации здесь   -  person BoboDarph    schedule 19.07.2019


Ответы (2)


Прежде всего, вы не должны устанавливать обработчик события onkeypress() каждый раз, когда происходит столкновение. Попробуйте поступить иначе:

def checkCollisions():
    if isCollision(player, stone1):
        stone1break()
    if isCollision(player, stone2):
        stone2break()
    ...

wn.onkeypress(checkCollisions, "space")

Этот код и все ваши определения функций вы должны поместить перед вашим основным (while True:) циклом.

Затем вам понадобится некоторое состояние ваших игровых объектов. Тривиальный способ - добавить переменные stone1strength=2, stone2strength=2, ... и уменьшить их в соответствующей функции stonebreak(), очищая камень после того, как его сила упадет ниже 1.

Мне очень нравятся ваши усилия. Это напоминает мне мои первые шаги по программированию игр. :)

Следующим шагом может быть переписывание вашего кода для хранения ваших каменных объектов в списке и их повторения вместо обработки десятков переменных stoneX...

person VVend    schedule 19.07.2019

Во-первых, я не вижу проблемы в установке обработчика onkeypress() каждый раз при обнаружении коллизии. Во-вторых, ваш код беспорядок! Например, у вас есть две несвязанные глобальные переменные с одинаковыми именами: stone значение счета и stone черепаха:

stone = 0
# ...
stone = turtle.Turtle()

Вы shape и shapesize() черепаху pen, которую все равно никогда не видно. И что здесь происходит:

wood = 2
wood += 3

что происходит несколько раз, сохраняя ваши оценки на фиксированных значениях, а не увеличивая их. Попытка обнаружить черепаху в точном месте бесполезна:

 if player.xcor() == 180 and player.ycor() == 140:

Поскольку игрок перемещается на 20 пикселей за раз, это плоскость с плавающей запятой. И у черепахи есть метод distance(), нет причин изобретать его заново.

Я считаю, что предложение машины состояний от @BoboDarph является хорошим. Ниже моя переделка и упрощение вашего кода, который делает что-то более простое. Когда вы впервые прикасаетесь к камню или дереву, они просто меняют цвет. После этого вы начинаете зарабатывать баллы:

from turtle import Screen, Turtle

FONT = ('system', 15, 'normal')

# Movement features

def player_left():
    player.setheading(180)

    x = player.xcor() - 20
    if x < -360:
        x = -360

    player.setx(x)

def player_right():
    player.setheading(0)

    x = player.xcor() + 20
    if x > 360:
        x = + 360

    player.setx(x)

def player_down():
    player.setheading(270)

    y = player.ycor() - 20
    if y < -275:
        y = - 275

    player.sety(y)

def player_up():
    player.setheading(90)

    y = player.ycor() + 20
    if y > 275:
        y = + 275

    player.sety(y)

def isCollision(t1, t2):
    return t1.distance(t2) < 25

def tree_touch():
    tree.color('dark green')
    tree.touched = True

def tree_break():
    global wood

    screen.onkeypress(None, 'space')
    tree.color('brown')

    wood += 2

    woodstring = "Wood: %s" % wood
    pen_wood.clear()
    pen_wood.write(woodstring, align='left', font=FONT)

def stone_touch():
    rock.color('gray')
    rock.touched = True

def stone_break():
    global stone

    screen.onkeypress(None, 'space')
    rock.color('light gray')

    stone += 9

    stonestring = "Stone: %s" % stone
    pen_stone.clear()
    pen_stone.write(stonestring, align='left', font=FONT)

# Turtles

screen = Screen()
screen.setup(800, 600)
screen.bgcolor('black')
screen.title("Catcher")
screen.tracer(0)

pen_wood = Turtle()
pen_wood.hideturtle()
pen_wood.color('white')
pen_wood.penup()
pen_wood.goto(-280, 275)

wood = 0
wood_string = "Wood: %s" %wood
pen_wood.write(wood_string, align='left', font=FONT)

pen_stone = Turtle()
pen_stone.hideturtle()
pen_stone.color('white')
pen_stone.penup()
pen_stone.goto(-200, 275)

stone = 0
stone_string = "Stone: %s" %stone
pen_stone.write(stone_string, align='left', font=FONT)

pen = Turtle()
pen.hideturtle()
pen.shape('circle')
pen.color('white')
pen.penup()
pen.setposition(360, 275)
pen.pendown()
pen.setposition(360, -275)
pen.setposition(-360, -275)
pen.setposition(-360, 275)
pen.setposition(360, 275)

rock = Turtle()
rock.shape('circle')
rock.color('dark gray')
rock.penup()
rock.setposition(-220, 180)
rock.shapesize(stretch_wid=2, stretch_len=3)

rock.touched = False

tree = Turtle()
tree.shape('circle')
tree.color('green')
tree.penup()
tree.setposition(200, 140)

tree.touched = False

player = Turtle()
player.hideturtle()
player.shape('triangle')
player.speed('fastest')
player.color('white')
player.setheading(180)
player.penup()
player.setx(180)
player.showturtle()

screen.onkeypress(player_left, 'Left')
screen.onkeypress(player_right, 'Right')
screen.onkeypress(player_up, 'Up')
screen.onkeypress(player_down, 'Down')
screen.listen()

while True:

    if isCollision(player, tree):
        if tree.touched:
            screen.onkeypress(tree_break, "space")
        else:
            screen.onkeypress(tree_touch, "space")
    elif isCollision(player, rock):
        if rock.touched:
            screen.onkeypress(stone_break, "space")
        else:
            screen.onkeypress(stone_touch, "space")
    else:
            screen.onkeypress(None, "space")

    screen.update()

screen.mainloop()  # never reached

ЗАДАЧА

  • Изящно включите несколько деревьев и камней.

  • Измените фиксированное значение 25 в isCollision() на значение, рассчитанное на основе shapesize() объекта.

  • Замените цикл while True: функцией и синхронизированным событием.

person cdlane    schedule 19.07.2019