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

Posted xiaotiejiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了左右躲避障碍-神手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();
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

 

以上是关于左右躲避障碍-神手ts版本的主要内容,如果未能解决你的问题,请参考以下文章

编程教育第五节 弹跳躲避障碍物

基于tensorflow的躲避障碍物的ai训练

狂欢圣诞节,Azure云邀你一起云端跑酷!

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

NavMesh动态碰撞

ros保存障碍物位置