MegaBall2D
Материал из Department of Theoretical and Applied Mechanics
Описание
Игра, где нужно попасть левым мячиком в правый. Присутствуют отскоки от стенок и гравитация. Радиус мячиков уменьшается с каждым уровнем. Если левый мячик уже никак не достигнет правого, то игра начинается заново.
Исполнитель: Грешников П.С.
Группа 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();
}
}
}