DÉMO : http://cnwander.com/demo/billiards/
Adresse originale : http://cnwander.com/blog/?p=11
Série de mini-jeux JS :
[Mini-jeu JS] Snake + commentaires détaillés
Collez d'abord le code :
<!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 ">
<tête>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Billard par CNwander</title>
<style type="text/css">
* {marge :0 ; remplissage :0}
corps {arrière-plan : noir ; texte-align : centre ; taille de police : 12px}
h1 {font-size:12px; couleur:gris; font-weight:normal;
h1 .sub {alignement vertical : super ; couleur : rouge ; taille de police : 9px ;
.info {position : absolue ; droite : 0 ; couleur : gris}
#table {position:relative; largeur:800px; marge:20px auto 10px; background:url( ); _background:none; progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod=' scale', src=" ); _background:none; _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='scale', src=" ); .AlphaImageLoader(enabled='true', sizingMethod='scale', src=" ) no-repeat}
#force {position : absolu ; gauche : 0 ; haut : 18px ; largeur : 75 px ; arrière-plan : url ( ) no-repeat ;
#scoreBoard {position : absolu ; z-index : 3 ; haut : 230px gauche : 346px ; couleur : blanc ; }
#tips {padding:15px 0 0 20px; text-align:left; couleur:rouge taille de police:12px}
</style>
<script type="text/javascript">
// commun
fonction $(str) {
return document.getElementById(str);
}
fonction $tag(str,cible) {
cible = document cible ||
return target.getElementsByTagName(str);
}
fonction addEventHandler(obj,eType,fuc){
si(obj.addEventListener){
obj.addEventListener(eType,fuc,false);
}sinon si(obj.attachEvent){
obj.attachEvent("on" + eType,fuc);
}autre{
obj["on" + eType] = fuc;
}
}
fonction removeEventHandler(obj,eType,fuc){
si(obj.removeEventListener){
obj.removeEventListener(eType,fuc,false);
}sinon si(obj.attachEvent){
obj.detachEvent("on" + eType,fuc);
}
}
function randomNum (début, fin) {
return Math.floor(Math.random()*(end - start)) + start;
}
Array.prototype.remove=fonction(dx) {
if(isNaN(dx)||dx>this.length){return false;}
pour(var i=0,n=0;i<this.length;i++)
{
si(ce[i]!=ce[dx])
{
ceci[n++]=ce[i]
}
}
ceci.longueur-=1
}
//const
var TOTALR = 15, //Le rayon de la balle (y compris l'ombre)
R = 12, //Le vrai rayon de la balle
POKER = 20,
W = 736, //largeur du boîtier
H = 480, //hauteur du boîtier
ÉPAISSEUR = 32, //épaisseur du bord
RATE = 100, //fréquence de rafraîchissement
F = 0,01, //force de frottement
LOSS = 0,2, // Perte de vitesse de collision
TIPS = ["Astuce 1 : Ballon de référence, ballon cible, sac cible, trois points et une ligne, c'est le moyen le plus basique de marquer des buts", "Astuce 2 : La barre bleue dans le coin inférieur droit représente la force de frappe. Petite force est plus facile de contrôler la position de la bille blanche, "Astuce 3 : Le point bleu sur la boule blanche dans le coin inférieur droit contrôle le point de frappe. Il contrôle la barre haute, la barre basse et le plug. La différence entre les maîtres et les maîtres est souvent ici. ","Tip4 : Au tennis de table, la balle cible n'est pas réellement jouée, c'est la bille blanche"];
var table, //cas
cueBall, // bille blanche
guideBall, //boule de référence
dotWrap, //ligne de référence
vitesse = 12,
rollUp = 0,
rollRight = 0,
minuteur,
forceTimer,
balles = [],
boules en mouvement = [],
coups = [[0,0],[W/2,-5],[W,0],[0,H],[W/2,H+5],[W,H]],
hasShot = faux ;
tirs = 0 ; //Nombre de tirs combinés
window.onload = fonction() {
initTable();
initShootPos();
showTips();
startGame();
}
fonction startGame() {
initBall();
addEventHandler(table,"mousemove",dragCueBall);
addEventHandler(table,"mouseup",setCueBall);
}
fonction initTable() {
tableau = $("tableau");
var dotWrapDiv = document.createElement("div"),
guideBallDiv = document.createElement("div");
dotWrapDiv.id = "dotWrap" ;
guideBallDiv.className = "boule de guidage";
setStyle(guideBallDiv,"display","aucun");
dotWrap = table.appendChild(dotWrapDiv);
guideBall = table.appendChild(guideBallDiv);
}
fonction initBall() {
//Ajouter une bille blanche
cueBall = new Ball("cue",170,H/2);
balles.push(cueBall);
//Ajouter une balle cible
pour(var je = 0; je < 5; je++) {
pour(var j = 0; j <= i; j++) {
var balle = new Ball("cible",520 + i*2*R, H/2 - R*i + j*2*R);
balles.push(balle);
}
}
}
fonction initShootPos() {
var wrap = $("shootPos"),
gestionnaire = $("point"),
flècheR = 18 ;
addEventHandler(wrap,"mousedown",selectDot);
fonction selectDot(e) {
e = e || événement ;
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)) > flècheR) {
var angle = Math.atan2(x-22,y-22);
x = flècheR*Math.sin(angle) + 22 ;
y = flècheR*Math.cos(angle) + 22 ;
}
setPos(gestionnaire,x,y);
}
}
fonction getElemPos (cible, référence) {
référence = référence ||
var gauche = 0, haut = 0 ;
return getPos (cible);
fonction getPos (cible) {
if(cible != référence) {
gauche += cible.offsetLeft;
top += cible.offsetTop;
return getPos(target.parentNode);
} autre {
return [gauche, haut] ;
}
}
}
// cours de balle
fonction Balle(type,x,y) {
var div = document.createElement("div");
div.className = type + "balle" ;
this.elem = table.appendChild(div);
this.type = type;
ceci.x = x; //position
ceci.y = y;
this.angle = 0; //Angle
this.v = 0; //Vitesse (hors direction)
setBallPos(this.elem,x,y);
rends ceci ;
}
fonction setCueBall() {
RemoveEventHandler(table,"mousemove",dragCueBall);
RemoveEventHandler(table,"mouseup",setCueBall);
startShot();
}
fonction startShot() {
show(cueBall.elem);
addEventHandler(table,"mousemove",showGuide);
addEventHandler(table,"mousedown",updateForce);
addEventHandler(table,"mouseup",shotCueBall);
}
fonction dragCueBall(e) {
var àX,àY;
e = e || événement ;
toX = e.clientX - table.offsetLeft - ÉPAISSEUR,
toY = e.clientY - table.offsetTop - ÉPAISSEUR ;
àX = àX >= R ? àX : R;
àX = àX <= 170 ? àX : 170;
àY = àY >= R ? àY : R;
àY = àY <= H - R ? àY : H - R;
setBallPos(cueBall,toX,toY);
}
fonction shotCueBall() {
RemoveEventHandler(table,"mousemove",showGuide);
RemoveEventHandler(table,"mousedown",updateForce);
RemoveEventHandler(table,"mouseup",shotCueBall);
window.clearInterval(forceTimer);
vitesse = $("force").offsetWidth * 0,15;
var dotDisX = $("point").offsetLeft-22,
dotDisY = $("point").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]);
cacher(dotWrap);
cacher (guideBall);
cueBall.v = vitesse ;
cueBall.angle = angle;
movingBalls.push(cueBall);
minuterie = window.setInterval(roll,1000 / RATE);
}
fonction showGuide(e) {
var deX,deY,àX,àY;
e = e || événement ;
toX = e.clientX - table.offsetLeft - ÉPAISSEUR,
toY = e.clientY - table.offsetTop - ÉPAISSEUR ;
setBallPos(guideBall,toX,toY);
show(dotWrap);
show(guideBall);
drawLine();
//ligne de référence
fonction drawLine() {
var numéropoint = 16,
pos = getBallPos(cueBall.elem);
dotWrap.innerHTML = "";
deX = pos[0];
deY = pos[1];
var partX = (toX - fromX) / dotNum,
partY = (toY - fromY) / dotNum ;
pour(var i = 1; i < dotNum; i++) {
var x = fromX + partX * i,
y = deY + partieY * i ;
drawDot(dotWrap,x,y);
}
}
}
fonction rouleau() {
si (movingBalls.length <= 0) {
if(!hasShot) coups = 0 ;
sinon coups ++; //combos accumulés
hasShot = faux ;
setStyle($("force"),"largeur",80+"px");
setPos($("point"),22,22);
window.clearInterval(minuterie);
if(shots > 1) showScore(shots); //Afficher le nombre de combos
startShot();
}
pour (var i = 0; i < movingBalls.length; i++) {
var balle = MovingBalls[i],
sin = Math.sin(balle.angle),
cos = Math.cos(balle.angle);
balle.v -= F;
//Retirer la balle stationnaire
si (Math.round (balle.v) == 0) {
balle.v = 0;
MovingBalls.remove(i);
continuer;
}
var vx = balle.v * péché,
vy = balle.v * cos;
balle.x += vx;
balle.y += vy;
//Mettez-le dans le sac
si(isPocket(ball.x,ball.y)) {
cacher(balle.elem);
if(ball.type == "cue") {
if(!hasShot) coups = 0 ;
hasShot = faux ;
window.setTimeout(function(){
balle.v = 0;
setBallPos(balle,170,250);
},500 );
}autre {
//Retirez les balles ensachées
hasShot = vrai ;
balle.v = 0;
for(var k = 0, l =0; k < balles.longueur; k++) {
if(balles[k] != balle) {
balles[l++] = balles[k];
}
}
balles.longueur -= 1;
}
retour;
}
//collision de bord
si (balle.x < R || balle.x > W - R) {
balle.angle *= -1;
balle.angle %= Math.PI;
balle.v = balle.v * (1 - PERTE);
vx = balle.v*Math.sin(balle.angle);
vy = balle.v*Math.cos(balle.angle);
si(balle.x < R) balle.x = R;
if(balle.x > W - R) ball.x = W - R;
//rembourrage de bille blanche
if(ball.type == "cue") {
if(ball.angle > 0) vy -= rollRight;
sinon vy += rollRight;
vx += rollUp;
rollUp *= 0,2 ;
rouler à droite *= 0,2 ;
balle.v = Math.sqrt(vx*vx + vy*vy);
balle.angle = Math.atan2(vx,vy);
}
}
si (balle.y < R || balle.y > H - R) {
balle.angle = balle.angle > 0 ? Math.PI - balle.angle : - Math.PI - balle.angle ;
balle.angle %= Math.PI;
balle.v = balle.v * (1 - PERTE);
vx = balle.v*Math.sin(balle.angle);
vy = balle.v*Math.cos(balle.angle);
si (balle.y < R) balle.y = R;
if(ball.y > H - R) ball.y = H - R;
//rembourrage de bille blanche
if(ball.type == "cue") {
if(Math.abs(ball.angle) < Math.PI/2) vx += rollRight;
sinon vx -= rollRight;
vy += rollUp;
rollUp *= 0,2 ;
rouler à droite *= 0,2 ;
balle.v = Math.sqrt(vx*vx + vy*vy);
balle.angle = Math.atan2(vx,vy);
}
}
//collision de balle
pour(var j = 0; j < balles.longueur; j++) {
var obj = boules[j];
if(obj == balle) continue ;
var disX = obj.x - balle.x,
disY = obj.y - balle.y,
écart = 2 * R ;
if(disX <= écart && disY <= écart) {
var dis = Math.sqrt(Math.pow(disX,2)+Math.pow(disY,2));
si (dis <= écart) {
//S'il est stationnaire, ajoutez-le au tableau movingBalls
si (Math.round (obj.v) == 0)
movingBalls.push(obj);
// Faites pivoter les coordonnées sur l'axe des x pour le calcul de collision
// Calculer les valeurs d'angle et de sinus et cosinus - valeurs exactes
//var c = (obj.x*ball.y - obj.y*ball.x)/(2*R),
// d = Math.sqrt(balle.x*balle.x + balle.y*balle.y),
// angle = Math.asin(ball.y/d) - Math.asin(c/d) - ball.angle%(Math.PI/2),
//angle = Math.asin(oy / (2 * R)),
//Restaurer l'état tangent des deux boules - valeur approximative
ball.x -= (écart - dis)*sin;
ball.y -= (écart - dis)*cos;
disX = obj.x - balle.x;
disY = obj.y - balle.y;
// Calculer les valeurs d'angle et de sinus et cosinus
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);
// Rotation des coordonnées
variable 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 ;
// Vitesse et position après collision
var plusVx = vx1 - vx2;
vx1 = vx2;
vx2 = plusVx + vx1 ;
//rembourrage de bille blanche
if(ball.type == "cue") {
vx1 += rollUp;
rollUp *= 0,2 ;
}
x1 += vx1;
x2 +=vx2;
// Retourner la position en arrière
var x1Final = x1 * hitcos - y1 * hitsin,
y1Final = y1 * hitcos + x1 * hitsin,
x2Final = x2 * hitcos - y2 * hitsin,
y2Final = y2 * hitcos + x2 * hitsin ;
obj.x = balle.x + x2Final;
obj.y = balle.y + y2Final;
balle.x = balle.x + x1Final;
balle.y = balle.y + y1Final;
// Faire pivoter la vitesse vers l'arrière
vx = vx1 * hitcos - vy1 * hitsin;
vy = vy1 * hitcos + vx1 * hitsin;
objVx = vx2 * hitcos - vy2 * hitsin ;
objVy = vy2 * hitcos + vx2 * hitsin ;
//vitesse finale
balle.v = Math.sqrt(vx*vx + vy*vy) * (1 - 0);
obj.v = Math.sqrt(objVx*objVx + objVy*objVy) * (1 - 0);
// Calculer l'angle
balle.angle = Math.atan2(vx, vy);
obj.angle = Math.atan2(objVx , objVy);
//casser;
}
}
}
setBallPos(balle,balle.x,balle.y);
}
}
la fonction estPocket(x,y) {
if(y < POKER) return check(0,2);
sinon si (y > H - POKER) return check(3,5);
sinon, retourne faux ;
vérification de la fonction (m, n) {
pour(var je=m; je<=n; je++) {
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) renvoie vrai ;
sinon, retourne faux ;
}
}
}
}
fonction getBallPos(obj) {
var pos = [];
pos.push(obj.offsetLeft - ÉPAISSEUR + TOTALR);
pos.push(obj.offsetTop - ÉPAISSEUR + TOTALR);
retour pos;
}
fonction setPos(obj,x,y) {
obj.style.left = x + "px" ;
obj.style.top = y + "px" ;
}
fonction setBallPos(balle,x,y) {
if(ball.constructor == Ball) {
balle.x = x;
balle.y = y;
balle = balle.elem;
}
setPos(balle,x + ÉPAISSEUR - TOTALR,y + ÉPAISSEUR - TOTALR);
}
fonction drawDot(wrap,x,y) {
var elem = document.createElement("div");
setStyle(élément,{
position : "absolue",
largeur : "1px",
hauteur : "1px",
Taille de la police : "1px",
fond : "blanc"
});
setPos(élément,x,y);
wrap.appendChild(elem);
}
fonction updateForce() {
var obj = $("force"),
lentille = 80,
haut = vrai ;
forceTimer = window.setInterval(update,10);
fonction mise à jour() {
if(up) setStyle(obj,"width",len+++"px");
sinon setStyle(obj,"width",len--+"px");
if(len > 136) up = faux ;
if(len <= 0) up = vrai ;
}
}
fonction setStyle() {
if(arguments.length == 2 && typeof arguments[1] == "object") {
pour (clé var dans les arguments [1]) {
arguments[0].style[key] = arguments[1][key];
}
} sinon si (arguments.length > 2) {
arguments[0].style[arguments[1]] = arguments[2];
}
}
fonction cacher(obj) {
setStyle(obj,"affichage","aucun");
}
fonction show(obj) {
setStyle(obj,"affichage","bloc");
}
//informations de sortie
fonction trace(qc,qui) {
qui = qui || $("conseils");
if(document.all) who.innerText = qch;
sinon who.textContent = qc;
rendre qui;
}
fonction showScore(n) {
var wrap = $("scoreBoard");
trace(n+"bielle",wrap);
fadeIn(wrap);
}
fonction 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,
étape = posStep.length,
inTimer = window.setInterval(showIn,20),
temporisateur ;
fonction showIn() {
setOpacity(obj,opaStep[t]);
obj.style.top = fromY + posStep[t] + "px";
t++ ;
si(t>=étape) {
window.clearInterval(inTimer);
outTimer = window.setInterval(fadeOut,50);
}
}
fonction fadeOut() {
t-- ;
setOpacity(obj,opaStep[t]);
obj.style.top = fromY + posStep[t] + "px";
si(t <= 0) {
window.clearInterval(outTimer);
cacher(obj);
}
}
}
fonction setOpacity(obj,n) {
obj.style.cssText = "filter:alpha(opacity="+ n*100 +"); -moz-opacity:"+ n +"; opacité:"+ n;
}
fonction showTips() {
var je = 0;
conseil();
window.setInterval(tip,3000);
fonction pointe() {
trace(CONSEILS[i++]);
si (i >= TIPS.length) i = 0;
}
}
</script>
</tête>
<corps>
<div class="info">Discuter : <a href=" http://bbs.blueidea.com/thread-2951566-1-1.html"> Blueidea</a >   ; //cnwander.com/blog/?p=11">L'espace de Wander</a></div>
<h1>Les Chinois se lèvent ! <span class="sub">60e anniversaire</span></h1>
<div id="table">
<div id="scoreBoard"></div>
</div>
<div class="bot">
<div id="tips"></div>
<classe div = "ctrl">
<div id="force"></div>
<div id="shootPos">
<div id="dot"></div>
</div>
</div>
</div>
</corps>
</html>
Bien qu'on l'appelle sans vergogne tennis de table, il est en réalité loin du vrai tennis de table, et il reste encore de nombreux points à améliorer.
Problèmes spécifiques à résoudre :
Il y aura certainement beaucoup d'autres problèmes. J'ai peur d'être trop distrait pendant les vacances et de ne pas pouvoir continuer plus tard. Je vais tout finir d'un coup. un peu pressé, je résoudrai les problèmes lentement plus tard. Je les publierai d'abord pour les étudiants intéressés par ce sujet.
Les mathématiques au collège ne sont fondamentalement qu'une formalité, et j'ai très peu oublié la physique et les mathématiques au lycée. Ce n'est que lorsque j'ai commencé à faire des choses que j'ai réalisé que j'étais trop faible dans ce domaine. la région me donnera quelques conseils.