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();
    }
	}
}