PyGame Window not starting - python

I created this simple snake game a while ago and I wanted to try running it and for some reason the window is not starting on my machine. I am sure the code was working before. I tried debugging for a while but can't seem to figure out why I am stuck on a black screen. It seems to detect a key pressed but nothing is displayed on the screen.
import pygame
from pygame.locals import *
import random
# Global Color Variables
RED = (255, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
CYAN = (0,255, 255)
# Set the speed of the Snake --> lower = faster
timeDelaySpeed = 0
class App:
def __init__(self):
self._running = True
self._display_surf = None
self.size = self.weight, self.height = 600, 700
# create the boarder
self.boarder = self.generateBoard()
# Initial Snake array with 3 Snake Blocks starting at (50, 50) and going left
self.snake = [Snake(WHITE, 10, 10, 150, 260), Snake(WHITE, 10, 10, 140, 260), Snake(WHITE, 10, 10, 130, 260)]
def on_init(self):
pygame.init()
self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
self._display_surf.fill(BLACK)
self._running = True
# Create Score Board
self.score = 0
self.displayScore(self.score, 45)
# Create Initial Food
self.initFood = Food(RED, 10, 10)
self._display_surf.blit(self.initFood.image, self.initFood.rect)
# display the initial Snake array
for i in range(len(self.snake)):
self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
# display the board
for i in range(len(self.boarder)):
self._display_surf.blit(self.boarder[i].image, self.boarder[i].rect)
pygame.display.update()
"""
Helper Method that will run the events that are clicked on by the user
"""
def on_event(self):
# Checks if Snake crashes with itself - LOSE
for i in range(1, len(self.snake)):
if pygame.sprite.collide_rect(self.snake[0], self.snake[1]):
self.spaceToRestartText(20)
self.gameRestart()
if pygame.sprite.collide_rect(self.snake[0], self.snake[i]):
self.spaceToRestartText(20)
self.gameRestart()
# Check if Snake hits the boarder - LOSE
for i in range(len(self.boarder)):
if pygame.sprite.collide_rect(self.snake[0], self.boarder[i]):
self.spaceToRestartText(20)
self.gameRestart()
# Checks if Snake eats Food
if pygame.sprite.collide_rect(self.snake[0], self.initFood):
self.eatFood()
# set the direction based of key that is pressed
for event in pygame.event.get():
if event.type == pygame.QUIT:
self._running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
# check for self collision before eating any food - weird collision method error fix
if self.move == 'right':
self.spaceToRestartText(20)
self.gameRestart()
break
self.move = 'left'
if event.key == pygame.K_RIGHT:
# check for self collision before eating any food
if self.move == 'left':
self.spaceToRestartText(20)
self.gameRestart()
break
self.move = 'right'
if event.key == pygame.K_UP:
# check for self collision before eating any food
if self.move == 'down':
self.spaceToRestartText(20)
self.gameRestart()
break
self.move = 'up'
if event.key == pygame.K_DOWN:
# check for self collision before eating any food
if self.move == 'up':
self.spaceToRestartText(20)
self.gameRestart()
break
self.move = 'down'
# if stored current direction is right
if self.move == 'right':
print("RIGHT")
# Reset the Board
self.boardReset()
# Store the current head of the snake
snakeHead = self.snake[0]
# remove the last block of the snake
self.snake.pop()
# create a new head for the snake that is shifted toward the right
newHead = snakeHead.moveRight()
# add the newly created head to the front of the list - make head
self.snake.insert(0, newHead)
# displays moved snake
for i in range(len(self.snake)):
self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
pygame.display.update()
pygame.time.delay(timeDelaySpeed)
# if stored current direction is left
if self.move == 'left':
print("LEFT")
# Reset the Board
self.boardReset()
# Store the current head of the snake
snakeHead = self.snake[0]
# remove the last block of the snake
self.snake.pop()
# create a new head for the snake that is shifted toward the right
newHead = snakeHead.moveLeft()
# add the newly created head to the front of the list - make head
self.snake.insert(0, newHead)
# displays moved snake
for i in range(len(self.snake)):
self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
pygame.display.update()
pygame.time.delay(timeDelaySpeed)
# if stored current direction is up
if self.move == 'up':
print("UP")
# Reset the Board
self.boardReset()
# Store the current head of the snake
snakeHead = self.snake[0]
# remove the last block of the snake
self.snake.pop()
# create a new head for the snake that is shifted toward the right
newHead = snakeHead.moveUp()
# add the newly created head to the front of the list - make head
self.snake.insert(0, newHead)
# displays moved snake
for i in range(len(self.snake)):
self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
pygame.display.update()
pygame.time.delay(timeDelaySpeed)
# if stored current direction is down
if self.move == 'down':
print("DOWN")
# Reset the Board
self.boardReset()
# Store the current head of the snake
snakeHead = self.snake[0]
# remove the last block of the snake
self.snake.pop()
# create a new head for the snake that is shifted toward the right
newHead = snakeHead.moveDown()
# add the newly created head to the front of the list - make head
self.snake.insert(0, newHead)
# displays moved snake
for i in range(len(self.snake)):
self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
pygame.display.update()
pygame.time.delay(timeDelaySpeed)
"""
Helper method that displays the current score on the screen.
"""
def displayScore(self, score, size):
font = pygame.font.SysFont("Comic Sans MS", size)
ScoreBoard = font.render("SCORE: {}".format(score), False, (WHITE))
self._display_surf.blit(ScoreBoard, [90, 100])
pygame.display.update()
"""
Helper method that will reset the screen:
Make screen Black
Add the current Food block
Add the current Score
"""
def boardReset(self):
# Erases the current screen
self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
self._display_surf.fill(BLACK)
# Create Score Board
self.displayScore(self.score, 45)
# Add Food
self._display_surf.blit(self.initFood.image, self.initFood.rect)
# Add Boarder
for i in range(len(self.boarder)):
self._display_surf.blit(self.boarder[i].image, self.boarder[i].rect)
"""
Eating food helper method
"""
def eatFood(self):
# Create a new Food at random location and display it
self.initFood = Food(RED, 10, 10)
self._display_surf.blit(self.initFood.image, self.initFood.rect)
# Create Score Board
self.score += 1
self.displayScore(self.score, 45)
# for i in range(len(self.snake)):
# self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
#
# Store the last and second to last blocks of the snake
lastSnakeBlock = self.snake[-1]
secondToLastBlock = self.snake[-2]
# if the last two blocks are on the same horizontal line and the last block is to the left of the
# second to last block, add a block to the left side of the last block
if lastSnakeBlock.rect.y == secondToLastBlock.rect.y and lastSnakeBlock.rect.x < secondToLastBlock.rect.x:
newX = lastSnakeBlock.rect.x - 10
newSnakeBlock = Snake(lastSnakeBlock.color, lastSnakeBlock.width, lastSnakeBlock.height, newX,
lastSnakeBlock.rect.y)
self.snake.append(newSnakeBlock)
# if the last two blocks are on the same horizontal line and the last block is to the right of the
# second to last block, add a block to the right side of the last block
if lastSnakeBlock.rect.y == secondToLastBlock.rect.y and lastSnakeBlock.rect.x > secondToLastBlock.rect.x:
newX = lastSnakeBlock.rect.x + 10
newSnakeBlock = Snake(lastSnakeBlock.color, lastSnakeBlock.width, lastSnakeBlock.height, newX,
lastSnakeBlock.rect.y)
self.snake.append(newSnakeBlock)
# if the last two blocks are on the same vertical line and the last block is above the
# second to last block, add a block above the last block
if lastSnakeBlock.rect.x == secondToLastBlock.rect.x and lastSnakeBlock.rect.y < secondToLastBlock.rect.y:
newY = lastSnakeBlock.rect.y - 10
newSnakeBlock = Snake(lastSnakeBlock.color, lastSnakeBlock.width, lastSnakeBlock.height,
lastSnakeBlock.rect.x, newY)
self.snake.append(newSnakeBlock)
# if the last two blocks are on the same vertical line and the last block is below the
# second to last block, add a block below the last block
if lastSnakeBlock.rect.x == secondToLastBlock.rect.x and lastSnakeBlock.rect.y > secondToLastBlock.rect.y:
newY = lastSnakeBlock.rect.y + 10
newSnakeBlock = Snake(lastSnakeBlock.color, lastSnakeBlock.width, lastSnakeBlock.height,
lastSnakeBlock.rect.x, newY)
self.snake.append(newSnakeBlock)
for i in range(len(self.snake)):
self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
"""
Takes the player back to initial start state
"""
def gameRestart(self):
# Erase the Board
self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
self._display_surf.fill(BLACK)
self._running = True
# Recreate the Snake
self.snake = [Snake(WHITE, 10, 10, 150, 260), Snake(WHITE, 10, 10, 140, 260), Snake(WHITE, 10, 10, 130, 260)]
# Create Score Board
self.score = 0
self.displayScore(self.score, 45)
# Create Initial Food
self.initFood = Food(RED, 10, 10)
self._display_surf.blit(self.initFood.image, self.initFood.rect)
# set current move to nothing
self.move = ''
# draw in the boarder
for i in range(len(self.boarder)):
self._display_surf.blit(self.boarder[i].image, self.boarder[i].rect)
# display the initial Snake array
for i in range(len(self.snake)):
self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
pygame.display.update()
"""
Creates a List of Blocks that outline the Boarder of the snake game
"""
def generateBoard(self):
boardCorners = []
boardTop = []
boardSide1 = []
boardSide2 = []
boardBottom = []
# Makes (0,0) of board = (100, 210)
# top left corner
boardCorners.append(Snake(CYAN, 10, 10, 90, 200))
# top right corner
boardCorners.append(Snake(CYAN, 10, 10, 500, 200))
# bottom left corner
boardCorners.append(Snake(CYAN, 10, 10, 90, 610))
# bottom right corner
boardCorners.append(Snake(CYAN, 10, 10, 500, 610))
# top and bottom sides
topCoord = 100
for i in range(40):
boardTop.append(Snake(CYAN, 10, 10, topCoord, 200))
boardBottom.append(Snake(CYAN, 10, 10, topCoord, 610))
topCoord += 10
# sides of board
sideCoord = 210
for i in range(40):
boardSide1.append(Snake(CYAN, 10, 10, 90, sideCoord))
boardSide2.append(Snake(CYAN, 10, 10, 500, sideCoord))
sideCoord += 10
# combine all parts
allBoarder = boardCorners + boardTop + boardSide1 + boardSide2 + boardBottom
# return list of blocks
return allBoarder
"""
Allows player to restart a game by pressing space bar - displays losing screen
"""
def spaceToRestartText(self, size):
self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
self._display_surf.fill(BLACK)
self.youLoseText(50)
self.yourScoreText(25)
font = pygame.font.SysFont("Comic Sans MS", size)
text_surface = font.render("Press space bar to play again", True, WHITE)
text_rect = text_surface.get_rect(center=(self.weight / 2, self.height / 2))
self._display_surf.blit(text_surface, text_rect)
pygame.display.flip()
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
done = True
"""
Helper function that prints 'YOU LOSE!'
"""
def youLoseText(self, size):
font = pygame.font.SysFont("Comic Sans MS", size)
text_surface = font.render("YOU LOSE!", True, WHITE)
# Shift height up so no collision with space bar text
text_rect = text_surface.get_rect(center=(self.weight / 2, (self.height / 2) - 75))
self._display_surf.blit(text_surface, text_rect)
pygame.display.flip()
"""
Helper function that prints your score at loss
"""
def yourScoreText(self, size):
font = pygame.font.SysFont("Comic Sans MS", size)
text_surface = font.render("Your Score was: " + str(self.score), True, WHITE)
# Shift height up so no collision with space bar text
text_rect = text_surface.get_rect(center=(self.weight / 2, (self.height / 2) - 35))
self._display_surf.blit(text_surface, text_rect)
pygame.display.flip()
def on_loop(self):
pass
def on_render(self):
pass
def on_cleanup(self):
pygame.quit()
"""
Game Loop
"""
def on_execute(self):
if self.on_init() == False:
self._running = False
self.move = ''
while (self._running):
self.on_event()
self.on_loop()
self.on_render()
self.on_cleanup()
"""
Class to create a Food at a random coordinate
"""
class Food(pygame.sprite.Sprite):
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# Update the position of this object by setting the values of rect.x and rect.y
self.rect = self.image.get_rect()
# set the position of the Food
# TODO: change values in randint to use the input width and height
randX = random.randint(10,49) * 10
randY = random.randint(21,60) * 10
self.rect.x = randX
self.rect.y = randY
class Snake(pygame.sprite.Sprite):
# TODO: Make Snake a chain of Blocks
def __init__(self, color, width, height, positionX, positionY):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# Update the position of this object by setting the values of rect.x and rect.y
self.rect = self.image.get_rect()
# set the position of the snake
self.rect.x = positionX
self.rect.y = positionY
# set the inputs the usable variables for later code
self.color = color
self.width = width
self.height = height
"""
Method the will change the direction of the Snake towards the left
"""
def moveLeft(self):
newX = self.rect.x - 10
return Snake(self.color, self.width, self.height, newX, self.rect.y)
"""
Method that will change the direction of the Snake toward the right
"""
def moveRight(self):
newX = self.rect.x + 10
return Snake(self.color, self.width, self.height, newX, self.rect.y)
"""
Method that will change the direction of the Snake to go upward
"""
def moveUp(self):
newY = self.rect.y - 10
return Snake(self.color, self.width, self.height, self.rect.x, newY)
"""
Method that will change the direction of the Snake to go downward
"""
def moveDown(self):
newY = self.rect.y + 10
return Snake(self.color, self.width, self.height, self.rect.x, newY)
if __name__ == "__main__":
theApp = App()
theApp.on_execute()

I can agree with the answers above. The only problem appears to be that you did not set the FPS i.e. clock.tick(fps) and the game is too fast so it is unplayable. 30 and under will do in my opinion. Please provide more details.

Code is okay, worked on my machine.
Can u add a screenshot of your command prompt?

Related

pygame top down shooting [duplicate]

This question already has answers here:
Problems with moving an enemy towards a character in pygame
(1 answer)
Pygame doesn't let me use float for rect.move, but I need it
(2 answers)
Closed 8 months ago.
So I have a functioning shooting mechanic in python pygame for a top down shooter, where I am using the mouse position to aim the bullets by working out the angles, however when I do this, the bullets are shooting slightly off where the mouse position is. for instance: the mouse would be where the red arrow is drawn and the bullets will be shooting by a small amount in the wrong direction
Any help would be appreciated
code below:
main.py:
#-------------Imports-------------#
import pygame,sys
#import globals
from background import*
from player import*
#-------------Constants-------------#
WIDTH,HEIGHT = 500,500
WINDOW = pygame.display.set_mode((WIDTH,HEIGHT))
CLOCK = pygame.time.Clock()
BLACK = (0, 0, 0)
#-------------Instances-------------#
bg = Background()
player = Player()
#-------------Functions-------------#
def draw():
WINDOW.fill(BLACK)
bg.update(WINDOW)
player.update(WINDOW)
pygame.display.update()
#-------------Main Game Loop-------------#
def main():
#globals.intialise()
while 1:
CLOCK.tick(1)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
draw()
#globals.game_ticks += 1
if __name__ == "__main__":
main()
player.py
#-------------Imports-------------#
import pygame,math
#import globals
#-------------Constants-------------#
WIDTH,HEIGHT = 500,500
PLAYER_COLOUR = (255, 212, 112)
BLACK = (0,0,0)
PI = 3.14159265359
#-------------Classes-------------#
class Bullet:
def __init__(self,origin,angle):
self.speed = 20
self.x_speed,self.y_speed = self.speed*math.cos(math.radians(angle)),self.speed*math.sin(math.radians(angle))
self.rect = pygame.Rect(origin[0],origin[1],5,5)
def __del__(self):
pass
def update(self,window):
# move bullet
self.rect.x += self.x_speed
self.rect.y += self.y_speed
# draw bullet
pygame.draw.rect(window,BLACK,self.rect)
# check if bullet is out of the screen
if self.rect.x > WIDTH or self.rect.x < 0:
return -1
elif self.rect.y > HEIGHT or self.rect.y < 0:
return -1
class Player:
def __init__(self):
self.sprite = pygame.transform.scale(pygame.image.load("sprites/temp_player.png"),(50,50))
self.rect = pygame.Rect(250,250,50,50)
self.center = (self.rect.x,self.rect.y)
self.bullets = []
self.fire_rate = 12
def shoot(self,angle,window):
# update all bullets and delete if bullet is out of screen
for bullet in self.bullets:
if bullet.update(window) == -1:
self.bullets.remove(bullet)
del bullet
# instantiate bullet if mouse button pressed
#if pygame.mouse.get_pressed()[0] and globals.game_ticks % self.fire_rate == 0:
if pygame.mouse.get_pressed()[0]:
self.bullets.append(Bullet(self.rect.center,-angle))
def update(self,window):
mx,my = pygame.mouse.get_pos()
# find distance between mouse position and player position
diff_x,diff_y = mx-self.rect.x,my-self.rect.y
# word out angle between mouse and player
angle_rad = math.atan2(diff_y,diff_x)
angle = -360*angle_rad/(2*PI)
# adjust angle according to where we want to rotate the player
# when angle is bottom left
if abs(angle) > 90 and angle < 0:
a = 270-abs(angle)
# when angle is top left
elif abs(angle) > 90:
a = angle-90
# when angle is to the right
else:
a = angle - 90
# create new sprite that is rotated
rotated_image = pygame.transform.rotate(self.sprite,a)
# replace current rectangle with rotated sprite
self.rect = rotated_image.get_rect(center = self.center)
self.shoot(angle,window)
# add image to the screen
#window.blit(pygame.transform.rotate(self.sprite,a),self.rect)
background.py:
#-------------Imports-------------#
import pygame,random,ast,time,globals
#-------------Constants-------------#
WIDTH,HEIGHT = 500,500
TILE_DIMENSION = 9
TILE_SIZE = int(round(WIDTH/TILE_DIMENSION,0))
TO_EDGE = int((TILE_DIMENSION+1)/2)
#-------------Classes-------------#
class Background:
def __init__(self):
self.tiles = self.generate_screen()
self.centre = [2,2]
self.right = 0
self.up = 0
self.speed = 5
def generate_screen(self):
# generate original chunk of tiles
tiles = [[random.randint(100,200) for i in range(TILE_DIMENSION)] for j in range(TILE_DIMENSION)]
# eventually use image instead of random RGB value
return tiles
def movement(self,tile_rects):
keys = pygame.key.get_pressed()
if keys[pygame.K_a] or keys[pygame.K_LEFT]:
# if player is on tile to the left of centre
if (self.right - self.speed) < -TILE_SIZE:
# reset movement and adjust centre
self.right = 0
self.centre[0] -= 1
else:
# add to movement if not on next tile
self.right -= self.speed
# move all rectangles in background to simulate player moving
for i in range(len(tile_rects)):
for j in range(len(tile_rects[0])):
tile_rects[i][j].x += self.speed
if keys[pygame.K_d] or keys[pygame.K_RIGHT]:
# if player is on tile to the right of centre
if (self.right + self.speed) > TILE_SIZE:
# reset movement and adjust centre
self.right = 0
self.centre[0] += 1
else:
# add to movement if not on next tile
self.right += self.speed
# move all rectangles in background to simulate player moving
for i in range(len(tile_rects)):
for j in range(len(tile_rects[0])):
tile_rects[i][j].x -= self.speed
if keys[pygame.K_w] or keys[pygame.K_UP]:
# if player is on tile above the centre
if (self.up + self.speed) > TILE_SIZE:
# reset movement and adjust centre
self.up = 0
self.centre[1] -= 1
else:
# add to movement if not on next tile
self.up += self.speed
# move all rectangles in background to simulate player moving
for i in range(len(tile_rects)):
for j in range(len(tile_rects[0])):
tile_rects[i][j].y += self.speed
if keys[pygame.K_s] or keys[pygame.K_DOWN]:
# if player is on tile below the centre
if (self.up - self.speed) < -TILE_SIZE:
# reset movement and adjust centre
self.up = 0
self.centre[1] += 1
else:
# add to movement if not on next tile
self.up -= self.speed
# move all rectangles in background to simulate player moving
for i in range(len(tile_rects)):
for j in range(len(tile_rects[0])):
tile_rects[i][j].y -= self.speed
return tile_rects
def update(self,window):
# rendering in brand new map chunks
# if part of the chunk trying to be rendered in is non-existant in the 2D map array to the left
if self.centre[0]-TO_EDGE < 0:
# check how many tiles it is offset by
for i in range(0-(self.centre[0]-TO_EDGE)):
# add new column of values at the beginning of the 2D array
for i in range(len(self.tiles)):
self.tiles[i].insert(0,random.randint(120,230))
# due to whole array being shifted to the right, adjust the centre accordingly
self.centre[0] += 1
# if part of the chunk trying to be rendered is non-existant in the 2D map array to the right
if self.centre[0]+TO_EDGE >= len(self.tiles[0]):
# check how many tiles it is offset by
for i in range((self.centre[0]+TO_EDGE)-(len(self.tiles[0])-1)):
# add a new column of values at the end of the 2D array
for i in range(len(self.tiles)):
self.tiles[i].append(random.randint(120,230))
# if part of the chunk trying to be rendered in is non-existant in the 2D array at the top
if self.centre[1]-TO_EDGE < 0:
# check how many tiles it is offset by
for i in range(0-(self.centre[1]-TO_EDGE)):
# add a new row at the top of the 2D array
self.tiles.insert(0,[random.randint(120,230) for i in range(len(self.tiles[0]))])
# due to whole array shifting downwards, adjust the centre accordingly
self.centre[1] += 1
# if part of the chunk trying to be rendered in is non-existant in the 2D array at the bottom
if self.centre[1]+TO_EDGE >= len(self.tiles):
# check how many tiles it is offset by
for i in range((self.centre[1]+TO_EDGE)-(len(self.tiles)-1)):
# add a new row at the bottom of the 2D array
self.tiles.append([random.randint(120,230) for i in range(len(self.tiles[0]))])
# determining which tiles should be rendered in according to the centre(where player would be)
t = []
for i in range(TILE_DIMENSION+2):
t.append([])
for j in range(TILE_DIMENSION+2):
try:
t[i].append(self.tiles[i+(self.centre[1]-TO_EDGE)][j+(self.centre[0]-TO_EDGE)])
except:
pass
# create a rectangle for each tile that is rendered in
tile_rects = [[pygame.Rect((i-1)*TILE_SIZE-self.right,(j-1)*TILE_SIZE+self.up,TILE_SIZE,TILE_SIZE) for i in range(TILE_DIMENSION+2)] for j in range(TILE_DIMENSION+2)]
tile_rects = self.movement(tile_rects)
# draw all rectangles
for i in range(TILE_DIMENSION+2):
for j in range(TILE_DIMENSION+2):
try:
pygame.draw.rect(window,(0,int(t[i][j]),0),tile_rects[i][j])
except:
pass
the background script doesnt affect anything, its just there as a background to make it easier to see, and you may have to make your own temp_player.png image to make it compatible

How do I restart my python game, or just reset where the player is?

I want to restart where my player is when the player touches a wall, but before I do that, I want to give them a warning then reset position. I can't do either, though. I recently asked a similar question, and although I got a very good and helpful answer, it wouldn't work. Thank you anyway, Rabbid76. This is my code:
def touch_walls(player_pos):
if x-20 < 0:
#give warning not to touch sides
#reset player position
elif x+20 > 800:
#give warning not to touch sides
#reset player position
If anyone finds a solution, please tell me.
You can call a function to draw a "Don't touch walls" text.
`
def touch_walls(player_pos):
global playerPos, blit_font_time
x = player_pos[0]
if x-20 < 0 or x+20 > 800:
#make a text varible
#reset player position
playerPos = (50, 0)
blit_font_time = 60 # set this to as long as you wish
def blit_font():
text = pygame.font.SysFont('Arial', 50)
warning_label = text.render('Don\'t Touch Walls', True, (255, 255, 255)) #You can modify the text or the color anyway you want
center = (screen.get_width()/2 - warning_label.get_width()/2, screen.get_height()/2 - warning_label.get_height()/2)
screen.blit(warning_label, center) #Blit the text at the center of the screen
`
The whole thing will look like this:
`
import pygame
pygame.init()
playerPos = (-60, 50) # Assume playerPos is a varible that contains the player's position
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
blit_font_time = 0
def touch_walls(player_pos):
global playerPos, blit_font_time
x = player_pos[0]
if x-20 < 0 or x+20 > 800:
#make a text varible
#reset player position
playerPos = (50, 0)
blit_font_time = 60 # set this to as long as you wish
def blit_font():
text = pygame.font.SysFont('Arial', 50)
warning_label = text.render('Don\'t Touch Walls', True, (255, 255, 255)) #You can modify the text or the color anyway you want
center = (screen.get_width()/2 - warning_label.get_width()/2, screen.get_height()/2 - warning_label.get_height()/2)
screen.blit(warning_label, center) #Blit the text at the center of the screen
run = True
while run:
clock.tick(60)
for e in pygame.event.get():
if e.type == pygame.QUIT:
run = False
screen.fill((20, 20, 20))
touch_walls(playerPos)
if blit_font_time > 0:
blit_font_time -= 1
blit_font()
pygame.display.update()
pygame.quit()
`

Having trouble with a "NameError"

I'm new to classes, and this is my third attempt at making one. I've ran into a NameError which I really have no idea how to solve. Take a look at my program and see if you can help.
import random
import math
import pygame
import pickle
# initialise pygame
pygame.init()
# player class
class player(object):
def __init__(self, playerimage, playerX, playerY = 700, playerX_change = 0):
self.playerimage = pygame.image.load("Main Player.png")
self.playerX = 365
self.playerY = 700
self.playerX_change = 0
# laser class
# ready - bullet not on screen
# fire - bullet is shown on screen and is moving
class laser(object):
def __init__(self, laserimage, laserX, laserY, laserY_change):
self.laserimage = pygame.image.load("laser.png")
self.laserX = 0
self.laserY = 700
self.laserY_change = 10
self.laser_state = "ready"
# alien player / random movement = random.randint()
class alien(object):
def __init__(self, alienimage, alienX, alienY, alienX_change, alienY_change, amount_aliens):
self.alienimage = pygame.image.load("alien.png")
self.alienX = []
self.alienY = []
self.alienX_change = []
self.alienY_change = []
self.amount_aliens = 10
for i in range(ufo.amount_aliens):
ufo.alienimage.append(pygame.image.load('alien.png'))
ufo.alienX.append(random.randint(0, 735))
ufo.alienY.append(random.randint(50, 200))
ufo.alienX_change.append(3)
ufo.alienY_change.append(7)
score = 0
# define player
def main_player(x, y):
screen.blit(male.playerimage, (x, y))
# define laster
def fire_laser(x, y):
lasr.laser_state = "fire"
screen.blit(lasr.laserimage, (x + 16, y + 10))
# define alien
def alien(x, y, i):
screen.blit(ufo.alienimage[i], (x, y))
# collision detection
def hascollision(alienX, alienY, laserX, laserY):
distance = math.sqrt((math.pow(alienX - laserX, 2)) + (math.pow(alienY - laserY, 2)))
if distance < 27:
return True
else:
return False
#frames per second
clock = pygame.time.Clock()
# background
background = pygame.image.load('stars.png')
# display and screen title/icon
(width, height) = (800, 800)
screen = pygame.display.set_mode((width, height))
flip = pygame.display.flip()
pygame.display.set_caption("space fighters")
pygame.event.get()
icon = pygame.image.load('logo.png')
pygame.display.set_icon(icon)
from sys import exit
ufo = alien()
lasr = laser(0, 700, 32, 32)
male = player(365, 700,)
# loop of functions
executed = True
while executed:
screen.fill((63, 62, 63))
# image background
screen.blit(background, (0, 0))
for event in pygame.event.get():
# if key pressed, check which input, right or left?
if event.type == pygame.KEYDOWN:
print("key pressed")
if event.key == pygame.K_a:
male.playerX_change = -6
if event.key == pygame.K_s:
male.playerX_change = 6
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_s:
male.playerX_change = 0
if event.key == pygame.K_SPACE:
if lasr.laser_state is "ready":
lasr.laserX = male.playerX
fire_laser(lasr.laserX, lasr.laserY)
#frames per second is 60fps
clock.tick(60)
# bounrary algorithm, prevents player moving out/enemy.
male.playerX += male.playerX_change
if male.playerX <= 0:
male.playerX = 0
elif male.playerX >= 736:
male.playerX = 736
# boundry algorithm, make sure alien doesn't go out of bountry
for i in range(ufo.amount_aliens):
ufo.alienX[i] += ufo.alienX_change[i]
if ufo.alienX[i] <= 0:
ufo.alienX_change[i] = 4
ufo.alienY[i] += ufo.alienY_change[i]
elif ufo.alienX[i] >= 736:
ufo.alienX_change[i] = -4
ufo.alienY[i] += ufo.alienY_change[i]
# collision
collision = hascollision(ufo.alienX[i], ufo.alienY[i], lasr.laserX, lasr.laserY)
if collision:
lasr.laserY = 650
lasr.laser_state = "ready"
score += 5
print(score)
alienX[i] = random.randint(0, 735)
alienY[i] = random.randint(50, 200)
alien(ufo.alienX[i], ufo.alienY[i], i)
# movement of laser shot
if lasr.laserY <= 0:
lasr.laserY = 650
lasr.laser_state = "ready"
if lasr.laser_state is "fire":
fire_laser(lasr.laserX, lasr.laserY)
lasr.laserY -= lasr.laserY_change
# updates screen to show screen
main_player(male.playerX, male.playerY)
pygame.display.update()
pygame.quit()
This is the output of the error given by visual studio code (it is on line 39)
for i in range(ufo.amount_aliens):
NameError: name 'ufo' is not defined
The alien class is a bit mixed up. (Although it's hard to tell if this is just an indentation issue in the SO paste.) I'm going to assume that the list of ufos needs to be made outside the class, because this is the only thing that makes sense. Later on in the code, you declare an alien function which will occlude the alien class too. You will need to fix this first - it's best moved into the alien class as alien.draw()
So to make a bunch of aliens, create a list:
alien_image = pygame.image.load('alien.png')
all_ufos = []
for i in range( amount_aliens ):
x_pos = random.randint( 0, 735 )
y_pos = random.randint( 50, 200 )
x_speed = 3
y_speed = 7
all_ufos.append( alien( alien_image, x_pos, y_pos, x_speed, y_speed ) )
Remove the amount_aliens from the alien object, so that it now only represents a single alien.
class alien( object ):
def __init__( self, alienimage, alienX, alienY, alienX_change, alienY_change ):
self.alienimage = alienimage
self.alienX = alienX
self.alienY = alienY
self.alienX_change = alienX_change
self.alienY_change = alienY_change
And move the support functions into the alien class.
def draw( self, screen ):
""" Draw the alien to the screen """
screen.blit( self.alienimage, ( self.alienX, self.alienY ) )
def hasCollision( self, laserX, laserY ):
""" Has the laser at collided with this alien? """
distance = math.sqrt((math.pow(self.alienX - laserX, 2)) + (math.pow(self.alienY - laserY, 2)))
return ( distance < 27 ):
This allows your main loop to iterate over the list of aliens, doing stuff simply:
### Main Loop
while not exiting:
...
# paint all UFO sprites
for ufo in all_ufos:
ufo.draw( screen )
# check all lasers for collision
for laser in all_lasers:
for ufo in all_ufos:
if ( ufo.hasCollision( laser.laserX, laser.laserY ) ):
print( "*boom*" )
What you are doing here is re-creating some of the functionality of the PyGame Sprite and SpriteGroup Classes. It might be worth a quick read of the documentation on it.

How do I make images appear/disappear in pygame?

I am creating a battleship-type game. I am using .blit to display images that I load using the function pygame.image.load. I was wondering, is it possible to make images like this appear/disappear at different points?
My code is as follows:
import random, sys, pygame
from pygame.locals import *
# Set variables, like screen width and height
# globals
FPS = 60 #Determines the number of frames per second
REVEALSPEED = 2 #Determines the speed at which the squares reveals after being clicked
WINDOWWIDTH = 800 #Width of game window
WINDOWHEIGHT = 600 #Height of game window
TILESIZE = 40 #Size of the squares in each grid(tile)
MARKERSIZE = 40 #Size of the box which contatins the number that indicates how many ships in this row/col
BUTTONHEIGHT = 20 #Height of a standard button
BUTTONWIDTH = 40 #Width of a standard button
TEXT_HEIGHT = 25 #Size of the text
TEXT_LEFT_POSN = 10 #Where the text will be positioned
BOARDWIDTH = 6 #Number of grids horizontally
BOARDHEIGHT = 6 #Number of grids vertically
DISPLAYWIDTH = 200 #Width of the game board
EXPLOSIONSPEED = 10 #How fast the explosion graphics will play
XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH * TILESIZE) - DISPLAYWIDTH - MARKERSIZE) / 2) #x-position of the top left corner of board
YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * TILESIZE) - MARKERSIZE) / 2) #y-position of the top left corner of board
#Colours which will be used by the game
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
GREEN = ( 0, 204, 0)
GRAY = ( 60, 60, 60)
BLUE = ( 0, 50, 255)
YELLOW = (255, 255, 0)
DARKGRAY =( 40, 40, 40)
transparent = (0, 0, 0, 0)
#Determine what to colour each element of the game
BGCOLOR = GRAY
BUTTONCOLOR = GREEN
TEXTCOLOR = WHITE
TILECOLOR = GREEN
BORDERCOLOR = BLUE
TEXTSHADOWCOLOR = BLUE
SHIPCOLOR = YELLOW
HIGHLIGHTCOLOR = BLUE
def main():
"""
The main function intializes the variables which will be used by the game.
"""
global DISPLAYSURF, FPSCLOCK, BASICFONT, HELP_SURF, HELP_RECT, NEW_SURF, \
NEW_RECT, SHOTS_SURF, SHOTS_RECT, BIGFONT, COUNTER_SURF, \
COUNTER_RECT, HBUTTON_SURF, EXPLOSION_IMAGES
pygame.init()
FPSCLOCK = pygame.time.Clock()
#Fonts used by the game
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
BASICFONT = pygame.font.Font('freesansbold.ttf', 20)
BIGFONT = pygame.font.Font('freesansbold.ttf', 50)
# Create and label the buttons
HELP_SURF = BASICFONT.render("HELP", True, WHITE)
HELP_RECT = HELP_SURF.get_rect()
HELP_RECT.topleft = (WINDOWWIDTH - 180, WINDOWHEIGHT - 350)
NEW_SURF = BASICFONT.render("NEW GAME", True, WHITE)
NEW_RECT = NEW_SURF.get_rect()
NEW_RECT.topleft = (WINDOWWIDTH - 200, WINDOWHEIGHT - 200)
# The 'Shots:' label at the top
SHOTS_SURF = BASICFONT.render("Shots: ", True, WHITE)
SHOTS_RECT = SHOTS_SURF.get_rect()
SHOTS_RECT.topleft = (WINDOWWIDTH - 750, WINDOWHEIGHT - 570)
# Load the explosion graphics from the /img folder
EXPLOSION_IMAGES = [
pygame.image.load("blowup1.png"), pygame.image.load("blowup2.png"),
pygame.image.load("blowup3.png"),pygame.image.load("blowup4.png"),
pygame.image.load("blowup5.png"),pygame.image.load("blowup6.png")]
# Set the title in the menu bar to 'Battleship'
pygame.display.set_caption('Battleship')
# Keep the game running at all times
while True:
shots_taken = run_game() #Run the game until it stops and save the result in shots_taken
show_gameover_screen(shots_taken) #Display a gameover screen by passing in shots_taken
def run_game():
greenButton = pygame.image.load('green-button-icon-png-13.png')
greenButton = pygame.transform.scale(greenButton, (75,75))
rect = greenButton.get_rect()
rect = rect.move((150, 475))
redButton = pygame.image.load('red-button-1426817_960_720.png')
redButton = pygame.transform.scale(redButton, (85,85))
rect2 = redButton.get_rect()
rect2 = rect2.move((400, 475))
"""
Function is executed while a game is running.
returns the amount of shots taken
"""
revealed_tiles = generate_default_tiles(False) #Contains the list of the tiles revealed by user
# main board object,
main_board = generate_default_tiles(None) #Contains the list of the ships which exists on board
ship_objs = ['raft'] # List of the ships available
main_board = add_ships_to_board(main_board, ship_objs) #call add_ships_to_board to add the list of ships to the main_board
mousex, mousey = 0, 0 #location of mouse
counter = [] #counter to track number of shots fired
while True:
# counter display (it needs to be here in order to refresh it)
COUNTER_SURF = BASICFONT.render(str(len(counter)), True, WHITE)
COUNTER_RECT = SHOTS_SURF.get_rect()
COUNTER_RECT.topleft = (WINDOWWIDTH - 680, WINDOWHEIGHT - 570)
# Fill background
DISPLAYSURF.fill(BGCOLOR)
# draw the buttons
DISPLAYSURF.blit(HELP_SURF, HELP_RECT)
DISPLAYSURF.blit(NEW_SURF, NEW_RECT)
DISPLAYSURF.blit(SHOTS_SURF, SHOTS_RECT)
DISPLAYSURF.blit(COUNTER_SURF, COUNTER_RECT)
DISPLAYSURF.blit(greenButton, rect)
DISPLAYSURF.blit(redButton, rect2)
greenButton.fill(transparent)
DISPLAYSURF.blit(greenButton, rect)
# Draw the tiles onto the board and their respective markers
draw_board(main_board, revealed_tiles)
mouse_clicked = False
check_for_quit()
#Check for pygame events
for event in pygame.event.get():
if event.type == MOUSEBUTTONUP:
if HELP_RECT.collidepoint(event.pos): #if the help button is clicked on
DISPLAYSURF.fill(BGCOLOR)
show_help_screen() #Show the help screen
elif NEW_RECT.collidepoint(event.pos): #if the new game button is clicked on
main() #goto main, which resets the game
else: #otherwise
mousex, mousey = event.pos #set mouse positions to the new position
mouse_clicked = True #mouse is clicked but not on a button
elif event.type == MOUSEMOTION: #Detected mouse motion
mousex, mousey = event.pos #set mouse positions to the new position
#Check if the mouse is clicked at a position with a ship piece
tilex, tiley = get_tile_at_pixel(mousex, mousey)
if tilex != None and tiley != None:
if not revealed_tiles[tilex][tiley]: #if the tile the mouse is on is not revealed
draw_highlight_tile(tilex, tiley) # draws the hovering highlight over the tile
if not revealed_tiles[tilex][tiley] and mouse_clicked: #if the mouse is clicked on the not revealed tile
reveal_tile_animation(main_board, [(tilex, tiley)])
revealed_tiles[tilex][tiley] = True #set the tile to now be revealed
if check_revealed_tile(main_board, [(tilex, tiley)]): # if the clicked position contains a ship piece
left, top = left_top_coords_tile(tilex, tiley)
blowup_animation((left, top))
if check_for_win(main_board, revealed_tiles): # check for a win
counter.append((tilex, tiley))
return len(counter) # return the amount of shots taken
counter.append((tilex, tiley))
pygame.display.update()
FPSCLOCK.tick(FPS)
def generate_default_tiles(default_value):
"""
Function generates a list of 10 x 10 tiles. The list will contain tuples
('shipName', boolShot) set to their (default_value).
default_value -> boolean which tells what the value to set to
returns the list of tuples
"""
default_tiles = [[default_value]*BOARDHEIGHT for i in range(BOARDWIDTH)]
return default_tiles
def blowup_animation(coord):
"""
Function creates the explosition played if a ship is shot.
coord -> tuple of tile coords to apply the blowup animation
"""
for image in EXPLOSION_IMAGES: # go through the list of images in the list of pictures and play them in sequence
#Determine the location and size to display the image
image = pygame.transform.scale(image, (TILESIZE+10, TILESIZE+10))
DISPLAYSURF.blit(image, coord)
pygame.display.flip()
FPSCLOCK.tick(EXPLOSIONSPEED) #Determine the delay to play the image with
def check_revealed_tile(board, tile):
"""
Function checks if a tile location contains a ship piece.
board -> the tiled board either a ship piece or none
tile -> location of tile
returns True if ship piece exists at tile location
"""
return board[tile[0][0]][tile[0][1]] != None
def reveal_tile_animation(board, tile_to_reveal):
"""
Function creates an animation which plays when the mouse is clicked on a tile, and whatever is
behind the tile needs to be revealed.
board -> list of board tile tuples ('shipName', boolShot)
tile_to_reveal -> tuple of tile coords to apply the reveal animation to
"""
for coverage in range(TILESIZE, (-REVEALSPEED) - 1, -REVEALSPEED): #Plays animation based on reveal speed
draw_tile_covers(board, tile_to_reveal, coverage)
def draw_tile_covers(board, tile, coverage):
"""
Function draws the tiles according to a set of variables.
board -> list; of board tiles
tile -> tuple; of tile coords to reveal
coverage -> int; amount of the tile that is covered
"""
left, top = left_top_coords_tile(tile[0][0], tile[0][1])
if check_revealed_tile(board, tile):
pygame.draw.rect(DISPLAYSURF, SHIPCOLOR, (left, top, TILESIZE,
TILESIZE))
else:
pygame.draw.rect(DISPLAYSURF, BGCOLOR, (left, top, TILESIZE,
TILESIZE))
if coverage > 0:
pygame.draw.rect(DISPLAYSURF, TILECOLOR, (left, top, coverage,
TILESIZE))
pygame.display.update()
FPSCLOCK.tick(FPS)
def check_for_quit():
"""
Function checks if the user has attempted to quit the game.
"""
for event in pygame.event.get(QUIT):
pygame.quit()
sys.exit()
def check_for_win(board, revealed):
"""
Function checks if the current board state is a winning state.
board -> the board which contains the ship pieces
revealed -> list of revealed tiles
returns True if all the ships are revealed
"""
for tilex in range(BOARDWIDTH):
for tiley in range(BOARDHEIGHT):
if board[tilex][tiley] != None and not revealed[tilex][tiley]: # check if every board with a ship is revealed, return false if not
return False
return True
def draw_board(board, revealed):
"""
Function draws the game board.
board -> list of board tiles
revealed -> list of revealed tiles
"""
#draws the grids depending on its state
for tilex in range(BOARDWIDTH):
for tiley in range(BOARDHEIGHT):
left, top = left_top_coords_tile(tilex, tiley)
if not revealed[tilex][tiley]:
pygame.draw.rect(DISPLAYSURF, TILECOLOR, (left, top, TILESIZE,
TILESIZE))
else:
if board[tilex][tiley] != None:
pygame.draw.rect(DISPLAYSURF, SHIPCOLOR, (left, top,
TILESIZE, TILESIZE))
else:
pygame.draw.rect(DISPLAYSURF, BGCOLOR, (left, top,
TILESIZE, TILESIZE))
#draws the horizontal lines
for x in range(0, (BOARDWIDTH + 1) * TILESIZE, TILESIZE):
pygame.draw.line(DISPLAYSURF, DARKGRAY, (x + XMARGIN + MARKERSIZE,
YMARGIN + MARKERSIZE), (x + XMARGIN + MARKERSIZE,
WINDOWHEIGHT - YMARGIN))
#draws the vertical lines
for y in range(0, (BOARDHEIGHT + 1) * TILESIZE, TILESIZE):
pygame.draw.line(DISPLAYSURF, DARKGRAY, (XMARGIN + MARKERSIZE, y +
YMARGIN + MARKERSIZE), (WINDOWWIDTH - (DISPLAYWIDTH + MARKERSIZE *
2), y + YMARGIN + MARKERSIZE))
def add_ships_to_board(board, ships):
"""
Function goes through a list of ships and add them randomly into a board.
board -> list of board tiles
ships -> list of ships to place on board
returns list of board tiles with ships placed on certain tiles
"""
new_board = board[:]
ship_length = 0
for ship in ships: #go through each ship declared in the list
#Randomly find a valid position that fits the ship
valid_ship_position = False
while not valid_ship_position:
xStartpos = random.randint(0, (BOARDHEIGHT-1))
yStartpos = random.randint(0, (BOARDHEIGHT-1))
isHorizontal = random.randint(0, 1) #vertical or horizontal positioning
#Type of ship and their respective length
if 'battleship' in ship:
ship_length = 5
elif 'destroyer' in ship:
ship_length = 4
elif 'cruiser'in ship:
ship_length = 3
elif 'submarine' in ship:
ship_length = 2
elif 'raft' in ship:
ship_length = 1
#check if position is valid
valid_ship_position, ship_coords = make_ship_position(new_board,
xStartpos, yStartpos, isHorizontal, ship_length, ship)
#add the ship if it is valid
if valid_ship_position:
for coord in ship_coords:
new_board[coord[0]][coord[1]] = ship
return new_board
def make_ship_position(board, xPos, yPos, isHorizontal, length, ship):
"""
Function makes a ship on a board given a set of variables
board -> list of board tiles
xPos -> x-coordinate of first ship piece
yPos -> y-coordinate of first ship piece
isHorizontal -> True if ship is horizontal
length -> length of ship
returns tuple: True if ship position is valid and list ship coordinates
"""
ship_coordinates = [] #the coordinates the ship will occupy
if isHorizontal:
for i in range(length):
if (i+xPos > (BOARDHEIGHT-1)) or (board[i+xPos][yPos] != None) or \
hasAdjacent(board, i+xPos, yPos, ship): #if the ship goes out of bound, hits another ship, or is adjacent to another ship
return (False, ship_coordinates) #then return false
else:
ship_coordinates.append((i+xPos, yPos))
else:
for i in range(length):
if (i+yPos > (BOARDHEIGHT-1)) or (board[xPos][i+yPos] != None) or \
hasAdjacent(board, xPos, i+yPos, ship): #if the ship goes out of bound, hits another ship, or is adjacent to another ship
return (False, ship_coordinates) #then return false
else:
ship_coordinates.append((xPos, i+yPos))
return (True, ship_coordinates) #ship is successfully added
def hasAdjacent(board, xPos, yPos, ship):
"""
Funtion checks if a ship has adjacent ships
board -> list of board tiles
xPos -> x-coordinate of first ship piece
yPos -> y-coordinate of first ship piece
ship -> the ship being checked for adjacency
returns true if there are adjacent ships and false if there are no adjacent ships
"""
for x in range(xPos-1,xPos+2):
for y in range(yPos-1,yPos+2):
if (x in range (BOARDHEIGHT)) and (y in range (BOARDHEIGHT)) and \
(board[x][y] not in (ship, None)):
return True
return False
def left_top_coords_tile(tilex, tiley):
"""
Function calculates and returns the pixel of the tile in the top left corner
tilex -> int; x position of tile
tiley -> int; y position of tile
returns tuple (int, int) which indicates top-left pixel coordinates of tile
"""
left = tilex * TILESIZE + XMARGIN + MARKERSIZE
top = tiley * TILESIZE + YMARGIN + MARKERSIZE
return (left, top)
def get_tile_at_pixel(x, y):
"""
Function finds the corresponding tile coordinates of pixel at top left, defaults to (None, None) given a coordinate.
x -> int; x position of pixel
y -> int; y position of pixel
returns tuple (tilex, tiley)
"""
for tilex in range(BOARDWIDTH):
for tiley in range(BOARDHEIGHT):
left, top = left_top_coords_tile(tilex, tiley)
tile_rect = pygame.Rect(left, top, TILESIZE, TILESIZE)
if tile_rect.collidepoint(x, y):
return (tilex, tiley)
return (None, None)
def draw_highlight_tile(tilex, tiley):
"""
Function draws the hovering highlight over the tile.
tilex -> int; x position of tile
tiley -> int; y position of tile
"""
left, top = left_top_coords_tile(tilex, tiley)
pygame.draw.rect(DISPLAYSURF, HIGHLIGHTCOLOR,
(left, top, TILESIZE, TILESIZE), 4)
def show_help_screen():
"""
Function display a help screen until any button is pressed.
"""
line1_surf, line1_rect = make_text_objs('Press a key to return to the game',
BASICFONT, TEXTCOLOR)
line1_rect.topleft = (TEXT_LEFT_POSN, TEXT_HEIGHT)
DISPLAYSURF.blit(line1_surf, line1_rect)
line2_surf, line2_rect = make_text_objs(
'This is a battleship puzzle game. Your objective is ' \
'to sink all the ships in as few', BASICFONT, TEXTCOLOR)
line2_rect.topleft = (TEXT_LEFT_POSN, TEXT_HEIGHT * 3)
DISPLAYSURF.blit(line2_surf, line2_rect)
line3_surf, line3_rect = make_text_objs('shots as possible. The markers on'\
' the edges of the game board tell you how', BASICFONT, TEXTCOLOR)
line3_rect.topleft = (TEXT_LEFT_POSN, TEXT_HEIGHT * 4)
DISPLAYSURF.blit(line3_surf, line3_rect)
line4_surf, line4_rect = make_text_objs('many ship pieces are in each'\
' column and row. To reset your game click on', BASICFONT, TEXTCOLOR)
line4_rect.topleft = (TEXT_LEFT_POSN, TEXT_HEIGHT * 5)
DISPLAYSURF.blit(line4_surf, line4_rect)
line5_surf, line5_rect = make_text_objs('the "New Game" button.',
BASICFONT, TEXTCOLOR)
line5_rect.topleft = (TEXT_LEFT_POSN, TEXT_HEIGHT * 6)
DISPLAYSURF.blit(line5_surf, line5_rect)
while check_for_keypress() == None: #Check if the user has pressed keys, if so go back to the game
pygame.display.update()
FPSCLOCK.tick()
def check_for_keypress():
"""
Function checks for any key presses by pulling out all KEYDOWN and KEYUP events from queue.
returns any KEYUP events, otherwise return None
"""
for event in pygame.event.get([KEYDOWN, KEYUP, MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION]):
if event.type in (KEYDOWN, MOUSEBUTTONUP, MOUSEBUTTONDOWN, MOUSEMOTION):
continue
return event.key
return None
def make_text_objs(text, font, color):
"""
Function creates a text.
text -> string; content of text
font -> Font object; face of font
color -> tuple of color (red, green blue); colour of text
returns the surface object, rectangle object
"""
surf = font.render(text, True, color)
return surf, surf.get_rect()
def show_gameover_screen(shots_fired):
"""
Function display a gameover screen when the user has successfully shot at every ship pieces.
shots_fired -> the number of shots taken before game is over
"""
DISPLAYSURF.fill(BGCOLOR)
titleSurf, titleRect = make_text_objs('Congrats! Puzzle solved in:',
BIGFONT, TEXTSHADOWCOLOR)
titleRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2))
DISPLAYSURF.blit(titleSurf, titleRect)
titleSurf, titleRect = make_text_objs('Congrats! Puzzle solved in:',
BIGFONT, TEXTCOLOR)
titleRect.center = (int(WINDOWWIDTH / 2) - 3, int(WINDOWHEIGHT / 2) - 3)
DISPLAYSURF.blit(titleSurf, titleRect)
titleSurf, titleRect = make_text_objs(str(shots_fired) + ' shots',
BIGFONT, TEXTSHADOWCOLOR)
titleRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2 + 50))
DISPLAYSURF.blit(titleSurf, titleRect)
titleSurf, titleRect = make_text_objs(str(shots_fired) + ' shots',
BIGFONT, TEXTCOLOR)
titleRect.center = (int(WINDOWWIDTH / 2) - 3, int(WINDOWHEIGHT / 2 + 50) - 3)
DISPLAYSURF.blit(titleSurf, titleRect)
pressKeySurf, pressKeyRect = make_text_objs(
'Press a key to try to beat that score.', BASICFONT, TEXTCOLOR)
pressKeyRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2) + 100)
DISPLAYSURF.blit(pressKeySurf, pressKeyRect)
while check_for_keypress() == None: #Check if the user has pressed keys, if so start a new game
pygame.display.update()
FPSCLOCK.tick()
if __name__ == "__main__": #This calls the game loop
main()
Generally there's two ways of doing this.
The more common way is to re-paint the entire screen on each iteration of the main loop.
For example:
### Main Loop
while not done:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
elif ( event.type == pygame.MOUSEBUTTONUP ):
mouse_position = pygame.mouse.get_pos() # Location of mouse-click
player_moves.append ( PlayerMove( mouse_position ) ) # Make a new move
# Re-paint the screen
window.fill( OCEAN_BLUE_COLOUR ) # clear the screen
# Paint each of the players turns
for m in player_moves:
m.draw( window ) # paints a hit or miss icon
pygame.display.flip()
Alternatively, instead of re-painting everything, only change the items that have updated, or when events happen. This is close to the "dirty-rectangles" method of updating.
# Initially paint the screen
window.fill( OCEAN_BLUE_COLOUR ) # clear the screen
### Main Loop
while not done:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
elif ( event.type == pygame.MOUSEBUTTONUP ):
mouse_position = pygame.mouse.get_pos() # Location of mouse-click
move = playerMove( mouse_position )
move.draw( window )
pygame.display.flip()
The difficulty of the second method, is that the program needs to clean up after the movement of on-screen images (otherwise they will leave a trail). Obviously in a battleship game, no on-screen elements move - but things like re-drawing scores or starting a new game will need to somehow erase the background. I'm not sure if this will also re-paint the window after it has been occluded by another window.
If you are a beginner programmer, I would use the first method. It's much simpler, and a lot of games are written this way.

Single player 'pong' game

I am just starting out learning pygame and livewires, and I'm trying to make a single-player pong game, where you just hit the ball, and it bounces around until it passes your paddle (located on the left side of the screen and controlled by the mouse), which makes you lose. I have the basic code, but the ball doesn't stay on the screen, it just flickers and doesn't remain constant. Also, the paddle does not move with the mouse. I'm sure I'm missing something simple, but I just can't figure it out. Help please! Here's what I have:
from livewires import games
import random
games.init(screen_width=640, screen_height=480, fps=50)
class Paddle(games.Sprite):
image=games.load_image("paddle.bmp")
def __init__(self, x=10):
super(Paddle, self).__init__(image=Paddle.image,
y=games.mouse.y,
left=10)
self.score=games.Text(value=0, size=25, top=5, right=games.screen.width - 10)
games.screen.add(self.score)
def update(self):
self.y=games.mouse.y
if self.top<0:
self.top=0
if self.bottom>games.screen.height:
self.bottom=games.screen.height
self.check_collide()
def check_collide(self):
for ball in self.overlapping_sprites:
self.score.value+=1
ball.handle_collide()
class Ball(games.Sprite):
image=games.load_image("ball.bmp")
speed=5
def __init__(self, x=90, y=90):
super(Ball, self).__init__(image=Ball.image,
x=x, y=y,
dx=Ball.speed, dy=Ball.speed)
def update(self):
if self.right>games.screen.width:
self.dx=-self.dx
if self.bottom>games.screen.height or self.top<0:
self.dy=-self.dy
if self.left<0:
self.end_game()
self.destroy()
def handle_collide(self):
self.dx=-self.dx
def end_game(self):
end_message=games.Message(value="Game Over",
size=90,
x=games.screen.width/2,
y=games.screen.height/2,
lifetime=250,
after_death=games.screen.quit)
games.screen.add(end_message)
def main():
background_image=games.load_image("background.bmp", transparent=False)
games.screen.background=background_image
paddle_image=games.load_image("paddle.bmp")
the_paddle=games.Sprite(image=paddle_image,
x=10,
y=games.mouse.y)
games.screen.add(the_paddle)
ball_image=games.load_image("ball.bmp")
the_ball=games.Sprite(image=ball_image,
x=630,
y=200,
dx=2,
dy=2)
games.screen.add(the_ball)
games.mouse.is_visible=False
games.screen.event_grab=True
games.screen.mainloop()
main()
I can't help you because you did not post the complete code here. At least, I do not see where you're updating the positions of the sprites (self.x += self.dx somewhere?) and updating the draw to screen. You're also not utilising your classes in the main() function.
That said, I'm seeing
def __init__(self, x=10):
and inside the constructor you never used the x variable. That worries me, too.
Consider using the Paddle and Ball class as a Sprite, like the following:
if __name__ == '__main__':
background_image = games.load_image("background.bmp", transparent=False)
games.screen.background = background_image
the_paddle = Puddle()
games.screen.add(the_paddle)
the_ball = Ball()
games.screen.add(the_ball)
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
Note I've taken the liberty to make your code read more Pythonic. I have never used livewires, however, so my code may not function. But it should point you to the right direction. Good luck!
Why are you using livewires? You can use only pygame for a pong game.
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480)) # window size
pygame.display.set_caption("Simple pong") # window title
# this is a rect that contains the ball
# at the beginning it is set in the center of the screen
ball_rect = pygame.Rect((312, 232), (16, 16))
# speed of the ball (x, y)
ball_speed = [4, 4]
# this contains your paddle
# vertically centered on the left side
paddle_rect = pygame.Rect((8, 200), (8, 80))
# 1 point if you hit the ball
# -5 point if you miss the ball
score = 0
# load the font for displaying the score
font = pygame.font.Font(None, 30)
# mainloop
while True:
# event handler
for event in pygame.event.get():
# quit event => close the game
if event.type == pygame.QUIT:
exit(0)
# control the paddle with the mouse
elif event.type == pygame.MOUSEMOTION:
paddle_rect.centery = event.pos[1]
# correct paddle position if it's going out of window
if paddle_rect.top < 0:
paddle_rect.top = 0
elif paddle_rect.bottom >= 480:
paddle_rect.bottom = 480
# this test if up or down keys are pressed
# if yes move the paddle
if pygame.key.get_pressed()[pygame.K_UP] and paddle_rect.top > 0:
paddle_rect.top -= 5
elif pygame.key.get_pressed()[pygame.K_DOWN] and paddle_rect.bottom < 480:
paddle_rect.top += 5
# update ball position
# this move the ball
ball_rect.left += ball_speed[0]
ball_rect.top += ball_speed[1]
# these two if block control if the ball is going out on the screen
# if it's going it reverse speed to simulate a bounce
if ball_rect.top <= 0 or ball_rect.bottom >= 480:
ball_speed[1] = -ball_speed[1]
if ball_rect.right >= 640:
ball_speed[0] = -ball_speed[0]
# this control if the ball touched the left side
elif ball_rect.left <= 0:
score -= 5
# reset the ball to the center
ball_rect = pygame.Rect((312, 232), (16, 16))
# test if the ball is hit by the paddle
# if yes reverse speed and add a point
if paddle_rect.colliderect(ball_rect):
ball_speed[0] = -ball_speed[0]
score += 1
# clear screen
screen.fill((255, 255, 255))
# draw the ball, the paddle and the score
pygame.draw.rect(screen, (0, 0, 0), paddle_rect) # paddle
pygame.draw.circle(screen, (0, 0, 0), ball_rect.center, ball_rect.width/2) # ball
score_text = font.render(str(score), True, (0, 0, 0))
screen.blit(score_text, (320-font.size(str(score))[0]/2, 5)) # score
# update screen and wait 20 milliseconds
pygame.display.flip()
pygame.time.delay(20)

Categories

Resources