I have used pygame for a while now, but now the player rect isn't updating or noticing collisions. It is still moving though. This just happened after I modified a bit of code. I have looked at the .draw functions and the walls and the border is being drawn, but the player isn't, and the screen is being updated. (The code snippet is in javascript because I still don't know how to use a code snippet in python.)
import pygame, sys, random
from pygame.locals import *
from time import sleep
pygame.init()
def render():
windowSurface.fill(black)
pygame.draw.rect(windowSurface,white,player1)
if level == 1:
pygame.draw.rect(windowSurface,white,wall_lvl_1_1)
pygame.draw.rect(windowSurface,white,wall_lvl_1_2)
pygame.draw.rect(windowSurface,white,border1_lvl_1)
elif level == 2:
filler = 'done'
pygame.display.update()
black = (0,0,0)
white = (255,255,255)
windowSurface = pygame.display.set_mode((500, 500),0,32)
windowSurface.fill(black)
level = 1
xmod = 0
ymod = 0
direction = 'none'
player1 = pygame.Rect(225 + xmod,450 - ymod,30,30)
wall_lvl_1_1 = pygame.Rect(0,225,250,50)
wall_lvl_1_2 = pygame.Rect(300,250,200,50)
border1_lvl_1 = pygame.Rect(0,0,25,500)
border2_lvl_1 = pygame.Rect(0,0,500,25)
border3_lvl_1 = pygame.Rect(0,0,1,1)
pygame.draw.rect(windowSurface,white,wall_lvl_1_1)
render()
while True:
render()
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_LEFT:
direction = 'left'
if event.key == K_RIGHT:
direction = 'right'
if event.key == K_UP:
direction = 'up'
if event.key == K_DOWN:
direction = 'down'
if event.type == QUIT:
pygame.quit()
sys.exit()
if player1.colliderect(wall_lvl_1_1) or player1.colliderect(wall_lvl_1_2):
xmod = 0
ymod = 0
player1 = pygame.Rect(225 + xmod,450 - ymod,30,30)
print('again')
if direction == 'left':
xmod -= 1
sleep(0.004)
if direction == 'right':
xmod += 1
sleep(0.004)
if direction == 'up':
ymod += 1
sleep(0.004)
if direction == 'down':
ymod -= 1
sleep(0.004)
if ymod == 450:
level = 2
render()
You need to update the position of the player1 rect each frame.
player1.topleft = (xmod, ymod)
Related
For a school project I am building a recreation of Among Us in python with Pygame. I have already set up all the server and client side code and that's all working fine. I'm now in the process of making the camera follow the player. Only I can't get it to work.
My idea was: when a player moves, everything in his surroundings has to move in the opposite direction. But when you have a multiplayer game this doesn't work. Because then the other player moves as well which breaks the system.
If anyone has any idea how to make such a code, please let me know.
Thank you in advance
You don't have to move the background and object rects around the player, you can just move the player around and have a scroll offset value that keeps track of how much the blitted objects have to be offset. You don't apply the scroll value to the rect position because the rect position isn't relative to the window like the blit objects are. Here is an example of how you could achieve this.
import pygame, sys
clock = pygame.time.Clock()
from pygame.locals import *
pygame.init()
pygame.display.set_caption("Scrolling example")
WINDOW_SIZE = (600, 400)
screen = pygame.display.set_mode(WINDOW_SIZE, 0, 32)
scroll = [0, 0]
player = pygame.Rect(100, 100, 10, 10)
up = False
down = False
left = False
right = False
blocks = [pygame.Rect(250,250,50,50)]
while True:
screen.fill((0, 0, 0))
scroll[0] += (player.x - scroll[0] - (WINDOW_SIZE[0]/2)) // 20
scroll[1] += (player.y - scroll[1] - (WINDOW_SIZE[1]/2)) // 20
player_movement = [0, 0]
if right == True:
player_movement[0] += 2
if left == True:
player_movement[0] -= 2
if up == True:
player_movement[1] -= 2
if down == True:
player_movement[1] += 2
player.x += player_movement[0]
player.y += player_movement[1]
player_scroll_rect = player.copy()
player_scroll_rect.x -= scroll[0]
player_scroll_rect.y -= scroll[1]
pygame.draw.rect(screen, (255,255,255), player_scroll_rect)
for block in blocks:
scroll_block = block.copy()
scroll_block.x = scroll_block.x - scroll[0]
scroll_block.y = scroll_block.y - scroll[1]
pygame.draw.rect(screen, (0,0,255), scroll_block)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_RIGHT:
right = True
if event.key == K_LEFT:
left = True
if event.key == K_UP:
up = True
if event.key == K_DOWN:
down = True
if event.type == KEYUP:
if event.key == K_RIGHT:
right = False
if event.key == K_LEFT:
left = False
if event.key == K_UP:
up = False
if event.key == K_DOWN:
down = False
pygame.display.update()
clock.tick(60)
If you want a solution for using images, ask me.
Also, you can find more about scrolling here: https://www.youtube.com/watch?v=5q7tmIlXROg
Before this I used the code to say 'every button press it moves' but now I have changed it to 'when you press the button it moves in one direction until further instructions', but now the colliderect doesn't work. It worked before, and I'm still new to pygame. I have found a few similar issues but I think I've done what the people asking the questions have done. Any help at all is accepted.
import pygame, sys, random
from pygame.locals import *
from time import sleep
pygame.init()
def render():
windowSurface.fill(black)
player = pygame.Rect(225 + xmod,450 - ymod,30,30)
pygame.draw.rect(windowSurface,white,player)
pygame.draw.rect(windowSurface,white,wall_1)
pygame.draw.rect(windowSurface,white,wall_2)
pygame.display.update()
black = (0,0,0)
white = (255,255,255)
windowSurface = pygame.display.set_mode((500, 500),0,32)
windowSurface.fill(black)
xmod = 0
ymod = 0
direction = 'none'
player = pygame.Rect(225 + xmod,450 - ymod,30,30)
wall_1 = pygame.Rect(0,225,250,50)
wall_2 = pygame.Rect(300,250,200,50)
render()
while True:
render()
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_LEFT:
direction = 'left'
if event.key == K_RIGHT:
direction = 'right'
if event.key == K_UP:
direction = 'up'
if event.key == K_DOWN:
direction = 'down'
if event.type == QUIT:
pygame.quit()
sys.exit()
if player.colliderect(wall_1) or player.colliderect(wall_2):
xmod = 0
ymod = 0
player = pygame.Rect(225 + xmod,450 - ymod,30,30)
render()
print('again')
if direction == 'left':
xmod -= 1
sleep(0.004)
if direction == 'right':
xmod += 1
sleep(0.004)
if direction == 'up':
ymod += 1
sleep(0.004)
if direction == 'down':
ymod -= 1
sleep(0.004)
You never update the global player variable, so it stays at its original coordinates. In the render function you create a new rect and assign it to a local player variable, but it is not the same as the global player which you use for the collision detection.
I suggest adding variables for the velocity speed_x, speed_y and adding them to the player.x and .y attributes every frame to move the rect directly.
The local player rect in the render function can be removed.
import sys
import pygame
from pygame.locals import *
pygame.init()
def render():
windowSurface.fill(black)
pygame.draw.rect(windowSurface, white, wall_1)
pygame.draw.rect(windowSurface, white, wall_2)
pygame.draw.rect(windowSurface, white, player)
pygame.display.update()
black = (0,0,0)
white = (255,255,255)
windowSurface = pygame.display.set_mode((500, 500),0,32)
clock = pygame.time.Clock() # A clock to limit the frame rate.
player = pygame.Rect(225, 450, 30, 30)
wall_1 = pygame.Rect(0,225,250,50)
wall_2 = pygame.Rect(300,250,200,50)
speed_x = 0
speed_y = 0
while True:
# Handle events.
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_LEFT:
speed_x = -5
speed_y = 0
elif event.key == K_RIGHT:
speed_x = 5
speed_y = 0
elif event.key == K_UP:
speed_y = -5
speed_x = 0
elif event.key == K_DOWN:
speed_y = 5
speed_x = 0
# Add the speed to the x and y attributes to move the rect.
player.x += speed_x
player.y += speed_y
# Game logic.
if player.colliderect(wall_1) or player.colliderect(wall_2):
player = pygame.Rect(225, 450, 30, 30)
print('again')
# Render everything.
render()
clock.tick(60) # Limit the frame rate to 60 FPS.
So I am making a simple "Dodge the Meteor Game" with Python 27 and Pygame. So everything ran smoothly, until I wanted to make classes, so I could make multiple meteors without retyping the same code. After I did this, when I run it, it stops responding with no error message. Here is my code:
import pygame
from pygame.locals import *
import sys
import random
pygame.init()
width,height = 800,600
gameDisplay = pygame.display.set_mode((width,height))
pygame.display.set_caption("Fifteen Minute Game ")
gameStart = False
bg = pygame.image.load("C:\Users\DEREK\Desktop\Python\\space.jpg")
bg = pygame.transform.scale(bg,(900,600))
x = 300
y = 300
move_x = 0
move_y = 0
playerspeed = 3
pellet_x = random.randint(0,800)
pellet_y = random.randint(0,550)
player = pygame.draw.rect( gameDisplay, (255,255,255), (x,y,30,30) )
pellet = pygame.draw.rect( gameDisplay, (255,255,255), (pellet_x,pellet_y,15,15) )
count = 0
#Functions
def pelletxy():
global pellet_x, pellet_y
pellet_x = random.randint(0,770)
pellet_y = random.randint(0,570)
def collision(rect1,rect2):
global player, count, pellet
if rect1.colliderect(rect2):
if rect2 == pellet:
pelletxy()
count +=1
class Meteor():
def __init__(self):
self.meteor_x = random.randint(0,800)
self.meteor_y = 0
self.meteorfall = 3
self.meteor = pygame.draw.rect( gameDisplay, (255,255,255), (self.meteor_x,self.meteor_y,35,35) )
def collision(self,rect1,rect2):
if rect1.colliderect(rect2):
if rect2 == self.meteor:
print "Good Game"
print "MUA HAHAHAHA"
print ""
print "Your score:" + str(count)
pygame.quit()
sys.exit()
def meteorxy(self):
self.meteor_x = random.randint(0,800)
self.meteor_y = 0
def render(self):
self.meteor_y += self.meteorfall
self.meteor
if meteor_y > 600:
meteorxy()
m1 = Meteor()
#Game Loop
while gameStart:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Keyboard Movement
if event.type == pygame.KEYDOWN:
if event.key == K_UP:
move_y -= playerspeed
if event.key == K_DOWN:
move_y += playerspeed
if event.key == K_LEFT:
move_x -= playerspeed
if event.key == K_RIGHT:
move_x += playerspeed
if event.type == pygame.KEYUP:
if event.key == K_UP:
move_y = 0
if event.key == K_DOWN:
move_y = 0
if event.key == K_LEFT:
move_x = 0
if event.key == K_RIGHT:
move_x = 0
#Calculate new position
x = x + move_x
y = y + move_y
#Stop Movement on boundaries
if x > 830:
x = -30
elif x < -30:
x = 830
elif y < -30:
y = 630
elif y > 630:
y = -30
#Check Different Collision Scenarios
collision(player, pellet)
m1.collision(player, m1.meteor)
#Draw the things onto the screen
gameDisplay.blit(bg,(0,0))
player = pygame.draw.rect( gameDisplay, (255,255,255), (x,y,30,30) )
pellet_outline = pygame.draw.rect( gameDisplay, (255,255,255), ((pellet_x - 1), (pellet_y - 1), 17,17))
pellet = pygame.draw.rect( gameDisplay, (0,0,255), (pellet_x,pellet_y,15,15) )
m1.render
pygame.display.update()
I don't know what I'm doing wrong, but I know it is with the classes. Thanks in advance
Hobby Programmer, Derek
Well, it's probably because gameStart is always False. So you're never getting into the game loop.
You should get to know debugging. You can use pdb or any IDE like Eclipse. The important thing is that it can help you understand what code is being running.
if event.key == K_RIGHT:
move_x = 0
#Calculate new position
x = x + move_x
y = y + move_y
See how the indentation changes? In Python, indentation is very important. Because all of your code after the line 'move_x = 0' is not indented adequately, it is not part of your while loop; therefore, it does not get executed in the loop. Fix your indentation.
I am having some issues with my code in python, I am making a version of snake, my issue concerns the movement of the snake itself. I have gotten the directions working fine, I just need to make it so that the snake continues moving in the direction it has been told to do so via the key press, I also need to make it so that it is the one block, currently it shows all previous blocks once it has been moved.
import pygame, sys, time, random
from pygame.locals import *
pygame.init()
size = width,height = 480, 480 #16x30,16x30
grey = (128,128,128)
screen = pygame.display.set_mode(size)
icon = pygame.image.load('snakeIcon.png')
newDir = 0
prevDir = 0
FPS = 8
xCoord = 10.0
yCoord = 10.0
#Main Program:
pygame.display.set_caption('Anthony\'s Snake')
pygame.display.set_icon(icon)
screen.fill(grey)
fpsTime = pygame.time.Clock()
gameB = pygame.image.load('gameB.png')
border = {}
createLvl()
snakeH = pygame.image.load('snakeH.png')
snake = {}
refreshScreen()
keyCheck = {'LEFT':bool(0), 'RIGHT':bool(0), 'UP':bool(0), 'DOWN':bool(0), 'ESC':bool(0)}
pygame.mixer.music.load('retroMusik.mp3')
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
while bool(1):
for i in range(1):
snake[str(len(snake))]=snakeH.get_rect()
x = xCoord
y = yCoord
for i in range(len(snake)):
snake[str(i)].x = x*16
snake[str(i)].y = y*16
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_UP :
keyCheck['UP'] = bool(1)
if event.key == K_DOWN :
keyCheck['DOWN'] = bool(1)
if event.key == K_LEFT :
keyCheck['LEFT'] = bool(1)
if event.key == K_RIGHT :
keyCheck['RIGHT'] = bool(1)
if event.key == K_ESCAPE :
keyCheck['ESC'] = bool(1)
if event.type == KEYUP:
if event.key == K_UP :
keyCheck['UP'] = bool(0)
elif event.key == K_DOWN :
keyCheck['DOWN'] = bool(0)
elif event.key == K_LEFT :
keyCheck['LEFT'] = bool(0)
elif event.key == K_RIGHT :
keyCheck['RIGHT'] = bool(0)
elif event.key == K_ESCAPE :
keyCheck['ESC'] = bool(0)
if keyCheck['UP']:
if prevDir != 'DOWN':
newDir = 'UP'
print('Direction changed to UP')
if keyCheck['DOWN']:
if prevDir != 'UP':
newDir = 'DOWN'
print('Direction changed to DOWN')
if keyCheck['LEFT']:
if prevDir != 'RIGHT':
newDir = 'LEFT'
print('Direction changed to LEFT')
if keyCheck['RIGHT']:
if prevDir != 'LEFT':
newDir = 'RIGHT'
print('Direction changed to RIGHT')
prevDir = newDir
if keyCheck['UP'] == bool(1):
yCoord -= 1
if keyCheck['DOWN'] == bool(1):
yCoord += 1
if keyCheck['LEFT'] == bool(1):
xCoord -= 1
if keyCheck['RIGHT'] == bool(1):
xCoord += 1
refreshScreen()
fpsTime.tick(FPS)
Please be soft on me, I am still new to this. Thank you in advance.
I think your animation doesn't work right because you don't erase (cover with background) the screen before drawing. See this Pygame tutorial for slow and detailed explanation.
Don't use bool(1). Use True and False.
I'm not sure but I think the problem with the snake not moving is either A) you reset your control/movement variable or B) you don't check it every "round"/frame.
I'd really recommend finding some tutorial (or something) and read some Python code by other people, your code could use a lot of improvement (this isn't bad, the important thing is trying to improve).
I need to make the player move continuously when I press a certain key.The problem that I have is that the image of the player is moving once (when I press one of the defined keys) and then it stops.
enter code here
import pygame
import sys
import os
import random
import time
from pygame.locals import *
pygame.init()
white = ( 255, 255, 255 )
black = ( 0, 0, 0 )
screenw = 800
screenh = 600
screen = pygame.display.set_mode( ( screenw, screenh ) )
pygame.display.set_caption( "Game" ) # Here I create a display.
clock = pygame.time.Clock()
class Car(pygame.sprite.Sprite): # Here I create a class.
def __init__( self, color = black, width = 100, height = 100 ):
pygame.sprite.Sprite.__init__( self )
self.image = pygame.Surface( ( width, height ) )
self.image.fill( color )
self.rect = self.image.get_rect()
def set_pos(self, x, y):
self.rect.x = x
self.rect.y = y
def set_img( self, filename = None):
if filename != None:
self.image = pygame.image.load( filename )
self.rect = self.image.get_rect()
def main():*I create a game loop
x_change = 0
y_change = 0
x = 0
y = 0
car_group = pygame.sprite.Group() # Make a group
player = Car()
player.set_img( "images.jpg" )
car_group.add( player )
exit = False
FPS = 60
while not exit:
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 = -10
elif event.key == pygame.K_RIGHT:
x_change = 10
elif event.key == pygame.K_UP:
y_change = -10
elif event.key == pygame.K_DOWN:
y_change = 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_UP or event.type == pygame.K_DOWN:
x_change = 0
y_change = 0
x += x_change
y += y_change
screen.fill( white )
player.set_pos( x, y ) # Blit the player to the screen
car_group.draw( screen )
clock.tick( FPS )
pygame.display.update()
main()
pygame.quit()
quit()
Well the problem is that you are only allowing the sprite to move once. For example, take this piece of your code:
if event.key == pygame.K_LEFT:
x_change = -10
This will allow the x position to be smaller by 10. Then it stops. You maybe want to make a update function. A variable will also be made to allow the function to be used or not to be used. Another one will be used to control the direction it goes. Here is the update function. Feel free to change it to be able to fit your needs:
def update():
global direction
if direction == 'LEFT':
x -= 10
elif direction == 'RIGHT':
x += 10
elif direction == 'UP'
y -= 10
elif direction == 'DOWN':
y += 10
Now we will need the variable to control whether the function will run or not. Add these two lines for our new two variables:
run = 0
direction = 'NONE'
They should be before the code for the class. You absolutely change the lines from your event.key lines, it should be (in proper indention):
if event.key == pygame.K_LEFT:
direction = 'LEFT'
run = 1
elif event.key == pygame.K_RIGHT:
direction = 'RIGHT'
run = 1
elif event.key == pygame.K_UP:
direction = 'UP'
run = 1
elif event.key == pygame.K_DOWN:
direction = 'DOWN'
run = 1
Of course, there must be something to stop the car from repeatedly moving infinitely right? Add these lines with the lines above:
elif event.key == pygame.K_SPACE:
direction = 'NONE'
run = 0
Now put these two lines in the while loop but before you for loop:
if run == 1:
Car.update()
else:
pass
This should work because as long run is equal to 1, the car will continue its movement in the given direction until stopped by pressing the spacebar. I hope this helps you!