Pygame not loading image - python-3.x

I cannot display the image that is in the same source folder as my project. Also it gives me squiggly lines under (x, y) and it tells me
"Shadows name "x" & "y" from outer scope"
It shows each one for the "x" and "y" so I just put &
Lastly my quit() at the end tells me
"PEP 8: blank line at the end of file"
Completely new to python and pygame
I am not sure what to try
import pygame
pygame.init()
display_Width = 400
display_Height = 400
gameDisplay = pygame.display.set_mode((display_Height, display_Width))
pygame.display.set_caption('Shonen Run Project')
black = (0, 0, 0)
white = (255, 255, 255)
clock = pygame.time.Clock()
crashed = False
heroImg = pygame.image.load('harper.png')
def hero(x, y):
gameDisplay.blit(heroImg, (x, y))
x = (display_Width * 0.45)
y = (display_Height * 0.8)
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
gameDisplay.fill(white)
hero(x,y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()

I guess you use a IDE. The image loading of your code seems fine, just note that it does only work if the current working directory is actually the directory your python file and your image file is in. A simple way to ensure this is:
import os
import sys
os.chdir(sys.path[0])
The other issues are just warnings.
You have two global variables x and y, and a function def hero(x, y): which has also two arguments x and y. The warning tells you that if you access x or y inside hero, you actually access the local x or y and you have no way to access the global x or y (they are shadowed).
I would suggest renaming the global x and y variables to a more meaningful name, and also remove the hero function, since it is pretty useless.
PEP 8 is the python style guide. You should follow it, as it helps to keep your code readable, especially if other people than yourself are going to read your code. But of course it's not a law, and a missing blank line at the end of file will probably bother no one...

Related

Labels containing images won't fully display when I change the label's attribute?

I started coding a little ago and already there is a bug I can't figure out.
I'm trying to make a Minesweeper-like program. My issue is that when I try to get a cell to display the picture of a flag, a mine or any other image (not number or letters, that I could manage very well), the grid just breaks.
Here is a very condensed part of my code to show my issue :
from tkinter import *
from functools import partial as part
from PIL import Image, ImageTk
class Grid:
def __init__(self, master):
self.master = master
self.images, self.frames, self.grid = [], [], []
self.images = {
"mine": ImageTk.PhotoImage(image=Image.open("Sprites/mine.png").resize((20, 20))),
"flag": ImageTk.PhotoImage(image=Image.open("Sprites/flag.png").resize((20, 20))),
"ghost_flag": ImageTk.PhotoImage(image=Image.open("Sprites/ghost_flag.png").resize((20, 20)))}
self.draw_grid()
def _on_click(self, event, x, y, *args):
if event == "left-click":
self.grid[x][y]["widget"]["image"] = self.images["mine"]
if event == "right-click":
self.grid[x][y]["widget"]["image"] = self.images["flag"]
def draw_grid(self):
for x in range(0, 9):
self.frames.append(Frame(self.master))
self.frames[len(self.frames) - 1].pack(side="top")
self.grid.append([])
for y in range(0, 9):
self.grid[x].append({"widget": Label(self.frames[x], bg="#888888", width=4, height=2, image=None)})
self.grid[x][y]["widget"].pack(fill=BOTH, expand=1, side="left", padx=1, pady=1)
self.grid[x][y]["widget"].bind("<Button-1>", part(self._on_click, "left-click", x, y))
self.grid[x][y]["widget"].bind("<Button-2>", part(self._on_click, "right-click", x, y))
self.grid[x][y]["widget"].bind("<Button-3>", part(self._on_click, "right-click", x, y))
root = Tk()
grid = Grid(root)
root.mainloop()
I obviously got rid of any Minesweeper core code, and the program only places mines on left clicks and flags on right clicks. The two only parts of the code that lock a size in are the .resize(x, y) function and the width and height arguments in the Label creation.
The result is something like that :
See picture
Hope someone can help me,
Have a good day
Edit: Also, if someone knows how to .bind more efficiently, I would be delighted.
Edit 2: After a little bit of thinking, I realised there is a dumb solution, which is to do something like :
self.grid[x][y]["widget"]["width"] = 92
But I would appreciate a cleaner solution.

I'm getting a NameError from using the event function from pygame

I'm making an electrical circuit simulator that's graphically based using Pygame and while using "event.type", I get a 'NameError'
This is for a school project. Here's some code:
#Drawing Rectangles (later used as buttons)
batteryBtn = pygame.draw.rect(display, red, (0,0,100,50))
bulbBtn = pygame.draw.rect(display, green, (100,0,100,50))
resistorBtn = pygame.draw.rect(display, blue, (200,0,100,50))
#Initialising the images
img1 = pygame.image.load(r'C:\Users\Amine\Pictures\Battery.jpg')
img2 = pygame.image.load(r'C:\Users\Amine\Pictures\bulbOn.jpg')
img3 = pygame.image.load(r'C:\Users\Amine\Pictures\bulbOff.jpg')
img4 = pygame.image.load(r'C:\Users\Amine\Pictures\Resistor.jpg')
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if batteryBtn.collidepoint(pos):
display.blit(img1, (0, 100))
I was expecting the program to let me click on the red rectangle and the image would pop up as a result, but I got the following error instead:
Traceback (most recent call last):
File "C:\Users\Amine\Desktop\ComputerScienceProject\Computer Science proj Pygame.py", line 25, in <module>
if event.type == pygame.MOUSEBUTTONDOWN:
NameError: name 'event' is not defined
What your code is missing is something called the event loop which defines the event variable (what is causing your error). Its syntax is this:
for event in pygame.event.get():
#all of your events and such, in your case if event.type == pygame.MOUSEBUTTONDOWN:
You can read up on all the events in the docs or here (a helpful little guide)
other ways you can solve this is by using this
pygame.mouse.get_pressed()[0]
which checks if the left mouse button is down. (read about it here).
or by putting right before you check if mouse is clicked
event = pygame.event.wait()
which functions the same way as the event loop except that it pauses the program if no events are occuring.

Class Attribute Variable is not updating

I am creating a game where the player is a ship that has to dodge meteors that fall. I have 2 classes, the ship and the meteors. The meteors "fall" by having their canvas objects moved down their y axis and their y coordinates are subtracted by the number as the move function. I have an if statement that detects whether the meteors have fallen passed the border of the canvas, and it deletes those meteors, and creates new meteors at the top of the screen, thus making it seem that there are multiple meteors that are falling. The ship class has a similar function that detects if the ship has gone passed the sides of the canvas, which triggers the death function. I have a function in the meteor class that detects whether it is overlapping, with the help from Sneaky Turtle's answer. Now, it's almost finished, I just have one problem. After 3 "rounds" the meteors should get faster. How I implemented this was by having an if statement that checks if a variable is over 3. If not, the variable adds 1. When it reaches 3, it resets and adds (speed amount) to the speed attribute of the meteor,which is used when it moves. the problem is it only works on the first "wave" after that, the speed attribute stays the same. All the sound functions are commented off so that I don't have to upload the files.
Code:
from random import *
from tkinter import *
from time import *
print('''****Meteor Run****
Don't let the meteors hit you!
A-Left D-Right ''')
sleep(1.25)
#from game_sounds import*
root=Tk()
c = Canvas(width=800,height=600,bg="#37061a")
c.pack()
m1=0
m2=0
m3=0
m4=0
m5=0
m6=0
m7=0
m8=0
direction=0
speed=0
score = 0
cont=True
class ship:
def __init__(self,x1,y1,x2,y2):
self.x1=x1
self.y1=y1
self.x2=x2
self.y2=y2
self.hitbox3=387.5 + x1
self.shape=c.create_polygon(353+x1,380+y1,387.5+x1,310+y1,
420+x1,380+y1,fill="Blue")
def move(self):
global direction
if direction=="L":
self.x1 = self.x1-10
self.hitbox3 = self.hitbox3-10
c.move(self.shape,-10,0)
sleep(0.001)
root.update()
if direction=="R":
self.x1 = self.x1+10
self.hitbox3 = self.hitbox3+10
c.move(self.shape,10,0)
root.update()
self.test_lost_in_space()
sleep(0.001)
def death(self):
root.destroy()
print("You Lost!")
print("Score:",score)
# death_sound()
def test_lost_in_space(self):
if self.hitbox3<=0:
self.death()
if self.hitbox3 >=800:
self.death()
def ship_explode(self):
overlap = c.find_overlapping(353+self.x1,380+self.y1,420+self.x1,310+self.y1)
if overlap != (self.shape,):
self.death()
class meteor:
def __init__(self,x1,y1):
self.x1=x1
self.y1=y1
self.hitbox=89+x1
self.speed=.75
self.shape =c.create_polygon(1+x1,50+y1,34+x1,23+y1,67+x1,23+y1,
89+x1,57+y1,64+x1,71+y1,27+x1,71+y1,fill="brown")
def meteor_return(self):
global m1
global m2
global m3
global m4
global m5
global m6
global m7
global m8
global speed
global score
if self.y1 >=600:
c.delete(self)
m1=meteor(randrange(0,700),randrange(6,12))
m2=meteor(randrange(0,700),randrange(6,12))
m3=meteor(randrange(0,700),randrange(6,12))
m4=meteor(randrange(0,700),randrange(6,12))
m5=meteor(randrange(0,700),randrange(6,12))
m6=meteor(randrange(0,700),randrange(6,12))
m7=meteor(randrange(0,700),randrange(6,12))
m8=meteor(randrange(0,700),randrange(6,12))
if speed!=3:
speed=speed +1
score = score + 1
# lvl_up()
if speed==3:
speed=0
self.speed= self.speed + .5
print(self.speed)
score = score + 5
# lvl_up_2()
def meteor_fall(self):
global speed
self.y1 = self.y1 + self.speed
c.move(self.shape,0,self.speed)
root.update()
self.meteor_return()
# ship1.ship_explode()
def ship_move(event):
global direction
if event.keysym=="a":
direction="L"
ship1.move()
if event.keysym=="d":
direction="R"
ship1.move()
ship1 =ship(0,0,0,0)
m1=meteor(randrange(0,200),randrange(6,12))
m2=meteor(randrange(200,400),randrange(6,12))
m3 =meteor(randrange(400,600),randrange(6,12))
m4=meteor(randrange(600,800),randrange(6,12))
m5 =meteor(randrange(400,600),randrange(6,12))
m6=meteor(randrange(600,800),randrange(6,12))
m7 =meteor(randrange(400,600),randrange(6,12))
m8=meteor(randrange(600,800),randrange(6,12))
c.bind_all("<KeyPress-a>",ship_move)
c.bind_all("<KeyPress-d>",ship_move)
while cont ==True:
m1.meteor_fall()
m2.meteor_fall()
m3.meteor_fall()
m4.meteor_fall()
m5.meteor_fall()
m6.meteor_fall()
m7.meteor_fall()
m8.meteor_fall()
c.bind_all("<KeyPress-a>",ship_move)
c.bind_all("<KeyPress-d>",ship_move)
ship1.death()
Instead of comparing the x and y coordinates of each meteor and seeing whether they are within the bounds of the ships co-ordinates, I would use find_overlapping to detect what actually overlaps the Ship.
If you have nothing on your canvas except the meteors and ship, you could implement something like:
ship_coords = c.coords(self.shape)
overlap = c.find_overlapping(*ship_coords)
if overlap != (self.shape, ):
#Code to run when the meteors collide with the ship.
...
Where (self.shape, ) is the tuple returned from the coordinates you pass to find_overlapping. I recommend reading documentation on the Tkinter canvas, it seems like you have just started learning! Hopefully this helps for the moment however.
If you need to specifically detect what items are overlapping with your ship, then there are plenty of other questions and answers on Stack Overflow about find_overlapping.

Using shell commands at the same time as a while loop.

I'm making a game that is for teaching people python, so I'm controlling it by assigning variables, calling functions etc. screeps.com is a similar concept, except it's Javascript, and this is Python. The problem I'm having though, is that I have to use a while loop to refresh the screen, but commands given through the shell can't be executed while the while loop is running. For example, I want to be able to input x += 5, and have the player move to the right. So what I need is a way to refresh the screen at the same time as executing shell commands. Also, I'm using Python 3.4. Thanks in advance.
import pygame
pygame.init()
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('My game')
black = (0,0,0)
white = (255,255,255)
clock = pygame.time.Clock()
crashed = False
pImg = pygame.image.load('player.png')
def car(x,y):
gameDisplay.blit(pImg, (x,y))
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
car_speed = 0
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
gameDisplay.fill(black)
car(x,y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
Why don't you use two threads
1) Thread - Update the display periodically based on inputs
2) Thread - Process inputs and update the shared variables
Threads are the right way to do this. Make sure you import thread at the top.
import thread
consoling = False
def threadedConsole():
global consoling
consoling = True
exec(raw_input(">>> "))
consoling = False
while True:
#Game loop
if not consoling:
thread.start_new_thread(threadedConsole,())

pygame.surface type error: an integer is required

I am new to pygame and i wanted to know what is wrong and how can i fix it, thank you! also my pygame closes right when i open it, thats why i took a screenshot like this one. if you could also explain why it closes that fast, that would be great! (pygame 1.9.2 python 3.4.1 , windows 8)![enter image description here][1]
#!/usr/bin/env python
import pygame, sys
from pygame.locals import *
pygame.init()
pygame.font.init()
pygame.display.set_caption('Primer juego de Gian Di Julio')
mainclock= pygame.time.Clock()
screen = pygame.display.set_mode((800,600))
pygame.mouse.set_visible(0)
#positioning the ship into the middle of the screen
ship = pygame.image.load('ship.png')
ship_top = screen.get_height() - ship.get_height()
ship_left = screen.get_width()/2 - ship.get_width()/2
pygame.Surface(ship,(ship_left,ship_top))
while True:
screen.fill((0,0,0))
x,y = pygame.mouse.get_pos()
screen.blit(ship, (x-ship.get.width()/2, ship_top))
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
pygame.display.update()
pygame.display.flip()
I just looked it up in the pygame docs:
Surface((width, height), flags=0, Surface) -> Surface
But the returned surface is not used in your program so you might leave it out.
When using pygame.display.flip() there is no need for calling pygame.display.update().
Additionally it should be indented.
It closes quickly because you have a syntax error in your code.
pygame.Surface(ship,(ship_left,ship_top))
This line tries to create a surface, with dimensions taken from the ship variable.
Since ship is a surface loaded from an image, it fails.
Removing this line will fix the issue.

Resources