I am following the instructions of a pygame project on youtube, this is the video, I am on the project called "Snake", and in the description of the video, you can find what time it starts and the actual code. I am about 10 minutes into the video. I will show you the code that I have written so far:
# Snake project on python
import math
import random
import pygame
import tkinter as tk
from tkinter import messagebox
class cube(object):
rows = 0
w = 0
def __init__(self, start,dirnx=1, dirny=0, colour=(255,0,0)):
pass
def move(self, dirnx, dirny):
pass
def draw(self, surface, eyes=False):
pass
class snake(object):
def __init__(self, color, pos):
pass
def move(self):
pass
def reset(self, pas):
pass
def addCube(self):
pass
def draw(self, surface):
pass
def drawGrid(w, rows, surface):
sizeBtwn = w // rows
x = 0
y = 0
for l in range(rows):
x = x + sizeBtwn
y = y + sizeBtwn
pygame.draw.line(surface, (255,255,255), (x,0), (x,w))
pygame.draw.line(surface, (255,255,255), (0,y), (w,y))
def redrawWindow(surface):
global rows, width
surface.fill(0,0,0)
drawGrid(width, rows, surface)
pygame.display.update()
def randomSnack(rows, items):
pass
def message_box(subject, content):
pass
def main():
global width, rows
width = 500
rows = 20
win = pygame.display.set_mode((width, width))
s = snake((255, 0, 0), (10, 10))
flag = True
clock = pygame.time.Clock()
while flag:
pygame.time.delay(50)
clock.tick(10)
redrawWindow(win)
main()
When I run the code the tutorial says I should be getting a grid (shown in 55:32 of the video). Instead, I am receiving this message:
Windows PowerShell
Try the new cross-platform PowerShell https://aka.ms/pscore6
PS C:\Users\holca\Desktop\Snake> & C:/Users/holca/AppData/Local/Programs/Python/Python38-32/python.exe c:/Users/holca/Desktop/Snake/snake.py
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "c:/Users/holca/Desktop/Snake/snake.py", line 77, in <module>
main()
File "c:/Users/holca/Desktop/Snake/snake.py", line 74, in main
redrawWindow(win)
File "c:/Users/holca/Desktop/Snake/snake.py", line 51, in redrawWindow
surface.fill(0,0,0)
ValueError: invalid rectstyle object
PS C:\Users\holca\Desktop\Snake>
I am using VSCode, and I have 2 warning messages talking about some unused variables, but I doubt they have to do anything with the problem. Am I missing something?
You have to specify the color by a tuple:
surface.fill(0,0,0)
surface.fill( (0, 0, 0) )
Explanation:
The first argument of fill() is the color (tuple). The other arguments are optional. The 2nd argument is an optional rectangle specifying area to be filled. The 3rd arguments are optional flags.
Hence the instruction surface.fill(0,0,0) can be read as:
surface.fill(0, rect=0, special_flags=0)
The 2nd argument (rect=0) causes the error
ValueError: invalid rectstyle object
Related
This question already has answers here:
Pygame window not responding after a few seconds
(3 answers)
Pygame unresponsive display
(1 answer)
Closed 1 year ago.
I am trying to make a simple snake game off a tutorial and the game is incomplete but I am supposed to be able to get the pygame gameboard or surface to open and show the basic grid structure but it shows the pygame window as not responding. I've already installed pygame on the anaconda prompt with pip install pygame. I am using Spyder 5, and python 3.8.10 and pygame 2.0.1.
import math
import random
import pygame
import tkinter as tk
from tkinter import messagebox
class cube(object):
rows = 0
w = 0
def _init_(self, start,dirnx=1, dirny=0, color=(255, 0, 0)):
pass
def move(self, dirnx, dirny):
pass
def draw(self, surface, eyes=False):
pass
class snake(object):
def _init_(self, color, pos):
pass
def move(self):
pass
def reset(self, pos):
pass
def addCube(self):
pass
def draw(self, surface):
pass
def drawGrid(w, rows, surface):
sizeBtwn = w // rows
x = 0
y = 0
for l in range(rows):
x = x + sizeBtwn
y = y + sizeBtwn
pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, w))
pygame.draw.line(surface, (255, 255, 255), (0, y), (w, y))
def drawWindow (surface):
global rows, width
surface.fill((0, 0, 0))
drawGrid(width, rows, surface)
pygame.display.update()
def randomSnack(rows, items):
pass
def message_box(subject, content):
pass
def main() :
global width, rows
width = 500
height = 500
rows = 20
win = pygame.display.set_mode((width, width))
s = snake((255, 0, 0), (10, 10))
flag = True
clock = pygame.time.Clock()
while flag:
pygame.time.delay(50)
clock.tick(10)
redrawWindow(win)
pass
main()
You have to handle the events in the application loop. See pygame.event.get() respectively pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
def main() :
global width, rows
width = 500
height = 500
rows = 20
win = pygame.display.set_mode((width, width))
s = snake((255, 0, 0), (10, 10))
flag = True
clock = pygame.time.Clock()
while flag:
for event in pygame.event.get():
if event.type == pygame.QUIT:
flag = False
clock.tick(10)
redrawWindow(win)
I don't know if it is a typo, but I think the
redrawWindow(win)
in the while loop should actually be
drawWindow(win)
as you named the function.
And def __init__ should consist of two underscores before and after.
I am currently in the process of making a 2D platformer game with procedurally generated levels in pygame, however I am getting the following error messages, which are preventing me from continuing:
Traceback (most recent call last):
File "C:\Users\Win10\Desktop\SCV v3.2.py", line 63, in <module>
main() #calls the main function
File "C:\Users\Win10\Desktop\SCV v3.2.py", line 36, in main
block_object = block_class(0, 5)
File "C:\Users\Win10\Desktop\SCV v3.2.py", line 29, in __init__
self.image.Rect = (32, 32) #block is 32*32 pixels large
AttributeError: 'pygame.Surface' object has no attribute 'Rect'
My first thought was that I had just made some of the classes and functions in the wrong order, however that didn't seem to help, I then tried renaming some of the variables, as well as making sure that I had correctly named all of my variables after this fact. I then went to youtube to see if anyone else was having a similar problem and I found that this works in python 3.4 as I had seen a very similar class work, however I have a feeling that this would only create more problems for the rest of the code as I have only used versions of python from 3.6 to the present.
Here is the code that is having the problem:
import pygame #imports pygame
import time #imports the timer so I can use the tick function to make game 60 fps
import sys #imports system
from pygame import * #imports all pygame files
win_height = 500 #height of the window is 500 pixles
win_width = 500 #width of the window is 500 pixels
red = (255, 0, 0) #makes red a preset colour using rgb
green = (0, 255, 0) #makes green a preset colour using rgb
display = (win_height, win_width) #creates the windown as 500*500 pixels
depth = 32 #prevents infinate recursion
timer = pygame.time.Clock() #creates a timer
flags = 0 #I don't really know what this does, however I have seen in many places it being used, therefore I assumed that it was important
screen = pygame.display.set_mode(display, depth, flags) #loads up a pygame window
class entity(pygame.sprite.Sprite): #makes player a sprite
def __init__(self):
pygame.sprite.Sprite.__init__(self) #sets sprite to initiate
class block_class(entity):
def __init__(self, x, y):
self.image = Surface((32, 32))
self.image.rect = (32, 32) #block is 32*32 pixels large
self.image.fill(Color ("#FF0400")) #block is red
self.image.convert()
self.rect = Rect(x, y, 32, 32)
def main(): #main game function
block_object = block_class(0, 5)
player_object = player_class(0,0)
while 1: #updates the screen so you can see changes like movement
timer.tick(60)
player_object.update()
screen.fill(red) #makes the screen red(will probably be temporary)
pygame.display.update()
class player_class(entity): #defines the player class
def __init__(self, x, y): #x is the players x coordinate, y is player y coordinate
self.xvel = 0 #how fast the player is moving to the left and right
self.yvel = 0 #how fast the player is moving up and down
self.image = Surface((32, 32))
self.image.rect = (32, 32) #player is 32*32 pixels large
self.image.fill(Color ("#00FF33")) #player is green
self.image.convert()
self.rect = Rect(x, y, 32, 32)
def update():
pass
main() #calls the main function
self.image = Surface((32, 32))
You set surface width and height there. There is no rect attr in Surface.
Surface doc
This question is asked a lot, but unfortunately I found no answer fitting my problem. If possible, I prefer a generic answer, since I'm a novice trying to learn Python. Thank you in advance.
This is the code I got by following a tutorial on the basics of python using the pygame library:
import pygame
background_colour = (255, 255, 255)
(width, height) = (300, 200)
class Particle:
def __init__(self, x, y, size):
self.x = x
self.y = y
self.size = size
self.colour = (0, 0, 255)
self.thickness = 1
screen = pygame.display.set_mode((width, height))
def display(self):
pygame.draw.circle(screen, self.colour, (self.x, self.y), self.size, self.thickness)
pygame.display.set_caption('Agar')
screen.fill(background_colour)
pygame.display.flip()
running = True
my_first_particle = Particle(150, 50, 15)
my_first_particle.display()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
It is used to create a window for gaming, with a circle in it. The circle is defined as a class to be used multiple times in a similar way later on.
I got the following error:
Traceback (most recent call last):
File "C:/Users/20172542/PycharmProjects/agarTryout/Agar.py", line 29, in <module>
my_first_particle.display()
AttributeError: 'Particle' object has no attribute 'display'
What principle am I not understanding, and what is the specific solution for this error?
Thank you for your time and effort.
The display function defined is not inside Particle, instead at the global (not sure if this name is right) level of your script. Indentation is significant in python, as it does not have brackets. Move the function after your __init__ function, with the same indentation.
Also, I guess you should move screen above your Particle definition.
By your definition of the Particle class, my_first_particle (an instance of Particle) has no display attribute.
It looks like the definition of the display function should be part of the Particle class definition.
Check out the Python Classes tutorial.
I am trying to understand the tilemaps in pygame, and to learn how to use Tiled Map Editor, but I can't succeed to load the map in the pygame.
Here is the code:
import pygame
import pytmx
pygame.init()
display = pygame.display.set_mode((600,400))
clock = pygame.time.Clock()
gameMap = pytmx.TiledMap("map.tmx")
while(True):
clock.tick(60)
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if(event.type == pygame.QUIT):
quit()
if(keys[pygame.K_ESCAPE]):
quit()
for layer in gameMap.visible_layers:
for x, y, gid, in layer:
tile = gameMap.get_tile_image_by_gid(gid)
if(tile != None):
display.blit(tile, (x * gameMap.tilewidth, y * gameMap.tileheight))
pygame.display.update()
It keep giving me this error:
Traceback (most recent call last):
File "main.py", line 27, in
display.blit(tile, (x * gameMap.tilewidth, y * gameMap.tileheight))
TypeError: argument 1 must be pygame.Surface, not tuple
I know that when I print the tile in console this is what I get
(a tuple):
('img/NES - Super Mario Bros - Tileset.png', (0, 144, 16, 16), TileFlags(flipped_horizontally=False, flipped_vertically=False, flipped_diagonally=False)).
What is the simplest method to successfully load a tilemap in pygame and what am I doing wrong?
use:
gameMap = pytmx.load_pygame("map.tmx")
instead of:
gameMap = pytmx.TiledMap("map.tmx")
I think that the following covers most of the mechanics of rendering the mapSurface and drawing something on it with update and loadMap. I don't have any real TMX files to test with. ymmv. Good luck.
import time
import pygame
import pytmx
class TiledMap():
""" This is creating the surface on which you make the draw updates """
def __init__(self):
self.gameMap = pytmx.load_pygame("map.tmx", pixelalpha=True)
self.mapwidth = self.gameMap.tilewidth * self.gameMap.width
self.mapheight = self.gameMap.tileheight * self.gameMap.height
def render(self, surface):
for layer in self.gameMap.visible_layers:
if isinstance(layer, pytmx.TiledTileLayer):
for x, y, gid in layer:
tile = self.gameMap.get_tile_image_by_gid(gid)
if tile:
surface.blit(tile, (x * self.gameMap.tilewidth, y * self.gameMap.tileheight))
def make_map(self):
mapSurface = pygame.Surface((self.mapwidth, self.mapheight))
self.render(mapSurface)
return mapSurface
pygame.init()
class Display():
""" This is the class that makes the changes that you want to display. You would add most of your changes here. """
def __init__(self):
self.displayRunning = True
self.displayWindow = pygame.display.set_mode((600, 400))
self.clock = pygame.time.Clock()
def update(self):
pygame.display.set_caption("{:.2f}".format(self.clock.get_fps()))
pygame.display.update()
def loadMap(self):
self.map = TiledMap()
self.map_img = self.map.make_map()
self.map_rect = self.map_img.get_rect()
def displayLoop(self):
self.clock.tick()
self.update()
self.loadMap()
# Here is the start of the main driver
runDisplay = Display()
runDisplay.update()
runDisplay.loadMap()
time.sleep(60)
If you want it to run in a loop then you would change that bottom driver block to something like:
runDisplay = Display()
while runDisplay.displayRunning is True:
runDisplay.displayLoop()
So I'm developing a game using Pygame and trying to abstract away a lot of the code. In the process though, I'm getting some weird errors. Namely, when I run main.py, I get this trace:
>>>
initializing pygame...
initalizing screen...
initializing background...
<Surface(Dead Display)> #Here I print out the background instance
Traceback (most recent call last):
File "C:\Users\Ceasar\Desktop\pytanks\main.py", line 19, in <module>
background = Background(screen, BG_COLOR)
File "C:\Users\Ceasar\Desktop\pytanks\background.py", line 8, in __init__
self.fill(color)
error: display Surface quit
I imagine it has something to do with me using a context in my main to manage the screen.
#main.py
import math
import sys
import pygame
from pygame.locals import *
...
from screen import controlled_screen
from background import Background
BATTLEFIELD_SIZE = (800, 600)
BG_COLOR = 100, 0, 0
FRAMES_PER_SECOND = 20
with controlled_screen(BATTLEFIELD_SIZE) as screen:
background = Background(screen, BG_COLOR)
...
#screen.py
import pygame.display
import os
#The next line centers the screen
os.environ['SDL_VIDEO_CENTERED'] = '1'
class controlled_screen:
def __init__(self, size):
self.size = size
def __enter__(self):
print "initializing pygame..."
pygame.init()
print "initalizing screen..."
return pygame.display.set_mode(self.size)
def __exit__(self, type, value, traceback):
pygame.quit()
#background.py
import pygame
class Background(pygame.Surface):
def __init__(self, screen, color):
print "initializing background..."
print screen
super(pygame.Surface, self).__init__(screen.get_width(),
screen.get_height())
print self
self.fill(color)
self = self.convert()
screen.blit(self, (0, 0))
Any thoughts on what is causing the error here?
Not technically my answer here, but the problem is that Surface cannot be extended with Python's super. Rather, it should be referred to as a Python old style class like so:
class ExtendedSurface(pygame.Surface):
def __init__(self, string):
pygame.Surface.__init__(self, (100, 100))
self.fill((220,22,22))
# ...
SOURCE: http://archives.seul.org/pygame/users/Jul-2009/msg00211.html
i was also trying to subclass pygame.Surface because i wanted to be able to add attributes to it. the following accomplishes that. i hope it helps future people.
pygame.display.set_mode() must be called because it inits all the pygame.video stuff. it appears that pygame.display is the surface that ultimately gets drawn to the screen. therefore we need to blit whatever surface we create to the return value of pygame.display.set_mode() (which is just another pygame.Surface object).
import pygame
from pygame.locals import *
pygame.init()
SCREEN_SIZE = (800, 600)
font = pygame.font.SysFont('exocet', 16)
class Screen(pygame.Surface):
def __init__(self):
pygame.Surface.__init__(self, SCREEN_SIZE)
self.screen = pygame.display.set_mode((SCREEN_SIZE))
self.text = "ella_rox"
My_Screen = Screen()
text_surface = font.render(My_Screen.text, 1, (155, 0, 0))
while True:
My_Screen.fill((255, 255, 255))
My_Screen.blit(text_surface, (50, 50))
My_Screen.screen.blit(My_Screen, (0, 0))
pygame.display.update()