内容简介:1.ticker$ 数据流 interval配合scheduler/animationFrame 作为游戏随时间变化的控制数据流2.key$ 数据流检测keydown/keyup 玩家控制的部分(整个状态中的一个副作用),改变底部船桨的位置
效果图
数据流分析
1.ticker$ 数据流 interval配合scheduler/animationFrame 作为游戏随时间变化的控制数据流
ticker$ = interval(this.TICKER_INTERVAL, animationFrame).pipe( map(() => ({ time: Date.now(), deltaTime: null })), scan((previous, current) => ({ time: current.time, deltaTime: (current.time - previous.time) / 1000 })) ); // Observable单播 每次订阅都是启动一个数据流
2.key$ 数据流检测keydown/keyup 玩家控制的部分(整个状态中的一个副作用),改变底部船桨的位置
PADDLE_CONTROLS = { ArrowLeft: -1, ArrowRight: 1 }; key$ = merge( fromEvent(document, 'keydown').pipe( map(event => this.PADDLE_CONTROLS[event['key']] || 0) ), fromEvent(document, 'keyup').pipe(map(event => 0)) ).pipe(distinctUntilChanged()); // 提供船桨移动的方位的数据源
实现逻辑:按下‘<’直到 keyup 输出 -1 / 按下‘>’直到 keyup 输出 1 / keyup 输出 0 3.paddle$ 数据流使用操作符withLatestFrom合并了ticker$和key$ 持续流出船桨的位置
createPaddle$(ticker$: Observable<{ time: number; deltaTime: any }>) { return ticker$.pipe( withLatestFrom(this.key$), // withLatestFrom操作符 作为游戏开始的触发条件,只有这个数据流产生数据才会往下游流动 scan<[{ deltaTime: number; time: number }, number], number>( (position: number, [ticker, direction]) => { const nextPosition = position + direction * ticker.deltaTime * this.PADDLE_SPEED; return Math.max( Math.min( nextPosition, this.breakoutCanvasService.stage.width - config.PADDLE_WIDTH / 2 ), config.PADDLE_WIDTH / 2 ); }, this.breakoutCanvasService.stage.width / 2 ), distinctUntilChanged() ); }
3.createState$ 数据流使用withLatestFrom合并ticker$和paddle$ 最终输出界面需要的全部状态数据
createState$(ticker$, paddle$) {
return ticker$.pipe(
withLatestFrom(paddle$),
scan<
[{ deltaTime: number; time: number }, number], { ball: Ball; bricks: Brick[]; score: number }
>(({ ball, bricks, score }, [ticker, paddle]) => { const remainingBricks = [];
const collisions = { paddle: false, // 球撞船桨 floor: false, // wall: false, // 撞墙 ceiling: false, // 撞顶 brick: false // 球撞砖块 };
ball.position.x = ball.position.x + ball.direction.x * ticker.deltaTime * this.BALL_SPEED; ball.position.y = ball.position.y + ball.direction.y * ticker.deltaTime * this.BALL_SPEED;
bricks.forEach(brick => { if (!this.isCollision(brick, ball)) { remainingBricks.push(brick); } else { collisions.brick = true; score = score + 10; } });
collisions.paddle = this.isHit(paddle, ball);
if (
ball.position.x < config.BALL_RADIUS || ball.position.x >
this.breakoutCanvasService.stage.width - config.BALL_RADIUS
) {
ball.direction.x = -ball.direction.x; collisions.wall = true;
}
collisions.ceiling = ball.position.y < config.BALL_RADIUS;
if (collisions.brick || collisions.paddle || collisions.ceiling) {
if (collisions.paddle) {
ball.direction.y = -Math.abs(ball.direction.y);
} else {
ball.direction.y = -ball.direction.y; }
}
return { ball: ball, bricks: remainingBricks, collisions: collisions, score: score }; }, this.initState()) ); }
- 用到ticker$流控制球的移动位置
- 根据当前状态控制下一步的状态,包括计分、球的运动方向、砖块数量
4.game$ 数据流最终的游戏控状态输出流(包括这状态数据、船桨位置数据)
game$ = Observable.create(observer => { this.breakoutCanvasService.drawIntro(); this.restart = new Subject(); const paddle$ = this.createPaddle$(this.ticker$); // 数据源吐出船桨的位置 const state$ = this.createState$(this.ticker$, paddle$); this.ticker$ .pipe( withLatestFrom(paddle$, state$), OperatorMerge(this.restart) ) .subscribe(observer); // 这个this.ticker$ 也可以不使用,直接通过merge合并后面两个数据流 });
merge数据流restart$后 可以通过error方法终止流从而控制游戏结束
状态
两个结果状态:砖块数量、分数
两个影响状态的副作用:时间、游戏者的行为
状态交叉点
球接触砖块 -> 砖块消失
球接触船桨/墙 -> 球自然改变运动方向
整个过程用rxjs实现不需要额外保存中间数据,在管道中实现数据的缓存、状态处理 。
两个字形容 “优秀”
演示地址: http://tiny.pubuzhixing.com/
github: https://github.com/pubuzhixing8/tiny-game
出处:《深入浅出RxJS》十四章实例,使用TS+Angular重新包装,修改了一个小缺陷,据说这个游戏最初是由乔布斯和他的一个朋友设计
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 微软放弃的游戏被他们复活了:Windows经典「三维弹球」现实版,CAD建模、Arduino编程、数控机床打造,...
- 「Flask实战」鱼书项目实战一
- 「Flask实战」鱼书项目实战三
- 「Flask实战」鱼书项目实战四
- 「Flask实战」鱼书项目实战六
- RocketMQ实战系列从理论到实战
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Build Your Own Web Site the Right Way Using HTML & CSS
Ian Lloyd / SitePoint / 2006-05-02 / USD 29.95
Build Your Own Website The Right Way Using HTML & CSS teaches web development from scratch, without assuming any previous knowledge of HTML, CSS or web development techniques. This book introduces you......一起来看看 《Build Your Own Web Site the Right Way Using HTML & CSS》 这本书的介绍吧!