DEMO: http://cnwander.com/demo/billiards/
Endereço original: http://cnwander.com/blog/?p=11
Série de minijogos JS:
[Minijogo JS] Snake + comentários detalhados
Cole o código primeiro:
<!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 ">
<cabeça>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Bilhar por CNwander</title>
<style type="texto/css">
* {margem:0;
corpo {fundo: preto; alinhamento de texto: centro; tamanho da fonte: 12px}
h1 {tamanho da fonte: 12px cor: cinza; peso da fonte: normal;
h1 .sub {vertical-align:super;cor:vermelho;tamanho da fonte:9px;
.info {posição:absoluta direita:0;
#table {posição:largura relativa:800px ; margem:20px altura automática:544px; escala', src=" ); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src=" ); .AlphaImageLoader(enabled='true', sizingMethod='scale', src=" ) no-repeat}
#force {posição:absoluta; esquerda:0; tamanho da fonte:1px;
#scoreBoard {position:absolute; z-index:3; top:230px; left:346px; font-size:50px; }
#dicas {preenchimento:15px 0 0 20px; alinhamento de texto:esquerda;cor:vermelho;tamanho da fonte:12px}
</estilo>
<script type="texto/javascript">
// comum
função $(str){
retornar document.getElementById(str);
}
função $tag(str,alvo) {
alvo = alvo || documento;
retornar target.getElementsByTagName(str);
}
função addEventHandler(obj,eType,fuc){
if(obj.addEventListener){
obj.addEventListener(eType,fuc,false);
}else if(obj.attachEvent){
obj.attachEvent("on" + eType,fuc);
}outro{
obj["on" + eType] = fuc;
}
}
função removeEventHandler(obj,eType,fuc){
if(obj.removeEventListener){
obj.removeEventListener(eType,fuc,false);
}else if(obj.attachEvent){
obj.detachEvent("on" + eType,fuc);
}
}
function numum aleatório(início,fim) {
return Math.floor(Math.random()*(end - start)) + start;
}
Array.prototype.remove=função(dx) {
if(isNaN(dx)||dx>this.length){retornar falso;}
for(var i=0,n=0;i<este.comprimento;i++)
{
if(isto[i]!=isto[dx])
{
isto[n++]=este[i]
}
}
este.comprimento-=1
}
//const
var TOTALR = 15, //O raio da bola (incluindo sombra)
R = 12, //O verdadeiro raio da bola
PÔQUER = 20,
W = 736, //largura da caixa
H = 480, //altura da caixa
ESPESSURA = 32, //espessura da borda
TAXA = 100, //frequência de atualização
F = 0,01, //força de atrito
PERDA = 0,2, // Perda de velocidade de colisão
DICAS = ["Dica1: Bola de referência, bola alvo, saco alvo, três pontos e uma linha, esta é a forma mais básica de fazer gols","Dica2: A barra azul no canto inferior direito representa a força de rebatida. Força pequena é mais fácil controlar a posição da bola branca","Dica 3: O ponto azul na bola branca no canto inferior direito controla o ponto de rebatida. Ele controla a barra alta, a barra baixa e o plug. A diferença entre mestres e mestres está frequentemente aqui. ","Dica4: No tênis de mesa, a bola alvo não é realmente jogada, é a bola branca"];
tabela var, //caso
cueBall, //bola branca
guideBall, //bola de referência
dotWrap, //linha de referência
velocidade = 12,
rollUp = 0,
rolar para a direita = 0,
temporizador,
forçaTemporizador,
bolas = [],
movendoBolas = [],
cutucadas = [[0,0],[W/2,-5],[W,0],[0,H],[W/2,H+5],[W,H]],
hasShot = falso;
tiros = 0; //Número de tiros combinados
janela.onload=função(){
tabelainicial();
initShootPos();
mostrarDicas();
startJogo();
}
function startJogo() {
initBall();
addEventHandler(tabela,"mousemove",dragCueBall);
addEventHandler(tabela,"mouseup",setCueBall);
}
função tabelainicial() {
tabela = $("tabela");
var dotWrapDiv = document.createElement("div"),
guideBallDiv = document.createElement("div");
dotWrapDiv.id = "dotWrap";
guideBallDiv.className = "bola guia";
setStyle(guideBallDiv,"display","none");
dotWrap = tabela.appendChild(dotWrapDiv);
guideBall = tabela.appendChild(guideBallDiv);
}
função initBall() {
//Adiciona bola branca
cueBall = new Ball("cue",170,H/2);
bolas.push(cueBall);
//Adiciona bola alvo
for(var i = 0; i < 5; i++) {
for(var j = 0; j <= i; j++) {
var bola = new Bola("alvo",520 + i*2*R, H/2 - R*i + j*2*R);
bolas.push(bola);
}
}
}
função initShootPos() {
var wrap = $("shootPos"),
manipulador = $("ponto"),
setaR = 18;
addEventHandler(wrap,"mousedown",selectDot);
função selecionePonto(e) {
e = e || evento;
var pos = getElemPos(wrap),
x = e.clientX - pos[0] - manipulador.offsetWidth/2,
y = e.clientY - pos[1] - handler.offsetHeight/2;
if(Math.sqrt((x-22)*(x-22) + (y-22)*(y-22)) > setaR) {
var ângulo = Math.atan2(x-22,y-22);
x = setaR*Math.sin(ângulo) + 22;
y = setaR*Math.cos(ângulo) + 22;
}
setPos(manipulador,x,y);
}
}
function getElemPos(destino,referência) {
referência = referência || documento;
var esquerda = 0, topo = 0;
return getPos(destino);
function getPos(alvo) {
if(alvo! = referência) {
esquerda += alvo.offsetLeft;
topo += alvo.offsetTop;
retornar getPos(target.parentNode);
} outro {
return [esquerda, topo];
}
}
}
// aula de bola
função Bola(tipo,x,y) {
var div = document.createElement("div");
div.className = tipo + "bola";
este.elem = tabela.appendChild(div);
este.tipo = tipo;
isto.x = x;
isto.y = y;
este.ângulo = 0; //Ângulo
this.v = 0; //Velocidade (excluindo direção)
setBallPos(este.elem,x,y);
devolva isso;
}
function setCueBall() {
removeEventHandler(tabela,"mousemove",dragCueBall);
removeEventHandler(tabela,"mouseup",setCueBall);
startShot();
}
function startShot() {
mostrar(cueBall.elem);
addEventHandler(tabela,"mousemove",showGuide);
addEventHandler(tabela,"mousedown",updateForce);
addEventHandler(tabela,"mouseup",shotCueBall);
}
function arrastarCueBall(e) {
var paraX,paraY;
e = e || evento;
toX = e.clientX - table.offsetLeft - ESPESSURA,
toY = e.clientY - table.offsetTop - ESPESSURA;
paraX = paraX >= R ? paraX : R;
toX = toX <= 170 ? toX : 170;
paraY = paraY >= R ? paraY : R;
paraY = paraY <= H - R ? paraY : H - R;
setBallPos(cueBall,toX,toY);
}
function shotCueBall() {
removeEventHandler(tabela,"mousemove",showGuide);
removeEventHandler(tabela,"mousedown",updateForce);
removeEventHandler(tabela,"mouseup",shotCueBall);
janela.clearInterval(forceTimer);
velocidade = $("força").offsetWidth * 0,15;
var pontoDisX = $("ponto").offsetLeft-22,
pontoDisY = $("ponto").offsetTop-22,
dotDis = Math.sqrt(dotDisX*dotDisX + dotDisY*dotDisY),
pontoAngle = Math.atan2(pontoDisX,pontoDisY);
rollRight = Math.round(dotDis*Math.sin(dotAngle))/5;
rollUp = -Math.round(dotDis*Math.cos(dotAngle))/5;
var formPos = getBallPos(cueBall.elem),
toPos = getBallPos(guiaBall),
ângulo = Math.atan2(toPos[0] - formPos[0],toPos[1] - formPos[1]);
ocultar(pontoWrap);
ocultar(guiaBola);
cueBall.v = velocidade;
cueBall.angle = ângulo;
movendoBalls.push(cueBall);
temporizador = window.setInterval(roll,1000/TAXA);
}
função showGuide(e) {
var deX,deY,paraX,paraY;
e = e || evento;
toX = e.clientX - table.offsetLeft - ESPESSURA,
toY = e.clientY - table.offsetTop - ESPESSURA;
setBallPos(guideBall,toX,toY);
mostrar(pontoWrap);
show(guiaBola);
desenharLinha();
//linha de referência
função desenharLinha() {
var pontoNum = 16,
pos = getBallPos(cueBall.elem);
dotWrap.innerHTML = "";
deX = pos[0];
deY = pos[1];
var parteX = (toX - fromX) / pontoNum,
parteY = (paraY - deY) /pontoNum;
for(var i = 1; i < pontoNum; i++) {
var x = deX + parteX * i,
y = deY + parteY * i;
desenharDot(pontoWrap, x, y);
}
}
}
função rolar() {
if (bolas em movimento. comprimento <= 0) {
if(!hasShot) tiros = 0;
else tiros ++; //combos acumulados
hasShot = falso;
setStyle($("força"),"largura",80+"px");
setPos($("ponto"),22,22);
window.clearInterval(temporizador);
if(shots > 1) showScore(shots); //Mostra o número de combos;
startShot();
}
for(var i = 0; i < MovingBalls.length; i++) {
var bola = bolas em movimento[i],
pecado = Math.sin(bola.ângulo),
cos = Math.cos(bola.ângulo);
bola.v -= F;
//Remove a bola estacionária
if(Math.round(bola.v) == 0) {
bola.v = 0;
movendoBalls.remove(i);
continuar;
}
var vx = bola.v * pecado,
vy = bola.v * cos;
bola.x += vx;
bola.y += vy;
//Coloque na bolsa
if(isPocket(bola.x,bola.y)) {
esconder(bola.elem);
if(ball.type == "sugestão") {
if(!hasShot) tiros = 0;
hasShot = falso;
janela.setTimeout(função(){
bola.v = 0;
setBallPos(bola,170.250);
},500);
}outro {
//Remove as bolas ensacadas
hasShot = verdadeiro;
bola.v = 0;
for(var k = 0, l =0; k < comprimento das bolas; k++) {
if(bolas[k] != bola) {
bolas[l++] = bolas[k];
}
}
bolas.comprimento -= 1;
}
retornar;
}
//colisão de borda
if(bola.x < R || bola.x > W - R) {
bola.ângulo *= -1;
bola.ângulo %= Math.PI;
bola.v = bola.v * (1 - PERDA);
vx = bola.v*Math.sin(bola.ângulo);
vy = bola.v*Math.cos(bola.ângulo);
if(bola.x < R) bola.x = R;
if(bola.x > W - R) bola.x = W - R;
//recheio de bola branca
if(ball.type == "sugestão") {
if(ball.angle > 0) vy -= rollRight;
senão vy += rollRight;
vx += rollUp;
acumulação *= 0,2;
roloDireita *= 0,2;
bola.v = Math.sqrt(vx*vx + vy*vy);
bola.ângulo = Math.atan2(vx,vy);
}
}
if(bola.y < R || bola.y > H - R) {
bola.ângulo = bola.ângulo > 0 ? Math.PI - bola.ângulo : - Math.PI - bola.ângulo ;
bola.ângulo %= Math.PI;
bola.v = bola.v * (1 - PERDA);
vx = bola.v*Math.sin(bola.ângulo);
vy = bola.v*Math.cos(bola.ângulo);
if(bola.y < R) bola.y = R;
if(bola.y > H - R) bola.y = H - R;
//recheio de bola branca
if(ball.type == "sugestão") {
if(Math.abs(ball.angle) < Math.PI/2) vx += rollRight;
senão vx -= rollRight;
vy += rollUp;
acumulação *= 0,2;
roloDireita *= 0,2;
bola.v = Math.sqrt(vx*vx + vy*vy);
bola.ângulo = Math.atan2(vx,vy);
}
}
//colisão de bola
for(var j = 0; j < comprimento das bolas; j++) {
var obj = bolas[j];
if(obj == bola) continuar;
var disX = obj.x - bola.x,
disY = obj.y - bola.y,
lacuna = 2 * R;
if(disX <= lacuna && disY <= lacuna) {
var dis = Math.sqrt(Math.pow(disX,2)+Math.pow(disY,2));
if(dis <= lacuna) {
//Se estiver estacionário, adicione-o ao array movingBalls
if(Math.round(obj.v) == 0)
movendoBalls.push(obj);
//Gira as coordenadas para o eixo x para cálculo de colisão
//Calcula valores de ângulo e seno e cosseno - valores exatos
//var c = (obj.x*bola.y - obj.y*bola.x)/(2*R),
// d = Math.sqrt(bola.x*bola.x + bola.y*bola.y),
//ângulo = Math.asin(ball.y/d) - Math.asin(c/d) - ball.angle%(Math.PI/2),
//ângulo = Math.asin(oy / (2 * R)),
//Restaura o estado tangente das duas bolas - valor aproximado
ball.x -= (gap - dis)*sin;
ball.y -= (gap - dis)*cos;
disX = obj.x - bola.x;
disY = obj.y - bola.y;
//Calcula valores de ângulo e seno e cosseno
var ângulo = Math.atan2(disY, disX),
hitsin = Math.sin(ângulo),
hitcos = Math.cos(ângulo),
objVx = obj.v * Math.sin(obj.ângulo),
objVy = obj.v * Math.cos(obj.ângulo);
//traço(ângulo*180/Math.PI);
//Roda as coordenadas
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;
//Velocidade e posição após colisão
var maisVx = vx1 - vx2;
vx1 = vx2;
vx2 = maisVx + vx1;
//recheio de bola branca
if(ball.type == "sugestão") {
vx1 += rollUp;
acumulação *= 0,2;
}
x1 += vx1;
x2 += vx2;
// Gira a posição de volta
var x1Final = x1 * hitcos - y1 * hitsin,
y1Final = y1 * hitcos + x1 * hitsin,
x2Final = x2 * hitcos - y2 * hitsin,
y2Final = y2 * hitcos + x2 * hitsin;
obj.x = bola.x + x2Final;
obj.y = bola.y + y2Final;
bola.x = bola.x + x1Final;
bola.y = bola.y + y1Final;
//Retorna a velocidade
vx = vx1 * hitcos - vy1 * hitsin;
vy = vy1 * hitcos + vx1 * hitsin;
objVx = vx2 * hitcos - vy2 * hitsin;
objVy = vy2 * hitcos + vx2 * hitsin;
//velocidade final
bola.v = Math.sqrt(vx*vx + vy*vy) * (1 - 0);
obj.v = Math.sqrt(objVx*objVx + objVy*objVy) * (1 - 0);
//Calcula o ângulo
bola.ângulo = Math.atan2(vx, vy);
obj.ângulo = Math.atan2(objVx, objVy);
//quebrar;
}
}
}
setBallPos(bola,bola.x,bola.y);
}
}
função isPocket(x,y) {
if(y <POKER) return verificação(0,2);
senão if (y > H - POKER) return check(3,5);
caso contrário, retorne falso;
verificação de função (m,n) {
for(var i=m; i<=n; i++) {
if(x >= cutucadas[i][0] - POKER && x <= cutucadas[i][0] + POKER) {
var dis = Math.sqrt(Math.pow(x - cutuca[i][0],2) + Math.pow(y - cutuca[i][1],2));
if(dis <= POKER) retorna verdadeiro;
caso contrário, retorne falso;
}
}
}
}
função getBallPos(obj) {
var pos = [];
pos.push(obj.offsetLeft - ESPESSURA + TOTALR);
pos.push(obj.offsetTop - ESPESSURA + TOTALR);
posição de retorno;
}
função setPos(obj,x,y) {
obj.style.left = x + "px";
obj.style.top = y + "px";
}
function setBallPos(bola,x,y) {
if(bola.construtor == Bola) {
bola.x = x;
bola.y = y;
bola = bola.elem;
}
setPos(bola,x + ESPESSURA - TOTALR,y + ESPESSURA - TOTALR);
}
function drawDot(wrap,x,y) {
var elem = document.createElement("div");
setStyle(elem,{
posição: "absoluta",
largura: "1px",
altura: "1px",
tamanho da fonte: "1px",
fundo: "branco"
});
setPos(elem,x,y);
wrap.appendChild(elem);
}
função updateForce() {
var obj = $("força"),
lente = 80,
para cima = verdadeiro;
forceTimer = window.setInterval(atualização,10);
função atualização() {
if(up) setStyle(obj,"largura",len+++"px");
senão setStyle(obj,"largura",len--+"px");
if(len > 136) up = falso;
if(len <= 0) up = verdadeiro;
}
}
function setEstilo() {
if(arguments.length == 2 && typeof argumentos[1] == "objeto") {
for(var chave em argumentos[1]) {
argumentos[0].estilo[chave] = argumentos[1][chave];
}
} else if (argumentos.length > 2) {
argumentos[0].estilo[argumentos[1]] = argumentos[2];
}
}
função ocultar(obj) {
setStyle(obj,"display","nenhum");
}
função mostrar(obj) {
setStyle(obj,"display","bloco");
}
//informações de saída
função trace(sth,quem) {
quem = quem || $("dicas");
if(document.all) who.innerText = sth;
senão who.textContent = sth;
devolver quem;
}
função mostrarPontuação(n) {
var wrap = $("scoreBoard");
trace(n+"biela",wrap);
fadeIn(envolver);
}
função fadeIn(obj){
var deY = 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],
deOpa = 0,
t = 0,
passo = posStep.length,
inTimer = window.setInterval(showIn,20),
outTimer;
função mostrarIn() {
setOpacity(obj,opaStep[t]);
obj.style.top = fromY + posStep[t] + "px";
t++;
if(t>=passo) {
janela.clearInterval(inTimer);
outTimer = window.setInterval(fadeOut,50);
}
}
função fadeOut(){
t--;
setOpacity(obj,opaStep[t]);
obj.style.top = fromY + posStep[t] + "px";
se(t <= 0) {
janela.clearInterval(outTimer);
ocultar(obj);
}
}
}
função setOpacity(obj,n) {
obj.style.cssText = "filter:alpha(opacity="+ n*100 +"); -moz-opacity:"+ n +"; opacidade:"+ n;
}
function mostrarDicas() {
var eu = 0;
dica();
janela.setInterval(tip,3000);
dica de função() {
rastrear(DICAS[i++]);
if(i >= DICAS.comprimento) i = 0;
}
}
</script>
</head>
<corpo>
<div class="info">Discutir: <a href=" http://bbs.blueidea.com/thread-2951566-1-1.html"> Blueidea</a > <a href=" http: //cnwander.com/blog/?p=11">Espaço de Wander</a></div>
<h1>O povo chinês levante-se! <span class="sub">60º aniversário</span></h1>
<div id="tabela">
<div id="scoreBoard"></div>
</div>
<div class="bot">
<div id="dicas"></div>
<divclass = "ctrl">
<div id="força"></div>
<div id="shootPos">
<div id="ponto"></div>
</div>
</div>
</div>
</body>
</html>
Embora seja descaradamente chamado de tênis de mesa, na verdade está longe de ser o verdadeiro tênis de mesa e ainda há muitas áreas para melhorias.
Questões específicas a serem resolvidas:
Definitivamente haverá muitos outros problemas. Estou preocupado em ficar muito distraído durante as férias e não conseguir continuar mais tarde. com pressa. Vou resolver os problemas lentamente mais tarde. Vou publicá-los primeiro para os alunos que estão interessados neste tópico.
A matemática universitária é basicamente apenas uma formalidade, e esqueci muito pouco sobre física e matemática no ensino médio. Só quando comecei a fazer as coisas é que percebi que era muito fraco nessa área, espero que os alunos com mais experiência nesta área. área vai me dar alguns conselhos.