Slow python turtle program - python

I was trying to make this snake game (no food yet) by using turtle. At length of 1 it still fast but as it goes longer it runs slower and slower.
from turtle import Turtle, Screen
SIZE = 500
GRID_NUM = 20
GRID_SIZE = SIZE // GRID_NUM
screen = Screen()
screen.setup(SIZE, SIZE)
screen.bgcolor('black')
screen.setworldcoordinates(10, 8, SIZE + 2, SIZE)
class Snake:
def __init__(self):
self.head = init_turtle()
self.head.setpos((GRID_SIZE // 2 + GRID_SIZE * 9, GRID_SIZE // 2 + GRID_SIZE * 10))
self.body = []
self.direction = 0 # 0 = left, 1 = up, 2 = right, 3 = down
self.speed = 100 * len(self.body) if len(self.body) > 0 else 100
def levelup(self):
if len(self.body) == 0:
self.body.append(self.head.clone())
else:
self.body.append(self.body[len(self.body) - 1].clone())
def update(self):
for i in range(len(self.body) - 1, -1 , -1):
if i == 0:
self.body[i].setpos(self.head.pos())
else:
self.body[i].setpos(self.body[i - 1].pos())
def init_turtle():
turtle = Turtle()
turtle.shape('square')
turtle.shapesize(1.25)
turtle.color('red')
turtle.pencolor('#404040')
turtle.speed('fastest')
turtle.up()
return turtle
def init_border():
def border():
turtle = init_turtle()
for _ in range(4):
turtle.down()
turtle.forward(SIZE)
turtle.left(90)
yield(0)
turtle.penup()
turtle.hideturtle()
def horizontal():
turtle = init_turtle()
for x in range(GRID_SIZE, SIZE, GRID_SIZE):
turtle.goto(x, 0)
turtle.pendown()
turtle.goto(x, SIZE)
turtle.penup()
yield(0)
turtle.hideturtle()
def vertical():
turtle = init_turtle()
for y in range(GRID_SIZE, SIZE, GRID_SIZE):
turtle.goto(0, y)
turtle.pendown()
turtle.goto(SIZE, y)
turtle.penup()
yield(0)
turtle.hideturtle()
generator1 = border()
generator2 = horizontal()
generator3 = vertical()
while(next(generator1, 1) + next(generator2, 1) + next(generator3, 1) < 3):
pass
def start_game():
snake = Snake()
def pop():
snake.body.pop()
def right():
snake.direction = 0
def up():
snake.direction = 1
def left():
snake.direction = 2
def down():
snake.direction = 3
def exit():
screen.bye()
screen.onkey(pop, 'q')
screen.onkey(left, 'Left')
screen.onkey(up, 'Up')
screen.onkey(right, 'Right')
screen.onkey(down, 'Down')
screen.onkey(exit, 'Escape')
screen.onkey(snake.levelup, 'Return')
screen.listen()
while True:
snake.update()
snake.head.setheading(snake.direction * 90)
snake.head.forward(GRID_SIZE)
print('snake', snake.head.pos())
init_border()
start_game()
screen.mainloop()
At first i think the cause of the problem was defines a lot of function but i don't know. Also i am new to python so i don't know any kind of optimizing methods.
Any ideas to optimize this program?

We can speed up long snakes by doing the drawing off screen and sending explicit updates. Below is a rework of your code that does just that and includes a temporary patch to make the snake move in a square so you can just hit to see how much the snake is affected by additional body segments:
from turtle import Turtle, Screen
SIZE = 525
GRID_NUM = 20
GRID_SIZE = SIZE // GRID_NUM
RIGHT, UP, LEFT, DOWN = range(4)
class Snake:
def __init__(self):
self.head = init_turtle()
self.head.setpos(GRID_NUM//2, GRID_NUM//2)
self.direction = LEFT
self.body = []
def levelup(self):
if self.body:
self.body.append(self.body[-1].clone())
else:
self.body.append(self.head.clone())
def update(self):
for i in range(len(self.body) - 1, -1, -1):
if i == 0:
self.body[i].setposition(self.head.position())
else:
self.body[i].setposition(self.body[i - 1].position())
def init_turtle():
turtle = Turtle()
turtle.shape('square')
print(GRID_SIZE)
turtle.shapesize((GRID_SIZE - 1) / 20)
turtle.color('#404040', 'red')
turtle.speed('fastest')
turtle.penup()
return turtle
def init_border():
def border():
turtle = init_turtle()
turtle.goto(-0.5, -0.5)
for _ in range(4):
turtle.pendown()
turtle.forward(GRID_NUM)
turtle.left(90)
turtle.penup()
turtle.hideturtle()
def vertical():
turtle = init_turtle()
for x in range(GRID_NUM):
turtle.goto(x - 0.5, -0.5)
turtle.pendown()
turtle.goto(x - 0.5, GRID_NUM - 0.5)
turtle.penup()
yield 0
turtle.hideturtle()
def horizontal():
turtle = init_turtle()
for y in range(GRID_NUM):
turtle.goto(-0.5, y + 0.5)
turtle.pendown()
turtle.goto(GRID_NUM - 0.5, y + 0.5)
turtle.penup()
yield 0
turtle.hideturtle()
border()
generator1 = horizontal()
generator2 = vertical()
while next(generator1, 1) + next(generator2, 1) < 2:
pass
def start_game():
snake = Snake()
def right():
snake.direction = RIGHT
def up():
snake.direction = UP
def left():
snake.direction = LEFT
def down():
snake.direction = DOWN
screen.onkey(snake.body.pop, 'q')
screen.onkey(left, 'Left')
screen.onkey(up, 'Up')
screen.onkey(right, 'Right')
screen.onkey(down, 'Down')
screen.onkey(screen.bye, 'Escape')
screen.onkey(snake.levelup, 'Return')
screen.listen()
while True:
snake.update()
snake.head.setheading(snake.direction * 90)
snake.head.forward(1)
# Run snake around in a square for testing purposes
x, y = snake.head.position()
if round(x) == 1 and snake.direction == LEFT:
up()
elif round(y) == GRID_NUM - 2 and snake.direction == UP:
right()
elif round(x) == GRID_NUM - 2 and snake.direction == RIGHT:
down()
elif round(y) == 1 and snake.direction == DOWN:
left()
screen.update()
screen = Screen()
screen.setup(SIZE, SIZE)
screen.bgcolor('black')
screen.setworldcoordinates(-0.75, -0.75, GRID_NUM + 0.25, GRID_NUM + 0.25)
init_border()
screen.tracer(False)
start_game()
screen.mainloop() # never reached!
I'd recommend both approaches as the main loop will only get more complicated (slower) as you add food and border detection.
I changed your coordinate system to make it snake centric. That is, forward(1) moves one square on the grid rather than having to do the math. If you're going to mess with the coordinates anyway, why not tweak them to your best advantage.

Related

I am developing snake game, I write few code line , but speed of snake is to fast, I want to slow down the speed to normal, How to do that? In python

In python
import time
from turtle import Turtle, Screen
# screen height and width
height = 600
width = 600
# snake initial positinn
x_coordinate = 0
y_coordinate = 0
game_on = True
screen = Screen()
screen.bgcolor("black")
screen.setup(height=height, width=width)
screen.title("Snake Game")
full_snake = []
screen.tracer(0)
# create a snake 3X3
for _ in range(3):
snake = Turtle("square")
snake.color("white")
snake.penup()
snake.goto(x_coordinate, y_coordinate)
x_coordinate -= 20
full_snake.append(snake)
snake_head = full_snake[0]
# function to operate the snake
def up():
if snake_head.heading() != 270:
snake_head.setheading(90)
def down():
if snake_head.heading() != 90:
snake_head.setheading(270)
def right():
if snake_head.heading() != 180:
snake_head.setheading(0)
def left():
if snake_head.heading() != 0:
snake_head.setheading(180)
screen.listen()
screen.onkey(up, "w")
screen.onkey(down, "s")
screen.onkey(right, "d")
screen.onkey(left, "a")
# function for snakes part to attached
def attached():
for i in range(len(full_snake) - 1, 0, -1):
new_x = full_snake[i - 1].xcor()
new_y = full_snake[i - 1].ycor()
full_snake[i].goto(new_x, new_y)
snake_head.fd(20)
# to move the snake
while game_on:
snake_head.speed(1)
screen.update()
time.sleep(0.1)
for snake in full_snake:
attached()
screen.exitonclick()
in this code snake speed is fast, I want to slow down to normal where I can placed speed() method or any method
Turtle module from python
expected output : speed of snake to be normal without detaching other two blocks
.................................................................................................................................................................................................................................................................................................................................
You can try the ontimer() method instead to control the snake movement. I modified your code a bit. You can check if the snake hits the wall too and set game_on to false in the move_snake function.
import time
from turtle import Turtle, Screen
# screen height and width
height = 600
width = 600
# snake initial position
x_coordinate = 0
y_coordinate = 0
game_on = True
screen = Screen()
screen.bgcolor("black")
screen.setup(height=height, width=width)
screen.title("Snake Game")
full_snake = []
screen.tracer(0)
# create a snake 3X3
for _ in range(3):
snake = Turtle("square")
snake.color("white")
snake.penup()
snake.goto(x_coordinate, y_coordinate)
x_coordinate -= 20
full_snake.append(snake)
snake_head = full_snake[0]
# function to operate the snake
def up():
if snake_head.heading() != 270:
snake_head.setheading(90)
def down():
if snake_head.heading() != 90:
snake_head.setheading(270)
def right():
if snake_head.heading() != 180:
snake_head.setheading(0)
def left():
if snake_head.heading() != 0:
snake_head.setheading(180)
screen.listen()
screen.onkey(up, "w")
screen.onkey(down, "s")
screen.onkey(right, "d")
screen.onkey(left, "a")
# function for snake parts to attached
def attached():
for i in range(len(full_snake) - 1, 0, -1):
new_x = full_snake[i - 1].xcor()
new_y = full_snake[i - 1].ycor()
full_snake[i].goto(new_x, new_y)
snake_head.fd(20)
# New function to move the snake
def move_snake():
attached()
screen.update()
# updated the height and width variables to fit the actual screen size (useful when screen is resized)
height = screen.window_height()
width = screen.window_width()
# check if the snake head hits the wall (19 or 20 pixels away looks fine but can be ajusted) then set game_on to false and stop the function execution
if snake_head.xcor() >= width/2 - 20 or snake_head.xcor() <= -width/2 + 19 or snake_head.ycor() >= height/2 - 19 or snake_head.ycor() <= -height/2 + 20:
game_on = False
return
# timer to recursively call the move_snake function every 500 milliseconds
screen.ontimer(move_snake, 500) # adapt to your desired speed (the lower the faster)
# start moving the snake
move_snake()
screen.exitonclick()

How to limit the amount of times a button is pressed

I am trying to make a game where you can shoot bullets to kill emojis. However, i can't manage to figure out how to stop spamming the space key to shoot bullets. If you keep on spamming, the game would be too easy. I am not exactly sure if what command I should use. Please help! thanks!
Here is my code:
# 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()
You can use a threaded timer to prevent the method to be called everytime you click the button, and just two attributes in your SpaceShip class.
Everytime the method fireBullet is called, a check is made on the variable can_shoot. If it's true, the bullet is spawned like you did and then a timer runs (with a thread, for not blocking the main flow) that just put can_shoot to False, sleep for any amount of ms you want, and then put can_shoot to True and the method is callable again.
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()
We don't need to introduce time nor threading to solve this. We can use turtle's own timer events to control the rate of fire:
def fire():
screen.onkey(None, 'space')
ship.fireBullet()
screen.ontimer(lambda: screen.onkey(fire, 'space'), 250)
Here I've limited the rate of fire to 4 rounds per second. (250 / 1000 milliseconds.) Adjust as you see fit. Below is a rework of your program with this modification as well as other fixes and style tweaks:
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()
Something to consider is that turtles are global entities that don't get garbage collected. So, you might want to collect your spent bullets in a list to reuse, only creating new ones when you need them.

Ball bounce in pong

I have written some code but can't get the ball to bounce on the floor or the ceiling naturally. Please help!
I've already tried getting the ball heading with ball_heading = ball.heading, but that didn't work
#Python 3.6.3
from turtle import *
import math
import random
#Screen Setup
bgcolor("black")
wn = Screen()
wn.title("Pong")
#Drawing Border
bd = Turtle()
bd.pencolor("white")
bd.pensize(3)
bd.hideturtle()
bd.penup()
bd.setposition(-400, -300)
bd.pendown()
bd.speed(0)
bd.pendown()
for line in range(2):
bd.forward(800)
bd.left(90)
bd.forward(600)
bd.left(90)
bd.penup()
bd.setposition(0, 300)
bd.setheading(270)
bd.pendown()
for dash in range(30):
bd.forward(10)
bd.penup()
bd.forward(10)
bd.pendown()
#Creating Paddles
#Paddle 1
player1 = Turtle()
player1.color("white")
player1.shape("square")
player1.shapesize(stretch_wid=5, stretch_len=1)
player1.penup()
player1.setposition(-370, 0)
#Paddle 2
player2 = Turtle()
player2.color("white")
player2.shape("square")
player2.shapesize(stretch_wid=5, stretch_len=1)
player2.penup()
player2.setposition(370, 0)
#Creating the ball
ball = Turtle()
ball.color("white")
ball.shape("square")
ball.speed(0)
ball.penup()
ball.setposition(0, 0)
ball.setheading(random.randint(0, 360))
#Moving the player
playerspeed = 15
#p1
def move_up():
y = player1.ycor()
y += playerspeed
#Setting the boundries
if y > 245:
y = 245
player1.sety(y)
def move_down():
y = player1.ycor()
y -= playerspeed
#Setting the boundries
if y < -245:
y = -245
player1.sety(y)
#p2
def move_up2():
y = player2.ycor()
y += playerspeed
#Setting the boundries
if y > 245:
y = 245
player2.sety(y)
def move_down2():
y = player2.ycor()
y -= playerspeed
#Setting the boundries
if y < -245:
y = -245
player2.sety(y)
#Ball movement
def ball_fd():
ball.forward(3)
#Ball ceiling / floor bounce
def ball_bounce():
by = ball.ycor()
if by > 279:
by = 279
ball.sety(by)
bx = ball.ycor()
if bx < -279:
bx = -279
ball.setx(bx)
#binding
listen()
onkey(move_up, "Up")
onkey(move_down, "Down")
onkey(move_up2, "w")
onkey(move_down2, "s")
#Making the ball move / main game loop
while True:
ball_fd()
ball_bounce()
Sorry the code is kind of long, but feel free to copy + paste it into IDLE or whatever.
Thank you
You didn't turn the ball when it hit the floor or ceiling.
while True:
ball.fd(3)
by = ball.ycor()
if abs(by) > 279:
ball.setheading(-ball.heading())

When I make 2 turtles collide, Python freezes and crashes

import turtle
import os
import math
ms = turtle.Screen()
ms.bgcolor("grey")
ms.title("ok")
ground = turtle.Turtle()
ground.speed(0)
ground.color("black")
ground.penup()
ground.setposition(-500, -500)
ground.shape("square")
ground.shapesize(20, 200)
player = turtle.Turtle()
player.shape("square")
player.color("blue")
player.penup()
player.speed(0)
player.setposition(-450, -280)
playerspeed = 15
prop = turtle.Turtle()
prop.speed(0)
prop.shape("square")
prop.penup()
prop.color("red")
prop.setposition(-200, -50)
def move_left():
x = player.xcor()
x-= playerspeed
if x <-460:
x = - 460
player.setx(x)
def move_right():
x = player.xcor()
x+= playerspeed
if x >460:
x = 460
player.setx(x)
def move_down():
y = player.ycor()
y-= playerspeed
if y <-290:
y = - 290
player.sety(y)
def move_up():
y = player.ycor()
y+= playerspeed
if y >290:
y = 290
player.sety(y)
turtle.listen()
turtle.onkey(move_left, "Left")
turtle.onkey(move_right, "Right")
turtle.onkey(move_up, "Up")
turtle.onkey(move_down, "Down")
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor() - t2.xcor(), 2) + math.pow(t1.ycor() - t2.ycor(), 2))
if distance < 10:
return True
else:
return False
while True:
if isCollision(player, prop):
player.setposition(100, 100)
If I change the distance to > 10
it works but not as I want it to.
I want it to change the position of the player when prop and player are 10 pixels or less away from each other.
I've tried most things I know about, but I am still new to Python, or any programming language.
But I don't know what would cause it to freeze and crash -- any help is appreciated.
The primary issue I see with your code is while True: which shouldn't be used in an event-based environment. By creating a tight loop, you can keep events (key pressed, cursor movements, window closing) from being processed.
Below is a rework of your code using a timer event instead of while True:. I've also parameterized it as every turtle user sees a different size default window based on the dimensions of their screen. So you either need to use setup() to force a fixed size window or have your code adust to the window size. Now it adjusts to the window size. I've also made prop move to a random location upon collision, just to make the game more fun for me to play. And I've tossed your distance code in favor of turtle's own implementation:
from turtle import Screen, Turtle, mainloop
from random import randint
PLAYER_SPEED = 15
GROUND_HEIGHT = 100
PROXIMITY = 10
CURSOR_SIZE = 20
def move_left():
x = player.xcor() - PLAYER_SPEED
if x < CURSOR_SIZE - width/2:
x = CURSOR_SIZE - width/2
player.setx(x)
def move_right():
x = player.xcor() + PLAYER_SPEED
if x > width/2 - CURSOR_SIZE:
x = width/2 - CURSOR_SIZE
player.setx(x)
def move_down():
y = player.ycor() - PLAYER_SPEED
if y < CURSOR_SIZE/2 + GROUND_HEIGHT - height/2:
y = CURSOR_SIZE/2 + GROUND_HEIGHT - height/2
player.sety(y)
def move_up():
y = player.ycor() + PLAYER_SPEED
if y > height/2 - CURSOR_SIZE:
y = height/2 - CURSOR_SIZE
player.sety(y)
def isCollision(t1, t2):
return t1.distance(t2) < PROXIMITY
def random_position():
x = randint(CURSOR_SIZE - width//2, width//2 - CURSOR_SIZE)
y = randint(CURSOR_SIZE + GROUND_HEIGHT - height//2, height//2 - CURSOR_SIZE)
return x, y
def check():
if isCollision(player, prop):
prop.setposition(random_position())
ms.ontimer(check, 100)
ms = Screen()
ms.bgcolor('grey')
ms.title("ok")
width, height = ms.window_width(), ms.window_height()
ground = Turtle('square')
ground.shapesize(GROUND_HEIGHT / CURSOR_SIZE, width / CURSOR_SIZE)
ground.speed('fastest')
ground.penup()
ground.sety(GROUND_HEIGHT/2 - height/2)
player = Turtle('square')
player.speed('fastest')
player.color('blue')
player.penup()
player.setposition(CURSOR_SIZE/2 - width/2, GROUND_HEIGHT + CURSOR_SIZE/2 - height/2)
prop = Turtle('square')
prop.speed('fastest')
prop.color('red')
prop.penup()
prop.setposition(random_position())
ms.onkey(move_left, 'Left')
ms.onkey(move_right, 'Right')
ms.onkey(move_up, 'Up')
ms.onkey(move_down, 'Down')
ms.listen()
check()
mainloop()

Making snake in Python, can't get bodies to follow head etc

I wanted to make a snake game in turtle but I can't seem to get the tail segments to follow the leader. As if to say I can't get the first body part to follow the head, and then the second body part to follow the first body, etc.
I tried using what maths I have but I can't seem to get it to calculate where the head just was or where the body in front of it just was.
here is my code:
#libraries
import turtle
import random
import math
#screen
the_screen = turtle.Screen()
the_screen.bgcolor("lightgreen")
the_screen.title("Catapillar")
#border
border_writer = turtle.Turtle()
border_writer.speed(0)
border_writer.color("green")
border_writer.penup()
border_writer.setposition(-275, -275)
border_writer.pendown()
border_writer.pensize(7)
for side in range(4):
border_writer.fd(550)
border_writer.lt(90)
border_writer.hideturtle()
#player
player = turtle.Turtle()
player.color("yellow")
player.shape("circle")
player.penup()
player.speed(0)
player.setposition(0,0)
player.setheading(0)
playerspeed = 2
#fruit
fruit = 1
fruit = turtle.Turtle()
fruit.color("red")
fruit.shape("circle")
fruit.penup()
fruit.speed(0)
fruit.shapesize(0.6, 0.6)
x = random.randint(-200, 200)
y = random.randint(100, 250)
fruit.setposition(x, y)
#moving and collision checker
def turnleft():
player.left(24.5)
def turnright():
player.right(24.5)
def increasespeed():
global playerspeed
playerspeed += 1
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(), 2) + math.pow(t1.ycor()-t2.ycor(), 2))
if distance < 24:
return True
else:
return False
#making the tail(s) and hiding them
tail1 = turtle.Turtle()
tail1.hideturtle()
tail1.color("yellow")
tail1.shape("circle")
tail1.penup()
tail1.speed(0)
tail1.setposition(+700,700)
tail1.shapesize(0.6, 0.6)
tail1state = 'off'
#key presses
turtle.listen()
turtle.onkeypress(turnleft, "Left")
turtle.onkeypress(turnright, "Right")
turtle.onkeypress(increasespeed, "Up")
#main loop player always moves forward, out of bound set, reset fruit
#randomly when collided, create tail1...
while True:
player.forward(playerspeed)
#gameovers'
if (player.xcor() > 275) or (player.xcor() < -275):
playerspeed += 7
print("GAME OVER")
if (player.ycor() > 275) or (player.ycor() < -275):
playerspeed += 7
print("GAME OVER")
#collision check between fruit and head
if isCollision(player, fruit):
#resets the fruit, moves it randomly
fruit.hideturtle()
if tail1state == 'off':
uuu = player.xcor()
vvv = player.ycor()
tail1.setposition(uuu,vvv)
tail1.showturtle()
tail1state = 'on'
#reset the fruit
x = random.randint(-200, 200)
y = random.randint(-100, 250)
fruit.setposition(x, y)
fruit.showturtle()
#playerspeed +=1
If you have any idea on how you think I should approach it, please let me know what you think.
Thank you.
Since this comes up over and over (but effort to effect it is rarely shown) here's my minimal, generic, slithering around a screen effect that you should be able to adapt for your own purposes:
from turtle import Turtle, Screen
SNAKE_LENGTH = 10
SNAKE_SIZE = 15
WIDTH, HEIGHT = 375, 375
CURSOR_SIZE = 20
def slither():
segment = snake[-1].clone() if len(snake) < SNAKE_LENGTH else snake.pop(0)
screen.tracer(False) # segment.hideturtle()
segment.setposition(snake[-1].position())
segment.setheading(snake[-1].heading())
segment.forward(SNAKE_SIZE)
while not -WIDTH/2 < segment.xcor() < WIDTH/2 or not -HEIGHT/2 < segment.ycor() < HEIGHT/2:
segment.undo()
segment.right(95)
segment.forward(SNAKE_SIZE)
screen.tracer(True) # segment.showturtle()
snake.append(segment)
screen.ontimer(slither, 100)
boundary = Turtle(shape='square', visible=False)
boundary.shapesize(HEIGHT / CURSOR_SIZE, WIDTH / CURSOR_SIZE)
boundary.fillcolor("white")
boundary.stamp()
head = Turtle("circle")
head.shapesize(SNAKE_SIZE / CURSOR_SIZE)
head.penup()
snake = [head]
screen = Screen()
slither()
screen.exitonclick()

Categories