How to make enemy follow player in pygame? - python

Ok, I've created a small game with pygame.draw.rect and so far I have created a player who can move around on the screen and an enemy who doesn't do anything as of right now. I would like the enemy to follow the player around on the screen if I come within a certain distance (say 100 pixels). How would I define this? My player starts at x = 300 and y = 300, the enemy starts at x = 500 and y = 400.
import pygame
import time
import random
import math
pygame.init()
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
blue = (35,65,155)
gameDisplay = pygame.display.set_mode((1280,800))
pygame.display.set_caption('Practice Game')
#FPS
clock = pygame.time.Clock()
#player block size
block_size = 20
#enemy block size
block_sz = 30
enemy_x = 500
enemy_y = 400
#player health
playerHealth = 100
#Health image
healthImg = pygame.image.load('healthbarimg.png')
#enemy image
enemyImg = pygame.image.load('enemyimg.png')
font = pygame.font.SysFont(None, 25)
def player(block_size, playerList):
for XnY in playerList:
pygame.draw.rect(gameDisplay, black, [XnY[0],XnY[1],block_size,block_size])
def enemy(block_sz):
#gameDisplay.blit(enemyImg,(900,700))
pygame.draw.rect(gameDisplay, blue,(enemy_x,enemy_y,block_sz,block_sz))
def playerHp(block_sz):
gameDisplay.blit(healthImg,(10,10))
gameDisplay.blit(healthImg,(45,10))
gameDisplay.blit(healthImg,(80,10))
def message_to_screen(msg,color):
screen_text = font.render(msg, True, color)
gameDisplay.blit(screen_text, [450,350])
def gameLoop():
gameExit = False
gameOver = False
lead_x = 300
lead_y = 300
enemy_x = 500
enemy_y = 400
enemy_x_change = 0
enemy_y_change = 0
lead_x_change = 0
lead_y_change = 0
healthList = []
healthLength = 1
playerList = []
playerLength = 1
randAppleX = round(random.randrange(0, 800-10))#/10.0)*10.0
randAppleY = round(random.randrange(0, 800-10))#/10.0)*10.0
while not gameExit:
while gameOver == True:
gameDisplay.fill(white)
message_to_screen("Game over, press C to play again or Q to quit", red)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameOver = False
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change = -10
if event.key == pygame.K_RIGHT:
lead_x_change = 10
if event.key == pygame.K_UP:
lead_y_change = -10
if event.key == pygame.K_DOWN:
lead_y_change = 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
lead_x_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
lead_y_change = 0
if lead_x >= 1280 or lead_x < 0 or lead_y >= 800 or lead_y < 0:
gameOver = True
'''if enemy_x >= 900:
enemy_x = -10 * enemySpeed
if enemy_x <= 250:
enemy_x = 10 * enemySpeed
if enemy_y >= 700:
enemy_y = -10 * enemySpeed
if enemy_y <= 50:
enemy_y = -10 * enemySpeed'''
pygame.display.update()
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(white)
AppleThickness = 30
pygame.draw.rect(gameDisplay, red, [randAppleX, randAppleY, AppleThickness,AppleThickness])
playerHead = []
playerHead.append(lead_x)
playerHead.append(lead_y)
playerList.append(playerHead)
if len(playerList) > playerLength:
del playerList[0]
player(block_size, playerList)
enemy(block_sz)
playerHp(block_sz)
pygame.display.update()
## if lead_x >= randAppleX and lead_x <= randAppleX + AppleThickness:
## if lead_y >= randAppleY and lead_y <= randAppleY + AppleThickness:
## randAppleX = round(random.randrange(0, 800-10))#/10.0)*10.0
## randAppleY = round(random.randrange(0, 800-10))#/10.0)*10.0
## snakeLength += 1
if lead_x > randAppleX and lead_x < randAppleX + AppleThickness or lead_x + block_size > randAppleX and lead_x + block_size < randAppleX + AppleThickness:
#print("x crossover")
if lead_y > randAppleY and lead_y < randAppleY + AppleThickness:
randAppleX = round(random.randrange(0, 800-10))#/10.0)*10.0
randAppleY = round(random.randrange(0, 800-10))#/10.0)*10.0
playerLength += 1
elif lead_y + block_size > randAppleY and lead_y + block_size < randAppleY + AppleThickness:
randAppleX = round(random.randrange(0, 800-10))#/10.0)*10.0
randAppleY = round(random.randrange(0, 800-10))#/10.0)*10.0
playerLength += 1
clock.tick(10)
pygame.quit()
quit()
gameLoop()

First you have to solve an issue. The variables enemy_x and enemy_y are declared twice. Onec global and once inside the gameLoop. Keep the global variables, but delete the local variables in the function:
enemy_x = 500
enemy_y = 400
# [...]
def gameLoop():
global enemy_x, enemy_y
# [...]
# enemy_x = 500 <---- delete this
# enemy_y = 400 <---- delete this
Define a threshold distance between the enemy and the player, which activates and deactivates the following up and define the speed of the enemy:
e.g.
enemySpeed = 5
min_dist = 200
To make the enemy follow player you have to calculate the distance between the enemy and the player:
delta_x = lead_x - enemy_x
delta_y = lead_y - enemy_y
Check if the player is close enough to the enemy. Test whether the threshold is undershot in both directions (x and y). Decide i the enemy steps along the x or y axis:
if abs(delta_x) <= min_dist and abs(delta_y) <= min_dist:
enemy_move_x = abs(delta_x) > abs(delta_y)
If the enemy is far away enough on both axis (more then 1 step), the the axis for the step can be chosen randomly. Note this is optional:
if abs(delta_x) > enemySpeed and abs(delta_x) > enemySpeed:
enemy_move_x = random.random() < 0.5
Do a step with the enemy, but limit the step by the distance to the player (the enemy should not step "over" the player):
if enemy_move_x:
enemy_x += min(delta_x, enemySpeed) if delta_x > 0 else max(delta_x, -enemySpeed)
else:
enemy_y += min(delta_y, enemySpeed) if delta_y > 0 else max(delta_y, -enemySpeed)
Add the code after lead_x and lead_y have been updated:
enemySpeed = 5
min_dist = 200
while not gameExit:
while gameOver == True:
gameDisplay.fill(white)
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
# [...]
pygame.display.update()
lead_x += lead_x_change
lead_y += lead_y_change
delta_x = lead_x - enemy_x
delta_y = lead_y - enemy_y
if abs(delta_x) <= min_dist and abs(delta_y) <= min_dist:
enemy_move_x = abs(delta_x) > abs(delta_y)
if abs(delta_x) > enemySpeed and abs(delta_x) > enemySpeed:
enemy_move_x = random.random() < 0.5
if enemy_move_x:
enemy_x += min(delta_x, enemySpeed) if delta_x > 0 else max(delta_x, -enemySpeed)
else:
enemy_y += min(delta_y, enemySpeed) if delta_y > 0 else max(delta_y, -enemySpeed)
gameDisplay.fill(white)
# [...]

You need a pathfinding. The most frequently used pathfinding in games is A* pathfinding. There has been tons of implementations in Python.
However, A* algorithm will find a shortest path to the target (thus, the player) and it may not be a necessity. Dumb moves sometimes give player time to react and knock back, so simply move towards the player with regardless of obstacles would probably be sufficient. The situation depends.

Related

How do I make the bullets to shoot towards my mouse when I leftclick in this code? [duplicate]

This question already has answers here:
How can you rotate the sprite and shoot the bullets towards the mouse position?
(1 answer)
calculating direction of the player to shoot pygame
(1 answer)
Shooting a bullet in pygame in the direction of mouse
(2 answers)
Closed 2 years ago.
import pygame
import random
import math
from pygame import mixer
pygame.init()
screen = pygame.display.set_mode((1280, 720))
background = pygame.image.load('1264.jpg')
background = pygame.transform.scale(background, (1290, 720))
pygame.display.set_caption("FlySwapper")
icon = pygame.image.load('logo.png')
pygame.display.set_icon(icon)
playerImg = pygame.image.load('Frosk.png')
playerX = 580
playerY = 550
playerX_change = 0
playerY_change = 0
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemyImg.append(pygame.image.load('flue.png'))
enemyX.append(random.randint(0, 1290))
enemyY.append(random.randint(0, 310))
enemyX_change.append(0.5)
enemyY_change.append(0.5)
bulletImg = pygame.image.load('skudd.png')
bulletX = 0
bulletY = 0
bulletX_change = 2
bulletY_change = 2
bullet_state = "ready"
def player(x, y):
screen.blit(playerImg, (x, y))
def enemy(x, y, i):
screen.blit(enemyImg[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bulletImg, (x + 35, y + 10))
running = True
while running:
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
playerX_change = -1
if event.key == pygame.K_d:
playerX_change = 1
if event.key == pygame.K_w:
playerY_change = -1
if event.key == pygame.K_s:
playerY_change = 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
playerX_change = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
playerY_change = 0
LEFT = 1
RIGHT = 3
if event.type == pygame.MOUSEBUTTONUP and event.button == LEFT:
if bullet_state == "ready":
#bullet_Sound = mixer.Sound('.wav')
#bullet_Sound.play()
bulletX = playerX
bulletY = playerY
fire_bullet(bulletX, bulletY)
playerX += playerX_change
playerY += playerY_change
if playerX <= 0:
playerX = 0
elif playerX >= 1150:
playerX = 1150
if playerY <= 310:
playerY = 310
elif playerY >= 590:
playerY = 590
player(playerX, playerY)
for i in range(num_of_enemies):
enemyX[i] += enemyX_change[i]
enemyY[i] += enemyY_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 0.5
elif enemyX[i] >= 1150:
enemyX_change[i] = -0.5
if enemyY[i] <= 0:
enemyY_change[i] = 0.5
elif enemyY[i] >= 590:
enemyY_change[i] = -0.5
enemy(enemyX[i], enemyY[i], i)
if bulletY <= 0:
bullet_state = "ready"
if bullet_state == "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
pygame.display.update()
I have been trying to make the bullet go towards my mouse on left click for weeks, my teacher can't help me apparantly and I am pretty new to python.
I know that I have made the bullet to only go forward in this code, but I was planning on changing it to go towards the mouse click later.
I'm sorry if this was a bad explanation of my problem.
When you click the mouse, you need to calculate the normalized direction vector (Unit vector) from the start position of the bullet to the mouse position. Define the speed of the bullet and multiply the direction vector by the speed:
dx = event.pos[0] - bulletX
dy = event.pos[1] - bulletY
dist = math.sqrt(dx*dx + dy*dy)
bulletX_change = bullet_speed * dx/dist
bulletY_change = bullet_speed * dy/dist
relevant changes:
def fire_bullet(x, y):
screen.blit(bulletImg, (x + 35, y + 10))
running = True
while running:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# [...]
if event.type == pygame.MOUSEBUTTONUP and event.button == LEFT:
if bullet_state == "ready":
#bullet_Sound = mixer.Sound('.wav')
#bullet_Sound.play()
bulletX = playerX
bulletY = playerY
bullet_state = "fire"
dx = event.pos[0] - bulletX
dy = event.pos[1] - bulletY
dist = math.sqrt(dx*dx + dy*dy)
bulletX_change = bullet_speed * dx/dist
bulletY_change = bullet_speed * dy/dist
# [...]
if playerX < 0 or bulletY < 0 or playerX > 1280 or bulletY > 720:
bullet_state = "ready"
if bullet_state == "fire":
bulletX += bulletX_change
bulletY += bulletY_change
fire_bullet(bulletX, bulletY)
pygame.display.update()

Python Snake Tutorial, Tail/Speed

I am trying to add a tail to my snake (at the very end use a triangle image rather than a square fill). While I think I got the code to work for the most part, I was seeing that if I changed directions, the last few seconds the tail would "disconnect" from the body. (tail points right and body going down leaves a gap). I tried to fix this by upping my FPS which seemed to work; however I wanted the snake speed to be the same as before and since I doubled the FPS I would have to 1/2 the speed. When I did that however, my collision detection was out of sync and if I slowed it down my body would draw over my face, and if I sped up I would have my body getting disconnected (block, space, block). I have tried it a few different ways so any help would be appreciated.
Please note that block_speed = 10, and if I manually type 10 it works, but if I change to 5 or 20, or if I change to a variable with value of 5 or 20 (say speed for example), the code does not work.
Code:
import pygame, sys
from pygame.locals import*
import time
import random
import os
pygame.init()
#GUI Settings
display_Width = 800
display_Height = 600
gameDisplay = pygame.display.set_mode((display_Width,display_Height))
pygame.display.set_caption("Gluttonous Snake")
gameicon = pygame.image.load('icon.png')
potatoimg = pygame.image.load('potato.png')
pygame.display.set_icon(gameicon)
FPS = 15
direction = "up"
#set path to where to .py/.exe is
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
print(dname)
snakeheadimg = pygame.image.load('snakehead.png')
snaketailimg = pygame.image.load('snaketail.png')
appleimg = pygame.image.load('apple.png')
#define colors
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
yellow = (255,255,0)
eggwhite = (255,255,204)
lightgrey = (242,242,242)
#Game Variables
block_size = 10
clock = pygame.time.Clock()
def game_intro():
intro = True
x = 500
y = 400
x_dir = "left"
while intro:
gameDisplay.fill(eggwhite)
gameDisplay.blit(potatoimg, (50, 25))
message_to_screen("Potato Productions Presents...", black, -100, size=45)
message_to_screen("Gluttonous Snake", green, -25, size=75)
message_to_screen("A game made by a potato to run on a potato", black, 50, size=25)
message_to_screen("Press C to Start!", red, 75, size=25)
gameDisplay.blit(gameicon, (x, y))
if x_dir == "left":
if x > 0:
x -= 10
else:
x_dir = "right"
else:
if x < 500:
x += 10
else:
x_dir = "left"
if x < 125 or x > 375:
y -= 9.66
else:
y += 10
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
intro = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
intro = False
if event.key == pygame.K_q:
pygame.quit()
quit()
def pickFont(name,size):
font = pygame.font.SysFont(name, size, bold=False)
return font
#font size = 25
#font = pygame.font.SysFont("comicsansms",size=25)
def snake(snakelist):
# faster GPU method is
# gameDisplay.fill(red, rect=[200,200,50,50])
if direction == "left":
head = pygame.transform.rotate(snakeheadimg,90)
if direction == "right":
head = pygame.transform.rotate(snakeheadimg,270)
if direction == "down":
head = pygame.transform.rotate(snakeheadimg,180)
if direction == "up":
head = pygame.transform.rotate(snakeheadimg,0)
gameDisplay.blit(head,(snakelist[-1][0],snakelist[-1][1]))
#-1 because we are drawing that above
# for XnY in snakelist[:-1]:
# #gameDisplay.fill(green, rect=[lead_x, lead_y, block_size, block_size])
# gameDisplay.fill(green, rect=[XnY[0], XnY[1], block_size, block_size])
# -1 because we are drawing that above
if len(snakelist) >= 2:
for XnY in snakelist[1:-1]:
gameDisplay.fill(green, rect=[XnY[0], XnY[1], block_size, block_size])
if direction == "up":
tail = pygame.transform.rotate(snaketailimg, 180)
if snakelist[1][0] > snakelist[0][0]:
tail = pygame.transform.rotate(snaketailimg, 90)
elif snakelist[1][0] < snakelist[0][0]:
tail = pygame.transform.rotate(snaketailimg, 270)
elif snakelist[1][1] > snakelist[0][1]:
tail = pygame.transform.rotate(snaketailimg, 0)
elif snakelist[1][1] < snakelist[0][1]:
tail = pygame.transform.rotate(snaketailimg, 180)
gameDisplay.blit(tail, (snakelist[-len(snakelist)][0], snakelist[-len(snakelist)][1]))
def text_objects(text, color,size):
font = pickFont("comicsansms", size)
textSurface = font.render(text,True,color,size)
return textSurface, textSurface.get_rect()
def message_to_screen(msg,color,y_displace=0, size=25):
#True is anti-aliasing
textSurf, textRect = text_objects(msg, color, size)
textRect.center = (display_Width/2),(display_Height/2) + y_displace
gameDisplay.blit(textSurf,textRect)
def gameLoop():
# set up variables
global direction
gameExit = False
gameOver = False
lead_x = display_Width / 2
lead_y = display_Height / 2
coinflip = random.randint(0, 1)
if coinflip == 0:
coinflip = random.randint(0, 1)
if coinflip == 0:
lead_x_change = **10**
lead_y_change = 0
direction = "right"
else:
lead_x_change = -**10**
lead_y_change = 0
direction = "left"
else:
coinflip = random.randint(0, 1)
if coinflip == 0:
lead_x_change = 0
lead_y_change = **10**
direction = "down"
else:
lead_x_change = 0
lead_y_change = -**10**
direction = "up"
#lead_x_change = 0
#lead_y_change = 0
#the 10 is round to 10
randAppleX = random.randrange(0, display_Width - block_size, 10)
randAppleY = random.randrange(0, display_Height - block_size, 10)
snakelist = []
snakelength = 1
while not gameExit:
while gameOver == True:
gameDisplay.fill(white)
#message_to_screen("Game over \n Press C to play again or Q to quit", red)
message_to_screen("Game Over", red, y_displace=-50, size=75)
message_to_screen("Press C to play again or Q to quit",black,y_displace=50,size=25)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
#gameOver = False
for event in pygame.event.get():
#shows every mouse move and key pressed
#print(event)
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
#check for single depress of keys
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
#lead_x -= 10
#this is so they can't back over themselves
if lead_x_change != **block_size**:
lead_x_change = - **block_size**
lead_y_change = 0
direction = "left"
#elif is only tested if the ifs and elifs above it are not true
elif event.key == pygame.K_RIGHT:
#lead_x += 10
if lead_x_change != -**block_size**:
lead_x_change = **block_size**
lead_y_change = 0
direction = "right"
elif event.key == pygame.K_UP:
if lead_y_change != **block_size**:
lead_x_change = 0
lead_y_change = -**block_size**
direction = "up"
elif event.key == pygame.K_DOWN:
if lead_y_change != -**block_size**:
lead_x_change = 0
lead_y_change = **block_size**
direction = "down"
# user releases key
# if event.type == pygame.KEYUP:
# if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
# lead_x_change = 0
#Ends the game once the square has left the window
if lead_x >= (display_Width - block_size) or lead_x <= 0 or lead_y >= (display_Height - block_size) or lead_y <= 0:
print("snake left at " + str(lead_x)+","+str(lead_y))
lead_x_change = 0
lead_y_change = 0
gameOver = True
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(lightgrey)
snakehead = []
snakehead.append(lead_x)
snakehead.append(lead_y)
snakelist.append(snakehead)
if len(snakelist) > snakelength:
del snakelist[0]
#-1 because last element is the head
for eachSegement in snakelist[:-1]:
if eachSegement == snakehead:
print("snake eats itself")
gameOver = True
#draw snake first so if apple spawns on it I can still see it
snake(snakelist)
#gameDisplay.fill(red, rect=[randAppleX, randAppleY, block_size, block_size])
gameDisplay.blit(appleimg,(randAppleX, randAppleY))
pygame.display.update()
#better collison detection as part of the snake can go over part of the apple
# if lead_x >= randAppleX and lead_x + block_size < randAppleX + block_size or lead_x + block_size >= randAppleX and lead_x + block_size < randAppleX + block_size:
# if lead_y >= randAppleY and lead_y < randAppleY + block_size or lead_y + block_size >= randAppleY and lead_y + block_size < randAppleY + block_size:
if lead_x >= randAppleX:
if lead_x + block_size <= randAppleX + block_size:
if lead_y >= randAppleY:
if lead_y + block_size <= randAppleY + block_size:
print("nom nom nom")
randAppleX = random.randrange(0, display_Width - block_size, 10)
randAppleY = random.randrange(0, display_Height - block_size, 10)
snakelength += 1
#used to make FPS
clock.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
Reply to answer provided:
Great thanks I will look into this. Were you able to figure out why I can't adjust the speed though? Seems weird it would draw the body over the head if I slow down the speed, or it will leave gaps if I speed it up. The part were I was adjusting the speed was in bold
You can probably smooth things a bit (and make your code clearer) by doing the following:
1 - store the tail (head) rotated images:
tail_left = pygame.transform.rotate(snaketailimg, 180) # choose appropriate rotation
tail_right = ...
tail_up = ...
tail_down = ...
2 - determine which direction the snake goes, and look up the images from a dict (for instance)
tail_oriented_images = {'left': tail_left, 'right': tail_right, ...}
...
tail_direction = get_tail_direction() # to be extracted
3- then replace the if cascade in snake(snakelist) with:
tail = tail_oriented_images[tail_direction]
4- Do the same for the head direction

Python Snake Game Boundries not working

I'm new to python and I'm trying following along with a tutorial that uses PyGame to create a snake like game. For some reason my boundaries are not working. It may be something simple but I can't see any reason why it wouldn't work. I don't get any errors, the snake just goes past the boundaries and the game doesn't end.
import pygame
import time
import random
pygame.init()
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Slither')
clock = pygame.time.Clock()
block_size = 10
FPS = 30
font = pygame.font.SysFont(None, 25)
def message_to_screen(msg,color):
screen_text = font.render(msg, True, color)
gameDisplay.blit(screen_text, [display_width/2, display_height/2])
def gameLoop():
gameExit = False
gameOver = False
lead_x = display_width/2
lead_y = display_height/2
lead_x_change = 0
lead_y_change = 0
randAppleX = random.randrange (0, display_width-block_size)
randAppleY = random.randrange (0, display_height-block_size)
while not gameExit:
while gameOver == True:
gameDisplay.fill(white)
message_to_screen("Game over, press C to play again or Q to quit", red)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change = -block_size
lead_y_change = 0
elif event.key == pygame.K_RIGHT:
lead_x_change = block_size
lead_y_change = 0
elif event.key == pygame.K_UP:
lead_y_change = -block_size
lead_x_change = 0
elif event.key == pygame.K_DOWN:
lead_y_change = block_size
lead_X_change = 0
**if lead_x >= display_width or lead_x < 0 or lead_y >= display_height or lead_y < 0:
gameOver == True #boundaries**
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(white)
pygame.draw.rect(gameDisplay, red, [randAppleX, randAppleY, block_size, block_size])
pygame.draw.rect(gameDisplay, black, [lead_x , lead_y, block_size, block_size])
pygame.display.update()
clock.tick(FPS)
message_to_screen("You Lose", red)
pygame.display.update()
time.sleep(2)
pygame.quit()
quit()
gameLoop()
In your exit condition, you're using the equality comparison, not the assignment operator:
if lead_x >= display_width or lead_x < 0 or lead_y >= display_height or lead_y < 0:
gameOver == True #boundaries
in the above,
gameOver == True
should be
gameOver = True

Index List Error

I am having a problem and i dont really even know what the problem is but my code but i already had the first problem fixed then this occured. Please help me fix this, or find out what is wrong.
import pygame
import time
import random
pygame.init()
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
orange = (255,127,0)
yellow = (255,255,0)
green = (0,255,0)
blue = (0,0,255)
purple = (143,0,255)
dark_green = (0,155,0)
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Slither")
img = pygame.image.load(r"C:\Users\BJBGaming\Desktop\snakehead.png")
clock = pygame.time.Clock()
block_size = 20
FPS = 15
font = pygame.font.SysFont(None, 25)
def snake(block_size, snakelist):
print(snakelist)
gameDisplay.blit(img,(snakelist[-1][0], snakelist[-1][1]))
for XnY in snakelist[:-1]:
pygame.draw.rect(gameDisplay, dark_green, [XnY[0],XnY[1],block_size,block_size])
def text_objects(text,color):
textSurface = font.render(text, True, color)
return textSurface, textSurface.get_rect()
def message_to_screen(msg,color):
textSurf, textRect = text_objects(msg,color)
#screen_text = font.render(msg, True, color)
#gameDisplay.blit(screen_text, [display_width/2, display_height/2])
textRect.center = (display_width / 2), (display_height / 2)
gameDisplay.blit(textSurf, textRect)
def gameLoop():
gameExit = False
gameOver = False
lead_x = display_width/2
lead_y = display_height/2
lead_x_change = 0
lead_y_change = 0
snakeList = []
snakeLength = 0
randAppleX = round(random.randrange(0, display_width-block_size))#/10.0)*10.0
randAppleY = round(random.randrange(0, display_height-block_size))#/10.0)*10.0
while not gameExit:
while gameOver == True:
gameDisplay.fill(white)
message_to_screen("Game over, press Q to play again ot W to quit", red)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
gameExit = True
gameOver = False
if event.key == pygame.K_q:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change = -block_size
lead_y_change = 0
elif event.key == pygame.K_RIGHT:
lead_x_change = block_size
lead_y_change = 0
elif event.key == pygame.K_UP:
lead_y_change = -block_size
lead_x_change = 0
elif event.key == pygame.K_DOWN:
lead_y_change = block_size
lead_x_change = 0
if lead_x >= display_width or lead_x < 0 or lead_y >= display_height or lead_y < 0:
gameOver = True
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(white)
AppleThickness = 30
pygame.draw.rect(gameDisplay, red, [randAppleX, randAppleY, AppleThickness, AppleThickness])
snakeHead = []
snakeHead.append(lead_x)
snakeHead.append(lead_y)
snakeList.append(snakeHead)
snake(block_size, snakeList)
if len (snakeList) > snakeLength:
del snakeList [0]
for eachSegment in snakeList[:-1]:
if eachSegment == snakeHead:
gameOver = True
snake(block_size, snakeList)
pygame.display.update()
## if lead_x >= randAppleX and lead_x <= randAppleX + AppleThickness:
## if lead_y >= randAppleY and lead_y <= randAppleY + AppleThickness:
## randAppleX = round(random.randrange(0, display_width-block_size))#/10.0)*10.0
## randAppleY = round(random.randrange(0, display_height-block_size))#/10.0)*10.0
## snakeLength += 1
if lead_x > randAppleX and lead_x < randAppleX + AppleThickness or lead_x + block_size > randAppleX and lead_x + block_size < randAppleX + AppleThickness:
if lead_y > randAppleY and lead_y < randAppleY + AppleThickness or lead_y + block_size > randAppleY and lead_y + block_size < randAppleY + AppleThickness:
randAppleX = round(random.randrange(0, display_width-block_size))#/10.0)*10.0
randAppleY = round(random.randrange(0, display_height-block_size))#/10.0)*10.0
snakeLength += 1
elif lead_y + block_size > randAppleY and lead_y + block_size < randAppleY + AppleThickness:
randAppleX = round(random.randrange(0, display_width-block_size))#/10.0)*10.0
randAppleY = round(random.randrange(0, display_height-block_size))#/10.0)*10.0
snakeLength += 1
clock.tick(FPS)
pygame.quit()
quit()
gameLoop()
And the Index Error thingy i got was this code.
Traceback (most recent call last):
File "C:\Users\BJBGaming\Desktop\FirstGame.py", line 165, in <module>
gameLoop()
File "C:\Users\BJBGaming\Desktop\FirstGame.py", line 132, in gameLoop
snake(block_size, snakeList)
File "C:\Users\BJBGaming\Desktop\FirstGame.py", line 35, in snake
gameDisplay.blit(img,(snakelist[-1][0], snakelist[-1][1]))
IndexError: list index out of range
Please help me, i dont understand how to fix it. Thank You.
Surely the error is with accessing snakelist[-1][0], snakelist[-1][1]. Check your logic with:
if len (snakeList) > snakeLength:
del snakeList [0]
Would it be the case where snakeLength == 0 and len(snakeList) == 1? If yes, then you'll delete the only element, causing snakeList to be empty.

Pygame won't print text in certain circumstances

So I'm trying to print "you lose" to the screen when the user moves a box off the playable screen, however this doesn't seem to work unless I call it from outside my main while loop. I have defined a function to handle the creation of the text, the rendering and 'blit'ing of it, although this has no effect when it is called from inside the while loop however it does when it is called from outside it at the bottom. I have checked and the function is executed from both locations, though it only seems to work from one.
import pygame
import time
pygame.init()
red = (255,0,0)
black = (0,0,0)
white = (255,255,255)
gamewidth = 900
gameheight = 900
snakecolour = black
gameDisplay = pygame.display.set_mode((gamewidth,gameheight))
pygame.display.set_caption("Snake")
gameExit = False
boxDimensions = 10
lead_x = (gamewidth // 2) - ((gamewidth // 2) % 20)
lead_y = (gameheight // 2) - ((gameheight // 2) % 20)
lead_x_change = 0
lead_y_change = 0
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 25)
def message_to_screen(msg, color):
screen_text = font.render(msg, True, color)
gameDisplay.blit(screen_text, [gamewidth//2, gameheight//2])
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
if not (lead_x_change == boxDimensions):
lead_x_change = -boxDimensions
lead_y_change = 0
elif event.key == pygame.K_RIGHT:
if not (lead_x_change == -boxDimensions):
lead_x_change = boxDimensions
lead_y_change = 0
elif event.key == pygame.K_UP:
if not (lead_y_change == boxDimensions):
lead_y_change = -boxDimensions
lead_x_change = 0
elif event.key == pygame.K_DOWN:
if not (lead_y_change == -boxDimensions):
lead_y_change = boxDimensions
lead_x_change = 0
lead_x += lead_x_change
lead_y += lead_y_change
if lead_x > gamewidth or lead_x < 0 or lead_y > gameheight or lead_y < 0:
snakecolour = red
gameExit = True
message_to_screen("You Lose!", red)
pygame.display.update()
#message_to_screen("You Lose!", red) WONT WORK HERE
if lead_x > gamewidth:
lead_x = gamewidth - boxDimensions
lead_x_change = 0
elif lead_x < 0:
lead_x = 0
lead_x_change = 0
elif lead_y > gameheight:
lead_y = gameheight - boxDimensions
elif lead_y < 0:
lead_y = 0
lead_y_change = 0
gameDisplay.fill(white)
pygame.draw.rect(gameDisplay, snakecolour, [lead_x,lead_y,boxDimensions,boxDimensions])
pygame.display.update()
clock.tick(15)
#message_to_screen("You Lose!", red) DOES WORK HERE
#pygame.display.update()
time.sleep(3)
pygame.quit()
message_to_screen("YOU LOSE!",(255,0,0))
pygame.display.update()
sleep(3)
From AirThomas comment, this is working. Outside of the while loop, put this statement.
For score board:
text = pygame.font.SysFont("None", 30)
score=0
text1=text.render("{}".format(score), True,(255,255,255))
while running:
screen.fill((0, 0, 0))
#codes
#codes
#codes
if sneakeatssomething:
score += 1
text1=text.render("{}".format(score), True,(255,255,255)) #rendering the score again
#codes
#codes
screen.blit(text1,(275,6))#showing the score
pygame.display.flip()
clock.tick(150)
This is updating the score when sneak eats and printing it to the pygame screen

Categories