Add character controller for testing physics
parent
06b07be8ea
commit
5011bca3f9
|
@ -0,0 +1,61 @@
|
|||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://character_controller.gd" type="Script" id=1]
|
||||
[ext_resource path="res://mouse_look.gd" type="Script" id=2]
|
||||
|
||||
[sub_resource type="CapsuleShape" id=1]
|
||||
|
||||
radius = 0.4
|
||||
height = 0.85
|
||||
|
||||
[node name="CharacterAvatar" type="KinematicBody"]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
input_ray_pickable = true
|
||||
input_capture_on_drag = false
|
||||
shape_count = 1
|
||||
shapes/0/shape = SubResource( 1 )
|
||||
shapes/0/transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
shapes/0/trigger = false
|
||||
collision_layer = 1
|
||||
collision_mask = 1
|
||||
collide_with/static = true
|
||||
collide_with/kinematic = true
|
||||
collide_with/rigid = true
|
||||
collide_with/character = true
|
||||
collision/margin = 0.001
|
||||
script = ExtResource( 1 )
|
||||
speed = 5.0
|
||||
gravity = 9.8
|
||||
jump_force = 8.0
|
||||
head = NodePath("Camera")
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
transform = Transform( 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0 )
|
||||
shape = SubResource( 1 )
|
||||
trigger = false
|
||||
_update_shape_index = 0
|
||||
|
||||
[node name="Camera" type="Camera" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.702764, 0 )
|
||||
projection = 0
|
||||
fov = 90.0
|
||||
near = 0.1
|
||||
far = 500.0
|
||||
keep_aspect = 1
|
||||
current = false
|
||||
cull_mask = 1048575
|
||||
environment = null
|
||||
h_offset = 0.0
|
||||
v_offset = 0.0
|
||||
script = ExtResource( 2 )
|
||||
sensitivity = 0.4
|
||||
min_angle = -90
|
||||
max_angle = 90
|
||||
capture_mouse = true
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
extends KinematicBody
|
||||
|
||||
export var speed = 5.0
|
||||
export var gravity = 9.8
|
||||
export var jump_force = 5.0
|
||||
export(NodePath) var head = null
|
||||
|
||||
var _velocity = Vector3()
|
||||
var _grounded = false
|
||||
var _head = null
|
||||
|
||||
|
||||
func _ready():
|
||||
_head = get_node(head)
|
||||
|
||||
# FIX
|
||||
set_shape_transform(0, Transform().rotated(Vector3(1,0,0), PI/2.0))
|
||||
|
||||
|
||||
func _fixed_process(delta):
|
||||
|
||||
var forward = _head.get_transform().basis.z.normalized()
|
||||
forward = Plane(Vector3(0, 1, 0), 0).project(forward)
|
||||
var right = _head.get_transform().basis.x.normalized()
|
||||
var motor = Vector3()
|
||||
|
||||
if Input.is_key_pressed(KEY_UP) or Input.is_key_pressed(KEY_Z) or Input.is_key_pressed(KEY_W):
|
||||
motor -= forward
|
||||
if Input.is_key_pressed(KEY_DOWN) or Input.is_key_pressed(KEY_S):
|
||||
motor += forward
|
||||
if Input.is_key_pressed(KEY_LEFT) or Input.is_key_pressed(KEY_Q) or Input.is_key_pressed(KEY_A):
|
||||
motor -= right
|
||||
if Input.is_key_pressed(KEY_RIGHT) or Input.is_key_pressed(KEY_D):
|
||||
motor += right
|
||||
|
||||
motor = motor.normalized() * speed
|
||||
|
||||
_velocity.x = motor.x
|
||||
_velocity.z = motor.z
|
||||
_velocity.y -= gravity * delta
|
||||
|
||||
if _grounded and Input.is_key_pressed(KEY_SPACE):
|
||||
_velocity.y = jump_force
|
||||
_grounded = false
|
||||
|
||||
var motion = _velocity * delta
|
||||
|
||||
var rem = move(motion)
|
||||
|
||||
if is_colliding():
|
||||
var n = get_collision_normal()
|
||||
var k = 1.0#clamp(n.y, 0, 1)
|
||||
rem = n.slide(rem)*k
|
||||
_velocity = n.slide(_velocity)*k
|
||||
_grounded = true
|
||||
move(rem)
|
||||
else:
|
||||
_grounded = false
|
||||
#get_node("debug").set_text("Grounded=" + str(_grounded))
|
|
@ -1,81 +1,11 @@
|
|||
[gd_scene load_steps=8 format=2]
|
||||
[gd_scene load_steps=9 format=2]
|
||||
|
||||
[ext_resource path="res://debug_camera.gd" type="Script" id=1]
|
||||
[ext_resource path="res://voxel_map.gd" type="Script" id=2]
|
||||
[ext_resource path="res://terrain.png" type="Texture" id=3]
|
||||
[ext_resource path="res://grid.gd" type="Script" id=4]
|
||||
[ext_resource path="res://voxel_map.gd" type="Script" id=1]
|
||||
[ext_resource path="res://terrain.png" type="Texture" id=2]
|
||||
[ext_resource path="res://grid.gd" type="Script" id=3]
|
||||
[ext_resource path="res://character_avatar.tscn" type="PackedScene" id=4]
|
||||
|
||||
[sub_resource type="FixedSpatialMaterial" id=1]
|
||||
|
||||
flags_transparent = false
|
||||
flags_unshaded = false
|
||||
flags_on_top = false
|
||||
flags_use_point_size = false
|
||||
vertex_color_use_as_albedo = true
|
||||
vertex_color_is_srgb = false
|
||||
params_diffuse_mode = 0
|
||||
params_blend_mode = 0
|
||||
params_cull_mode = 0
|
||||
params_depth_draw_mode = 0
|
||||
params_line_width = 1.0
|
||||
params_point_size = 1.0
|
||||
albedo_color = Color( 1, 1, 1, 1 )
|
||||
albedo_texture = ExtResource( 3 )
|
||||
specular_mode = 0
|
||||
specular_color = Color( 0.1, 0.1, 0.1, 1 )
|
||||
specular_metalness = 0.1
|
||||
specular_roughness = 0.0
|
||||
emission_enabled = false
|
||||
normal_enabled = false
|
||||
rim_enabled = false
|
||||
clearcoat_enabled = false
|
||||
anisotropy_enabled = false
|
||||
ao_enabled = false
|
||||
height_enabled = false
|
||||
subsurf_scatter_enabled = false
|
||||
refraction_enabled = false
|
||||
detail_enabled = false
|
||||
uv1_scale = Vector2( 1, 1 )
|
||||
uv1_offset = Vector2( 0, 0 )
|
||||
uv2_scale = Vector2( 1, 1 )
|
||||
uv2_offset = Vector2( 0, 0 )
|
||||
|
||||
[sub_resource type="FixedSpatialMaterial" id=2]
|
||||
|
||||
flags_transparent = true
|
||||
flags_unshaded = false
|
||||
flags_on_top = false
|
||||
flags_use_point_size = false
|
||||
vertex_color_use_as_albedo = false
|
||||
vertex_color_is_srgb = false
|
||||
params_diffuse_mode = 0
|
||||
params_blend_mode = 0
|
||||
params_cull_mode = 0
|
||||
params_depth_draw_mode = 0
|
||||
params_line_width = 1.0
|
||||
params_point_size = 1.0
|
||||
albedo_color = Color( 0.7, 0.7, 0.7, 1 )
|
||||
albedo_texture = ExtResource( 3 )
|
||||
specular_mode = 0
|
||||
specular_color = Color( 0.1, 0.1, 0.1, 1 )
|
||||
specular_metalness = 0.1
|
||||
specular_roughness = 0.0
|
||||
emission_enabled = false
|
||||
normal_enabled = false
|
||||
rim_enabled = false
|
||||
clearcoat_enabled = false
|
||||
anisotropy_enabled = false
|
||||
ao_enabled = false
|
||||
height_enabled = false
|
||||
subsurf_scatter_enabled = false
|
||||
refraction_enabled = false
|
||||
detail_enabled = false
|
||||
uv1_scale = Vector2( 1, 1 )
|
||||
uv1_offset = Vector2( 0, 0 )
|
||||
uv2_scale = Vector2( 1, 1 )
|
||||
uv2_offset = Vector2( 0, 0 )
|
||||
|
||||
[sub_resource type="Environment" id=3]
|
||||
[sub_resource type="Environment" id=1]
|
||||
|
||||
background_mode = 0
|
||||
background_skybox_scale = 1.0
|
||||
|
@ -87,7 +17,7 @@ ambient_light_energy = 1.0
|
|||
ambient_light_skybox_contribution = 0.0
|
||||
ss_reflections_enabled = false
|
||||
ss_reflections_max_steps = 64
|
||||
ss_reflections_accel = 0.04
|
||||
ss_reflections_accel = 0.0
|
||||
ss_reflections_fade = 2.0
|
||||
ss_reflections_depth_tolerance = 0.2
|
||||
ss_reflections_accel_smooth = true
|
||||
|
@ -139,40 +69,130 @@ adjustment_brightness = 1.0
|
|||
adjustment_contrast = 1.0
|
||||
adjustment_saturation = 1.0
|
||||
|
||||
[sub_resource type="FixedSpatialMaterial" id=2]
|
||||
|
||||
flags_transparent = false
|
||||
flags_unshaded = false
|
||||
flags_on_top = false
|
||||
flags_use_point_size = false
|
||||
vertex_color_use_as_albedo = true
|
||||
vertex_color_is_srgb = false
|
||||
params_diffuse_mode = 0
|
||||
params_blend_mode = 0
|
||||
params_cull_mode = 0
|
||||
params_depth_draw_mode = 0
|
||||
params_line_width = 1.0
|
||||
params_point_size = 1.0
|
||||
albedo_color = Color( 1, 1, 1, 1 )
|
||||
albedo_texture = ExtResource( 2 )
|
||||
specular_mode = 0
|
||||
specular_color = Color( 0, 0, 0, 1 )
|
||||
specular_metalness = 0.0
|
||||
specular_roughness = 0.0
|
||||
emission_enabled = false
|
||||
normal_enabled = false
|
||||
rim_enabled = false
|
||||
clearcoat_enabled = false
|
||||
anisotropy_enabled = false
|
||||
ao_enabled = false
|
||||
height_enabled = false
|
||||
subsurf_scatter_enabled = false
|
||||
refraction_enabled = false
|
||||
detail_enabled = false
|
||||
uv1_scale = Vector2( 1, 1 )
|
||||
uv1_offset = Vector2( 0, 0 )
|
||||
uv2_scale = Vector2( 1, 1 )
|
||||
uv2_offset = Vector2( 0, 0 )
|
||||
|
||||
[sub_resource type="FixedSpatialMaterial" id=3]
|
||||
|
||||
flags_transparent = true
|
||||
flags_unshaded = false
|
||||
flags_on_top = false
|
||||
flags_use_point_size = false
|
||||
vertex_color_use_as_albedo = false
|
||||
vertex_color_is_srgb = false
|
||||
params_diffuse_mode = 0
|
||||
params_blend_mode = 0
|
||||
params_cull_mode = 0
|
||||
params_depth_draw_mode = 0
|
||||
params_line_width = 1.0
|
||||
params_point_size = 1.0
|
||||
albedo_color = Color( 0.7, 0.7, 0.7, 1 )
|
||||
albedo_texture = ExtResource( 2 )
|
||||
specular_mode = 0
|
||||
specular_color = Color( 0.1, 0.1, 0.1, 1 )
|
||||
specular_metalness = 0.1
|
||||
specular_roughness = 0.0
|
||||
emission_enabled = false
|
||||
normal_enabled = false
|
||||
rim_enabled = false
|
||||
clearcoat_enabled = false
|
||||
anisotropy_enabled = false
|
||||
ao_enabled = false
|
||||
height_enabled = false
|
||||
subsurf_scatter_enabled = false
|
||||
refraction_enabled = false
|
||||
detail_enabled = false
|
||||
uv1_scale = Vector2( 1, 1 )
|
||||
uv1_offset = Vector2( 0, 0 )
|
||||
uv2_scale = Vector2( 1, 1 )
|
||||
uv2_offset = Vector2( 0, 0 )
|
||||
|
||||
[sub_resource type="FixedSpatialMaterial" id=4]
|
||||
|
||||
flags_transparent = false
|
||||
flags_unshaded = false
|
||||
flags_on_top = false
|
||||
flags_use_point_size = false
|
||||
vertex_color_use_as_albedo = false
|
||||
vertex_color_is_srgb = false
|
||||
params_diffuse_mode = 0
|
||||
params_blend_mode = 0
|
||||
params_cull_mode = 0
|
||||
params_depth_draw_mode = 0
|
||||
params_line_width = 1.0
|
||||
params_point_size = 1.0
|
||||
albedo_color = Color( 1, 1, 1, 1 )
|
||||
albedo_texture = ExtResource( 2 )
|
||||
specular_mode = 0
|
||||
specular_color = Color( 0.1, 0.1, 0.1, 1 )
|
||||
specular_metalness = 0.1
|
||||
specular_roughness = 0.0
|
||||
emission_enabled = false
|
||||
normal_enabled = false
|
||||
rim_enabled = false
|
||||
clearcoat_enabled = false
|
||||
anisotropy_enabled = false
|
||||
ao_enabled = false
|
||||
height_enabled = false
|
||||
subsurf_scatter_enabled = false
|
||||
refraction_enabled = false
|
||||
detail_enabled = false
|
||||
uv1_scale = Vector2( 1, 1 )
|
||||
uv1_offset = Vector2( 0, 0 )
|
||||
uv2_scale = Vector2( 1, 1 )
|
||||
uv2_offset = Vector2( 0, 0 )
|
||||
|
||||
[node name="Node" type="Node"]
|
||||
|
||||
[node name="Camera" type="Camera" parent="."]
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
projection = 0
|
||||
fov = 80.0
|
||||
near = 0.1
|
||||
far = 500.0
|
||||
keep_aspect = 1
|
||||
current = false
|
||||
cull_mask = 1048575
|
||||
environment = null
|
||||
h_offset = 0.0
|
||||
v_offset = 0.0
|
||||
script = ExtResource( 1 )
|
||||
sensitivity = 0.4
|
||||
min_angle = -90
|
||||
max_angle = 90
|
||||
speed = 10.0
|
||||
capture_mouse = true
|
||||
environment = SubResource( 1 )
|
||||
|
||||
[node name="VoxelTerrain" type="VoxelTerrain" parent="."]
|
||||
|
||||
script = ExtResource( 2 )
|
||||
solid_material = SubResource( 1 )
|
||||
transparent_material = SubResource( 2 )
|
||||
script = ExtResource( 1 )
|
||||
solid_material = SubResource( 2 )
|
||||
transparent_material = SubResource( 3 )
|
||||
|
||||
[node name="TestCube" type="TestCube" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -4.58428 )
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.0723, -4.58428 )
|
||||
layers = 1
|
||||
material_override = null
|
||||
material_override = SubResource( 4 )
|
||||
cast_shadow = 1
|
||||
extra_cull_margin = 0.0
|
||||
use_as_billboard = false
|
||||
|
@ -185,9 +205,10 @@ lod_min_hysteresis = 0.0
|
|||
lod_max_distance = 0.0
|
||||
lod_max_hysteresis = 0.0
|
||||
|
||||
[node name="MeshInstance" type="MeshInstance" parent="."]
|
||||
[node name="Grid" type="MeshInstance" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
visible = false
|
||||
layers = 1
|
||||
material_override = null
|
||||
cast_shadow = 1
|
||||
|
@ -203,12 +224,7 @@ lod_max_distance = 0.0
|
|||
lod_max_hysteresis = 0.0
|
||||
mesh = null
|
||||
skeleton = NodePath("..")
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
environment = SubResource( 3 )
|
||||
script = ExtResource( 3 )
|
||||
|
||||
[node name="DirectionalLight" type="DirectionalLight" parent="."]
|
||||
|
||||
|
@ -258,4 +274,11 @@ directional_shadow_blend_splits = false
|
|||
directional_shadow_normal_bias = 0.1
|
||||
directional_shadow_bias_split_scale = 0.1
|
||||
|
||||
[node name="CharacterAvatar" parent="." instance=ExtResource( 4 )]
|
||||
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 22.0569, 0 )
|
||||
speed = 4.0
|
||||
gravity = 30.0
|
||||
jump_force = 10.0
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
extends Spatial
|
||||
|
||||
export var sensitivity = 0.4
|
||||
export var min_angle = -90
|
||||
export var max_angle = 90
|
||||
export var capture_mouse = true
|
||||
|
||||
var _yaw = 0
|
||||
var _pitch = 0
|
||||
|
||||
|
||||
func _ready():
|
||||
if capture_mouse:
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
|
||||
|
||||
func _input(event):
|
||||
if event.type == InputEvent.MOUSE_BUTTON:
|
||||
if event.pressed and Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
|
||||
if capture_mouse:
|
||||
# Capture the mouse
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
|
||||
elif event.type == InputEvent.MOUSE_MOTION:
|
||||
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED || not capture_mouse:
|
||||
# Get mouse delta
|
||||
var motion = event.relative_pos
|
||||
|
||||
# Add to rotations
|
||||
_yaw -= motion.x * sensitivity
|
||||
_pitch += motion.y * sensitivity
|
||||
|
||||
# Clamp pitch
|
||||
var e = 0.001
|
||||
if _pitch > max_angle-e:
|
||||
_pitch = max_angle-e
|
||||
elif _pitch < min_angle+e:
|
||||
_pitch = min_angle+e
|
||||
|
||||
# Apply rotations
|
||||
set_rotation(Vector3(0, deg2rad(_yaw), 0))
|
||||
rotate(get_transform().basis.x.normalized(), -deg2rad(_pitch))
|
||||
|
||||
elif event.type == InputEvent.KEY:
|
||||
if event.pressed:
|
||||
if event.scancode == KEY_ESCAPE:
|
||||
# Get the mouse back
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||
|
||||
elif event.scancode == KEY_I:
|
||||
var pos = get_translation()
|
||||
var fw = get_forward()
|
||||
print("Position: ", pos, ", Forward: ", fw)
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://debug_camera.gd" type="Script" id=1]
|
||||
|
||||
[node name="Camera" type="Camera"]
|
||||
|
||||
_import_transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
|
||||
projection = 0
|
||||
fov = 80.0
|
||||
near = 0.1
|
||||
far = 500.0
|
||||
keep_aspect = 1
|
||||
current = false
|
||||
cull_mask = 1048575
|
||||
environment = null
|
||||
h_offset = 0.0
|
||||
v_offset = 0.0
|
||||
script = ExtResource( 1 )
|
||||
sensitivity = 0.4
|
||||
min_angle = -90
|
||||
max_angle = 90
|
||||
speed = 10.0
|
||||
capture_mouse = true
|
||||
|
||||
|
|
@ -11,22 +11,42 @@ var _generator = null
|
|||
|
||||
|
||||
func _ready():
|
||||
|
||||
_library.set_atlas_size(4)
|
||||
|
||||
_library.create_voxel(0, "air").set_transparent()
|
||||
_library.create_voxel(1, "grass_dirt").set_cube_geometry().set_cube_uv_tbs_sides(Vector2(0,0), Vector2(0,1), Vector2(1,0))
|
||||
_library.create_voxel(2, "dirt").set_cube_geometry().set_cube_uv_all_sides(Vector2(1,0))
|
||||
_library.create_voxel(3, "log").set_cube_geometry().set_cube_uv_tbs_sides(Vector2(3,0), Vector2(3,0), Vector2(2,0))
|
||||
_library.create_voxel(4, "water").set_transparent().set_cube_geometry(15.0/16.0).set_cube_uv_all_sides(Vector2(2,1)).set_material_id(1)
|
||||
|
||||
_library.create_voxel(1, "grass_dirt") \
|
||||
.set_cube_geometry() \
|
||||
.set_cube_uv_tbs_sides(Vector2(0,0), Vector2(0,1), Vector2(1,0))
|
||||
|
||||
_library.create_voxel(2, "dirt") \
|
||||
.set_cube_geometry() \
|
||||
.set_cube_uv_all_sides(Vector2(1,0))
|
||||
|
||||
_library.create_voxel(3, "log") \
|
||||
.set_cube_geometry() \
|
||||
.set_cube_uv_tbs_sides(Vector2(3,0), Vector2(3,0), Vector2(2,0))
|
||||
|
||||
_library.create_voxel(4, "water") \
|
||||
.set_transparent() \
|
||||
.set_cube_geometry(15.0/16.0) \
|
||||
.set_cube_uv_all_sides(Vector2(2,1)) \
|
||||
.set_material_id(1)
|
||||
|
||||
var mesher = get_mesher()
|
||||
mesher.set_library(_library)
|
||||
mesher.set_material(solid_material, 0)
|
||||
mesher.set_material(transparent_material, 1)
|
||||
mesher.set_occlusion_enabled(true)
|
||||
mesher.set_occlusion_darkness(1.0)
|
||||
|
||||
set_generate_collisions(true)
|
||||
|
||||
#set_provider(CustomProvider.new())
|
||||
var provider = VoxelProviderTest.new()
|
||||
provider.set_mode(VoxelProviderTest.MODE_WAVES)
|
||||
provider.set_pattern_size(Vector3(10,20,10))
|
||||
provider.set_pattern_size(Vector3(10,5,10))
|
||||
set_provider(provider)
|
||||
# var map = get_map()
|
||||
# for x in range(0, 50):
|
||||
|
@ -38,7 +58,7 @@ func _ready():
|
|||
# map.set_voxel(v, x, y-10, z)
|
||||
# map.set_voxel(0, 50,50,50)
|
||||
|
||||
force_load_blocks(Vector3(0,0,0), Vector3(12,4,12))
|
||||
force_load_blocks(Vector3(0,0,0), Vector3(16,4,16))
|
||||
# var Testouille = preload("debug_camera.gd")
|
||||
# var t = Testouille.new()
|
||||
# t.lolance()
|
||||
|
|
Loading…
Reference in New Issue