Python function not defined - python

I have been making a python 3d game in ursina. So far so good but for one error:
File "C:\Users\my name\AppData\Local\Programs\Python\Python39\lib\site-packages\ursina\main.py", line 117, in _update
__main__.update()
File "c:\Users\my name\Desktop\game456.py", line 14, in update
release()
NameError: name 'release' is not defined```
I dont understand this error. I have seen others run code like this too. This code is inspired by another person making a game in ursina so i copied a little bit of code myself. i tried googling an answer but it's just about a variable not being defined,etc. View code below.
from ursina import*
from ursina.prefabs.first_person_controller import FirstPersonController
gamebyme = Ursina()
def update():
if held_keys["left mouse"]:
shoot()
else:
release()
class Voxel(Button):
def __init__(self, position = (0,0,0)):
super().__init__(
parent = scene,
position = position,
model = 'map',
origin_y = 0.5,
texture = texture,
color = color.color(0,0,random.uniform(0.9,1)),
scale = 0.1)
class Gun(Entity):
def __init__(self):
super().__init__(
parent=camera.ui,
model='ak_47',
position=Vec2(0.8,-0.1),
color=color.gray,
scale=0.3)
def shoot(self):
self.rotation=Vec3(0,0,10)
def release(self):
self.rotation=None
def reload(self):
self.rotation=Vec3(0,0,0)
plr = FirstPersonController()
gun = Gun()
vxl = Voxel()
gamebyme.run()

In this function
def update():
if held_keys["left mouse"]:
shoot()
else:
release()
you should specify the Gun type object you want to call the functions from, eg:
def update(gun):
if held_keys["left mouse"]:
gun.shoot()
else:
gun.release()

Related

Pygame segmentation fault with import depending on position in code?

I know these segmentation fault questions are common, but I couldn't find answer and I am pulling my hair out as the code works without issue in some parts of the code, but not others or in some cases it works the first time then, the next day, it falls over.
Basically, I am importing spritesheets for a simply pygame game. With help, I wrote a small class which allows spritesheets to be imported and, through a few methods turns them into a list using the json file. That program is as follows:
import pygame
import json
pygame.init()
class Spritesheet:
def __init__(self, filename):
self.filename = filename
self.sprite_sheet = pygame.image.load(filename).convert()
self.data_addr = self.filename.replace('png', 'json')
with open(self.data_addr, encoding = 'utf8') as f:
self.data = json.load(f)
f.close()
def check_file(self):
print(self.data)
def get_sprite(self, x, y, w, h):
sprite = pygame.Surface((w, h))
sprite.set_colorkey((0,0,0))
sprite.blit(self.sprite_sheet,(0, 0),(x, y, w, h))
return sprite
def parse(self, index):
sprite = self.data['frames'][index]['frame']
x, y, w, h = sprite["x"], sprite["y"], sprite["w"], sprite["h"]
image = self.get_sprite(x, y, w, h)
return image
def dict_len(self):
length = len(self.data['frames'])
return length
This has worked fine in the main code. I have a player class, an enemy class etc and, upon initiallising, this class is called to create a list of pngs for the graphics (that I can step through etc.) A pertinent cut of the player class is as follows:
class Player(pygame.sprite.Sprite):
def __init__(self, player_posx, health):
super().__init__()
#right facing sprites
self.spritesr = Spritesheet('../graphics/player/players.png')
self.player_spritesr = []
for value in range(self.spritesr.dict_len()):
self.player_spritesr.append(self.spritesr.parse(value))
# left facing sprites
self.spritesl = Spritesheet('../graphics/player/playersl.png')
self.player_spritesl = []
for value in range(self.spritesl.dict_len()):
self.player_spritesl.append(self.spritesl.parse(value))
#static sprites
self.sprites_static = Spritesheet('../graphics/player/player_static.png')
self.player_static = []
for value in range(self.sprites_static.dict_len()):
self.player_static.append(self.sprites_static.parse(value))
self.image_index = 0
self.image = self.player_spritesr[self.image_index]
self.rect = self.image.get_rect()
In this class it works fine with the Spritesheets class. However, when I decided to create new file to import all the graphics in a separate file, I get the segmentation error. The code is simply:
from spritesheets import Spritesheet
test = Spritesheet('../graphics/player/playersl.png')
Calling exactly the same class with the same argument, but I get an error saying:
Fatal Python error: (pygame parachute) Segmentation Fault
Python runtime state: initialized
I really don't understand at all, especially why it runs fine in one file but falls over everywhere else.
The likely problem is that you are doing your import before you have called pygame.init(), so pygame has not been initialized.
Consider doing this in your second file:
from spritesheets import Spritesheet
def get_sprites():
return [
Spritesheet('../graphics/player/players.png'),
Spritesheet('../graphics/player/playersl.png'),
Spritesheet('../graphics/player/players_static.png')
]
Now you can put your import at the top, and call
sprites = xxx.get_sprites()
after you have initialized pygame.

Why "NameError: name 'draw_Objects' is not defined" occurs

I am making a small game using pygame.
I have defined a function called draw_Objects() but Name Error occurs as if I didn't define the function. What should I do?
The code is part of the module
I have tried to change the draw_Objects() function but I couldn't solve it.
import pygame
from const import *
class item(pygame.sprite.Sprite):
def __init__(self,game):
super().__init__()
self.game=game
#self.screen=screen
self.width=WIDTH
self.height=HEIGHT
#potion 사진 불러옴
self.image=pygame.image.load("tile/red-potion.png")
self.rect = self.image.get_rect()
self.red_potion=pygame.image.load("tile/red-potion.png")
self.blue_potion=pygame.image.load("tile/blue-potion.png")
self.mask=pygame.mask.from_surface(self.image)
self.rect = self.image.get_rect()
redItem=[50,530,300,50,850,100,600,280,800,400]
def __call__(self):
print (" ")
def item_display(self,screen):
#아이템 화면에 표시
screen.blit(self.red_potion,(50,530)) #red1
screen.blit(self.blue_potion,(30,530))
screen.blit(self.blue_potion,(30,460))
screen.blit(self.red_potion,(300,50)) #red2
screen.blit(self.blue_potion,(400,150))
screen.blit(self.image,(850,100)) #red3
screen.blit(self.red_potion,(600,280)) #red4
screen.blit(self.red_potion,(800,400)) #red5
screen.blit(self.blue_potion,(600,370))
def draw_Objects(myList=[]):
for i in myList:
x=myList[i]
y=myList[i+1]
screen.blit(self.red_potion,(x,y))
i+=1
def item_eat(self,screen):
item__=item(self)
#red2 item
self.rect.x=300
self.rect.y=50
#item과 player 충돌 검사
hits_item=pygame.sprite.spritecollide(self,self.game.player_group,False,pygame.sprite.collide_mask)
if hits_item :
screen.blit(self.red_potion,(50,530)) #red1
screen.blit(self.blue_potion,(30,530))
screen.blit(self.blue_potion,(30,460))
screen.blit(self.blue_potion,(400,150))
screen.blit(self.red_potion,(850,100)) #red3
screen.blit(self.red_potion,(600,280)) #red4
screen.blit(self.red_potion,(800,400)) #red5
screen.blit(self.blue_potion,(600,370))
else:
#item__.item_display(self.screen)
draw_Objects(redItem)
this line
draw_Objects(redItem)
is looking for a global function named draw_Objects which does not exist. you need to call
self.draw_Objects(redItem)
However, you would also need to include self as a parameter in the function definition like so
def draw_Objects(self, myList=[]):
draw_Objects is not a global function, it is an attribute of the class and can be called with self.
def item_eat(self,screen):
item__=item(self)
#red2 item
self.rect.x=300
self.rect.y=50
#item과 player 충돌 검사
hits_item=pygame.sprite.spritecollide(self,self.game.player_group,False,pygame.sprite.collide_mask)
if hits_item :
screen.blit(self.red_potion,(50,530)) #red1
screen.blit(self.blue_potion,(30,530))
screen.blit(self.blue_potion,(30,460))
screen.blit(self.blue_potion,(400,150))
screen.blit(self.red_potion,(850,100)) #red3
screen.blit(self.red_potion,(600,280)) #red4
screen.blit(self.red_potion,(800,400)) #red5
screen.blit(self.blue_potion,(600,370))
else:
#item__.item_display(self.screen)
self.draw_Objects(redItem) # Change this line to reference draw_Objects
It's rather simple.
def draw_Objects(self):
myList=[]
for i in myList:
x=myList[i]
y=myList[i+1]
screen.blit(self.red_potion,(x,y))
i+=1
Then call it like:
self.draw_Objects()

NameError: name "winroot" is not defined

I am building a calculator app, and I solved a lot of problems except this one. It is bigger than me to solve it, I tried nearly everything except 1 way that I am thinking of it right now is: making the program in one (.py) file.
My program is designed in Kivy and I made the app in two python files, so here is the problem: the main screen has several choices to open a new page, and that page must have a button that make the app gets back to the main screen, and this button did not work.
A variable has just disappeared magically .. called 'winroot'!
Here is the code (main.py):
class Base(App):
def build(self):
global winroot
winroot = TheMainScreen()
mnsc = MainScreen()
winroot.add_widget(mnsc)
return winroot
class TheMainScreen(FloatLayout):
def back(self, obj=1):
print('pressed')
winroot.clear_widgets()
winroot.add_widget(MainScreen())
class MainScreen(FloatLayout):
def __init__(self, **kwargs):
self.B1 = Button(text='Base Calculator\n\n\n', on_press=self.basecalc)
def basecalc(self, obj):
winroot.clear_widgets()
from calculator.basecalculator import BaseCalculator
winroot.add_widget(BaseCalculator())
and this is for the second python file (basecalculator.py):
class BaseCalculator(FloatLayout):
def __init__(self, **kwargs):
super(BaseCalculator, self).__init__(**kwargs)
self.B11 = Button(size_hint=(.08, .13), on_release=self.prev)
def prev(self, obj=1):
from calculator.main import TheMainScreen
a = TheMainScreen()
a.back()
and here is the Error that is showing up :
File "C:\Users\work\PycharmProjects\Kivy\calculator\basecalculator.py", line 95, in prev
a.back()
File "C:\Users\work\PycharmProjects\Kivy\calculator\main.py", line 26, in back winroot.clear_widgets()
NameError: name 'winroot' is not defined
since winroot is a global variable created inside a function, you have to declare it as global in every function you use it.
Or, you know, instead of global, set is as instance attribute and pass it around, then you don't need globals:
class Base(App):
def build(self):
self.winroot = TheMainScreen()
self.mnsc = MainScreen(self.winroot)
self.winroot.add_widget(self.mnsc)
return winroot
class TheMainScreen(FloatLayout):
def back(self, obj=1):
print('pressed')
self.clear_widgets()
self.add_widget(MainScreen())
class MainScreen(FloatLayout):
def __init__(self, winroot, **kwargs):
self.B1 = Button(text='Base Calculator\n\n\n', on_press=self.basecalc)
self.winroot = winroot
def basecalc(self, obj):
self.winroot.clear_widgets()
from calculator.basecalculator import BaseCalculator
self.winroot.add_widget(BaseCalculator())

Creating class objects in a function (python)

Currently I am exploring the possibilities of Pygame and have created a simple game and am now trying to neaten it up. I am trying to define new objects by using a class I have made in a function.
This is what I tried:
def CreateEnemy():
enemy1 = Enemies()
enemy2 = Enemies()
enemy3 = Enemies()
enemy1.getInstructions()
enemy2.getInstructions()
enemy3.getInstructions()
However when I try to use the object enemy1 it says it is not defined. From what I know the objects may be only local in the function. Does this mean that I have to somehow use the return function?
I am assuming you have a class called Enemies something like below
class Enemies:
def getInstructions():
return "instructions"
now want a method to create a bunch of enemies instances
def create_enemies(num_of_enemies):
enemies = []
for i in range(num_of_enemies):
enemies.append(enemy)
return enemies
and then use the above method to create enemies like this:
enemy1, enemy2 , enemy3 = create_enemies(3)
class Ins_Normal():
def getInstructions(self, *args):
return "GetInstructions_Normal"
class Ins_Agressive():
def getInstructions(self, *args):
return "GetInstructions_Agressive"
class Enemies(object):
def __init__(self, behaivor = 'Ins_Normal', mode = True, *args):
self.behaivor = behaivor
self.mode = mode
def getInstructions(self, *args):
#create instance based on behaivor
try:
ins = globals()[self.behaivor]() # same like ins = Ins_Agressive()
except KeyError as e:
raise NotImplementedError(e)
# return getInstructions() init value behaivor
return ins.getInstructions()
def xyz(self, *args):
# if True return worldspace position (eg)
if self.mode:
return "xyz"
return 'com_xyz'
def CreateEnemy(enemy = 0, behaivor = 'Ins_Normal', mode =True):
# wrapper function to collect Enemies
# create dict, so no hardcoded variabels, scalable....
data = dict((_id, Enemies(behaivor, mode)) for _id in range(enemy))
return data
# create groups of enemies
enemies_com_normal = CreateEnemy(3, 'Ins_Normal') #com
enemies_user_normal = CreateEnemy(3, 'Ins_Normal', True) #interactive
enemies_com_agressive = CreateEnemy(5, 'Ins_Agressive', True) #interactive
print enemies_com_normal
# we get dict of Enemy instances with id(int) as key
#>>> {0: <Enemies object at 0x7f2d8cfe5b10>, 1: <Enemies object at 0x7f2d8cfe5b50>, 2: <Enemies object at 0x7f2d8cfe5b90>}
#lets print some infos of the agents
print enemies_com_normal[0].xyz()
#>>>xyz
print enemies_com_normal[0].getInstructions()
#>>>GetInstructions_Normal
print enemies_com_agressive[2].getInstructions()
#>>>GetInstructions_Agressive
enemies_com_hgd = CreateEnemy(5, 'Ins_HGD', True) #interactive
print enemies_com_hgd[0].getInstructions()
#Traceback (most recent call last):
# File "python", line 56, in <module>
# File "python", line 21, in getInstructions
#NotImplementedError: 'Ins_HGD' <<<<< no Instruction Implemented for Ins_HGD
please include some code so that you can get better answer but no you don't require to write return function as you can see in my example.
class Enemies:
def getInstructions(self):
print("Instructions")
def createEnemy():
global allEnemy
allEnemy.append(Enemies())
allEnemy = []
createEnemy()
createEnemy()
for enemy in allEnemy :
enemy.getInstructions()

Calling class functions through list

I was attempting to place certain class variables within a list. Each class has a method known as update and considering they each do the exact same thing I though it would be allot more convenient to simply place them in a list and call the method that way.
The method I am trying to call is known as update and this is the error that I get:
Traceback (most recent call last):
File "C:\Users\GoodPie\Desktop\New Game Dev\main.py", line 177, in <module>
initialize_game()
File "C:\Users\GoodPie\Desktop\New Game Dev\main.py", line 61, in initialize_game
start_menu(debugging, screen, clock, image_cache)
File "C:\Users\GoodPie\Desktop\New Game Dev\main.py", line 88, in __init__
self.init_start_screen()
File "C:\Users\GoodPie\Desktop\New Game Dev\main.py", line 115, in init_start_screen
self.update_group.append[New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button]
TypeError: 'builtin_function_or_method' object is not subscriptable
Here is the code I am trying to use
Entities.py:
class Quit_Game_Button(Entity):
def __init__(self, x, y, image_cache):
Entity.__init__(self)
self.image_cache = image_cache
self.image = function.get_image("images/Quit_Game.png", self.image_cache)
self.image.convert()
self.rect = Rect(x, y, 150, 30)
def update(self, mouse_position):
if self.rect.collidepoint(mouse_position):
self.image = function.get_image("images/Quit_Game_Hover.png", self.image_cache)
else:
self.image = function.get_image("images/Quit_Game.png", self.image_cache)
def check_click(self, clicked, mouse_position):
quit = False
if self.rect.collidepoint(mouse_position):
if clicked:
quit = True
return quit
class Settings_Button(Entity):
def __init__(self, x, y, image_cache):
Entity.__init__(self)
self.image_cache = image_cache
self.image = function.get_image("images/Settings_Button.png", self.image_cache)
self.image.convert()
self.rect = Rect(x, y, 50, 50)
def update(self, mouse_position):
if self.rect.collidepoint(mouse_position):
self.image = function.get_image("images/Settings_Button_Hover.png", self.image_cache)
else:
self.image = function.get_image("images/Settings_Button.png", self.image_cache)
main.py
self.update_group.append[New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button]
mouse_position = pygame.mouse.get_pos()
#Updating Entities on the screen
for entity in self.update_group:
entity.update(mouse_position)
Just so it's clear, the functions do exist. I was just wondering if I was going about calling methods the write way through a list/array? If not could someone please point me in the right direction? :)
You are trying to assign one to one(1) and two to two(), that results in a referenced before assignment error So change the class Names to something more suitable like One and Two
Also It is strictly recommended(for CapWords convention see pg4 here) to always start a python class name with a uppercase character
Corrected code would look like: (I've implemented the str method)
class One:
def __init__(self, x):
self.x = x
def update(self):
self.x += 1
def __str__(self):
return str(self.x)
class Two:
def __init__(self, x):
self.x = x
def update(self):
self.x += 1
def __str__(self):
return str(self.x)
def test():
one = One(1)
two = Two(2)
update_list = [one, two]
for i in update_list:
i.update()
print i
test()
Output:
2
3
This is a simple error.
self.update_group.append[New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button]
should be
self.update_group.extend([New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button])
You're trying to index append where you should call it. Second point is, that append takes only one parameter, so you should use extend.
But you're still operating on the classes, not instances of the classes.
The issue did not lie within the actual for loop for calling the update function within the class, it occurred through the appending off the class instances to the list. Therefore to solve this problem I tried:
self.update_group = [New_Game_Button, Load_Game_Button, Quit_Game_Button, Settings_Button]
and it worked perfectly. I don't know what the issue is with the appending to the array, but having a fixed list/array seems to work just fine for me. Credits to #Matthias for actually making me look at the method for adding the instances to the array.

Categories