I'm trying to write a collision detection, but I'm getting some weird sticking behaviour, when I run into the object, it goes through, then when I go back, it sticks. what is going on here? the
module setup
import tkinter as tk
import random
setting up the variables
groundheight = 700
playersize = 50
PVx = 5
PVy = 0
playermass = 25
groundmass = 1000
playerx = 0
playery = -5
isgrounded = False
enemysize = 25
the player behavior
def forever():
global PVx
global PVy
global playerx
global playery
global isgrounded
enemyarray = canv.find_withtag("enemy")
playerx = canv.coords("player")[2]-playersize/2
playery = canv.coords("player")[3]-playersize/2
canv.move("player", PVx, PVy)
distoground = math.sqrt(math.pow(playery - groundheight, 2))
if distoground <= playersize:
PVy = 0
else:
isgrounded = False
PVy += 0.1
root.after(16, forever)
the enemy behavior
def enemyupdate():
global PVx
global PVy
enemyarray = canv.find_withtag("enemy")
for i in enemyarray:
enemymass = 25
Evx = 0
EVy = 0
x = canv.coords("enemy")[2]-playersize
y = canv.coords("enemy")[3]-playersize
distoground = math.sqrt(math.pow(y - groundheight, 2))
distoplayer = math.sqrt(((x-playerx)**2)+((y-playery)**2))
if distoground <= playersize:
EVy = 0
else:
EVy += 5
here's where the collisions happen
if distoplayer <= playersize+enemysize:
tempx = Evx
Evx = (playermass*PVx + enemymass*Evx)/(playermass+enemymass)
PVx = (playermass*PVx + enemymass*Evx)/(playermass+enemymass)
canv.move(i, Evx, EVy)
root.after(16, enemyupdate)
receiving input
def getaxis(X):
global PVx
PVx = X
jump code for later
def jump(event):
global PVy
if isgrounded:
PVy -= 5
tkinter main loop
root = tk.Tk()
root.geometry("1920x1080")
root.state("zoomed")
canv = tk.Canvas(width=1920, height=1080, bg='light blue')
canv.create_rectangle(0, groundheight, 1920, 1080, fill="White")
player = canv.create_oval(0, 700, playersize, 700-playersize, fill="Red", tag="player")
canv.pack()
root.after(1, forever)
root.after(1, enemyupdate)
root.bind("<space>", jump)
root.bind("<Left>", lambda *args: getaxis(-5))
root.bind("<Right>", lambda *args: getaxis(5))
for i in range(1):
enemx = 500
player = canv.create_oval(enemx+enemysize, 700, enemx - enemysize, 700-enemysize*2, fill="Red", tag="enemy")
root.mainloop()
Related
I am trying to make a racing game for my final project(High School). but I am having problems rotating the car. It loads and draws the image properly but I haven't been able to rotate the image.The program is much longer but here is the parts that are involved:
from tkinter import *
from time import *
from math import *
from random import *
from PIL import *
global screenWidth, screenHeight
screenWidth = 1200
screenHeight = 800
root = Tk()
s = Canvas(root, width=screenWidth, height=screenHeight, background= "gray")
def setGameStartingValues():
carLength = 60
carWidth = 28
carAngle = 0
lapCount = 0
speed = 0
speedX = 0
speedY = 0
directionX = ""
directionY = ""
imageCar = PhotoImage(file = "C:\\Users\\Antonio\\Desktop\\Python Programs\\GameFinal\\car.png")
colisionX = False
colisionY = False
carRadius = sqrt((carLength/2)**2 + (carWidth/2)**2)
carAngleFixed = asin((carWidth/2)/carRadius)
barriers, finishLine = createCirquit()
drawnBarriers = []
for i in range(len(barriers)):
drawnBarriers.append(None)
return carAngle, carRadius, carAngleFixed, barriers, speed, drawnBarriers, speedY, speedX, lapCount, finishLine, colisionX, colisionY, imageCar, directionX, directionY
def drawCar(carAngle, carRadius, carAngleFixed):
global screenWidth, screenHeight, correctCarImage
backLeftAngle = ((2*pi-carAngleFixed+carAngle)%(2*pi))
backRightAngle = ((carAngle+carAngleFixed)%(2*pi))
frontRightAngle = ((pi-carAngleFixed+carAngle)%(2*pi))
frontLeftAngle = ((pi+carAngle+carAngleFixed)%(2*pi))
frontRightX = carRadius*cos(frontRightAngle) + screenWidth/2
frontRightY = carRadius*sin(frontRightAngle) + screenHeight/2
frontLeftX = carRadius*cos(frontLeftAngle) + screenWidth/2
frontLeftY = carRadius*sin(frontLeftAngle) + screenHeight/2
backRightX = carRadius*cos(backRightAngle) + screenWidth/2
backRightY = carRadius*sin(backRightAngle) + screenHeight/2
backLeftX= carRadius*cos(backLeftAngle) + screenWidth/2
backLeftY = carRadius*sin(backLeftAngle) + screenHeight/2
car = s.create_image(600, 400, anchor = NW, image = correctCarImage)
return car, frontRightX, frontRightY, frontLeftX, frontLeftY, backRightX, backRightY, backLeftX, backLeftY
def sKeyPressed(event):
global speed, screenUsed
if screenUsed == "Game Screen":
if speed > -6:
speed = speed - 2
def wKeyPressed(event):
global speed, screenUsed
if screenUsed == "Game Screen":
if speed < 30:
speed = speed + 2
def aKeyPressed(event):
global carAngle, screenUsed, imageCar, correctCarImage
if screenUsed == "Game Screen":
carAngle = carAngle - radians(15)
correctCarImage = imageCar.rotate(degrees(carAngle))
def dKeyPressed(event):
global carAngle, screenUsed, correctCarImage, imageCar
if screenUsed == "Game Screen":
carAngle = carAngle + radians(15)
correctCarImage = imageCar.rotate(degrees(carAngle))
The full code doesn't fit in the question
I have a game - catching coins into a bowl. However, one of the criteria is to make it limited by entering time in seconds - how long will the game last. The time user enters is from tkinter.Entry, and I have no idea how to execute a timer and a function at the same time. Code progress:
import tkinter, random, time
from threading import Thread
window = tkinter.Tk()
window.title("Dukaty")
canvas = tkinter.Canvas(window, height = 400, width = 800)
canvas.pack()
timeLabel = tkinter.Label(text = "Time:", font = "Helvetica 15")
timeLabel.pack()
timeEntry = tkinter.Entry(bd = 1)
timeEntry.pack()
mistakesLabel = tkinter.Label(text = "Allowed mistakes:", font = "Helvetica 15")
mistakesLabel.pack()
mistakesEntry = tkinter.Entry(bd = 1)
mistakesEntry.pack()
timeEntry.insert(0, "0")
mistakesEntry.insert(0, "0")
speed = 250
score = 0
mistakes = 0
allowedTime = ""
def countdown(t):
while t:
mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
allowedTime = timer
print(allowedTime)
time.sleep(1)
t -= 1
print("Time's up!")
def timedGame():
time = int(timeEntry.get())
canvas.after(time * 1000)
end()
def movingCoin():
global speed, score, mistakes, allowedTime
time = int(timeEntry.get())
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
canvas.create_text(700, 50, text = str(score), font = "Helvetica 20", fill = "green", tags = "score")
canvas.create_text(700, 80, text = str(mistakes), font = "Helvetica 20", fill = "red", tags = "mistakes")
# ENDLESS
if timeEntry.get() == "0" and mistakesEntry.get() == "0":
while True:
if canvas.coords(coin)[1] < 360:
canvas.move(coin, 0, 5)
canvas.after(speed)
canvas.update()
elif canvas.coords(coin)[1] >= 360 and (canvas.coords(coin)[0] > (canvas.coords(bowl)[0] - 40) and canvas.coords(coin)[0] < (canvas.coords(bowl)[0] + 40)):
canvas.delete("score")
score += 1
canvas.create_text(700, 50, text=str(score), font="Helvetica 20", fill="green", tags="score")
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
else:
canvas.delete("mistakes")
mistakes += 1
canvas.create_text(700, 80, text=str(mistakes), font="Helvetica 20", fill="red", tags="mistakes")
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
# TIME - not done yet
elif timeEntry.get() != "0" and mistakesEntry.get() == "0":
while str(allowedTime) != "00:00":
if canvas.coords(coin)[1] < 360:
canvas.move(coin, 0, 5)
canvas.after(speed)
canvas.update()
elif canvas.coords(coin)[1] >= 360 and (canvas.coords(coin)[0] > (canvas.coords(bowl)[0] - 40) and canvas.coords(coin)[0] < (canvas.coords(bowl)[0] + 40)):
score += 1
print(score)
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
else:
mistakes += 1
print(mistakes)
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
# MISTAKES
elif timeEntry.get() == "0" and mistakesEntry != "0":
allowedMistakes = int(mistakesEntry.get())
print("Allowed mistakes: " + str(allowedMistakes))
while True:
if canvas.coords(coin)[1] < 360:
canvas.move(coin, 0, 5)
canvas.after(speed)
canvas.update()
elif canvas.coords(coin)[1] >= 360 and (canvas.coords(coin)[0] > (canvas.coords(bowl)[0] - 40) and canvas.coords(coin)[0] < (canvas.coords(bowl)[0] + 40)):
canvas.delete("score")
score += 1
canvas.create_text(700, 50, text=str(score), font="Helvetica 20", fill="green", tags="score")
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
else:
if allowedMistakes > mistakes:
canvas.delete("mistakes")
mistakes += 1
canvas.create_text(700, 80, text=str(mistakes), font="Helvetica 20", fill="red", tags="mistakes")
canvas.delete(coin)
coin = canvas.create_image(random.randint(15, 585), 18, image=coinImg, tags="coin")
speed -= 10
elif allowedMistakes == mistakes:
print("ending the program")
break
def end():
window.destroy()
def tap():
Thread(target=countdown(int(timeEntry.get()))).start()
Thread(target=movingCoin).start()
endButton = tkinter.Button(text = "End", command = end)
endButton.pack(side = "right")
startButton = tkinter.Button(text = "Start", command = tap)
startButton.pack(side = "left")
window.mainloop()
What this does, is that it starts the timer, and when it comes to end, THEN it executes the movingCoin function.
What I want to achieve is to make the timer start (when in Entry is value greater than 0) and at the same time execute the movingCoin - which then drops to the time section and the while breaks when the time is up.
You can use this method
window.after(1000,<function_name>)
It means the function call after 1 sec. If you are use recursion with this method then you can create timer.
I hope it works for you, cheer.
import time
# time.time() return in second
game_duration = float(input('duration: ')) + time.time()
game_is_running = True
while game_is_running:
if game_duration == time.time(): # this means: if now equal to game_duration
game_is_running = False
# note: it is quite critical where you place time.time()
One more example:
# I used the following technique to build an explosion animation for 30 seconds, then it will do something else.
class Explosion(pygame.sprite.Sprite):
def __init__(self, center):
pygame.sprite.Sprite.__init__(self)
self.image = explosion_animation[0]
self.rect = self.image.get_rect()
self.rect.center = center
self.frame = 0
self.last_update = pygame.time.get_ticks()
self.duration = 30
def update(self):
now = pygame.time.get_ticks()
if now - self.last_update > self.duration:
self.last_update = now
self.frame += 1
if self.frame == len(explosion_animation):
self.kill()
else:
center = self.rect.center
self.image = explosion_animation[self.frame]
self.rect = self.image.get_rect()
self.rect.center = center
So, I have been working on this game called Space Invader. Everything is doing great except for one thing which is the sound. As in the below code, I've imported winsound module and it is not doing well. When I fire the bullet it makes the fire noise which I wanted but the problem is that I've also added background music, and whenever I hit fire it stops the background music and starts making fire noises until it hits the target. I want background music to run continuously. I've also seen many Youtube videos but couldn't get any help. Can anyone tell me the mistake which I've made in the below code?
import turtle
import random
import math
import winsound
score = 0
highscore = 0
targets = []
live_remaining = 3
screen = turtle.Screen()
screen.title("Space War")
screen.bgcolor("Black")
screen.setup(width=800, height=770)
screen.bgpic("Space.gif")
screen.addshape("Spaceship.gif")
screen.addshape("Missile.gif")
screen.addshape("ufo.gif")
screen.addshape("gameover.gif")
screen.addshape("youwin.gif")
screen.tracer(0)
winsound.PlaySound("bgmusic.wav", winsound.SND_ASYNC)
spaceship = turtle.Turtle()
spaceship.speed(0)
spaceship.shape("Spaceship.gif")
spaceship.penup()
spaceship.ht()
spaceship.goto(0, -320)
spaceship.st()
spaceship.direction = "stop"
spaceshipspeed = 15
num_of_targets = 50
for i in range(num_of_targets):
targets.append(turtle.Turtle())
target_start_x = -250
target_start_y = 275
target_number = 0
for target in targets:
target.shape("ufo.gif")
target.penup()
target.speed(0)
x=target_start_x + (50 * target_number)
y=target_start_y
target.goto(x, y)
target_number += 1
if target_number == 10:
target_start_y -= 20
target_number = 0
targetspeed = 0.5
fires=turtle.Turtle()
fires.shape("Missile.gif")
fires.penup()
fires.ht()
fires.speed(0)
fires.goto(0, -340)
fires.direction = "stop"
firesspeed=3
fire = turtle.Turtle()
fire.shape("Missile.gif")
fire.penup()
fire.ht()
fire.speed(0)
fire.goto(0, -340)
fire.direction = "stop"
firespeed = 4
firestate = "ready"
sb=turtle.Turtle()
sb.shape("square")
sb.color("white")
sb.ht()
sb.penup()
sb.goto(0,320)
sb.write("Score: 0 | High Score: 0", align="center", font=("courier", 30, "bold"))
life = turtle.Turtle()
life.shape("square")
life.ht()
life.penup()
life.goto(-350,-350)
life.color("white")
life.write("Life remaining: 3", font=("courier",10,"bold"))
def go_left():
x = spaceship.xcor()
x -= spaceshipspeed
if x < -340:
x = -340
spaceship.setx(x)
def go_right():
x = spaceship.xcor()
x += spaceshipspeed
if x > 340:
x = 340
spaceship.setx(x)
def go_forward():
global firestate
if firestate == "ready":
firestate = "fire"
x = spaceship.xcor()
y = spaceship.ycor()
fire.setposition(x, y)
fire.st()
winsound.PlaySound("fire.wav", winsound.SND_ASYNC)
def move():
pass
screen.listen()
screen.onkeypress(go_left, "a")
screen.onkeypress(go_right, "d")
screen.onkeypress(go_forward, "space")
while True:
screen.update()
for target in targets:
x = target.xcor()
x += targetspeed
target.setx(x)
if target.xcor() > 340:
targetspeed *= -1
for t in targets:
y = t.ycor()
y -= 20
t.sety(y)
if target.xcor() < -340:
targetspeed *= -1
for t in targets:
y = t.ycor()
y -= 20
t.sety(y)
if fire.distance(target) < 20:
fire.direction = "stop"
fire.ht()
fire.clear()
firestate = "ready"
fire.goto(10000000, 1000000)
target.goto(0, 10000000)
score += 10
winsound.PlaySound("explosion.wav", winsound.SND_ASYNC)
if score > highscore:
highscore = score
sb.clear()
sb.write("Score: {} | High Score: {}".format(score,highscore), align="center",
font=("courier", 30, "bold"))
if score == 500:
screen.clear()
screen.bgcolor("black")
gf = turtle.Turtle()
gf.shape("youwin.gif")
gf.goto(0, 0)
winsound.PlaySound("gamewin.wav",winsound.SND_ASYNC)
if spaceship.distance(target) < 60:
spaceship.goto(0, -320)
target.goto(-320, 300)
live_remaining -= 1
winsound.PlaySound("explosion.wav",winsound.SND_ASYNC)
life.clear()
life.write("Life remaining: {}".format(live_remaining), font=("courier",10,"bold"))
if live_remaining == 0:
screen.clear()
screen.bgcolor("black")
gover=turtle.Turtle()
gover.shape("gameover.gif")
gover.goto(0, 0)
winsound.PlaySound("gamelose.wav", winsound.SND_ASYNC)
replay = input("Press r to retry",)
y = fire.ycor()
y += firespeed
fire.sety(y)
if fire.ycor() > 300:
fire.ht()
firestate = "ready"
move()
screen.mainloop()
I have no clue what to do here, I want to make it so that a turtle in Python will shoot a bullet and if it collides with the other turtle, the score goes up. Except if I run this code, the game will crash when I shoot the bullet. So far, I only tried it for one of the eight move commands.
#imports turtles
import turtle
import random
#Sets screen, turtle program, and colour group
turtle.setup(1000, 800)
screen = turtle.Screen()
wn = turtle.Screen()
wn.bgcolor("springgreen")
amir = turtle.Turtle()
amir.shape("arrow")
amir.shapesize(1)
amir.speed(10)
amir.pensize (2)
amir.color("blue")
amir.setheading(90)
amir.penup()
#bullet 1
jonafat = turtle.Turtle()
jonafat.shape("circle")
jonafat.shapesize(0.5)
jonafat.speed(2)
jonafat.pensize (1)
jonafat.color("black")
jonafat.penup()
jonafat.ht()
hossein = turtle.Turtle()
hossein.shape("arrow")
hossein.shapesize(1)
hossein.speed(10)
hossein.pensize (2)
hossein.color("gold")
hossein.setheading(90)
hossein.penup()
#bullet
jonafat2 = turtle.Turtle()
jonafat2.shape("circle")
jonafat2.shapesize(0.5)
jonafat2.speed(2)
jonafat2.pensize (1)
jonafat2.color("black")
jonafat2.penup()
jonafat2.ht()
#scoreboard
TT = turtle.Turtle()
TT.ht()
TT.penup()
TT.goto(-500,200)
TT.color("black")
TT.write("0", move = False, align = "center", font = ("Arial", 20, "normal"))
#second scoreboard
TT = turtle.Turtle()
TT.ht()
TT.penup()
TT.goto(-500,200)
TT.color("black")
TT.write("0", move = False, align = "center", font = ("Arial", 20, "normal"))
x = 0
y = 0
amirs = 2
hosseins = 2
auto = 15
vanguard = 15
trump = 0
time = 1
score = 0
panda = 295
def up():
global amir
global x
global amirs
global hosseins
amir.seth(90)
n = 1
for i in range(0, n):
amir.sety(amir.ycor()+10)
n + 1
def down():
global amir
global x
global amirs
global hosseins
amir.seth(270)
n = 1
for i in range(0, n):
amir.sety(amir.ycor()-10)
n + 1
def left():
global amir
global x
global amirs
global hosseins
amir.seth(180)
n = 1
for i in range(0, n):
amir.setx(amir.xcor()-10)
n + 1
def right():
global amir
global x
global amirs
global hosseins
amir.seth(0)
n = 1
for i in range(0, n):
amir.setx(amir.xcor()+10)
n + 1
def up2():
global hossein
global y
global hosseins
hossein.seth(90)
n = 1
for i in range(0, n):
hossein.sety(hossein.ycor()+10)
n + 1
def down2():
global hossein
global y
global hosseins
hossein.seth(270)
n = 1
for i in range(0, n):
hossein.sety(hossein.ycor()-10)
n + 1
def left2():
global hossein
global y
global hosseins
hossein.seth(180)
n = 1
for i in range(0, n):
hossein.setx(hossein.xcor()-10)
n + 1
def right2():
global hossein
global y
global hosseins
hossein.seth(0)
n = 1
for i in range(0, n):
hossein.setx(hossein.xcor()+10)
n + 1
def collisionCheck(jonafat, hossein):
crash = True
jonafat1X = jonafat.xcor()
jonafat1Y = jonafat.ycor()
hossein2X = hossein.xcor()
hossein2Y = hossein.ycor()
jonafatPos = (int(jonafat1X), int(jonafat1Y))
hosseinPos = (int(hossein2X), int(hossein2Y))
if jonafatPos != hosseinPos:
crash = False
if jonafatPos == hosseinPos:
crash = True
return crash
def clock():
global time
time = time-1
def move():
global auto
global vanguard
global score
global time
wn.ontimer(clock,1000)
angle = amir.heading()
jonafat.ht()
jonafat.speed(10)
jonafat.setpos(amir.xcor(), amir.ycor())
if angle == 0:
trump = 1.
time = time-1
jonafat.showturtle()
jonafat.speed(2)
n = 1
for i in range(0, n):
jonafat.goto(amir.xcor()+300, amir.ycor())
n + 1
infLoop = 1
while infLoop == 1:
if collisionCheck(jonafat, hossein) == True:
infLoop = 0
break
score = score + 1
TT.clear()
TT.write(score, move = False, align = "center", font = ("Arial", 20, "normal"))
if time == 0:
break
infLoop = 0
if angle == 90:
jonafat.showturtle()
jonafat.speed(2)
n = 1
for i in range(0, n):
jonafat.goto(amir.xcor(),amir.ycor()+300)
n + 1
if angle == 180:
jonafat.showturtle()
jonafat.speed(2)
n = 1
for i in range(0, n):
jonafat.goto(amir.xcor()-300, amir.ycor())
n + 1
if angle == 270:
jonafat.showturtle()
jonafat.speed(2)
n = 1
for i in range(0, n):
jonafat.goto(amir.xcor(), amir.ycor()-300)
n + 1
def move2():
angle2 = hossein.heading()
jonafat2.ht()
jonafat2.speed(10)
jonafat2.setpos(hossein.xcor(), hossein.ycor())
if angle2 == 0:
jonafat2.showturtle()
jonafat2.speed(2)
n = 1
for i in range(0, n):
jonafat2.goto(hossein.xcor()+300, hossein.ycor())
n + 1
if angle2 == 90:
jonafat2.showturtle()
jonafat2.speed(2)
n = 1
for i in range(0, n):
jonafat2.goto(hossein.xcor(), hossein.ycor()+300)
n + 1
if angle2 == 180:
jonafat2.showturtle()
jonafat2.speed(2)
n = 1
for i in range(0, n):
jonafat2.goto(hossein.xcor()-300, hossein.ycor())
n + 1
if angle2 == 270:
jonafat2.showturtle()
jonafat2.speed(2)
n = 1
for i in range(0, n):
jonafat2.goto(hossein.xcor(), hossein.ycor()-300)
n + 1
wn.onkeypress(up, "w")
wn.onkeypress(down, "s")
wn.onkeypress(left, "a")
wn.onkeypress(right, "d")
wn.onkeypress(up2, "Up")
wn.onkeypress(down2, "Down")
wn.onkeypress(left2, "Left")
wn.onkeypress(right2, "Right")
wn.onkeypress(move2, "Shift_R")
wn.onkeypress(move, "space")
wn.listen()
This is the part I have trouble with
def collisionCheck(jonafat, hossein):
crash = True
jonafat1X = jonafat.xcor()
jonafat1Y = jonafat.ycor()
hossein2X = hossein.xcor()
hossein2Y = hossein.ycor()
jonafatPos = (int(jonafat1X), int(jonafat1Y))
hosseinPos = (int(hossein2X), int(hossein2Y))
if jonafatPos != hosseinPos:
crash = False
if jonafatPos == hosseinPos:
crash = True
return crash
def clock():
global time
time = time-1
def move():
global auto
global vanguard
global score
global time
wn.ontimer(clock,1000)
angle = amir.heading()
jonafat.ht()
jonafat.speed(10)
jonafat.setpos(amir.xcor(), amir.ycor())
if angle == 0:
trump = 1.
time = time-1
jonafat.showturtle()
jonafat.speed(2)
n = 1
for i in range(0, n):
jonafat.goto(amir.xcor()+300, amir.ycor())
n + 1
infLoop = 1
while infLoop == 1:
if collisionCheck(jonafat, hossein) == True:
infLoop = 0
break
score = score + 1
TT.clear()
TT.write(score, move = False, align = "center", font = ("Arial", 20, "normal"))
if time == 0:
break
infLoop = 0
It appears your only checking if their position is the same, although two objects can pass close to each other so that they visually collide, but aren't on the exact same position as each other.
You'll want to take their dimensions into account to properly check for collisions. The easiest way to check if they collide is to take the distance between their positions and check if it's smaller than a certain value. Although better options exist.
Instead of all this:
def collisionCheck(jonafat, hossein):
crash = True
jonafat1X = jonafat.xcor()
jonafat1Y = jonafat.ycor()
hossein2X = hossein.xcor()
hossein2Y = hossein.ycor()
jonafatPos = (int(jonafat1X), int(jonafat1Y))
hosseinPos = (int(hossein2X), int(hossein2Y))
if jonafatPos != hosseinPos:
crash = False
if jonafatPos == hosseinPos:
crash = True
return crash
Let's take advantage of #JoshuaWaring's advice as well as turtle's distance() method and come up with something more like:
PERSONAL_SPACE = 10 # assign this to be how close is too close
def collisionCheck(jonafat, hossein):
return jonafat.distance(hossein) < PERSONAL_SPACE
Let's rework the rest of the code to produce a minimally playable game:
# imports turtles
from turtle import Turtle, Screen
PERSONAL_SPACE = 15 # assign this to be how close is too close
FIRE_DISTANCE = 300
FONT = ('Arial', 36, 'normal')
# Sets screen, turtle program, and color group
screen = Screen()
screen.setup(1000, 800)
screen.bgcolor('springgreen')
def collisionCheck(bullet, player):
return bullet.distance(player) < PERSONAL_SPACE
def up1():
player1.seth(90)
player1.forward(10)
def down1():
player1.seth(270)
player1.forward(10)
def left1():
player1.seth(180)
player1.forward(10)
def right1():
player1.seth(0)
player1.forward(10)
def clock1():
global time1, score1
if collisionCheck(bullet1, player2):
score1 += 1
TT1.undo()
TT1.write(score1, align='center', font=FONT)
time1 = 1
else:
bullet1.forward(1)
time1 -= 1
if time1:
screen.ontimer(clock1, 10)
else:
bullet1.hideturtle()
def fire1():
global time1
bullet1.setpos(player1.pos())
bullet1.setheading(player1.heading())
bullet1.showturtle()
time1 = FIRE_DISTANCE
screen.ontimer(clock1, 100)
screen.onkeypress(up1, 'w')
screen.onkeypress(down1, 's')
screen.onkeypress(left1, 'a')
screen.onkeypress(right1, 'd')
screen.onkeypress(fire1, 'space')
def up2():
player2.seth(90)
player2.forward(10)
def down2():
player2.seth(270)
player2.forward(10)
def left2():
player2.seth(180)
player2.forward(10)
def right2():
player2.seth(0)
player2.forward(10)
def clock2():
global time2, score2
if collisionCheck(bullet2, player1):
score2 += 1
TT2.undo()
TT2.write(score2, align='center', font=FONT)
time2 = 1
else:
bullet2.forward(1)
time2 -= 1
if time2:
screen.ontimer(clock2, 10)
else:
bullet2.hideturtle()
def fire2():
global time2
bullet2.setpos(player2.pos())
bullet2.setheading(player2.heading())
bullet2.showturtle()
time2 = FIRE_DISTANCE
screen.ontimer(clock2, 100)
screen.onkeypress(up2, 'Up')
screen.onkeypress(down2, 'Down')
screen.onkeypress(left2, 'Left')
screen.onkeypress(right2, 'Right')
screen.onkeypress(fire2, '0')
player1 = Turtle('arrow')
player1.speed('fastest')
player1.color('blue')
player1.setheading(180)
player1.penup()
player1.forward(10)
# bullet 1
bullet1 = Turtle('circle', visible=False)
bullet1.shapesize(0.5)
bullet1.speed('fastest')
bullet1.color('black', 'blue')
bullet1.penup()
player2 = Turtle('arrow')
player2.speed('fastest')
player2.color('gold')
player2.setheading(0)
player2.penup()
player2.forward(10)
# bullet 2
bullet2 = Turtle('circle', visible=False)
bullet2.shapesize(0.5)
bullet2.speed('fastest')
bullet2.color('black', 'gold')
bullet2.penup()
# scoreboard
TT1 = Turtle(visible=False)
TT1.penup()
TT1.goto(-450, 300)
TT1.color('blue')
TT1.write('0', align='center', font=FONT)
# second scoreboard
TT2 = Turtle(visible=False)
TT2.penup()
TT2.goto(450, 300)
TT2.color('gold')
TT2.write('0', align='center', font=FONT)
time1 = 0
score1 = 0
time2 = 0
score2 = 0
screen.listen()
screen.mainloop()
Still needs additional work, i.e. doesn't handle (or disable) multiple shots correctly, etc.
I have some problems and I cant figure out how to fix them...
It is really simple game. A bar moved by the mouse and one ball is (or some balls) bouncing.
The user just need to keep the ball bouncing.
The user can choose how many balls he wants (1,2,3), the size of the bar (small, medium,large) and the speed of the balls (slow, normal, fast).
Problems:
- sometimes everything works fine, and sometimes the ball (or balls) just goes through the bar. Like if the collision function does not work. Is there any other way I can do?
everytime there is a collision, the score should add 10 points for the total displayed on top of the screen, but this score is been overwriting all the time.
For this game be run, I just have to call the function (startGame) from other file (settings), where it also sends the value of number of balls, size of bar and speed of balls.
If anyone can help I appreciate.
Thanks
from livewires import games, color
from tkinter import*
import random
games.init(screen_width = 735, screen_height = 350, fps = 60)
class Bounce(games.Sprite):
global total_score
total_score = 0
def update(self):
global total_score
if self.bottom == 315 and self.overlapping_sprites:
self.dy = -self.dy
total_score += 10
the_score = games.Text(value = 0, size = 25,
color = color.gray,x = 700, y = 20)
games.screen.add(the_score)
if self.right > games.screen.width or self.left < 0:
self.dx = -self.dx
if self.top < 0:
self.dy = -self.dy
if self.bottom == 400:
lose_message = games.Message(value = " - GAME OVER -",
size = 50,
color = color.gray,
x = games.screen.width/2,
y = games.screen.height/2,
lifetime = 300,
after_death = games.screen.quit)
games.screen.add(lose_message)
class Bar_moving(games.Sprite):
def update(self):
self.x = games.mouse.x
self.y = 315
if self.left < 0:
self.left = 0
if self.right > games.screen.width:
self.right = games.screen.width
class have_settings():
def __init__(self):
global the_ball_speed
global the_ball_number
global the_bar_size
if "the_ball_speed" not in globals():
the_ball_speed = "normal"
if "the_bar_size" not in globals():
the_bar_size = "medium"
if "the_ball_number" not in globals():
the_ball_number = 1
def set_all(self, number, size, speed):
global the_ball_speed
global the_bar_size
global the_ball_number
if speed in ("slow","normal","fast"):
the_ball_speed = speed
if size in ("small","medium","large"):
the_bar_size = size
if number in (1,2,3):
the_ball_number = number
def startGame():
call = have_settings()
background = games.load_image("BG.jpg", transparent = False)
games.screen.background = background
#-------------------------------------SPEED
sp_is = 0
if the_ball_speed == "slow":
sp_is = 2
elif the_ball_speed == "normal":
sp_is = 3
elif the_ball_speed == "fast":
sp_is = 4
#-------------------------------------BALL NUMBER
if the_ball_number in (1,2,3):
for n in range(the_ball_number):
position_x_list =(50,150,250,350,400,450,500,550)
position_x = random.choice(position_x_list)
position_y_list =(50,100,150,200,225,250)
position_y = random.choice(position_y_list)
vert_speed_list = (-2,2)
vert_speed = random.choice(vert_speed_list)
ball_img = games.load_image("ball.bmp")
ball = Bounce(image = ball_img,
x = position_x,
y = position_y,
dx = vert_speed,
dy = - sp_is)
games.screen.add(ball)
#-------------------------------------BAR SIZE
if the_bar_size in ("small","medium","large"):
if the_bar_size == "small":
bar_pic = "bar_small.jpg"
elif the_bar_size == "medium":
bar_pic = "bar_medium.jpg"
elif the_bar_size == "large":
bar_pic = "bar_large.jpg"
bar = games.load_image(bar_pic, transparent = False)
the_bar = Bar_moving(image = bar, x = games.mouse.x)
games.screen.add(the_bar)
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
You should do a greater than check rather than an equals check as follows:
if self.bottom >= 315 and self.overlapping_sprites:
^^
instead of
if self.bottom == 315 and self.overlapping_sprites:
This is because rarely will the ball's y position ever perfectly line up with the bottom. In some cases it may go from y==314 to y==316. In such cases, your method above wouldn't work. Therefore, you should be a greater than test rather than an equality test.
You can apply similar changes everywhere else and it should work.