I'm working with animation in my game, but I've got an error.. Can you help me pls?)
Or do I need to add all of my code?
class Animation:
def __init__(self, x, y, sprites=None, time=100):
self.x = x
self.y = y
self.sprites = sprites
self.time = time
self.work_time = 0
self.skip_frame = 0
self.frame = 0
def update(self, dt):
self.work_time += dt
self.skip_frame = self.work_time // self.time
if self.skip_frame > 0:
self.work_time = self.work_time % self.time
self.frame += self.skip_frame
if self.frame >= len(self.sprites):
self.frame = 0
def get_sprite(self):
return self.sprites[self.frame]
Traceback (most recent call last):
File "C:\Users\Zyzz\Desktop\game\bin.py", line 210, in <module>
target.update(dt)
File "C:\Users\Zyzz\Desktop\game\bin.py", line 98, in update
self.skip_frame = self.work_time // self.time
TypeError: unsupported operand type(s) for //: 'int' and 'module'
What I can see in your code it is nothing related to code in python2/python3.
Here self.time = time , time seems to be the imported module.
You are trying self.skip_frame = self.work_time // self.time where self.work_time is initialized with 0 earlier in def __init__(...)
It is trying to do operation between int(0) and a module(time) which is not acceptable.
But as per your question header if you want your code to migrate from python2.x to python3.x compatible there is a package available 2to3
You can install 2to3 using python-tools
$ 2to3 example.py
$ 2to3 -w example.py # -w for write the changes back to file
Related
I'm creating FPS game with Ursina Engine (python). But I started to get a error whenever I tried to play it.
I just started coding so I don't know what I should do.
Code:
from ursina import *
from ursina.prefabs.first_person_controller import *
class Player(Entity):
def __init__(self, **kwargs):
self.controller = FirstPersonController(**kwargs)
super().__init__(parent=self.controller)
self.hand_gun = Entity(parent=self.controller.camera_pivot, scale=0.1, position=Vec3(0.7, -1, 1.5), rotation=Vec3(0, 170, 0), model='gun', Texture='M1911-RIGHT', visible=False)
self.knife = Entity(parent=self.controller.camera_pivot, scale=0.4, position=Vec3(0.7, -1, 1.5), rotation=Vec3(0, 170, 0), model='knife', Texture='knife', visible=False)
self.weapons = [self.hand_gun, self.knife]
self.current_weapon = 0
self.switch_weapons()
def switch_weapon(self):
for i, v in enumerate(self.weapons):
if i == self.current_weapon:
v.visible = True
else:
v.visible = False
def input(self, key):
try:
self.current_weapon = int(key) - 1
self.switch_weapon()
except ValueError:
pass
if key == 'scroll up':
self.current_weapon = (self.current_weapon + 1) % len(self.weapons)
self.switch_weapon()
if key == 'scroll down':
self.current_weapon = (self.current_weapon - 1) % len(self.weapons)
self.switch_weapon()
if key == 'left_mouse_down' and self.current_weapon == 0:
Bullet(model='sphere', color=color.black, scale=0.2, position=self.controller.camera_pivot.world_position, rotation=self.controller.camera_pivot.world_rotation)
def update(self):
self.controller.camera_pivot.y = 2 - held_keys['left control']
class Bullet(Entity):
def __init__(self, speed=50, lifetime = 10, **kwargs):
super().__init__(**kwargs)
self.speed = speed
self.lifetime = lifetime
self.start = time.time()
def update(self):
ray = raycast(self.world_position, self.forward, distance=self.speed*time.dt)
if not ray.hit and time.time() - self.start < self.lifetime:
self.world_position += self.forward * self.speed * time.daylight
else:
destroy(self)
app = Ursina
ground = Entity(model='plane', scale=20, texture='white_cube', texture_scale='mesh')
player = Player(position=(0,10,0))
app.run()
It's just small shooting game that I made for learning Ursina Engine
and the error message I got was:
package_folder: C:\Users\Yunwoo Chang\AppData\Roaming\Python\Python310\site-packages\ursina
asset_folder: c:\Users\Yunwoo Chang\Desktop\Tetris\Ursina Engine
Exception ignored in: <function Texture.__del__ at 0x000001E55A5129E0>
Traceback (most recent call last):
File "C:\Users\Yunwoo Chang\AppData\Roaming\Python\Python310\site-packages\ursina\texture.py", line 185, in __del__ del self._cached_image
AttributeError: _cached_image
Traceback (most recent call last):
File "c:\Users\Yunwoo Chang\Desktop\Tetris\Ursina Engine\03 - Weapons.py", line 71, in <module>
player = Player(position=(0,10,0))
File "c:\Users\Yunwoo Chang\Desktop\Tetris\Ursina Engine\03 - Weapons.py", line 6, in __init__
self.controller = FirstPersonController(**kwargs)
File "C:\Users\Yunwoo Chang\AppData\Roaming\Python\Python310\site-packages\ursina\prefabs\first_person_controller.py", line 32, in __init__
ray = raycast(self.world_position+(0,self.height,0), self.down, ignore=(self,))
File "C:\Users\Yunwoo Chang\AppData\Roaming\Python\Python310\site-packages\ursina\entity.py", line 433, in world_position
return Vec3(self.get_position(render))
NameError: name 'render' is not defined
How can I fix it?
I think it's some kind of attribute error but I don't know what to do.
You should instantiate Ursina with app = Ursina() before instantiating Entities. You're missing the ().
So after getting inspired by code bullet to try out pyglet. Recently I have been creating many small games and simulations with it. The current one being a game is a flappy bird(Pretty sure you've all played that). So my mission is to code flappybird with pyglet today. But as usual, I fell into a problem, and even though there were many questions and answers for this problem as I was using pyglet all of the other answers weren't working.
The code I have written for the flappy bird is pretty straightforward. I have 2 classes the bird and the pipe and I render all of them using batches and groups. here:
import math, sys
import pyglet, random
from pyglet.window import key, mouse
window = pyglet.window.Window(width=335, height=540, caption="FLAPPY BIRD!")
batch = pyglet.graphics.Batch()
background = pyglet.graphics.OrderedGroup(0)
pipes = pyglet.graphics.OrderedGroup(1)
foreground = pyglet.graphics.OrderedGroup(2)
player = pyglet.graphics.OrderedGroup(3)
bg = pyglet.image.load("background.png")
background_1 = pyglet.sprite.Sprite(bg, 0, 0, batch=batch, group=background)
background_2 = pyglet.sprite.Sprite(bg, bg.width, 0, batch=batch, group=background)
base = pyglet.image.load("base.png")
base_1 = pyglet.sprite.Sprite(base, 0, 0, batch=batch, group=foreground)
base_2 = pyglet.sprite.Sprite(base, base.width, 0, batch=batch, group=foreground)
bird_image = pyglet.image.load("yellowbird-midflap.png")
bird_image.anchor_x = bird_image.width // 2
bird_image.anchor_y = bird_image.height // 2
class Bird:
def __init__(self):
self.charector = \
pyglet.sprite.Sprite(bird_image, window.width * 0.2, window.height/2, batch=batch, group=player)
self.y_speed = 0
self.rotation_vel = 0
self.alive = True
def update(self):
self.y_speed -= 0.6
self.rotation_vel += 1
self.charector.y += self.y_speed
self.charector.rotation = min(self.rotation_vel, 90)
def jump(self):
self.y_speed = 7 * 1.5
self.rotation_vel = -35
bird_image = pyglet.image.load("yellowbird-midflap.png")
class Pipe:
tp = pyglet.image.load("down-pipe.png")
bp = pyglet.image.load("pipe.png")
def __init__(self):
self.top_pipe = pyglet.sprite.Sprite(self.tp, x = window.width + 100, y = random.randint(325, 484), batch=batch, group=pipes)
self.bottom_pipe = pyglet.sprite.Sprite(self.bp, x = window.width + 100, y = self.top_pipe.y - 125 - self.bp.height, batch=batch, group=pipes)
def update(self):
self.top_pipe.x -= 3
self.bottom_pipe.x -= 3
bird = Bird()
pipes = [Pipe()]
time_created_pipe = 50
def update_char(dt):
global time_created_pipe, pipes
if bird.alive:
bird.update()
for pipe in pipes:
pipe.update()
if pipe.top_pipe.x <= -100:
pipes.remove(pipe)
if time_created_pipe <= 0:
time_created_pipe = 50
pipes.append(Pipe())
time_created_pipe -= 1
def update_bg(dt):
if bird.alive:
background_1.x -= 0.5
background_2.x -= 0.5
if background_1.x <= -bg.width:
background_1.x = bg.width
if background_2.x <= -bg.width:
background_2.x = bg.width
base_1.x -= 1.5
base_2.x -= 1.5
if base_1.x <= -base.width:
base_1.x = base.width
if base_2.x <= -base.width:
base_2.x = base.width
#window.event
def on_mouse_press(x, y, button, modifiers):
if button == mouse.LEFT:
bird.jump()
#window.event
def on_draw():
window.clear()
batch.draw()
pyglet.clock.schedule_interval(update_char, 1/60)
pyglet.clock.schedule_interval(update_bg, 1/60)
pyglet.app.run()
But the second I run the code this happens:
back (most recent call last):
File "c:\Users\Tejas&Shiva\OneDrive\Desktop\HTCODEATHON PYTHON PRACTICE\Day4\flappy bird.py", line 105, in <module>
pyglet.app.run()
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\app\__init__.py", line 107, in run
event_loop.run()
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\app\base.py", line 169, in run
timeout = self.idle()
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\app\base.py", line 239, in idle
redraw_all = self.clock.call_scheduled_functions(dt)
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\clock.py", line 292, in call_scheduled_functions
item.func(now - item.last_ts, *item.args, **item.kwargs)
File "c:\Users\Tejas&Shiva\OneDrive\Desktop\HTCODEATHON PYTHON PRACTICE\Day4\flappy bird.py", line 73, in update_char
pipes.append(Pipe())
File "c:\Users\Tejas&Shiva\OneDrive\Desktop\HTCODEATHON PYTHON PRACTICE\Day4\flappy bird.py", line 50, in __init__
self.top_pipe = pyglet.sprite.Sprite(self.tp, x = window.width + 100, y = random.randint(325, 484), batch=batch, group=pipes)
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\sprite.py", line 246, in __init__
self._create_vertex_list()
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\sprite.py", line 391, in _create_vertex_list
self._vertex_list = self._batch.add(
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\graphics\__init__.py", line 366, in add
domain = self._get_domain(False, mode, group, formats)
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\graphics\__init__.py", line 443, in _get_domain
self._add_group(group)
File "C:\Users\Tejas&Shiva\AppData\Local\Programs\Python\Python310\lib\site-packages\pyglet\graphics\__init__.py", line 468, in _add_group
if group.parent not in self.group_map:
TypeError: unhashable type: 'list'
My guess is there is a problem with the pipes list but I'm not sure why. Is there any solution to this?
The problem is that the name pipes is used twice. First is used for the OrderedGroup of pipes. In this group, the initial pipe batches are added:
pipes = pyglet.graphics.OrderedGroup(1)
However, it is then used for a list of pipes. The original group pipes is shadowed by the list of pipes and creating a new Pipe object fails:
pipes = [Pipe()]
Use different names for the group and the list. Rename list:
pipes_list = [Pipe()]
time_created_pipe = 50
def update_char(dt):
global time_created_pipe, pipes_list
if bird.alive:
bird.update()
for pipe in pipes_list:
pipe.update()
if pipe.top_pipe.x <= -100:
pipes_list.remove(pipe)
if time_created_pipe <= 0:
time_created_pipe = 50
pipes_list.append(Pipe())
time_created_pipe -= 1
I want to make a simple physical game with balls on Python using pygame and Box2D, but when I try to get the speed of the ball using a well-known method, I get this error. What might be the problem?
class Ball:
def __init__(self, x, y, radius, world, color, fric=0.3, maxspeed=20, density=0.01, restitution=0.5):
self.x = x
self.y = y
self.radius = radius
self.fric = fric
self.maxspeed = maxspeed
self.density = density
self.restitution = restitution
self.color = color
#body
self.bodyDef = box2d.b2BodyDef()
self.bodyDef.type = box2d.b2_dynamicBody
self.bodyDef.position = (x, y)
self.body = world.CreateBody(self.bodyDef)
#shape
self.sd = box2d.b2CircleShape()
self.sd.radius = radius
#fixture
self.fd = box2d.b2FixtureDef()
self.fd.shape = self.sd
#phys params
self.fd.density = density
self.fd.friction = fric
self.fd.restitution = restitution
self.body.CreateFixture(self.fd)
player = Ball(width / 3, height / 2, 30, world, (150, 150, 150))
v = player.body.GetLinearVelocity()
The Error:
Traceback (most recent call last):
File "D:\projs\box2d\bonk\main.py", line 60, in <module>
keyIsDown(pygame.key.get_pressed())
File "D:\projs\box2d\bonk\main.py", line 35, in keyIsDomn
v = player.body.GetLinearVelocity()
AttributeError: 'b2Body' Object has no attribute 'GetLinearVelocity'
screenshot of error
It looks like the GetLinearVelocity method is only available in the C library. The Python wrapper just uses linearVelocity:
v = player.body.linearVelocity
For the future, if you want to know what the variable type is and what methods\properties are available, you can use the type and dir functions:
print(type(player.body)) # class name # <class 'Box2D.Box2D.b2Body'>
print(dir(player.body)) # all methods and properties # ['ApplyAngularImpulse', 'ApplyForce',....,'linearVelocity',...]
I was doing in a project where i have to take values from two subscribers then fulfill some conditions and then publish data. Im using classes to values for the two subscribers. However, whenever In the attribute move_bot i call self.ranges and self.linear_pose which should work as they have been set when the code subscribed to them. However, i have to call the move_bot attribute within the laser_callback to make it work but now it only recognizes the self.ranges and not the self.linear_pose. If i do place the move_bot in the odom_callback the same thing happens but with self.linear_pose. Why are the callbacks not working?
import rospy
import math
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist
from nav_msgs.msg import Odometry
class Move(object):
def __init__(self):
rospy.init_node('robot_maze')
rospy.Subscriber('/kobuki/laser/scan',LaserScan,self.laser_callback)
rospy.Subscriber('/odom',Odometry,self.odom_callback)
self.pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
self.twist_angle = Twist()
def laser_callback(self,msg):
self.ranges = msg.ranges
def odom_callback(self,msg):
self.linear_pose = msg
def move_bot(self):
pi = math.pi
kp = -0.027
val =[]
if self.linear_pose.twist.twist.linear.x < 0.001:
self.twist_angle.linear.x = -0.2
for i in self.ranges:
if i <= 0.6:
if self.ranges.index(i) > 360:
self.twist_angle.angular.z = 1
else:
self.twist_angle.angular.z = -1
break
elif self.ranges[360] > 1.2:
self.twist_angle.angular.z = 0
self.twist_angle.linear.x = 0.5
else:
for i in self.ranges:
if i > 1.2:
val.append(i)
angle = self.ranges.index(max(val))
print(max(val))
if self.ranges[angle] > self.ranges[360]:
self.twist_angle.angular.z = kp * (360 - angle)
self.pub.publish(self.twist_angle)
if __name__== '__main__':
try:
move = Move()
move.move_bot()
rate = rospy.Rate(10)
except rospy.ROSInterruptException: pass
while not rospy.is_shutdown():
rate.sleep()
I get the following error message
Traceback (most recent call last):
File "/home/user/catkin_ws/src/robot_maze/src/robot_maze.py", line 100, in <module>
move.move_bot()
File "/home/user/catkin_ws/src/robot_maze/src/robot_maze.py", line 45, in move_bot
if self.ranges[360] > 1.2:
AttributeError: 'Move' object has no attribute 'ranges'
[robot_maze-1] process has died [pid 16344, exit code 1, cmd
/home/user/catkin_ws/src/robot_maze/src/robot_maze.py
__name:=robot_maze __log:=/home/user/.ros/log/e4216cee-9f0e-11ea-9fd8-06b6df32753c/robot_maze-
1.log].
log file: /home/user/.ros/log/e4216cee-9f0e-11ea-9fd8-06b6df32753c/robot_maze-1*.log
To point out what #a_guest said in the comments:
class Move(object):
def __init__(self):
...
self.ranges = None
self.linear_pose = None
...
def move_bot(self):
if self.ranges is not None and self.linear_pose is not None:
if self.linear_pose.twist.twist.linear.x < 0.001:
...
elif self.ranges[360] > 1.2:
...
else:
...
self.pub.publish(self.twist_angle) # Don't publish until received initial values
I know that something very basic is wrong here which I just fail to see. I'd really appreciate if somebody more experienced in Python could point out where I misunderstood things here. I post a simplified version of my code below. To trace back where the problems start, have an eye on the following:
The MainProgram, instanciated as Main = MainProgram(), has a menu (self.menu = Startmenu()) which is an instance of the Menu class. This Menu class has a list of buttons (self.buttons = [...]) - in this case only one. They are an instance of the Button class. I now need to pass the function to be triggered when the button is clicked to that instance of the Button class, so I can actually use it.
I would really be thankful to any more experienced user having a quick glance at it. I'm sure I'm failing to see something very basic. I bet I'm too tired to see it... Had only some 2 hours sleep since there's a baby in the house now :D
My code:
class MainProgram:
#Much much more code
def __init__(self):
#And so much more code here
self.menu = StartMenu()
class StartMenu:
def __init__(self):
#Much code which is not important to us here
self.buttons = [Button("d_bt_start", (100, 60)
, testfunc, "TEST-TEXT")]
class Button:
def __init__(self, image, pos = (0, 0), path = Paths.path_img
, alpha = False, func = None, args = None):
self.img_normal = helper.loadImage(path, image + "_normal.jpg", alpha)
self.img_hover = helper.loadImage(path, image + "_hover.jpg", alpha)
self.image = self.img_normal
self.pos = pos
self.x = pos[0]
self.y = pos[1]
self.width = self.x + self.image.get_width()
self.height = self.y + self.image.get_height()
self.mouseover = 0
self.func = func
self.args = args
def update(self, (mx, my)):
if (mx >= self.x and mx <= self.width and
my >= self.y and my <= self.height):
if self.mouseover == 0:
self.image = self.img_hover
self.mouseover = 1
else:
if self.mouseover == 1:
self.image = self.img_normal
self.mouseover = 0
def clicked(self, button):
if (mx >= self.x and mx <= self.width and
my >= self.y and my <= self.height):
if button == 1:
self.func(self.args)
What should happen: The main file creates an instance of the StartMenu class. In the StartMenu class we define one button as an instance of the Button class. That button should trigger the function testfunc(args) upon being clicked. This testfunction is so far just a print of the "TEST-TEXT" argument.
If I pass the function as
testfunc
then I get the following error Traceback:
Traceback (most recent call last):
File "D:\Python27\_RPG DEMO\DEMO\main.py", line 41, in <module>
Main = MainProgram()
File "D:\Python27\_RPG DEMO\DEMO\main.py", line 21, in __init__
self.menu = menus.StartMenu()
File "D:\Python27\_RPG DEMO\DEMO\menus.py", line 11, in __init__
, zztestfile.testfunc, "TESTEST")
File "D:\Python27\_RPG DEMO\DEMO\buttons.py", line 7, in __init__
self.img_normal = helper.loadImage(path, image + "_normal.jpg", alpha)
File "D:\Python27\_RPG DEMO\DEMO\helper.py", line 13, in loadImage
return pygame.image.load(os.path.join(folder, name)).convert_alpha()
File "D:\Python27\lib\ntpath.py", line 96, in join
assert len(path) > 0
TypeError: object of type 'function' has no len()
If I pass it as:
testfunc("TEST-TEXT")
it triggers but then causes the following Traceback:
TEST-TEXT
Traceback (most recent call last):
File "D:\Python27\_RPG DEMO\DEMO\main.py", line 41, in <module>
Main = MainProgram()
File "D:\Python27\_RPG DEMO\DEMO\main.py", line 21, in __init__
self.menu = menus.StartMenu()
File "D:\Python27\_RPG DEMO\DEMO\menus.py", line 11, in __init__
, testfunc("TEST-TEXT"))
File "D:\Python27\_RPG DEMO\DEMO\buttons.py", line 7, in __init__
self.img_normal = helper.loadImage(path, image + "_normal.jpg", alpha)
File "D:\Python27\_RPG DEMO\DEMO\helper.py", line 15, in loadImage
return pygame.image.load(os.path.join(folder, name)).convert()
File "D:\Python27\lib\ntpath.py", line 96, in join
assert len(path) > 0
TypeError: object of type 'NoneType' has no len()
I've gone through a few tutorials so far, but I really can't figure out where I'm misunderstanding them. I'd really appreciate any help in this!
You are passing your test function to the path argument of your Button class:
self.buttons = [Button("d_bt_start", (100, 60)
, testfunc, "TEST-TEXT")]
That's the 3rd positional argument there:
def __init__(self, image, pos = (0, 0), path = Paths.path_img
, alpha = False, func = None, args = None):
matching up with path. Use keyword arguments instead:
self.buttons = [Button("d_bt_start", (100, 60)
, func=testfunc, args="TEST-TEXT")]