def __init__(self, world: BulletWorld, entity: Entity, radius=1, height=2, name='Player', **opts) -> None: super().__init__(BulletCapsuleShape(radius / 2, height / 2, 1), radius / 2, name) self.np = application.base.render.attachNewNode(self) if entity.parent: self.np.reparent_to(entity.parent) rotation = Vec3(0, 0, 0) if None in rotation: hpr = entity.getHpr() for x in range(len(hpr)): rotation[x] = hpr[x] self.np.setHpr(rotation) self.np.setPos(entity.x, entity.y, entity.z) entity.reparent_to(self.np) world.attachCharacter(self) self.__fall_speed = None self.__jump_speed = None self.__max_jump_height = None for x in opts: setattr(self, x, opts[x])
def create_map(self): """ create game background """ Entity(model='quad', scale=(MAP_SIZE_X, MAP_SIZE_Y), position=(MAP_SIZE_X / 2 - 0.5, MAP_SIZE_Y / 2 - 0.5, 0.51), color=color.dark_gray) Entity(model=Grid(MAP_SIZE_X, MAP_SIZE_Y), scale=(MAP_SIZE_X, MAP_SIZE_Y), position=(MAP_SIZE_X / 2 - 0.5, MAP_SIZE_Y / 2 - 0.5, 0.5), color=color.white)
def __init__(self, world:BulletWorld, entity:Entity, shape, name, rotation): super().__init__(name) self.addShape(shape) self.np = application.base.render.attachNewNode(self) world.attachGhost(self) if entity.parent: self.np.reparent_to(entity.parent) if None in rotation: hpr = entity.getHpr() for x in range(len(hpr)): rotation[x] = hpr[x] self.np.setHpr(Vec3(*rotation)) self.np.setPos(entity.x, entity.y, entity.z) entity.reparent_to(self.np)
class Block(Entity): def __init__(self, is_head=False, **kwargs): self.is_head = is_head self.direction = kwargs.get('direction') if IS_SNAKE_SMOOTH: super().__init__(**kwargs) self.follower = Entity(model='sphere', **kwargs) self.follower.add_script( SmoothFollow(speed=30, target=self, offset=(0, 0, 0))) if self.is_head: # ( 90, 90, 90) - left (-1, 0, 0) # (-90, 90, 90) - right (1, 0, 0) # (0, 90, 90) - down (0, -1, 0) # (180, 90, 90) - up (0, 1, 0) self.follower.rotation = ( (self.direction[1] * (self.direction[1] + 1) - self.direction[0]) * 90, 90, 90) else: super().__init__(model='sphere', **kwargs) def move(self, direction): self.direction = direction if self.is_head: self.follower.rotation = ( (self.direction[1] * (self.direction[1] + 1) - self.direction[0]) * 90, 90, 90) # is reached boundaries if direction[0] == -1 and self.position[0] <= 0: self.position = Vec3(MAP_SIZE_X - 1, self.position[1], self.position[2]) elif direction[1] == -1 and self.position[1] <= 0: self.position = Vec3(self.position[0], MAP_SIZE_Y - 1, self.position[2]) elif direction[0] == 1 and self.position[0] >= MAP_SIZE_X - 1: self.position = Vec3(0, self.position[1], self.position[2]) elif direction[1] == 1 and self.position[1] >= MAP_SIZE_Y - 1: self.position = Vec3(self.position[0], 0, self.position[2]) else: self.position = self.position + direction
def __init__(self, button_dict, button_height=1.1, width=.5, font=Text.default_font, **kwargs): super().__init__(parent=camera.ui, model='quad', scale=(width, 1), color=Button.color, origin=(-.5, .5), position=(-.25, .45), collider='box') self.button_height = button_height self.text_entity = Text(parent=self, font=font, origin=(-.5, .5), text='empty', world_scale=20, z=-.1, x=.01, line_height=button_height) self.highlight = Entity(parent=self, model='quad', color=color.white33, scale=(1, self.button_height), origin=(-.5, .5), z=-.01, add_to_scene_entities=False) self.selection_marker = Entity(parent=self, model='quad', color=color.azure, scale=(1, self.button_height), origin=(-.5, .5), z=-.02, enabled=False, add_to_scene_entities=False) self.button_dict = button_dict for key, value in kwargs.items(): setattr(self, key, value)
def __init__(self, is_head=False, **kwargs): self.is_head = is_head self.direction = kwargs.get('direction') if IS_SNAKE_SMOOTH: super().__init__(**kwargs) self.follower = Entity(model='sphere', **kwargs) self.follower.add_script( SmoothFollow(speed=30, target=self, offset=(0, 0, 0))) if self.is_head: # ( 90, 90, 90) - left (-1, 0, 0) # (-90, 90, 90) - right (1, 0, 0) # (0, 90, 90) - down (0, -1, 0) # (180, 90, 90) - up (0, 1, 0) self.follower.rotation = ( (self.direction[1] * (self.direction[1] + 1) - self.direction[0]) * 90, 90, 90) else: super().__init__(model='sphere', **kwargs)
def icon(self, value): if value: if not hasattr(self, 'icon_entity'): self.icon_entity = Entity(parent=self.model, name=f'buttonicon_entity_{value}', model='quad', texture=value, z=-.1, add_to_scene_entities=False) else: self.icon_entity.texture = value
def __init__(self, **kwargs): super().__init__(**kwargs) self.phoneme_store = None self.voxels = [] self.correct = False self.started = False self.update_counter = None self.score = 0 self.difficulty = 3 # lower difficulty is harder self.help_text = Text( '', parent=camera.ui, x=-.6, y=.35, enabled=False ) self.score_text = Text( '', parent=camera.ui, x=.5, y=.35, enabled=False ) self.player = None self.ground = Entity(model='plane', scale=(100, 1, 100), y=-1, color=color.yellow.tint(-.2), texture='white_cube', texture_scale=(100, 100), collider='box', enabled=False) self.sky = Entity(model='sphere', texture='sky2.jpg', scale=10000, double_sided=True, color=color.white, enabled=False) self.rotated_y = 30 self.next_block = Entity(parent=camera.ui, rotation=Vec3(10, 30, 30), model='cube', scale=.1, x=.7, y=.2, texture='index') self.give_up_button = Button(parent=scene, text='give up', double_sided=True, x=-1, z=ARENA_DEPTH, y=3, on_click=self.give_up, enabled=False, scale_x=2) self.reset_text = Text( 'Press ESC to change words and/or start again.', parent=scene, x=0, z=ARENA_DEPTH, y=2, double_sided=True, enabled=False, scale=15 )
def __init__(self, mass, radius, lineColor, model, texture): super().__init__(model=model, texture=texture) self.mass = mass self.radius = radius #Applies for the Sun for example self.static = False self._position = [[0.0, 0.0, 0.0]] self._velocity = [[0.0, 0.0, 0.0]] self._acceleration = [[0.0, 0.0, 0.0]] self._vnew = [0.0, 0.0, 0.0] self._partialPos = [0.0, 0.0, 0.0] self._maxPoint = 100 self._trajectoryMesh = Mesh(mode='line', vertices=[], thickness=1) self._line = Entity(model=self._trajectoryMesh, color=lineColor, z=0)
def __init__(self, title='', content=[], **kwargs): super().__init__(origin=(-0,.5), scale=(.5, Text.size*2), color=color.black) self.content = content self.text = title self.popup = False self._prev_input_field = None self._original_scale = self.scale for key, value in kwargs.items(): setattr(self, key ,value) if self.text_entity: self.text_entity.world_scale_y = 1 self.panel = Entity(parent=self, model='quad', origin=(0,.5), z=.1, color=self.color.tint(.1), collider='box') if self.popup: self.lock = Vec3(1,1,1) self.bg = Button(parent=self, z=1, scale=(999, 999), color=color.black66, highlight_color=color.black66, pressed_color=color.black66) self.bg.on_click = self.close self.layout()
if name == 'width': self.b.style.width = f'{value}px' if name == 'heigth': self.b.style.heigth = f'{value}px' if name == 'size': self.width, self.height = value[0], value[1] if name == 'color': self.b.style.backgroundColor = value @property def aspect_ratio(self): return self.width / self.height window = Window() from ursina import Entity scene = Entity(model=None, scale_x=1 / window.aspect_ratio, name='scene', entities=[]) _window.appendChild(scene.b) # mouse = Empty() from ursina.camera import Camera camera = Camera() class Mouse: def __init__(self): self.enabled = True # self.locked = False self.position = (0, 0) self.delta = (0, 0)
if other in self.triggerers and dist > self.radius: self.triggerers.remove(other) if hasattr(self, 'on_trigger_exit'): self.on_trigger_exit() continue if other in self.triggerers and hasattr(self, 'on_trigger_stay'): self.on_trigger_stay() if __name__ == '__main__': from ursina import * app = Ursina() player = Entity(model='cube', color=color.azure, scale=.05) def update(): player.x += held_keys['d'] * time.dt * 2 player.x -= held_keys['a'] * time.dt * 2 t = Trigger(trigger_targets=scene.entities, x=1, model='sphere', color=color.color(0, 1, 1, .5)) t.on_trigger_enter = Func(print, 'enter') t.on_trigger_exit = Func(print, 'exit') t.on_trigger_stay = Func(print, 'stay') app.run()
from ursina import Ursina app = Ursina() player_graphics = SpriteSheetAnimation('sprite_sheet', tileset_size=(4, 4), fps=6, animations={ 'idle': ((0, 0), (0, 0)), 'walk_up': ((0, 0), (3, 0)), 'walk_right': ((0, 1), (3, 1)), 'walk_left': ((0, 2), (3, 2)), 'walk_down': ((0, 3), (3, 3)), }) def input(key): if key == 'w': player_graphics.play_animation('walk_up') elif key == 's': player_graphics.play_animation('walk_down') elif key == 'd': player_graphics.play_animation('walk_right') elif key == 'a': player_graphics.play_animation('walk_left') # elif key == 'w up': # player_graphics.play_animation('idle') # print(player_graphics.animations['walk_up'].funcs) Entity(model='quad', texture='sprite_sheet', x=-1) app.run()
def make_editor_gui( self ): # called by main after setting up camera and application.development_mode from ursina import camera, Entity, Text, Button, ButtonList, Func, Tooltip, held_keys, mouse import time self.editor_ui = Entity(parent=camera.ui, eternal=True, enabled=bool(application.development_mode)) self.exit_button = Button(parent=self.editor_ui, eternal=True, ignore_paused=True, origin=(.5, .5), enabled=self.borderless, position=self.top_right, z=-999, scale=(.05, .025), color=color.red.tint(-.2), text='x', on_click=application.quit, name='exit_button') def _exit_button_input(key): if held_keys['shift'] and key == 'q' and not mouse.right: self.exit_button.on_click() self.exit_button.input = _exit_button_input self.fps_counter = Text( parent=self.editor_ui, eternal=True, origin=(.8, .5), text='60', ignore=False, i=0, position=(.5 * self.aspect_ratio, .47 + (.02 * (not self.exit_button.enabled)), -999)) def _fps_counter_update(): if self.fps_counter.i > 60: self.fps_counter.text = str(int(1 // time.dt)) self.fps_counter.i = 0 self.fps_counter.i += 1 self.fps_counter.update = _fps_counter_update import webbrowser self.cog_menu = ButtonList( { # 'Build' : Func(print, ' '), 'API Reference': Func(webbrowser.open, 'https://www.ursinaengine.org/cheat_sheet_dark.html'), # 'Asset Store' : Func(webbrowser.open, 'https://itch.io/tools/tag-ursina'), 'ursfx (Sound Effect Maker)': lambda: exec( 'from ursina.prefabs import ursfx; ursfx.gui.enabled = True' ), # 'Open Scene Editor' : Func(print, ' '), 'Change Render Mode <gray>[F10]<default>': self.next_render_mode, 'Reset Render Mode <gray>[F9]<default>': Func(setattr, self, 'render_mode', 'default'), 'Reload Models <gray>[F7]<default>': application.hot_reloader.reload_models, 'Reload Textures <gray>[F6]<default>': application.hot_reloader.reload_textures, 'Reload Code <gray>[F5]<default>': application.hot_reloader.reload_code, }, width=.35, x=.62, enabled=False, eternal=True, name='cog_menu', ) self.cog_menu.on_click = Func(setattr, self.cog_menu, 'enabled', False) self.cog_menu.y = -.5 + self.cog_menu.scale_y self.cog_menu.scale *= .75 self.cog_menu.text_entity.x += .025 self.cog_menu.highlight.color = color.azure self.cog_button = Button(parent=self.editor_ui, eternal=True, model='quad', texture='cog', scale=.015, origin=(1, -1), position=self.bottom_right, name='cog_button') info_text = '''This menu is not enabled in builds <gray>(unless you set application.development_mode to be not False).''' self.cog_menu.info = Button(parent=self.cog_menu, model='quad', text='<gray>?', scale=.1, x=1, y=.01, origin=(.5, -.5), tooltip=Tooltip(info_text, scale=.75, origin=(-.5, -.5), eternal=True), eternal=True, name='cog_menu_info') self.cog_menu.info.text_entity.scale *= .75 def _toggle_cog_menu(): self.cog_menu.enabled = not self.cog_menu.enabled self.cog_button.on_click = _toggle_cog_menu
def make_entity(self): self.entity = Entity(model="quad", texture=self.texture, scale=1, position=(round(self.x), round(self.y), self.z_index))
class ButtonList(Entity): def __init__(self, button_dict, button_height=1.1, width=.5, font=Text.default_font, **kwargs): super().__init__(parent=camera.ui, model='quad', scale=(width, 1), color=Button.color, origin=(-.5, .5), position=(-.25, .45), collider='box') self.button_height = button_height self.text_entity = Text(parent=self, font=font, origin=(-.5, .5), text='empty', world_scale=20, z=-.1, x=.01, line_height=button_height) self.highlight = Entity(parent=self, model='quad', color=color.white33, scale=(1, self.button_height), origin=(-.5, .5), z=-.01, add_to_scene_entities=False) self.selection_marker = Entity(parent=self, model='quad', color=color.azure, scale=(1, self.button_height), origin=(-.5, .5), z=-.02, enabled=False, add_to_scene_entities=False) self.button_dict = button_dict for key, value in kwargs.items(): setattr(self, key, value) @property def button_dict(self): return self._button_dict @button_dict.setter def button_dict(self, value): self._button_dict = value self.actions = list(self._button_dict.values()) self.text_entity.text = '\n'.join(self.button_dict.keys()) self.scale_y = self.button_height * len(value) * Text.size self.text_entity.world_scale = 20 self.highlight.scale_y = 1 / len(value) self.selection_marker.scale_y = 1 / len(value) def input(self, key): # handle click here instead of in on_click so you can assign a custom on_click function if key == 'left mouse down' and self.hovered: y = floor(-mouse.point.y * len(self.button_dict)) action = self.actions[y] self.highlight.blink(color.black, .1) self.selection_marker.enabled = True self.selection_marker.y = self.highlight.y if callable(action): action() elif isinstance(action, Sequence): action.start() if key == 'left mouse down' and not self.hovered: self.selection_marker.enabled = False def update(self): self.highlight.enabled = mouse.hovered_entity == self if mouse.hovered_entity == self: y = floor(-mouse.point.y * len(self.button_dict)) self.highlight.y = -y / len(self.button_dict) def on_disable(self): self.selection_marker.enabled = False
verts.append(Vec3(0, height, 0)) if add_bottom: for i in range(resolution): verts.append(Vec3(v[0], 0, v[1])) verts.append(Vec3(0, 0, 0)) v = rotate_point_2d(v, origin, -degrees_to_rotate) verts.append(Vec3(v[0], 0, v[1])) super().__init__(vertices=verts, uvs=[e.xy for e in verts], mode=mode, **kwargs) if __name__ == '__main__': from ursina import Ursina, Entity, color, EditorCamera app = Ursina() e = Entity(model=Cone(3), texture='brick') # # rotate model # for i, v in enumerate(e.model.vertices): # x, y = rotate_point_2d((v.x, v.y), (0,0), 90) # # e.model.vertices[i] = Vec3(x, y, v.z) # # e.model.generate() origin = Entity(model='quad', color=color.orange, scale=(.05, .05)) ed = EditorCamera() app.run()
class Tile(): def __init__(self, position, typ, controller, hitbox=[0.0, 0.0, 1.0, 1.0], z_index=2): # hitbox: min-x, min-y, max-x, max-y self.position = position self.hitbox = Hitbox(hitbox[:]) self.type = typ self.texture = self.type.default_texture() self.entity = None self.controller = controller self.animator = Animator(self, self.texture) self.z_index = z_index if self.texture: self.make_entity() def make_entity(self): self.entity = Entity(model="quad", texture=self.texture, scale=1, position=(round(self.x), round(self.y), self.z_index)) def load(self, new_type, texture=True): """Change the type of the tile to new_type. If texture is True, then also change the texture.""" self.type = new_type self.texture = self.type.default_texture() if self.entity and texture: self.entity.texture = self.texture def load_toggle(self): self.load(self.type.toggle()) def update(self, dt): ... def collide(self, tile, direction, commit=True): return True # if this method is called, then self.type.collides() @property def x(self): return self.position[0] @property def y(self): return self.position[1] def __repr__(self): return str(self.type).split(".")[1] + f" at {self.position}" def hide(self, now=False): self.type = TileType.AIR if now: self.entity.hide() else: self.entity.fade_out() def setup(self): ... def inside(self, tile, density=10): # TODO: transparency (hitboxes) """Tells if this tile is inside the given tile. Works by testing the boundary points of the one by one box with the bottom left corner in the specified position.""" return self.inside_position(tile.position, tile.hitbox, density=density) def inside_position(self, position, hitbox, density=3): for i in range(density): if point_inside([ self.position[0] + i / density * (self.hitbox.max_x - self.hitbox.min_x), self.position[1] + self.hitbox.min_y ], position, hitbox): return True if point_inside([ self.position[0] + i / density * (self.hitbox.max_x - self.hitbox.min_x), self.position[1] + self.hitbox.max_y ], position, hitbox): return True if point_inside([ self.position[0] + self.hitbox.min_x, self.position[1] + i / density * (self.hitbox.max_y - self.hitbox.min_y) ], position, hitbox): return True if point_inside([ self.position[0] + self.hitbox.max_x, self.position[1] + i / density * (self.hitbox.max_y - self.hitbox.min_y) ], position, hitbox): return True return False
class MainGame(Entity): def __init__(self, **kwargs): super().__init__(**kwargs) self.phoneme_store = None self.voxels = [] self.correct = False self.started = False self.update_counter = None self.score = 0 self.difficulty = 3 # lower difficulty is harder self.help_text = Text( '', parent=camera.ui, x=-.6, y=.35, enabled=False ) self.score_text = Text( '', parent=camera.ui, x=.5, y=.35, enabled=False ) self.player = None self.ground = Entity(model='plane', scale=(100, 1, 100), y=-1, color=color.yellow.tint(-.2), texture='white_cube', texture_scale=(100, 100), collider='box', enabled=False) self.sky = Entity(model='sphere', texture='sky2.jpg', scale=10000, double_sided=True, color=color.white, enabled=False) self.rotated_y = 30 self.next_block = Entity(parent=camera.ui, rotation=Vec3(10, 30, 30), model='cube', scale=.1, x=.7, y=.2, texture='index') self.give_up_button = Button(parent=scene, text='give up', double_sided=True, x=-1, z=ARENA_DEPTH, y=3, on_click=self.give_up, enabled=False, scale_x=2) self.reset_text = Text( 'Press ESC to change words and/or start again.', parent=scene, x=0, z=ARENA_DEPTH, y=2, double_sided=True, enabled=False, scale=15 ) def create_clouds(self): self.sky.enable() for i in range(20): cloud = Entity(parent=scene, model='cube', texture='index', scale_x=random.randint(2, ARENA_DEPTH), scale_y=random.randint(1, 6), scale_z=random.randint(2, ARENA_DEPTH), color=color.white, position=Vec3(random.randint(-50, ARENA_DEPTH+50), random.randint(10, 50), random.randint(-50, ARENA_DEPTH+50))) self.voxels.append(cloud) def give_up(self): self.score -= 1 if self.phoneme_store.words: self.build() else: self.end_game() def end_game(self): self.destroy_all() self.build_platform() self.correct = False self.update_counter = None self.update_score() if self.score > 0: self.help_text.text = f'GAME OVER! YOU WIN!\nYour score: {self.score}' else: self.help_text.text = f'GAME OVER! YOU LOSE!\nYour score: {self.score}' def reset(self): pass def build(self): self.started = True word = self.phoneme_store.get_new_word() self.update_counter = 0 if self.give_up_button.enabled: self.give_up_button.disable() if self.reset_text.enabled: self.reset_text.disable() if word is not None: if self.phoneme_store.pron() is not None: self.help_text.text = f'The word is: "{self.phoneme_store.word}"\nLeft click in the green area to lay a phoneme,\nright click to pick one up.' self.help_text.enable() self.score_text.text = f'Score: {self.score}' self.score_text.enable() if self.voxels: self.destroy_all() self.help_text.text = self.phoneme_store.word self.correct = False for z in range(ARENA_DEPTH + 1): voxel_side_wall = Voxel(self.phoneme_store, self, position=(-1, 1, z)) voxel_other_side_wall = Voxel(self.phoneme_store, self, position=(len(self.phoneme_store.phonemes), 1, z)) self.voxels.append(voxel_side_wall) self.voxels.append(voxel_other_side_wall) for x in range(len(self.phoneme_store.phonemes)): voxel = Voxel(self.phoneme_store, self, position=(x, 0, z)) voxel_wall = Voxel(self.phoneme_store, self, position=(x, 1, -1)) self.voxels.append(voxel) self.voxels.append(voxel_wall) if voxel.position[2] == ARENA_DEPTH: voxel.color = color.lime voxel.texture = 'white_cube' invoke(self.create_clouds, delay=0.1) if self.player: self.player.y = 0 self.player.x = len(self.phoneme_store.phonemes) // 2 self.player.z = 1 else: self.generate_player() else: return self.build() else: self.end_game() def build_platform(self): self.ground.enable() self.update_counter = None self.reset_text.enable() self.give_up_button.disable() self.create_clouds() self.started = False def update_score(self): self.score_text.text = f'Score: {self.score}' def destroy_all(self): for v in self.voxels: destroy(v) self.voxels = [] def generate_player(self): self.player = FirstPersonController(enabled=True) self.player.speed += 2 self.player.mouse_sensitivity = Vec2(50, 50) self.player.jump_duration = .3 self.player.gravity *= .8 self.player.y = 0 self.player.x = len(self.phoneme_store.phonemes) // 2 self.player.z = 1 def spin_block(self): self.rotated_y -= 1 self.next_block.rotation = Vec3(10, self.rotated_y, 30)
'texture_offset' : Vec2(0.0, 0.0), 'position_offsets' : [Vec3(i,0,0) for i in range(256)], 'rotation_offsets' : [Vec4(0) for i in range(256)], 'scale_multipliers' : [Vec3(1) for i in range(256)], } ) if __name__ == '__main__': from ursina import Ursina, Entity, EditorCamera, Vec3, color, application, time, Cone import random app = Ursina(vsync=False) instances = [] Entity(model='plane', texture='grass', scale=128) application.asset_folder = application.asset_folder.parent.parent p = Entity(model=Cone(5), y=1, texture='brick') p.model.uvs = [(v[0],v[1]) for v in p.model.vertices] p.model.generate() p.shader = instancing_shader p.setInstanceCount(256) for z in range(16): for x in range(16): e = Entity(position=Vec3(x, 0, z), color=color.lime, rotation_y=random.random()*360) instances.append(e) print(e.quaternion, Quat()) p.set_shader_input('position_offsets', [e.position*4 for e in instances]) p.set_shader_input('rotation_offsets', [e.quaternion for e in instances])
def create_clouds(self): self.sky.enable() for i in range(20): cloud = Entity(parent=scene, model='cube', texture='index', scale_x=random.randint(2, ARENA_DEPTH), scale_y=random.randint(1, 6), scale_z=random.randint(2, ARENA_DEPTH), color=color.white, position=Vec3(random.randint(-50, ARENA_DEPTH+50), random.randint(10, 50), random.randint(-50, ARENA_DEPTH+50))) self.voxels.append(cloud)
# Taken from https://www.ursinaengine.org/ from ursina import Entity, Ursina, color, held_keys app = Ursina() player = Entity(model="cube", color=color.orange, scale_y=2) def update(): # update gets automatically called. player.x += held_keys["d"] * 0.1 player.x -= held_keys["a"] * 0.1 app.run() # opens a window and starts the game.