python - 如何限制按钮按下的次数

标签 python turtle-graphics

我正在尝试制作一款可以用子弹杀死表情符号的游戏。但是,我无法弄清楚如何停止发送空格键来射击子弹。如果你继续发垃圾邮件,这个游戏就太简单了。我不太确定我应该使用什么命令。请帮忙!谢谢!

这是我的代码:

# import everything from turtle
from turtle import *
import random
import math
#create a link to the object (creates the environment)
screen = Screen()
speed1 = 1.3
ht()
amountOfEmojis = 11
#set a boundary for screen, if touches end, goes to the other side
screenMinX = -screen.window_width()/2
screenMinY = -screen.window_height()/2
screenMaxX = screen.window_width()/2
screenMaxY = screen.window_height()/2
#establish important data for screen environment
screen.setworldcoordinates(screenMinX,screenMinY,screenMaxX,screenMaxY)
screen.bgcolor("black")
#turtle setup
penup()
ht()
speed(0)
goto(0, screenMaxY - 50)
color('white')
write("Welcome to Emoji Run!", align="center", font=("Courier New",26))
goto(0, screenMaxY - 70)
write("Use the arrow keys to move and space to fire. The point of the game is to kill the emojis", align="center")
goto(0, 0)
color("red")

emojis = ["Poop_Emoji_7b204f05-eec6-4496-91b1-351acc03d2c7_grande.png", "1200px-Noto_Emoji_KitKat_263a.svg.png", 
"annoyningface.png", "Emoji_Icon_-_Sunglasses_cool_emoji_large.png"]


class Bullet(Turtle):
  #constructor, object for a class, pass in information
  def __init__(self,screen,x,y,heading):
    #create a bullet
    Turtle.__init__(self)#clones bullet
    self.speed(0)
    self.penup()
    self.goto(x,y)
    self.seth(heading)#pointing to itself
    self.screen = screen 
    self.color('yellow')
    self.max_distance = 500
    self.distance = 0
    self.delta = 20
    self.shape("bullet")
  #logic to move bullet
  def move(self):
    self.distance = self.distance + self.delta#how fast it's going to move
    self.forward(self.delta)
    if self.done():
      self.reset()

  def getRadius(self):
    return 4#collision detection helper function

  def blowUp(self):
    self.goto(-300,0)#function that makes something go off the screen 

  def done(self):
    return self.distance >= self.max_distance # append to list

class Asteroid(Turtle):
  def __init__(self,screen,dx,dy,x,y,size,emoji):#spawn asteroid randomly
    Turtle.__init__(self)#clone itself
    self.speed(0)
    self.penup()
    self.goto(x,y)
    self.color('lightgrey')
    self.size = size
    self.screen = screen
    self.dx = dx
    self.dy = dy
    r = random.randint(0, len(emoji) - 1)
    screen.addshape(emojis[r])
    self.shape(emojis[r])
    #self.shape("rock" + str(size)) #sets size and shape for asteroid

  def getSize(self):#part of collision detection
    return self.size
  #getter and setter functions
  def getDX(self):
    return self.dx

  def getDY(self):
    return self.dy

  def setDX(self,dx):
    self.dx = dx

  def setDY(self,dy):
    self.dy = dy

  def move(self):
    x = self.xcor()
    y = self.ycor()
#if on edge of screen. go to opposite side
    x = (self.dx + x - screenMinX) % (screenMaxX - screenMinX) + screenMinX
    y = (self.dy + y - screenMinY) % (screenMaxY - screenMinY) + screenMinY

    self.goto(x,y)

  def blowUp(self):
    self.goto(-300,0)#function that makes something go off the screen 

  def getRadius(self):
    return self.size * 10 - 5

class SpaceShip(Turtle):
  def __init__(self,screen,dx,dy,x,y):
    Turtle.__init__(self)
    self.speed(0)
    self.penup()
    self.color("white")
    self.goto(x,y)
    self.dx = dx
    self.dy = dy
    self.screen = screen   
    self.bullets = []
    self.shape("turtle")

  def move(self):
    x = self.xcor()
    y = self.ycor()
    x = (self.dx + x - screenMinX) % (screenMaxX - screenMinX) + screenMinX
    y = (self.dy + y - screenMinY) % (screenMaxY - screenMinY) + screenMinY

    self.goto(x,y)
  #logic for collision
  def powPow(self, asteroids):
    dasBullets = []
    for bullet in self.bullets:
      bullet.move()
      hit = False
      for asteroid in asteroids:
        if intersect(asteroid, bullet):#counts every asteroid to see if it hits
          asteroids.remove(asteroid)
          asteroid.blowUp()
          bullet.blowUp()
          hit = True
      if (not bullet.done() and not hit):
        dasBullets.append(bullet)


    self.bullets = dasBullets

  def fireBullet(self):
    self.bullets.append(Bullet(self.screen, self.xcor(), self.ycor(), self.heading()))

  def fireEngine(self):#how turtle moves
    angle = self.heading()
    x = math.cos(math.radians(angle))
    y = math.sin(math.radians(angle))

    self.dx = self.dx + x#how it rotates
    self.dy = self.dy + y
    self.dx = self.dx / speed1
    self.dy = self.dy / speed1

  #extra function
  def turnTowards(self,x,y):
    if x < self.xcor():
      self.left(7)
    if x > self.xcor():
      self.right(7)

  def getRadius(self):
      return 10

  def getDX(self):
      return self.dx

  def getDY(self):
      return self.dy

#collision detection
def intersect(object1,object2):
  dist = math.sqrt((object1.xcor() - object2.xcor())**2 + (object1.ycor() - object2.ycor())**2)

  radius1 = object1.getRadius()
  radius2 = object2.getRadius()

  # The following if statement could be written as 
  # return dist <= radius1+radius2
  if dist <= radius1+radius2:
      return True
  else:
      return False

#adds object to screen
screen.register_shape("rock3",((-20, -16),(-21, 0), (-20,18),(0,27),(17,15),(25,0),(16,-15),(0,-21)))
screen.register_shape("rock2",((-15, -10),(-16, 0), (-13,12),(0,19),(12,10),(20,0),(12,-10),(0,-13)))
screen.register_shape("rock1",((-10,-5),(-12,0),(-8,8),(0,13),(8,6),(14,0),(12,0),(8,-6),(0,-7)))
screen.register_shape("ship",((-10,-10),(0,-5),(10,-10),(0,10)))
screen.register_shape("bullet",((-2,-4),(-2,4),(2,4),(2,-4)))
#ship spawn exactly the middle everytime
ship = SpaceShip(screen,0,0,(screenMaxX-screenMinX)/2+screenMinX,(screenMaxY-screenMinY)/2 + screenMinY)

#randomize where they spawn
asteroids = []
for k in range(amountOfEmojis):
  dx = random.random() * 6 - 3
  dy = random.random() * 6 - 3
  x = random.randrange(10) * (screenMaxX - screenMinX) + screenMinX
  y = random.random() * (screenMaxY - screenMinY) + screenMinY
  asteroid = Asteroid(screen,dx,dy,x,y,random.randint(1,3), emojis)
  asteroids.append(asteroid)

def play():
  # Tell all the elements of the game to move
  ship.move()

  gameover = False
  for asteroid in asteroids:
    r = random.randint(0, 1)
    if r == 1:
      asteroid.right(50)
    else:
      asteroid.left(20)
    asteroid.move()
    if intersect(ship,asteroid):
      write("You Got Killed :(",font=("Verdana",25),align="center")
      gameover = True

  ship.powPow(asteroids)

  screen.update()

  if not asteroids:
    color('green')
    write("You Killed the Emojis!!",font=("Arial",30),align="center")
    ht()

  if not gameover:
    screen.ontimer(play, 30)

bullets = []
#controls
def turnLeft():
  ship.left(7)

def turnRight():
  ship.right(7)

def go():
  ship.fireEngine()

def fire():         
  ship.fireBullet()

ht()

screen.tracer(0);

screen.onkey(turnLeft, 'left')
screen.onkey(turnRight, 'right')
screen.onkey(go, 'up')
screen.onkey(fire, 'space')
screen.listen()

play()

最佳答案

您可以使用线程计时器来防止每次单击按钮时调用该方法,并且只需使用 SpaceShip 类中的两个属性即可。

每次调用方法 fireBullet 时,都会对变量 can_shoot 进行检查。如果是 true,则像您一样生成子弹,然后运行一个计时器(使用一个线程,以免阻塞主流程),将 can_shoot 设置为 False,休眠您想要的任意毫秒数,然后将 can_shoot 设置为 True,该方法就可以再次调用。

import time
import threading

def __init__(self):
    # your stuff
    self.wait_between_fire = 300 / 1000  # amount of ms / 1000 to convert in seconds
    self.can_shoot = True

class TimerThread(threading.Thread):
    def __init__(self, ref):
        threading.Thread.__init__(self)
        self.ref = ref

    def run():
        self.ref.can_shoot = False
        time.sleep(ref.wait_between_fire)
        self.ref.can_shoot = True

def set_timer(self):
    TimerThread(self).start()

def fireBullet(self):
    if self.can_shoot:
        self.bullets.append(Bullet(self.screen, self.xcor(), self.ycor(), self.heading()))
        self.set_timer()

关于python - 如何限制按钮按下的次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56819563/

相关文章:

python - 当使用 Dill 和与 Pickle 配合良好的代码时,出现 "pickle exhausted before end of frame"

java - 如何从 Java 等非 python 语言调用 celery 任务延迟函数?

python-2.7 - 如何仅在Python turtle 中绘制半圆

python - 如何在 Turtle 中填充这些方 block - Python

Python turtle.setup() 将 Canvas 截断为屏幕大小——如何避免这种情况?

python - 按当前日期过滤 aws ec2 快照

python - 如何在 FastAPI 中验证请求正文?

python - tf.reshape() 在内部是如何工作的?

python - 使用 Python Turtle 进行多线程处理

python - 用 python Turtle 图形绘制 X