三零网 www.q3060.com -- 技术、分享、进步
当前位置: > 网络编程 > CSS/HTML > html5实例:CSS+JS实现的好玩的2D桌球游戏的综合应用代码

html5实例:CSS+JS实现的好玩的2D桌球游戏的综合应用代码

投稿:mmqxmq2p  发布时间:2018-01-01  【手机版】  人气:

导读:三零(q3060.com)小编琪琪接下来为你介绍一下关于综合应用的技巧,希望对您有帮助。那么下面我们一起看看,具体内容所述如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS+JS实现的好玩的2D桌球游戏</title>
<meta http-equiv="content-type" content="text/html;charset=gb2312">
<!--把下面代码加到<head>与</head>之间-->
<style type="text/css">
* {margin:0; padding:0}
body {background:black; text-align:center; font-size:12px}
h1 {font-size:12px; color:gray; font-weight:normal; line-height:200%}
h1 .sub {vertical-align:super; color:red; font-size:9px}
.info {position:absolute; right:0; color:gray}
#table {position:relative; width:800px; margin:20px auto 10px; height:544px; background:url(/html/txdm_2/images/20100919/table.jpg) no-repeat}
.ball {position:absolute; width:30px; height:30px}
#dotWrap {position:absolute; z-index:2; left:32px; top:32px; width:736px; height:480px}
.guide {z-index:3; background-image:url(/html/txdm_2/images/20100919/dashed_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src="/html/txdm_2/images/20100919/dashed_ball.png"); background-repeat:no-repeat}
.target {left:500px; top:250px; background-image:url(/html/txdm_2/images/20100919/yellow_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src="/html/txdm_2/images/20100919/yellow_ball.png"); background-repeat:no-repeat}
.cue {background-image:url(/html/txdm_2/images/20100919/white_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src="/html/txdm_2/images/20100919/white_ball.png"); background-repeat:no-repeat}
.bot {position:relative; width:800px; margin:10px auto 10px; height:70px}
.ctrl {position:absolute; top:0; right:0; width:200px; height:80px; background:url(/html/txdm_2/images/20100919/bg_controler.png) no-repeat}
#force {position:absolute; left:0; top:18px; width:75px; height:20px; background:url(/html/txdm_2/images/20100919/force_conver.png) no-repeat}
#shootPos {position:absolute; top:0; right:14px; width:52px; height:52px}
#dot {position:absolute; top:22px; left:22px; width:8px; height:8px; background:url(/html/txdm_2/images/20100919/bule_dot.png) no-repeat; font-size:1px}
#scoreBoard {position:absolute; z-index:3; top:230px; left:346px; font-size:50px; color:white; filter:alpha(opacity=0); -moz-opacity:0; opacity:0}
#tips {padding:15px 0 0 20px; text-align:left; color:red; font-size:12px}
</style>
<script type="text/javascript">
// common 
function $(str) {
 return document.getElementById(str);
}
function $tag(str,target) {
 target = target || document;
 return target.getElementsByTagName(str);
}
function addEventHandler(obj,eType,fuc){
 if(obj.addEventListener){ 
  obj.addEventListener(eType,fuc,false);
 }else if(obj.attachEvent){ 
  obj.attachEvent("on" + eType,fuc); 
 }else{ 
  obj["on" + eType] = fuc; 
 } 
} 
function removeEventHandler(obj,eType,fuc){
 if(obj.removeEventListener){ 
  obj.removeEventListener(eType,fuc,false);
 }else if(obj.attachEvent){ 
  obj.detachEvent("on" + eType,fuc); 
 } 
}
function randowNum(start,end) {
 return Math.floor(Math.random()*(end - start)) + start;
}
Array.prototype.remove=function(dx) {
 if(isNaN(dx)||dx>this.length){return false}
 for(var i=0,n=0;i<this.length;i++)
 {
  if(this[i]!=this[dx])
  {
   this[n++]=this[i]
  }
 }
 this.length-=1
}
//const
var TOTALR = 15, //球的半径(包括阴影)
 R = 12, //球真实半径
 POKER = 20,
 W = 736, //案宽
 H = 480, //案高
 THICKNESS =  32, //边缘厚度
 RATE = 100, //刷新频率
 F = 0.01, //摩擦力
 LOSS = 0.2, // 碰撞速度损失
 TIPS = ["Tip1: 参考球,目标球,目标袋,三点一线,这是最基本的进球方法","Tip2: 右下角蓝条代表击球力度,小的力度更便于控制母球位置","Tip3: 右下角白球上的蓝点控制击球点,高杆,低杆,加塞都由它控制,高手与菜鸟的区别往往在此","Tip4: 桌球,其实打的不是目标球,是母球"];
var table, //案子
 cueBall, //母球
 guideBall, //参考球
 dotWrap, //参考线
 speed = 12,
 rollUp = 0,
 rollRight = 0,
 timer,
 forceTimer,
 balls = [],
 movingBalls = [],
 pokes = [[0,0],[W/2,-5],[W,0],[0,H],[W/2,H+5],[W,H]],
 hasShot = false;
 shots = 0; //连击次数
window.onload = function() {
 initTable();
 initShootPos();
 showTips();
 startGame();
}
function startGame() {
 initBall();
 addEventHandler(table,"mousemove",dragCueBall);
 addEventHandler(table,"mouseup",setCueBall);
}
function initTable() {
 table = $("table");
 var dotWrapDiv = document.createElement("div"),
  guideBallDiv = document.createElement("div");
 dotWrapDiv.id = "dotWrap";
 guideBallDiv.className = "guide ball";
 setStyle(guideBallDiv,"display","none");
 dotWrap = table.appendChild(dotWrapDiv);
 guideBall = table.appendChild(guideBallDiv);
}
function initBall() {
 //添加母球
 cueBall = new Ball("cue",170,H/2);
 balls.push(cueBall);
 //添加目标球
 for(var i = 0; i < 5; i++) {
  for(var j = 0; j <= i; j++) {
   var ball = new Ball("target",520 + i*2*R, H/2 - R*i + j*2*R);
   balls.push(ball);
  }
 }
}
function initShootPos() {
 var wrap = $("shootPos"),
  handler = $("dot"),
  arrowR = 18;
 addEventHandler(wrap,"mousedown",selectDot);
 function selectDot(e) {
  e = e || event;
  var pos = getElemPos(wrap),
   x = e.clientX - pos[0] - handler.offsetWidth/2,
   y = e.clientY - pos[1] - handler.offsetHeight/2;
  if(Math.sqrt((x-22)*(x-22) + (y-22)*(y-22)) > arrowR) {
   var angle = Math.atan2(x-22,y-22);
   x = arrowR*Math.sin(angle) + 22;
   y = arrowR*Math.cos(angle) + 22;
  }
  setPos(handler,x,y);
 }
}
function getElemPos(target,reference) {
 reference = reference || document;
 var left = 0,top = 0;
 return getPos(target);
 function getPos(target) {
  if(target != reference) {
   left += target.offsetLeft;
   top += target.offsetTop;
   return getPos(target.parentNode);
  } else {
   return [left,top];
  }
 }
}
// ball class
function Ball(type,x,y) {
 var div = document.createElement("div");
 div.className = type + " ball";
 this.elem = table.appendChild(div);
 this.type = type;
 this.x = x; //位置
 this.y = y;
 this.angle = 0; //角度
 this.v = 0; //速度(不包含方向)
 setBallPos(this.elem,x,y);
 return this;
}
function setCueBall() {
 removeEventHandler(table,"mousemove",dragCueBall);
 removeEventHandler(table,"mouseup",setCueBall);
 startShot();
}
function startShot() {
 show(cueBall.elem);
 addEventHandler(table,"mousemove",showGuide);
 addEventHandler(table,"mousedown",updateForce);
 addEventHandler(table,"mouseup",shotCueBall);
}
function dragCueBall(e) {
 var toX,toY;
 e = e || event;
 toX = e.clientX - table.offsetLeft - THICKNESS,
 toY = e.clientY - table.offsetTop - THICKNESS;
 toX = toX >= R ? toX : R;
 toX = toX <= 170 ? toX : 170;
 toY = toY >= R ? toY : R;
 toY = toY <= H - R ? toY : H - R;
 setBallPos(cueBall,toX,toY);
}
function shotCueBall() {
 removeEventHandler(table,"mousemove",showGuide);
 removeEventHandler(table,"mousedown",updateForce);
 removeEventHandler(table,"mouseup",shotCueBall);
 window.clearInterval(forceTimer);
 speed = $("force").offsetWidth * 0.15;
 var dotDisX = $("dot").offsetLeft-22,
  dotDisY = $("dot").offsetTop-22,
  dotDis = Math.sqrt(dotDisX*dotDisX + dotDisY*dotDisY),
  dotAngle = Math.atan2(dotDisX,dotDisY);
 rollRight = Math.round(dotDis*Math.sin(dotAngle))/5;
 rollUp = -Math.round(dotDis*Math.cos(dotAngle))/5;
 var formPos = getBallPos(cueBall.elem),
  toPos = getBallPos(guideBall),
  angle = Math.atan2(toPos[0] - formPos[0],toPos[1] - formPos[1]);
 hide(dotWrap);
 hide(guideBall);
 cueBall.v = speed;
 cueBall.angle = angle;
 movingBalls.push(cueBall);
 timer = window.setInterval(roll,1000 / RATE);
}
function showGuide(e) {
 var fromX,fromY,toX,toY;
 e = e || event;
 toX = e.clientX - table.offsetLeft - THICKNESS,
 toY = e.clientY - table.offsetTop - THICKNESS;
 setBallPos(guideBall,toX,toY);
 show(dotWrap);
 show(guideBall);
 drawLine();
 //参考线
 function drawLine() {
  var dotNum = 16,
   pos = getBallPos(cueBall.elem);
  dotWrap.innerHTML = "";
  fromX = pos[0];
  fromY = pos[1];
  var partX = (toX - fromX) / dotNum,
   partY = (toY - fromY) / dotNum;
  for(var i = 1; i < dotNum; i++) {
   var x = fromX + partX * i,
    y = fromY + partY * i;
   drawDot(dotWrap, x, y);
  }
 }
}
function roll() {
 if(movingBalls.length <= 0) {
  if(!hasShot) shots = 0;
  else shots ++; //累计连击
  hasShot = false;
  setStyle($("force"),"width",80+"px");
  setPos($("dot"),22,22);  
  window.clearInterval(timer);
  if(shots > 1) showScore(shots); //显示连击数
  startShot();
 }
 for(var i = 0; i < movingBalls.length; i++) {
  var ball = movingBalls[i],
   sin = Math.sin(ball.angle),
   cos = Math.cos(ball.angle);
  ball.v -= F;
  //移除静止的小球
  if(Math.round(ball.v) == 0) {
   ball.v = 0;
   movingBalls.remove(i);
   continue; 
  }
  var vx = ball.v * sin,
   vy = ball.v * cos;
  ball.x += vx;
  ball.y += vy;
  //入袋
  if(isPocket(ball.x,ball.y)) {
   hide(ball.elem);
   
   if(ball.type == "cue") {
     if(!hasShot) shots = 0;
     hasShot = false;
    window.setTimeout(function(){
    
     ball.v = 0; 
     setBallPos(ball,170,250);
    },500);
   }else {
    //移除入袋小球
    hasShot = true;
    ball.v = 0; 
    for(var k = 0, l =0; k < balls.length; k++) {
     if(balls[k] != ball) {
      balls[l++] = balls[k];
     }
    }
    balls.length -= 1;
   }
   return;
  }
  //边缘碰撞
  if(ball.x < R || ball.x > W - R) {
   ball.angle *= -1;
   ball.angle %= Math.PI;
   ball.v = ball.v * (1 - LOSS);
   vx = ball.v*Math.sin(ball.angle);
   vy = ball.v*Math.cos(ball.angle);
   if(ball.x < R) ball.x = R;
   if(ball.x > W - R) ball.x = W - R;
   //母球加塞
   if(ball.type == "cue") {
    if(ball.angle > 0) vy -= rollRight;
    else vy += rollRight;
    vx += rollUp;
    rollUp *= 0.2;
    rollRight *= 0.2;
    ball.v = Math.sqrt(vx*vx + vy*vy);
    ball.angle = Math.atan2(vx,vy);
   }
  }
  if(ball.y < R || ball.y > H - R) {
   ball.angle = ball.angle > 0 ? Math.PI - ball.angle : - Math.PI - ball.angle ;
   ball.angle %= Math.PI;
   ball.v = ball.v * (1 - LOSS);
   vx = ball.v*Math.sin(ball.angle);
   vy = ball.v*Math.cos(ball.angle);
   if(ball.y < R) ball.y = R;
   if(ball.y > H - R) ball.y = H - R;
   //母球加塞
   if(ball.type == "cue") {
    if(Math.abs(ball.angle) < Math.PI/2) vx += rollRight;
    else vx -= rollRight;
    vy += rollUp;
    rollUp *= 0.2;
    rollRight *= 0.2;
    ball.v = Math.sqrt(vx*vx + vy*vy);
    ball.angle = Math.atan2(vx,vy);
   }
  }
  //小球碰撞
  for(var j = 0; j < balls.length; j++) {
   var obj = balls[j];
   if(obj == ball) continue;
   var disX = obj.x - ball.x,
    disY = obj.y - ball.y,
    gap = 2 * R;
   if(disX <= gap && disY <= gap) {
    var dis = Math.sqrt(Math.pow(disX,2)+Math.pow(disY,2));
    if(dis <= gap) {
     //如果是静止的,则添加到数组movingBalls
     if(Math.round(obj.v) == 0) 
     movingBalls.push(obj);
     //将坐标旋转到x轴进行碰撞计算
     // 计算角度和正余弦值 - 精确值
     //var c = (obj.x*ball.y - obj.y*ball.x)/(2*R),
     // d = Math.sqrt(ball.x*ball.x + ball.y*ball.y),
     // angle = Math.asin(ball.y/d) - Math.asin(c/d) - ball.angle%(Math.PI/2),
      //angle =  Math.asin(oy / (2 * R)),
     //还原两球相切状态 - 近似值
     ball.x -= (gap - dis)*sin;
     ball.y -= (gap - dis)*cos;
     disX = obj.x - ball.x;
     disY = obj.y - ball.y;
     // 计算角度和正余弦值
     var angle = Math.atan2(disY, disX),
      hitsin = Math.sin(angle),
      hitcos = Math.cos(angle),
      objVx = obj.v * Math.sin(obj.angle),
      objVy = obj.v * Math.cos(obj.angle);
      //trace(angle*180/Math.PI);
     // 旋转坐标
     var x1 = 0,
      y1 = 0,
      x2 = disX * hitcos + disY * hitsin,
      y2 = disY * hitcos - disX * hitsin,
      vx1 = vx * hitcos + vy * hitsin,
      vy1 = vy * hitcos - vx * hitsin,
      vx2 = objVx * hitcos + objVy * hitsin,
      vy2 = objVy * hitcos - objVx * hitsin;
     // 碰撞后的速度和位置
     var plusVx = vx1 - vx2;
     vx1 = vx2;
     vx2 = plusVx + vx1;
     //母球加塞
     if(ball.type == "cue") {
      vx1 += rollUp;
      rollUp *= 0.2;
     }
     x1 += vx1;
     x2 += vx2;  
     // 将位置旋转回来
     var x1Final = x1 * hitcos - y1 * hitsin,
      y1Final = y1 * hitcos + x1 * hitsin,
      x2Final = x2 * hitcos - y2 * hitsin,
      y2Final = y2 * hitcos + x2 * hitsin;
     obj.x = ball.x + x2Final;
     obj.y = ball.y + y2Final;
     ball.x = ball.x + x1Final;
     ball.y = ball.y + y1Final;
     // 将速度旋转回来
     vx = vx1 * hitcos - vy1 * hitsin;
     vy = vy1 * hitcos + vx1 * hitsin;
     objVx = vx2 * hitcos - vy2 * hitsin;
     objVy = vy2 * hitcos + vx2 * hitsin;  
     //最终速度
     ball.v = Math.sqrt(vx*vx + vy*vy) * (1 - 0);
     obj.v = Math.sqrt(objVx*objVx + objVy*objVy) * (1 - 0);
     
     // 计算角度
     ball.angle = Math.atan2(vx , vy);
     obj.angle = Math.atan2(objVx , objVy);
     //break;
    }
   }
  }
  setBallPos(ball,ball.x,ball.y); 
 }
}
function isPocket(x,y) {
 if(y < POKER) return check(0,2);
 else if (y > H - POKER) return check(3,5);
 else return false;
 function check(m,n) {
  for(var i=m; i<=n; i++) {
   if(x >= pokes[i][0] - POKER && x <= pokes[i][0] + POKER) {
    var dis = Math.sqrt(Math.pow(x - pokes[i][0],2) + Math.pow(y - pokes[i][1],2));
    if(dis <= POKER) return true;
    else return false;
   }
  } 
 } 
}
function getBallPos(obj) {
 var pos = [];
 pos.push(obj.offsetLeft - THICKNESS + TOTALR);
 pos.push(obj.offsetTop - THICKNESS + TOTALR);
 return pos;
}
function setPos(obj,x,y) {
 obj.style.left = x + "px";
 obj.style.top = y + "px";
}
function setBallPos(ball,x,y) {
 if(ball.constructor == Ball) {
  ball.x = x;
  ball.y = y;
  ball = ball.elem;
 }
 setPos(ball,x + THICKNESS - TOTALR,y + THICKNESS - TOTALR);
}
function drawDot(wrap,x,y) {
 var elem = document.createElement("div");
 setStyle(elem,{
  position: "absolute",
  width: "1px",
  height: "1px",
  fontSize: "1px",
  background: "white"
 });
 setPos(elem,x,y);
 wrap.appendChild(elem);
}
function updateForce() {
 var obj = $("force"),
  len = 80,
  up = true;
 forceTimer = window.setInterval(update,10);
 function update() {
   if(up) setStyle(obj,"width",len+++"px");
   else setStyle(obj,"width",len--+"px");
   if(len > 136) up = false;
   if(len <= 0) up = true;
 }
}
function setStyle() {
 if(arguments.length == 2 &&  typeof arguments[1] == "object") {
  for(var key in arguments[1]) {
   arguments[0].style[key] = arguments[1][key];
  }
 } else if (arguments.length > 2) {
  arguments[0].style[arguments[1]] = arguments[2];
 }
}
function hide(obj) {
 setStyle(obj,"display","none");
}
function show(obj) {
 setStyle(obj,"display","block");
}
//输出信息
function trace(sth,who) {
 who = who || $("tips");
 if(document.all) who.innerText = sth;
 else who.textContent = sth;
 return who;
}
function showScore(n) {
 var wrap = $("scoreBoard");
 trace(n+"连杆",wrap);
 fadeIn(wrap);
}
function fadeIn(obj){
 var fromY = 230,
  posStep = [8,14,19,23,26,28,29,29,30,30,30],
  opaStep = [0,0.05,0.1,0.15,0.2,0.25,0.3,0.4,0.5,0.6,0.8],
  fromOpa = 0,
  t = 0,
  step = posStep.length,
  inTimer = window.setInterval(showIn,20),
  outTimer;
 
 function showIn() {
  setOpacity(obj,opaStep[t]);
  obj.style.top = fromY + posStep[t] + "px";
  t++;
  if(t>=step) {
   window.clearInterval(inTimer);
   outTimer = window.setInterval(fadeOut,50);
  } 
 }
 function fadeOut() {
  t--;
  setOpacity(obj,opaStep[t]);
  obj.style.top = fromY + posStep[t] + "px";
  if(t <= 0) {
   window.clearInterval(outTimer);
   hide(obj);
  }
 }
}
function setOpacity(obj,n) {
 obj.style.cssText = "filter:alpha(opacity="+ n*100 +"); -moz-opacity:"+ n +"; opacity:"+ n;
}
function showTips() {
 var i = 0;
 tip();
 window.setInterval(tip,3000);
 
 function tip() {
  trace(TIPS[i++]);
  if(i >= TIPS.length) i = 0;
 }
}
</script>
</head>
<body>
<!--把下面代码加到<body>与</body>之间-->
<div id="table">
 <div id="scoreBoard"></div>
</div>
<div class="bot">
 <div id="tips"></div>
    <div class = "ctrl">
        <div id="force"></div>
        <div id="shootPos">
         <div id="dot"></div>
        </div>
    </div>
</div>
</body>
</html>

<p align="center"><font color=skyblue>本特效由 <a href="http://www.q3060.com" target="_blank">三零网</a>丨 收集于互联网,只为兴趣,不作商业用途。</font></p>

结语:以上就是分享给大家的综合应用内容了,希望大家多多支持三零网站。更多知识点,可以能过本站网页顶端的搜索或进入相关专题,如果有任何疑问都可以一起留言交流。

●【往下看,下一页更精彩】●
1  2  3  4  5  6  7  下一页 
延伸阅读:
·html5实例:超简单的JS获取当前页面的网址的综合应用代码
·html5实例:JS动画测试:透明度渐变、位置移动、尺寸变化的综合应用代码
·html5实例:JS询问确认程序对话框,改进版的“你好”程序的综合应用代码
·html5实例:纯CSS代码表现一座漂亮的房子的特效的综合应用代码
·html5实例:非常不错的评分特效的综合应用代码
·html5实例:JS配合CSS实现的个性漂亮滚动条的综合应用代码
·html5实例:用一款按钮把输入框中一段英文的首字母全部大写的综合应用代码
·html5实例:漂亮的加入收藏夹和收藏到网摘特效的综合应用代码
·html5实例:颜色选择程序脚本,鼠标指向即显示颜色代码的综合应用代码
·html5实例:用图片制作的选色器的综合应用代码
  
温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,请收藏本网站!
大家感兴趣的内容
最新的内容
热门搜索
三零网 | 网站地图| 最近更新 | 关于我们 | 联系方式 | |

Copyright © 2012-2020,Q3060.COM All Rights Reserved.