How do I perform a collision check? - python

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.

Related

Every time I run this function it is slower and slower

I am trying to do code a simple game in python using tkinter where a block jumps over obstacles, however I got stuck on the jumping part. Every time I call the jump function it jumps slower and slower, and I don't know the reason. Ty in advance.
import time
import tkinter
import random
bg = "white"
f = 2
k=0
t = 0.01
groundLevel = 550
root = tkinter.Tk()
root.geometry("1000x600")
canvas = tkinter.Canvas(root,width = 1000,height = 1000,bg = bg)
canvas.pack(fill= tkinter.BOTH, expand= True)
posX = 50
posY= 530
startButton = tkinter.Button(canvas,text=" Start ")
def startPlayer(xx,yy):
canvas.create_rectangle(xx-20,yy-22,xx+20,yy+18,fill = "orange")
return(xx,yy)
def move(x,y,x2,y2,direction,fill,outline):
global f
#direction 0 = up
#direction 1 = down
#direction 2 = left
#direction 3 = right
if direction == 0:
canvas.create_rectangle(x,y,x2,y2,fill="cyan",outline="cyan")
canvas.create_rectangle(x,y-f,x2,y2-f,fill=fill,outline=outline)
if direction == 1:
canvas.create_rectangle(x,y,x2,y2,fill="cyan",outline="cyan")
canvas.create_rectangle(x,y+f,x2,y2+f,fill=fill,outline=outline)
if direction == 2:
canvas.create_rectangle(x,y,x2,y2,fill="cyan",outline="cyan")
canvas.create_rectangle(x,y,x2,y2,fill=fill,outline=outline)
if direction == 3:
canvas.create_rectangle(x,y,x2,y2,fill="cyan",outline="cyan")
canvas.create_rectangle(x,y,x2,y2,fill=fill,outline=outline)
def playerJump():
global groundLevel, f, k,posX,posY,t
while k != 1:
move(posX-20,posY-22,posX+20,posY+18,direction = 0, fill = "orange",outline = "black")
posY -= 2
canvas.update()
if (posY) == 480:
k = 1
time.sleep(t)
k = 0
while k != 1:
move(posX-20,posY-22,posX+20,posY+18,direction = 1, fill = "orange",outline = "black")
posY += 2
canvas.update()
if (posY) == 530:
k = 1
time.sleep(t)
k = 0
def start():
canvas.create_rectangle(0,0,1000,600,fill="cyan")
canvas.create_line(0,550,1000,550,width = 3)
startButton.destroy()
startPlayer(50,530)
startGameButton = tkinter.Button(canvas, text ="Go!",command = playerJump)
startGameButton.place(x = 35, y=400)
return(startGameButton)
def resetButton():
global startGameButton
startGameButton.destroy()
startGameButton = tkinter.Button(canvas, text ="Go!",command = playerJump)
startGameButton.place(x = 35, y=400)
startImage = tkinter.PhotoImage(file="C:/Users/marti/OneDrive/Desktop/Wheel finder/startSign.png")
canvas.create_rectangle(0,0,1000,1000,fill="green")
startButton.config(image = startImage,command = start)
startButton.place(x = 130, y= 25)
canvas.create_rectangle(300,400,700,500,fill="#113B08",outline = "black",width = 3)
canvas.create_text(500,450,text = "By: --------", font = "Arial 30",fill ="white")
I shrinking the sleep time every time it runs so its faster, but that is only a temporary solution and it didn't even work.
Problem with your code is you are always adding new items into your canvas. When you jump you update orange rectangle and repaint its old place. However they stack top of each other and handling too many elements makes slower your program.
We create player and return it to main function.
def startPlayer(xx,yy):
player=canvas.create_rectangle(xx-20,yy-22,xx+20,yy+18,fill = "orange")
return player
This is new start function. Check that we get player and send to playerjump function.
def start():
canvas.create_rectangle(0,0,1000,600,fill="cyan")
canvas.create_line(0,550,1000,550,width = 3)
startButton.destroy()
player = startPlayer(50,530)
startGameButton = tkinter.Button(canvas, text ="Go!",command = lambda :playerJump(player))
startGameButton.place(x = 35, y=400)
return(startGameButton)
And this is playerjump function.We get player and sent to move function.
def playerJump(player):
global groundLevel, f, k,posX,posY,t
while k != 1:
move(posX-20,posY-22,posX+20,posY+18,direction = 0, fill = "orange",outline = "black",player=player)
posY -= 2
canvas.update()
if (posY) == 480:
k = 1
time.sleep(t)
k = 0
while k != 1:
move(posX-20,posY-22,posX+20,posY+18,direction = 1, fill = "orange",outline = "black",player=player)
posY += 2
canvas.update()
if (posY) == 530:
k = 1
time.sleep(t)
k = 0
Except move lines, I didn't change anything in this function.
Okay now let's check key part.
def move(x,y,x2,y2,direction,fill,outline,player):
global f
#direction 0 = up
#direction 1 = down
#direction 2 = left
#direction 3 = right
if direction == 0:
canvas.coords(player,x,y-f,x2,y2-f)
if direction == 1:
canvas.coords(player,x,y+f,x2,y2+f)
if direction == 2:
canvas.coords(player,x,y,x2,y2)
if direction == 3:
canvas.coords(player,x,y,x2,y2)
look that instead of creating new rectangles,we updated existing one. which is much more stable
Also you forgot adding root.mainloop in your code snippet.

Continuous background music with winsound module

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 tried to make Game of Life by John Conway in pygame. Not sure exactly what went wrong [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
The cells don't behave like they're supposed to, meaning they don't follow the rules. I've tried everything I could think of, but it doesn't work.
The variable "state" is used to store the current states of all the cells (1 if active 0 if not) in the format state[x][y], similarly, "cells" also follow the same format but instead of 1s and 0s, it stores all the sprites, aka cells. The "new_state" is exactly like the state but it stores the states for the next generation. (The next generation is calculated from "state" and stored in "new_state".)
Heres an example of what "state" might look like:
state = [[0,0,0,0,0,0,0,0,0],[0,1,1,1,0,0,0], . . . ]
To calculate how many active neighbors there are next to a cell, I just did a nested for loop, both with range(-1, 2). If i, j are the variables of the for loops, then that would look something like this:
for i in range(-1, 2):
for j in range(-1, 2):
sum += state[x + i][y + j]
sum -= state[x][y]
Anyways, heres the code:
import pygame as pg
pg.init()
ticking = False
# colours
white = (255, 255, 255)
grey = (100, 100, 100)
blue = (0, 0, 255)
black = (0, 0, 0)
drk_blue = (0, 0, 100)
red = (255, 0, 0)
# now the screen
width = 750
height = 500
main_screen = pg.display.set_mode([width, height])
main_screen_rect = main_screen.get_rect()
game_width = width - width // 5
main_screen.fill(black)
game_screen = pg.Surface([game_width, height])
game_screen_rect = game_screen.get_rect()
game_screen.fill(black)
WH_cells = [0, 42]
for x in range(0, game_width, 12):
WH_cells[0] += 1
a = False # This is for toggling the eraser for the cells
# The state says which cells are active and inactive and cells is just a list containing the sprites
state = []
cells = []
new_state = []
# New state is for updating, i.e., it contains the states of the next generation
# imp functions
def logic():
sum_calc()
drawer()
global state, new_state
state = new_state
new_state = blank
def sum_calc():
global new_state
state_len = len(state)
state_len_part = len(state[0])
for x_c in range(1, state_len - 1):
for y_c in range(1, state_len_part - 1):
neigh_sum = 0
for i in range(-1, 2):
for j in range(-1, 2):
if x_c + i < state_len and y_c + j < len(state[x_c + i]):
neigh_sum += state[x_c + i][y_c + j]
neigh_sum -= state[x_c][y_c]
if neigh_sum < 2 or neigh_sum > 3:
new_state[x_c][y_c] = 0
elif neigh_sum == 3:
new_state[x_c][y_c] = 1
def drawer():
state_len = len(new_state)
state_len_part = len(new_state[0])
for x in range(state_len):
for y in range(state_len_part):
if new_state[x][y] != 1:
cells[x][y].Activate(False)
else:
cells[x][y].Activate(True)
# sprites
class Cell(pg.sprite.Sprite):
def __init__(self):
super(Cell, self).__init__()
self.surf = pg.Surface((10, 10))
self.surf.fill(grey)
self.rect = self.surf.get_rect()
self.index = None
def update(self, mouse_pos, eraser):
if self.rect.collidepoint(mouse_pos[0], mouse_pos[1]):
cell_x = self.index[0]
cell_y = self.index[1]
global state
if not eraser:
self.surf.fill(white)
state[cell_x][cell_y] = 1
else: # if eraser
self.surf.fill(grey)
state[cell_x][cell_y] = 0
def Activate(self, yesno):
global new_state
cell_x = self.index[0]
cell_y = self.index[1]
if yesno:
self.surf.fill(white)
new_state[cell_x][cell_y] = 1
else:
self.surf.fill(grey)
new_state[cell_x][cell_y] = 0
all_sprites = pg.sprite.Group()
running = True
# generating the cells and lists
for x in range(0, game_width, 12):
state.append([])
cells.append([])
for y in range(0, height, 12):
x_coord = int(x / 12)
state[x_coord].append(0)
new_cell = Cell()
new_cell.rect.x = x
new_cell.rect.y = y
new_cell.index = (x_coord, int(y / 12))
cells[x_coord].append(new_cell)
all_sprites.add(new_cell)
game_screen.blit(new_cell.surf, (x, y))
sprite_list = all_sprites.sprites()
sprite_list_len = len(sprite_list)
new_state = state
blank = state
while running:
if ticking:
logic()
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_a:
a = not a
if event.key == pg.K_SPACE:
if ticking:
ticking = not ticking
else:
ticking = True
print("ticking toggled to: ", ticking)
if event.type == pg.MOUSEMOTION or pg.mouse.get_pressed()[0]:
if pg.mouse.get_pressed()[0]:
for sprites in all_sprites:
sprites.update(pg.mouse.get_pos(), a)
for sprites in sprite_list:
game_screen.blit(sprites.surf, (sprites.rect.x, sprites.rect.y))
main_screen.blit(game_screen, (0, 0))
pg.display.update(main_screen_rect)
fps = pg.time.Clock()
fps.tick(60)
An assignment operation like new_state = state doesn't generate a new object. After this expression, you have 2 variables that refer to the same object.
Actually you have just 1 grid of states. The variables state, new_state and blank refer to the same object. You must create a new and empty state grid in each frame:
def logic():
global state, new_state
new_state = [[0 for _ in row] for row in state]
sum_calc()
drawer()
state = new_state
Furthermore, your algorithm is not correct. See Conway's Game of Life. Change the lgoic:
def sum_calc():
global new_state
state_len = len(state)
state_len_part = len(state[0])
for x_c in range(1, state_len - 1):
for y_c in range(1, state_len_part - 1):
neigh_sum = 0
for i in range(-1, 2):
for j in range(-1, 2):
if x_c + i < state_len and y_c + j < len(state[x_c + i]):
neigh_sum += state[x_c + i][y_c + j]
neigh_sum -= state[x_c][y_c]
#if neigh_sum < 2 or neigh_sum > 3:
# new_state[x_c][y_c] = 0
#elif neigh_sum == 3:
# new_state[x_c][y_c] = 1
if state[x_c][y_c] == 1 and (neigh_sum == 2 or neigh_sum == 3):
new_state[x_c][y_c] = 1
elif state[x_c][y_c] == 0 and neigh_sum == 3:
new_state[x_c][y_c] = 1
else:
new_state[x_c][y_c] = 0

A Sticky Situation In Tkinter

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()

Python Turtle Graphics Game Lagging

My Python game is lagging a lot. I started making a new Python game and every time it came to testing it, it would always lag although I am not using any images.
import turtle
import random
#head orientation
h = [0]
#score
a = [0]
b = [0]
#food coord
fcoord = [0,0,0]
#position
pos = []
def home(x,y):
x = 0
y = 0
a[0] = 0
b[0] = 0
h[0] = 0
fcoord[2] = 0
pos[:] = []
turtle.hideturtle()
turtle.clear()
turtle.pu()
turtle.color("lime")
turtle.goto(0,0)
turtle.write("PLAY", align="center",font="Calibri")
turtle.title("Snake Game")
turtle.onscreenclick(start)
turtle.mainloop()
def level_1():
turtle.clear()
turtle.pu()
turtle.speed(0)
turtle.pensize(20)
turtle.color("grey")
turtle.goto(-220,220)
turtle.pd()
turtle.goto(220,220)
turtle.goto(220,-220)
turtle.goto(-220,-220)
turtle.goto(-220,220)
turtle.pu()
turtle.goto(0,0)
def start(x,y):
turtle.onscreenclick(None)
level_1()
tfood = turtle.Turtle()
tfood.hideturtle()
tfood.pu()
tfood.speed(0)
tfood.shape("square")
tfood.color("red")
tscore = turtle.Turtle()
tscore.hideturtle()
tscore.pu()
tscore.speed(0)
tscore.goto(100,-250)
tscore.write("Score:" + str(a[0]), align="center",font=(10))
while x > -210 and x < 210 and y > -210 and y <210:
if fcoord[2] == 0:
food(tfood)
fcoord[2] = 1
turtle.onkey(u,"Up")
turtle.onkey(l,"Left")
turtle.onkey(r,"Right")
turtle.onkey(d,"Down")
turtle.listen()
move()
x = turtle.xcor()
y = turtle.ycor()
if x > fcoord[0]*20-5 and x < fcoord[0]*20+5 and y > fcoord[1]*20-5 and y < fcoord[1]*20+5:
fcoord[2] = 0
tfood.clear()
a[0] += 1
tscore.clear()
tscore.write("Score:" + str(a[0]), align="center",font=(10))
if len(pos) > 1:
for i in range(1,len(pos)):
if x < pos[i][0]+5 and x > pos[i][0]-5 and y < pos[i][1]+5 and y > pos[i][1]-5:
tscore.clear()
tfood.clear()
gameover()
tscore.clear()
tfood.clear()
gameover()
#Food
def food(tfood):
x = random.randrange(-8,8,1)
y = random.randrange(-8,8,1)
fcoord[0] = x
fcoord[1] = y
tfood.hideturtle()
tfood.pu()
tfood.shape("circle")
tfood.color("red")
tfood.goto(x*20,y*20)
tfood.stamp()
#Up
def u():
if h[0] == 270:
pass
else:
h[0] = 90
#Down
def d():
if h[0] == 90:
pass
else:
h[0] = 270
#Left
def l():
if h[0] == 0:
pass
else:
h[0] = 180
#Right
def r():
if h[0] == 180:
pass
else:
h[0] = 0
def move():
turtle.pensize(1)
turtle.color("green")
turtle.pu()
turtle.speed(3)
turtle.setheading(h[0])
turtle.shape("square")
turtle.stamp()
turtle.fd(20)
x = turtle.xcor()
y = turtle.ycor()
if b[0] > a[0]:
turtle.clearstamps(1)
pos.insert(0,[round(x),round(y)])
pos.pop(-1)
else:
pos.insert(0,[round(x),round(y)])
b[0] += 1
def gameover():
turtle.onscreenclick(None)
turtle.speed(0)
turtle.pu()
turtle.goto(0,150)
turtle.color("red")
turtle.write("Game Over",align="center", font=(10))
turtle.goto(0,50)
turtle.write("Score:" + str(a[0]),align="center",font=(10))
turtle.goto(200,-200)
turtle.write("(Click anywhere to return to the main menu)",align="right",font=(0.0000001))
turtle.onscreenclick(home)
turtle.mainloop()
# # # # # # # # # # # # # # # # # # # # # #
# Main #
# # # # # # # # # # # # # # # # # # # # # #
if __name__ == '__main__':
home(0,0)
I'm not sure what you mean by lagging but I've addressed a couple of issues in my rewrite below. The first is that turtles are global entities that don't get garbage collected under normal circumstances so don't recreate them, reuse them instead. Second, when you have your own while loop to control the game, you potentially lock out events. I've eliminated your loop and modified the game to work with ontimer events so that turtle movement should be handled by the same event loop that's handing user input, making it slightly more responsive to the user:
from turtle import Turtle, Screen
from random import randint
FONT = ('Arial', 18, 'bold')
# Up
def u():
if h[0] != 270:
h[0] = 90
# Down
def d():
if h[0] != 90:
h[0] = 270
# Left
def l():
if h[0] != 0:
h[0] = 180
# Right
def r():
if h[0] != 180:
h[0] = 0
def gameover():
screen.onkey(None, "Up")
screen.onkey(None, "Left")
screen.onkey(None, "Right")
screen.onkey(None, "Down")
tscore.clear()
tfood.clear()
tplayer.clear()
tfood.hideturtle()
tplayer.hideturtle()
tscore.color("red")
tscore.goto(0, 150)
tscore.write("Game Over", align="center", font=FONT)
tscore.goto(0, 50)
tscore.write("Score:" + str(a[0]), align="center", font=FONT)
tscore.goto(0, -200)
tscore.write("(Click anywhere to return to the main menu)", align="center", font=FONT)
screen.onscreenclick(home)
def food(tfood):
x = randint(-160, 160)
y = randint(-160, 160)
tfood.goto(x, y)
tfood.showturtle()
def move():
x, y = tplayer.position()
if -210 < x < 210 and -210 < y < 210:
if not tfood.isvisible():
food(tfood)
tplayer.setheading(h[0])
tplayer.stamp()
tplayer.forward(20)
if b[0] > a[0]:
tplayer.clearstamps(1)
pos.insert(0, [round(x), round(y)])
pos.pop(-1)
else:
pos.insert(0, [round(x), round(y)])
b[0] += 1
if tplayer.distance(tfood) < 15:
tfood.hideturtle()
tfood.clear()
a[0] += 1
tscore.clear()
tscore.write("Score:" + str(a[0]), align="center", font=FONT)
flag = True
x, y = tplayer.position()
if len(pos) > 1:
for i in range(1, len(pos)):
if pos[i][0] - 5 < x < pos[i][0] + 5 and pos[i][1] - 5 < y < pos[i][1] + 5:
flag = False
break
if flag:
screen.ontimer(move, 25)
else:
screen.ontimer(gameover, 100)
def level_1():
tmarker.penup()
tmarker.goto(-220, 220)
tmarker.pendown()
tmarker.goto(220, 220)
tmarker.goto(220, -220)
tmarker.goto(-220, -220)
tmarker.goto(-220, 220)
tmarker.penup()
def start(x, y):
screen.onscreenclick(None)
tscore.clear()
level_1()
tplayer.home()
tplayer.setheading(h[0])
tscore.goto(100, -250)
tscore.write("Score:" + str(a[0]), align="center", font=FONT)
screen.onkey(u, "Up")
screen.onkey(l, "Left")
screen.onkey(r, "Right")
screen.onkey(d, "Down")
move()
def home(x=0, y=0):
screen.onscreenclick(None)
a[0] = 0
b[0] = 0
h[0] = 0
pos[:] = []
tscore.clear()
tscore.home()
tscore.color('lime')
tscore.write("PLAY", align="center", font=FONT)
screen.onscreenclick(start)
# head orientation
h = [0]
# score
a = [0]
b = [0]
# position
pos = []
# turtles
tfood = Turtle('circle', visible=False)
tfood.speed('fastest')
tfood.color('red')
tfood.penup()
tscore = Turtle(visible=False)
tscore.speed('fastest')
tscore.penup()
tplayer = Turtle("square", visible=False)
tplayer.speed('slow')
tplayer.color("green")
tplayer.penup()
tmarker = Turtle(visible=False)
tmarker.speed('fastest')
tmarker.pensize(20)
tmarker.color("grey")
# # # # # # # # # # # # # # # # # # # # # #
# Main #
# # # # # # # # # # # # # # # # # # # # # #
if __name__ == '__main__':
screen = Screen()
screen.title("Snake Game")
screen.listen()
home()
screen.mainloop()

Categories

Resources