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.
Related
I recently started exploring classes and I have made my first class (sort of) but it doesn't seem to be working. I have code creating the class and function, then takes the values and blits an image to certain coordinates. for some reason It takes the values from inside the class instead of what I told it to have. I am new to classes so I'm not sure what to do, please help, thanks!
import pygame
pygame.init()
Screen = pygame.display.set_mode((800, 400))
TC = pygame.image.load("TC.png").convert_alpha()
ANUM = 0
class MTC() :
def __init__(self,) :
self.Tx = 0
self.Ty = 0
Screen.blit(TC,(self.Tx,self.Ty))
TMTC = MTC()
TMTC.Tx = 800
TMTC.Ty = 800
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
pygame.display.update()
The image is blit in the constructor. At this point the coordinates are not yet changed. You have add a method that blits the object:
class MTC() :
def __init__(self,) :
self.Tx = 0
self.Ty = 0
def dra():
Screen.blit(TC,(self.Tx,self.Ty))
Call the draw method in the application loop:
TMTC = MTC()
TMTC.Tx = 800
TMTC.Ty = 800
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
Screen.fill((0, 0, 0))
TMTC.draw()
pygame.display.update()
You are calling Screen.blit in the class constructor which is executed when your class is instantiated (TMTC = MTC()).
You are then setting the tx and ty after Screen.blit has already run
import pygame
import time
# WINDOW SETUP
window = pygame.display.set_mode((900, 500))
pygame.display.set_caption("Pong")
time.sleep(5)
FPS = 60
# RGB VALUE VARIABLES
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
def background(window):
window.fill(WHITE)
pygame.display.update()
# FRAMERATE AND EVENT LOOP INITIALIZATION
def main():
run = True
clock = pygame.time.Clock()
while run:
clock.tick(FPS)
background(window)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if running == False:
pygame.quit()
Above, is my code. I'm trying to make a pong game with pygame. The text editor I am coding with is Visual Studios Code (VSCODE).
Firstly, you need to call the main. You should also make you're code nice and easy to read when possible. I imported pygame as pg which makes typing pygame functions a bit faster as you have less to type. Also, it's better to use global variables to hold variables that won't change through the program, like screen width, height, colours, etc. Then make sure you initialise the module.
As well as that, the only update you have is in background(). You should put the update at the bottom of the loop and remove it from background(). This way everything above will update each loop.
I apologise for not adding you're FPS counter in here as well but I think this should be enough to help you get you're window running with more readable code and a more efficient loop.
import pygame as pg
# Global Variables
screen_width = 900
screen_height = 500
screen = pg.display
window = screen.set_mode((screen_width, screen_height))
colour = 'red'
def main():
# Initialise module
pg.init()
pg.display.set_caption('PONG')
running = True
while running:
# This is a better way of writing your loop
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
# Call background function
background()
# Updates window
# place this inside the loop near the bottom
# so everything is updated at the end of each loop
screen.flip()
def background():
window.fill(colour)
# Remember to call your main function
# This if statement is good practise but not required
# You can just place main() here
if __name__ == '__main__':
main()
So I'm trying to implement a class for a basic game. It woked without the class but now instead of spawning the "coin" it pops up and then immediatly dissapears. No idea as it's in the main loop. I have a moving "player" that works fine.
Here's my code:
class Coin_Class:
def __init__(self):
coin_1 = pygame.Rect(425, 30, 40, 40)
pygame.draw.rect(WIN, YELLOW, coin_1)
pygame.display.update()
# def coin_collect():
# if player.colliderect():
# coin_1.x = random.randint(0, 800)
# coin_1.y = random.randint(0, 250)
# pygame.event.post(pygame.event.Event(coin_collected))
# global score
# score += 1
# print(score)
coin_class = Coin_Class()
# main function loop
def main():
score_check = 0
clock = pygame.time.Clock()
run = True
while run:
# game speed
clock.tick(FPS)
# initialise pygame
pygame.init()
# checking all the events in pygame and looping them
for event in pygame.event.get():
# checking quit function is pressed
if event.type == pygame.QUIT:
run = False
pygame.quit()
exit()
keys_pressed = pygame.key.get_pressed() # recognise key presses
player_movement(keys_pressed, player) # movement function
draw_window() # create window function
coin_class
main()
# runs the main file
if __name__ == "__main__":
main()
Add a draw method to the coin class (also class names per PEP 8 should be in CapitalCase not Capital_Snake_Case so CoinClass):
class Coin_Class:
def __init__(self):
self.coin_1 = pygame.Rect(425, 30, 40, 40)
...
def draw(self):
pygame.draw.rect(WIN, YELLOW, self.coin_1)
And in the loop instead of using
coin_class
you would now use
coin_class.draw()
The rest can stay the same, except remove pygame.init() from the loop and put it somewhere at the start of the code after imports
This question already has answers here:
Using global variables in a function
(25 answers)
Closed 1 year ago.
Why do I get a NameError exception in this program?
I am programming a Python plane fight game using pygame. I have just finished added the plane PNG to the background. However, when I want to test the movement of the plane, the error is raised and I couldn't find why it occurred.
Error traceback:
Traceback (most recent call last):
File "C:\Users\Desktop\Plane Fight\Plane Fight.py", line 34, in <module>
main()
File "C:\Users\Desktop\Plane Fight\Plane Fight.py", line 29, in main
draw_window()
File "C:\Users\Desktop\Plane Fight\Plane Fight.py", line 12, in draw_window
win.blit(leftjet, (left.x, left.y))
NameError: name 'left' is not defined
Code:
import pygame
import os
win = pygame.display.set_mode((900, 500)) #生成一个900*500分辨率的游戏界面
pygame.display.set_caption("Plane Fight Game")
leftjet = pygame.transform.rotate(pygame.transform.scale(pygame.image.load(os.path.join('fighterjet.jpg')), (55 ,40)), 270)
rightjet = pygame.transform.rotate(pygame.transform.scale(pygame.image.load(os.path.join('fighterjet.jpg')), (55 ,40)), 90)
def draw_window():
win.fill((0, 0, 0)) #设置背景为黑色
win.blit(leftjet, (left.x, left.y))
win.blit(rightjet, (right.x, right.y))
pygame.display.update()
def main():
left = pygame.Rect(100, 100, 55, 40)
right = pygame.Rect(800, 100, 55, 40)
run = True
while run:
pygame.time.Clock().tick(60) #设置游戏帧率为60帧
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
right.x += 1
draw_window()
pygame.quit()
if __name__ == "__main__":
main()
You accessed local variables (left, right) in main().
edit to following code.
import pygame
import os
win = pygame.display.set_mode((900, 500)) #生成一个900*500分辨率的游戏界面
pygame.display.set_caption("Plane Fight Game")
leftjet = pygame.transform.rotate(pygame.transform.scale(pygame.image.load(os.path.join('fighterjet.jpg')), (55 ,40)), 270)
rightjet = pygame.transform.rotate(pygame.transform.scale(pygame.image.load(os.path.join('fighterjet.jpg')), (55 ,40)), 90)
def draw_window(left, right):
win.fill((0, 0, 0)) #设置背景为黑色
win.blit(leftjet, (left.x, left.y))
win.blit(rightjet, (right.x, right.y))
pygame.display.update()
def main():
left = pygame.Rect(100, 100, 55, 40)
right = pygame.Rect(800, 100, 55, 40)
run = True
while run:
pygame.time.Clock().tick(60) #设置游戏帧率为60帧
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
right.x += 1
draw_window(left, right)
pygame.quit()
if __name__ == "__main__":
main()
Look at the example I have provided below.
def respond():
left += 90
right += 50
def call():
left = 0
right = 0
respond()
call()
This is basically the structure of your code. What is going wrong is, variables left & right belong to the function call(), they cannot be used outside of the function. So in respond we break that rule, and get the error left is not defined. So in order to solve this problem, we make left&right accessible to respond by passing them in as arguments.
def respond(left,right):
left += 90
right += 50
def call():
left = 0
right = 0
respond(left,right)
call()
no error occurs.
The pygame.Rect objects left and right are local variables of main(). In other words, they are variables which belong to the local scope of main(). Since this is the case, left and right can only be referenced inside of the main() function. Thus, left and right are undefined in draw_window().
The easiest solution, in this case, would be to add the parameters left and right to the function draw_window(). Then, when calling draw_window() in main(), pass the variables left and right.
def draw_window(left, right): # Require 'left' and 'right' as parameters
win.fill((0, 0, 0))
win.blit(leftjet, (left.x, left.y))
win.blit(rightjet, (right.x, right.y))
pygame.display.update()
def main():
left = pygame.Rect(100, 100, 55, 40)
right = pygame.Rect(800, 100, 55, 40)
run = True
while run:
pygame.time.Clock().tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
right.x += 1
draw_window(left, right) # Pass 'left' and 'right'
pygame.quit()
See the Python Programming FAQ for a summary on local and global variables.
Note: Alternatively, you could have defined left and right in the global scope and accessed the variables within draw_window() and main() using the global keyword (when necessary). While it is a solution, it is not recommended, as it infringes on readability, and somewhat defeats the purpose of a function: to create a 'self-contained' block of code.
hello im new to python/pygame and tried to make a basic project. it did not turn out as planned as i don't understand this error if you can tell my why my image is not loading it will very much appreciated. Traceback (most recent call last):
File "C:\Users\Nicolas\Desktop\template\templat.py", line 15, in <module>
screen.fill(background_colour)
NameError: name 'background_colour' is not defined
this is the error i was speaking of however i have fixed now. how ever now the screen opens displayes the background and crashes.
import pygame, sys
pygame.init()
def game():
background_colour = (255,255,255)
(width, height) = (800, 600)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Tutorial 1')
pygame.display.set_icon(pygame.image.load('baller.jpg'))
background=pygame.image.load('path.png')
target = pygame.image.load('Player.png')
targetpos =target.get_rect()
screen.blit(target,targetpos)
screen.blit(background,(0,0))
pygame.display.update()
while True:
screen.blit(background,(0,0))
screen.blit(target,targetpos)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if__name__==('__main__')
game()
You missed the __init__ definition!
While your code does run, it is not what you want. There's an infinite loop inside the definition of the class, which means, however you are running this, there's something missing. You should put this code (most of it at least) inside the __init__ function, and then create an instance of the class.
This is what I assume you want:
import pygame, sys
class game():
width, height = 600,400
def __init__(self):
ball_filename = "Ball.png"
path_filename = "path.png"
self.screen = pygame.display.set_mode((self.width, self.height))
pygame.display.set_caption('Star catcher')
self.background = pygame.image.load(path_filename)
self.screen.blit(self.background,(0,0))
self.target = pygame.image.load(ball_filename)
def run(self):
while True:
self.screen.blit(self.background, (0,0))
targetpos = self.target.get_rect()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if __name__ == "__main__":
# To run this
pygame.init()
g = game()
g.run()
UPDATE:
I made more modifications than what you must do, but they could be useful. I did not test this, but it should be fine.
The error of width and height not being defined is because they are not local/global variables, but bound to the class and/or the instance of the class, therefore in their namespace. So you need to access these either via game.width (per class) or self.width (per instance, only inside a method defined in the class) or g.width (per instance, if you are outside the class definition and g is an instance of game class).
I hope I'm clear. :)