zoukankan      html  css  js  c++  java
  • 网页版台球小游戏

    主要是用html  js  css 做的一个网页版小游戏,从网上看到的所以整理下面给大家看看

    先来看效果图

    html文件

    <!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>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>网页版台球小游戏 - 源码之家</title>
    <link href="css/zzsc.css" rel="stylesheet" type="text/css">
    <script type="text/javascript" src="js/zzsc.js"></script>
    </head>
    <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>
    <div style="text-align:center;clear:both">
    <p>来源:<a href="http://www.mycodes.net/" target="_blank">源码之家</a></p>
    </div>
    </body>
    </html>
    

     然后css文件

    * {margin:0; padding:0}
    body {background:black; text-align:center}
    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}
    #table {position:relative; 800px; margin:20px auto 10px; height:544px; background:url(images/table.jpg) no-repeat}
    .ball {position:absolute; 30px; height:30px}
    #dotWrap {position:absolute; z-index:2; left:32px; top:32px; 736px; height:480px}
    .guide {z-index:3; background-image:url(images/dashed_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src="images/dashed_ball.png"); background-repeat:no-repeat}
    .target {left:500px; top:250px; background-image:url(images/yellow_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src="images/yellow_ball.png"); background-repeat:no-repeat}
    .cue {background-image:url(images/white_ball.png); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src="images/white_ball.png"); background-repeat:no-repeat}
    .bot {position:relative; 800px; margin:10px auto 10px; height:70px}
    .ctrl {position:absolute; top:0; right:0; 200px; height:80px; background:url(images/bg_controler.png) no-repeat}
    #force {position:absolute; left:0; top:18px; 75px; height:20px; background:url(images/force_conver.png) no-repeat}
    #shootPos {position:absolute; top:0; right:14px; 52px; height:52px}
    #dot {position:absolute; top:22px; left:22px; 8px; height:8px; background:url(images/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}
    

    js文件

    // 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",
    		 "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;
    	}
    }
    

     下面是图片:

      

     

  • 相关阅读:
    docker建镜像
    注册路由的简易实现
    docker的小技巧记录(如果使用了更多会继续添加)
    Alembic使用
    SQLAlchemy的常用数据类型
    记录SQLAlchemy的基本使用
    linux创建桌面快捷方式
    vim编辑器命令
    redis发布订阅
    谨慎使用mysql的utf8
  • 原文地址:https://www.cnblogs.com/douchenchen/p/7224062.html
Copyright © 2011-2022 走看看