I decided to try and make the snake-eating dot game on my own. I can't make my pygame window stay open when I try and run what I have. How can I make it stay open?
import pygame
import time
import random
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
black = (0,0,0)
white = (255,255,255)
snake_width = 20
snake_height = 20
pygame.init()
game_width = 800
game_height = 600
gameDisplay = pygame.display.set_mode((game_width,game_height))
pygame.display.set_caption('Snake Game!')
clock = pygame.time.Clock()
class game:
def _init_(self):
snake_startx = (game_width/2)
snake_starty = (game_heiht/2)
x = thingx
y = thingy
x_change = 0
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
x_change = -5
elif event.key == pygame.K_UP:
x_change = 5
snake(white, thing_startx, thing_starty, snake_width,
snake_height, x_change)
pygame.display.update()
clock.tick(60)
class snake:
def _init_(self, color, thingx, thingy, thingw, thingh, things):
color = white
thingx = snake_startx
thingy = snake_starty
thingw = snake_width
thingh = snake_height
things = x_change
pygame.draw.rect(gameDisplay, white, [snake_startx,
snake_starty,
snake_width, snake_height,])
game()
pygame.quit()
quit()
Had to rewrite more than half of the code. I wouldn't suggest following what guide you were using. Furthermore if you are very beginner at the python language I wouldn't recommend looking into object orientation just yet. First learn about data types, and loops. You can still make pygame projects without object orientation, but if you know how to use OOP then still use it.
import pygame
import time
import random
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
black = (0,0,0)
white = (255,255,255)
snake_width = 20
snake_height = 20
pygame.init()
game_width = 800
game_height = 600
x_change = 0
y_change = 0
gameDisplay = pygame.display.set_mode((game_width,game_height))
pygame.display.set_caption('Snake Game!')
clock = pygame.time.Clock()
gameDisplay.fill(black)
class snake:
def __init__(self, color, thingw, thingh, movementspeedX, movementspeedY):
self.color = color
self.width = thingw
self.height = thingh
self.Xspeed = movementspeedX
self.Yspeed = movementspeedY
self.snake_startx = (game_width/2)
self.snake_starty = (game_height/2)
self.Xpos = self.snake_startx
self.Ypos = self.snake_starty
def Draw(self):
pygame.draw.rect(gameDisplay, self.color, pygame.Rect([self.Xpos, self.Ypos, self.width, self.height]))
def Update(self):
self.Xpos += self.Xspeed
self.Ypos += self.Yspeed
SnakeObject = snake(white, snake_width, snake_height, x_change, y_change)
SnakeObject.Draw()
gameRunning = True
while gameRunning:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print("QUIT")
pygame.quit()
gameRunning = False
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
SnakeObject.Xspeed = -5
SnakeObject.Yspeed = 0
elif event.key == pygame.K_RIGHT:
SnakeObject.Xspeed = 5
SnakeObject.Yspeed = 0
elif event.key == pygame.K_DOWN:
SnakeObject.Yspeed = 5
SnakeObject.Xspeed = 0
elif event.key == pygame.K_UP:
SnakeObject.Yspeed = -5
SnakeObject.Xspeed = 0
print(SnakeObject.Yspeed)
print(SnakeObject.Xspeed)
SnakeObject.Update()
SnakeObject.Draw()
pygame.display.update()
clock.tick(60)
Related
I am having this problem where I can draw a grid for my snake but I cant fill in the colour between it.It seems like the problem is that because the grid on the surface overrides the actual colour of the background but I dont know how to fix this, can anyone who knows more about pygame help.
See line 74 of my code and that is the colour it should be.
How could I optimise this simple python pygame code
import pygame
import time
import random
pygame.init()
display_width = 960
display_height = 540
display = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Snake")
pureblue = (0,0,255)
purered = (255,0,0)
puregreen = (0,255,0)
green = (0,150,0)
white = (255,255,255)
black = (1,1,1)
grey = (75,75,75)
darkgrey = (50,50,50)
clock = pygame.time.Clock()
snake_block = 10
snake_speed = 5
font_style = pygame.font.SysFont(None, 50)
def drawGrid(surf):
blockSize = snake_block
for x in range(display_width):
for y in range(display_height):
rect = pygame.Rect(x*blockSize, y*blockSize,blockSize, blockSize)
pygame.draw.rect(surf, darkgrey, rect, 1)
grid_surf = pygame.Surface(display.get_size())
drawGrid(grid_surf)
def message(msg, colour):
text = font_style.render(msg, True, colour)
display.blit(text, [display_width/2, display_height/2])
def SnakeGameLoop():
game_over = False
X = display_width/2
Y = display_height/2
X_change = 0
Y_change = 0
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
X_change = -snake_block
Y_change = 0
elif event.key == pygame.K_RIGHT:
X_change = snake_block
Y_change = 0
elif event.key == pygame.K_UP:
X_change = 0
Y_change = -snake_block
elif event.key == pygame.K_DOWN:
X_change = 0
Y_change = snake_block
if X >= display_width or X < 0 or Y >= display_height or Y < 0:
game_over = True
X += X_change
Y += Y_change
display.fill(grey)
display.blit(grid_surf, (0,0))
pygame.draw.rect(display,puregreen,[X,Y,snake_block,snake_block])
pygame.display.update()
clock.tick(snake_speed)
message("You lost", purered)
pygame.display.update()
time.sleep(2)
pygame.quit()
quit()
SnakeGameLoop()
You need to fill the grid Surface with the background color:
def drawGrid(surf):
surf.fill(grey) # <--- ADD
blockSize = snake_block
for x in range(display_width):
for y in range(display_height):
rect = pygame.Rect(x*blockSize, y*blockSize,blockSize, blockSize)
pygame.draw.rect(surf, darkgrey, rect, 1)
grid_surf = pygame.Surface(display.get_size())
drawGrid(grid_surf)
Since the grid Surface covers the entire display it is not necessary to clear the display in the application loop:
def SnakeGameLoop():
# [...]
while not game_over:
# [...]
# display.fill(grey) <--- DELETE
display.blit(grid_surf, (0,0))
pygame.draw.rect(display,puregreen,[X,Y,snake_block,snake_block])
pygame.display.update()
# [...]
I am unable to detect when two rectangles of different sizes collide.
I've tried, "if x == obj_x and y == obj_y:" where x is one rectangle's x-value, obj_x is the other rectangle's x value, and the same for the y-values.
import pygame
import time
import random
pygame.init()
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
display_width = 500
display_height = 500
screen = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Avoid')
x_change = 0
y_change = 0
FPS = 30
block_size = 10
font = pygame.font.SysFont(None, 25)
smallfont = pygame.font.SysFont("comicsansms",25)
def showLives(lives):
text = smallfont.render("Lives: "+str(lives), True, white)
screen.blit(text, [0,0])
def message_to_screen(msg,color):
screen_text = font.render(msg, True, color)
screen.blit(screen_text, [100,250])
clock = pygame.time.Clock()
def gameLoop():
gameExit = False
gameOver = False
x = 250
y = 425
x_change = 0
y_change = 0
obj_speed = 5
obj_y = 0
obj_x = 0
obj2_y = 0
obj2_x = 0
obj2_speed = 3
lives = 3
while not gameExit:
while gameOver == True:
screen.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:
x_change = -block_size
y_change = 0
elif event.key == pygame.K_RIGHT:
x_change = block_size
y_change = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
x_change = 0
y_change = 0
if x > 500-block_size:
x-=block_size
if x < 0+block_size:
x+=block_size
# if x >= display_width-block_size-block_size or x < 0:
# gameOver = True
obj_y = obj_y + obj_speed
if obj_y > display_height:
obj_x = random.randrange(0, display_width-block_size)
obj_y = -25
obj2_y = obj2_y + obj2_speed
if obj2_y > display_height:
obj2_x = random.randrange(1, display_width-block_size)
obj2_y = -27
x += x_change
y += y_change
screen.fill(black)
pygame.draw.rect(screen,white, [obj_x,obj_y,20,20])
pygame.draw.rect(screen,white, [obj2_x,obj2_y,20,20])
pygame.draw.rect(screen, red, [x,y,block_size,block_size])
showLives(lives)
pygame.display.update()
if x == obj_x and y == obj_y:
lives -= 1
if lives == 0:
gameOver = True
clock.tick(FPS)
pygame.quit()
quit()
gameLoop()
I want the program to detect when any part of the rectangles collide instead of just detecting when one point on each of the rectangles collide.
PyGame has class pygame.Rect() to keep rectangle's position and size. It uses it to draw images/sprites and check collision between sprites.
x = 250
y = 425
obj_y = 0
obj_x = 0
rect_1 = pygame.Rect(x, y, 10, 10)
rect_2 = pygame.Rect(obj_x, obj_y, 20, 20)
and then you can check collision
rect_1.colliderect(rect_2)
You can also use it to draw rectangle on screen
pygame.draw.rect(screen, white, rect_2)
pygame.draw.rect(screen, red, rect_1)
You can also use it to check collision between rectangle and point - ie. to check if button was clicked by mouse
button_rect.collidepoint(event.pos)
To change values in rectangle you have rect_1.x, rect_1.y, rect_1.width, rect_1.height but also
x,y
top, left, bottom, right
topleft, bottomleft, topright, bottomright
midtop, midleft, midbottom, midright
center, centerx, centery
size, width, height
w,h
Some of them takes tuple with (x, y)
for example: center rectangle on screen
rect_1.center = (display_width//2, display_height//2)
or event using screen
rect_1.center = screen.get_rect().center
OR center text on screen
screen_text_rect = screen_text.get_rect()
screen_text_rect.center = screen.get_rect().center
screen.blit(screen_text, screen_text_rect)
I'm attempting to detect a collision between two objects (both images).
I have rect's for both the objects, but cannot get the collision to be detected.
I've attempted to use rect's, comparing x and y positions.
import sys
import pygame
from pygame.locals import *
#init pygame
pygame.init()
window_width = 840
window_height = 650
size = (window_width, window_height)
screen = pygame.display.set_mode(size)
bg_img = pygame.image.load("img.png").convert_alpha()
crash = False
bot1x = 150
bot1y = 100
x = (window_width * 0.45)
y = (450)
clock = pygame.time.Clock()
fr = clock.tick(30)
x_speed = 0
car_img = pygame.image.load("car.png").convert_alpha()
car_img = pygame.transform.scale(car_img, (125, 175))
bot_img = pygame.image.load("bot.png").convert_alpha()
bot_img = pygame.transform.scale(bot_img, (175, 200))
def car(x, y):
screen.blit(car_img, (x,y))
def bot(x, y):
screen.blit(bot_img, (x,y))
car_rect = pygame.Rect(x, y, 125, 175)
bot_rect = pygame.Rect(bot1x, bot1y, 175, 200)
#game loop
while(crash==False):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == K_LEFT:
x_speed = -.9
print("Moving Left")
if event.key == K_RIGHT:
x_speed = .9
print("Moving Right")
if event.type == pygame.KEYUP:
if event.key == K_LEFT:
x_speed = 0
if event.key == K_RIGHT:
x_speed= 0
if event.type == pygame.QUIT:
crash = True
bot1y += .5
# Move car
x += x_speed
if car_rect.colliderect(bot_rect):
print("collision deceted")
#blit images to screen
screen.blit(bg_img, [0, 0])
#spawn car
car(x,y)
bot(bot1x, bot1y)
#flip game display
pygame.display.flip()
#end game
pygame.quit()
quit()
I expect the game to output "Collision detected" when the two objects touch eachother.
Thanks,
Lachlan
I am trying to move this rectangle to make Pong. I had it working before but I messed up the code.
Could anyone help me make it move and possibly make my code look cleaner?
Again, I made it move, but the problem seems to be in the Update method.
Possibly the ScreenSide parameter???...
import pygame, sys, random
from pygame.locals import *
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((800, 600))
rectImg1 = 'Rect.jpg'
rectImg2 = 'Rect2.jpg'
RIGHT = "RIGHT"
LEFT = "LEFT"
WHITE = (255,255,255)
FPS = 30
PADDLE_SPEED = 5
BALL_SPEED = 10
fpsClock = pygame.time.Clock()
xPos = 0
yPos = 0
leftY = 20
rightY = 20
class Paddle(pygame.sprite.Sprite):
def __init__(self, screenSide):
pygame.sprite.Sprite.__init__(self)
self.screenSide = screenSide
if self.screenSide == LEFT:
self.image = pygame.image.load(rectImg1).convert_alpha()
self.rect = self.image.get_rect()
self.rect.x = 20
self.rect.y = 20
def update(self):
if self.screenSide == LEFT:
self.y = leftY
allSpritesGroup = pygame.sprite.Group()
paddle = Paddle(LEFT)
allSpritesGroup.add(paddle)
#code to make it move
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if paddle.screenSide == LEFT:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
paddle.y += PADDLE_SPEED
elif event.key == pygame.K_w:
paddle.y -= PADDLE_SPEED
elif event.type == pygame.KEYUP:
if event.key == pygame.K_s or event.key == pygame.K_w:
paddle.y == 0
screen.fill((255,255,255))
allSpritesGroup.draw(screen)
allSpritesGroup.update()
pygame.display.flip()
fpsClock.tick(FPS)
pygame.quit()
Just a guess but your problem might be in:
elif event.type == pygame.KEYUP:
if event.key == pygame.K_s or event.key == pygame.K_w:
paddle.y == 0
This looks more like a comparison and if not then you're setting the y to 0 whenever you let go of a key.
Also, You're right about the update function:
def update(self):
if self.screenSide == LEFT:
self.y = leftY
You're constantly setting the y to 20 so it won't move since every time it updates its moved to 20.
Your event handling is broken. The KEYDOWN and KEYUP events are outside of the event loop because of this line if paddle.screenSide == LEFT:. You also need to update paddle.rect.y not paddle.y and you should do that in the class not with global variables. I'd give the paddles a self.y_speed attribute which you set in the event loop and then use it to update the self.rect.y position each frame in the update method. And remove the screenSide checks and just pass the image and position to the sprites during the instantiation.
import sys
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
screen_rect = screen.get_rect()
rectImg1 = pygame.Surface((30, 50))
rectImg1.fill((20, 20, 120))
rectImg2 = pygame.Surface((30, 50))
rectImg2.fill((120, 10, 20))
WHITE = (255,255,255)
FPS = 30
PADDLE_SPEED = 5
fpsClock = pygame.time.Clock()
class Paddle(pygame.sprite.Sprite):
def __init__(self, image, pos):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect(topleft=pos)
self.y_speed = 0
def update(self):
self.rect.y += self.y_speed
allSpritesGroup = pygame.sprite.Group()
paddle = Paddle(rectImg1, (20, 20))
paddle2 = Paddle(rectImg2, (750, 20))
allSpritesGroup.add(paddle, paddle2)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
paddle.y_speed = PADDLE_SPEED
elif event.key == pygame.K_w:
paddle.y_speed = -PADDLE_SPEED
elif event.type == pygame.KEYUP:
if event.key == pygame.K_s or event.key == pygame.K_w:
paddle.y_speed = 0
allSpritesGroup.update()
screen.fill(WHITE)
allSpritesGroup.draw(screen)
pygame.display.flip()
fpsClock.tick(FPS)
import pygame
pygame.init()
window = pygame.display.set_mode((800,600))
pygame.display.set_caption("TEST2")
black=(0,0,0)
white=(255,255,255)
moveX,moveY=0,0
clock = pygame.time.Clock()
class Sprite:
def __init__(self,x,y):
self.x=x
self.y=y
self.width=100
self.height=110
self.i100 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite0.PNG")
self.i1 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite1.PNG")
self.i2 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite2.PNG")
self.i3 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite3.PNG")
self.i4 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite4.PNG")
self.i5 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite5.PNG")
self.i6 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite6.PNG")
self.i7 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite7.PNG")
self.i8 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite8.PNG")
self.i9 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite9.PNG")
self.i10 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite10.PNG")
self.i11 = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite11.PNG")
self.timeTarget=10
self.timeNum=0
self.currentImage=0
def update(self):
self.timeNum+=1
if(self.timeNum==self.timeTarget):
if (self.currentImage==0):
self.currentImage+=1
else:
self.currentImage=0
self.timeNum=0
self.render()
def render(self):
if (self.currentImage==0):
window.blit(self.i100, (self.x,self.y))
else:
window.blit(self.i1, (self.x,self.y))
window.blit(self.i2, (self.x,self.y))
window.blit(self.i3, (self.x,self.y))
player=Sprite(110,100)
gameLoop = True
while gameLoop:
for event in pygame.event.get():
if event.type==pygame.QUIT:
gameLoop = False
if (event.type==pygame.KEYDOWN):
if (event.key==pygame.K_LEFT):
moveX = -3
if (event.key==pygame.K_RIGHT):
moveX = 3
if (event.key==pygame.K_UP):
moveY = -3
if (event.key==pygame.K_DOWN):
moveY = 3
if (event.type==pygame.KEYUP):
if (event.key==pygame.K_LEFT):
moveX=0
if (event.key==pygame.K_RIGHT):
moveX=0
if (event.key==pygame.K_UP):
moveY=0
if (event.key==pygame.K_DOWN):
moveY=0
window.fill(black)
player.x+=moveX
player.x+=moveY
player.update()
clock.tick(50)
pygame.display.flip()
pygame.quit()
What im doing is trying to animate 11 photos into an animation with pygame. this code works but when I run it the pictures seem to almost overlap. I did window.blit for the first few images and put them under else? I feel like I rendered them wrong. also I must add im really bad at picking up what people are trying to say and best learn from examples. Thanks!
BTW: your code could look like this:
I use my images in example but there are still lines with your images.
I use timer to change images.
You can press space to pause and escape to exit.
etc.
import pygame
#----------------------------------------------------------------------
class Sprite:
def __init__(self, x, y, curren_time):
self.rect = pygame.Rect(x, y, 100, 110)
self.images = []
#for x in range(12):
for x in range(1,4):
img = pygame.image.load("ball" + str(x) +".png")
#img = pygame.image.load("C:/Users/Trevor/SkyDrive/Documents/TEST2.0/Sprite" + str(x) +".PNG")
self.images.append( img )
self.current_image = 0
self.time_num = 100 # miliseconds
self.time_target = curren_time + self.time_num
def update(self, curren_time):
if curren_time >= self.time_target:
self.time_target = curren_time + self.time_num
self.current_image += 1
if self.current_image == len(self.images):
self.current_image = 0
def render(self, window):
window.blit(self.images[self.current_image], self.rect)
#----------------------------------------------------------------------
# CONSTANS - uppercase
BLACK = (0 ,0 ,0 )
WHITE = (255,255,255)
#----------------------------------------------------------------------
# MAIN
def main():
pygame.init()
window = pygame.display.set_mode((800,600))
pygame.display.set_caption("TEST2")
move_x, move_y = 0, 0
clock = pygame.time.Clock()
curren_time = pygame.time.get_ticks()
player = Sprite(110,100, curren_time)
font = pygame.font.SysFont(None, 150)
pause_text = font.render("PAUSE", 1, WHITE)
pause_rect = pause_text.get_rect( center = window.get_rect().center ) # center text on screen
# mainloop
state_game = True
state_pause = False
while state_game:
curren_time = pygame.time.get_ticks()
# events
for event in pygame.event.get():
if event.type == pygame.QUIT:
state_game = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state_game = False
elif event.key == pygame.K_SPACE:
state_pause = not state_pause
if event.key == pygame.K_LEFT:
move_x = -3
elif event.key == pygame.K_RIGHT:
move_x = 3
elif event.key == pygame.K_UP:
move_y = -3
elif event.key == pygame.K_DOWN:
move_y = 3
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_LEFT, pygame.K_RIGHT):
move_x = 0
elif event.key in (pygame.K_UP, pygame.K_DOWN):
move_y = 0
# moves
if not state_pause:
player.rect.x += move_x
player.rect.y += move_y
player.update(curren_time)
# draws
window.fill(BLACK)
player.render(window)
if state_pause:
window.blit(pause_text, pause_rect)
pygame.display.flip()
# FPS
clock.tick(50)
# the end
pygame.quit()
#----------------------------------------------------------------------
if __name__ == '__main__':
main()
ball1.png
ball2.png
ball3.png
By putting all those window.blit(...) calls one after another, you are drawing those three frames on top of each other. Even if your computer lagged for a second between each call, you still wouldn't see them individually because they all can't appear until pygame.display.flip() is called.
You should store the images in a list, and keep a counter like currentFrame that loops from 0 to number_of_frames-1 (or len(frames)-1). Then each frame of the game you do something like this:
class Player:
...
def draw(window):
window.blit(self.frames[self.currentFrame])