Collision detection between an image and an object in Pygame - python

Hope you all are having a great day.
I am trying to detect a collision between my object (the black rectangle) and the food image.
What i want to basically do is whenever my rectangle collides with the food image, the food image is then placed randomly on the screen and the score gets increased by +1.
import pygame
import time
import random
pygame.init()
#Colours
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,155,0)
#Game Display
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('KALM Creation')
#Directions
DOWN='down'
UP='up'
LEFT='left'
RIGHT='right'
#Score
score=0
# My food image
foodimg=pygame.image.load("food.png")#.convert_alpha()
foodrect = foodimg.get_rect()
foodrect.centerx = 100
foodrect.centery = 200
#Our Icon For The Game
icon=pygame.image.load('icon1.jpg')
pygame.display.set_icon(icon)
#Clock
clock = pygame.time.Clock()
FPS = 30
cellSize=10
#Font Size
smallfont = pygame.font.SysFont("comicsansms", 25)
medfont = pygame.font.SysFont("comicsansms", 50)
largefont = pygame.font.SysFont("comicsansms", 80)
#The score function - displays the score on top right
def scoredisplay(scoredef=0):
text=smallfont.render("Score :%s" %(scoredef) ,True ,black)
gameDisplay.blit(text,[0,0])
#Starting Of the game
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key ==pygame.K_c:
intro = False
if event.key ==pygame.K_q:
pygame.quit()
quit()
gameDisplay.fill(white)
#Game Initial display message
message_to_screen("Welcome To Eat it Game",
green,
-200,
size="medium")
message_to_screen("Press 'C' to play the game or 'Q' to quit.",
black,
150,
size="small")
pygame.display.update()
clock.tick(15)
#Text Size
def text_objects(text,color, size):
if size=="small":
textSurface=smallfont.render(text, True ,color)
elif size=="medium":
textSurface=medfont.render(text, True ,color)
elif size=="large":
textSurface=largefont.render(text, True ,color)
return textSurface,textSurface.get_rect()
#Message to screen
def message_to_screen(msg,color,y_displace=0,size="small"):
textSurf,textRect=text_objects(msg,color,size)
textRect.center = (display_width / 2),(display_height / 2)+y_displace
gameDisplay.blit(textSurf,textRect)
#Drawing Cells
def drawCell(coords,ccolor):
for coord in coords:
x=coord['x']*cellSize
y=coord['y']*cellSize
makeCell=pygame.Rect(x,y,cellSize,cellSize)
pygame.draw.rect(gameDisplay,ccolor,makeCell)
#The Game run up
def runGame():
score=0
gameExit = False
gameOver = False
#Starting Position of the object
startx=3
starty=3
coords=[{'x':startx,'y':starty}]
direction = RIGHT
while not gameExit:
while gameOver == True:
#Game Over message
gameDisplay.fill(white)
message_to_screen("Game over",
red,
y_displace=-50,
size="large")
message_to_screen("Press C to play again or Q to quit",
black,
y_displace=50,
size="medium")
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()
#Game Controls
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
direction = LEFT
elif event.key == pygame.K_RIGHT:
direction = RIGHT
elif event.key == pygame.K_UP:
direction = UP
elif event.key == pygame.K_DOWN:
direction = DOWN
if direction == UP:
newCell={'x':coords[0]['x'],'y':coords[0]['y']-1}
elif direction == DOWN:
newCell={'x':coords[0]['x'],'y':coords[0]['y']+1}
elif direction == LEFT:
newCell={'x':coords[0]['x']-1,'y':coords[0]['y']}
elif direction == RIGHT:
newCell={'x':coords[0]['x']+1,'y':coords[0]['y']}
del coords[-1]
coords.insert(0, newCell)
gameDisplay.fill(white)
drawCell(coords,black)
clock.tick(FPS)
#If object moves outside the screen , game gets over.
if(newCell['x']<0 or newCell['y']<0 or newCell['x']>display_width/cellSize or newCell['y']>display_height):
gameOver= True
#Displays Score
scoredisplay(score)
gameDisplay.blit(foodimg,foodrect)
#pygame.display.flip()
pygame.display.update()
#The game run up
def gameLoop():
clock.tick(FPS)
runGame()
pygame.quit()
quit()
game_intro()
gameLoop()

In the drawcell() call:
if makecell.colliderect(foodrect):
foodrect.x = random.randint(0, sceeenwidth)
foodrect.y = random.randint(0, screenheight)
Should do it.

Related

Pygame dinosaur image keeps duplicating

I'm trying to make a dinosaur game in python (like the offline dino game in chrome).
I want the dino to jump when space is pressed but when I press it,not only the image of dino is duped but it also doesn't come back.
import pygame
import time
pygame.init()
displayWidth = 700
displayHeight = 350
gameDisplay = pygame.display.set_mode((displayWidth,displayHeight))
pygame.display.set_caption("Dino-Run")
black = (0,0,0)
white = (255,255,255)
clock = pygame.time.Clock()
dinoimg = pygame.image.load("dino.png")
def dino(x,y):
gameDisplay.blit(dinoimg,(x,y))
def gameloop():
gameExit = False
x = (displayWidth * 0.005)
y = (displayHeight * 0.75)
y_change = 0
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_RIGHT:
y_change = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
y_change = 0
y += y_change
dino(x,y)
pygame.display.update()
clock.tick(60)
Could someone please tell me how can I prevent the dino to dupe each time space is pressed and for the dino to come back to the ground.
You have to override everything before drawing new things to the screen.
Add this at the beginning of your loop:
gameDisplay.fill(color)

Python game over screen won't accept input

I'm trying to make it so when the game over screen shows the user can press space to get back into the game. Currently, when a game over happens, it displays the game over screen but accepts no input or at least doesn't do anything with the input. For some context, the game is basically about moving left and right to avoid obstacles. Currently, I only have one obstacle, but I just have not gotten to that yet. Thanks!
import pygame
import random
import math
pygame.init()
screenWidth = 700
screenHeight = 800
x = screenWidth / 2
y = (screenHeight / 4) * 3
width = 50
height = 50
win = pygame.display.set_mode((screenWidth, screenHeight))
pygame.display.set_caption("Test Game")
bg = pygame.image.load("background.png").convert()
gameover = pygame.image.load("gameover.png").convert()
bgx = (screenWidth / 6) * 2
bgy = 0
clock = pygame.time.Clock()
class enemy():
def __init__(self,c,y,width,height):
self.c = c
self.y = y
self.width = width
self.height = height
self.vel = 5
def draw(self, win):
if self.c == 1:
self.x = 250
#250
elif self.c == 2:
self.x = 350
#350
else:
self.x = 450
#450
self.y += self.vel
pygame.draw.rect(win, (0,0,255), (self.x,self.y,self.width,self.height))
evil = enemy(random.randint(1,3),0,50,50)
#def redrawGameWindow():
# evil.draw(win)
# pygame.display.update()
running = True
gameOver = False
while running:
clock.tick(60)
while gameOver:
win.blit(gameover, (0,0))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if pygame.event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
gameOver = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
x+=100
if event.key == pygame.K_LEFT:
x-=100
win.fill((0,0,0))
win.blit(bg, (bgx, bgy))
evil.draw(win)
dist = math.hypot(evil.x - x, evil.y - y)
if dist <= 50:
print("Game Over!")
running = False
gameOver = True
pygame.draw.rect(win, (255,0,0), (x,y,width,height))
pygame.display.update()
#redrawGameWindow()
while gameOver:
win.blit(gameover, (0,0))
pygame.display.update()
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
gameOver = False
pygame.quit()
The main problem is that your game over scene is the loop behind the main while running: loop and there's no way to go back to the first loop when you reach it. When you touch the evil object, you set running = False, leave the main and enter the while gameOver: loop.
In this loop you also need to call pygame.event.pump(), otherwise the pygame.key.get_pressed() function doesn't work correctly and the window freezes after a while because the events are not handled. If you want to restart the game, you should rather use only the nested while gameOver loop. Actually, I would recommend that you restructure the scenes even more and use a finite state machine instead (here's an answer in which I use functions as scenes but check out the link in the comment below as well).
Here's a working version of your code. I've changed a few things and added comments to explain the changes.
while running:
# -----The game over scene.-----
while gameOver:
for event in pygame.event.get():
if event.type == pygame.QUIT:
# pygame.quit only uninitializes the pygame modules and
# doesn't quit the program.
pygame.quit()
# This will quit the whole program. You need to import sys.
sys.exit()
elif event.type == pygame.KEYUP: # event.type not pygame.event.type
if event.key == pygame.K_SPACE:
# Change it to False to break out of the loop.
gameOver = False
# Reset the game. You could reset the position of the
# `evil` object or instantiate a new one.
evil.x = 350
evil.y = 0
win.blit(gameover, (0,0))
pygame.display.update()
clock.tick(60) # You need to call tick in this loop as well.
# ------------------------------
# -----The main scene.-----
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
x += 100
elif event.key == pygame.K_LEFT:
x -= 100
win.fill((0,0,0))
win.blit(bg, (bgx, bgy))
evil.draw(win)
dist = math.hypot(evil.x - x, evil.y - y)
if dist <= 50:
print("Game Over!")
# running = False # This would stop the main loop.
gameOver = True
pygame.draw.rect(win, (255,0,0), (x,y,width,height))
pygame.display.update()
clock.tick(60)
# The other while loop was removed.
pygame.quit()

How do I stop my snake moving into itself (python, pygame)

this is my first game I have created using pygame, it's basically snake.
Please do not mind my hideous comments.
## William's Snake Game
import pygame
import time
import random
pygame.init()
##Global variables
# Colours
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
green = (0, 155, 0)
bground = (204, 204, 0)
# Display vars.
display_width = 800
display_height = 600
# Variables
gameDisplay = pygame.display.set_mode((display_width, display_height)) ##resolution, note that this is a tuple.
pygame.display.set_caption("Snake VS Apple") # Title at the top of the screen
icon = pygame.image.load('logoapple32x32.png') # Loads the icon for the top left
pygame.display.set_icon(icon) # Sets the icon for the top left
snakeHeadImg = pygame.image.load("snakeHead.png") # Loads the image for the snake head
appleImg = pygame.image.load("apple20x20.png") # Loads the image for the apple
appleThickness = 20 # Defines how thick apple will be. Note to self: This is changable
clock = pygame.time.Clock() # Starts clocking the game, used later for FPS
blockSize = 20 # Defines how big the snake will be. Changing this will mess up collision detection.
FPS = 15 # Frames per second. Called at the bottom of script
smallfont = pygame.font.SysFont("arial", 25) ## format: ("font", fontsize)
medfont = pygame.font.SysFont("arial", 40) ##
largefont = pygame.font.SysFont("arial", 80) ##
direction = "right" # Starting direction of snake, used in main gameLoop
##
def pauseGame():
gameisPaused = True
while gameisPaused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
gameisPaused = False
elif event.key == pygame.K_q:
pygame.quit()
quit()
gameDisplay.fill(white)
message_to_screen("Paused",
black,
-100,
size="large")
message_to_screen("Press ESC to continue or Q to quit.",
black,
25,
size="small")
pygame.display.update()
clock.tick(5)
def text_objects(text, color, size): # Function to render text
if size == "small":
textSurface = smallfont.render(text, True, color)
elif size == "medium":
textSurface = medfont.render(text, True, color)
elif size == "large":
textSurface = largefont.render(text, True, color)
return textSurface, textSurface.get_rect()
def message_to_screen(msg, color, y_displace=0, size="medium"): # Function to blit (draw) text to surface
textSurf, textRect = text_objects(msg, color, size)
textRect.center = (display_width / 2), (display_height / 2) + y_displace
gameDisplay.blit(textSurf, textRect)
##
def score(score):
text = smallfont.render("Score: " + str(score), True, black)
gameDisplay.blit(text, [0, 0])
def randAppleGen(): # Function to generate random apples
randAppleX = round(
random.randrange(0, display_width - appleThickness)) # /10.0)*10.0 ##Create another rand X value for new apple
randAppleY = round(
random.randrange(0, display_height - appleThickness)) # /10.0)*10.0 ##Create another rand Y value for new apple
return randAppleX, randAppleY
def gameIntro(): # Function for game menu.
intro = True
while intro: # Event handling during menu
for eachEvent in pygame.event.get():
if eachEvent.type == pygame.QUIT:
pygame.quit()
quit()
if eachEvent.type == pygame.KEYDOWN:
if eachEvent.key == pygame.K_c:
gameLoop()
if eachEvent.key == pygame.K_q:
pygame.quit()
quit()
# Text displayed in menu
gameDisplay.fill(white)
message_to_screen("Welcome to Slither",
green,
-90,
"large")
message_to_screen("The more apples you eat, the longer you are",
black,
100)
message_to_screen("The objective of the game is to eat red apples",
black,
0,
"small")
message_to_screen("If you run into yourself, or the edges, you die!",
black,
30,
"small")
message_to_screen("Press C to play or Q to quit.",
black,
180)
pygame.display.update()
clock.tick(500)
def snake(blockSize, snakeList): # Function to draw snake
if direction == "right":
head = pygame.transform.rotate(snakeHeadImg,
270) # In gameLoop, right,left,up,down are used to change direction of snakeHead
elif direction == "left":
head = pygame.transform.rotate(snakeHeadImg, 90)
elif direction == "up":
head = snakeHeadImg
elif direction == "down":
head = pygame.transform.rotate(snakeHeadImg, 180)
gameDisplay.blit(head, (snakeList[-1][0], snakeList[-1][1])) ##???
for XandY in snakeList[:-1]:
pygame.draw.rect(gameDisplay, green,
[XandY[0], XandY[1], blockSize, blockSize]) ##width height, width height, drawing
##Main Game Loop
def gameLoop():
global direction ## Make direction a global var. Important
# Local variables
gameExit = False
gameOver = False
lead_x = display_width / 2
lead_y = display_height / 2
lead_x_change = 10
lead_y_change = 0
snakeList = []
snakeLength = 3
randAppleX, randAppleY = randAppleGen() # Generate apples. Calls randAppleGen()
# Main Game Loop ##eventHandler
while not gameExit:
snakeHead = [] # Creates list snakeHead
snakeHead.append(lead_x) # Appends snakeHead x value to list
snakeHead.append(lead_y) # Appends snakeHead y value to list
snakeList.append(snakeHead) # Appends coordinates of snakeHead x,y to list
while gameOver == True: # Handles game over
gameDisplay.fill(white)
message_to_screen("Game over",
red,
-50,
size="large")
message_to_screen("Press C to play again or Q to quit",
black,
50,
size="medium")
pygame.display.update()
for event in pygame.event.get(): # eventHandler for loss screen
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
direction = "right"
gameLoop()
for event in pygame.event.get(): # eventHandler for keyboard events during game
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a: # Each of these handles either arrow keys or WASD key events.
lead_x_change = -blockSize
lead_y_change = 0
direction = "left"
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
lead_x_change = blockSize
lead_y_change = 0
direction = "right"
elif event.key == pygame.K_UP or event.key == pygame.K_w:
lead_y_change = -blockSize
lead_x_change = 0
direction = "up"
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
lead_y_change = blockSize
lead_x_change = 0
direction = "down"
elif event.key == pygame.K_ESCAPE:
pauseGame()
# Checks if user has hit screen boundaries.
if lead_x >= display_width or lead_x < 0 or lead_y >= display_height or lead_y < 0: # If user hits display boundaries
gameOver = True # They lose
lead_x += lead_x_change # Ensures continous movement of the snake
lead_y += lead_y_change
# Drawing
gameDisplay.fill(bground) # Fills the display background with predefined bground colour (defined at the top)
gameDisplay.blit(appleImg,
(randAppleX, randAppleY)) ##Draws the apple using the appleImg, at random coordinates.
if len(
snakeList) > snakeLength: # If the length of the list of snake body coordinates is greater than the length
del snakeList[0] # Delete the oldest value in the list (as the snake is constantly moving)
for eachSegment in snakeList[:-1]: # For each coordinate in snakeList
if eachSegment == snakeHead: # If the segment touches the snakeHead
## gameDisplay.fill(bground)
## snake(blockSize, snakeList)
##
## pygame.display.update
time.sleep(0.3)
gameOver = True # Game over
snake(blockSize, snakeList) ##Creates snake using function snake
score(snakeLength - 3) # Displays score (it minuses 3 because the snake starts at 3)
pygame.display.update() ##Updates to screen
## COLLISION DETECTION
if lead_x + blockSize > randAppleX and lead_x < randAppleX + appleThickness:
if lead_y + blockSize > randAppleY and lead_y < randAppleY + appleThickness:
randAppleX, randAppleY = randAppleGen()
snakeLength += 1
clock.tick(FPS)
pygame.quit()
quit()
##update screen
##
gameIntro()
gameLoop()
##Code goes above.
I have a problem where if my snake is going right, and then it turns left, my snake will crash onto itself and the game will end.
I want to design this so when my snake is going right, it cannot simply turn left, crash into itself and end the game. So when it turns right, it can only turn up, down, or keep going right. So simply, I want to make it so it cannot run backwards into itself.
I have tried coding this in myself, and I have tried many methods but nothing has worked.
Please help!!
Without altering your code too much (and without testing), an easy way to get what you want is to add another condition to your key checks. If you alter the relevant code section as follows, all should be fine:
for event in pygame.event.get(): # eventHandler for keyboard events during game
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_LEFT or event.key == pygame.K_a) and direction != "right": # Each of these handles either arrow keys or WASD key events.
lead_x_change = -blockSize
lead_y_change = 0
direction = "left"
elif (event.key == pygame.K_RIGHT or event.key == pygame.K_d) and direction != "left":
lead_x_change = blockSize
lead_y_change = 0
direction = "right"
elif (event.key == pygame.K_UP or event.key == pygame.K_w) and direction != "down":
lead_y_change = -blockSize
lead_x_change = 0
direction = "up"
elif (event.key == pygame.K_DOWN or event.key == pygame.K_s) and direction != "up":
lead_y_change = blockSize
lead_x_change = 0
direction = "down"
elif event.key == pygame.K_ESCAPE:
pauseGame()
Mind the parentheses around the or'd key checks!

Python Sprites/Images are blinking

I have been coding a program, a survival game, on Python. I seem to have an issue with adding Images/Sprites. I am noticing the images blink. Any way to fix this?
import os
import pygame
import time
import random
from pygame.locals import *
launchLog = pygame.init()
print(launchLog)
white = (255,255,255)
black = (0,0,0)
red=(255,0,0)
blue=(0,0,255)
green=(0,255,0)
skin = (236,227,100)
size = 10
dependant = (green)
rate = 0.0018
weight = 100
bound_x = 600
bound_x2 = bound_x-size
bound_y = 600
bound_y2 = bound_y-size
screen = pygame.display.set_mode((bound_x,bound_y))
pygame.display.set_caption("Survival: EfEs Edition")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None,25)
x = 300
y = 300
roundX = x
roundY = y
img=pygame.image.load("pewds.png")
def hmn(x,y,size):
clothes = pygame.draw.rect(screen,skin,[x,y,size,size-size*2])
snake = pygame.draw.rect(screen, red, [x,y,size,size])
def mesg(msg,color):
txt = font.render(msg, True, color)
screen.blit(txt, [x,y-30])
display.flip(img)
def gameLoop():
global x
global y
jump = 1
quitted = False
starved = 100
eaten = False
restart = False
lead_change = 0
lead_y = 0
randF_x = random.randrange(0,bound_x)
randF_y = random.randrange(0,bound_y)
didX2=round(randF_x/10.0)*10.0
didY2=round(randF_y/10.0)*10.0
while not quitted:
screen.blit(img,(x,y -15))
screen.blit(img,(x,y -15))
pygame.display.update()
hmn(x,y,size)
starved=starved-rate
#print(starved)
if starved<0:
screen.fill(white)
mesg("You died of hunger! Press R to restart.",red)
pygame.display.flip()
time.sleep(0.3)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
starved = 100
pygame.display.update()
rate = 0.0018
x=300
y=300
for event in pygame.event.get():
#print(event)
if event.type == pygame.QUIT:
pygame.display.update()
quitted = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
lead_change = -.2
elif event.key == pygame.K_d:
lead_change = .2
elif event.key == pygame.K_w:
lead_y = .2
elif event.key == pygame.K_s:
lead_y = -0.2
if event.type == pygame.KEYUP:
if event.key == pygame.K_d or event.key == pygame.K_a:
lead_change = 0
#print(x)
#print(y)
elif event.key == pygame.K_ESCAPE:
#print("Quitting")
quitted = True
elif event.key == pygame.K_w or event.key == pygame.K_s:
#print(y)
lead_y=0
x += lead_change
y -= lead_y
roundX = x
roundY = y
global roundX
global roundY
didX=round(roundX/10)*10
didY=round(roundY/10)*10
screen.fill(white)
s = pygame.draw.rect(screen, red, [bound_x2/15,bound_y2/20, starved * 2, 50])
pygame.draw.rect(screen, dependant, [didX2,didY2,10,10])
pygame.display.update()
#boundary script
if x>bound_x2:
x=bound_x2
elif x<-1:
x=-1
elif y<2:
y=2
elif y>590:
y=590
hmn(x,y,size)
pygame.display.flip()
if didX == didX2 and didY==didY2:
didX2 = round(random.randrange(0,bound_x)/10)*10
didY2 = round(random.randrange(0,bound_y)/10)*10
global dependant
dependant = green
global starved
starved = starved +0.01
global weight
weight = weight + 3
elif weight>150:
mesg("Weight increased! You now get hungry faster.",black)
pygame.display.update()
global rate
rate = rate+0.0008
pygame.display.update()
clock.tick(55)
mesg("Leaving game", black)
screen.blit(img,(x,y-15))
pygame.display.update()
time.sleep(2)
pygame.quit()
quit()
gameLoop()`
Please excuse the bad coding, the game is only in it's earliest state.
The correct sequence is to:
draw everything you want to show on a frame (all the blit()s, draw()s), etc.
do only one of display.update() with a list of all the changed regions OR display.flip() to update the whole screen once you've drawn everything
tl;dr - don't mix draw()s with update()s.

Pygame Index Out of Range

I am building an asteroids-like game with python, but I'm running into trouble with keeping within the range of my possibleTurrets array. All I'm doing is iterating through the array, and when the edge cases outside of the array occur, I deal with them through:
if currentTurPos > 8:
currentTurPos = 8
elif currentTurPos < 0:
currenTurPos = 0
This is in reference to this array:
possibleTurrets = [ (x-27,y-2),
(x-26,y-5),
(x-25,y-8),
(x-23,y-12),
(x-20,y-14),
(x-18,y-15),
(x-15,y-17),
(x-13,y-19),
(x-11,y-21)
]
For some reason this code works fine on pygame.K_UP but not on pygame.K_DOWN and I have no idea why.
This seems like it should be really obvious, but I've spent an hour trying to fix it, and am drawing a blank. The issue is with my ufo function, and the currentTurPos variable.
# Libraries
import pygame
import time
import random
import os
# Initialize Pygame
pygame.init()
# Colors
white = (255,255,255)
black = (0,0,0)
red = (200,0,0)
blue = (0,0,255)
green = (34,177,76)
light_green = (0,255,0)
yellow = (200,200,0)
light_yellow = (255,255,0)
light_red = (255,0,0)
# Display
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
#pygame.display.set_caption('Slither')
#icon = pygame.image.load('apple.bmp')
#pygame.display.set_icon(icon)
clock = pygame.time.Clock()
# Sprites
ufoWidth = 40
ufoHeight = 20
turretWidth = 5
turretHeight = 10
fps = 15 # Speed
# Fonts
smallFont = pygame.font.SysFont("comicsansms", 25)
medFont = pygame.font.SysFont("comicsansms", 50)
largeFont = pygame.font.SysFont("comicsansms", 80)
def ufo(x,y,turPos):
x = int(x)
y = int(y)
possibleTurrets = [ (x-27,y-2),
(x-26,y-5),
(x-25,y-8),
(x-23,y-12),
(x-20,y-14),
(x-18,y-15),
(x-15,y-17),
(x-13,y-19),
(x-11,y-21)
]
pygame.draw.circle(gameDisplay, blue, (x,y),int(ufoHeight/2))
pygame.draw.ellipse(gameDisplay, black, (x-ufoHeight, y, ufoWidth, ufoHeight))
pygame.draw.line(gameDisplay,blue,(x,y),possibleTurrets[turPos],turretWidth)
# Font sizes
def text_objects(text, color, size):
if size == "small":
textSurface = smallFont.render(text, True, color)
elif size == "medium":
textSurface = medFont.render(text, True, color)
elif size == "large":
textSurface = largeFont.render(text, True, color)
return textSurface, textSurface.get_rect()
# Displays a message: Requires message, color, y-displacement, and size arguments
def message_to_screen(msg, color, y_displace=0, size="small"):
textSurf, textRect = text_objects(msg, color, size)
textRect.center = (int(display_width/2), (int(display_height/2) + y_displace))
gameDisplay.blit(textSurf, textRect)
# Show button text
def text_to_button(msg,color, buttonx,buttony,buttonwidth,buttonheight,size="small"):
textSurf, textRect = text_objects(msg,color,size)
textRect.center = ((buttonx+(buttonwidth/2)), buttony+(buttonheight/2))
gameDisplay.blit(textSurf, textRect)
# On button hover
def button(text,x,y,width,height,inactive_color,active_color,action):
cursor = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + width > cursor[0] > x and y + height > cursor[1] > y:
pygame.draw.rect(gameDisplay,active_color,(x,y,width,height))
if click[0] == 1 and action != None:
if action == "play":
gameLoop()
if action == "controls":
game_controls()
if action == "quit":
pygame.quit()
quit()
else:
pygame.draw.rect(gameDisplay,inactive_color,(x,y,width,height))
text_to_button(text,black,x,y,width,height)
def game_controls():
gcont = True
while gcont:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
intro = False
if event.key == pygame.K_q:
pygame.quit()
quit()
gameDisplay.fill(white)
message_to_screen("Controls", green, -100, size="large")
message_to_screen("Fire: Spacebar", black, -30, size="small")
message_to_screen("Move turret: Up and Down arrows", black, 10, size="small")
message_to_screen("Move UFO: Left and Right arrows", black, 50, size="small")
message_to_screen("Pause: P", black, 90, size="small")
button("Play",150,450,100,50, green, light_green, action="play")
button("Quit",550,450,100,50, red, light_red, action="quit")
pygame.display.update()
clock.tick(fps)
# Pauses game and gives continue and quit options
def pause():
paused = True
message_to_screen("Paused", black, -100, size="large")
message_to_screen("Press P to play, or Q to quit.", black, 25, size="small")
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
paused = False
elif event.key == pygame.K_q:
pygame.quit()
quit()
pygame.display.update()
clock.tick(fps)
# Keeps track of, and displays the score
def score(score):
text = smallFont.render(" Score: " + str(score), True, black)
gameDisplay.blit(text, [0,0])
# Barrier
def barrier():
xlocation = (display_width/2) + random.randint(-0.2*displayWidth,0.2*displayWidth)
# Intro screen - Title and directions
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
intro = False
if event.key == pygame.K_q:
pygame.quit()
quit()
gameDisplay.fill(white)
message_to_screen("Welcome to UFO!", green, -100, size="large")
message_to_screen("The objective of the game is to search and destroy.", black, -30, size="small")
message_to_screen("Destroy your opponent before they destroy you.", black, 10, size="small")
message_to_screen("The more enemies you destroy, the harder they get.", black, 50, size="small")
button("Play",150,450,100,50, green, light_green, action="play")
button("Controls",350,450,100,50, yellow, light_yellow, action="controls")
button("Quit",550,450,100,50, red, light_red, action="quit")
pygame.display.update()
clock.tick(fps)
# Main game loop
def gameLoop():
gameExit = False
gameOver = False
mainUfoX = display_width * 0.9
mainUfoY = display_height * 0.9
ufoMove = 0
currentTurPos = 0
changeTur = 0
# Game over screen and changes for key inputs
while not gameExit:
if gameOver == True:
message_to_screen("Game over!", red, -50, size="large")
message_to_screen("Press C to play again, Q to quit.", black, 50, size="medium")
pygame.display.update()
while gameOver == True:
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_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
# Make changes for specific key inputs
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
ufoMove = -5
elif event.key == pygame.K_RIGHT:
ufoMove = 5
elif event.key == pygame.K_UP:
changeTur = 1
elif event.key == pygame.K_DOWN:
changeTur = -1
elif event.key == pygame.K_p:
pause()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
ufoMove = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
changeTur = 0
gameDisplay.fill(white)
mainUfoX += ufoMove
currentTurPos += changeTur
if currentTurPos > 8:
currentTurPos = 8
elif currentTurPos < 0:
currenTurPos = 0
ufo(mainUfoX,mainUfoY,currentTurPos)
pygame.display.update()
clock.tick(fps)
# Quits
pygame.quit()
quit()
# Loads game intro screen
game_intro()
# gameLoop calls itself to begin game
gameLoop()
It was a typo (I'm an idiot).
currentTurPos was currenTurPos.
Lesson learned: complex variable names with repeating letters are dangerous.

Categories

Resources