I use Python 3.7.4 and Pygame 1.9.6. I'm trying to create just a test game so I can save data like a score per say using pickle this is my first time. But I'll get down that path once I'm done with the test game.
I'm getting an error two separate occasions in ball(ballX[i], ballY[i], i) and in screen.blit(ballImg, (x, y), i). It's a TypeError: arugument 1 must be pygame.Surface, not list.
Full Trace Back:
Traceback (most recent call last):
File "C:Test/main.py", line 128, in <module>
ball(ballX[i], ballY[i], i)
File "C:/Test/main.py", line 66, in ball
screen.blit(ballImg, (x, y), i)
The code:
import pygame
import random
# Ball
ballImg = []
ballX = []
ballY = []
num_of_balls = 4
for i in range(num_of_balls):
ballImg.append(pygame.image.load('ball.png'))
ballX.append(random.randint(0, 736))
ballY.append(random.randint(50, 535))
'''This code is above the while running loop'''
def ball(x, y, i):
screen.blit(ballImg, (x, y), i)
running = True
while running:
'''The key stuff and what not'''
'''I have the screen color load before the image appears'''
for i in range(num_of_balls):
ball(ballX[i], ballY[i], i)
pygame.display.update()
I'm not understanding what I'm doing wrong in my function/list or evening bliting the image. I feel like I'm doing everything right filling out the parameters, etc. I appreciate the advice. So thank you.
A few things:
As #Ewong mentioned, you are passing ballImg to blit instead of ballImg[i]
You're not processing OS messages, so the program will freeze
Try this code:
import pygame
import random
scr_width = 800
scr_height = 600
screen = pygame.display.set_mode((scr_width, scr_height))
# Ball
ballImg = []
ballX = []
ballY = []
num_of_balls = 4
for i in range(num_of_balls):
ballImg.append(pygame.image.load('ball.png'))
ballX.append(random.randint(0, 736))
ballY.append(random.randint(50, 535))
#'''This code is above the while running loop'''
def ball(x, y, i):
screen.blit(ballImg[i], (x, y))
running = True
while running:
#'''The key stuff and what not'''
#'''I have the screen color load before the image appears'''
for i in range(num_of_balls):
ball(ballX[i], ballY[i], i)
for event in pygame.event.get(): # process OS messages
if event.type == pygame.QUIT:
pygame.quit()
break
pygame.display.update()
Related
I made some code for my game using PyGame to spawn an obstacle and im new to coding. It wouldn't spawn the obstacles and so i put a print statement to see when it spawns and it does print but doesn't show up on screen. This is not all the code but instead a minimalistic version of it that only shows the problematic code. no errors show up when running the code
import pygame as pg
import random
pg.init()
obstacle1 = pg.image.load('download1.jpeg')
obstacley = 600#tells object to spawn at top of screen
spawn = random.randint(1,10)
spawned = 0
if spawn == 1 and spawned == 0:
spawn = 0
Obstaclex = random.randint(600,800)#determines where on the top of the screen it spawns with rng
obstaclesize = random.randint(1,5)# determines obstacletype because there are 5 obstacle types that i havent included in this to be as simple as possbile
obstaclespeed = random.randint(3,8)#determines obstaclespeed using rng
spawned = 1
if obstaclesize == 1:
gameDisplay.blit(obstacle1,(obstacley,Obstaclex))
obstacley -= obstaclespeed #changes y position to lower it down the screen to hit player
print ("i have spawned")
You have to blit all the existing obstacles in the game loop in ever frame, not just when creating a new obstacle.
Create an obstacle list (obstacle_list) and append the coordinates of the new obstacle to the list. Draw all the obstacles in the main application loop:
obstacle_list = []
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# [...]
if len(obstacle_list) < spawn:
x = random.randint(600,800)
y = 600
size = random.randint(1,5)
speed = random.randint(3,8)
obstacle_list.append((x, y, size, speed))
# [...]
# move obstacles
for i in range(len(obstacle_list)):
x, y, size, speed = obstacle_list[i]
new_y = y - speed
obstacle_list[i] = (x, new_y, size, speed)
# [...]
# draw obstacles
for x, y, size, speed in obstacle_list:
gameDisplay.blit(obstacle1, (x, y))
# [...]
Basically, I'm working on an AI project and I am trying to make a loop that does it as long as one coordinate is <= to another coordinate and I have defined a function but when I try to call it it has this error
Traceback (most recent call last):
File "not important", line 66, in
A()
NameError: name 'A' is not defined
and if I try to re-arrange the definition it runs into a variable problem fixed by being placed where it is.
Here is my code (Note I am using pygame for the actual Interface)
import pygame as pg
import math
import time
import random
#starts pygame/create window
pg.init()
screen = pg.display.set_mode((800,600))
pg.display.set_caption("AI ALG")
clock = pg.time.Clock()
#Presets
KillerX = 50
KillerY = 50
EnemyX = 375
EnemyY = 275
gray = (255,255,255)
font = pg.font.Font(None, 32)
TICKSPASSED = 0
font_color = (100, 200, 150)
killertexture = pg.Surface((25,25))
killertexture.fill((0, 255, 0))
enemytexture = pg.Surface((25,25))
enemytexture.fill((255, 0, 0))
startAI = False
#main loop
runing = True
while runing:
ticktxt = font.render(str(TICKSPASSED), True, font_color)
activetxt = font.render(str(startAI), True, font_color)
COO1 = font.render(str(KillerX), True, font_color)
clock.tick(60)
keys = pg.key.get_pressed()
#events
if keys[pg.K_SPACE]:
startAI = True
TICKSPASSED += 1
for event in pg.event.get():
#if event.type == pg.QUIT:
#runing = False
if event.type == pg.QUIT:
runing = False
#update
#render
screen.fill(gray)
screen.blit(ticktxt, ((8,8), (8,8)))
screen.blit(activetxt, ((730,8), (792,8)))
screen.blit(COO1, ((730,8), (792,8)))
screen.blit(killertexture, (KillerX,KillerY))
screen.blit(enemytexture, (EnemyX,EnemyY))
A()
pg.display.flip()
def A():
if not KillerX <= EnemyX:
KillerX =- .5
pg.quit()
Any help would be awesome, thanks
also sorry if my code is messy :)
You should define A before it is referenced. Move the definition of A before the while loop, in which A is called, and the error would go away.
Note that you should also either declare KillerX and EnemyX as global variables in the function A, or make them parameters to A and make A return the altered KillerX.
The code you're running is in-line, rather than in a function, so it is run as soon as it's encountered in the file, which is before it has seen the definition of function A. You can move the definition of A up to a point before it's referenced, or you can place your main code in a function that you call at the end of the file. The definition of A just needs to be seen before you attempt to call it.
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 trying to get into using Pygame, but all of the tutorials I can find online utilize only one file. I played around with ideas on how I can load all of the images in a single function. and decided on saving them in a Dictionary. Problem is, when I try to paste the image from the dictionary, I get the following error:
Traceback (most recent call last):
File "J:\Growth of Deities\Main.py", line 32, in <module>
pygame.Surface.blit(Sprites["TileWastelandBasic"], (0, 0))
TypeError: argument 1 must be pygame.Surface, not tuple
So I played around with the code a bit and googled it for an hour or so, but I can't figure out why I'm getting an error. I assume it's because I can't save images in dictionaries, but I'm not certain. Does anyone have any ideas on how to fix it?
My Main File:
import pygame
from Startup import LoadTextures
pygame.init()
#Sets the color White
WHITE = (255, 255, 255)
#Sets screen size Variable
size = (900, 900)
#Sets Screen Size
screen = pygame.display.set_mode(size)
#Sets name of Game
pygame.display.set_caption("Growth of Deities")
closeWindow = False
clock = pygame.time.Clock()
Sprites = LoadTextures.Load()
while not closeWindow:
#Repeat while game is playing
for event in pygame.event.get():
#Close Window if you close the window
if event.type == pygame.QUIT:
closeWindow = True
#Logic Code
#Rendering Code
pygame.Surface.blit(Sprites["TileWastelandBasic"], (0, 0))
#Clear Screen
screen.fill(WHITE)
#Update Screen
pygame.display.flip()
#Set Tick Rate
clock.tick(60)
#Closes Game
pygame.quit()
My Image Loading File:
import pygame
import os, sys
def Load():
Sprites = {}
WastelandSprites = 'Assets\Textures\Tile Sprites\Wasteland'
Sprites["TileWastelandBasic"] = pygame.image.load(os.path.join(WastelandSprites + "\WastelandBasic.png")).convert_alpha()
Sprites["TileWastelandBasic"] = pygame.transform.scale(Sprites["TileWastelandBasic"], (50, 50)).convert_alpha()
return Sprites
The problem is not because of your dictionary. The signature of blit is
blit(source, dest, area=None, special_flags = 0) -> Rect
where source must be a surface. However, this assumes that blit is being invoked with a pygame.Surface instance as the receiver. Instead, you're calling the blit function from its class, which means that its signature is effectively
blit(self, source, dest, area=None, special_flags = 0) -> Rect
where self must also be a surface. You could fix your problem by changing the call to
pygame.Surface.blit(screen, Sprites["TileWastelandBasic"], (0, 0))
but I would recommend the more idiomatic
screen.blit(Sprites["TimeWastelandBasic"], (0, 0))
instead.
See: http://www.pygame.org/docs/ref/surface.html#pygame.Surface.blit
I am trying to learn pyGame. And I ran into a problem. I have a rectangle which can be moved with arrow buttons. Then I created another thread which generates smaller rectangles which can be picked up. But when I run my game, the small generated rectangles blink too much. How can I make them be stable? I think I dont understand time concept here well. Could someone explain me etc
My code:
import pygame
import random
import threading
import thread
import sys
import time
pygame.init()
screen = pygame.display.set_mode((400, 300))
done = False
is_blue = True
entityList = []
x = 30
y = 30
clock = pygame.time.Clock()
class Entity():
def __init__(self, x, y):
self.x = x
self.y = y
def getX(self):
return self.x
def getY(self):
return self.y
def drawStuff(entityList):
# pygame.draw.rect(screen, (255, 100, 0), pygame.Rect(55, 45, 10, 10))
for x in range (0, entityList.__len__()):
pygame.draw.rect(screen, (255, 100, 0), pygame.Rect(entityList[x].getX(), entityList[x].getY(), 10, 10))
pygame.display.flip()
clock.tick(60)
class EntityManager(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while True:
entityList = generateEntities()
drawStuff(entityList)
def endJob(self):
thread.exit()
time.sleep(2)
def detect_collision(x,y):
if x > 340:
x -= 1
if y > 240:
y -= 1
if y < 0:
y += 1
if x < 0:
x += 1
return x,y
def generateEntities():
itemlist = []
for x in range (0,4):
x = random.randint(1,339)
y = random.randint(1,239)
entity = Entity(x,y)
itemlist.append(entity)
return itemlist
entityList = generateEntities()
a = EntityManager()
a.setDaemon(True)
a.start()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
is_blue = not is_blue
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]:
y -= 1
x,y = detect_collision(x, y)
if pressed[pygame.K_DOWN]:
y += 1
x,y = detect_collision(x, y)
if pressed[pygame.K_LEFT]:
x -= 1
x,y = detect_collision(x, y)
if pressed[pygame.K_RIGHT]:
x += 1
x,y = detect_collision(x, y)
screen.fill((0, 0, 0))
if is_blue: color = (0, 128, 255)
else: color = (255, 100, 0)
pygame.draw.rect(screen, color, pygame.Rect(x, y, 60, 60))
pygame.display.flip()
clock.tick(60)
clock.tick() actually means FPS (frames per second); instead of changing it, change another variable.
Watch this tutorial, it might help you understand FPS.
Issues about smoothness are sometimes about the size of your object and how many pixels you are moving it when key events are True. Be careful about that; imagine you have a little box and you are trying to move it. If you move it with big steps, it seems 'laggy', but if you move it with little steps then it may look smoother. Hope you understand what I mean.
For your second question please check this documentation.
Okay, I figured it out now. OMG, I feel such an idiot after this. But I forgive myself that I am also doing parallell learning of Python. I used to code in Java more.
Anyway: problem was that my drawStuff function drew things in function but when it left this function, it did nothing. Changes were made locally. I solved this problem by using global keyword. I made in my code changes that thread computes entity coordinates and then main loop does update. This leads me to another idea that maybe there should be some game info object which gets updated all the time and all rectangles info go to that game info object.
Anyway, soon I will edit this post code too to see what i did