I have a problem with my python Minecraft copy - python

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.🙂

Related

Python class Attribute Error even though attribute is in __init__

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.

Error: TypeError: Voxel.__init__() got an unexpected keyword argument 'position'

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)):

How can I restart the game by pressing "r"?

My plans are to restart the game / reset the character to the middle of the map.
import keyboard as kb
from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
app = Ursina()
window.fps_counter.enabled = False
player = FirstPersonController()
Sky()
boxes = []
def random_color():
red = random.Random().random() * 20
green = random.Random().random() * 255
blue = random.Random().random() * 20
return color.rgb(red, green, blue)
def add_box(position):
boxes.append(
Button(
parent=scene,
model='cube',
origin=0.5,
color=random_color(),
position=position,
texture='grass'
)
)
for x in range(20):
for y in range(20):
add_box( (x, 0, y) )
def input(key):
for box in boxes:
if box.hovered:
if key == "right mouse down":
add_box(box.position + mouse.normal)
if key == "left mouse down":
boxes.remove(box)
destroy(box)
if kb.is_pressed("escape"):
exit()
if kb.is_pressed("shift"):
player.speed = 15
else:
player.speed = 7
app.run()
I can´t find help for this issue in the whole world of the internet. Please help me.
What do you mean with reset? Reset the hole game or just the player position?
To reset player position you can do something like this:
from ursina import *
app = Ursina()
# Change this to whatever your player is. In your case First person controller
player = Entity(model = 'cube')
player_reset_position = (0,0,0)
def input(key):
if key == 'r':
player.position = player_reset_position
app.run()
Your code with some fixes:
from ursina import *
from ursina.prefabs.first_person_controller import FirstPersonController
app = Ursina()
window.fps_counter.enabled = False
player = FirstPersonController()
Sky()
boxes = []
def random_color():
red = random.Random().random() * 20
green = random.Random().random() * 255
blue = random.Random().random() * 20
return color.rgb(red, green, blue)
def add_box(position):
boxes.append(
Button(
parent=scene,
model='cube',
origin=0.5,
color=random_color(),
position=position,
texture='grass'
)
)
for x in range(20):
for y in range(20):
add_box((x, 0, y))
player_reset_position = (5,10,5)
def input(key):
for box in boxes:
if box.hovered:
if key == "right mouse down":
add_box(box.position + mouse.normal)
if key == "left mouse down":
boxes.remove(box)
destroy(box)
if key == ("escape"):
exit()
if key == ("shift"):
player.speed = 15
else:
player.speed = 7
if key == 'r':
player.position = player_reset_position
app.run()
I have changed indentation and your input function where you had if kb.is_pressed("escape"): to if key == "escape":

Replicating Mouse clicks NameError

I'm trying to incorporate mouse events. I got this code from the link ctypes mouse_events
The code there had an error so I changed some part of the code into making it into an integer.
import win32gui, win32api, win32con, ctypes
class Mouse:
"""It simulates the mouse"""
MOUSEEVENTF_MOVE = 0x0001 # mouse move
MOUSEEVENTF_LEFTDOWN = 0x0002 # left button down
MOUSEEVENTF_LEFTUP = 0x0004 # left button up
MOUSEEVENTF_RIGHTDOWN = 0x0008 # right button down
MOUSEEVENTF_RIGHTUP = 0x0010 # right button up
MOUSEEVENTF_MIDDLEDOWN = 0x0020 # middle button down
MOUSEEVENTF_MIDDLEUP = 0x0040 # middle button up
MOUSEEVENTF_WHEEL = 0x0800 # wheel button rolled
MOUSEEVENTF_ABSOLUTE = 0x8000 # absolute move
SM_CXSCREEN = 0
SM_CYSCREEN = 1
def _do_event(self, flags, x_pos, y_pos, data, extra_info):
"""generate a mouse event"""
x_calc = int(65536 * x_pos / ctypes.windll.user32.GetSystemMetrics(self.SM_CXSCREEN) + 1)
y_calc = int(65536 * y_pos / ctypes.windll.user32.GetSystemMetrics(self.SM_CYSCREEN) + 1)
return ctypes.windll.user32.mouse_event(flags, x_calc, y_calc, data, extra_info)
def _get_button_value(self, button_name, button_up=False):
"""convert the name of the button into the corresponding value"""
buttons = 0
if button_name.find("right") >= 0:
buttons = self.MOUSEEVENTF_RIGHTDOWN
if button_name.find("left") >= 0:
buttons = buttons + self.MOUSEEVENTF_LEFTDOWN
# time.sleep(0.1)
# self.MOUSEEVENTF_LEFTUP
if button_name.find("middle") >= 0:
buttons = buttons + self.MOUSEEVENTF_MIDDLEDOWN
if button_up:
buttons = buttons << 1
return buttons
def move_mouse(self, pos):
"""move the mouse to the specified coordinates"""
(x, y) = pos
old_pos = self.get_position()
x = x if (x != -1) else old_pos[0]
y = y if (y != -1) else old_pos[1]
self._do_event(self.MOUSEEVENTF_MOVE + self.MOUSEEVENTF_ABSOLUTE, x, y, 0, 0)
def press_button(self, pos=(-1, -1), button_name="left", button_up=False):
"""push a button of the mouse"""
self.move_mouse(pos)
self._do_event(self.get_button_value(button_name, button_up), 0, 0, 0, 0)
def click(self, pos=(-1, -1), button_name= "left"):
"""Click at the specified placed"""
self.move_mouse(pos)
self._do_event(self._get_button_value(button_name, False)+self._get_button_value(button_name, True), 0, 0, 0, 0)
def double_click (self, pos=(-1, -1), button_name="left"):
"""Double click at the specifed placed"""
for i in xrange(2):
self.click(pos, button_name)
def get_position(self):
"""get mouse position"""
return win32api.GetCursorPos()
With mouse = Mouse(),
The mouse.click((100, 100), "left") works, but mouse.double_click((100,100), "left") doesn't and come out with error with "NameError: name 'xrange' is not defined"
How can I trouble shoot this?
Thank you very much in advance!
Ah Thanks Furas.
"xrange() was in Python 2.7. In Python 3.x you have to use range()"
Just changed xrange() into range() and it works.
Also the reason why I'm not using PyAutoGUI/pynput that some of the mouse function does not properly work with certain games that uses DirectX inputs and is faulty with the mouse as well. Thus, this code should work properly in case if the PyAutoGUI/pynput does not work.

Python turtle mouse does not follow directly

How do you make turtle move without using turtle.goto(x,y) but turtle.speed(speed) and turtle.heading(angle)? I need this for a game I am making. Where the mouse is, I want to make it go in that direction. But when I change it, it goes to that place then to my mouse:
import turtle
screen = turtle.Screen()
screen.title("Test")
screen.bgcolor("white")
screen.setup(width=600, height=600)
ship = turtle.Turtle()
ship.speed(1)
ship.shape("triangle")
ship.penup()
ship.goto(0,0)
ship.direction = "stop"
ship.turtlesize(3)
turtle.hideturtle()
def onmove(self, fun, add=None):
if fun is None:
self.cv.unbind('<Motion>')
else:
def eventfun(event):
fun(self.cv.canvasx(event.x) / self.xscale, -self.cv.canvasy(event.y) / self.yscale)
self.cv.bind('<Motion>', eventfun, add)
def goto_handler(x, y):
onmove(turtle.Screen(), None)
ship.setheading(ship.towards(x, y)) #this is where you use the x,y cordinates and I have seat them to got to x,y and set heading
ship.goto(x,y)
onmove(turtle.Screen(), goto_handler)
onmove(screen, goto_handler)
If you only setheading and speed it just turns that way and does not move. If you try this code it works -- it is just that I use ship.goto(x, y) which makes it go to (x, y). But when you change your mouse when it is moving, it first goes to (x, y) then to your new mouse position. I pretty much just want it to just follow the mouse but I can not do that.
I believe the code below gives you the motion you desire. It only uses onmove() to stash the target's position and uses an ontimer() to aim and move the turtle. It also stops when the target has been enveloped:
from turtle import Screen, Turtle, Vec2D
def onmove(self, fun, add=None):
if fun is None:
self.cv.unbind('<Motion>')
else:
def eventfun(event):
fun(Vec2D(self.cv.canvasx(event.x) / self.xscale, -self.cv.canvasy(event.y) / self.yscale))
self.cv.bind('<Motion>', eventfun, add)
def goto_handler(position):
global target
onmove(screen, None)
target = position
onmove(screen, goto_handler)
def move():
if ship.distance(target) > 5:
ship.setheading(ship.towards(target))
ship.forward(5)
screen.ontimer(move, 50)
screen = Screen()
screen.title("Test")
screen.setup(width=600, height=600)
ship = Turtle("triangle")
ship.turtlesize(3)
ship.speed('fast')
ship.penup()
target = (0, 0)
onmove(screen, goto_handler)
move()
screen.mainloop()

Categories

Resources