左右躲避障碍-神手ts版本

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();

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>

原文地址:https://www.cnblogs.com/xiaotiejiang/p/9629482.html

时间: 2024-10-07 04:22:24

左右躲避障碍-神手ts版本的相关文章

神手微信CMR营销管理,有什么方法让客户主动找我?

微信不单单是一个社交软件了,它不仅影响了大家的社交方式,也影响了网络营销的模式,但微信和QQ相比是较封闭的,那么在微信营销中,有没有让客户主动来找你的方法呢? 微信用朋友圈做口碑传播,然后进行精准引流做微信营销,微信营销现在也已经成为了目目前移动网络营销的最佳方式,做营销肯定是圈子越广越好,接下来和大家说说让粉丝主动找你的5大微信营销技巧! 1.挖粉丝圈 先要自己培养一批种子粉丝并做好维护,在借助粉丝的微信端进行分享在.这是通过粉丝的信任度来发展期微信圈的用户,并以此类推,就可以深度的挖掘粉子圈

教你如何去选个人微信号管理软件的妙招神手CRM

现在很多企业都已经加入到微信营销的队列,依靠微信作为第一社交软件的沟通优势,配合销售加速客户转化.随着微信营销的深入,新的问题也随之而来,微信账号过多管理混乱.销售私加客户损害公司利益...个人微信号管理刻不容缓.但现在市面上的个人微信号管理软件品类繁多,企业不知道该如何选择.今天小编就给大家介绍一些选择个人微信号管理软件的妙招. 1. 易操作 要说挑选软件,我们首先要考虑的是什么?肯定是简单易用,好上手.神手多聊微信管理软件操作界面简单,将微信号接入即用,即使是小编这种软件小白,都可以很快掌握

php5 NTS和TS版本的区别

php5 non-thread-safe和thread-safe这两个版本的区别 从PHP5.2.10版本开始(现在有PHP5.2.10和5.3两个版本),有None-Thread Safe与Thread Safe两种版本的可供选择,这两种版本有何不同,作为使用者来说又应该如何选择呢?下面聚友将为您讲述. 先从字面意思上理解,None-Thread Safe就是非线程安全,在执行时不进行线程(thread)安全检查:Thread Safe就是线程安全,执行时会进行线程(thread)安全检查,以

Kuhn-Munkres算法。带权二分图匹配模板 (bin神小改版本)

/****************************************************** 二分图最佳匹配 (kuhn munkras 算法 O(m*m*n)). 邻接矩阵形式 . 返回最佳匹配值,传入二分图大小m,n 邻接矩阵 map ,表示权,m1,m2返回一个最佳匹配,为匹配顶点的match值为-1, 一定注意m<=n,否则循环无法终止,最小权匹配可将全职取相反数. 初始化: for(i=0;i<MAXN;i++) for(j=0;j<MAXN;j++) mat

PHP版本中的VC6,VC9,VC11,TS,NTS区别

以windows为例,看看下载到得php zip的文件名 php-5.4.4-nts-Win32-VC9-x86.zip VC6:legacy Visual Studio 6 compiler,是使用这个编译器编译的.VC9:Visual Studio 2008 compiler,就是这个编译器编译的. 这个其实没有什么太大的影响,因为从php 5.3,已经没有vc6版本提供下载了 IIS 如果想使用IIS配置PHP的话,那么需要选择Non-Thread Safe(NTS)版本的PHP Apac

电影TS/TC/SCR/R5/BD/HD版本意思收集(转)

一.版本说明: 1.CAM(枪版) CAM通常是用数码摄像机从电影院盗录.有时会使用小三角架,但大多数时候不可能使用,所以摄像机会抖动.因此我们看到画面通常偏暗人物常常会失真,下方的 字幕时常会出现倾斜. 由于声音是从摄像机自带的话筒录制,所以经常会录到观众的笑声等声音.因为这些因素,图象和声音质量通常都很差. 2.TS(准枪版) TS是TELESYNC的缩写.TS与CAM版的标准是相同的.但它使用的是外置音源(一般是影院座椅上为听力不好的人设的耳机孔)这个音源不能保证是好的音源,因为受到很多背

电影TS、TC、SCR、R5、BD、HD等版本是什么意思

在很多电影下载网站的影片标题中我们都能看到,比如<刺杀希特勒BD版>.<游龙戏凤TS版>等,这些英文缩写都是什么意思呢?都代表什么画质?以下就是各个版本的具体含义: 1.CAM(枪版) CAM通常是用数码摄像机从电影院盗录.有时会使用小三角架,但大多数时候不可能使用,所以摄像机会抖动.因此我们看到画面通常偏暗人物常常会失真,下方的 字幕时常会出现倾斜. 由于声音是从 摄像机自带的话筒录制,所以经常会录到观众的笑声等声音.因为这些因素,图象和声音质量通常都很差. 2.TS(准枪版)

无尽跑酷3D (Endless Run 3D) 苹果安卓版免费下载|iOS|Android|iPhone版本免费下载 - 休闲 3D游戏 跑酷游戏 竞速游戏

无尽跑酷3D (Endless Run 3D) 发布了 无尽跑酷3D是一款非常经典的跑酷类手机游戏,该游戏拥有着独特的跑酷玩法.炫酷的跑酷特色和精美的游戏画面设计.感兴趣的小伙伴们快来加入无尽跑酷3D手游试试吧!这是一款不错的游戏哟! 游戏介绍 <无尽跑酷3D>是一款背景设置在外太空的科幻障碍跑酷手游,游戏以第一人称视角跑酷玩法,诠释了科幻躲避障碍的刺激感,游戏中你可以利用重力感应或者屏幕点触在细长的空间轨道上飞驰,以避开标记未知文明符号的障碍物.你所需要做的就是存活更长的时间. 游戏特色 -

游戏设备技术提升分析小7手游稳定性是否靠谱

经过了这么多年的发展,游戏行业依旧是很大的热门.因为游戏设备技术的不断提升,让人们对游戏有了更多需求.比如现在用户追求的游戏画面和操作方式,确实让很多游戏公司明确新的方向.而整个产业也是如此,会朝着这个大致的方向发力,让用户得到满足.所以在做游戏行业分析的时候,依旧觉得游戏行业还有很大的空缺.因为技术是推进游戏行业发展的关键因素,并且不会达到一个饱和的状态.虽然可能会出现技术维持的阶段,但是最终还是提升的一个过程.只有技术水平得到了提升,游戏行业就得继续努力.这就是市场附庸的一种关系,只要用户提