I'm trying to run my program:
from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
app = Ursina()
window.fullscreen = True
class Voxel(Button):
def __init__(self, colour, position = (0, 0, 0)):
super().__init__(
parent = scene,
position = position,
model = "cube",
orgin_y = 0.5,
texture = "white_cube",
color = colour,
)
def start_game(self):
self.colour = color.white
def input(self, key):
if self.hovered:
if key == "right mouse up":
voxel = Voxel(position = self.position + mouse.normal, colour = self.colour)
if key == "left mouse up":
destroy(self)
if key == "0":
self.colour = color.white
if key == "1":
self.colour = color.lime
for z in range(22):
for x in range(22):
voxel = Voxel(position = (x, 0, z), colour = color.lime)
voxel.start_game()
player = FirstPersonController()
app.run()
I'm using python 3.10.6 and Idle.
When I run the program it works as expected except when I choose green after I place a block it turn into white. If I spam click I get the error:
File "C:\Users\game.py", line 24, in input
voxel = Voxel(position = self.position + mouse.normal, colour = self.colour)
AttributeError: 'Voxel' object has no attribute 'colour'
This code appears to be using both color and colour in multiple places.
It looks like the ursina library uses the color form.
I would suggest using color everywhere in your code to stay consistent with the library you are using. It will be harder to maintain if you need to translate between spellings and remember which version is used in which place.
Additionally, even though their examples may use from ursina import *, it is not the best practice to do so because it makes it unclear what names are available in the namespace. It would be better to explicitly do from ursina import Ursina, Button, window.
You are using colour instead of color when using self.colour and also when calling Voxel.
You should do:
voxel = Voxel(position = self.position + mouse.normal, colour = self.color)
And:
self.color = color
The solution is to replace colour with color in your code.
Related
I am trying to make minecraft in ursina but whenever I run it, it says:
TypeError: Voxel.__init__() got an unexpected keyword argument 'position'
This is my code
from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
app = Ursina()
player = FirstPersonController()
Sky()
block = load_model('block.obj')
grass_texture = load_texture('grass_block.png')
class Voxel(Button):
def __init__(self, positon = (0,0,0)):
super().__init__(
parent = scene,
position = position,
model = block,
origin_y = 0.5,
texture = grass_texture,
color = color.color(0,0,random.uniform(0.9, 1)),
highlight_color = color.lime)
def input(self, key):
if self.hovered:
if key == 'left mouse down':
voxel = Voxel(position = self.position + mouse.normal)
if key == 'right mouse down':
destroy(self)
for z in range(20):
for x in range(20):
voxel = Voxel(position = (x,0,z))
app.run()
There's a typo in Voxel's initializer declaration:
def __init__(self, positon = (0,0,0)):
You have positon (instead of position).
Correct that, and you should be fine:
def __init__(self, position=(0, 0, 0)):
from ursina import *
#preloads a cube
class Voxel(Button):
def __init__(self):
super().__init__(self, position = (0,0,0))(
parent = scene,
position = position,
model = 'cube',
origin_y = 0.5,
texture = 'white_cube',
color = color.white,
highlight_color = color.lime)
app = Ursina()
#loads a cube
for z in range(8):
for x in range(8):
Voxel = Voxel(position = (x,0,z))
app.run()
the error is here please help me:
File "D:\project\game.py", line 18, in <module>
Voxel = Voxel(position=(x,0,z)) TypeError: Voxel.__init__() got an unexpected keyword argument 'position'
so what I'm trying to do with this code is make cubes
You likely copy-pasted to the wrong place.
For example, this part of your super call (self, position = (0,0,0)), was probably intended for your class __init__ method.
def __init__(self, position = (0,0,0)):
Moving that makes your class functional.
class Voxel(Button):
def __init__(self, position = (0,0,0)):
super().__init__(
parent = scene,
position = position,
model = 'cube',
origin_y = 0.5,
texture = 'white_cube',
color = color.white,
highlight_color = color.lime)
You also need to change the name of your class instance at Voxel = Voxel(position = (x,0,z)) from Voxel to something else. As it stands, anything after the first loop would refer to an instance of Voxel and not the class itself.
Full working code:
from ursina import *
#preloads a cube
class Voxel(Button):
def __init__(self, position):
super().__init__(
parent = scene,
position = position,
model = 'cube',
origin_y = 0.5,
texture = 'white_cube',
color = color.white,
highlight_color = color.lime)
app = Ursina()
#loads a cube
for z in range(8):
for x in range(8):
voxel = Voxel(position = (x,0,z))
app.run()
I was working with "Ursina Engine"
My project is to make a copy of Minecraft, then I found out a problem that every time I run the program
and when I want to right-click to place a block, nothing happens.
Thanks to someone who can help me find the issue and tell me how to fix it * Here is my Code:*
from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
class Vovel(Button):
def __init__(self, position = (0,0,0)):
super().__init__(
parent=scene,
position=position,
model='cube',
origin_y = 0.5,
texture= 'white_cube',
color= color.white,
highlight_color = color.lime,
)
def Input(self, key):
if self.hovered:
if key == 'left mouse down':
vovel = Vovel(position= self.position + mouse.normal)
if key == 'right mouse down':
destroy(self)
app = Ursina()
for z in range(8):
for x in range(8):
vovel = Vovel(position= (x,0,z))
player = FirstPersonController()
app.run()
End.
The name of the input function is wrong. Input should be input
The input function should be input and not Input, rest of the code is absolutely correct. So, your code should be:
from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
class Vovel(Button):
def __init__(self, position=(0, 0, 0)):
super().__init__(
parent=scene,
position=position,
model='cube',
origin_y=0.5,
texture='white_cube',
color=color.white,
highlight_color=color.lime,
)
def input(self, key):
if self.hovered:
if key == 'left mouse down':
vovel = Vovel(position=self.position + mouse.normal)
if key == 'right mouse down':
destroy(self)
app = Ursina()
for z in range(8):
for x in range(8):
vovel = Vovel(position=(x, 0, z))
player = FirstPersonController()
app.run()
This code works, you can place a block with left click and remove a block with right click!
You only have to replace left mouse down with right mouse down and right mouse down with left mouse down, but I'm using this code for "Minecraft":
`
from ursina.prefabs.first_person_controller import *
app=Ursina()
FirstPersonController()
Sky()
def voxel(position:Vec3):
Voxel=Entity(model="assets/block.obj", position=position, collider="box", texture="assets/sand_block.jpg",origin_y=0.5,scale=0.5,on_click=lambda:destroy(Voxel))
for x in range(20):
for z in range(20):
voxel(position=Vec3(x,0,z))
def input(key):
if key=="right mouse down":
vox=voxel(position=Vec3(round(mouse.world_point.x),ceil(mouse.world_point.y),round(mouse.world_point.z)))
app.run()`
Ah now I'm understanding your problem, you have to change input to Input, the rest is fine.🙂
I have a pygame Sprite which is generated through Font. It's just a 16x16 surface with a letter printed on it and blitted.
The sprite has a timer (it's a powerup) and when it's near the end of it's life I want it to flash a random color on every update. I've been successful doing this with other text but that text isn't a sprite, just a string I blit to the score board. I figured this would be the same, but once the sprite is generated, no matter how much I change the sprite's color, the change doesn't translate to the screen (though if I print(self.color) I can see the updated color tuple in the console).
I've tried putting the random color picker inside the Class as well as trying outside the class in my while loop. I can change the color easily enough, but the sprite on screen doesn't actually change. I am not using an external sprite image, just a Font blitted to a pygame.Surface.
This is my item class.
class Item(pygame.sprite.Sprite):
def __init__(self, name, pos):
pygame.sprite.Sprite.__init__(self)
self.name = name
self.image = pygame.Surface([16, 16])
self.image.set_colorkey(black)
self.font = pygame.font.Font("./fonts/myfont.ttf", 16)
self.pos = pos
if self.name == "health":
self.color = (255, 0, 0)
self.text = self.font.render("H", True, self.color)
self.lifespan = 200
self.lifespan_counter = 0
self.image.blit(self.text, (0, 0))
def update(self):
# Update timer
self.lifespan_counter += 0.1
if self.lifespan_counter >= self.lifespan:
self.kill()
# Update position
self.rect.center = (int(self.pos[0]), int(self.pos[1]))
And then at the bottom of my def main() in the while loop, I have this stuff:
random_color_counter += 1
if random_color_counter > 3:
random_color = get_random_color()
random_color_counter = 0
screen.fill(background)
text_box.fill(blue)
game_box.fill(white)
# Update the sprites positions and then draw them to game_box surface
player_sprites.update()
player_bullet_sprites.update()
enemy_sprites.update()
enemy_bullet_sprites.update()
item_sprites.update()
player_sprites.draw(game_box)
player_bullet_sprites.draw(game_box)
enemy_sprites.draw(game_box)
enemy_bullet_sprites.draw(game_box)
item_sprites.draw(game_box)
...
for i in item_sprites:
game_box.blit(i.image, (int(i.pos[0]), int(i.pos[1])))
# Refresh everything
pygame.display.update()
And this is the function that picks a new color.
def get_random_color():
r = random.randint(0, 255)
g = random.randint(0, 255)
b = random.randint(0, 255)
return r, g, b
And then I can use the color random_color for most things, just not sprites apparently.
Like I said, this displays the sprite just fine at the position it is supposed to (where the baddie died), but I cannot seem to have a change to the item sprites color translate to the screen. I'm just not seeing what I'm doing wrong.
When you want to change the color of the text, you have to render the text again and update the text Surface. Write a change_color method:
class Item(pygame.sprite.Sprite):
# [...]
def change_color(self, color):
self.image = pygame.Surface([16, 16])
self.image.set_colorkey(black)
self.color = color
self.text = self.font.render("H", True, self.color)
self.image.blit(self.text, (0, 0))
I'm trying to make a simple application with pyglet. My main problem so far is that I can't seem to blit an image with alpha - all of the transparent pixels are converted into black pixels. I'm not sure whether the problem is with the loading of the image or the blitting. Here is a very basic overview of how I'm trying to render the image:
import pyglet
import pyglet.clock
window = pyglet.window.Window()
window.config.alpha_size = 8
#fancy text
text = pyglet.resource.image("text.png")
#background image
bg = pyglet.resource.image("bg.png")
bg.blit(0, 0)
text.blit(100, 100)
pyglet.app.run()
Any help is appreciated. Thanks in advance.
You most likely just need to enable GL ALPHA blends.
from pyglet.gl import *
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
But first of all, your code is not able to run.
Mostly because you don't declare a window.event function to handle the on_draw where you normally render things.
Secondly, you never clear your window (which will cause a mess).
Here's a minimal working example of your code:
import pyglet
import pyglet.clock
window = pyglet.window.Window()
window.config.alpha_size = 8
#fancy text
text = pyglet.resource.image("text.png")
#background image
bg = pyglet.resource.image("bg.png")
#window.event
def on_draw():
window.clear()
bg.blit(0, 0)
text.blit(100, 100)
pyglet.app.run()
Now this generates this:
And here's a working example of how you use the GL_BLEND feature:
import pyglet
import pyglet.clock
from pyglet.gl import *
window = pyglet.window.Window()
window.config.alpha_size = 8
#fancy text
text = pyglet.resource.image("text.png")
#background image
bg = pyglet.resource.image("bg.png")
#window.event
def on_draw():
window.clear()
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
bg.blit(0, 0)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
text.blit(100, 100)
pyglet.app.run()
This yields a result like so:
However, this code will quickly become messy.
So there's two things you can do. You can first, put your images into sprite objects. Secondly, make this a bit more object oriented.
First, we'll use sprites.
self.fancy_background = pyglet.sprite.Sprite(pyglet.image.load('bg.png'))
self.fancy_background.draw() # not blit!
Sprites automatically uses transparency, which makes your life (and code) a lot easier.
Secondly, we'll put these into a batch.
Batches are made to bunch A LOT of sprites so you can call .draw() on the batch, and all sprites in that batch gets insta-rendered.
self.background = pyglet.graphics.Batch()
self.fancy_background = pyglet.sprite.Sprite(pyglet.image.load('bg.png'), batch=self.background)
self.background.draw() # background, not fancy_background! And also not blit!!
Last and most certainly not least.
We'll put this into a class so we can do cool stuff later on.
import pyglet
import pyglet.clock
from pyglet.gl import *
key = pyglet.window.key
class main(pyglet.window.Window):
def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
super(main, self).__init__(width, height, *args, **kwargs)
self.x, self.y = 0, 0
self.background = pyglet.graphics.Batch()
self.texts = pyglet.graphics.Batch()
self.fancy_background = pyglet.sprite.Sprite(pyglet.image.load('bg.png'), batch=self.background)
self.fancy_text = pyglet.sprite.Sprite(pyglet.image.load('text.png'), batch=self.texts)
self.mouse_x = 0
self.mouse_y = 0
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_mouse_motion(self, x, y, dx, dy):
self.mouse_x = x
self.mouse_y = y
def on_mouse_press(self, x, y, button, modifiers):
if button == 1: # Left click
pass
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
def render(self):
self.clear()
self.background.draw()
self.texts.draw()
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main()
x.run()
BAM.
This code will enable you to create custom functions and custom "player objects" later on for instance. Also you can do collision detection easier and the code just looks a lot more structured (I threw in a little bonus features such as keyboard and mouse events).
Note tho, that the position of the sprites will default to x=0, y=0 as shown in the last picture. You can set the position with x=100 either on the variable/handle or when creating the sprite.