TypeScript-左右躲避障碍-神手

学习typescript,第一步应该是学习官方文档,理解最基础的语法。第二步开始用typescript实现一些js+css 或者canvas类型的游行。现在开始我们用ts写跳一跳

前言:

  最近微信小程序里面,出现了一个左右手躲避障碍物的游戏:神手。玩了一下觉得很有意思,决定用typescript写一版。

核心点:

  1.识别手势动作:双指同时点击,单指随机放开

  2.障碍物的成对生成。

  3.动画帧的优化

游戏截图

  

Typescript脚本:

  

  1 //1.创建障碍
  2 //2.移动障碍
  3 //3.小球控制
  4 //4.碰撞检测
  5 module game {
  6
  7     interface FootBall {
  8         node: JQuery<HTMLElement>;
  9         track: Track;
 10     }
 11     enum Direction {
 12         left, right
 13     }
 14     enum Track {
 15         one, two, three, four
 16     }
 17     let mask: JQuery<HTMLElement> = $(".game");
 18     let speed: number = 10;
 19     let score: number = 0;
 20     let rblist: Array<RandBox> = [];
 21     let roadList: Array<Road> = [];
 22     let ft1: FootBall = { node: $("#ft1"), track: Track.two };
 23     let ft2: FootBall = { node: $("#ft2"), track: Track.three };
 24     //h5的专门适应绘制动画的属性
 25     window.requestAnimationFrame =
 26         window.requestAnimationFrame ||
 27         window.webkitRequestAnimationFrame ||
 28         (function () {
 29             return function (callback: Function, element: { __lastTime: number }) {
 30                 var lastTime = element.__lastTime;
 31                 if (lastTime === undefined) {
 32                     lastTime = 0;
 33                 }
 34                 var currTime = Date.now();
 35                 var timeToCall = Math.max(1, 33 - (currTime - lastTime));
 36                 window.setTimeout(callback, timeToCall);
 37                 element.__lastTime = currTime + timeToCall;
 38             };
 39         })();
 40     window.cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame;
 41     let requestAnimationFrameFlag = 0;
 42     class MathHelp {
 43         /**
 44          * 返回范围内随机数[min,max]
 45          * @param min 最小值
 46          * @param max 最大值
 47          */
 48         static RandRange(min: number, max: number): number {
 49             return Math.floor(Math.random() * (max - min + 1) + min);
 50         }
 51     }
 52     export class Road {
 53         top: number = 0;
 54         id: number = 0;
 55         heigth: number = document.documentElement.clientHeight;
 56         node: JQuery<HTMLElement> = $('');
 57         static num: number = 0;
 58         constructor() {
 59             this.id = Road.num;
 60             this.top = -(Road.num) * this.heigth;
 61             this.node = $(`<div id="${this.id}" class="road" style="top:${this.top}px;"></div>`);
 62             mask.append(this.node);
 63             Road.num++;
 64         }
 65         move() {
 66             this.top += speed;
 67             this.node.css({
 68                 top: this.top + "px"
 69             });
 70             //循环路面
 71             if (this.top >= this.heigth) {
 72                 this.top -= Road.num * this.heigth;
 73             }
 74         }
 75     }
 76     export class RandBox {
 77
 78         left: number = 0;
 79         top: number = -100;
 80         heigth: number = 80;
 81         width: number = 80;
 82         node: JQuery<HTMLElement> = $('');
 83         type: Direction = Direction.left;
 84         id: string = "p" + new Date().getTime();
 85         track: Track = Track.one;
 86         constructor(p: number = 0) {
 87             this.top = p;
 88         }
 89         createrb(type: Direction) {
 90             this.type = type;
 91             let r = 0;
 92             if (type == Direction.left) {
 93                 r = MathHelp.RandRange(0, 1);
 94             } else {
 95                 r = MathHelp.RandRange(2, 3);
 96             }
 97             this.track = r;
 98             //计算所属赛道
 99             this.left = 70 + 126 * r + (126 - this.width) / 2;
100             this.node = $(`<div id="${this.id}" class='rb'style='left:${this.left}px;top:${this.top}px;    background-image:url(img/c${MathHelp.RandRange(1, 4)}.png);'></div>`);
101             mask.append(this.node);
102         }
103         move() {
104             this.top += speed;
105             this.node.css({
106                 top: this.top + "px"
107             });
108             //碰撞检测
109             if (this.top >= 870 && this.top < 950) {
110                 if (this.track == ft1.track || this.track == ft2.track) {
111                     scence.gameover();
112                     return false;
113                 }
114             }
115             return true;
116         }
117     }
118
119     export class scence {
120         static timer: number;
121         static Init() {
122             //重新开始
123             $(".againBtn").on("click", () => {
124                 scence.restart();
125             });
126             //创建路面
127             for (let i = 0; i < 3; i++) {
128                 let road = new Road();
129                 roadList.push(road);
130             }
131             //最开始给一对障碍,此后是每秒一对
132             scence.makeDoubleRb(450);
133             //开始游戏(可以绑定到开始按钮)
134             scence.start();
135         }
136         static start() {
137             scence.loadlisten();
138             //场景平移
139             let move = () => {
140                 let status = true;
141                 $.each(rblist, (i, item) => {
142                     if (!item.move()) {
143                         status = false;
144                         return false;
145                     }
146
147                 });
148                 if (status) {
149                     $.each(roadList, (i, item) => {
150                         item.move();
151                     });
152                     requestAnimationFrameFlag = requestAnimationFrame(move);
153                 } else {
154                     cancelAnimationFrame(requestAnimationFrameFlag);
155                 }
156             }
157             move();
158             //积分及创建障碍
159             scence.timer = setInterval(() => {
160                 score++;
161                 speed++;
162                 $(".jfb").html(score.toString());
163                 scence.makeDoubleRb();
164                 //移除超出屏幕路障
165                 rblist.forEach((item, i) => {
166
167                     if (item.top > 1200) {
168                         $("#" + item.id).remove();
169                         rblist.splice(i, 1);
170                     }
171                 })
172             }, 1000);
173
174         }
175         static gameover() {
176             clearInterval(scence.timer);
177             $(".gameEnd").show();
178             $(".score").html(score.toString());
179             scence.removelisten();
180             //小车回到原始位置
181             ft1.node.animate({
182                 left: "235px"
183             }, 50);
184             ft1.track = Track.two;
185             ft2.node.animate({
186                 left: "360px"
187             }, 50);
188             ft2.track = Track.three;
189         }
190         static restart() {
191             speed = 10;
192             score = 0;
193             $(".rb").remove();
194             rblist = [];
195             $(".jfb").html(score.toString());
196             $(".gameEnd").hide();
197             scence.start();
198         }
199         //创建成对出现的障碍
200         static makeDoubleRb(top?: number) {
201             let RB1 = new game.RandBox(top);
202             RB1.createrb(Direction.left);
203             rblist.push(RB1);
204             let RB2 = new game.RandBox(top);
205             RB2.createrb(Direction.right);
206             rblist.push(RB2);
207         }
208         private static loadlisten() {
209             document.addEventListener('touchstart', scence.touch, false);
210             document.addEventListener('touchmove', scence.touch, false);
211             document.addEventListener('touchend', scence.touch, false);
212         }
213         private static removelisten() {
214             document.removeEventListener('touchstart', scence.touch, false);
215             document.removeEventListener('touchmove', scence.touch, false);
216             document.removeEventListener('touchend', scence.touch, false);
217         }
218         private static touch(e: TouchEvent) {
219             e.preventDefault();
220             if (e.type == "touchstart") {
221                 if (e.touches.length == 1) {
222                     //一指的情况
223                     let x1 = e.touches[0].clientX;
224                     if (x1 < 320) {
225                         //左边
226                         ft1.node.animate({
227                             left: "112px"
228                         }, 50);
229                         ft1.track = Track.one;
230
231                     } else {
232                         //右边
233                         ft2.node.animate({
234                             left: "490px"
235                         }, 50);
236                         ft2.track = Track.four;
237                     }
238                 } else if (e.touches.length == 2) {
239                     //两指手指的情况
240                     let x1 = e.touches[0].clientX;
241                     let x2 = e.touches[1].clientX;
242                     let a = x1 < 320 ? 0 : 1;
243                     let b = x2 < 320 ? 0 : 1;
244                     if (a + b == 0) {
245
246                         //两指都在左边
247                         ft1.node.animate({
248                             left: "112px"
249                         }, 50);
250                         ft1.track = Track.one;
251
252                     } else if (a + b == 1) {
253                         //两指一左一右
254                         ft1.node.animate({
255                             left: "112px"
256                         }, 50);
257                         ft1.track = Track.one;
258                         ft2.node.animate({
259                             left: "490px"
260                         }, 50);
261                         ft2.track = Track.four;
262                     } else if (a + b == 2) {
263                         //两指都在右边
264                         ft2.node.animate({
265                             left: "490px"
266                         }, 50);
267                         ft2.track = Track.four;
268                     }
269                 }
270
271             } else if (e.type == "touchend") {
272
273                 if (e.touches.length == 0) {
274                     //放开两指
275                     ft1.node.animate({
276                         left: "235px"
277                     }, 50);
278                     ft1.track = Track.two;
279                     ft2.node.animate({
280                         left: "360px"
281                     }, 50);
282                     ft2.track = Track.three
283                 } else if (e.touches.length == 1) {
284                     //放开一指
285                     let x1 = e.touches[0].clientX;
286                     if (x1 > 320) {
287                         //放开的左边
288                         ft1.node.animate({
289                             left: "235px"
290                         }, 50);
291                         ft1.track = Track.two;
292                     } else {
293                         //放开的右边
294                         ft2.node.animate({
295                             left: "360px"
296                         }, 50);
297                         ft2.track = Track.three
298                     }
299                 }
300             }
301         }
302     }
303
304 }
305
306 game.scence.Init();

View Code

html代码

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /><script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script><script type="text/javascript">var isios = false;! function(userAgent) {var screen_w = parseInt(window.screen.width),scale = screen_w / 640;console.log(scale);if(/Android (\d+\.\d+)/.test(userAgent)) {var version = parseFloat(RegExp.$1);document.write(version > 2.3 ? '<meta name="viewport" content="width=640, initial-scale = ' + scale + ',user-scalable=1, minimum-scale = ' + scale + ', maximum-scale = ' + scale + ', target-densitydpi=device-dpi">' : '<meta name="viewport" content="width=640, target-densitydpi=device-dpi">');} else {isios = true;document.write('<meta name="viewport" content="width=640, initial-scale = ' + scale + ' ,minimum-scale = ' + scale + ', maximum-scale = ' + scale + ', user-scalable=no, target-densitydpi=device-dpi">');}}(navigator.userAgent);</script><style>html,body {margin: 0;padding: 0;height: 100%;width: 100%;overflow: hidden;}.game {height: 100%;width: 100%;background-size: 100% auto;position: relative;left: 0;top: 0;}.road{height: 100%;width: 100%;background: url(img/road.jpg) no-repeat;background-size: 100% 100%;position: absolute;left: 0;top: 0;z-index: 10;}.rb {height: 80px;width: 80px;position: absolute;left: 70px;top: 70px;background-position: left top;background-size: 100% 100%;/*    animation: move 5s linear;*/z-index: 11;}.ft {height: 139px;width: 63px;/*border-radius: 25px;*/background-image: url(img/tyn.png);background-position: left top;background-size: 100% 100%;position: absolute;bottom: 50px;left: 235px;z-index: 11;}#ft1 {/*animation: football1 1.5s linear infinite;*/}#ft2 {left: 360px;/*animation: football2 1.5s linear infinite;*/}@keyframes football2 {from {transform: rotate(0deg);}to {transform: rotate(360deg);}}@keyframes football1 {from {transform: rotate(0deg);}to {transform: rotate(-360deg);}}@keyframes move {from {top: 0px;}to {top: 1300px;}}.gameEnd {position: absolute;top: 0;left: 0;width: 100%;height: 100%;overflow: hidden;background-color: rgba(0, 0, 0, .8);z-index: 999;display: none;}.getScore {width: 492px;height: 760px;background: url(img/getScore.png) no-repeat;background-size: 100% auto;position: absolute;top: 0;right: 0;left: 0;bottom: 0;margin: auto;}.score {color: #dcc226;font-size: 130px;text-align: center;margin-top: 120px;font-weight: 900;}.againBtn {width: 309px;height: 87px;background: url(img/bg.png) no-repeat;background-size: 100% 100%;font-size: 40px;color: #dcc226;text-align: center;border: none;font-weight: 900;position: absolute;left: 50%;margin-left: -154.5px;}.jfb {position: absolute;top: 30px;right: 100px;font-size: 45px;font-weight: 800;color: #FFF;text-align: center;line-height: 45px;z-index: 11;}</style></head><body><div class="game"><div id="ft1" class="ft"></div><div id="ft2" class="ft"></div><div class="jfb">0</div></div><div class="gameEnd"><div class="getScore"><p class="score">10</p><button class="againBtn">再来一局</button></div></div><script src="js/game.js" type="text/javascript" charset="utf-8"></script></body></html>

View Code

转载于:https://www.cnblogs.com/xiaotiejiang/p/9629482.html

左右躲避障碍-神手ts版本相关推荐

  1. android手机最低内存,原神手机端需要哪些配置 手机端最低配置要求介绍

    原神是一款由米哈游自主研发的全新开放世界冒险游戏,游戏最近迎来了pc端的首次测试,而且在不久之后就会开启原神手机端的公测版本,那么手机端需要什么配置呢?小编带来了详细的介绍. 移动端预下载:9月25日 ...

  2. Android开发p图软件,媲美大神P图效果 Android软件抠图神手

    媲美大神P图效果 Android软件抠图神手 2013年02月20日 01:50作者:杨霏霏编辑:杨霏霏文章出处:泡泡网原创 分享 泡泡网手机频道2月20日 PS的功能大家耳熟能详,其中抠图便是各位P ...

  3. 神马笔记 版本1.8.0——删除笔记/文件夹·技术细节篇

    神马笔记 版本1.8.0--删除笔记/文件夹·技术细节篇 一.目标 二.体验地址 三.技术问题 1. 拖拽排序问题 2. indexOf问题 四.Finally 一.目标 记录开发过程中的2个技术问题 ...

  4. 神马笔记 版本1.4.0

    神马笔记 版本1.4.0 一.新版本介绍 二.下载地址 三.下一版本功能预告 四.已经完成的功能 五.计划中的功能 六.意见反馈 1. 微信 2. 聊天宝 一.新版本介绍 新增undo/redo功能 ...

  5. 神马笔记 版本1.3.0

    神马笔记 版本1.3.0 一.新版本介绍 二.下载地址 三.已经完成的功能 四.下一版本功能预告 五.计划中的功能 六.意见反馈 1. 微信 2. 聊天宝 一.新版本介绍 新增文件夹收藏功能 添加文件 ...

  6. 001-查看ts版本、安装、卸载

    1.查看本机TS版本 npm view typescript version 2.查看本地是否安装 npm ls typescript 3.安装 npm i -g typescript 4.卸载 np ...

  7. 原神手游怎么用电脑玩 原神模拟器玩法教程

    <原神>手游是一款3D全新开放世界冒险游戏.游戏发生在一个被称作「提瓦特」的幻想世界,我们将扮演一名旅行者的神秘角色,在自由的旅行中邂逅性格各异.能力独特的同伴们,和他们一起击败强敌,找回 ...

  8. 神马笔记 版本1.8.0——删除笔记/文件夹·代码篇

    神马笔记 版本1.8.0--删除笔记/文件夹·代码篇 一.目标 二.体验地址 三.功能设计 1. 实现删除功能 2. 处理最近删除的可见性 四.实现过程 1. 删除到最近删除 2. 从最近删除恢复 3 ...

  9. android模拟器pc版怎么玩,原神电脑版安卓模拟器怎么使用,电脑上怎么玩原神手游...

    原神电脑版对很多电脑上玩想原神手游的玩家来说应该是必须的,相对于手机上原神手游,电脑上使用手机模拟器玩原神手游,大屏幕,键鼠操控,性能更强,还可以多开挂机的优势让使用手游模拟器玩原神电脑版可以获得更好 ...

最新文章

  1. java的发展_java的发展
  2. matplotlib——交互按钮中的Home键无法使用
  3. java Hello World程序分析(翻译自Java Tutorials)
  4. Android Button 实现透明 + 圆角按钮效果
  5. Sun发布MySQL 5.4 响应速度提升90% ?
  6. 软件工程毕设(三)·进度考核表
  7. 三极管放大电路原理-电子技术方案
  8. “ 鸡声茅店月,人迹板桥霜” 道尽多少旅人的离愁别绪
  9. 几种并行计算模型的区别(BSP LogP PRAM)
  10. 硬件中控一键开关机设计方案
  11. 从客户端(jianjie=psasdasdfas/p)中检测到有潜在危险的 Request.Form 值
  12. 树莓派vsftpd 425 Failed to establish connection
  13. linux 格式化工具 mkfs 简介
  14. Abaqus2019的abaqus_v6.env在哪里
  15. Android Studio 连接阿里云数据库【制作基于数据库的多人远程聊天APP】
  16. Kafka 消息中间件
  17. 人力外派和猎头的区别是什么?哪个行业更赚钱?
  18. BT面板创建站点显示已存在问题解决
  19. 做好自动化运维平台需要哪些技能?
  20. 改善SilverLight安装体验(翻译)

热门文章

  1. Mysql迁移到Postgresql
  2. 慎用MySQL replace语句
  3. Python 操作Word文档插入图片和表格实例演示
  4. Python 技术篇 - pip下载、安装慢解决方法,更改pip数据源实现秒速下载,配置阿里云国内镜像实例演示
  5. STM32F105的时钟配置
  6. How far away ? HDU - 2586
  7. 第7周项目实践 1 队列算法库的建立
  8. 【mysql问题】foreign key without name 解决方法
  9. opencv imencode跟imdecode函数jpg(python)
  10. windows下mysql安装失败的一个解决案例