How do I make a certain sprite move in pygame? - python

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!

Related

Problem with flipping images in Pygame (python)

I am trying to create a game in which you can move a character with arrow keys. When moving left or right, I want the character (an image) to flip and point left/right accordingly. The original image/character is pointing left. But I cannot get the character to flip, please help me, thanks.
import pygame
pygame.init()#initiate pygame
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
display_width = 1200
display_height = 800
display = pygame.display.set_mode((display_width,display_height))
characterimg = pygame.image.load(r'/Users/ye57324/Desktop/Make/coding/python/characterimg.png')
def soldier(x,y):
display.blit(characterimg, (x,y))
x = (display_width * 0.45)
y = (display_height * 0.1)
pygame.display.set_caption('Game')
clock = pygame.time.Clock()#game clock
flip_right = False
x_change = 0
y_change = 0
start = True
while start:
for event in pygame.event.get():
if event.type == pygame.QUIT:
start = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change += -5
if flip_right == True:
pygame.transform.flip(characterimg, True, False)
flip_right = False
elif event.key == pygame.K_RIGHT:
x_change += 5
if flip_right == False:
pygame.transform.flip(characterimg, True, False)
flip_right = True
elif event.key == pygame.K_UP:
y_change += -5
elif event.key == pygame.K_DOWN:
y_change += 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x_change += 5
elif event.key == pygame.K_RIGHT:
x_change += -5
elif event.key == pygame.K_UP:
y_change += 5
elif event.key == pygame.K_DOWN:
y_change += -5
x += x_change
y += y_change
display.fill(white)
soldier(x,y)
pygame.display.update()
clock.tick(60)#fps
Pygame's doc-page about pygame.transform.flip states
Flipping a Surface is non-destructive and returns a new Surface with the same dimensions.
This means that the surface you pass to that method remains unaffected. You have to keep the return-value around in order to see any effect.
In practice, this means that you should replace
pygame.transform.flip(characterimg, True, False)
with
characterimg = pygame.transform.flip(characterimg, True, False)
So that characterimg point to the new, flipped version of the image.
Note: Performance wise, this is not a very good method of doing things. Each time you call pygame.transform.flip, pygame has to allocated new memory for the new surface, go over each pixel of the original surface and copy it over to the new surface, transforming its position in the process. You'd better flip the image once at the beginning of your program, so that you have a variable characterimg_left and characterimg_right and then just assign those to your characterimg variable.

I am trying to shoot multiple of bullets using pygame group module but I don't know how to do it properly

Problem 1: I am trying to shoot maximum of 5 bullets using pygame group class module but I can only shoot maximum of 1 bullet...
This is the bullet class:
class Bullets(pygame.sprite.Sprite):
def __init__(self,image,location):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect=self.image.get_rect()
self.location =location
self.rect.left,self.rect.top = self.location
Down below: I have set 'bullet' as a sprite
def bullet_group(group):
for bullet in group:
print(group.sprites)
group.remove(bullet)
# After shooting a bullet, I want to remove the bullet from the group
# in order to change the 'shoot_point'(which is the location of the bullet)
# back to where it starts
shoot_point_x = fixed_shoot_point_x #fixed_shoot_point is the start location
shoot_point_y = fixed_shoot_point_y #of the bullet
group.add(bullet)
Just before the main while loop:
group=pygame.sprite.Group()
for i in range(0,5):
group.add(bullet)
I made 5 bullet sprites
In the main code down below:
if event.type == pygame.KEYDOWN:
if #some code
elif event.key == pygame.K_SPACE:
fixed_bullet_speed_change = [round(-(math.cos(math.atan2(RealTank.Trect.centery-shoot_point_y,RealTank.Trect.centerx-shoot_point_x))),1)*10,round(-(math.sin(math.atan2(RealTank.Trect.centery-shoot_point_y,RealTank.Trect.centerx-shoot_point_x))),1)*10]
# the line of code above is just some calculations that is not related to the question
group.remove(bullet)
# I removed the sprite from the group after shooting some bullets, in order to
# shoot another one
if event.type == pygame.KEYUP:
if #some code
elif event.key == pygame.K_SPACE:
group.add(bullet)
# adding back another one
Does anyone know what I am doing wrong????
Problem 2:
When I do 'print(group.sprites)' and press 'SPACEBAR', I get more sprites every time I press it...
==================================================================
Here's all of my code down below:(you don't need to see it...it isn't necessary)
Try the code down below, to visualize my problem
pictures:
import pygame,math
pygame.init()
red = (155,0,0)
class Tanks(pygame.sprite.Sprite):
def __init__(self,image,location,angle,speed,x_change,y_change,
turret_image,turret_angle,bullet_image):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image)
self.turret_image = pygame.image.load(turret_image)
self.bullet_image = pygame.image.load(bullet_image)
self.Brect = self.bullet_image.get_rect()
self.Trect = self.turret_image.get_rect()
self.rect = self.image.get_rect()
self.rect.left,self.rect.top=location
self.Trect.centerx,self.Trect.bottom = self.rect.centerx,self.rect.centery
self.angle = angle
self.turret_angle = turret_angle
self.speed = speed
self.x_change = x_change
self.y_change = y_change
print(self.angle)
def rotate(self):
rot_image = pygame.transform.rotate(self.image,self.angle)
rot_rect = rot_image.get_rect(center = self.rect.center)
return rot_image,rot_rect
def turret_rotate(self):
turret_rot_image = pygame.transform.rotate(self.turret_image,self.turret_angle)
turret_rot_rect = turret_rot_image.get_rect(center = self.Trect.midbottom)
return turret_rot_image,turret_rot_rect
## def bullet_rotate(self):
## bullet_rot_image = pygame.transform.rotate(self.bullet_image,self.turret_angle)
## bullet_rot_rect = bullet_rot_image.get_rect(center = )
def moving_after_angle_change(self):
x=round(math.cos(math.radians(self.angle+90)),1)*self.speed
y=round(math.sin(math.radians(self.angle-90)),1)*self.speed
return x,y
def shoot_point(self):
#print(self.turret_angle)
shoot_point_x = RealTank.Trect.centerx + math.cos(math.radians(RealTank.turret_angle+90))*55
shoot_point_y = RealTank.Trect.centery + math.sin(math.radians(RealTank.turret_angle-90))*55
return shoot_point_x,shoot_point_y
class Bullets(pygame.sprite.Sprite):
def __init__(self,image,location):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect=self.image.get_rect()
self.location =location
self.rect.left,self.rect.top = self.location
def bullet_group(group):
for bullet in group:
print(group.sprites)
group.remove(bullet)
shoot_point_x = fixed_shoot_point_x
shoot_point_y = fixed_shoot_point_y
group.add(bullet)
#initial
player_image_str = 'Tank.png'
player_turret_str = 'turret - Copy.png'
player_gold_bullet_str = 'bullet.png'
clock = pygame.time.Clock()
FPS = 30
display_width,display_height = 900,600
screen = pygame.display.set_mode([display_width,display_height])
player_location = [600,300]
player_angle = 0
player_angle_change = 0
player_speed = 0
player_x_change=0
player_y_change=0
RealTank_x_change_store=0
RealTank_y_change_store=0
turret_angle = 0
turret_angle_change = 0
bullet_speed_change = [0,0]
fixed_bullet_speed = [0,0]
fixed_bullet_speed_change = [0,0]
shoot_point_x = 0
shoot_point_y=0
fixed_shoot_point_x=0
fixed_shoot_point_y=0
#main
RealTank = Tanks(player_image_str,player_location,player_angle,player_speed,
player_x_change,player_y_change,player_turret_str,turret_angle,player_gold_bullet_str)
bullet=Bullets(RealTank.bullet_image,[shoot_point_x,shoot_point_y])
group=pygame.sprite.Group()
for i in range(0,5):
group.add(bullet)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
turret_angle_change = 5
elif event.key == pygame.K_d:
turret_angle_change = -5
elif event.key == pygame.K_UP:
player_speed=2
elif event.key == pygame.K_DOWN:
player_speed=-2
elif event.key == pygame.K_LEFT:
player_angle_change = 2
elif event.key == pygame.K_RIGHT:
player_angle_change = -2
elif event.key == pygame.K_SPACE:
fixed_bullet_speed_change = [round(-(math.cos(math.atan2(RealTank.Trect.centery-shoot_point_y,RealTank.Trect.centerx-shoot_point_x))),1)*10,round(-(math.sin(math.atan2(RealTank.Trect.centery-shoot_point_y,RealTank.Trect.centerx-shoot_point_x))),1)*10]
group.remove(bullet)
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
turret_angle_change = 0
elif event.key == pygame.K_UP:
player_speed = 0
elif event.key == pygame.K_DOWN:
player_speed = 0
elif event.key == pygame.K_LEFT:
player_angle_change = 0
elif event.key == pygame.K_RIGHT:
player_angle_change = 0
elif event.key == pygame.K_SPACE:
group.add(bullet)
player_angle+=player_angle_change
turret_angle+=turret_angle_change
RealTank = Tanks(player_image_str,player_location,player_angle,player_speed,
player_x_change,player_y_change,player_turret_str,turret_angle,player_gold_bullet_str)
RealTank.image,RealTank.rect=RealTank.rotate()
RealTank.turret_image,RealTank.Trect = RealTank.turret_rotate()
RealTank.x_change,RealTank.y_change=RealTank.moving_after_angle_change()
RealTank_x_change_store += RealTank.x_change
RealTank_y_change_store += RealTank.y_change
RealTank.Trect.centerx +=RealTank_x_change_store
RealTank.Trect.centery +=RealTank_y_change_store
RealTank.rect.centerx += RealTank_x_change_store
RealTank.rect.centery += RealTank_y_change_store
shoot_point_x,shoot_point_y=RealTank.shoot_point()
fixed_shoot_point_x,fixed_shoot_point_y = RealTank.shoot_point()
screen.fill([0,0,0])
screen.blit(RealTank.image,RealTank.rect)
#bullet
print(fixed_bullet_speed_change)
fixed_bullet_speed[0]+=fixed_bullet_speed_change[0]
fixed_bullet_speed[1]+=fixed_bullet_speed_change[1]
shoot_point_x+=fixed_bullet_speed[0]
shoot_point_y+=fixed_bullet_speed[1]
#bullet end
bullet=Bullets(RealTank.bullet_image,[shoot_point_x,shoot_point_y])
#bullet group
bullet_group(group)
#bullet group end
screen.blit(bullet.image,bullet.location)
screen.blit(RealTank.turret_image,RealTank.Trect)
pygame.display.update()
clock.tick(FPS)
pygame.quit()
You create only one instance of bullet - you need 5 instances
group = pygame.sprite.Group()
for i in range(5):
bullet = Bullets(RealTank.bullet_image, [shoot_point_x, shoot_point_y])
group.add(bullet)
Doc: pygame.sprite.Group.add():
Add any number of Sprites to this Group. This will only add Sprites
that are not already members of the Group.
Inside while loop you create new bullet bullet = Bullets() (variable name bullet doesn't matter, id(bullet) do matter) and you try to remove it (remove(bullet)) but this instance is not in group so it removes nothing. And later you add bullet (add(bullet)) and it adds it because this instance is not in group yet.

Pygame not checking keyevents after another happens

I am moving a sprite on the x-axis. It is properly moving left and right. When I press both LEFT and RIGHT at the same time it stop moving properly.
I am trying to make it when a user presses both keys and then lets go of one, for it to continue moving in the direction still pressed.
Weirdly it works while I holding right and letting go of left. It continues moving right.
When I hold left and tap right it stops moving until I press right again.
I commented out some ideas I had to make this work, but they failed me.
I am sure its a simple fix or a logic failure on my part.
I have worked a couple hours on this.
Thanks for responses ahead of time.
import pygame
import time
import random
import sys
import math
pygame.init()
displayWidth = 1200
displayHeight = 800
white = (255,255,255)
black = (0,0,0)
gameDisplay = pygame.display.set_mode((displayWidth, displayHeight))
pygame.display.set_caption('Game 3')
clock = pygame.time.Clock()
class firstSquare:
def __init__(self,player_x,player_y):
self.x = player_x
self.y = player_y
self.width = 100
self.height = 100
def render(self):
pygame.draw.rect(gameDisplay, white,(self.x, self.y, self.width, self.height))
class secondSquare:
def __init__(self,cpu_x,cpu_y):
self.x = cpu_x
self.y = cpu_y
self.width = 100
self.height = 100
def render(self):
pygame.draw.rect(gameDisplay, white,(self.x, self.y, self.width, self.height))
player = firstSquare(300,300)
cpu = secondSquare(100,100)
def gameLoop():
### variables##
player_x = 100
player_y = 100
x = 100
y = 100
movement_x = 0
movement_y = 0
frame_rate = 0
frame_table = 0
inGame = True
while inGame:
for event in pygame.event.get():
if event.type == pygame.QUIT:
inGame = False
pygame.quit()
sys.exit()
keyPressed= pygame.key.get_pressed()
#### this is moving the player on x-axis##
if keyPressed[pygame.K_LEFT]:
movement_x = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
movement_x = 0
if keyPressed[pygame.K_RIGHT]:
movement_x = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
movement_x = 0
### two keys at once won't move the player###
if keyPressed[pygame.K_LEFT] and keyPressed[pygame.K_RIGHT]:
movement_x = 0
### pressing one key and letting go the other will continue movement
## if keyPressed[pygame.K_LEFT] and keyPressed[pygame.K_RIGHT]:
## if event.type == pygame.KEYUP:
## if event.key == pygame.K_LEFT:
## movement_x = 5
## print("left dropped")
## if keyPressed[pygame.K_RIGHT] and keyPressed[pygame.K_LEFT]:
## if event.type == pygame.KEYUP:
## if event.key == pygame.K_RIGHT:
## movement_x = -5
## print("Right dropped")
gameDisplay.fill(black)
player.render()
cpu.render()
player.x += movement_x
pygame.display.update()
clock.tick(60)
gameLoop()
pygame.quit()
quit()
I think what you need is this:
if keyPressed[pygame.K_LEFT]:
movement_x = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and movement_x < 0:
movement_x = 0
if keyPressed[pygame.K_RIGHT]:
movement_x = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT and movement_x > 0:
movement_x = 0
And that would be it... Hope it helps.
Try to use the following code in your movement:
if keyPressed[pygame.K_LEFT]:
movement_x = -5
elif keyPressed[pygame.K_RIGHT]:
movement_x = +5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
movement_x = 0
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
movement_x = 0

Having Trouble with Python Classes

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.

How to create a border in Pygame

I would like to know how to create a border in Pygame to stop the user controlled object from exiting the screen. Right now, I only have it so python prints some text when the user controlled object has come near one of the 4 sides.
Here is my code so far.
import pygame
from pygame.locals import *
pygame.init()
#Display Stuff
screenx = 1000
screeny = 900
screen = pygame.display.set_mode((screenx,screeny))
pygame.display.set_caption('Block Runner')
clock = pygame.time.Clock()
image = pygame.image.load('square.png')
#Color Stuff
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
white = (255,255,255)
black = (0,0,0)
#Variables
x_blocky = 50
y_blocky = 750
blocky_y_move = 0
blocky_x_move = 0
#Animations
def Blocky(x_blocky, y_blocky, image):
screen.blit(image,(x_blocky,y_blocky))
#Game Loop
game_over = False
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
blocky_y_move = -3
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
blocky_y_move = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
blocky_y_move = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
blocky_y_move = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
blocky_x_move = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
blocky_x_move = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
blocky_x_move = -3
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
blocky_x_move = 0
if x_blocky > 870 or x_blocky < 0:
print(' X Border')
if y_blocky > 750 or y_blocky < 2:
print(' Y Border')
y_blocky += blocky_y_move
x_blocky += blocky_x_move
screen.fill(white)
Blocky(x_blocky, y_blocky, image)
pygame.display.update()
clock.tick(60)
Don't use integers to store your position. Use a Rect.
So instead of
x_blocky = 50
y_blocky = 750
use
blocky_pos = pygame.rect.Rect(50, 750)
Now you can simply use
blocky_pos.move_ip(blocky_x_move, blocky_y_move)
to move your object.
After moving, you can simply call clamp/clamp_ip to ensure the blocky_pos Rect is always inside the screen.
blocky_pos.clamp_ip(screen.get_rect())
Also, you don't need to define basic colors yourself, you could simply use pygame.color.Color('Red') for example.
I also suggest you use pygame.key.get_pressed() to get all pressed keys to see how to move your object instead of creating 1000 lines of event handling code.
Well, simply don't increase your move variable any further, if you detect that the user object is near or at the border. Or reverse the move direction, depending on your general intent.
if x_blocky > 870 or x_blocky < 0:
print(' X Border')
blocky_x_move = 0
if y_blocky > 750 or y_blocky < 2:
print(' Y Border')
blocky_y_move = 0
Also, you have some redundant code with your keyboard movement. Instead of writing
if event.type == KEYDOWN:
over and over again, group the KEYUP if statements and KEYDOWN if statements.
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
blocky_y_move = -3
elif event.key == pygame.K_DOWN:
blocky_y_move = +3
etc, and:
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
blocky_y_move = 0
elif event.type == pygame.K_DOWN:
blocky_y_move = 0
etc
You can set the boundaries using the min and max functions.
Here is the concept:
We have a pygame object that moves in all four directions; lets say the user holds down the LEFT arrow key, so that the object reaches the top of the screen. The y-coordinate of the top of the screen will always be 0, so we want the object to come to a stop at y-coordinate 0.
This may seem as simple as:
if char.rect.y > 0:
char.rect.y -= char.speed
But this will result in a bug ig char.speed is greater than 1. Like when the object is at y-coordinate 5,
and its speed is 10; the condition still allows for one more step for the object, resulting in the object
coming 5 pixels out of the pygame window. What we want to do is more like:
if char.rect.y > 0:
char.rect.y -= char.speed
if char.rect.y < 0:
char.rect.y = 0
to push the object back into the boundaries. The above block of code can be simplified with the max function:
self.rect.y = max([self.rect.y - self.speed, 0])
For the object moving down:
if char.rect.y < HEIGHT - char.height:
char.rect.y += char.speed
if char.rect.y > HEIGHT - char.height:
char.rect.y = HEIGHT - char.height
or, the more efficient and clean method:
self.rect.y = min([self.rect.y + self.speed, HEIGHT - self.height])
For going left and right, simply replace the ys and height (and HEIGHT) from two lines above with xs and widths (and WIDTH).
All together:
import pygame
pygame.init()
WIDTH = 600
HEIGHT = 600
wn = pygame.display.set_mode((WIDTH, HEIGHT))
class Player:
def __init__(self):
self.speed = 1
self.width = 20
self.height = 20
self.color = (255, 255, 0)
self.rect = pygame.Rect((WIDTH - self.width) / 2, (HEIGHT - self.height) / 2, 20, 20)
def up(self):
self.rect.y = max([self.rect.y - self.speed, 0])
def down(self):
self.rect.y = min([self.rect.y + self.speed, HEIGHT - self.height])
def left(self):
self.rect.x = max([self.rect.x - self.speed, 0])
def right(self):
self.rect.x = min([self.rect.x + self.speed, WIDTH - self.width])
def draw(self):
pygame.draw.rect(wn, self.color, self.rect)
char = Player()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
char.up()
if keys[pygame.K_DOWN]:
char.down()
if keys[pygame.K_LEFT]:
char.left()
if keys[pygame.K_RIGHT]:
char.right()
wn.fill((0, 0, 0))
char.draw()
pygame.display.update()
Good luck!

Categories