I have try something, but don’t know if it can work. I recreate the behaviour of the ninepatch for a sprite node (this way it’s not a control node).
Here is the script :
SpritePlateform
@tool
class_name Plateform
extends Sprite2D
# Plateform width in pixel
@export var plateform_width : int = 60:
get:
return plateform_width
set(value):
plateform_width = value
_refresh_texture()
# Movement start from editor position to this position
@export var move_to: Vector2
# Speed of the plateform
@export var speed: float = 80
@export_category("Texture")
# Texture use to generate the plateform texture
@export var plateform_texture: Texture2D :
get:
return plateform_texture
set(value):
plateform_texture = value
_refresh_texture()
# Type of stretch (see ninepatch for more info)
@export_enum("Stretch", "Tile", "Tile Fit") var stretch_mode : int = 0:
get:
return stretch_mode
set(value):
stretch_mode = value
_refresh_texture()
# Only left and right margin is used and same way as ninepatch
@export_group("Margin")
@export var left : int = 0:
get:
return left
set(value):
left = value
_refresh_texture()
@export var right : int = 0:
get:
return right
set(value):
right = value
_refresh_texture()
# Recreate texture when parameters changes
func _refresh_texture():
# If no texture is defined return
if plateform_texture == null: return
var base_texture = plateform_texture.get_image()
var base_size = plateform_texture.get_size()
var base_format = base_texture.get_format()
# Create a new image with good width (cannot be under left+right margin width)
var plateforme_image = Image.create(max(plateform_width, left + right), base_size.y, false, base_format)
# Add left and right part
plateforme_image.blit_rect(base_texture, Rect2i(0, 0, left, base_size.y), Vector2i.ZERO)
plateforme_image.blit_rect(base_texture, Rect2i(base_size.x - right, 0, right, base_size.y), Vector2i(plateform_width - right, 0))
# If size inbetween is to small, stop here
if (plateform_width - left - right <= 0):
texture = ImageTexture.create_from_image(plateforme_image)
return
# Get filter for stretch and tile fit mode
var filter = ProjectSettings.get_setting("rendering/textures/canvas_textures/default_texture_filter")
# Get middle part of the texture
var part_middle = Image.create(base_size.x - left - right, base_size.y, false, base_format)
part_middle.blit_rect(base_texture, Rect2i(left, 0, plateform_width - left - right, base_size.y), Vector2i.ZERO)
var w = plateform_width - left - right;
var h = base_size.y
if (stretch_mode == 0): # Stretch mode
part_middle.resize(w, h, filter)
plateforme_image.blit_rect(part_middle, Rect2i(0, 0, w, h), Vector2i(left, 0))
elif (stretch_mode == 1): # Tile mode
var x = 0;
var dx = base_size.x - left - right
while x <= w:
plateforme_image.blit_rect(part_middle, Rect2i(0, 0, min(dx, w - x), h), Vector2i(left + x, 0))
x += dx;
elif (stretch_mode == 2): # Tile fit mode
var dx = base_size.x - left - right
var part_middle2 = Image.create(floor(w / dx) * dx, base_size.y, false, base_format)
for i in range(floor(w / dx)):
part_middle2.blit_rect(part_middle, Rect2i(0, 0, dx, h), Vector2i(i * dx, 0))
part_middle2.resize(w, h, filter)
plateforme_image.blit_rect(part_middle2, Rect2i(0, 0, w, h), Vector2i(left, 0))
# Assign texture to the sprite2D texture
texture = ImageTexture.create_from_image(plateforme_image)
@onready var collision_shape_2d: CollisionShape2D = $AnimatableBody2D/CollisionShape2D
@onready var animatable_body_2d: AnimatableBody2D = $AnimatableBody2D
@onready var start_position = position
# The position to which the platform is moving
var target_position: Vector2;
func _ready() -> void:
# Match the size of the collider with the size of the sprite
var rect: RectangleShape2D = collision_shape_2d.shape
var base_size = texture.get_size()
rect.size.x = base_size.x - 4
rect.size.y = base_size.y
# Init moving points
target_position = move_to
func _physics_process(delta: float) -> void:
if not Engine.is_editor_hint():
# If the platform reaches the target position, change it
if position.is_equal_approx(target_position):
target_position = start_position if target_position == move_to else move_to
# Move the NinePatchRect
position = lerp(position, position.move_toward(target_position, delta * 80), 0.5)
# For some reason the animatable body must be moved separately ???
animatable_body_2d.global_position = position
It’s a simplified version (its not a real ninepatch anymore, it can only expend left and right). Attach it to a Sprite2D and set your plateforme texture in the “plateform texture” property living the sprite2D original texture blank. The script will generate the texture based on the size of the plateform.
Hope this can get rid of jittering