DEMOSTRACIÓN: http://cnwander.com/demo/billiards/
Dirección original: http://cnwander.com/blog/?p=11
Serie de minijuegos JS:
[Minijuego JS] Snake + comentarios detallados
Pega el código primero:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transicional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
<html xmlns=" http://www.w3.org/1999/xhtml ">
<cabeza>
<meta http-equiv="Tipo de contenido" content="text/html; charset=utf-8" />
<title>Billar de CNwander</title>
<tipo de estilo="texto/css">
* {margen:0; relleno:0}
cuerpo {fondo:negro; alineación de texto:centro; tamaño de fuente:12px}
h1 {tamaño de fuente: 12px; color: gris; peso de fuente: normal; altura de línea: 200%}
h1 .sub {alineación vertical: super; color: rojo; tamaño de fuente: 9 px;
.info {posición:absoluta; derecha:0; color:gris}
#table {posición:relativa; ancho:800px; margen:20px auto 10px; altura:544px; fondo:url( ); _fondo:ninguno; escala', src=" ); _fondo: ninguno; _filtro: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='escala', src=" ); .AlphaImageLoader(enabled='true', sizingMethod='scale', src=" ) no-repeat}
#force {posición:absoluta; izquierda:0; arriba:18px; ancho:75px; fondo:url( ) sin repetición;
#scoreBoard {posición:absoluta; índice z:3; arriba:230px; izquierda:346px; color:blanco; }
#tips {relleno:15px 0 0 20px; texto-align:izquierda; color:rojo; tamaño de fuente:12px}
</estilo>
<tipo de script="texto/javascript">
// común
función $(cadena) {
devolver document.getElementById(str);
}
función $etiqueta(cadena,objetivo) {
objetivo = objetivo || documento;
devolver target.getElementsByTagName(str);
}
función addEventHandler(obj,eType,fuc){
si(obj.addEventListener){
obj.addEventListener(eType,fuc,false);
}si no (obj.attachEvent){
obj.attachEvent("encendido" + eType,fuc);
}demás{
obj["on" + eType] = fuc;
}
}
función removeEventHandler(obj,eType,fuc){
si(obj.removeEventListener){
obj.removeEventListener(eType,fuc,false);
}si no (obj.attachEvent){
obj.detachEvent("encendido" + eType,fuc);
}
}
function número aleatorio(inicio,fin) {
return Math.floor(Math.random()*(fin - inicio)) + inicio;
}
Array.prototype.remove=función(dx) {
if(isNaN(dx)||dx>this.length){return false;}
para(var i=0,n=0;i<this.length;i++)
{
si(este[i]!=este[dx])
{
esto[n++]=esto[i]
}
}
esta.longitud-=1
}
//constante
var TOTALR = 15, //El radio de la bola (incluida la sombra)
R = 12, //El verdadero radio de la pelota.
PÓKER = 20,
W = 736, //ancho de caja
H = 480, //altura de la caja
ESPESOR = 32, //grosor del borde
TASA = 100, //frecuencia de actualización
F = 0,01, //fuerza de fricción
LOSS = 0.2, // Pérdida de velocidad de colisión
TIPS = ["Consejo 1: bola de referencia, bola objetivo, bolsa objetivo, tres puntos y una línea, esta es la forma más básica de marcar goles","Consejo 2: la barra azul en la esquina inferior derecha representa la fuerza de golpe. Fuerza pequeña es más fácil controlar la posición de la bola blanca","Consejo 3: el punto azul en la bola blanca en la esquina inferior derecha controla el punto de golpe. Controla la barra alta, la barra baja y el enchufe. La diferencia entre maestros y maestros suele estar aquí. ","Consejo 4: En el tenis de mesa, la bola objetivo en realidad no se juega, es la bola blanca"];
tabla var, //caso
bola blanca, //bola blanca
GuideBall, //bola de referencia
dotWrap, //línea de referencia
velocidad = 12,
acumular = 0,
rodarDerecha = 0,
minutero,
temporizador de fuerza,
bolas = [],
bolas en movimiento = [],
golpes = [[0,0],[W/2,-5],[W,0],[0,H],[W/2,H+5],[W,H]],
hasShot = falso;
disparos = 0; //Número de disparos combinados
ventana.onload = función() {
tablainit();
initShootPos();
mostrarConsejos();
iniciarJuego();
}
función iniciarJuego() {
initBall();
addEventHandler(tabla,"mousemove",dragCueBall);
addEventHandler(tabla,"mouseup",setCueBall);
}
función tablainit() {
tabla = $("tabla");
var dotWrapDiv = document.createElement("div"),
guíaBallDiv = document.createElement("div");
dotWrapDiv.id = "dotWrap";
GuideBallDiv.className = "bola guía";
setStyle(guideBallDiv,"display","none");
dotWrap = table.appendChild(dotWrapDiv);
guíaBall = table.appendChild(guideBallDiv);
}
función initBall() {
//Agregar bola blanca
bolacue = new Ball("cue",170,H/2);
bolas.push(cueBall);
//Agregar bola objetivo
para(var i = 0; i < 5; i++) {
para(var j = 0; j <= i; j++) {
var bola = nueva Bola("objetivo",520 + i*2*R, H/2 - R*i + j*2*R);
bolas.push(bola);
}
}
}
función initShootPos() {
var envoltura = $("shootPos"),
controlador = $("punto"),
flechaR = 18;
addEventHandler(wrap,"mousedown",selectDot);
función seleccionarPunto(e) {
mi = mi || evento;
var pos = getElemPos(envoltura),
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)) > flechaR) {
var ángulo = Math.atan2(x-22,y-22);
x = flechaR*Math.sin(ángulo) + 22;
y = flechaR*Math.cos(ángulo) + 22;
}
setPos(controlador,x,y);
}
}
función getElemPos(objetivo,referencia) {
referencia = referencia || documento;
var izquierda = 0, arriba = 0;
devolver getPos(objetivo);
función getPos(objetivo) {
si (objetivo! = referencia) {
izquierda += objetivo.offsetLeft;
arriba += objetivo.offsetTop;
devolver getPos(target.parentNode);
} demás {
regresar [izquierda,arriba];
}
}
}
// clase de pelota
función Bola(tipo,x,y) {
var div = document.createElement("div");
div.className = tipo + "bola";
this.elem = table.appendChild(div);
este.tipo = tipo;
this.x = x; //posición
esto.y = y;
this.angle = 0; //Ángulo
this.v = 0; //Velocidad (excluyendo dirección)
setBallPos(this.elem,x,y);
devolver esto;
}
función setCueBall() {
removeEventHandler(tabla,"mousemove",dragCueBall);
removeEventHandler(tabla,"mouseup",setCueBall);
iniciarDisparo();
}
función iniciarDisparo() {
mostrar(cueBall.elem);
addEventHandler(tabla,"mousemove",showGuide);
addEventHandler(tabla,"mousedown",updateForce);
addEventHandler(tabla,"mouseup",shotCueBall);
}
función arrastrarBolaCue(e) {
var toX,toY;
mi = mi || evento;
toX = e.clientX - table.offsetLeft - ESPESOR,
toY = e.clientY - table.offsetTop - ESPESOR;
aX = aX >= R ? aX : R;
aX = aX <= 170 ? aX : 170;
aY = aY >= R ? aY : R;
aY = aY <= H - R ? aY : H - R;
setBallPos(cueBall,toX,toY);
}
función tiroCueBall() {
removeEventHandler(table,"mousemove",showGuide);
removeEventHandler(tabla,"mousedown",updateForce);
removeEventHandler(tabla,"mouseup",shotCueBall);
ventana.clearInterval(forceTimer);
velocidad = $("fuerza").offsetWidth * 0,15;
var dotDisX = $("punto").offsetLeft-22,
dotDisY = $("punto").offsetTop-22,
puntoDis = Math.sqrt(puntoDisX*puntoDisX + puntoDisY*puntoDisY),
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(guíaBall),
ángulo = Math.atan2(toPos[0] - formPos[0],toPos[1] - formPos[1]);
ocultar(envoltura de puntos);
ocultar (bola guía);
bolacue.v = velocidad;
cueBall.ángulo = ángulo;
bolas en movimiento.push(bola blanca);
temporizador = ventana.setInterval(roll,1000 / TASA);
}
función mostrarGuía(e) {
var deX,deY,aX,aY;
mi = mi || evento;
toX = e.clientX - table.offsetLeft - ESPESOR,
toY = e.clientY - table.offsetTop - ESPESOR;
setBallPos(guideBall,toX,toY);
mostrar(envoltura de puntos);
mostrar(bolaguía);
dibujarLínea();
//línea de referencia
función dibujarLínea() {
var númeropunto = 16,
pos = getBallPos(cueBall.elem);
dotWrap.innerHTML = "";
deX = pos[0];
deY = pos[1];
var partX = (toX - fromX) / dotNum,
partY = (toY - fromY) / dotNum;
for(var i = 1; i < dotNum; i++) {
var x = deX + parteX * i,
y = deY + parteY * i;
dibujarPunto(envoltura de puntos, x, y);
}
}
}
función rollo() {
if(bolas en movimiento.longitud <= 0) {
if(!hasShot) disparos = 0;
else tiros ++; //combos acumulados
hasShot = falso;
setStyle($("fuerza"),"ancho",80+"px");
setPos($("punto"),22,22);
ventana.clearInterval(temporizador);
if(shots > 1) showScore(shots); //Muestra el número de combos.
iniciarDisparo();
}
for(var i = 0; i < bolas en movimiento.longitud; i++) {
var bola = bolas en movimiento[i],
pecado = Math.sin(bola.ángulo),
cos = Math.cos(bola.ángulo);
bola.v -= F;
//Retira la bola estacionaria
if(Math.ronda(bola.v) == 0) {
bola.v = 0;
bolas en movimiento.remove(i);
continuar;
}
var vx = bola.v * pecado,
vy = bola.v * cos;
bola.x += vx;
bola.y += vy;
//Ponlo en la bolsa
if(isPocket(bola.x,bola.y)) {
ocultar(bola.elem);
if(bola.tipo == "cue") {
if(!hasShot) tiros = 0;
hasShot = falso;
ventana.setTimeout(función(){
bola.v = 0;
setBallPos(bola,170,250);
},500);
}demás {
//Retirar las bolas en bolsas
hasShot = verdadero;
bola.v = 0;
for(var k = 0, l =0; k < bolas.longitud; k++) {
si(bolas[k] != bola) {
bolas[l++] = bolas[k];
}
}
bolas.longitud -= 1;
}
devolver;
}
//colisión de borde
if(bola.x < R || bola.x > W - R) {
bola.ángulo *= -1;
bola.ángulo %= Matemáticas.PI;
bola.v = bola.v * (1 - PÉRDIDA);
vx = bola.v*Math.sin(bola.ángulo);
vy = bola.v*Math.cos(bola.ángulo);
si(bola.x < R) bola.x = R;
si(bola.x > W - R) bola.x = W - R;
//relleno de bola blanca
if(bola.tipo == "cue") {
if(ball.angle > 0) vy -= rollRight;
else vy += rollRight;
vx += acumular;
acumular *= 0,2;
rodarDerecha *= 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 %= Matemáticas.PI;
bola.v = bola.v * (1 - PÉRDIDA);
vx = bola.v*Math.sin(bola.ángulo);
vy = bola.v*Math.cos(bola.ángulo);
if(bola.y < R) bola.y = R;
si(bola.y > H - R) bola.y = H - R;
//relleno de bola blanca
if(bola.tipo == "cue") {
if(Math.abs(bola.ángulo) < Math.PI/2) vx += rollRight;
else vx -= rollRight;
vy += acumular;
acumular *= 0,2;
rodarDerecha *= 0.2;
bola.v = Math.sqrt(vx*vx + vy*vy);
bola.ángulo = Math.atan2(vx,vy);
}
}
// colisión de bolas
for(var j = 0; j < bolas.longitud; j++) {
var obj = bolas[j];
if(obj == bola) continuar;
var disX = obj.x - bola.x,
disY = obj.y - bola.y,
brecha = 2 * R;
if(disX <= brecha && disY <= brecha) {
var dis = Math.sqrt(Math.pow(disX,2)+Math.pow(disY,2));
si(dis <= brecha) {
//Si es estacionario, lo agregamos a la matriz movingBalls
if(Matemáticas.ronda(obj.v) == 0)
bolas en movimiento.push(obj);
//Gira las coordenadas al eje x para calcular la colisión
// Calcular ángulos y valores de seno y coseno - valores exactos
//var c = (obj.x*ball.y - obj.y*ball.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)),
//Restaurar el estado tangente de las dos bolas - valor aproximado
ball.x -= (brecha - dis)*sin;
ball.y -= (brecha - dis)*cos;
disX = obj.x - bola.x;
disY = obj.y - bola.y;
// Calcular ángulos y valores de seno y coseno
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);
//trace(ángulo*180/Math.PI);
// rotar 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;
// Velocidad y posición después de la colisión.
var plusVx = vx1 - vx2;
vx1 = vx2;
vx2 = másVx + vx1;
//relleno de bola blanca
if(bola.tipo == "cue") {
vx1 += rollUp;
acumular *= 0,2;
}
x1 += vx1;
x2 += vx2;
// rotar la posición hacia atrás
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;
// Girar la velocidad hacia atrás
vx = vx1 * hitcos - vy1 * hitsin;
vy = vy1 * hitcos + vx1 * hitsin;
objVx = vx2 * hitcos - vy2 * hitsin;
objVy = vy2 * hitcos + vx2 * hitsin;
//velocidad final
bola.v = Math.sqrt(vx*vx + vy*vy) * (1 - 0);
obj.v = Math.sqrt(objVx*objVx + objVy*objVy) * (1 - 0);
// Calcular ángulo
bola.ángulo = Math.atan2(vx, vy);
obj.ángulo = Math.atan2(objVx, objVy);
//romper;
}
}
}
setBallPos(bola,bola.x,bola.y);
}
}
la función esBolsillo(x,y) {
if(y < PÓKER) devolver cheque(0,2);
de lo contrario, si (y > H - PÓKER) devolver cheque(3,5);
de lo contrario devolverá falso;
verificación de función (m, n) {
para(var i=m; i<=n; i++) {
if(x >= pokes[i][0] - POKER && x <= pokes[i][0] + POKER) {
var dis = Math.sqrt(Math.pow(x - toques[i][0],2) + Math.pow(y - toques[i][1],2));
if(dis <= PÓKER) devuelve verdadero;
de lo contrario devolverá falso;
}
}
}
}
función getBallPos(obj) {
varpos = [];
pos.push(obj.offsetLeft - ESPESOR + TOTAL);
pos.push(obj.offsetTop - ESPESOR + TOTAL);
pos de retorno;
}
función establecerPos(obj,x,y) {
obj.style.left = x + "px";
obj.style.top = y + "px";
}
función setBallPos(bola,x,y) {
if(bola.constructor == Bola) {
bola.x = x;
bola.y = y;
bola = bola.elem;
}
setPos(bola,x + ESPESOR - TOTAL,y + ESPESOR - TOTAL);
}
función dibujarPunto(envoltura,x,y) {
var elem = document.createElement("div");
setStyle(elem,{
posición: "absoluta",
ancho: "1px",
altura: "1px",
Tamaño de fuente: "1px",
fondo: "blanco"
});
setPos(elem,x,y);
wrap.appendChild(elem);
}
función actualizarForce() {
var obj = $("fuerza"),
longitud = 80,
arriba = verdadero;
forceTimer = ventana.setInterval(actualización,10);
actualización de función() {
if(arriba) setStyle(obj,"ancho",len+++"px");
else setStyle(obj,"ancho",len--+"px");
if(len > 136) arriba = falso;
if(len <= 0) arriba = verdadero;
}
}
función establecerEstilo() {
if(argumentos.longitud == 2 && tipo de argumentos[1] == "objeto") {
for(var clave en argumentos[1]) {
argumentos[0].estilo[clave] = argumentos[1][clave];
}
} más si (argumentos.longitud > 2) {
argumentos[0].estilo[argumentos[1]] = argumentos[2];
}
}
función ocultar (obj) {
setStyle(obj,"mostrar","ninguno");
}
función mostrar (obj) {
setStyle(obj,"mostrar","bloquear");
}
// información de salida
función traza(algo,quién) {
quien = quien || $("consejos");
if(document.all) quién.innerText = algo;
más quién.textContent = algo;
devolver quién;
}
función mostrarPuntuación(n) {
var wrap = $("puntuación");
trace(n+"biela",envoltura);
desvanecerse(envolver);
}
función desvanecerse(obj){
var deY = 230,
posPaso = [8,14,19,23,26,28,29,29,30,30,30],
opaPaso = [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,
paso = posPaso.longitud,
inTimer = ventana.setInterval(showIn,20),
temporizador de salida;
función mostrarEn() {
setOpacity(obj,opaStep[t]);
obj.style.top = fromY + posStep[t] + "px";
t++;
si(t>=paso) {
ventana.clearInterval(inTimer);
outTimer = ventana.setInterval(fadeOut,50);
}
}
función desvanecerse() {
t--;
setOpacity(obj,opaStep[t]);
obj.style.top = fromY + posStep[t] + "px";
si(t <= 0) {
ventana.clearInterval(outTimer);
ocultar(obj);
}
}
}
función establecerOpacidad(obj,n) {
obj.style.cssText = "filtro:alpha(opacidad="+ n*100 +"); -moz-opacidad:"+ n +"; opacidad:"+ n;
}
función mostrarConsejos() {
var i = 0;
consejo();
ventana.setInterval(consejo,3000);
consejo de función() {
traza(CONSEJOS[i++]);
if(i >= CONSEJOS.longitud) i = 0;
}
}
</script>
</cabeza>
<cuerpo>
<div class="info">Discutir: <a href=" http://bbs.blueidea.com/thread-2951566-1-1.html"> Blueidea</a >   ; //cnwander.com/blog/?p=11">Espacio de Wander</a></div>
<h1>¡El pueblo chino se pone de pie! <span class="sub">60.º aniversario</span></h1>
<div id="tabla">
<div id="tablero de puntuaciones"></div>
</div>
<div clase="bot">
<div id="consejos"></div>
<div clase = "ctrl">
<div id="fuerza"></div>
<div id="dispararPos">
<div id="punto"></div>
</div>
</div>
</div>
</cuerpo>
</html>
Aunque descaradamente se le llama tenis de mesa, en realidad está lejos del tenis de mesa real y todavía quedan muchas áreas por mejorar.
Cuestiones específicas a resolver:
Definitivamente habrá muchos otros problemas. Me preocupa distraerme demasiado durante las vacaciones y no poder continuar más tarde. Lo terminaré todo de una vez. Tengo un poco de prisa. Resolveré los problemas lentamente más tarde. Los publicaré primero para que los estudiantes interesados en este tema los discutan.
Las matemáticas universitarias son básicamente una formalidad y me he olvidado muy poco de la física y las matemáticas en la escuela secundaria. Solo cuando comencé a hacer cosas me di cuenta de que era demasiado débil en esta área. Espero que los estudiantes tengan más experiencia en esta área. El área me dará algunos consejos.