Python Turtle Space Invaders bullets not hitting invaders - python

I'm very new to turtle and python in general, so I apologize if my code seems messy.
I'm currently coding a turtle version of space invaders and I can't figure out why my invaders aren't dying when they hit the turtles. The code seems to be the same as all the other space invader turtle programs I can find. Any help would be greatly appreciated.
import turtle
import random
import math
#### Player ####
player1 = turtle.Turtle()
player1.shape("arrow")
player1.color("white")
player1.speed(0)
player1.penup()
player1.setheading(90)
player1.setposition(0, -175)
player1.speed(4)
def move_right():
x = player1.xcor()
x += playerspeed
if x > 210:
x = 210
player1.setx(x)
def move_left():
x = player1.xcor()
x -= playerspeed
if x < -210:
x = -210
player1.setx(x)
bulletlist = []
def fire():
if len(bulletlist) < 5:
bulletlist.append(Bullet())
#### Window ####
win = turtle.Screen()
win.bgcolor("black")
win.tracer(2)
border_pen = turtle.Turtle()
border_pen.speed(0)
border_pen.color("white")
border_pen.penup()
border_pen.setposition(-225, -225)
border_pen.pensize(3)
border_pen.pendown()
for side in range(4):
border_pen.fd(450)
border_pen.lt(90)
border_pen.hideturtle()
### Invader ###
class Invader(turtle.Turtle):
def __init__(self, xcor, ycor):
turtle.Turtle.__init__(self)
self.color("red")
self.shape("turtle")
self.penup()
self.speed(0)
self.setposition(xcor, ycor)
self.setheading(270)
self.speed(1)
self.hit = 0
### Bullet ###
bulletstate = 1
class Bullet(turtle.Turtle):
def __init__(self):
turtle.Turtle.__init__(self)
self.color("yellow")
self.shape("arrow")
self.shapesize(.5, 1)
self.penup()
self.speed(0)
self.setheading(90)
self.hideturtle()
self.bulletspeed = 20
fire()
def bullet_movement():
global firedb
firedb = bulletlist[-1]
firedb.speed(0)
ybul = firedb.ycor()
ybul += 10
firedb.sety(ybul)
if ybul > 195:
firedb.hideturtle()
def fire_bullet():
print("fire!")
firedb = bulletlist[-1]
firedb.hideturtle()
x = player1.xcor()
y = player1.ycor() + 20
firedb.setpos(x, y)
firedb.showturtle()
if firedb.ycor() > 200:
firedb.hideturtle()
bulletlist.remove(firedb)
def bulletmake():
bulletfire = Bullet()
def bulletmechanics():
fire()
fire_bullet()
win.listen()
win.onkey(move_left, "Left")
win.onkey(move_right, "Right")
win.onkey(fire_bullet, "space")
enemies = []
xx = -175
xxxx = -175
for invader in range(19):
if invader <= 9:
enemies.append(Invader(xx, 200))
xx += 30
if invader >= 9:
enemies.append(Invader(xxxx, 175))
xxxx += 30
playerspeed = 7
enemyspeed = 8
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(),2)+math.pow(t1.ycor()-t2.ycor(),2))
if distance < 15:
return True
else:
return False
dead = []
while True:
global firedb
firedb = bulletlist[-1]
fire()
bullet_movement()
for Invader in enemies:
bullet_movement()
# if Invader.distance(firedb.xcor()+200, firedb.ycor()+200) < 1:
if isCollision(bulletlist[-1], Invader) == True:
print("AAAAAAAAGH")
isCollision(firedb, Invader)
Invader.hit += 1
if Invader.hit == 1:
Invader.color("orange")
if Invader.hit == 2:
Invader.color("yellow")
if Invader.hit == 3:
Invader.speed(0)
Invader.setpos(1000, 1000)
dead.append(Invader)
Invader.hideturtle()
for invader in enemies:
bullet_movement()
xpos = invader.xcor()
invader.speed(0)
xpos += enemyspeed
invader.setx(xpos)
if invader.xcor() > 200:
for invader in enemies:
ypos = invader.ycor()
ypos -= 40
invader.sety(ypos)
enemyspeed *= -1
if invader.xcor() < -200:
for invader in enemies:
y = invader.ycor()
y -= 40
invader.sety(y)
enemyspeed *= -1

I belive your problem is the way you interlace bullet movements with invader movements. In your while True: loop (which shouldn't exist in an event-driven world like turtle) you call bullet_movement() at the top level, then in a for loop and again within a nested for loop. So where you see the bullet and where it is relative to invaders aren't necessarily the same.
I've reworked your code, and for example purposes, simplified it in places. Along with the above issues, I've also modified the code to use turtle tilt which is perfect for this sort of game where the turtles face in one direction but move in another. And I've completely trashed your isCollision() function as turtles already know how to compute their distance from another turtle.
from turtle import Screen, Turtle
class Invader(Turtle):
def __init__(self, xcor, ycor):
super().__init__(shape="turtle")
self.color("red")
self.penup()
self.setposition(xcor, ycor)
self.tilt(-90)
self.speed('slow')
self.hit = 0
class Bullet(Turtle):
def __init__(self):
super().__init__(shape="arrow", visible=False)
self.shapesize(.5, 1)
self.color("yellow")
self.penup()
self.setheading(90)
self.speed('fastest')
self.bulletspeed = 20
def move_right():
if player.xcor() + playerspeed < 210:
player.forward(playerspeed)
def move_left():
if player.xcor() - playerspeed > -210:
player.backward(playerspeed)
def bullet_movement():
firedb.forward(10)
if firedb.ycor() > 195:
firedb.hideturtle()
def fire_bullet():
if not firedb.isvisible():
x, y = player.position()
firedb.setposition(x, y + 20)
firedb.showturtle()
def isCollision(t1, t2):
return t1.distance(t2) < 20
def move():
global enemyspeed
if firedb.isvisible():
bullet_movement()
for invader in enemies:
if firedb.isvisible() and isCollision(firedb, invader):
invader.hit += 1
if invader.hit == 1:
invader.color("orange")
elif invader.hit == 2:
invader.color("yellow")
elif invader.hit == 3:
invader.hideturtle()
enemies.remove(invader)
firedb.hideturtle() # only one hit per bullet!
invader.forward(enemyspeed)
if invader.xcor() < -200 or invader.xcor() > 200:
for invader in enemies:
y = invader.ycor() - 40
invader.sety(y)
enemyspeed *= -1
win.update()
win.ontimer(move, 50)
#### Player ####
player = Turtle("arrow")
player.color("white")
player.penup()
player.tilt(90)
player.sety(-175)
player.speed('fast')
#### Window ####
win = Screen()
win.bgcolor("black")
win.tracer(False)
border_pen = Turtle(visible=False)
border_pen.speed('fastest')
border_pen.color("white")
border_pen.pensize(3)
border_pen.penup()
border_pen.setposition(-225, -225)
border_pen.pendown()
for _ in range(4):
border_pen.forward(450)
border_pen.left(90)
### Bullet ###
firedb = Bullet()
enemies = []
xx = -175
xxxx = -190
for invader_count in range(19):
if invader_count < 9:
enemies.append(Invader(xx, 200))
xx += 30
else:
enemies.append(Invader(xxxx, 175))
xxxx += 30
playerspeed = 7
enemyspeed = 2
win.onkey(move_left, "Left")
win.onkey(move_right, "Right")
win.onkey(fire_bullet, "space")
win.listen()
move()
win.mainloop()
Finally, be careful with Python global and turtle tracer() which are routinely misunderstood.

Related

Making python turtle based game reset on click

I'm trying to get my game to restart once the user clicks on the screen. I've tried wrapping the whole thing in a while loop, but that gave me errors about variables not being defined.
I've also tried wrapping the code in a function but that also gives me errors on variables.
Here's the code.
import turtle
import math
import random
import pygame
pygame.init()
pygame.mixer.init()
# MUSIC AND SOUND SETUP
pygame.mixer.music.load("Sounds/music.mp3")
pygame.mixer.music.play(loops=-1)
I'm using pygame just to add music into my game.
bubblefiredsound = pygame.mixer.Sound("Sounds/bubblefired.mp3")
enemyhitsound = pygame.mixer.Sound("Sounds/enemyhit.mp3")
# SCREEN SETUP
screen = turtle.Screen()
screen.bgcolor("black")
screen.title("Space Invaders")
screen.bgpic("TurtleInvadersBackground.png")
# CUSTOM SHAPES
turtle.register_shape("Enemy.gif")
turtle.register_shape("Turtle.gif")
turtle.register_shape("Bubble.gif")
# BORDERS
border_pen = turtle.Turtle()
border_pen.speed(0)
border_pen.color("white")
border_pen.penup()
border_pen.setposition(-300, -300)
border_pen.pendown()
border_pen.pensize(3)
for side in range(4):
border_pen.fd(600)
border_pen.lt(90)
border_pen.hideturtle()
# SCORE
score = 0
score_pen = turtle.Turtle()
score_pen.speed(0)
score_pen.color("white")
score_pen.penup()
score_pen.setposition(-290, 270)
scorestring = "Score: %s" % score
score_pen.write(scorestring, False, align="left", font=("Bubble3D", 20, "normal"))
score_pen.hideturtle()
# MAIN TURTLE
MajorTom = turtle.Turtle()
MajorTom.color("blue")
MajorTom.shape("Turtle.gif")
MajorTom.penup()
MajorTom.speed(0)
MajorTom.setposition(0, -250)
MajorTom.setheading(90)
playerspeed = 0
# NUMBER OF ENEMIES
number_of_enemies = 5
# PLACEHOLDER FOR ENEMIES
enemies = []
# ADD ENEMIES TO THE PLACEHOLDER
for i in range(number_of_enemies):
# CREATE ENEMIES
enemies.append(turtle.Turtle())
for enemy in enemies:
enemy.color("red")
enemy.shape("Enemy.gif")
enemy.penup()
enemy.speed(0)
x = random.randint(-200, 200)
y = random.randint(100, 250)
enemy.setposition(x, y)
enemyspeed = 5
# CREATE THE PROJECTILE BUBBLE
bubble = turtle.Turtle()
bubble.color("blue")
bubble.shape("Bubble.gif")
bubble.penup()
bubble.speed(0)
bubble.setheading(90)
bubble.hideturtle()
bubble.setpos(0, -300)
bubblespeed = 20
# BUBBLE STATE, READY = READY TO FIRE, FIRE = FIRING
bubblestate = "ready"
# MOVEMENT (LEFT AND RIGHT)
def move_left():
global playerspeed
playerspeed = -7
def move_right():
global playerspeed
playerspeed = 7
def stop_player():
global playerspeed
playerspeed = 0
def fire_bubble():
global bubblestate
if bubblestate == "ready":
bubblestate = "fire"
# MOVE BUBBLE TO MAJOR TOM
x = MajorTom.xcor()
y = MajorTom.ycor() + 10
bubble.setposition(x, y)
bubble.showturtle()
if bubblestate == "fire":
bubblefiredsound.play()
def CollisionDetection(t1, t2):
distance = math.sqrt(math.pow(t1.xcor() - t2.xcor(), 2) + math.pow(t1.ycor() - t2.ycor(), 2))
if distance < 32:
return True
else:
return False
# KEYBINDINGS
screen.listen()
screen.onkeypress(move_left, "a")
screen.onkeypress(move_right, "d")
screen.onkeyrelease(stop_player, "a")
screen.onkeyrelease(stop_player, "d")
screen.onkey(fire_bubble, "space")
This is the main loop, most of the code is put together here.
# GAME LOOP
while True:
# MOVE PLAYER
MajorTom.setx(MajorTom.xcor() + playerspeed)
# BORDER CONTROL
if MajorTom.xcor() > 285:
MajorTom.setx(285)
playerspeed = 0
elif MajorTom.xcor() < -285:
MajorTom.setx(-285)
playerspeed = 0
for enemy in enemies:
# ENEMY MOVEMENT
x = enemy.xcor()
x += enemyspeed
enemy.setx(x)
# MOVE THE ENEMY BACK AND DOWN
if enemy.xcor() > 280 or enemy.xcor() < -280:
# MOVE ALL ENEMIES DOWN
for e in enemies:
y = e.ycor()
y -= 40
e.sety(y)
# CHANGE ENEMY DIRECTION
enemyspeed *= -1
# BUBBLE HITS ENEMY
if CollisionDetection(bubble, enemy):
# PLAY BUBBLE BURST SOUND
enemyhitsound.play()
# RESET BUBBLE POSITION
bubble.hideturtle()
bubblestate = "ready"
bubble.setposition(0, -400)
# RESET ENEMY POSITION "SPAWN NEW ENEMY"
x = random.randint(-200, 200)
y = random.randint(100, 250)
enemy.setposition(x, y)
# ADD SCORE IF PLAYER HITS BUBBLE
score += 10
scorestring = "Score: %s" % score
score_pen.clear()
score_pen.write(scorestring, False, align="left", font=("Bubble3D", 20, "normal"))
if CollisionDetection(MajorTom, enemy) or enemy.ycor() < -300:
MajorTom.hideturtle()
enemy.hideturtle()
print("Game Over")
GameOverPen = turtle.Turtle()
GameOverPen.hideturtle()
GameOverPen.penup()
GameOverPen.goto(0,0)
GameOverPen.speed(0)
GameOverPen.color("pink")
GameOverPen.write("GAME OVER!", align="center", font=("Bubble3D", 90, "normal"))
GameOverPen.goto(0, -20)
GameOverPen.write("\nClick to try again!", align="center", font=("Arial", 20, "normal"))
break
# BUBBLE MOVEMENT
if bubblestate == "fire":
y = bubble.ycor()
y += bubblespeed
bubble.sety(y)
# CHECK TO SEE IF BUBBLE HAS HIT THE CEILING
if bubble.ycor() > 275:
bubble.hideturtle()
bubblestate = "ready"
you are looking for the turtle.onscreenclick function.
this function is called with the current x and y coordinates of the mouse when the screen is clicked.
def reset(x_pos, y_pos):
# reset the game
turtle.onscreenclick(reset)

how do i loop keys left and right in python using turtle

so i'm trying to loop the left and right keys to when i run the game code and press left or right i can hold left or right and the player moves left or right until i let off the key i'm using turtle
the code
enter code here
def move_left():
x = player.xcor()
x -= playerspeed
if x < -280:
x = -280
player.setx(x)
def move_right():
x = player.xcor()
x += playerspeed
if x > 280:
x = 280
player.setx(x)
def fire_bullet():
global bulletstate
if bulletstate == "ready":
winsound.PlaySound("stonks",winsound.SND_FILENAME |
winsound.SND_ASYNC)
bulletstate = "fire"
x = player.xcor()
y = player.ycor() + 10
bullet.setposition(x, y)
bullet.showturtle()
def iscollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(),2)+math.pow(t1.ycor()-
t2.ycor(),2))
if distance < 15:
return True
else:
return False
turtle.listen()
turtle.onkey(move_left, "Left")
turtle.onkey(move_right, "Right")
turtle.onkey(fire_bullet, "space")

Python Turtle module hideturtle() isn't working

I am writing the Space Invaders game from Christian Thompson
I have problem exactly in line 188 where the player and enemy hide when a collision is detected. My player turtle is hiding but the enemy turtle doesn't "want" to hide. Here is the code:
import turtle
import os
import math
import random
import winsound
#Set up the screen
wn = turtle.Screen()
wn.bgcolor("black")
wn.title("Space Invaders")
wn.bgpic("space_invaders_background.gif")
#Register the shapes
turtle.register_shape("invader.gif")
turtle.register_shape("player.gif")
#Draw border
border_pen = turtle.Turtle()
border_pen.speed(0)
border_pen.color("white")
border_pen.penup()
border_pen.setposition(-300,-300)
border_pen.pendown()
border_pen.pensize(3)
for side in range(4):
border_pen.fd(600)
border_pen.lt(90)
border_pen.hideturtle()
#Set the score to 0
score = 0
#Draw score
score_pen = turtle.Turtle()
score_pen.speed(0)
score_pen.color("white")
score_pen.penup()
score_pen.setposition(-290, 280)
scorestring = "Score: %s" %score
score_pen.write(scorestring, False, align="left", font=("Arial", 14, "normal"))
score_pen.hideturtle()
#Game Over
game_over = turtle.Turtle()
game_over.speed(0)
game_over.color("red")
game_over.penup()
game_over.setposition(0, 0)
gameOverMsg = "Game Over!"
game_over.hideturtle()
#Create player
player = turtle.Turtle()
player.color("blue")
player.shape("player.gif")
player.penup()
player.speed(0)
player.setposition(0,-230)
player.setheading(90)
playerspeed = 15
#Choose a number of enemies
number_of_enemies = 20
#Create empty list of enemies
enemies = []
#Add enemies to list
for i in range(number_of_enemies):
# Create the enemy
enemies.append(turtle.Turtle())
for enemy in enemies:
enemy.color("red")
enemy.shape("invader.gif")
enemy.penup()
enemy.speed(0)
x = random.randint(-200, 200)
y = random.randint(100, 250)
enemy.setposition(x, y)
enemyspeed = number_of_enemies * 0.5
#Create the player's bullet
bullet = turtle.Turtle()
bullet.color("yellow")
bullet.shape("triangle")
bullet.penup()
bullet.speed(0)
bullet.setheading(90)
bullet.shapesize(0.5, 0.5)
bullet.hideturtle()
bulletspeed = 20
def laser():
winsound.PlaySound("laser.wav", winsound.SND_ASYNC)
def explosion():
winsound.PlaySound("explosion.wav", winsound.SND_ASYNC)
#Move the player left and right
def move_left():
x = player.xcor()
x -= playerspeed
if x < -280:
x = -280
player.setx(x)
def move_right():
x = player.xcor()
x += playerspeed
if x > 280:
x = 280
player.setx(x)
def fire_bullet():
if not bullet.isvisible():
laser()
#Move the bullet to the just above the player
x = player.xcor()
y = player.ycor() + 10
bullet.setposition(x, y)
bullet.showturtle()
#Checking collision between enemy and bullet
def isCollision(t1, t2) :
distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(),2)+math.pow(t1.ycor()-t2.ycor(),2))
if distance < 20:
return True
else:
return False
#Create keyboard bindings
turtle.listen()
turtle.onkeypress(move_left, "Left")
turtle.onkeypress(move_right, "Right")
turtle.onkeypress(fire_bullet, "space")
#Main game loop
while True:
for enemy in enemies:
#Move the enemy
x = enemy.xcor()
x += enemyspeed
enemy.setx(x)
#Move the enemy back and down
if enemy.xcor() > 280:
#Move all enemies down
for e in enemies:
y = e.ycor()
y -= 40
e.sety(y)
#Change enemy direction
enemyspeed *= -1
if enemy.xcor() < -280:
#Move all enemies down
for e in enemies:
y = e.ycor()
y -= 40
e.sety(y)
#Change enemy direction
enemyspeed *= -1
# Check for a collision between the bullet and the enemy
if isCollision(bullet, enemy):
explosion()
# Reset the bullet
bullet.hideturtle()
bullet.setposition(0, -400)
# Reset the enemy
x = random.randint(-200, 200)
y = random.randint(100, 250)
enemy.setposition(x, y)
#Update the score
score += 10
scorestring = "Score: %s" %score
score_pen.clear()
score_pen.write(scorestring, False, align="left", font=("Arial", 14, "normal"))
if isCollision(player, enemy):
explosion()
player.hideturtle()
enemy.hideturtle()
game_over.write(gameOverMsg, False, align="center", font=("Arial", 60, "normal"))
break
#Move the bullet
if bullet.isvisible():
y = bullet.ycor()
y += bulletspeed
bullet.sety(y)
#Check border collision
if bullet.ycor() > 290:
bullet.hideturtle()
wn.mainloop()
I wasn't able to reproduce your problem. I've reworked your code below: I've dropped the images and sound so anyone can run it and help you debug it; I tossed your isCollision() code and substituted turtle's own distance() method; I replaced the while True: loop, which has no place in an event-driven world like turtle, with a timer event; I've streamlined the code where I could:
from turtle import Screen, Turtle
from random import randint
PLAYER_SPEED = 15
BULLET_SPEED = 20
# Choose a number of enemies
NUMBER_OF_ENEMIES = 20
SMALL_FONT = ('Arial', 14, 'normal')
LARGE_FONT = ('Arial', 60, 'normal')
# Move the player left and right
def move_left():
x = player.xcor() - PLAYER_SPEED
if x < -280:
x = -280
player.setx(x)
def move_right():
x = player.xcor() + PLAYER_SPEED
if x > 280:
x = 280
player.setx(x)
def fire_bullet():
if not bullet.isvisible():
# Move the bullet to the just above the player
x, y = player.position()
bullet.setposition(x, y + 10)
bullet.showturtle()
# Check collision between enemy and bullet
def isCollision(t1, t2):
return t1.distance(t2) < 20
# Set up the screen
wn = Screen()
wn.bgcolor('black')
wn.title("Space Invaders")
# Draw border
border_pen = Turtle(visible=False)
border_pen.speed('fastest')
border_pen.color('white')
border_pen.pensize(3)
border_pen.penup()
border_pen.setposition(-300, -300)
border_pen.pendown()
for _ in range(4):
border_pen.fd(600)
border_pen.lt(90)
# Set the score to 0
score = 0
# Draw score
score_pen = Turtle(visible=False)
score_pen.speed('fastest')
score_pen.color('white')
score_pen.penup()
score_pen.setposition(-290, 280)
scorestring = "Score: %s" % score
score_pen.write(scorestring, False, align='left', font=SMALL_FONT)
# Game Over
game_over = Turtle(visible=False)
game_over.speed('fastest')
game_over.color('red')
game_over.penup()
gameOverMsg = "Game Over!"
# Create player
player = Turtle('turtle')
player.speed('fastest')
player.color('blue')
player.penup()
player.setposition(0, -230)
player.setheading(90)
# Create empty list of enemies
enemies = []
# Add enemies to list
for _ in range(NUMBER_OF_ENEMIES):
# Create the enemy
enemy = Turtle('turtle', visible=False)
enemy.settiltangle(270) # for non GIF version of game
enemy.speed('fastest')
enemy.color('red')
enemy.penup()
enemy.setposition(randint(-200, 200), randint(100, 250))
enemies.append(enemy)
for enemy in enemies:
enemy.showturtle()
# Create the player's bullet
bullet = Turtle('triangle', visible=False)
bullet.color('yellow')
bullet.penup()
bullet.speed('fastest')
bullet.setheading(90)
bullet.shapesize(0.5)
# Create keyboard bindings
wn.onkeypress(move_left, 'Left')
wn.onkeypress(move_right, 'Right')
wn.onkeypress(fire_bullet, 'space')
wn.listen()
enemy_speed = NUMBER_OF_ENEMIES * 0.5
# Main game loop
def move():
global score, enemy_speed
collision = False
for enemy in enemies:
# Move the enemy
enemy.forward(enemy_speed)
# Check for a collision between the bullet and the enemy
if isCollision(bullet, enemy):
# Reset the bullet
bullet.hideturtle()
# Reset the enemy
enemy.setposition(randint(-200, 200), randint(100, 250))
# Update the score
score += 10
scorestring = "Score: %s" % score
score_pen.clear()
score_pen.write(scorestring, False, align='left', font=SMALL_FONT)
if isCollision(player, enemy):
player.hideturtle()
enemy.hideturtle()
game_over.write(gameOverMsg, False, align='center', font=LARGE_FONT)
collision = True
break
if any(enemy.xcor() < -280 or enemy.xcor() > 280 for enemy in enemies):
# Move all enemies down
for enemy in enemies:
enemy.sety(enemy.ycor() - 40)
# Change enemy direction
enemy_speed *= -1
# Move the bullet
if bullet.isvisible():
bullet.forward(BULLET_SPEED)
# Check border collision
if bullet.ycor() > 290:
bullet.hideturtle()
if not collision:
wn.ontimer(move, 50)
move()
wn.mainloop()
This program is déjà vu for me with respect to this question so see my answer to it for more ideas. Also, see this answer to another space invaders game in turtle to see what you can learn from it to polish your game.

Game loop in turtle python not functioning

Hi i am trying to create a simple environment/ game with turtle. It is a 3x4 grid with the upper right most square being the end goal. as the token enters this goal I would like the token to reset to the start. My while loop however seems to be freezing the script. I believe my logic here is wrong. the coordinates of the goal is (-25,225). I would like to check if the token's current position matches this and if so return true - this is the logic i would like to implement. Thanks for your help!
import turtle
wn = turtle.Screen()
wn.bgcolor("white")
wn.title("test")
""" Create the Grid """
greg = turtle.Turtle()
greg.speed(0)
def create_square(size,color="black"):
greg.color(color)
greg.pd()
for i in range(4):
greg.fd(size)
greg.lt(90)
greg.pu()
greg.fd(size)
def row(size,color="black"):
for i in range(4):
create_square(size)
def board(size,color="black"):
greg.pu()
greg.goto(-(size*4),(size*4))
for i in range(3):
row(size)
greg.bk(size*4)
greg.rt(90)
greg.fd(size)
greg.lt(90)
def color_square(start_pos,distance_sq, sq_width, color):
greg.pu()
greg.goto(start_pos)
greg.fd(distance_sq)
greg.color(color)
greg.begin_fill()
for i in range(4):
greg.fd(sq_width)
greg.lt(90)
greg.end_fill()
greg.pu()
def initiate_grid():
board(50)
color_square((-200,200),150, 50,color="green")
color_square((-200,150),50, 50,color="black")
color_square((-200,150),150, 50,color="red")
greg.hideturtle()
initiate_grid()
""" Create the token object """
player = turtle.Turtle()
player.color("blue")
player.shape("circle")
player.penup()
player.speed(0)
player.setposition(-175,125)
player.setheading(90)
""" Player Movement """
playerspeed = 50
#Move the player left and right
def move_left():
x = player.xcor()
x -= playerspeed
if x < -175:
x = -175
player.setx(x)
def move_right():
x = player.xcor()
x += playerspeed
if x > -25:
x = -25
player.setx(x)
def move_up():
y = player.ycor()
y += playerspeed
if y > 225:
y = 225
player.sety(y)
def move_down():
y = player.ycor()
y -= playerspeed
if y < 125:
y = 125
player.sety(y)
#Create Keyboard Bindings
turtle.listen()
turtle.onkey(move_left, "Left")
turtle.onkey(move_right, "Right")
turtle.onkey(move_up, "Up")
turtle.onkey(move_down, "Down")
def isGoal(player_pos):
if player_pos.xcor() == -25 and player_pos.ycor() == 225:
return True
else:
return False
#Main Game loop
while True:
#check for collision between player and goal
if isGoal(player):
#reset player
player.setposition(-175,125)
delay = input("Press enter to finish.")
EDIT :
I have now tried the following code. Game doesn't freeze anymore and once i enter the square the token appears inside the square but this is where the second problem occurs. I have now entered the square which should reset me back to my original position (-175, 125). However I need to press any key a second time in order for that reset to happen and by this time the token would have reset and moved one space based on the key I pressed. any ideas?
def isGoal():
if player.xcor() == -25 and player.ycor() == 225:
player.goto(-175,125)
else:
pass
""" Player Movement """
playerspeed = 50
#Move the player left and right
def move_left():
isGoal()
x = player.xcor()
x -= playerspeed
if x < -175:
x = -175
player.setx(x)
def move_right():
isGoal()
x = player.xcor()
x += playerspeed
if x > -25:
x = -25
player.setx(x)
def move_up():
isGoal()
y = player.ycor()
y += playerspeed
if y > 225:
y = 225
player.sety(y)
def move_down():
isGoal()
y = player.ycor()
y -= playerspeed
if y < 125:
y = 125
player.sety(y)
#Create Keyboard Bindings
turtle.listen()
turtle.onkey(move_left, "Left")
turtle.onkey(move_right, "Right")
turtle.onkey(move_up, "Up")
turtle.onkey(move_down, "Down")
delay = input("Press enter to finish.")
Your while loop prevents anything else to happen indeed. What you want here is to put your isGoal() checks in the move_<XXX> event handlers and let turtle's own main loop run.
EDIT: for your second question:
However I need to press any key a second time in order for that reset to happen
the reason is quite simple: you should call isGoal() after you move the player's turtle, not before:
def move_left():
x = player.xcor()
x -= playerspeed
if x < -175:
x = -175
player.setx(x)
isGoal()

Space Invaders movement is acting really weird [duplicate]

I've created a Space Invaders clone in Python using the PyGame modules but I'm running into some difficulty getting them to move down together when reaching the edge of the game screen.
How would I make it so when the aliens reach the edge of the game screen they all simultaneously change direction and drop down a level?
import pygame
import random
class spaceInvader(pygame.sprite.Sprite):
def __init__(self):
self.image = pygame.image.load("spaceInvader.png")
self.x = 200
self.y = 390
self.shots = []
def handle_keys(self):
key = pygame.key.get_pressed()
dist = 5
if key[pygame.K_RIGHT]:
self.x+=dist
elif key[pygame.K_LEFT]:
self.x-=dist
def draw(self, surface):
surface.blit(self.image,(self.x,self.y))
for s in self.shots:
s.draw(screen)
class Alien(pygame.sprite.Sprite):
def __init__(self,x,y,direction,alienType):
pygame.sprite.Sprite.__init__(self)
self.AlienType = alienType
self.Direction = direction
if alienType == 1:
alienImage = pygame.image.load("alien1.png")
self.Speed = 1
self.Score = 5
if alienType == 2:
alienImage = pygame.image.load("alien2.png")
self.Score = 15
self.Speed = 1
if alienType == 3:
alienImage = pygame.image.load("alien3.png")
self.Score = 10
self.Speed = 1
if alienType == 4:
alienImage = pygame.image.load("alien4.png")
self.Score = 20
self.Speed = 1
if alienType == 5:
alienImage = pygame.image.load("alien5.png")
self.Score = 25
self.Speed = 1
self.image = pygame.Surface([26, 50])
self.image.set_colorkey(black)
self.image.blit(alienImage,(0,0))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def moveAliens(self):
if self.Direction == "right":
self.rect.x += self.Speed
if self.Direction == "left":
self.rect.x -= self.Speed
pygame.init()
pygame.mouse.set_visible(False)
screen = pygame.display.set_mode([400,400])
allAliens = pygame.sprite.Group()
spaceInvader = spaceInvader()
pygame.display.set_caption("Space Attack")
background_image = pygame.image.load("Galaxy.png").convert()
pygame.mouse.set_visible(True)
done = False
clock = pygame.time.Clock()
black =( 0, 0, 0)
white =( 255,255,255)
red = (255, 0, 0)
score = 0
enemies = []
#For X coords
spawnPositions = [50,100,150,200,250,300,350]
yCoord = 10
for n in range(5):
for i in range(len(spawnPositions)):
xCoord = spawnPositions[i]
alienType = random.randint(1,5)
alien = Alien(xCoord, yCoord,"right", alienType)
allAliens.add(alien)
yCoord = yCoord + 15
loop = 0
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
for alien in (allAliens.sprites()):
if alien.rect.x < 0:
alien.rect.y = alien.rect.y + 15
alien.Direction = "right"
if alien.rect.x > 395:
alien.rect.y = alien.rect.y + 15
alien.Direction = "left"
loop =+1
for alien in (allAliens.sprites()):
alien.moveAliens()
spaceInvader.handle_keys()
screen.blit(background_image,[0,0])
spaceInvader.draw(screen)
allAliens.draw(screen)
pygame.display.flip()
clock.tick(20)
pygame.quit()
Thanks.
Your problem lies here:
for alien in (allAliens.sprites()):
if alien.rect.x < 0:
alien.rect.y = alien.rect.y + 15
alien.Direction = "right"
if alien.rect.x > 395:
alien.rect.y = alien.rect.y + 15
alien.Direction = "left"
loop =+1
I assume the aliens are currently individually dropping down?
You need to change this so that when one alien triggers these if statements, all alien's y and direction are appropriately set, not just the one hitting the side.
# Space Invader
import turtle
import os
import random
import math
# Set up the screen.
wn = turtle.Screen()
wn.setup(700,700)
wn.bgcolor("lightblue")
wn.title("Space Invaders")
# Draw border
border = turtle.Turtle()
border.speed("fastest")
border.color("white")
border.penup()
border.setposition(-300,-270)
border.pendown()
border.pensize(3)
for side in range(4):
border.forward(560)
border.left(90)
border.hideturtle()
# Set the score to 0.
score = 0
# Draw the score.
score_pen = turtle.Turtle()
score_pen.speed("fastest")
score_pen.color("white")
score_pen.penup()
score_pen.setposition(-290,260)
scorestring = "Score: %s" %score
score_pen.write(scorestring, False, align="left", font = ("Arial",14,"normal"))
score_pen.hideturtle()
# Create the player turtle
player = turtle.Turtle()
player.color("black")
player.speed("fastest")
player.shape("triangle")
player.penup()
player.setposition(0,-265)
player.setheading(90)
playerspeed = 15
# Create enemy
#enemy = turtle.Turtle()
#enemy.shape("circle")
#enemy.color("red")
#enemy.penup()
#enemy.speed(2)
#enemy.setposition(-200,250)
#enemyspeed = 2
# Choose number of enemies.
number_of_enemies = 5
# Create an empty list of enemies.
enemies = []
# Add enemies to list.
for i in range(number_of_enemies):
# Create enemy
enemies.append(turtle.Turtle())
for enemy in enemies:
enemy.shape("circle")
enemy.color("red")
enemy.penup()
enemy.speed(2)
x = random.randint(-200,200)
y = random.randint(100,250)
enemy.setposition(x,y)
enemyspeed = 2
# Create the player's bullet.
bullet = turtle.Turtle()
bullet.color("yellow")
bullet.shape("triangle")
bullet.penup()
bullet.speed("fastest")
bullet.setheading(90)
bullet.shapesize(.5,.5)
bullet.hideturtle()
bulletspeed = 20
# Define bullet state
# ready - ready to fire
# fire - bullet is firing
bulletstate = "ready"
# Move the player left and right.
def move_left():
x = player.xcor()
x -= playerspeed
if x < -280:
x = -280
player.setx(x)
def move_right():
x = player.xcor()
x += playerspeed
if x >250:
x = 250
player.setx(x)
def fire_bullet():
# Declare the bulletstate as a global if it needs changed.
global bulletstate
if bulletstate == "ready":
bulletstate = "fire"
# Move the bullet just above the player.
x = player.xcor()
y = player.ycor() + 10
bullet.setposition(x,y)
bullet.showturtle()
def isCollision(t1,t2):
dx = t1.xcor() - t2.xcor()
dy = t1.ycor()- t2.ycor()
distance = dx**2 + dy**2
distance1 = math.sqrt(distance)
if distance1 < 15:
return True
else:
return False
# Create keyboard bindings
wn.onkey(move_left, "Left")
wn.onkey(move_right,"Right")
wn.onkey(fire_bullet,"space")
wn.listen()
# Main game loop
while True:
for enemy in enemies:
# Move enemy
x = enemy.xcor()
x += enemyspeed
enemy.setx(x)
# Move the enemy back and down
if enemy.xcor()>250:
# Move all the enemies down
for e in enemies:
y = e.ycor()
y -= 40
e.sety(y)
# Change the enemy direction
enemyspeed *= -1
if enemy.xcor()< -280:
# Move all the enemies down
for e in enemies:
y = e.ycor()
y -= 40
e.sety(y)
# change the enemy direction
enemyspeed *= -1
# Check for the collision between bullet and the enemy.
if isCollision(bullet ,enemy):
# Reset the bullet
bullet.hideturtle()
bulletstate = "ready"
bullet.setposition(0,-400)
# Reset the enemy
x = random.randint(-200,200)
y = random.randint(100,250)
enemy.setposition(x,y)
# Update the score.
score += 1
scorestring = "Score: %s" %score
score_pen.clear()
score_pen.write(scorestring, False, align = "left",font = ("Arial",14, "normal"))
if isCollision(player,enemy):
player.hideturtle()
enemy.hideturtle()
print("Game Over")
break
# Move the bullet.
if bulletstate == "fire":
y = bullet.ycor()
y += bulletspeed
bullet.sety(y)
# Check to see if the bullet has gone to the top.
if bullet.ycor() > 275:
bullet.hideturtle()
bulletstate = "ready"
turtle.mainloop()

Categories

Resources