Время и нажатия клавиш с Python черепахой - PullRequest
0 голосов
/ 06 марта 2020

Я пытаюсь создать простую игру с черепахой:

  • Черепаха, управляемая пользователем, может стрелять пулями при нажатии space
  • Вражеская черепаха создается в случайная позиция
  • Если пуля поражает противника, он уничтожается и перемещается на новую позицию.
  • Если пуля покидает экран, она исчезает.
  • Пока пуля движется, игрок все еще должен двигаться.
  • Если враг не будет уничтожен в течение 20 секунд, игрок проигрывает.

Поэтому мне нужно немного события, которые будут управляться с клавиатуры и другие, которые запускаются через определенное время. Я не могу придумать, как это сделать, не имея всего 1025 *, внутри которого я проверяю расстояние между пулей и противником, но если я делаю это таким образом, я не могу управлять главной черепахой в течение 1 oop.

import turtle as trtl
from random import randint
import time

class Game():
    def __init__(self):
        self.scr = trtl.Screen()
        self.scr.update()

        self.player = trtl.Turtle()
        self.player.shape('turtle')
        self.player.penup()

        trtl.onkeypress(self.forward,'w')
        trtl.onkeypress(self.backwards,'s')
        trtl.onkeypress(self.left,'a')
        trtl.onkeypress(self.right,'d')
        trtl.onkeypress(self.shoot,'space')
        trtl.listen()

        self.enemy = trtl.Turtle()
        self.enemy.shape('square')
        self.enemy.penup()
        self.enemy.speed(0)
        self.move_enemy()

        self.bullet = trtl.Turtle()
        self.bullet.penup()
        self.bullet.hideturtle()
        self.bulletShot = False


    def forward(self):
        self.player.forward(5)

    def backwards(self):
        self.player.back(5)

    def left(self):
        self.player.left(6)

    def right(self):
        self.player.right(6)

    def shoot(self):
        if self.bulletShot == False:
            self.bullet.speed(0)
            self.bullet.goto(self.player.pos())
            self.bullet.seth(self.player.heading())
            self.bullet.showturtle()
            self.bulletShot = True

    def move_enemy(self):
        x = randint(-300,300)
        y = randint(-300,300)
        self.enemy.hideturtle()
        self.enemy.goto(x,y)
        self.enemy.showturtle()

    def play(self):
        startTime = time.time()
        print(time.time() - startTime)
        while time.time() - startTime < 20:
            if self.bulletShot:
                self.bullet.forward(1)
                collision = self.bullet.distance(self.enemy.pos()) < 10
                isIn = (self.bullet.pos()[0] <= 300 and 
                        self.bullet.pos()[0] >= -300 and 
                        self.bullet.pos()[1] <= 300 and 
                        self.bullet.pos()[1] >= -300)

                if not(isIn):
                    self.bullet.hideturtle()
                    self.bulletShot = False
                elif collision:
                    self.bullet.hideturtle()
                    self.bulletShot = False
                    self.move_enemy()
                    startTime = time.time()

        self.player.write('You loose')
        self.scr.exitonclick()


game = Game()
game.play()

Я попробовал более простую версию, в которой одна черепаха перемещается автоматически в oop, а другая черепаха управляется с клавиатуры, и она работает хорошо.

import turtle as trtl

def up():
    jane.sety(jane.pos()[1] + 10)

def down():
    jane.sety(jane.pos()[1] - 10)

scr = trtl.Screen()
scr.update()

bob = trtl.Turtle()
bob.penup()
bob.seth(180)
bob.setx(300)
bob.speed(1)

jane = trtl.Turtle()
jane.penup()

trtl.onkeypress(up,'w')
trtl.onkeypress(down,'s')
trtl.listen()

while True:
    if bob.pos()[0] > -300:
        bob.forward(10)
    else:
        break

scr.exitonclick()

Есть ли способ исправить это с черепахой?

Ответы [ 2 ]

0 голосов
/ 07 марта 2020

Мне удалось решить эту проблему, не сильно изменив код и не сделав функцию play() рекурсивной. Проблема заключалась в том, что если if внутри de while требуется else, в противном случае нажатие клавиши не записывается. Поэтому я дал ему кое-что сделать, и теперь он работает, как я хочу.

while time.time() - startTime < 20:
    if self.bulletShot:
        self.bullet.forward(3)
        ...
    else:
        self.scr.update()
0 голосов
/ 06 марта 2020

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

from turtle import Screen, Turtle
from random import randint
import time

class Game():
    def __init__(self):
        self.startTime = -1

        self.screen = Screen()
        self.screen.tracer(False)

        self.player = Turtle()
        self.player.shape('turtle')
        self.player.penup()

        self.enemy = Turtle()
        self.enemy.shape('square')
        self.enemy.penup()
        self.move_enemy()

        self.bullet = Turtle()
        self.bullet.hideturtle()
        self.bullet.penup()
        self.bulletShot = False

        self.screen.onkeypress(self.forward, 'w')
        self.screen.onkeypress(self.backwards, 's')
        self.screen.onkeypress(self.left, 'a')
        self.screen.onkeypress(self.right, 'd')
        self.screen.onkeypress(self.shoot, 'space')
        self.screen.listen()

    def forward(self):
        self.player.forward(5)
        self.screen.update()

    def backwards(self):
        self.player.back(5)
        self.screen.update()

    def left(self):
        self.player.left(6)
        self.screen.update()

    def right(self):
        self.player.right(6)
        self.screen.update()

    def shoot(self):
        if not self.bulletShot:
            self.bullet.setposition(self.player.position())
            self.bullet.setheading(self.player.heading())
            self.bullet.showturtle()
            self.bulletShot = True

            self.screen.update()

    def move_enemy(self):
        x = randint(-300, 300)
        y = randint(-300, 300)

        self.enemy.goto(x, y)

        self.screen.update()

    def play(self):
        if self.startTime == -1:
            self.startTime = time.time()

        if self.bulletShot:
            self.bullet.forward(1)

            x, y = self.bullet.position()

            if not(-300 <= x <= 300 and -300 <= y <= 300):
                self.bullet.hideturtle()
                self.bulletShot = False
            elif self.bullet.distance(self.enemy.pos()) < 10:
                self.bullet.hideturtle()
                self.bulletShot = False
                self.move_enemy()
                self.startTime = time.time()

            self.screen.update()

        if time.time() - self.startTime > 20:
            self.player.write('You loose!')
            self.screen.update()
        else:
            self.screen.ontimer(self.play, 10)

screen = Screen()

game = Game()

game.play()

screen.mainloop()

Все еще немного сыро но должно быть играбельным У вас был self.scr.update() звонок в исходном коде, но без первоначального звонка на tracer() он ничего не делает. Здесь мы используем tracer() и update() для ускорения и сглаживания движения путем ручного управления всеми обновлениями экрана.

...