typescript 简版跳一跳

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

核心点:1.场景的随机创建

    2.旗子的跳动

    3.落脚点的判断,重点要提及的是射线判断法,参见博客

    4.场景平移

    5.游戏重置

    6.销毁场景外方块

Ts代码:

 //1.创建底座:
//2.创建跳棋:
//3.点击移动
//4.开始按压动画,
//5.放开动画
//6.跳动
//7.是否跳对
//8.移动场景
//9.创建新底座
module Jump {
interface Pos {
x: number;
y: number;
}
enum Flag {
on, in, out
}
enum Direction {
left,
right
}
let direction: Direction = Direction.right;
let diamondsList: diamonds[] = [];
let mask: JQuery<HTMLElement> = $(".game-p");
let chess: Chess;
let score:number=0;
class MathHelp {
/**
* 返回范围内随机数[min,max]
* @param min 最小值
* @param max 最大值
*/
static RandRange(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1) + min);
}
/**
* 根据角度求对边长度。Math.sin(randian)
* @param r 斜边长
* @param angle 角度
*/
static righttriangle(r: number, angle: number): number {
return Math.sin(Math.PI / 180 * angle) * r;
}
/**
* 射线法判断点是否在多边形内部
* @param p 待判断的点
* @param poly 多边形顶点
*/
static rayCasting(p: Pos, poly: Pos[]): Flag {
var px = p.x,
py = p.y,
flag = false for (var i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) {
var sx = poly[i].x,
sy = poly[i].y,
tx = poly[j].x,
ty = poly[j].y // 点与多边形顶点重合
if ((sx === px && sy === py) || (tx === px && ty === py)) {
return Flag.on;
} // 判断线段两端点是否在射线两侧
if ((sy < py && ty >= py) || (sy >= py && ty < py)) {
// 线段上与射线 Y 坐标相同的点的 X 坐标
var x = sx + (py - sy) * (tx - sx) / (ty - sy) // 点在多边形的边上
if (x === px) {
return Flag.on;
} // 射线穿过多边形的边界
if (x > px) {
flag = !flag
}
}
} // 射线穿过多边形边界的次数为奇数时点在多边形内
return flag ? Flag.in : Flag.out;
} }
class diamonds { private width: number = 180;
private height: number = 180;
id: string = "p" + new Date().getTime();;
node: JQuery<HTMLElement>;
left: number = 0;
top: number = 0;
constructor(isauto: boolean = true, isRe = true, left: number = 0, top: number = 0) {
this.left = left;
this.top = top;
if (isauto) { let dl = MathHelp.RandRange(200, 300);
let x = MathHelp.righttriangle(dl, 57);
let y = MathHelp.righttriangle(dl, 33);
let lastbox = diamondsList[diamondsList.length - 1];
if (isRe) {
if (direction == Direction.left) {
direction = Direction.right;
} else if (direction == Direction.right) {
direction = Direction.left;
}
}
if (direction == Direction.right) {
this.left = lastbox.left + x;
} else {
this.left = lastbox.left - x;
}
this.top = lastbox.top - y;
}
this.node = $(`<div id='${this.id}' class='gb' style="top:${this.top}px;left:${this.left}px">
<div class='box' style="background:url(img/c${MathHelp.RandRange(1, 4)}.png)"></div>
<div class='shadw'></div>
</div>`);
mask.append(this.node); }
GetPointList(): Pos[] {
var result = [{
x: this.left,
y: this.top + 57
}, {
x: this.left + (this.width / 2),
y: this.top + 4
}, {
x: this.left + this.width,
y: this.top + 57
}, {
x: this.left + (this.width / 2),
y: this.top + (57 * 2 - 4)
}];
return result;
}
move(p: Pos) {
this.node.css({
left: p.x + "px",
top: p.y + "px",
transition: "",
transform: ""
});
}
}
class Chess {
private width: number = 180;
private height: number = 182;
left: number = 49;
top: number = 531;
node: JQuery<HTMLElement>;
constructor() { this.node =$(`<div class="chess gb"></div>`);
mask.append(this.node);
}
jump(pt: Pos, call: Function) {
let numb = 0;
let t1 = setInterval(() => { if (numb == 0) {
this.node.animate({
left: pt.x + "px",
top: pt.y + "px"
}, 504); }
this.node.css({
"background-position": "-" + this.width * numb + "px" + " 0px"
});
numb++;
if (numb >= 11) {
window.clearInterval(t1);
call();
} }, 42) }
GetCenter(): Pos {
return {
x: this.left + this.width / 2,
y: this.top + this.height
}
}
move(p: Pos) {
this.node.css({
left: p.x + "px",
top: p.y + "px",
transition: "",
transform: ""
});
}
} class Game {
static distince = 0;
static time: number;
/**
* 初始化游戏场景
*/
static scence() {
let d1 = new diamonds(false, false, 50, 650);
diamondsList.push(d1);
let d = new diamonds(true, false);
diamondsList.push(d);
Game.loadlisten();
chess = new Chess();
$(".againBtn").on("click",()=>{
//重置
Game.GameRest(); });
}
/**
* 重置游戏
*/
static GameRest(){
$(".gameEnd").css({
"z-index":-1
});
diamondsList=[];
score=0;
$(".jfb").html(score.toString());
$(".gb").remove();
direction=Direction.right;
Game.scence(); }
static CreateSP() {
let d = new diamonds();
diamondsList.push(d);
Game.loadlisten();
}
private static loadlisten() {
document.addEventListener('touchstart', Game.touch, false);
document.addEventListener('touchmove', Game.touch, false);
document.addEventListener('touchend', Game.touch, false);
}
private static removelisten() {
document.removeEventListener('touchstart', Game.touch, false);
document.removeEventListener('touchmove', Game.touch, false);
document.removeEventListener('touchend', Game.touch, false);
}
private static touch(e: Event) {
e.preventDefault();
let currentDiamonds = diamondsList[diamondsList.length - 2];
if (e.type == "touchstart") {
//挤压形变动画
let scaley = 1;
let chessy = 0;
Game.distince = 0;
Game.time = setInterval(() => {
if (scaley > 0.7) {
scaley -= 0.01;
}
if (chessy < 30) {
chessy++;
chess.node.css({
"transform": " scaleX(" + (1 + chessy * 0.006) + ") scaleY(" + (1 - (chessy * 0.007)) + ")"
})
}
Game.distince++;
currentDiamonds.node.css({
"transform-origin": "bottom center",
"transform": "scaleY(" + scaley + ")"
}); }, 50); } else if (e.type == "touchend") {
//1.底座还原动画
//2.旗子动画轨迹
//3.落脚点判断
//4.场景平移,创建新底座,移除画外底座
currentDiamonds.node.css({
"transform": "scaleY(1)"
});
clearInterval(Game.time);
Game.removelisten();
Game.Jump(Game.distince); }
}
private static Jump(distince: number) {
let dl = distince * 17;
let x = MathHelp.righttriangle(dl, 57);
let y = MathHelp.righttriangle(dl, 33);
if (direction == Direction.left) {
x = -x;
}
chess.left = chess.left + x;
chess.top = chess.top - y;
chess.jump({ x: chess.left, y: chess.top }, () => {
let p = chess.GetCenter();
let last = diamondsList[diamondsList.length - 1];
let poly = last.GetPointList();
//判断是否跳在基座上
let result = MathHelp.rayCasting(p, poly);
if (result == Flag.in) {
direction = Math.random() > 0.5 ? 1 : 0;
Game.moveblock();
score++;
$(".jfb").html(score.toString());
} else {
//game over
$(".gameEnd").css({
"z-index":999
});
$(".score").html(score.toString());
console.log("game over!");
}
}) }
/**
* 移动场景
*/
private static moveblock() {
let last = diamondsList[diamondsList.length - 1];
let p1: Pos;
let x: number = 0;
let y: number = 0;
//以左右标准基座为左边平移
if (direction == Direction.left) {
p1 = { x: 50, y: 650 };
} else {
p1 = { x: 400, y: 650 };
}
x = p1.x - last.left;
y = p1.y - last.top; $(".gb").css({
"transform": "translate(" + x + "px," + y + "px)",
"transition": "transform 0.9s"
}); setTimeout(() => {
//更新class中left,top属性
$.each(diamondsList, (a, b) => {
b.left = b.left + x;
b.top = b.top + y;
b.move({ x: b.left, y: b.top });
});
chess.left = chess.left + x;
chess.top = chess.top + y;
chess.move({
x: chess.left,
y: chess.top
});
Game.Destroy();
//创建新底座
Game.CreateSP();
}, 1100)
}
//销毁画外的底座
private static Destroy(){
diamondsList.forEach((item,i,list)=>{ if(item.top>1008){
diamondsList.splice(i,1);
$("#"+item.id).remove();
}
})
}
}
Game.scence(); }

html:

 <!DOCTYPE html>
<html> <head>
<meta charset="utf-8" />
<title>Typescript跳一跳</title>
<meta name="viewport" content="width=device-width, initial-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>
<link rel="stylesheet" type="text/css" href="css/ts.css" />
<script type="text/javascript">
var isios = false;
! function(userAgent) {
var screen_w = parseInt(window.screen.width),
scale = screen_w / 640;
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>
</head> <body> <!--游戏页面-->
<div class="game"> <div class="game-p">
<!--<div class="chess gb"></div>
<div id="one" class="gb">
<div class="box"></div>
<div class="shadw"></div>
</div>-->
</div>
<img class="logo" src="img/logo.png" />
<div class="jfb">0</div>
<div class="toolp">距离开启宝箱还有5步</div>
</div> <div class="gameEnd"> <div class="getScore"> <p class="score">10</p>
<button class="againBtn">再来一局</button> </div> </div> <script src="js/myjump.js" type="text/javascript" charset="utf-8"></script>
</body> </html>

css:

 html,
body {
margin:;
padding:;
height: 100%;
min-height: 1008px;
} .game {
height: 100%;
width: 100%;
position: relative;
left:;
top:;
} .logo {
position: absolute;
left: 30px;
top: 26px;
} .jfb {
position: absolute;
top: 30px;
right: 60px;
font-size: 100px;
font-weight:;
color: #4f4e3f;
text-align: center;
line-height: 100px;
} .toolp {
position: absolute;
bottom: 5%;
left: 30%;
width: 40%;
height: 50px;
border-radius: 50px;
color: #FFFFFF;
text-align: center;
font-size: 20px;
line-height: 50px;
background-color: #4a764e;
}
.game-p {
height: 100%;
width: 100%;
position: absolute;
left:;
top:;
background-color: #8aad8e;
}
.gb{
position: absolute;
left: 50px;
top: 650px; }
.box{
height: 180px;
width: 180px;
background-image:url(../img/c1.png);
background-size: 100% 100%;
z-index:;
position: absolute;
}
.shadw{
position: absolute;
left: 120px;
top:;
height: 133px;
width: 234px;
background-image: url(../img/s2.png);
background-size: 100% 100%;
opacity: 0.3;
transform: translateY(35px) translateX(-180px);
transform-origin: bottom center;
}
.chess{
width: 182px;
height: 227px;
background-image: url(../img/e3.png);
background-position:0 0;
position: absolute;
top: 531px;
left: 49px;
z-index:; }
.gameEnd{
position: absolute;
top:;
left:;
width: 100%;
height: 100%;
overflow: hidden;
background-color: rgba(0,0,0,.8);
z-index: -1;
}
.getScore{
width: 492px;
height: 760px;
background: url(../img/getScore.png) no-repeat;
background-size: 100% auto;
position: absolute;
top:;
right:;
left:;
bottom:;
margin: auto;
}
.score{
color: #dcc226;
font-size: 130px;
text-align: center;
margin-top: 120px;
font-weight:; }
.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:;
position: absolute;
left: 50%;
margin-left: -154.5px;
}

源码:留下邮箱,看到就发。

typescript 简版跳一跳的更多相关文章

  1. 用Kotlin破解Android版微信小游戏-跳一跳

    前言 微信又更新了,从更新日志上来看,似乎只是一次不痛不痒的小更新.不过,很快就有人发现,原来微信这次搞了个大动作——在小程序里加入了小游戏.今天也是朋友圈被刷爆的缘故. 看到网上 有人弄了一个破解版 ...

  2. 微信小程序跳一跳辅助程序(手动版)

    最近,微信官方推出了demo小程序游戏<跳一跳>,这个游戏操作简单,容易上手,却又不容易获得高分,受到很多人的喜爱(emm...这游戏有毒).自己也尝试了玩了几次,作为一个手残+脑残的资深 ...

  3. 微信跳一跳辅助Demo

    [原创] 前几天没事干看别人一直在玩微信上线的那一个跳一跳小游戏,玩着玩着老是掉下去,闲着没事呗 就想了想做一个辅助程序的呗.不过先做的手动版的.自动版的有点麻烦.就不发了.用的Java写的,也就一个 ...

  4. AI之微信跳一跳

    需要环境:1,Python3.6 2,android手机 3,ADB驱动,下载地址https://adb.clockworkmod.com/ 步骤: 配置Python3,ADB安装目录到环境变量pat ...

  5. 用Python代码实现微信跳一跳作弊器

    最近随着微信版本的更新,在进入界面有个跳一跳的小游戏,在网上看到技术篇教你用Python来玩微信跳一跳 ( 转载自 " 工科给事中的技术博客 " ) 本文旨在总结,技术全靠大神完成 ...

  6. java语言实现简单接口工具--粗简版

    2016注定是变化的一年,忙碌.网红.项目融资失败,现在有点时间整整帖子~~ 目标: 提高工作效率与质量,能支持平台全量接口回归测试与迭代测试也要满足单一接口联调测试. 使用人员: 测试,开发 工具包 ...

  7. python练习_购物车(简版)

    python练习_购物车(简版) 需求: 写一个python购物车可以输入用户初始化金额 可以打印商品,且用户输入编号,即可购买商品 购物时计算用户余额,是否可以购买物品 退出结算时打印购物小票 以下 ...

  8. 挑战App Store,微信通过“跳一跳”秀了一下“小程序”的肌肉

    2017年即将结束的时候,微信放了一个大招.随着最新的微信v6.6.1版本更新,基于小程序的"小游戏"板块正式上线.微信上首发的这款"小游戏"叫"跳一 ...

  9. .NET开发一个微信跳一跳辅助程序

    昨天微信更新了,出现了一个小游戏"跳一跳",玩了一下 赶紧还蛮有意思的 但纯粹是拼手感的,玩了好久,终于搞了个135分拿了个第一名,没想到过一会就被朋友刷下去了,最高的也就200来 ...

随机推荐

  1. js分割字符串

    js分割字符串 我想达到通过 : 分割 只要第一次分割,后面的内容不使用分割 不行,没找到可以直接用的方法,不过可以通过其它方式达到效果 eg: str.split(':',2)[0] (第一个分隔符 ...

  2. MySQL innodb表使用表空间物理文件复制或迁移表

    MySQL InnoDB引擎的表通过拷贝物理文件来进行单表或指定表的复制,可以想到多种方式,今天测试其中2种: 将innodb引擎的表修改为Myisam引擎,然后拷贝物理文件 直接拷贝innodb的表 ...

  3. QQ兴趣部落 大批量引流实战技巧

    兴趣部落,犹如pc端贴吧,除去盔甲,几乎大同小异. 在文章<QQ运动,新楛的马桶还在香,营销人不应摒弃>中,阿力推推对稍微僻静的平台做过简述,和QQ运动一样,兴趣部落稍显“僻静”,执行到位 ...

  4. Symfony FOSUserBundle用户登录验证

    symfony是一个由组件构成的框架,登录验证的也是由一些组件构成,下面就介绍一下FOSUserBundle的使用. 以symfony 3.3为例, 首先我们需要先安装一下FOSUserBundle. ...

  5. pyspider -- 禁止请求非200响应码抛异常

    在pyspider中若crawl()网址时出现非200的异常信息,会抛出一个异常. 可以在对应的回调函数上面通过@catch_status_code_error 进行修饰,这样就能不抛出异常正常进入回 ...

  6. stm32+lwip(三):TCP测试

    我是卓波,很高兴你来看我的博客. 系列文章: stm32+lwip(一):使用STM32CubeMX生成项目 stm32+lwip(二):UDP测试 stm32+lwip(三):TCP测试 stm32 ...

  7. LeetCode算法1—— 两数之和

    给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...

  8. kafka集群部署文档(转载)

    原文链接:http://www.cnblogs.com/luotianshuai/p/5206662.html Kafka初识 1.Kafka使用背景 在我们大量使用分布式数据库.分布式计算集群的时候 ...

  9. LeetCode:12. Integer to Roman(Medium)

    1. 原题链接 https://leetcode.com/problems/integer-to-roman/description/ 2. 题目要求 (1) 将整数转换成罗马数字: (2) 整数的范 ...

  10. 虚拟接VMnet1 和VMnet8的区别

    vmnet1是host-only,也就是说,选择用vmnet1的话就相当于VMware给你提供了一个虚拟交换机,仅将虚拟机和真实系统连上了,虚拟机可以与真实系统相互共享文件,但是虚拟机无法访问外部互联 ...