我正在尝试制作一个游戏,在其中您可以发射子弹杀死表情符号。但是,我无法弄清楚如何停止发送空格键来发射子弹。如果您继续发送垃圾邮件,那么游戏将变得非常简单。我不确定是否应该使用什么命令。请帮忙!谢谢!
这是我的代码:
# 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()
答案 0 :(得分:0)
您可以使用线程计时器防止每次单击按钮时调用该方法,并且只在SpaceShip
类中提供两个属性。
每次调用方法fireBullet
时,都会对变量can_shoot
进行检查。如果是真的,则像您一样生成子弹,然后运行计时器(使用线程,以防止阻塞主流程),该计时器将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()
答案 1 :(得分:0)
我们不需要引入 time 或 threading 即可解决此问题。我们可以使用乌龟自己的计时器事件来控制射速:
def fire():
screen.onkey(None, 'space')
ship.fireBullet()
screen.ontimer(lambda: screen.onkey(fire, 'space'), 250)
在这里,我将射速限制为每秒4发。 (250/1000毫秒。)根据需要进行调整。下面是对程序进行的修改,包括此修改以及其他修复和样式调整:
from turtle import Screen, Turtle
from random import random, randint, randrange, choice
from math import radians, sin as sine, cos as cosine
class Bullet(Turtle):
MAX_DISTANCE = 500
DELTA = 20
RADIUS = 4
def __init__(self, position, heading):
super().__init__(shape="bullet")
self.hideturtle()
self.penup()
self.goto(position)
self.setheading(heading)
self.color('yellow')
self.showturtle()
self.distance = 0
def move(self):
self.distance += self.DELTA
self.forward(self.DELTA)
if self.done():
self.reset()
def getRadius(self):
''' collision detection helper method '''
return self.RADIUS
def blowUp(self):
''' method that makes something go off the screen '''
self.hideturtle()
def done(self):
return self.distance >= self.MAX_DISTANCE
class Asteroid(Turtle):
def __init__(self, dx, dy, position, size, emoji):
super().__init__()
self.hideturtle()
self.penup()
self.goto(position)
self.color('lightgrey')
emoji = choice(emojis)
# screen.addshape(emoji) # for StackOverflow debugging
self.shape(emoji)
self.showturtle()
self.size = size
self.dx = dx
self.dy = dy
def move(self):
x, y = self.position()
# 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):
''' method that makes something go off the screen '''
self.hideturtle()
def getRadius(self):
return self.size * 10 - 5
class SpaceShip(Turtle):
RADIUS = 10
def __init__(self, screen, dx, dy, x, y):
super().__init__(shape='turtle')
self.hideturtle()
self.penup()
self.color("white")
self.goto(x, y)
self.showturtle()
self.dx = dx
self.dy = dy
self.screen = screen
self.bullets = []
def move(self):
x, y = self.position()
x = (self.dx + x - screenMinX) % (screenMaxX - screenMinX) + screenMinX
y = (self.dy + y - screenMinY) % (screenMaxY - screenMinY) + screenMinY
self.goto(x, y)
def powPow(self, asteroids):
''' logic for collision '''
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()
hit = True
if not bullet.done() and not hit:
dasBullets.append(bullet)
else:
bullet.blowUp()
self.bullets = dasBullets
def fireBullet(self):
bullet = Bullet(self.position(), self.heading())
self.bullets.append(bullet)
def fireEngine(self):
angle = self.heading() # how turtle moves
x = cosine(radians(angle))
y = sine(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
def getRadius(self):
return self.RADIUS
def turnLeft(self):
self.left(7)
def turnRight(self):
self.right(7)
def intersect(object1, object2):
''' collision detection '''
return object1.distance(object2) <= object1.getRadius() + object2.getRadius()
def play():
# Tell all the elements of the game to move
ship.move()
gameover = False
for asteroid in asteroids:
r = randint(0, 1)
if r == 1:
asteroid.right(50)
else:
asteroid.left(20)
asteroid.move()
if intersect(ship, asteroid):
turtle.write("You Got Killed :(", font=("Verdana", 25), align="center")
gameover = True
ship.powPow(asteroids)
screen.update()
if not asteroids:
turtle.color('green')
turtle.write("You Killed the Emojis!!", font=("Arial", 30), align="center")
if not gameover:
screen.ontimer(play, 30)
# controls
def fire():
screen.onkey(None, 'space')
ship.fireBullet()
screen.ontimer(lambda: screen.onkey(fire, 'space'), 250)
# create a link to the object (creates the environment)
speed1 = 1.3
amountOfEmojis = 11
# establish important data for screen environment
screen = Screen()
screen.bgcolor("black")
# 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
screen.setworldcoordinates(screenMinX, screenMinY, screenMaxX, screenMaxY)
# 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)))
screen.tracer(0)
# turtle setup
turtle = Turtle()
turtle.hideturtle()
turtle.penup()
turtle.goto(0, screenMaxY - 50)
turtle.color('white')
turtle.write("Welcome to Emoji Run!", align="center", font=("Courier New", 26))
turtle.goto(0, screenMaxY - 70)
turtle.write("Use the arrow keys to move, and space to fire. The point of the game is to kill the emojis.", align="center", font=("Courier New", 13))
turtle.goto(0, 0)
turtle.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"
]
emojis = ['rock1', 'rock2', 'rock3'] # for StackOverflow debugging purposes
# 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, dy = random() * 6 - 3, random() * 6 - 3
x = randrange(10) * (screenMaxX - screenMinX) + screenMinX
y = random() * (screenMaxY - screenMinY) + screenMinY
asteroid = Asteroid(dx, dy, (x, y), randint(1, 3), emojis)
asteroids.append(asteroid)
screen.onkey(ship.turnLeft, 'Left')
screen.onkey(ship.turnRight, 'Right')
screen.onkey(ship.fireEngine, 'Up')
screen.onkey(fire, 'space')
screen.listen()
screen.update()
play()
screen.mainloop()
需要考虑的是,海龟是不会收集垃圾的全局实体。因此,您可能希望将用过的子弹收集在列表中以供重复使用,仅在需要时创建新子弹。