MegaBall2D — различия между версиями

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск
(Описание)
(Описание)
 
(не показано 6 промежуточных версий 3 участников)
Строка 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 Грешников П.С.]
+
Исполнитель: [http://tm.spbstu.ru/%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 Грешников П.С.]
  
 
Группа 13632/1 Кафедра Теоретической механики.
 
Группа 13632/1 Кафедра Теоретической механики.
  
Файл: [[http://mech.spbstu.ru/images/0/0c/%D0%9A%D0%A0_JS.docx]]
+
Файл: [[http://tm.spbstu.ru/htmlets/Greshnikov%20PS/KR_JS.docx]]
  
 
== Математическая модель ==
 
== Математическая модель ==
Строка 16: Строка 18:
  
 
{{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Greshnikov%20PS/BB.html |width=1050 |height=600 |border=1 }}
 
{{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Greshnikov%20PS/BB.html |width=1050 |height=600 |border=1 }}
 +
 +
== Код программы ==
 +
<div class="mw-collapsible mw-collapsed">
 +
<syntaxhighlight lang=javascript>
 +
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();
 +
    }
 +
}
 +
}
 +
</syntaxhighlight>
 +
<div>

Текущая версия на 15:18, 19 июня 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();
    }
	}
}