character movement python (pygame) - python

Im trying to call moveleft method but there is no movement. i pass the distance of the character and this should be updated but its not. Any ideas?
import pygame, sys
from pygame.locals import *
pygame.init()
pygame.font.init()
width,height=(842,595)
window = pygame.display.set_mode((width,height),0,32)
pygame.display.set_caption("game!")
speedX=3
movingX =0
clock= pygame.time.Clock()
man = pygame.image.load("man.png")
target= pygame.image.load("target.png")
x = 100
y = height-300
def name(name=""):
myfont = pygame.font.SysFont(None, 15)
label = myfont.render(name, 1, (255,255,0))
result=window.blit(label, (100, 100))
pygame.display.update()
return name
def moveleft(distanceX):
movingX =0
speedX =0
x=0
while True:
pygame.display.update()
ticks=clock.tick(25)
time_passedSeconds=ticks/1000.0
distanceX = time_passeSeconds*speedX
movingX+=distanceX
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
elif event.type==KEYDOWN:
if event.key ==K_LEFT:
x+=distanceX
window.blit(man, (x,y))
return movingX
name("werodo!")
moveleft(5)
pygame.display.update()

You draw the character at (x, y). The only time you change x is here:
elif event.type==KEYDOWN:
if event.key ==K_LEFT:
x+=distanceX
What is distanceX? It changes every iteration of the loop:
distanceX = time_passeSeconds*speedX
Yet you only assign speedX once at the start of the function:
speedX = 0
So, you're always moving by 0. Change speedX to 50 and see what happens.

Related

Pygame: Is there a way of scrolling the 'coordinate system' of a white-filled display without setting a background image?

I have a game display on which I used the blit-function to display a flight path as well as a drone. The flight path starts from the right side and goes beyond the left side of the display.
The game display is filled white and what I want is to move my drone via pressed keys from right to left along the flight path (which is just a set of contiguous lines connecting random points).
I want the 'coordinate system' of my display to move/scroll so that you can see where the flight path ends. At the same time I want my drone to maintain a static position during that scrolling, e.g. stay in the middle of the screen while it follows the flight path.
Does anybody know a function that allows me to achieve that? All I found in forums and on YouTube seemed rather complex and required one to have set a background image first. I just want the white-filled screen to scroll while I move my drone to the left to follow the red flight path. Below is what I coded so far.
Thank you a lot in advance for any advice!
import pygame
import pygame.gfxdraw
import random
import sys
white = (255,255,255)
display_width = 1200
display_height = 700
game_screen = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('gameScreen')
the_drone = pygame.image.load('drone.png')
X=1000
Y=350
p1=[X, Y]
p2=[X, Y]
p3=[X, Y]
p4=[X, Y]
p5=[X, Y]
pointlist = [p1, p2, p3, p4, p5]
limit1=1000
limit2=850
for i in pointlist:
i[0] = random.randrange(limit2, limit1)
limit1-=300
limit2-=300
for i in pointlist:
if i == 0:
i[1] = random.randrange(200, 600)
else:
range = i[1]-1
i[1] = random.randrange(range-100, range+100)
def flightpath(pointlist):
pygame.draw.lines(game_screen, (255, 0, 0), False, pointlist, 3)
def drone(x,y):
game_screen.blit(the_drone,(X,Y))
def game_loop():
global X, Y
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
keys = pygame.key.get_pressed() #checking pressed keys
if keys[pygame.K_LEFT]:
X -= 0.5
if keys[pygame.K_DOWN]:
Y -= 0.5
if keys[pygame.K_UP]:
Y +=0.5
game_screen.fill(white)
flightpath(pointlist)
drone(X,Y)
pygame.display.update()
game_loop()
pygame.quit()
sys.exit()
Hi to be hones I don't really understand your Code but I got it working like that:
import pygame
import sys
import random
# init window
def init():
pygame.init()
pygame.display.set_caption("Drone Game")
screen = pygame.display.set_mode((500, 500))
return screen
# make closing the window possible
def escape():
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# draws all objects on screen
def draw(screen, f, y_pos):
screen.fill((50, 50, 50))
for y in range(20):
for x in range(5):
pygame.draw.rect(screen, f[y][x], (x * 100, (y * 100) - y_pos, 100, 100))
pygame.draw.rect(screen, (250, 0, 0), (240, 240, 20, 20)) # drone
pygame.display.update()
# creates background
def field():
f = []
for y in range(20):
f.append([])
for x in range(5):
f[y].append((random.randint(200, 255), random.randint(200, 255), random.randint(200, 255)))
return f
# combines all functions
def main(screen):
f = field()
y_pos = 500
while True:
pygame.time.Clock().tick(30)
escape()
y_pos -= 1
draw(screen, f, y_pos)
# starts program
if __name__ == '__main__':
main(init())
I hope it works for you. :)

Timing the blit of an enemy list in Pygame

Outside of my game loop, I have created a function that creates a list of 200 enemies with random coordinates. These enemies are suppose to start at the top of the screen and then drop down at random speeds. Inside the loop, I use a "for" loop to blit the enemies on screen. It works, but all 200 hundred are spawned and fall at the same time, albeit, at different speeds. So I know I need a timer and herein lies the problem; nothing I do works. Ive tried clock.tick(), pygame.delay(), import time and do the time.time() method. Everything either strobes or the system just crashes. What's causing the problem?
[Code]
import pygame
import sys
import random
import time
pygame.init()
#MAIN GAME
game_screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Beer Goggles")
bg = pygame.image.load("bg.png")
bg_image = pygame.transform.scale(bg, (600, 600))
class Object:
def __init__(self, image_path, width, height, x, y):
self.image_path = image_path
self.width = width
self.height = height
self.x = x
self.y = y
player = pygame.image.load(image_path)
self.player_main = pygame.transform.scale(player, (width,height))
def draw(self, background):
background.blit(self.player_main, (self.x, self.y))
#enemies
def enemy():
enemy_list = []
for e in range(200):
x_cor = random.randint(25, 361)
e = Object("enemy.png", 70, 70, x_cor, 25)
enemy_list.append(e)
return enemy_list
#Main Objects
player1 = Object("crate.png", 70, 70, 25, 500)
list1 = enemy()
#ladies
fat_lady = Object("fat_lady.png", 300, 300, 360, 180)
# Main Loop
direction = 0
game_on = True
while game_on:
clock = pygame.time.Clock()
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_on = False
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
direction = 1
elif event.key == pygame.K_LEFT:
direction = -1
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
direction = 0
game_screen.fill((0,0,0))
game_screen.blit(bg_image, (0,0))
#title.draw(game_screen)
player1.draw(game_screen)
fat_lady.draw(game_screen)
#move
if direction > 0:
player1.x = player1.x + 10
elif direction < 0:
player1.x = player1.x - 10
#boundaries
if player1.x <= 25:
player1.x = 25
elif player1.x >= 360:
player1.x = 360
#for enemy in list1:
for enemy in list1:
a = random.randint(1, 30)
enemy.draw(game_screen)
enemy.y += a
#collisions
#scoring
pygame.display.update()
quit()
In the code where you create the enemy list you could add a drop start time. Just like you create a random x co-ordinate you could create a time to start dropping it. Then later when you start changing the y position for them (dropping them), you would not start it dropping until after that time had passed.
By the way You have a method enemy() and later you have a loop iterator enemy which will override hide the method by that name. After that point if you tried to call the method enemy() it would fail and you would access the loop iterator instead. It does not affect your code here because you do not try to access the method after creating the loop iterator variable, but it is not a great idea and could cause problems if you later changed the code and did try to access that method. You should be careful about name choices.

"pygame.error: display Surface quit" when running the code

I am trying to make a simple moving game with Pygame since I am currently learning it. Whenever i try to run the code I keep on getting a problem saying: "pygame.error: display Surface quit"
I've tried adding "break" at the end but the window closes immediately! I've tried searching for the solution but I can't find one that helps my code.
import pygame
import random
pygame.init()
# Window setup
size = [400, 400]
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
# player position
x = size[0] // 2
y = size[1] // 2
# ball position
ballX = random.randrange(0, size[0])
ballY = random.randrange(0, size[1])
# colours
red = pygame.color.Color('#FF8080')
blue = pygame.color.Color('#8080FF')
white = pygame.color.Color('#FFFFFF')
black = pygame.color.Color('#000000')
def CheckOffScreenX(x):
if x > size[0]:
x = 0
elif x < 0:
x = size[0]
return x
def CheckOffScreenY(y):
if y > size[1]:
y = 0
elif y < 0:
y = size[1]
return y
# Game loop
done = False
while not done:
screen.fill(black)
keys = pygame.key.get_pressed()
#player movement
if keys[pygame.K_w]:
y -=1
if keys[pygame.K_s]:
y +=1
if keys[pygame.K_a]:
x -=1
if keys[pygame.K_d]:
x +=1
# Check offscreen
x = CheckOffScreenX(x)
y = CheckOffScreenY(y)
# draw player
pygame.draw.circle(screen, red, [x, y], 6)
pygame.display.flip()
# draw ball
pygame.draw.circle(screen, blue, [ballX, ballY], 6)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
clock.tick(32)
pygame.quit()
Any help would be appreciated!
The issue is the pygame.quit() insider the main loop. pygame.quit() uninitialize all pygame modules. After the modules are uninitialized all further calls to pygyme instructions (in the next frame) will cause a crash.
Do pygame.quit() after the main loop, when the application has end.
done = False
while not done:
screen.fill(black)
# [...]
# pygame.quit() <----- delete
pygame.quit() # <---- add
Note, probably you've added an Indentation when you copied the code.

Collide Images in Pygame

im trying to check if two images collide but im just getting back an error saying
"'pygame.Surface' object has no attribute 'colliderect'". The images are battery and playerPic and i did a define to see if they collide. It should return a black screen if they collide.
Note: i removed the drawScene from my code on here
#initialize pygame
from pygame import *
import os
import random
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" %(0, 0)
init()
#set screen size
size = width, height = 800, 600
screen = display.set_mode(size)
#set fonts
fontGame=font.SysFont("Times New Roman", 30)
fontBack=font.SysFont("Ariel", 30)
fontTitle=font.SysFont("Ariel", 100)
fontResearch=font.SysFont ("Times New Roman", 18)
#set button and page to 0
button = 0
page=0
#setting colours
BLACK = (0, 0, 0)
RED = (255,0,0)
GREEN = (0, 255, 0)
BLUE = (106,186,232)
#loading image
backgroundPic=image.load("Background.jpg")
backgroundGame=image.load("gameBackground.jpg")
backgroundGame=transform.scale(backgroundGame,(800,600))
battery=image.load("Battery.png")
battery=transform.scale(battery,(100,100))
backgroundx=0
playerPic=image.load("player.png")
playerPic=transform.scale(playerPic,(70,70))
batteryx=[]
#defining what is going to be shown on the screen
def drawScene(screen, button,page,locationx,locationy):
global batteryx
mx, my = mouse.get_pos() #will get where the mouse is
#if the user does nothing
if page==0:
draw.rect(screen, BLACK, (0,0, width, height))
screen.fill(BLACK)
rel_backgroundx= backgroundx % backgroundGame.get_rect().width
screen.blit(backgroundGame, (rel_backgroundx - backgroundGame.get_rect().width,0))
if rel_backgroundx < width:
screen.blit (backgroundGame, (rel_backgroundx,0))
screen.blit(playerPic,(locationx,locationy))
screen.blit(battery,(batteryx,420))
batteryx-=1
display.flip()
return page
def collision (battery, playerPic):
if battery.colliderect(playerPic):
return True
return False
running = True
myClock = time.Clock()
KEY_LEFT= False
KEY_RIGHT= False
KEY_UP= False
KEY_DOWN= False
locationx=0
jumping=False
accel=20
onGround= height-150
locationy=onGround
batteryx=random.randrange(50,width,10)
# Game Loop
while running:
button=0
print (KEY_LEFT, KEY_RIGHT)
for evnt in event.get(): # checks all events that happen
if evnt.type == QUIT:
running=False
if evnt.type == MOUSEBUTTONDOWN:
mx,my=evnt.pos
button = evnt.button
if evnt.type== KEYDOWN:
if evnt.key==K_LEFT:
KEY_LEFT= True
KEY_RIGHT= False
if evnt.key==K_RIGHT:
KEY_RIGHT= True
KEY_LEFT= False
if evnt.key==K_UP and jumping==False:
jumping=True
accel=20
if evnt.key== K_DOWN:
KEY_DOWN= True
KEY_UP= False
if evnt.type==KEYUP:
if evnt.key==K_LEFT:
KEY_LEFT= False
if evnt.key==K_RIGHT:
KEY_RIGHT= False
if evnt.key==K_DOWN:
KEY_DOWN=False
if KEY_LEFT== True:
locationx-=10
backgroundx+=10
if KEY_RIGHT== True:
locationx+=10
backgroundx-=10
if jumping==True:
locationy-=accel
accel-=1
if locationy>=onGround:
jumping=False
locationy=onGround
#player cannot move off screen
if locationx<0:
locationx=0
if locationx>400:
locationx=400
if collision(battery, playerPic)==True:
screen.fill(BLACK)
page=drawScene(screen,button,page,locationx,locationy)
myClock.tick(60) # waits long enough to have 60 fps
if page==6: #if last button is clicked program closes
running=False
quit()
Images/pygame.Surfaces can't be used for collision detection. You have to create pygame.Rect objects for the battery and the player and then use their colliderect method. You can use the get_rect method of the surfaces to get rects with their size and then update the positions of the rects every time you move the player or the battery.
# Create a rect with the size of the playerPic with
# the topleft coordinates (0, 0).
player_rect = playerPic.get_rect()
In the while loop:
# Adjust the position of the rect.
player_rect.x = locationx
player_rect.y = locationy
# You can also assign the location variables to the topleft attribute.
player_rect.topleft = (locationx, locationy)
# Then pass the battery_rect and player_rect to the collision function.
if collision(battery_rect, player_rect):
You can also shorten the collision function:
def collision(battery_rect, player_rect):
return battery_rect.colliderect(player_rect)
Or just call battery_rect.colliderect(player_rect) in the while loop.
Here's a minimal, complete example:
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')
player_image = pg.Surface((30, 50))
player_image.fill(pg.Color('dodgerblue1'))
battery_image = pg.Surface((30, 50))
battery_image.fill(pg.Color('sienna1'))
speed_x = 0
location_x = 100
# Define the rects.
# You can pass the topleft position to `get_rect` as well.
player_rect = player_image.get_rect(topleft=(location_x, 100))
battery_rect = battery_image.get_rect(topleft=(200, 100))
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_a:
speed_x = -4
elif event.key == pg.K_d:
speed_x = 4
# Update the location and the player_rect.
location_x += speed_x
player_rect.x = location_x
if player_rect.colliderect(battery_rect):
print('collision')
# Blit everything.
screen.fill(BG_COLOR)
screen.blit(player_image, player_rect)
screen.blit(battery_image, battery_rect)
pg.display.flip()
clock.tick(30)
pg.quit()

How do i get my game to resize with the window

Im wokring on my own version of Pacman and am currently trying to get the window to resize. i read an answer here :https://reformatcode.com/code/python/pygame-how-do-i-resize-a-surface-and-keep-all-objects-within-proportionate-to-the-new-window-size. but it didnt help me in my case. at the i have 2 screen, screen and fake screen. if i set everything to blit on fake screen they appear but dont update themselces (pacman wont move). if i set them to screen they appear and update but dont resize. any help or suggestions would be greatly appreciated. btw its still a work on progress
import pygame
from Variables import pelletspawns #imports pellet spwans list from different script
from pygame.locals import *
#Initialisation
pygame.init()
pygame.display.set_caption("Pacman")
myfont = pygame.font.SysFont("monospace", 15)
screen = pygame.display.set_mode((448, 576)) #Creates screen object
fake_screen = screen.copy()
pic = pygame.surface.Surface((50,50))
pic.fill((255,100,100))
clock = pygame.time.Clock() #Creates clock object
Fin = False
#Declaring Variables
FPS = 60
MoveLeft = pygame.K_LEFT
MoveRight = pygame.K_RIGHT
MoveUp = pygame.K_UP
MoveDown = pygame.K_DOWN
#Load images
PACMAN_MAP = pygame.image.load("images/pacman_map.png").convert_alpha()
PACMANSPRITE = pygame.image.load("images/pacman.png").convert_alpha()
#pacmans class
class SpriteClass(pygame.sprite.Sprite):
def __init__(self, image, x, y):
self.image = image
self.y=y
self.x=x
self.rect = self.image.get_rect()
self.rect.left = self.x
self.rect.top = self.y
self.rect.width=16
self.rect.height=16
#draws Pacman
def draw(self, surface):
# blit yourself at your current position
surface.blit(self.image, (self.x, self.y))
# move pacman
def movement(self):
pressed= pygame.key.get_pressed()
if pressed[MoveUp]:
self.y -= 2
print('key pressed')
if pressed[MoveDown]:
self.y += 2
print('key pressed')
if pressed[MoveLeft]:
self.x -= 2
print('key pressed')
if pressed[MoveRight]:
self.x += 2
print('key pressed')
self.rect.left = self.x
self.rect.top = self.y
print(self.x,self.y)
#instances Pacman
Pacman = SpriteClass(PACMANSPRITE, 216 ,416)
#Function to spawn pellets
def SpawnPellets(pelletspawns):
pelletx=0 #the temp x co-ordinate for the pellet to spawn
pellety= -8 #the temp y co-ordinate for the pellet to spawn (starts at -ve 0.5(gridscpare) for allignment
for row in pelletspawns:
#adds 1 grid space to correctly align spawns
pellety += 16
for pellet in row:
pelletx= 16*pellet
pelletx -=8
pygame.draw.circle(screen,(255, 204, 153), (pelletx, pellety) , 5)
#main game loop
while not Fin:
#For event is used to close the program
for event in pygame.event.get():
if event.type == QUIT:
pygame.display.quit()
if event.type == VIDEORESIZE:
screen = pygame.display.set_mode(event.dict['size'],RESIZABLE)
screen.blit(pygame.transform.scale(fake_screen, event.dict['size']), (0, 0))
pygame.display.flip()
#calls movement function
Pacman.movement()
#blits pacman map as background
screen.blit(PACMAN_MAP, (0, 0))
#draws pacman
Pacman.draw(screen)
#Spawns pellets
SpawnPellets(pelletspawns)
#draws screen
pygame.display.flip()
clock.tick(FPS)
I figured it out, i needed to move
screen.blit(pygame.transform.scale(fake_screen, event.dict['size']), (0, 0))
into the core game loop just above clock.tick. i tried this before but ran into a key error as there was no event for event.dict['size'] to get a size from, so i made a variable in the for event in pygame.event.get(): loop, and then passed that variable where it was asking for event.dict['size']. Here is the section of code i changed:
#main game loop
while not Fin:
#For event is used to close the program
for event in pygame.event.get():
if event.type == QUIT:
pygame.display.quit()
if event.type == VIDEORESIZE:
size = event.dict['size']
screen = pygame.display.set_mode(size,RESIZABLE)
#calls movement function
Pacman.movement()
#blits pacman map as background
fake_screen.blit(PACMAN_MAP, (0, 0))
#draws pacman
Pacman.draw(fake_screen)
#Spawns pellets
SpawnPellets(pelletspawns)
#draws screen
screen.blit(pygame.transform.scale(fake_screen, size), (0, 0))
pygame.display.flip()
clock.tick(FPS)

Categories