set mouse cursor position as objects heading - python

I want to set object u1's heading by the mouse cursors position inside the window.
import turtle
import pygame
import time
win = turtle.Screen()#window
win.title("eagle.py")
win.setup(1920,1080)
win.bgcolor("black")
win.bgpic("triangle")
c1 = turtle.Turtle()#cloud1
c1.speed(0)
c1.penup()
c1.setposition(-1075, 256)
c1.color("white")
c1.shape("triangle")
c_speed = 1 #cloudspeed
u1 = turtle.Turtle()#user1
mouse_pos = pygame.mouse.get_pos()
u1.shape("triangle")
u1.color("red")
u1.speed(0)
u1.setposition(0,0)
u1.setheading(mouse_pos)
u1.penup()
u_speed = 10 #playerspeed
def u1_r():
x = u1.xcor()
x += u_speed
u1.setx(x)
def u1_l():
x = u1.xcor()
x -= u_speed
u1.setx(x)
def u1_up():
y = u1.ycor()
y += u_speed
u1.sety(y)
def u1_down():
y = u1.ycor()
y -= u_speed
u1.sety(y)
while True:
win.update()
time.sleep(1/160)
c1.setx(c1.xcor() + c_speed)
if c1.xcor() > 1075:
c1.goto(-1075, 256)
win.listen()
win.onkeypress(u1_r, "d")
win.onkeypress(u1_l, "a")
win.onkeypress(u1_up, "w")
win.onkeypress(u1_down, "s")
The program keeps shutting down immediately after running. What have I done wrong?

The fact that you have the following:
win.listen()
win.onkeypress(u1_r, "d")
win.onkeypress(u1_l, "a")
win.onkeypress(u1_up, "w")
win.onkeypress(u1_down, "s")
inside a loop indicates that you don't have a basic understanding of the environment in which you're working. Let's start over, tossing pygame and time and just work within the turtle framework:
from turtle import Screen, Turtle
def player_r():
player.setheading(0)
player.setx(player.xcor() + player_speed)
def player_l():
player.setheading(180)
player.setx(player.xcor() - player_speed)
def player_up():
player.setheading(90)
player.sety(player.ycor() + player_speed)
def player_down():
player.setheading(270)
player.sety(player.ycor() - player_speed)
def move():
cloud.setx(cloud.xcor() + cloud_speed)
if cloud.xcor() > 940:
cloud.goto(-940, 256)
screen.update()
screen.ontimer(move)
screen = Screen()
screen.setup(1920, 1080)
screen.bgcolor('black')
screen.tracer(False)
cloud = Turtle()
cloud.shape('circle')
cloud.shapesize(1, 3)
cloud.color('white')
cloud.penup()
cloud.setposition(-940, 256)
cloud_speed = 1
player = Turtle()
player.shape('turtle')
player.color('red')
player.penup()
player_speed = 10
screen.onkeypress(player_r, 'd')
screen.onkeypress(player_l, 'a')
screen.onkeypress(player_up, 'w')
screen.onkeypress(player_down, 's')
screen.listen()
move()
screen.mainloop()

In your code, string is in heading. Instead, put variable.
u1 = turtle.Turtle()
mouse_pos = pygame.mouse.get_pos()
u1.heading(mouse_pos) # variable
Edit: This worked for me, triangle moving..
It seems pygame.init() is need at first.
u1.setheading has a number inside, not tuple. This is for angle. (man turtle)
import turtle
import pygame
import time
pygame.init()
win = turtle.Screen()#window
win.title("eagle.py")
win.setup(1920,1080)
win.bgcolor("black")
win.bgpic() # changed
c1 = turtle.Turtle()#cloud1
c1.speed(0)
c1.penup()
c1.setposition(-1075, 256)
c1.color("white")
c1.shape("triangle")
c_speed = 1 #cloudspeed
u1 = turtle.Turtle()#user1
mouse_pos = pygame.mouse.get_pos()
u1.shape("triangle")
u1.color("red")
u1.speed(0)
u1.setposition(0,0)
u1.setheading(0) # to be changed, setheading(int)
u1.penup()
u_speed = 10 #playerspeed
def u1_r():
x = u1.xcor()
x += u_speed
u1.setx(x)
def u1_l():
x = u1.xcor()
x -= u_speed
u1.setx(x)
def u1_up():
y = u1.ycor()
y += u_speed
u1.sety(y)
def u1_down():
y = u1.ycor()
y -= u_speed
u1.sety(y)
while True:
win.update()
time.sleep(1/160)
c1.setx(c1.xcor() + c_speed)
if c1.xcor() > 1075:
c1.goto(-1075, 256)
win.listen()
win.onkeypress(u1_r, "d")
win.onkeypress(u1_l, "a")
win.onkeypress(u1_up, "w")
win.onkeypress(u1_down, "s")

turtle.heading() expects a numeric argument specifying the heading in degrees.
I don't think you can use the pygame and turtle modules at the same time. Both have their own way of drawing graphics and getting the mouse's current position, so theoretically you can use either.
Regardless, of which one you're using, you'll need to compute the heading's angle from the mouse's x, y position.
Here's how to measure the angle to the origin of an x, y position (assuming its x value isn't zero):
import math
x, y = ... # Mouse position.
print(math.degrees(math.atan(y/x)))

Related

How to bind enter key to a function using turtle

I'm trying to make a tic tac toe game where you use arrow keys to move a turtle around the board, and when you press the enter key it draws a circle (nought in the code) or a cross.
I've tried using similar code to what I used for the movement keys but replace it for the enter key and C key (for cross) but they don't work and automatically draw the cross when it starts up. I've also tried using monkey but that doesn't work.
import turtle
sc = turtle.Screen()
bo = turtle.Turtle()
#screen
sc.bgcolor("black")
sc.title("tic tac toe")
#board
bo.color("white")
bo.penup()
bo.speed(0)
bo.setposition(-100, -300)
bo.pendown()
bo.setposition(-100, 300)
bo.penup()
bo.setposition(100, 300)
bo.pendown()
bo.setposition(100, -300)
bo.penup()
bo.setposition(-300, 100)
bo.pendown()
bo.setposition(300, 100)
bo.penup()
bo.setposition(300, -100)
bo.pendown()
bo.setposition(-300,-100)
bo.penup()
bo.setposition(0,0)
#naught and cross function
def c() :
bo.pendown()
x = bo.xcor()-80
y = bo.ycor()+80
bo.penup()
bo.setposition(x,y)
bo.pendown()
x = bo.xcor()+160
y = bo.ycor()-160
bo.setposition(x,y)
bo.penup()
x = bo.xcor()-160
bo.setposition(x,y)
bo.pendown()
x = bo.xcor()+160
y = bo.ycor()+160
bo.setposition(x,y)
bo.penup()
bo.setposition(0,0)
def n() :
y = bo.ycor()-80
x = bo.xcor()
bo.setposition(x, y)
bo.pendown()
bo.circle(80)
bo.penup()
bo.setposition(0,0)
#movment
def move_left(event):
x = bo.xcor()
x -= 200
if x < -300:
x = -200
bo.setx(x)
def move_right(event):
x = bo.xcor()
x += 200
if x > 300:
x = 200
bo.setx(x)
def move_down(event):
y = bo.ycor()
y -= 200
if y < -300:
y = -200
bo.sety(y)
def move_up(event):
y = bo.ycor()
y += 200
if y > 300:
y = 200
bo.sety(y)
#Keybinding
turtle.listen()
turtle.getcanvas().bind("<Left>", move_left)
turtle.getcanvas().bind("<Right>", move_right)
turtle.getcanvas().bind("<Up>", move_up)
turtle.getcanvas().bind("<Down>", move_down)
I'd eventually like to have it where once you draw a cross, and press enter, it draws a circle where there isn't a cross.
There's no need to drop down to the Tk Canvas to configure your key events:
turtle.getcanvas().bind("<Left>", move_left)
You can do the same from turtle itself:
sc.onkey(move_left, "Left")
I've reworked your code below, adding a key event for "Return" that draws the naughts and crosses. Since you don't have an underlying data structure for your game, I set it up to simply alternate between the two:
from turtle import Screen, Turtle
# naught and cross functions
def cross():
x, y = board.position()
board.penup()
board.setposition(x - 80, y - 80)
board.pendown()
board.setposition(x + 80, y + 80)
board.penup()
board.setx(x - 80)
board.pendown()
board.setposition(x + 80, y - 80)
board.penup()
board.home()
def naught():
board.sety(board.ycor() - 80)
board.pendown()
board.circle(80)
board.penup()
board.home()
first_player = True
def choose():
global first_player
if first_player:
naught()
else:
cross()
first_player = not first_player
# movement
def move_left():
x = board.xcor() - 200
if x < -300:
x = -200
board.setx(x)
def move_right():
x = board.xcor() + 200
if x > 300:
x = 200
board.setx(x)
def move_down():
y = board.ycor() - 200
if y < -300:
y = -200
board.sety(y)
def move_up():
y = board.ycor() + 200
if y > 300:
y = 200
board.sety(y)
# screen
screen = Screen()
screen.bgcolor("black")
screen.title("tic tac toe")
# board
board = Turtle()
board.color("white")
board.speed('fastest')
# vertical lines
board.penup()
board.setposition(-100, -300)
board.pendown()
board.sety(300)
board.penup()
board.setx(100)
board.pendown()
board.sety(-300)
board.penup()
# horizontal lines
board.setposition(-300, 100)
board.pendown()
board.setx(300)
board.penup()
board.sety(-100)
board.pendown()
board.setx(-300)
board.penup()
board.home()
# Keybinding
screen.onkey(move_left, "Left")
screen.onkey(move_right, "Right")
screen.onkey(move_up, "Up")
screen.onkey(move_down, "Down")
screen.onkey(choose, "Return")
screen.listen()
screen.mainloop()
This allows two people to play the game and should be something you can build upon.

Alternative to using turtle.goto() in Python

This program creates a bouncing ball using turtle.goto(), is there an alternative?
from random import *
from turtle import *
from base import vector
# The ball is drawn, the actions are used from the base file
def draw():
ball.move(aim)
x = ball.x
y = ball.y
if x < -200 or x > 200:
aim.x = -aim.x
if y < -200 or y > 200:
aim.y = -aim.y
clear()
# Can this program serve a purpose without it?
goto(x, y)
dot(10, 'blue')
ontimer(draw,50)
Generally, what is the point of having a goto() function?
Yes, you can create a bouncing ball without using turtle.goto(), here's a rough example:
from turtle import Screen, Turtle
def draw():
ball.forward(10)
x, y = ball.position()
if not (-200 < x < 200 and -200 < y < 200):
ball.undo() # undo 'forward()'
ball.setheading(ball.heading() + 90)
ball.forward(10)
screen.update()
screen.ontimer(draw, 50)
screen = Screen()
screen.tracer(False)
box = Turtle('square')
box.hideturtle()
box.fillcolor('white')
box.shapesize(20)
box.stamp()
ball = Turtle('circle')
ball.color('blue')
ball.setheading(30)
ball.penup()
draw()
screen.exitonclick()

Python while loop with no expressions

Is is possible to have a while loop in Python with no expressions?
I know in other languages you can do something like:
while(flag) {};
I'm trying to do something similar in Python but cannot find an answer.
Here is what I have so far:
import turtle
from random import randrange
def is_in_screen(t, w): #CHECKS TO SEE IF STILL IN SCREEN
flag = True
r = w.window_width() / 2
l = r * -1
u = w.window_height() / 2
d = u * -1
x_cor = t.xcor()
y_cor = t.ycor()
if (x_cor < l or x_cor > r or y_cor < d or y_cor > u):
flag = False
return flag
def move_to(t, w): #MOVE IN RANDOM DIRECTION AND RANDOM DISTANCE
t.forward(randrange(1, 100))
if (randrange(1, 2) == 1):
t.left(randrange(1, 180))
else:
t.right(randrange(1, 180))
return is_in_screen(t, w)
def random_movement(t1, t2, w):
while (move_to(t1, w) and move_to(t2, w)): #<<<<<<<<LOOP IN QUESTION
i = 0
def main():
t1 = turtle.Turtle()
t2 = turtle.Turtle()
w = turtle.Screen()
t1.color("green")
t2.color("purple")
random_movement(t1, t2, w)
w.exitonclick()
main()
The reason I'm trying to do no expressions is because I want the second turtle to not move if the first turtle goes out of bounds. Also, I do not want return statements in the function.
You're looking for the pass keyword.
while (flag):
pass
Below is a rework of your code with the while expr: pass that everyone's suggesting along with some other style and idiom changes to tighten up the code:
from turtle import Screen, Turtle
from random import randrange
def is_in_screen(turtle, screen):
r = screen.window_width() / 2
u = screen.window_height() / 2
x, y = turtle.position()
return -r < x < r and -u < y < u
def move_to(turtle, screen):
turtle.forward(randrange(1, 100))
turtle.left(randrange(-180, 180)) # negative left turn is a right turn
return is_in_screen(turtle, screen)
def random_movement(turtle_1, turtle_2, screen):
while move_to(turtle_1, screen) and move_to(turtle_2, screen): pass
screen = Screen()
t1 = Turtle()
t1.color("green")
t2 = Turtle()
t2.color("purple")
random_movement(t1, t2, screen)
screen.exitonclick()

How do i move an object on the screen using the mousex and mousey coordinates in tkinter

I am trying to move the green object called char relative to the mouse x and mouse y coordinates but I don't know how. Can anyone help me? In case you are wondering i am trying to make a version of single player agario.
from tkinter import *
import random
from random import uniform, randrange
import time
#left,top,right,bottom
tk = Tk()
canvas = Canvas(tk,width=600,height=600)
canvas.pack()
pointcount = 0
char = canvas.create_oval(400,400,440,440,fill="green")
pos1 = canvas.coords(char)
x = canvas.canvasx()
y = canvas.canvasy()
class Ball:#ball characteristics#
def __init__(self,color,size):
self.shape = canvas.create_oval(10,10,50,50,fill=color)
self.xspeed = randrange(-5,7)
self.yspeed = randrange(-5,7)
def move(self):#ball animation#
global pointcount
canvas.move(self.shape,self.xspeed,self.yspeed)
pos = canvas.coords(self.shape)
if pos[0] <= 0 or pos[2] >= 600:#if ball hits the wall#
self.xspeed = -self.xspeed
if pos[1] <= 0 or pos[3] >= 600:
self.yspeed = -self.yspeed
left_var = abs(pos[0] - pos1[0])
top_var = abs(pos[1] - pos1[1])
if left_var == 0 and top_var == 0:
pointcount = pointcount + 1
print(pointcount)
colors = ["red","blue","green","yellow","purple","orange"]
balls = []
for i in range(10):
balls.append(Ball(random.choice(colors),50))
while True:
for ball in balls:
ball.move()
tk.update()
time.sleep(0.01)
To move the green circle with the mouse, you need to bind the position of the circle to mouse motion event. Here is an example where the circle is always centered on the mouse when the mouse is in the canvas:
from tkinter import *
root = Tk()
canvas = Canvas(root)
canvas.pack(fill="both", expand=True)
char = canvas.create_oval(400,400,440,440,fill="green")
def follow_mouse(event):
""" the center of char follows the mouse """
x, y = event.x, event.y
canvas.coords(char, x - 20, y - 20, x + 20, y + 20)
# bind follow_mouse function to mouse motion events
canvas.bind('<Motion>', follow_mouse)
root.mainloop()

Python: pygame deleting image on mouse click and creating it again

im trying to make a simple game where the there are soldiers coming towards you and when you click them to "kill" them they go at the back of the screen and start to come towards you, so on.....
however i'm having trouble with pygame mouse click event and it just doesnt work.
heres my code so far:
import pygame, math
from random import randrange
import sys, math, pygame
from operator import itemgetter
def getKey(customobj):
return customobj.getKey()
class Point3D:
def __init__(self, imfiles, nfrm, x = 0, y = 0, z = 0):
self.x, self.y, self.z = float(x), float(y), float(z)
self.frms = []
self.nfrm=nfrm
self.index=0
for k in range(0,nfrm):
im=pygame.image.load(imfiles+'_'+str(k+1)+'.png')
im.set_colorkey((0,0,0))
self.frms.append(im)
def
project(self, win_width, win_height, fov, viewer_distance):
""" Transforms this 3D point to 2D using a perspective projection. """
factor = fov / (viewer_distance + self.z)
x = self.x * factor + win_width / 2
y = -self.y * factor + win_height / 2
return Point3D(x, y, self.z)
def draw3D(self, wsurface, fov, viewer_distance, max_depth):
win_width=wsurface.get_width()
win_height=wsurface.get_height()
factor = fov / (viewer_distance + self.z)
x = self.x * factor + win_width / 2
y = -self.y * factor + win_height / 2
size = int((1 - float(self.z) / max_depth) * 64)
im=pygame.transform.smoothscale(self.frms[self.index],(size,size))
try:
wsurface.blit(im, (x, y))
except:
print((x,y))
self.index=self.index+1
if self.index >= self.nfrm:
self.index=0
def getKey(self):
return -self.z
class StartField:
def __init__(self, num_stars, max_depth):
pygame.init()
myWin = pygame.display.set_mode((640, 450), 0, 32)
pygame.display.set_caption('Drawing')
self.screen = myWin.subsurface([0,0,640,400]);
self.txtwin = myWin.subsurface([0,400,640,50]);
pygame.display.set_caption("Task C")
self.clock = pygame.time.Clock()
self.num_stars = num_stars
self.max_depth = max_depth
self.init_stars()
def init_stars(self):
""" Create the starfield """
self.stars = []
for i in range(self.num_stars):
# A star is represented as a list with this format: [X,Y,Z]
star = Point3D('im',8,randrange(-25,25), randrange(-25,25), randrange(1, self.max_depth))
self.stars.append(star)
def move_and_draw_stars(self):
""" Move and draw the stars """
origin_x = self.screen.get_width() / 2
origin_y = self.screen.get_height() / 2
stars=sorted(self.stars,key = getKey)
for star in stars:
# The Z component is decreased on each frame.
star.z -= 0.05
# If the star has past the screen (I mean Z<=0) then we
# reposition it far away from the screen (Z=max_depth)
# with random X and Y coordinates.
if star.z <= 0:
star.x = randrange(-25,25)
star.y = randrange(-25,25)
star.z = self.max_depth
# Convert the 3D coordinates to 2D using perspective projection.
star.draw3D(self.screen, 128, 0, self.max_depth)
def run(self):
""" Main Loop """
bgPicture = pygame.transform.smoothscale(pygame.image.load('Starfield.jpg'),(self.screen.get_width(),self.screen.get_height()))
font = pygame.font.Font(None, 36)
while 1:
# Lock the framerate at 50 FPS.
self.clock.tick(50)
# Handle events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return
self.screen.blit(bgPicture, [0,0])
self.move_and_draw_stars()
# Text window outputs
self.txtwin.fill([200,200,200])
text = font.render("Total Score: ", 1, (10, 10, 10))
self.txtwin.blit(text, [5, 5])
pygame.display.update()
if __name__ == "__main__":
StartField(256, 24).run()
pygame.init()
pygame.mixer.init()
sounda= pygame.mixer.Sound("MuseUprising.mp3")
sounda.play()
To test for the left mouse button:
if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0]:
If give the soldier a pygame.Rect you can use that to check for collision with the mouse pointer like this:
mouse_pos = pygame.mouse.get_pos()
if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0] and self.rect.collidepoint(mouse_pos):

Categories