Scrolling infinite background in Pygame [duplicate] - python

This question already has answers here:
Making the background move sideways in pygame
(2 answers)
How to scroll the background surface in PyGame?
(1 answer)
Why is my pygame application loop not working properly?
(1 answer)
Closed 2 years ago.
Hi I am trying to render out the menu_background in my menu screen with my menu options showing. When I run my code all I get is the image scrolling but my menu options and audio do not play and show. Anyone can help write code that makes it work where the audio plays and my menu options show up?
import pygame, sys, random, time, os, math
from pygame.locals import *
fps = pygame.time.Clock()
global screen
screen = pygame.display.set_mode((WIDTH, HEIGHT),pygame.FULLSCREEN)
display = pygame.Surface((400,250))
def menu_background():
menu_bg = pygame.image.load("assets/images/menu_bg.png").convert()
x = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
rel_x = x % menu_bg.get_rect().width
screen.blit(menu_bg, (rel_x - menu_bg.get_rect().width, 0))
if rel_x < WIDTH:
screen.blit(menu_bg, (rel_x, 0))
x -= 1
pygame.display.update()
fps.tick(120)
def menu():
bg = menu_background()
menu_options = ['Play','Controls','Highscores','Settings','Credits','Quit']
menu_choice = 0
in_menu = True
pygame.mixer.music.load('assets/audio/mainmenu.wav')
while in_menu:
bg(display)
n = 0
for option in menu_options:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == K_UP:
menu_choice -= 1
if menu_choice < 0:
menu_choice = len(menu_options)-1
if event.key == K_DOWN:
menu_choice += 1
if menu_choice >= len(menu_options):
menu_choice = 0
if event.key == K_SPACE:
choice = menu_options[menu_choice]
if choice == 'Play':
play()
if choice == 'Controls':
controls()
screen.blit(pygame.transform.scale(display,(WIDTH,HEIGHT)),(0,0))
pygame.display.update()
fps.tick(60)

The major issue is that you have implemented 2 main application loops. The loops are executed one after the other.
(By the way, the first of this loops never terminates)
Put all the implementation in one loop. The application loop has to
handle the events and change states
draw the background
draw the scene and menu
update the display
e.g.:
def menu():
x = 0
menu_bg = pygame.image.load("assets/images/menu_bg.png").convert()
menu_options = ['Play','Controls','Highscores','Settings','Credits','Quit']
menu_choice = 0
in_menu = True
# load and play music
pygame.mixer.music.load('assets/audio/mainmenu.wav')
pygame.mixer.music.play()
while in_menu:
fps.tick(120)
# handle events
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == K_UP:
menu_choice -= 1
if menu_choice < 0:
menu_choice = len(menu_options)-1
if event.key == K_DOWN:
menu_choice += 1
if menu_choice >= len(menu_options):
menu_choice = 0
if event.key == K_SPACE:
choice = menu_options[menu_choice]
if choice == 'Play':
play()
if choice == 'Controls':
controls()
# draw background
rel_x = x % menu_bg.get_rect().width
screen.blit(menu_bg, (rel_x - menu_bg.get_rect().width, 0))
if rel_x < WIDTH:
screen.blit(menu_bg, (rel_x, 0))
x -= 1
# draw menu
#n = 0
#for option in menu_options:
# [...]
# update disaplay
pygame.display.update()
menu()

Related

Is there an event handling option to minimize and maximize screen in pygame?

Is there any event handler to minimize or maximize screen like there is to quit screen?
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
Pygame adds pygame.ACTIVEEVENTs to the event queue when the window is minimized/iconified or maximized. You can check if event.gain == 1 and event.state == 6: and if event.gain == 0 and event.state == 6: to see if the window was maximized or minimized. The only problem is that event.gain == 1 and event.state == 6 is also True when the window gains input focus.
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')
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_i:
pg.display.iconify()
elif event.type == pg.ACTIVEEVENT:
if event.gain == 1 and event.state == 6:
print('maximized')
elif event.gain == 0 and event.state == 6:
print('minimized')
screen.fill(BG_COLOR)
pg.display.flip()
clock.tick(60)
If you want to minimize/iconify the window with a key press, you can call pygame.display.iconify().

Pausing a game using pygame by pressing two keys simultaneously - tamagotchi project

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/

pygame - Key pressed

I am kinda stuck with a supposed to be simple code to check if the user has pressed "w" or "s".
Below you can see my code:
import pygame
pygame.init()
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_w:
print('Forward')
elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
print('Backward')
Am I forgetting something here?
Thanks!
A window needs to be created to receive key presses, the following works.
import pygame
import sys
pygame.init()
pygame.display.set_mode((100, 100))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
print('Forward')
elif event.key == pygame.K_s:
print('Backward')
This is what seems to me the most simple and understandable way to do it:
import pygame
pygame.init()
pygame.display.set_mode((300, 300))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
print('Forward')
elif event.key == pygame.K_s:
print('Backward')
Instead of using the sys.exit() method I prefer to just use pygame.quit()
it is no good to ask the gamer to keep hitting w to get the response. If you want to read the "pressed" state. You could consider the followings:
from pygame import *
import time
flag = False # The flag is essential.
DONE = False
screen = display.set_mode((500,500)) # 1180, 216
count=0
while not DONE:
event.pump() # process event queue
keys = key.get_pressed() # It gets the states of all keyboard keys.
#print("%d"%count,keys)
count+=1
if keys[ord('w')]: # And if the key is K_DOWN:
print("%d w down"%count)
if keys[ord('s')]: # And if the key is K_DOWN:
print("%d s down"%count)
time.sleep(0.1)
Try this:
import pygame
pygame.init()
key = pygame.key.get_pressed()
while True:
for event in pygame.event.get():
if event.type == KEYDOWN and event.key == pygame.K_w:
print('Forward')
elif event.type == KEYDOWN and event.key == pygame.K_s:
print('Backward')
Sample code to understand how key press events work.
import pygame
from pygame.locals import *
def main():
pygame.init()
pygame.display.set_caption("Move Box With Arrow Keys")
wndsize = (320, 240)
display = pygame.display.set_mode(wndsize)
x = 5
y = 5
black = (0, 0, 0)
white = (255, 255, 255)
rectpos = (x, y)
rectdim = (50, 50)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x += 5
print("K_RIGHT")
if event.key == pygame.K_LEFT:
x -= 5
print("K_LEFT")
if event.key == pygame.K_UP:
y -= 5
print("K_UP")
if event.key == pygame.K_DOWN:
y += 5
print("K_DOWN")
# Don't allow coords below 0
if 0 > x:
x = 5
if 0 > y:
y = 5
# Don't allow overflow
if x + rectdim[0] > wndsize[0]:
x = wndsize[0] - rectdim[0] - 5
if y + rectdim[1] > wndsize[1]:
y = wndsize[1] - rectdim[1] - 5
rectpos = (x, y)
display.fill(white)
rect = pygame.draw.rect(display, black, ((rectpos), (rectdim)))
pygame.display.update()
main()
This might work:
from pygame import *
init()
if key.get_pressed()[K_w] == True:
print('Forwards')
if key.get_pressed()[K_s] == True:
print('Backwards')`

Character only maintains movement while mouse is moving on screen?

My while loops only maintains the movement for the sprite while the cursor is moving inside of the screen. I've tried reorganizing some of the screen.blits and display.update() and display.flip(). I can't seem to figure out why the character stops after a change in one pixel instead of continuing like it I intended.
background_image = 'Terrain_Grass_First.png'
import pygame, sys
from pygame.locals import *
pygame.init()
pygame.display.set_caption('Hans')
screen_width = 600
screen_height = 400
screen = pygame.display.set_mode((screen_width, screen_height),0,32)
pygame.mouse.set_visible(False)
sprite = pygame.image.load('Hans_front_still.png').convert_alpha()
x,y = (0,0)
movex, movey = (0,0)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == K_w:
y = -1
elif event.key == K_a:
x = -1
elif event.key == K_s:
y = +1
elif event.key == K_d:
x = +1
elif event.type == KEYUP:
if event.key == K_w:
y = 0
elif event.key == K_a:
x = 0
elif event.key == K_s:
y = 0
elif event.key == K_d:
x = 0
movex += x
movey += y
screen.fill((0,0,0))
screen.blit(sprite,(movex,movey))
pygame.display.flip()
Your loop blocks on pygame.event.get.
You don't schedule any events of your own.
So, you do nothing until the OS has an event (mouse move, redraw, etc.) to give you.
And, even if you fixed that, you're calling movex += x once per event. So, when the OS is throwing a lot of events at you, your sprite will go zipping madly across the screen, but when the events are coming more slowly, it will crawl along. That's almost never what you want.
An easy fix for both problems is to just schedule your own events. For example, with pygame.time.set_timer(), you can make sure you get an event every, say, 250 milliseconds, and you can only move the sprite on those events. For example:
timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event, 250)
while True:
for event in pygame.event.get():
# ...
elif event.type == timer_event:
movex += x
movey += y
Another alternative is to design your game with a fixed framerate.
A trivial example looks like this:
FRAME_TIME = 50 # 50ms = 20fps
next_frame_time = pygame.time.get_ticks() + FRAMES
while True:
while True:
event = pygame.event.poll()
if event.type == pygame.NOEVENT:
break
elif # ...
pygame.display.flip()
now = pygame.time.get_ticks()
if now < next_frame_time:
pygame.time.wait(next_frame_time - now)
next_frame_time += FRAMES
Now you can just move every 5th frame.
A realistic example has to deal with missed frames, too many events in the queue, choose between wait and delay appropriately, etc.
But I'd go with the event-driven version with a timer instead of a fixed-framerate version in most cases, especially if you're already going down that line.
The only problem is your Indentation!
The fifth and sixth lines from the bottom have wrong indentation, and you need to delete them.
These two lines:
movex += x
movey += y
should be:
movex += x
movey += y
And it works

Python-Pygame always crashing and Not Responding when running a module in IDLE

I'm quite new to Pygame or even Python, but i know that when something in the isn't right, it displays some text in the Python Shell telling you that there was some error. I've actually encountered many of them and this time, it finally runs and displays the window, but it does not respond. I know there might be some mistakes in my whole code so please feel free to correct me (and please, kindly explain since I'm still new to this stuff).
The code is below, but if it can help, if you'd ask for it, i'll see if i could post the file as well. Anyway, here's the codes:
#import Modules
import os, sys
import pygame
from pygame.locals import *
background_img="C:/Users/JM/Documents/Python/Pygame_Alpha/background_img.jpg"
cursor_img="C:/Users/JM/Documents/Python/Pygame_Alpha/pygameCursor.png"
def load_image(img_file, colorkey=None):
file_pathname = os.path.join("\Users\JM\Documents\Python\Pygame_Alpha",img_file)
try:
image = pygame.image.load(file_pathname).convert_alpha()
except pygame.error, message:
print "Can't load image:", file_pathname
raise SystemExit, message
image = image.convert()
if colorkey is not None:
if colorkey is -1:
colorkey = image.get_at((0,0))
image.set_colorkey(colorkey, RLEACCEL)
return image, image.get_rect()
#Main character's position and movements
char_x,char_y = 0,0
char_go_x,char_go_y = 0,0
#Main char class
class char(pygame.sprite.Sprite):
"""Main Character"""
def __init__(self):
pygame.sprite.Sprite.__init__(self)#call Sprite initializer
self.image, self.rect = load_image("char_img.png", -1)
self.jumping = 0
def update(self):
self.rect.midtop = char_x,char_y
if self.jumping == 1:
self.rect.move_ip(-35,-3)
def char_no_jump(self):
self.jumping = 0
pygame.init()
pygame.display.set_caption("pygame_Alpha")
screen = pygame.display.set_mode((800,480),0,32)
background = pygame.image.load(background_img).convert()
cursor = pygame.image.load(cursor_img).convert_alpha()
char = char()
clock = pygame.time.Clock()
millisec = clock.tick()
sec = millisec/1000.0
char_fall = sec*25
jump = sec*50
#blit the background
screen.blit(background,(0,0))
#Main Loop
while 1:
#Tell pygame not to exceed 60 FPS
clock.tick(60)
#Events
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
#Events triggered when a key/s is/are pressed
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
elif event.key == K_UP or event.key == K_w:
char.jumping = 1
elif event.key == K_DOWN or event.key == K_s:
char_go_y += 1
elif event.key == K_LEFT or event.key == K_a:
char_go_x -= 0.5
elif event.key == K_RIGHT or event.key == K_d:
char_go_x += 0.75
if char_x > 800:
char_x = 0
#Events triggered when a key/s is/are released
if event.type == KEYUP:
if event.key == K_UP or event.key == K_w:
char_go_y += 1
elif event.key == K_DOWN or event.key == K_s:
char_go_y = 0
elif event.key == K_LEFT or event.key == K_a:
char_go_x = 0
if char_x < 0:
char_x = 0
elif event.key == K_RIGHT or event.key == K_d:
char_go_x = 0
if char_x > 700:
char_x = 0
char.update()
while char_y < 200:
char_go_y += char_fall
if char_y > 200:
char_y = 200
#Update values of position of Main Char
char_x += char_go_x
char_y += char_go_y
#Position Variables of Cursor Image, setting its values equal to cursor pos, and blit it to screen
cursor_x,cursor_y = pygame.mouse.get_pos()
cursor_x -= cursor.get_width()/2
cursor_y -= cursor.get_height()/2
screen.blit(cursor,(cursor_x,cursor_y))
pygame.display.update()
Hmm...
while char_y < 200:
char_go_y += char_fall
Unless you have some interesting aliasing I'm not seeing, if char_y < 200 (which it should be at start, it will always be since you're updating char_go_y.
If that's not the issue, would still suggest adding some prints to figure out if it's getting through the loop or not.
is there any error message in idle when you run it? whenever the screen freezes you have something wrong, but its hard to pinpoint what without knowing the error messages. maybe it is trouble opening the picture, you should try putting .convert() at the end of your picture file name, but that is just a guess.
Calling pygame.quit and sys.exit are probably causing issues. Normally you'd never need them in pygame.
Instead of:
#Main Loop
while 1:
#Tell pygame not to exceed 60 FPS
clock.tick(60)
#Events
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
Do this
#Main Loop
done = False
while not done:
clock.tick(60)
for event in pygame.event.get():
if event.type == QUIT:
done = True
if event.type == KEYDOWN:
if event.key == K_ESC:
done = True

Categories