MegaBall2D — различия между версиями
(→top) |
|||
Строка 1: | Строка 1: | ||
+ | |||
+ | |||
+ | == Описание == | ||
+ | Игра, где нужно попасть левым мячиком в правый. Присутствуют отскоки от стенок и гравитация. Радиус мячиков уменьшается с каждым уровнем. Если левый мячик уже никак не достигнет правого, то игра начинается заново. | ||
+ | |||
+ | Исполнитель: [http://%D0%93%D1%80%D0%B5%D1%88%D0%BD%D0%B8%D0%BA%D0%BE%D0%B2_%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB#.D0.9D.D0.B0.D1.83.D1.87.D0.BD.D0.B0.D1.8F_.D0.B4.D0.B5.D1.8F.D1.82.D0.B5.D0.BB.D1.8C.D0.BD.D0.BE.D1.81.D1.82.D1.8C Грешников П.С.] | ||
+ | |||
+ | Группа 13632/1 Кафедра Теоретической механики. | ||
+ | |||
+ | Файл: [[http://mech.spbstu.ru/images/0/0c/%D0%9A%D0%A0_JS.docx]] | ||
+ | |||
+ | == Математическая модель == | ||
+ | |||
+ | Рассматриваем левый мячик как тело, брошенное под углом к горизонту. | ||
+ | |||
+ | |||
+ | == Визуализация == | ||
+ | |||
+ | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Greshnikov%20PS/BB.html |width=1050 |height=600 |border=1 }} | ||
+ | |||
== Код программы == | == Код программы == | ||
+ | <div class="mw-collapsible mw-collapsed"> | ||
window.addEventListener("load",main,false); | window.addEventListener("load",main,false); | ||
function main(){ | function main(){ | ||
Строка 200: | Строка 221: | ||
} | } | ||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Версия 12:02, 31 мая 2019
Описание
Игра, где нужно попасть левым мячиком в правый. Присутствуют отскоки от стенок и гравитация. Радиус мячиков уменьшается с каждым уровнем. Если левый мячик уже никак не достигнет правого, то игра начинается заново.
Исполнитель: Грешников П.С.
Группа 13632/1 Кафедра Теоретической механики.
Файл: [[1]]
Математическая модель
Рассматриваем левый мячик как тело, брошенное под углом к горизонту.
Визуализация
Код программы
window.addEventListener("load",main,false); function main(){
var ctx = example_canvas.getContext("2d"); var h=example_canvas.height; var w=example_canvas.width; var lvl=1; var r=40*10/(10+lvl); var dt=0.05; var fps=100; var flag=false; var x=250; var y=h/2; var x0=0; var y0=0; var x_k=250; var y_k=800; var vx=0; var vy=0; var padding ={x:0, y:0}; var defaultColor="black"; var TouchColor="red"; var XSL; var YSL; var start=false; var imp=0;
setInterval(control,1000/fps);
function get_mouse_coords(e){ var m={}; // объявление пустого объекта var rect = example_canvas.getBoundingClientRect(); m.x=e.clientX-rect.left; m.y=e.clientY-rect.top; return m; }
example_canvas.onmousedown=function(e){ m=get_mouse_coords(e); var dx=m.x-x; var dy=m.y-y; padding.x=dx; padding.y=dy; if (Math.sqrt(dx*dx+dy*dy)<r) { x0=m.x; y0=m.y; flag = true; ctx.fillStyle=TouchColor; draw(); } }
star();
example_canvas.onmouseup=function(e){ flag = false; ctx.fillStyle=defaultColor; draw(); m=get_mouse_coords(e); var dx=m.x-x; var dy=m.y-y; padding.x=dx; padding.y=dy; if (Math.sqrt(dx*dx+dy*dy)<r) { x_k=m.x; y_k=m.y; speed(); start=true; }
}
example_canvas.onmousemove = function(e){ if (flag) { m=get_mouse_coords(e); x=m.x-padding.x; y=m.y-padding.y; draw(); ctx.beginPath(); ctx.moveTo(Math.round(x),Math.round(y)); ctx.lineTo(Math.round(x0),Math.round(y0)); ctx.stroke(); } }
function phys(){
if (vy*vy<(y-YSL-2*r)) console.log('imp');
vy+=100*dt; x=x+vx*dt; y=y+vy*dt+100*dt*dt/2; if(x>=w-(r)) { vx=(-0.9)*Math.abs(vx); } else if(x<=(r)) vx=0.9*Math.abs(vx); if(y>=h-(r)){ vy=-0.9*Math.abs(vy); if (Math.abs(vy)<10){ vy=-150*dt; } } else if(y<=(r)) vy=0.9*Math.abs(vy);
if ((x >w/2-5-r)&&(x<w/2)&&(y>h*1/3-r)) { vx=-0.9*Math.abs(vx); } if ((x>w/2)&&(x<w/2+5+r)&&(y>h*1/3-r)){ vx=0.9*Math.abs(vx); } if ((x>w/2-5)&&(x<w/2+5)&&(y<h/3-r+5)&&(y>h/3-r)){ vy=-1000*Math.abs(vx); } }
function speed(){ vx=-(x_k-x0)*2; vy=-(y_k-y0)*2; }
function draw() { ctx.clearRect(0,0,w,h); ctx.beginPath(); ctx.arc(x,y,r,0,2*Math.PI); ctx.arc(XSL,YSL,r,0,2*Math.PI); ctx.moveTo(Math.round(x0),Math.round(y0)); ctx.lineTo(x,y); ctx.font = 'bold 30px sans-serif'; ctx.strokeText("CURRENT LEVEL:", 600, 100); ctx.strokeText(lvl, 900, 100);
ctx.fill();
ctx.beginPath();
ctx.moveTo(w/2-5,h);
ctx.lineTo(w/2-5,h/3);
ctx.moveTo(w/2+5,h/3);
ctx.lineTo(w/2+5,h);
ctx.moveTo(w/2+5,h/3);
ctx.lineTo(w/2-5,h/3);
ctx.stroke();
}
draw();
function control() { if (start) phys(); draw(); confront();
imposible();
}
function star(){ XSL=Math.random()*(500-2*(r))+w/2+r; YSL=Math.random()*(h-2*(r))+r; }
function confront(){ if (((x-XSL)*(x-XSL)+(y-YSL)*(y-YSL)<=4*(r)*(r))&&(start)){ levelup(); } }
function levelup(){ x=250; y=h/2; vx=0; vy=0; lvl++;
r=40*10/(10+lvl);
star(); start=false; }
function restart(){
x=250; y=h/2; vx=0; vy=0; lvl=1;
r=40*10/(10+lvl);
star(); start=false; }
function imposible() {
if ((start)&&((vy*vy<(y-YSL-2*r))||((x<w/2)&&(vy*vy<(2*y/3+r))))) { imp++; } if (imp>40) { imp=0; restart(); }
}
}