摇杆设计和主角鱼的移动
通过触屏操作设计摇杆实现主角鱼的移动
首先定义遥杆,使用两个Circle组件绘制两个半径不同的圆,较小的圆形作为遥杆可以移动,较大的圆形作为较小圆的移动范围,并添加处理用户触屏操作的事件
import router from '@ohos.router'
import curves from '@ohos.curves'
import NpcInfo from '../viewmodel/NpcInfo';
import npcView from '../view/npcView'
@Entry
@Component
struct AnimationPage {
@State screenHeight:number=1440;
@State screenWidth:number=2200;
@State fishSize:number=200
// 小鱼坐标
@State fishX: number = 200
@State fishY: number = 120
// 小鱼角度
@State angle: number = 0
// 小鱼图片
@State src: Resource = $r('app.media.fish')
// 是否开始游戏
@State isBegin: boolean = false
// 摇杆中心区域坐标
private centerX: number = 120
private centerY: number = 120
// 大、小圆半径
private maxRadius: number = 200
private radius: number = 60
// 摇杆小圆球初始位置
@State positionX: number = this.centerX;
@State positionY: number = this.centerY;
// 角度正弦和余弦
sin: number = 0
cos: number = 0
// 小鱼移动速度
speed: number = 0
// 任务id
taskId: number = -1
build() {
Row() {
Stack(){
// 返回按钮
Button('BACK')
.position({x:30, y: 30})
.backgroundColor('#20101010')
.onClick(() => {
// 返回上一页
router.back()
})
.fontSize(50)
.width(200)
.height(100)
// 开始按钮和小鱼
if(!this.isBegin){
// 开始按钮
Button('GAME START')
.onClick(() => {
animateTo(
{duration: 1000},
() => {
//点击后显示小鱼
this.isBegin = true
}
)
})
.fontSize(85)
.width(600)
.height(200)
}else{
// 小鱼图片
Image(this.src)
.position({x: this.fishX, y: this.fishY})
.rotate({angle:this.angle, centerX: '50%', centerY: '50%'})
.width(this.fishSize)
.height(this.fishSize)
.transition({
type: TransitionType.Insert,
opacity: 0,
translate: {x: -250}
})
}
// 摇杆
Row(){
Circle({width: this.maxRadius * 2, height: this.maxRadius * 2})
.fill('#20101010')
.position({ x: this.centerX-this.maxRadius, y: this.centerY-this.maxRadius })
Circle({ width: this.radius * 2, height: this.radius * 2 })
.fill('#403A3A3A')
.position({ x: this.positionX - this.radius, y: this.positionY - this.radius})
}
.height(440)
.width(440)
.justifyContent(FlexAlign.Center)
.position({x:100,y:1050})
.onTouch(this.handleTouchEvent.bind(this))
}
自定义触屏事件
实现了摇杆跟随触屏移动但不会超过外面的大圆范围,在触屏事件停止发生即手指离开时让摇杆回到原来的坐标位置,并且实现小鱼根据摇杆操控移动
首先利用event.touch得到手指的位置,再计算手指与中心点的差值vx,vy,通过差值利用tan函 数计算夹角angle,之后再利用得到的夹角计算出出手指离中心点的距离
代码如下:
handleTouchEvent(event: TouchEvent){
switch (event.type){
case TouchType.Up:
// 还原小鱼速度
this.speed = 0
// 取消定时任务
clearInterval(this.taskId)
// 还原摇杆小球的坐标
animateTo(
{curve: curves.springMotion()},
() => {
this.positionX = this.centerX
this.positionY = this.centerY
this.angle = 0
}
)
break
case TouchType.Down:
// 开始定时任务
this.taskId = setInterval(() => {
this.fishX += this.speed * this.cos
this.fishY += this.speed * this.sin
this.eatFish()
//console.log("opacity:"+this.opacitycnt.toString())
}, 40)
break
case TouchType.Move:
// 1.获取手指位置坐标
let x = event.touches[0].x
let y = event.touches[0].y
// 2.计算手指与中心点的坐标差值
let vx = x - this.centerX
let vy = y - this.centerY
// 3.计算手指与中心点连线和x轴正半轴的夹角,单位是弧度
let angle = Math.atan2(vy, vx)
// 4.计算手指与中心点的距离
let distance = this.getDistance(vx, vy)
this.sin = Math.sin(angle)
this.cos = Math.cos(angle)
//加上动画使得摇杆移动更丝滑
animateTo(
{curve: curves.responsiveSpringMotion()},//可以提供自然和流畅的动画曲线
() => {
// 5.计算摇杆小球的坐标
this.positionX = this.centerX + distance * this.cos
this.positionY = this.centerY + distance * this.sin
// 6.修改小鱼的角度
if(Math.abs(angle * 2) < Math.PI){
this.src = $r('app.media.fish')
}else{
this.src = $r('app.media.fish_rev')
angle = angle < 0 ? angle + Math.PI : angle - Math.PI
}
this.angle = angle * 180 / Math.PI
// console.log(this.speed.toString())
this.speed = 20;//小鱼移动的速度
}
)
break
}
}
getDistance(x: number, y: number){
let d = Math.sqrt(x * x + y * y)
return Math.min(d, this.maxRadius)
}