Keeping the turtle inside a square, no output and no errors - python

I wanted turtle not to go out of square
the window comes out and no error but loading keeps and if I click the window, it shuts down.
x, y is turtle's location.
D is to show weather or not turtle is inside square and on line(?).
a is nothing
direction changes
speed changes
location check and change
if turtle's in line, it go along boundary.
import turtle
import msvcrt
turtle.setup(100, 100, 0, 0)
t = turtle.Turtle()
D = 0
a = 1
while True:
if msvcrt.kbhit():
c = msvcrt.getch().decode('UTF - 8')
if c == 'j': # turn left
t.left(10)
if c == 'k':
t.right(10)
if c == 'a':# speed change
a += 1
if a > 10: # speed limitation
a = 10
if c == 'z':
a += -1
if a < 0:
a = 0
#---------------------------------------
x = t.xcor() # turtle's location
y = t.ycor()
if x > 100: # if go out of square, go back to the square
t.setx(100)
if x < -100:
t.setx(-100)
if y > 100:
t.sety(100)
if y < -100:
t.sety(-100)
#---------------------------------------
x = t.xcor() # turtle's location
y = t.ycor()
h = t.heading() # turtle's direction
#---------------------------------------
if - 100 < x < 100 and -100 < y < 100:
D = 0 # if it's in the square, D = 0
elif x == 100 and -100 < y < 100: # if it's in ~
if 0 <= d <= 90: # direction changes
t.setheading(90) # direction change to 90 degrees
D = 1 # D = 1
elif 270 <= d < 360:
t.setheading(270)
D = 2
elif x == -100 and -100 < y < 100:
if 90 <= d < 180:
t.setheading(90)
D = 2
elif 180 <= d <= 270:
t.setheading(270)
D = 1
elif y == 100 and -100 < x < 100:
if 0 <= d < 90:
t.setheading(0)
D = 2
elif 90 <= d <= 180:
t.setheading(180)
D = 1
elif y == -100 and -100 < x < 100:
if 180 <= d < 270:
t.setheading(180)
D = 2
elif 270 <= d < 360:
t.setheading(0)
D = 1
elif D == 1:
t.left(90)
elif D == 2:
t.right(90)

This code is a mess. First, by setting your window size to 100 x 100 and then moving your turtle between -100 and 100 in both dimensions, only 1/4 of your field of play is visible! Why use the msvcrt module when turtle has perfectly good keyboard events built in? As far as I can tell, your code checks and corrects the turtle's position but never actually moves it! And you have a while True: loop which has no place in an event-driven environment like turtle.
Let's start over with a simple example of motion within a square which can be manipulated via the keyboard:
from turtle import Screen, Turtle
def turn_left():
turtle.left(10)
def turn_right():
turtle.right(10)
def speed_up():
speed = turtle.speed() + 1
if speed > 10: # speed limitation
speed = 10
turtle.speed(speed)
def slow_down():
speed = turtle.speed() - 1
if speed < 1: # speed limitation
speed = 1
turtle.speed(speed)
def move():
# there are two different senses of 'speed' in play, we'll exploit
# both! I.e. as we move faster, we'll draw faster and vice versa
turtle.forward(turtle.speed())
# if we go out of square, go back into the square
if not -100 < turtle.xcor() < 100:
turtle.undo()
turtle.setheading(180 - turtle.heading())
elif not -100 < turtle.ycor() < 100:
turtle.undo()
turtle.setheading(360 - turtle.heading())
screen.ontimer(move, 100)
screen = Screen()
screen.setup(300, 300)
# show turtle's boundary
boundary = Turtle('square', visible=False)
boundary.color('pink')
boundary.shapesize(10)
boundary.stamp()
turtle = Turtle()
move()
screen.onkey(turn_left, 'j')
screen.onkey(turn_right, 'k')
screen.onkey(speed_up, 'a')
screen.onkey(slow_down, 'z')
screen.listen()
screen.mainloop()

Related

Trouble with detetcting where a player clicks

So I made a simple tracking game as a project, everything about the base works (clicking green squares for +1 point) but when I added a blue square that only sometimes appears it doesnt want to detect it when a player clicks on it.
import tkinter
canvas = tkinter.Canvas(width=500,height=500)
from random import *
canvas.pack()
def timer1():
canvas.delete("all")
global cx,cy,rn
rn = randrange(3)
cx = randrange(50,300)
cy = randrange(20,250)
cw = randrange(50,300)
cz = randrange(20,250)
canvas.create_rectangle(cx,cy,cx-size,cy+size,fill="green")
canvas.create_text(100,10,text="Score: ")
canvas.create_text(200,10,text=score)
if rn == 2:
canvas.create_rectangle(cw,cz,cw-size,cz+size,fill="blue")
if score < 100 and score > -10:
canvas.after(1000,timer1)
elif score == -10:
canvas.delete("all")
canvas.create_text(200,100,text="Wow you suck :/")
else:
canvas.delete("all")
canvas.create_text(200,100,text="Good job")
def click(cor):
global score
x = cor.x
y = cor.y
if cx > x > cx-size and cy < y < cy+size:
score = score + 1
else:
score = score -1
if cw > x > cw-size and cz < y < cz+size:
score = score + 5
canvas.bind("<Button-1>",click)
score = 0
cx = 0
cy = 0
cz = 0
cw = 0
rn = 0
size = 50
timer1()
You need to declare cw and cz as global variables inside timer1() as well.

How to set random movement direction of koning(ghost in pacman) and how to make the coins to disappear in pacman game using tKinter?

We are creating pacman in Python- tKinter(not in pygame) and the coins are not disappearing. I am not able to finish the program of random movement of koning(ghost).
It is supposed to change direction every 10 steps and not go out of the canvas. The coins are supposed to disappear after the pacman goes through the coin, it would disappear. The coins are supposed to be counted and be shown in the corner. After the 3 times the pacman meets the ghost, it would print ;Game over;.
sirka = 0
vyska = 0
koning_x = 0
koning_y = 0
```pome=coins
pome_x = 0
pome_y = 0
random_direction = random.randint(0,3)
counter = 10
def platne_pole (y, x) :
global sirka
global vyska
if (x > 0 and x < sirka - 1) and (y > 0 and y < vyska - 1):
return True
return False
def kmove (event):
global koning_x
global koning_y
global mapa
target_x = koning_x *cell_size
target_y = koning_y *cell_size
def posun (target_x, target_y, koning_smer):
if koning_smer == 0:
target_y -= 1
elif koning_smer == 1:
target_x += 1
elif koning_smer == 2:
target_y += 1
elif koning_smer == 3:
target_x == 1
return target_x, target_y
target_x, target_y = kmove(koning_x, koning_y, koning_smer)

Snake segments that "flow" rather than "snap" to the snake's head position

I am trying to make a snake game in python and I would like the segments of the snake to flow when the user presses the WASD keys rather than the segments snapping to the user's desired direction
import pygame
import random
import time
pygame.init()
win = pygame.display.set_mode((800,600))
pygame.display.set_caption("Pygame")
clock = pygame.time.Clock()
x = 30
y = 30
x2 = x
y2 = random.randrange(1,601-30)
vel = 2
run = True
facing = 0
direction = 0
text = pygame.font.SysFont('Times New Roman',30)
score = 0
segments = []
green = ((0,128,0))
white = ((255,255,255))
counting = 0
segmentTime = time.time()
class segmentClass():
def __init__(self,x,y,pos,color):
self.x = x
self.y = y
self.pos = pos
self.color = color
def draw(self,win):
pygame.draw.rect(win,(self.color),(self.x,self.y,30,30))
def gameOver():
global run
run = False
def segmentGrowth():
global x2
global y2
global score
global vel
global ammount
segments.append(segmentClass(x,y,len(segments)+1,green))
ammount = 0
x2 = random.randrange(1,801-30)
y2 = random.randrange(1,601-30)
score += 1
print(vel)
while run:
currentTime = time.time()
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
vel += (score*0.0001)
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
if direction != 1:
direction = 1
facing = -1
if keys[pygame.K_s]:
if direction != 1:
direction = 1
facing = 1
if keys[pygame.K_a]:
if direction != 0:
direction = 0
facing = -1
if keys[pygame.K_d]:
if direction != 0:
direction = 0
facing = 1
if direction == 1:
y += (vel*facing)
else:
x += (vel*facing)
if x > x2 and x < x2 + 30 or x + 30 > x2 and x + 30 < x2 + 30:
if y == y2:
segmentGrowth()
if y > y2 and y < y2 + 30 or y + 30 > y2 and y + 30 < y2 + 30:
segmentGrowth()
if y > y2 and y < y2 + 30 or y + 30 > y2 and y + 30 < y2 + 30:
if x == x2:
segmentGrowth()
if x > x2 and x < x2 + 30 or x + 30 > x2 and x + 30 < x2 + 30:
segmentGrowth()
if x > 800-30 or y > 600-30 or x < 0 or y < 0:
gameOver()
win.fill((0,0,0))
for segment in segments:
if direction == 0: #X value
if facing == 1: #Right
segment.x = x - (35 * segment.pos)
segment.y = y
else: #Left
segment.x = x + (35 * segment.pos)
segment.y = y
else: #Y value
if facing == -1: #Up
segment.y = y + (35 * segment.pos)
segment.x = x
else:#Down
segment.y = y - (35 * segment.pos)
segment.x = x
for segment in segments:
segment.draw(win)
scoreDisplay = text.render(str(score),1,(255,255,255))
win.blit(scoreDisplay,(760,0))
pygame.draw.rect(win,(0,128,0),(x,y,30,30))
pygame.draw.rect(win,(255,0,0),(x2,y2,30,30))
pygame.display.update()
pygame.quit()
How it works is there is a list of segments and a class for information of each segment (ie x, y, etc). I append to that list an instance of the segment class whenever the user has collided with the red cube. I have this code:
for segment in segments:
if direction == 0: #X value
if facing == 1: #Right
segment.x = x - (35 * segment.pos)
segment.y = y
else: #Left
segment.x = x + (35 * segment.pos)
segment.y = y
else: #Y value
if facing == -1: #Up
segment.y = y + (35 * segment.pos)
segment.x = x
else:#Down
segment.y = y - (35 * segment.pos)
segment.x = x
That will move all segments of the snake all at once when the player decides what direction they want the snake to move. However, the segments are snapping immediately to the x position of the head rather than moving one at a time, smoothly. If someone could help me out with this that would be great. Thanks!
Nice game. I recommend to create a list of points, which is a list of tuples of the snakes head positions ((x, y)). Add every position to the list:
pts = []
while run:
# [...]
pts.append((x, y))
Create a function which calculates the position of a part of the snake by its index (i) counted to the head of the snake. The distance to the head has to be lenToI = i * 35.
The distance between to points can be calculated by the Euclidean distance (math.sqrt((px-pnx)*(px-pnx) + (py-pny)*(py-pny)), where the points are (px, py) and (pnx, pny). If the sum of the distances between the points (lenAct) exceeds the length to point (lenToI), then the position of part i is found:
def getPos(i):
global pts
lenToI = i * 35
lenAct = 0
px, py = pts[-1]
for j in reversed(range(len(pts)-1)):
px, py = pts[j]
pnx, pny = pts[j+1]
lenAct += math.sqrt((px-pnx)*(px-pnx) + (py-pny)*(py-pny))
if lenAct >= lenToI:
break
return (px, py)
Write another function cutPts, which deletes the points from the list, which ar not further required:
def cutPts(i):
global pts
lenToI = i * 35
lenAct = 0
cut_i = 0
px, py = pts[0]
for j in reversed(range(len(pts)-1)):
px, py = pts[j]
pnx, pny = pts[j+1]
lenAct += math.sqrt((px-pnx)*(px-pnx) + (py-pny)*(py-pny))
if lenAct >= lenToI:
break
cut_i = j
del pts[:cut_i]
Update the positions of the segments in a loop:
pts.append((x, y))
for i in range(len(segments)):
segments[i].x, segments[i].y = getPos(len(segments)-i)
cutPts(len(segments)+1)
Regarding the comment:
how would I go about calling the gameOver() function if the head of the snake touches any of its segments? I tried using an if statement to check for collision (the same way I did for the apple) using segment.x and segment.y but this won't work since the second segment of the snake always overlaps the head when the snake moves.
Note, the head can never "touch" the first segment, except the direction is changed to the reverse direction, but this case can be handled by an extra test, with ease.
It is sufficient to check if the head "hits" any segment except the fist one which connects to the head.
Use pygame.Rect.colliderect to check for the intersection of rectangular segments:
def selfCollide():
for i in range(len(segments)-1):
s = segments[i]
if pygame.Rect(x, y, 30, 30).colliderect(pygame.Rect(s.x, s.y, 30, 30)):
return True
return False
if selfCollide():
gameOver()

Stop a moving Python turtle when it's close to another turtle

How do I stop a randomly moving turtle using a while loop when it comes with 50 units of another turtle?
I have one turtle that randomly selects a location and creates a large dot or hole, and another turtle that moves around randomly making 90 degree turns and moving forward 50 units every time. The randomly moving turtle stops when it goes off of the end of the screen, but how do I also make the turtle stop when it gets to the hole created by the other turtle?
import random
import turtle
def turtlesClose(t1, t2):
if t1.distance(t2)<50:
return True
else:
return False
def isInScreen(win,turt):
leftBound = -win.window_width() / 2
rightBound = win.window_width() / 2
topBound = win.window_height() / 2
bottomBound = -win.window_height() / 2
turtleX = turt.xcor()
turtleY = turt.ycor()
stillIn = True
if turtleX > rightBound or turtleX < leftBound:
stillIn = False
if turtleY > topBound or turtleY < bottomBound:
stillIn = False
return stillIn
def main():
wn = turtle.Screen()
# Define your turtles here
june = turtle.Turtle()
july = turtle.Turtle()
july.shape('turtle')
july.up()
july.goto(random.randrange(-250, 250, 1), random.randrange(-250, 250, 1))
july.down()
july.dot(100)
june.shape('turtle')
while isInScreen(wn,june):
coin = random.randrange(0, 2)
dist = turtlesClose(july, june)
if coin == 0:
june.left(90)
else:
june.right(90)
june.forward(50)
if dist == 'True':
break
main()
The problem with your code is this statement:
if dist == 'True':
You don't want quotes around True. Although this will work:
if dist == True:
The correct way to express this is:
if dist is True:
or better yet:
if dist:
Otherwise your code seems to work. Below's a rewrite taking advantage of some turtle idioms and other code cleanup:
from random import randrange, choice
from turtle import Screen, Turtle
CURSOR_SIZE = 20
def turtlesClose(t1, t2):
return t1.distance(t2) < 50
def isInScreen(window, turtle):
leftBound = -window.window_width() / 2
rightBound = window.window_width() / 2
topBound = window.window_height() / 2
bottomBound = -window.window_height() / 2
turtleX, turtleY = turtle.position()
return leftBound < turtleX < rightBound and bottomBound < turtleY < topBound
def main():
screen = Screen()
july = Turtle('circle')
july.shapesize(100 / CURSOR_SIZE)
july.up()
july.goto(randrange(-250, 250), randrange(-250, 250))
july.down()
june = Turtle('turtle')
while isInScreen(screen, june):
if turtlesClose(july, june):
break
turn = choice([june.left, june.right])
turn(90)
june.forward(50)
main()

Character doesn't change direction like it's supposed to

another pygame problem. I've tried to make a square move around on the screen in a formation of a, well, square. It works fine: first it goes down, then it turns to right, then it starts going up, then left, but as it gets to the point where it's supposed to go down, it simply doesn't and instead continues forward and out of the screen. Here's what I think is the relevant part
import pygame
from pygame.locals import *
from render import *
from player import *
import sys
pygame.init()
class collisions():
square1x = 50
square1y = 60
direction1 = "down"
vel1y = 0
vel1x = 0
square2x = 0
square2y = 0
direction2 = -1
square3x = 0
square3y = 0
direction3 = -1
square4x = 0
square4y = 0
direction4 = -1
square5x = 0
square5y = 0
direction5 = -1
green = pygame.Color(0,255,0)
def hitbox():
red = pygame.Color(255,0,0)
time = 1000/50
playerhb = pygame.rect.Rect(playerObj.x, playerObj.y,20,20)
if collisions.square1x < 40:
collisions.direction1 = "down"
if collisions.square1y > 200:
collisions.direction1 = "right"
if collisions.square1x > 600:
collisions.direction1 = "up"
if collisions.square1y < 50:
collisions.direction1 = "left"
if collisions.direction1 == "down":
collisions.vel1y = 0.02*time
collisions.vel1x = 0
if collisions.direction1 == "right":
collisions.vel1x = 0.02*time
collisions.vel1y = 0
if collisions.direction1 == "up":
collisions.vel1y = -0.02*time
collisions.vel1x = 0
if collisions.direction1 == "left":
collisions.vel1x = -0.02*time
collisions.vel1y = 0
collisions.square1x = collisions.square1x+collisions.vel1x
collisions.square1y = collisions.square1y+collisions.vel1y
enemy = pygame.rect.Rect(collisions.square1x,collisions.square1y,20,20)
draw(enemy,playerhb)
if enemy.colliderect(playerhb):
pygame.quit()
sys.exit()
pygame.display.flip()
Ignore all the other square coordinates and directions, I'm planning on making more of the squares move around on the screen.
There is a some problem with your sequence of "if". You cannot check only x or y axis in order to decide whether to change directions. You need to check both axis (or make sure the square goes back 1 pixel when the goal is reached).
I believe the code bellow will fix the problem with changing collisions.direction1.
if collisions.square1x < 40 and collisions.square1y < 50:
collisions.direction1 = "down"
if collisions.square1y > 200 and collisions.square1x < 40:
collisions.direction1 = "right"
if collisions.square1x > 600 and collision.square1y > 200:
collisions.direction1 = "up"
if collisions.square1y < 50 and collisions.square1x > 600:
collisions.direction1 = "left"

Categories