DirectX学习笔记_关于Sprite.Draw2D的说明

本文详细介绍了DirectX Sprite的Draw2D方法,特别是纹理旋转轴点坐标的使用技巧。通过实例演示,阐述了如何正确设置轴点坐标以实现纹理的精确旋转,并解释了纹理大小与实际图片大小的关系。
在DirectX的Sprite中提供一个Draw2D的方法,该方法绘制一个Sprite对象用于二维空间中显示,在DirectX 9.0C中,该方法有6个重载,分别是 
1 public void Draw2D(Texture srcTexture, PointF rotationCenter, float rotationAngle, PointF position, Color color);
2 public void Draw2D(Texture srcTexture, PointF rotationCenter, float rotationAngle, PointF position, int color);
3 public void Draw2D(Texture srcTexture, Rectangle srcRectangle, SizeF destinationSize, PointF position, Color color);
4 public void Draw2D(Texture srcTexture, Rectangle srcRectangle, SizeF destinationSize, PointF position, int color);
5 public void Draw2D(Texture srcTexture, Rectangle* srcRectangle, SizeF* destinationSize, PointF* center, float rotationAngle, PointF position, int color);
6 public void Draw2D(Texture srcTexture, Rectangle srcRectangle, SizeF destinationSize, PointF rotationCenter, float rotationAngle, PointF position, Color color);
7 public void Draw2D(Texture srcTexture, Rectangle srcRectangle, SizeF destinationSize, PointF rotationCenter, float rotationAngle, PointF position, int color);

这里我将以 
 public void Draw2D(Texture srcTexture, Rectangle srcRectangle, SizeF destinationSize, PointF rotationCenter, float rotationAngle, PointF position, Color color);作为例子来说明该方法实现的效果,其余重载函数均是参数个数和类型不同。
参数说明(*注意:我们所说的纹理大小和实际图片大小不同,即纹理的高宽并不等于实际图片的高宽,稍后会有说明)
Texture srcTexture——源纹理;
Rectangle srcRectangle——显示纹理的矩形范围,由矩形左上角坐标和宽高共4个参数描述,当矩形范围小于源纹理大小时可用于切割图片,指定Empty不使用;
SizeF destinationSize——纹理的高宽,可用于缩放纹理,指定Empty为使用源纹理大小;
PointF rotationCenter——纹理旋转轴点坐标,在给该参数赋值时需要注意两个情况,一个是轴点在纹理范围内,一个是在纹理外,两种情况下赋值不一样,稍后说明;
float rotationAngle——旋转度数,此处使用弧度为计量单位;
PointF position——纹理显示位置,即纹理左上角坐标,决定纹理在哪里进行绘制;
Color color——颜色覆盖,取White时候透明处理;

当图片通过TextureLoader.FromFile()加载进来后,给方法把原始图片解释为一个纹理,此时纹理的大小不再是原始图片的大小,也就是说纹理的高宽和于是图片的高宽在数值上并不相等,纹理的大小为2的幂。
1 Texture srcTexture = TextureLoader.FromFile(device, imagePath//图片路径);

Render()渲染方法
1 public override void Render2D()
2 {
3        sprite.Begin(SpriteFlags.AlphaBlend);//开始绘制
4        
5        sprite.Draw2D(srcTexture, Rectangle.Empty,new SizeF(100,100), PointF.Empty, 0.0fnew PointF(5050), Color.White);  //基本绘制 
6 
7        sprite.End();//结束绘制
8             
9 }
上述代码中,我们将纹理绘制在50×50处,其他参数使用默认,测试用图片大小为100×100

但纹理绘制出来以后会发现 此时纹理的高宽并不是100×100,而是128×128,(纹理的大小为2的幂),如果要显示与原始图片大小相同的纹理,则将第三个参数改为new SizeF(100,100)即可:(我们可以通过GetLevelDescription()方法来获取纹理的高宽)
1 public override void Render2D()
2 {
3        sprite.Begin(SpriteFlags.AlphaBlend);//开始绘制
4        
5        sprite.Draw2D(srcTexture, Rectangle.Empty,new SizeF(100,100), PointF.Empty, 0.0fnew PointF(5050), Color.White);  //基本绘制 
6 
7        sprite.End();//结束绘制
8             
9 }

下面我们来讨论关于第4个参数
纹理旋转轴点坐标。
刚才我们说到这个参数的赋值分不同的情况考虑,如果指定为Empty则以纹理左上角坐标为轴点坐标。
设定条件为 纹理位置(左上角坐标)为(10,10),原始图片高宽为100*100,我们想让图片以自己的中心点为轴点旋转,照常理,此时轴点坐标应该为(60,60),当我们将此作为轴点坐标传入方法运行后发现 图形并没有以自己的中心点为轴点旋转,而是偏离了一些。

此时回到最初的问题,纹理的大小并不是100*100,而是128*128,那我们传入(69,69)应该就是对的了,于是我们再次运行发现还是不对。

正确的赋值应该是(64,64),即128的一半。

于是我们得到以下规律
如果需要纹理以本身纹理以外的点为轴点旋转,传入该点坐标即可,如果我们需要以纹理范围内的点为轴点则需要换算坐标信息,例如中点 比例是1/2,所以将比例系数乘以128(128可以通过
GetLevelDescription()获取)!
角色在原地不停抽动可能是由于速度的更新或者动画状态的切换出现了问题,以下是一些可能的修正方法: #### 1. 确保速度在合适的状态下更新 在滑铲结束后,速度被设置为 0,但可能在其他地方又被意外地更新了。要确保在滑铲状态下,速度的更新逻辑是正确的。 #### 2. 检查动画状态的切换 确保动画状态的切换是平滑的,避免在不应该切换的时候进行切换。 以下是修正后的代码示例: ```gdscript enum State { NORMAL, TO_SLIDE, SLIDE, SLIDE_OUT, CROUCH } var current_state = State.NORMAL @onready var animated_sprite = $AnimatedSprite2D var slide_direction = 1 @onready var normal_collision = $NormalCollisionShape2D @onready var crouch_collision = $CrouchCollisionShape2D @onready var slide_collision = $SlideCollisionShape2D var velocity = Vector2.ZERO var gravity = 300 var SPEED = 200 func start_slide(): current_state = State.TO_SLIDE animated_sprite.play("toslide") animated_sprite.flip_h = slide_direction < 0 normal_collision.disabled = true crouch_collision.disabled = true slide_collision.disabled = false velocity.x = slide_direction * SPEED * 1.8 func enter_slide(): current_state = State.SLIDE animated_sprite.play("slide") func end_slide(): current_state = State.SLIDE_OUT animated_sprite.play("slideout") velocity.x = 0 func back_to_crouch(): current_state = State.CROUCH normal_collision.disabled = true crouch_collision.disabled = false slide_collision.disabled = true func _input(event): if event.is_action_pressed("slide"): start_slide() elif event.is_action_released("slide"): end_slide() func _physics_process(delta): if not is_on_floor(): velocity.y += gravity * delta if current_state == State.TO_SLIDE and animated_sprite.is_playing() == false: enter_slide() elif current_state == State.SLIDE_OUT and animated_sprite.is_playing() == false: back_to_crouch() # 确保在滑铲状态下,速度不会意外更新 if current_state == State.SLIDE: velocity.x = slide_direction * SPEED * 1.8 move_and_slide(velocity, Vector2.UP) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值