我在ball2.js工作。我有一个有4面墙的盒子里的可拖动的球。球是可拖动的,可拉动的。我想更新我的底部直墙到一个小曲线,所以它会看起来像一个碗。任何帮助将不胜感激
球JS(文件)
var canvas;
let xyz = 1;
var delta = [ 0, 0 ];
var stage = [ window.screenX, window.screenY, window.innerWidth, window.innerHeight ];
getBrowserDimensions();
var themes = [ [ "#10222B", "#95AB63", "#BDD684", "#E2F0D6", "#F6FFE0" ],
]; // Here you can add/remove the theme colours.
var theme;
var worldAABB, world, iterations = 1, timeStep = 1 / 15;
var walls = [];
var wall_thickness = 200;
var wallsSetted = false;
var bodies, elements, text;
var createMode = false;
var destroyMode = false;
var isMouseDown = false;
var mouseJoint;
var mouse = { x: 0, y: 0 };
var gravity = { x: 0, y: 1 };
var PI2 = Math.PI * 2;
var timeOfLastTouch = 0;
init();
play();
function init() {
canvas = document.getElementById("canvas");
console.log(canvas);
canvas.style.borderTopLeftRadius = "20px";
// canvas.style[ 'backgroundColor' ] = "#000";
// var ctx = canvas.getContext("2d");
// ctx.fillStyle = "blue";
document.onmousedown = onDocumentMouseDown;
document.onmouseup = onDocumentMouseUp;
document.onmousemove = onDocumentMouseMove;
document.ondblclick = onDocumentDoubleClick;
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
document.addEventListener( 'touchend', onDocumentTouchEnd, false );
window.addEventListener( 'deviceorientation', onWindowDeviceOrientation, false );
// init box2d
worldAABB = new b2AABB();
worldAABB.minVertex.Set( -200, -200 );
worldAABB.maxVertex.Set( window.innerWidth + 200, window.innerHeight + 200 );
world = new b2World( worldAABB, new b2Vec2( 0, 0 ), true );
setWalls();
reset();
}
function play() {
setInterval( loop, 1000 / 40 );
}
function reset() {
var i;
if ( bodies ) {
for ( i = 0; i < bodies.length; i++ ) {
var body = bodies[ i ]
canvas.removeChild( body.GetUserData().element );
world.DestroyBody( body );
body = null;
}
}
// color theme
theme = themes[ Math.random() * themes.length >> 0 ];
// document.body.style[ 'backgroundColor' ] = "#e2e2e2";
bodies = [];
elements = [];
// createInstructions();
for( i = 0; i < 50; i++ ) {
createBall();
}
}
//
function onDocumentMouseDown() {
isMouseDown = true;
return false;
}
function onDocumentMouseUp() {
isMouseDown = false;
return false;
}
function onDocumentMouseMove( event ) {
mouse.x = event.clientX + 0;
mouse.y = event.clientY + 250;
}
function onDocumentDoubleClick() {
reset();
}
function onDocumentTouchStart( event ) {
if( event.touches.length == 1 ) {
event.preventDefault();
// Faking double click for touch devices
var now = new Date().getTime();
if ( now - timeOfLastTouch < 250 ) {
reset();
return;
}
timeOfLastTouch = now;
mouse.x = event.touches[ 0 ].pageX;
mouse.y = event.touches[ 0 ].pageY;
isMouseDown = true;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouse.x = event.touches[ 0 ].pageX;
mouse.y = event.touches[ 0 ].pageY;
}
}
function onDocumentTouchEnd( event ) {
if ( event.touches.length == 0 ) {
event.preventDefault();
isMouseDown = false;
}
}
function onWindowDeviceOrientation( event ) {
if ( event.beta ) {
gravity.x = Math.sin( event.gamma * Math.PI / 180 );
gravity.y = Math.sin( ( Math.PI / 4 ) + event.beta * Math.PI / 180 );
}
}
//
function createInstructions() {
var size = 250;
var element = document.createElement( 'div' );
element.width = size;
element.height = size;
element.style.position = 'absolute';
element.style.left = -200 + 'px';
element.style.top = -200 + 'px';
element.style.cursor = "default";
canvas.appendChild(element);
elements.push( element );
var circle = document.createElement( 'canvas' );
circle.width = size;
circle.height = size;
var graphics = circle.getContext( '2d' );
graphics.fillStyle = theme[ 3 ];
graphics.beginPath();
graphics.arc( size * .5, size * .5, size * .5, 0, PI2, true );
graphics.closePath();
graphics.fill();
element.appendChild( circle );
text = document.createElement( 'div' );
text.onSelectStart = null;
text.innerHTML = '<span style="color:' + theme[0] + ';font-size:40px;">Hello!</span><br /><br /><span style="font-size:15px;"><strong>This is how it works:</strong><br /><br />1. Drag a ball.<br />2. Double click to change colors.<br />3. Shake your browser.<br />4. Click Background.<br />5. Play!</span>';
text.style.color = theme[1];
text.style.position = 'absolute';
text.style.left = '0px';
text.style.top = '0px';
text.style.fontFamily = 'Georgia';
text.style.textAlign = 'center';
element.appendChild(text);
text.style.left = ((250 - text.clientWidth) / 2) +'px';
text.style.top = ((250 - text.clientHeight) / 2) +'px';
var b2body = new b2BodyDef();
var circle = new b2CircleDef();
circle.radius = size / 2;
circle.density = 1;
circle.friction = 0.3;
circle.restitution = 0.3;
b2body.AddShape(circle);
b2body.userData = {element: element};
b2body.position.Set( Math.random() * stage[2], Math.random() * -200 );
b2body.linearVelocity.Set( Math.random() * 400 - 200, Math.random() * 400 - 200 );
bodies.push( world.CreateBody(b2body) );
}
function createBall( x, y ) {
// console.log(xyz);
xyz++;
if(xyz == 1){
var img = document.getElementById("coin1")
}else if(xyz == 2){
var img = document.getElementById("coin2")
}else if(xyz == 3){
var img = document.getElementById("coin3")
}else if(xyz == 4){
var img = document.getElementById("coin4")
}else if(xyz == 5){
var img = document.getElementById("coin5")
}else if(xyz == 6){
var img = document.getElementById("coin6")
}else if(xyz == 7){
var img = document.getElementById("coin7")
}else if(xyz == 8){
var img = document.getElementById("coin8")
}else if(xyz == 9){
var img = document.getElementById("coin9")
}else if(xyz == 10){
var img = document.getElementById("coin10")
}else if(xyz == 11){
var img = document.getElementById("coin11")
}else if(xyz == 12){
var img = document.getElementById("coin12")
}else if(xyz == 13){
var img = document.getElementById("coin13")
}else if(xyz == 14){
var img = document.getElementById("coin14")
}else if(xyz == 15){
var img = document.getElementById("coin15")
}else if(xyz == 16){
var img = document.getElementById("coin16")
}else if(xyz == 17){
var img = document.getElementById("coin17")
}else if(xyz == 18){
var img = document.getElementById("coin18")
}else if(xyz == 19){
var img = document.getElementById("coin19")
}else if(xyz == 20){
var img = document.getElementById("coin20")
}else if(xyz == 21){
var img = document.getElementById("coin21")
}else if(xyz == 22){
var img = document.getElementById("coin22")
}else if(xyz == 23){
var img = document.getElementById("coin23")
}else if(xyz == 24){
var img = document.getElementById("coin24")
}else if(xyz == 25){
var img = document.getElementById("coin25")
}else if(xyz == 26){
var img = document.getElementById("coin26")
}else if(xyz == 27){
var img = document.getElementById("coin27")
}else if(xyz == 28){
var img = document.getElementById("coin28")
}else if(xyz == 29){
var img = document.getElementById("coin29")
}else if(xyz == 30){
var img = document.getElementById("coin30")
}else if(xyz == 31){
var img = document.getElementById("coin31")
}else if(xyz == 32){
var img = document.getElementById("coin32")
}else if(xyz == 33){
var img = document.getElementById("coin33")
}else if(xyz == 34){
var img = document.getElementById("coin34")
}else if(xyz == 35){
var img = document.getElementById("coin35")
}else if(xyz == 36){
var img = document.getElementById("coin36")
}else if(xyz == 37){
var img = document.getElementById("coin37")
}else if(xyz == 38){
var img = document.getElementById("coin38")
}else if(xyz == 39){
var img = document.getElementById("coin39")
}else if(xyz == 40){
var img = document.getElementById("coin40")
}else if(xyz == 41){
var img = document.getElementById("coin41")
}else if(xyz == 42){
var img = document.getElementById("coin42")
}else if(xyz == 43){
var img = document.getElementById("coin43")
}else if(xyz == 44){
var img = document.getElementById("coin44")
}else if(xyz == 45){
var img = document.getElementById("coin45")
}else if(xyz == 46){
var img = document.getElementById("coin46")
}else if(xyz == 47){
var img = document.getElementById("coin47")
}else if(xyz == 48){
var img = document.getElementById("coin48")
}else if(xyz == 49){
var img = document.getElementById("coin49")
}
else{
var img = document.getElementById("coin50")
}
var x = x || Math.random() * stage[2];
var y = y || Math.random() * -200;
var size = (Math.random() * 100 >> 0) + 20;
var element = document.createElement("canvas");
element.width = size;
element.height = size;
element.style.position = 'absolute';
element.style.left = -200 + 'px';
element.style.top = -200 + 'px';
element.style.WebkitTransform = 'translateZ(0)';
element.style.MozTransform = 'translateZ(0)';
element.style.OTransform = 'translateZ(0)';
element.style.msTransform = 'translateZ(0)';
element.style.transform = 'translateZ(0)';
var graphics = element.getContext("2d");
var num_circles = Math.random();
for (var i = size; i > 0; i-= (size/num_circles)) {
graphics.drawImage(img,0,0, size , size);
graphics.arc(size * .5, size * .5, i * .5, 0, PI2, true);
canvas.appendChild(element);
elements.push( element );
// graphics.arc(size, size, i, 0, PI2, true);
// graphics.closePath();
// graphics.fill();
}
var b2body = new b2BodyDef();
var circle = new b2CircleDef();
circle.radius = size >> 1;
circle.density = 1;
circle.friction = 0.3;
circle.restitution = 0.3;
b2body.AddShape(circle);
b2body.userData = {element: element};
b2body.position.Set( x, y );
b2body.linearVelocity.Set( Math.random() * 400 - 200, Math.random() * 400 - 200 );
bodies.push( world.CreateBody(b2body) );
}
//
function loop() {
if (getBrowserDimensions()) {
setWalls();
}
delta[0] += (0 - delta[0]) * .5;
delta[1] += (0 - delta[1]) * .5;
world.m_gravity.x = gravity.x * 350 + delta[0];
world.m_gravity.y = gravity.y * 350 + delta[1];
mouseDrag();
world.Step(timeStep, iterations);
for (i = 0; i < bodies.length; i++) {
var body = bodies[i];
var element = elements[i];
element.style.left = (body.m_position0.x - (element.width >> 1)) + 'px';
element.style.top = (body.m_position0.y - (element.height >> 1)) + 'px';
if (element.tagName == 'DIV') {
var style = 'rotate(' + (body.m_rotation0 * 57.2957795) + 'deg) translateZ(0)';
text.style.WebkitTransform = style;
text.style.MozTransform = style;
text.style.OTransform = style;
text.style.msTransform = style;
text.style.transform = style;
}
}
}
// .. BOX2D UTILS
function createBox(world, x, y, width, height, fixed) {
if (typeof(fixed) == 'undefined') {
fixed = true;
}
var boxSd = new b2BoxDef();
if (!fixed) {
boxSd.density = 1.0;
}
boxSd.extents.Set(width, height);
var boxBd = new b2BodyDef();
boxBd.AddShape(boxSd);
boxBd.position.Set(x,y);
return world.CreateBody(boxBd);
}
function createBox2(world, x, y, width, height, fixed) {
if (typeof(fixed) == 'undefined') {
fixed = true;
}
var boxSd = new b2CircleDef();
if (!fixed) {
boxSd.density = 1.0;
}
boxSd.radius = 100;
var boxBd = new b2BodyDef();
boxBd.AddShape(boxSd);
boxBd.position.Set(x,y);
return world.CreateBody(boxBd);
}
function mouseDrag()
{
// mouse press
if (createMode) {
createBall( mouse.x, mouse.y );
} else if (isMouseDown && !mouseJoint) {
var body = getBodyAtMouse();
if (body) {
var md = new b2MouseJointDef();
md.body1 = world.m_groundBody;
md.body2 = body;
md.target.Set(mouse.x, mouse.y);
md.maxForce = 30000 * body.m_mass;
// md.timeStep = timeStep;
mouseJoint = world.CreateJoint(md);
body.WakeUp();
} else {
// createMode = true;
}
}
// mouse release
if (!isMouseDown) {
createMode = false;
destroyMode = false;
if (mouseJoint) {
world.DestroyJoint(mouseJoint);
mouseJoint = null;
}
}
// mouse move
if (mouseJoint) {
var p2 = new b2Vec2(mouse.x, mouse.y);
mouseJoint.SetTarget(p2);
}
}
function getBodyAtMouse() {
// Make a small box.
var mousePVec = new b2Vec2();
mousePVec.Set(mouse.x, mouse.y);
var aabb = new b2AABB();
aabb.minVertex.Set(mouse.x - 1, mouse.y - 1);
aabb.maxVertex.Set(mouse.x + 1, mouse.y + 1);
// Query the world for overlapping shapes.
var k_maxCount = 10;
var shapes = new Array();
var count = world.Query(aabb, shapes, k_maxCount);
var body = null;
for (var i = 0; i < count; ++i) {
if (shapes[i].m_body.IsStatic() == false) {
if ( shapes[i].TestPoint(mousePVec) ) {
body = shapes[i].m_body;
break;
}
}
}
return body;
}
function setWalls() {
if (wallsSetted) {
world.DestroyBody(walls[0]);
world.DestroyBody(walls[1]);
world.DestroyBody(walls[2]);
world.DestroyBody(walls[3]);
walls[0] = null;
walls[1] = null;
walls[2] = null;
walls[3] = null;
}
walls[0] = createBox(world, stage[2] / 2, - wall_thickness, stage[2], wall_thickness);
// Bottom Wall Starts
walls[1] = createBox(world, stage[2], stage[3] + wall_thickness, stage[2], wall_thickness);
// Bottom Wall Ends
// function createBox(world, x, y, width, height, fixed) {
// Left Wall
walls[2] = createBox(world, - wall_thickness, stage[3] / 2, wall_thickness, stage[3]);
// Left Wall
// Right wall
walls[3] = createBox(world, stage[2] + wall_thickness, stage[3] / 2, wall_thickness, stage[3]);
// Right Wall
wallsSetted = true;
}
// BROWSER DIMENSIONS
function getBrowserDimensions() {
var changed = false;
if (stage[0] != window.screenX) {
delta[0] = (window.screenX - stage[0]) * 50;
stage[0] = window.screenX;
changed = true;
}
if (stage[1] != window.screenY) {
delta[1] = (window.screenY - stage[1]) * 50;
stage[1] = window.screenY;
changed = true;
}
if (stage[2] != window.innerWidth) {
stage[2] = window.innerWidth;
changed = true;
}
if (stage[3] != window.innerHeight) {
stage[3] = window.innerHeight;
changed = true;
}
return changed;
}
超文本标记语言
<div class="md:block hidden">
<img src="{{ asset('/assets/img/coin-1.png') }}" id="coin1" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-2.png') }}" id="coin2" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-3.png') }}" id="coin3" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-4.png') }}" id="coin4" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-5.png') }}" id="coin5" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-6.png') }}" id="coin6" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-7.png') }}" id="coin7" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-8.png') }}" id="coin8" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-9.png') }}" id="coin9" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-10.png') }}" id="coin10" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-11.png') }}" id="coin11" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-12.png') }}" id="coin12" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-13.png') }}" id="coin13" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-14.png') }}" id="coin14" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-15.png') }}" id="coin15" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-16.png') }}" id="coin16" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-17.png') }}" id="coin17" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-18.png') }}" id="coin18" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-19.png') }}" id="coin19" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-20.png') }}" id="coin20" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-21.png') }}" id="coin21" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-22.png') }}" id="coin22" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-23.png') }}" id="coin23" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-24.png') }}" id="coin24" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-25.png') }}" id="coin25" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-26.png') }}" id="coin26" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-27.png') }}" id="coin27" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-28.png') }}" id="coin28" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-29.png') }}" id="coin29" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-30.png') }}" id="coin30" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-31.png') }}" id="coin31" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-32.png') }}" id="coin32" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-33.png') }}" id="coin33" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-34.png') }}" id="coin34" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-35.png') }}" id="coin35" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-36.png') }}" id="coin36" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-37.png') }}" id="coin37" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-38.png') }}" id="coin38" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-39.png') }}" id="coin39" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-40.png') }}" id="coin40" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-41.png') }}" id="coin41" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-42.png') }}" id="coin42" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-43.png') }}" id="coin43" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-44.png') }}" id="coin44" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-45.png') }}" id="coin45" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-46.png') }}" id="coin46" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-47.png') }}" id="coin47" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-48.png') }}" id="coin48" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-49.png') }}" id="coin49" style="display: none;" width="32" height="32">
<img src="{{ asset('/assets/img/coin-50.png') }}" id="coin50" style="display: none;" width="32" height="32">
<div>
<div id="canvas"></div>
</div>
</div>
我把球放在盒子里,盒子有4面墙,这样球就不会跑到外面去。它是可以拖动的,可以放下的,可以在彼此之间推动的。我希望底部的墙有点弯曲,这样它看起来就像一个碗里的球。
1条答案
按热度按时间qvtsj1bj1#
Box 2D不支持凹形,只支持凸形,所以你需要用以下两种方法来近似你的曲线:
1.外部三角形Map到圆环的四分之一切片,圆环的内部是内壁
1.角点是所有三角形上的共享点,其他两个点(内部)从曲线计算。
https://box2d.org/posts/2020/06/ghost-collisions/
然而,由于球实际上被束缚在曲线之外,因为盒子防止球的周长接触到角落,你可以直接用图形绘制曲线,而不需要包含在box 2d中,因为box 2d检查是多余的。虽然这会防止球滚动,如果它们在重力下掉落并落在一边,即特别是为了拖或拉,这是可以的。