I'm having some trouble getting a reaction from pressing the D key in my program. I will show and then explain. (Irrelevant things omitted)
Main.py
while True:
process(Cursor,movie,music)
Effects.List.draw(screen)
pygame.display.flip()
Classes.py
class BaseClass(pygame.sprite.Sprite):
allsprites = pygame.sprite.Group()
def __init__(self,x,y,image_string):
pygame.sprite.Sprite.__init__(self)
BaseClass.allsprites.add(self)
self.image = pygame.image.load(image_string)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def destroy(self, ClassName):
ClassName.List.remove(self)
BaseClass.allsprites.remove(self)
del self
class Effects(BaseClass):
List = pygame.sprite.Group()
def __init__(self,x,y,image_string):
BaseClass.__init__(self,x,y,image_string)
Effects.List.add(self)
Process.py
def process(Cursor,movie,music):
for event in pygame.event.get():
Stage = True
Stage2 = False
keys = pygame.key.get_pressed()
if Stage:
if Cursor.rect.collidepoint(370,340): #Start
if keys[pygame.K_RETURN]:
Stage2 = True
if Stage2:
Stage = False
hitkeys = HitKeys(65,600,"Images/Hit Keys.png") #520
lane = KeyLane(50,0,"Images/4k lane.png")
movie.play()
pygame.mixer.music.play()
if keys[pygame.K_d]:
effect1 = Effects(55,0,"Images/Effect.png")
I am not experienced in programming so my methods to achieve what I want are very roundabout. As you can see, I want the Effect.png to appear when I press D but to only appear during Stage2. It just doesn't happen. It would work if I dedented it one part but that would mean it would appear during Stage. Not what I want.
Would appreciate if you could help me determine why it isn't showing up in Stage2.
In for event in pygame.event.get(): you set
Stage = True
Stage2 = False
so every time you run process() you go to Stage (Stage = True)
You have to set
Stage = True
Stage2 = False
at the beginning of game (before while True:)
BTW: you will have to use Stage and Stage2 in
process(Cursor,movie,music, Stage, Stage2)
Maybe better use one Stage and assign stage number 1, 2
BTW: there are python rules how to name functions and variables (PEP8) - use lowercase (and _) for variable names (stage, stage1, all_sprites) and use upper letter in class names. Event Stackover use that rules and it use light blue color for class names.
EDIT:
I made script to test keyboard. Check what you get.
keys = pygame.key.get_pressed() works but only when screen/window exists.
import pygame
import pygame.locals
pygame.init()
screen = pygame.display.set_mode((800,600))
d_pressed = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.key == pygame.K_d:
d_pressed = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
d_pressed = False
keys = pygame.key.get_pressed()
if d_pressed:
print '> d_pressed <'
if keys[pygame.K_RETURN]:
print '> K_RETURN <'
if keys[pygame.K_d]:
print '> K_d <'
EDIT: sending stages as list - not (separated) values
stages = [True, False]
while True:
process(Cursor, movie, music, stages)
Effects.List.draw(screen)
pygame.display.flip()
-
while True
def process(Cursor,movie,music, stages):
for event in pygame.event.get():
keys = pygame.key.get_pressed()
if stages[0]:
if Cursor.rect.collidepoint(370,340): #Start
if keys[pygame.K_RETURN]:
stages[0] = False
stages[1] = True
if stage[1]:
hitkeys = HitKeys(65,600,"Images/Hit Keys.png") #520
lane = KeyLane(50,0,"Images/4k lane.png")
movie.play()
pygame.mixer.music.play()
if keys[pygame.K_d]:
effect1 = Effects(55,0,"Images/Effect.png")
Related
I'm creating a small game in pygame with obstacles that fall from the top of the screen to the bottom. At each event tick, an obstacle is created. However, at each new tick (1500milliseconds) the current obstacle is removed before it can reach the bottom and a new one is created. I need the obstacles to stay on the screen while new ones are generated.
I'm trying to get this done with classes and functions only.
So I want to create an obstacle_movement() function within the obstacle class.
Can you help please?
My code is below.
import pygame
import sys
from random import randint
from pygame import surface
import time
import os
class obstacle(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
Obstacle_directory = r'C:\\Users\\ctcar\\Documents\\CompSci\\GameDev\\selfgame\\Graphics\\Obstacles'
obstacle_lst = []
self.obstacle_frames = []
for filename in sorted(os.listdir(Obstacle_directory), key = len):
if filename.endswith('.png'):
obstacle_lst.append('Graphics/Obstacles/' + filename)
for sprite in obstacle_lst:
alpha_sprite = pygame.image.load(sprite).convert_alpha()
self.obstacle_frames.append(alpha_sprite)
y_pos = -20
self.obstacle_idx = 0
self.frames = self.obstacle_frames
self.image = self.frames[self.obstacle_idx]
self.rect = self.image.get_rect(midbottom = (randint(50, 750), y_pos))
def obstacle_animation(self):
self.obstacle_idx += 0.1
if self.obstacle_idx >= len(self.frames):
self.obstacle_idx = 0
self.image = self.frames[int(self.obstacle_idx)]
def update(self):
self.obstacle_animation()
self.rect.y += 4
obstacle_group = pygame.sprite.GroupSingle()
obstacle_timer = pygame.USEREVENT + 1
pygame.time.set_timer(obstacle_timer, randint(1000, 1100))
game_active = True
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if game_active:
screen.blit(sky_surface,(0,0))
screen.blit(ground_surface,(100,710))
if event.type == obstacle_timer:
obstacle_group.add(obstacle())
obstacle_group.draw(screen)
obstacle_group.update()
pygame.display.update()
clock.tick(60)
You need to use a pygame.sprite.Group insterad of a pygame.sprite.GroupSingle:
obstacle_group = pygame.sprite.GroupSingle()
obstacle_group = pygame.sprite.Group()
See obstacle_group = pygame.sprite.GroupSingle():
The GroupSingle container only holds a single Sprite. When a new Sprite is added, the old one is removed.
Furthermore, the events must be handled in the event loop:
game_active = True
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if game_active:
if event.type == obstacle_timer:
obstacle_group.add(obstacle())
if game_active:
screen.blit(sky_surface,(0,0))
screen.blit(ground_surface,(100,710))
obstacle_group.draw(screen)
obstacle_group.update()
pygame.display.update()
clock.tick(60)
pygame.quit()
sys.exit()
I created a class of the player and I instantiated it and it doesn't work when I try to move it.
I don't understand what is wrong.
I thought the problem was in the order of the functions but isn't it.
Here is the code:
import pygame
from variabile import *
pygame.init()
screen = pygame.display.set_mode((1000,1000))
def ecranAlb():
WHITE = (255,255,255)
screen.fill(WHITE)
class Player():
def __init__(self,x,y):
self.x = x
self.y = y
def display(self):
rect = pygame.Rect(self.x,self.y,100,100)
pygame.draw.rect(screen,(255,255,0),rect)
def move(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
self.x = self.x + 2
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
a = Player(100,100)
ecranAlb()
a.move()
a.display()
pygame.display.flip()
You have to create the instance object of the Player class before the application loop. When you do it in the loop, then the a new object at the initial position is generated in each frame:
a = Player(100,100) # <--- INSERET
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# a = Player(100,100) <--- DELETE
ecranAlb()
a.move()
a.display()
pygame.display.flip()
I'm just adding some finishing touches to my tank game, but there's this slight thing that's been bothering me. It's just that, at the menu screen, when the user presses a different set of keys to access different things such as the instruction screen, game screen, or custom username input screen, it takes two presses of the button to respond and not the desired one single press. Here's the little excerpt of code:
menu = True
instruct = False
run = False
name1 = False
name2 = False
while menu:
pygame.event.get()
theKey = pygame.key.get_pressed()
if theKey[pygame.K_RETURN]:
menu = False
run = False
instruct = True
name1 = False
if theKey[pygame.K_LSHIFT] or theKey[pygame.K_RSHIFT]:
menu = False
run = True
begin = time.time()
if theKey[pygame.K_BACKSPACE]:
menu = False
run = False
instruct = False
name1 = True
user_input = ''
menu_screen()
FONT = pygame.font.Font(None, 40) # A font object which allows you to render text.
BG_COLOR = pygame.Color('gray12')
BLUE = pygame.Color('dodgerblue1')
USEFONT = pygame.font.Font(None, 70)
yourText1 = "Player 1, Enter Your Name: "
yourText2 = "Player 2, Enter Your Name: "
userNamePrompt = USEFONT.render(yourText1, True, BLUE)
userNamePrompt2 = USEFONT.render(yourText2, True, BLUE)
while name1:
theKey = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
name1 = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_BACKSPACE:
user_input = user_input[:-1]
elif event.key == pygame.K_RETURN:
name1 = False
name2 = True
user2_input = ''
else:
user_input += event.unicode
screen.fill(BG_COLOR)
# Create the text surface.
text = FONT.render(user_input, True, BLUE)
# And blit it onto the screen.
screen.blit(userNamePrompt, (20,20))
screen.blit(text, (20, 300))
pygame.display.flip()
clock.tick(30)
while name2:
theKey = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
name1 = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_BACKSPACE:
user2_input = user2_input[:-1]
elif event.key == pygame.K_RETURN:
name2 = False
run = True
begin = time.time()
else:
user2_input += event.unicode
screen.fill(BG_COLOR)
# Create the text surface.
text = FONT.render(user2_input, True, BLUE)
# And blit it onto the screen.
screen.blit(userNamePrompt2, (20,20))
screen.blit(text, (20, 300))
pygame.display.flip()
clock.tick(30)
playName1 = user_input
playName2 = user2_input
while instruct:
pygame.event.get()
theKey = pygame.key.get_pressed()
if theKey[pygame.K_BACKSPACE]:
instruct = False
run = False
menu = True
if theKey[pygame.K_LSHIFT] or theKey[pygame.K_RSHIFT]:
instruct = False
run = True
begin = time.time()
instruct_screen()
In this case, the code takes two taps of the "return" or enter button to get the instruction screen and two taps of the shift key to show the game screen - and I've tried to fix it, but to no avail. Does anyone know why this may be occurring and what/how the code needs to be modified in order for it to work as desired?
It's because you're calling pygame.key.get_pressed() twice, once in the menu loop and once in the name1 loop. Each time you call it, it's popping the keypress event off the stack, so the second time it will wait for a second keypress. You should store the result the first time, and use that in the second loop.
When we run our pygame's code, our target scope image will NOT move, but our do robots generate. We are trying to use our arrow keys to move them and I included all of our code.
Commented out under our newest trial code for moving are two other things we tried.
import pygame, sys
from graphics import *
import time
import random
pygame.init()
level=1
bg = pygame.image.load('bg.png')
bg_width = 800
pygame.display.set_caption('Robot Apocalypse')
surfacew = 1054
surfacel = 562
surface = pygame.display.set_mode((surfacew,surfacel))
black = (0, 0, 0)
score = 0
#player_health = 99
alive=True
targetImg = pygame.image.load('target.png')
targetImg = pygame.transform.scale(targetImg, (40, 40))
targetxy = targetImg.get_rect()
targetx = targetxy[0]
targety = targetxy[1]
def move_target(targetImg):
pygame.event.clear()
while alive == True:
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_LEFT]:
targetx -= 5
if keys_pressed[pygame.K_RIGHT]:
targetx += 5
if keys_pressed[pygame.K_UP]:
targety -= 5
if keys_pressed[pygame.K_DOWN]:
targety += 5
pygame.display.update()
# pygame.event.clear()
# for event in pygame.event.get():
# if event.type ==KEYDOWN:
# if event.key == K_LEFT:
# direction = MOVE_LEFT
# elif event.key == K_RIGHT:
# direction = MOVE_RIGHT
# elif event.type == KEYUP:
# if event.key == K_LEFT:
# direction = 0
# elif event.key == K_RIGHT:
# direction = 0
# if(direction == MOVE_LEFT):
# targetx-=10
# elif(direction == MOVE_RIGHT):
# targetx+=10
# for event in pygame.event.get():
# print(event)
# if event.type==QUIT:
# pygame.quit()
# sys.exit()
# if event.type == KEYDOWN:
# if event.key == K_LEFT:
# targetx-=5
# elif event.key == K_RIGHT:
# targetx+=5
# elif event.key == K_UP:
# targety-=5
# elif event.key == K_DOWN:
# targety+=5
# pygame.display.update()
def shoot():
#while True:
shot = False
pos = (targetx, targety)
t = screen.blit(robot, (64,64))
if t.collidepoint(pos):
shot = True
return shot
def generate_robot(x,y):
#while displayrobot == True
robot=pygame.draw.rect(surface, (255,0,0), (x,y,64,64), 0)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
shoot()
if shot == True:
displayrobot = False
cover = surface.blit(bg, (x,y))
pygame.display.update()
return x, y
#if shot == True:
def die():
message("YOU DIED")
pygame.display.update()
def win(level):
level+=1
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def message(text):
largeText = pygame.font.Font('freesansbold.ttf',60)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((surfacew/6),(surfacel/2))
surface.blit(TextSurf, TextRect)
pygame.display.update()
time.sleep(2)
def main(alive):
#displayrobot = True:
robot=0
score=0
surface.fill(black)
surface.blit(bg, (0,0))
message("Level "+ str(level))
mouse = pygame.mouse.get_pos()
target = surface.blit(targetImg, (mouse))
while alive==True:
# robot = enemy(64, 64)
x=random.randint(40,760)
y=random.randint(40,560)
generate_robot(x,y)
pygame.display.update()
robot+=1
time.sleep(8/level)
if robot>50 and robot>score:
alive=False
# if pygame.mouse.get_pressed()==True:
# shoot() #maybe??
if shot==True:
score+=1
robot-=1
if robot==10/(level/2): #if 10- robots on screen then...
die()
if score>25*(level/2):
win()
move_target(targetImg)
main(alive)
pygame.quit()
quit()
.
There are no error messages, but it won't move. We've tried a ton of different things (that aren't included) and looked up a lot of websites so please help us. Thanks
To move object you have to not only change x,y and update screen (send buffer to video card which will display it) but also clean buffer, draw image in new place in buffer (blit()).
This code shows only working move_target. I skiped rest of code.
I keep position in target_rect which is pygame.Rect. You can use it to blit(img,rect) but later you can also use to check collision rect.colliderect(other_rect)
import pygame
# --- constants --- (UPPER_CASE_NAMES)
BLACK = (0, 0, 0)
SURFACE_WIDTH = 1054
SURFACE_HEIGHT = 562
# --- functions --- (lower_case_names)
def move_target(target_img, target_rect):
alive = True
clock = pygame.time.Clock()
while alive:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
alive = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
alive = False
# --- updates/changes ---
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_LEFT]:
target_rect.x -= 5
if keys_pressed[pygame.K_RIGHT]:
target_rect.x += 5
if keys_pressed[pygame.K_UP]:
target_rect.y -= 5
if keys_pressed[pygame.K_DOWN]:
target_rect.y += 5
# --- draws ---
surface.fill(BLACK)
surface.blit(target_img, target_rect)
pygame.display.update()
# the same game's speed on all computers = 60 FPS
clock.tick(60)
# --- main --- (lower_case_names)
pygame.init()
pygame.display.set_caption('Robot Apocalypse')
surface = pygame.display.set_mode((SURFACE_WIDTH, SURFACE_HEIGHT))
target_img = pygame.image.load('target.png')
target_img = pygame.transform.scale(target_img, (40, 40))
target_rect = target_img.get_rect()
move_target(target_img, target_rect)
pygame.quit()
It looks like my original functional comment is still "in force": your code doesn't move any game object.
targetxy = targetImg.get_rect()
targetx = targetxy[0]
targety = targetxy[1]
At this point, targetxy is a reference to the bounding rectangle for your game object.
targetx and targety are copies of the values of the rect position.
def move_target(targetImg):
pygame.event.clear()
while alive == True:
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_LEFT]:
targetx -= 5
...
You've change the local copy of the x-coordinate. This does not affect the position of targetImg. You need to change the object's attributes, such as
targetxy.x -= 5
After this, you need to update the game screen.
I'm trying to implement a pause function in my tamagotchi clone (I'm practising for my controlled assessment next year) and I can't get the left and up keys to work simultaneously as a pause button. If possible I want to stay as true to the original game as possible so I would prefer not to use on-screen buttons. Thanks!
import pygame
import time
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
size =(200, 200)
screen = pygame.display.set_mode(size)
pygame.display.set_caption('Tama v4.5')
screen.fill(WHITE)
pygame.init()
clock = pygame.time.Clock()
sprites = ['AdultSpriteAAA.png']
up_pressed = False
left_pressed = False
right_pressed = False
def main():
controls()
if up_pressed == True and left_pressed == True:
time.sleep(2)
pause()
player_position = pygame.mouse.get_pos()
x = player_position[0]
y = player_position[1]
screen.blit(background, [0,0])
screen.blit(sprite, [x, y])
pygame.display.flip()
clock.tick(60)
def controls():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
print(animate())
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
global up_pressed
right_pressed = True
if event.key == pygame.K_LEFT:
global left_pressed
left_pressed = True
if event.key == pygame.K_RIGHT:
global right_pressed
right_pressed = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
global up_pressed
right_pressed = False
if event.key == pygame.K_LEFT:
global left_pressed
left_pressed = False
if event.key == pygame.K_RIGHT:
global right_pressed
right_pressed = False
def info():
return 0
def food():
return 1
def toilet():
return 2
def game():
return 3
def connect():
return 4
def talk():
return 5
def medic():
return 6
def post():
return 7
def history():
return 8
def animate():
return 9
def pause():
time.sleep(2)
while True:
controls()
if up_pressed == True and left_pressed == True:
time.sleep(2)
break
sprite = pygame.image.load(sprites[0]).convert()
background = pygame.image.load('Background 200x200.png').convert()
sprite.set_colorkey(BLACK)
while True:
main()
A way to make it pause when both left iey and up key are pressed is this:
import pygame
from pygame.locals import *
#game code
…
def pause():
keyspressed = pygame.keys.get_pressed()
if keyspressed[K_LEFT] and keyspressed[K_UP]:
#pause code
…
This code should be correct, but if you find any weird things, try to research the pygame key module. Keep in note that K_LEFT and K_UP are from pygame.locals, which is imported seperately from pygame
Here is a method that I have found really useful when writing games in PyGame:
if event.type == pygame.KEYDOWN
if event.key == (pygame.K_RIGHT and pygame.K_LEFT):
while True: # Infinite loop that will be broken when the user press the space bar again
event = pygame.event.wait()
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: # decid how to unpause?
break #Exit infinite loop
An interesting tid-bit I only recently discovered is that pygame.key.get_pressed() returns a tuple of 1s and 0s representing all of the keys on the keyboard, and these can be used as booleans or indexed to get the effective "value" of a key. Some great tuts at http://programarcadegames.com/