原生js实现重力感应积木游戏效果代码
代码语言:html
所属分类:游戏
代码描述:原生js实现重力感应积木游戏效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!doctype html> <html> <head> <meta charset="utf-8"> <title>HTML5重力感应积木游戏在线演示</title> <style> html { overflow: hidden; -ms-touch-action: none; -ms-content-zooming: none; } body { position: absolute; margin: 0; padding: 0; background: #000; width: 100%; height: 100%; } #screen { position: absolute; width: 100%; height: 100%; } #textures, .textures { visibility:hidden; } </style> <script> // ===== ge1doot global ===== var ge1doot = ge1doot || { json: null, screen: null, pointer: null, camera: null, loadJS: function (url, callback, data) { if (typeof url == "string") url = [url]; var load = function (src) { var script = document.createElement("script"); if (callback) { if (script.readyState){ script.onreadystatechange = function () { if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; if (--n === 0) callback(data || false); } } } else { script.onload = function() { if (--n === 0) callback(data || false); } } } script.src = src; document.getElementsByTagName("head")[0].appendChild(script); } for (var i = 0, n = url.length; i < n; i++) load(url[i]); } } // ===== html/canvas container ===== ge1doot.Screen = function (setup) { ge1doot.screen = this; this.elem = document.getElementById(setup.container) || setup.container; this.ctx = this.elem.tagName == "CANVAS" ? this.elem.getContext("2d") : false; this.style = this.elem.style; this.left = 0; this.top = 0; this.width = 0; this.height = 0; this.cursor = "default"; this.setup = setup; this.resize = function () { var o = this.elem; this.width = o.offsetWidth; this.height = o.offsetHeight; for (this.left = 0, this.top = 0; o != null; o = o.offsetParent) { this.left += o.offsetLeft; this.top += o.offsetTop; } if (this.ctx) { this.elem.width = this.width; this.elem.height = this.height; } this.setup.resize && this.setup.resize(); } this.setCursor = function (type) { if (type !== this.cursor && 'ontouchstart' in window === false) { this.cursor = type; this.style.cursor = type; } } window.addEventListener('resize', function () { ge1doot.screen.resize(); }, false); !this.setup.resize && this.resize(); } // ==== unified touch events handler ==== ge1doot.Pointer = function (setup) { ge1doot.pointer = this; var self = this; var body = document.body; var html = document.documentElement; this.setup = setup; this.screen = ge1doot.screen; this.elem = this.screen.elem; this.X = 0; this.Y = 0; this.Xi = 0; this.Yi = 0; this.bXi = 0; this.bYi = 0; this.Xr = 0; this.Yr = 0; this.startX = 0; this.startY = 0; this.scale = 0; this.wheelDelta = 0; this.isDraging = false; this.hasMoved = false; this.isDown = false; this.evt = false; var sX = 0; var sY = 0; // prevent default behavior if (setup.tap) this.elem.onclick = function () { return false; } if (!setup.documentMove) { document.ontouchmove = function(e) { e.preventDefault(); } } document.addEventListener("MSHoldVisual", function(e) { e.preventDefault(); }, false); if (typeof this.elem.style.msTouchAction != 'undefined') this.elem.style.msTouchAction = "none"; this.pointerDown = function (e) { if (!this.isDown) { if (this.elem.setCapture) this.elem.setCapture(); this.isDraging = false; this.hasMoved = false; this.isDown = true; this.evt = e; this.Xr = (e.clientX !== undefined ? e.clientX : e.touches[0].clientX); this.Yr = (e.clientY !== undefined ? e.clientY : e.touches[0].clientY); this.X = sX = this.Xr - this.screen.left; this.Y = sY = this.Yr - this.screen.top + ((html && html.scrollTop) || body.scrollTop); this.setup.down && this.setup.down(e); } } this.pointerMove = function(e) { this.Xr = (e.clientX !== undefined ? e.clientX : e.touches[0].clientX); this.Yr = (e.clientY !== undefined ? e.clientY : e.touches[0].clientY); this.X = this.Xr - this.screen.left; this.Y = this.Yr - this.screen.top + ((html && html.scrollTop) || body.scrollTop); if (this.isDown) { this.Xi = this.bXi + (this.X - sX); this.Yi = this.bYi - (this.Y - sY); } if (Math.abs(this.X - sX) > 11 || Math.abs(this.Y - sY) > 11) { this.hasMoved = true; if (this.isDown) { if (!this.isDraging) { this.startX = sX; this.startY = sY; this.setup.startDrag && this.setup.startDrag(e); this.isDraging = true; } else { this.setup.drag && this.setup.drag(e); } } else { sX = this.X; sY = this.Y; } } this.setup.move && this.setup.move(e); } this.pointerUp = function(e) { this.bXi = this.Xi; this.bYi = this.Yi; if (!this.hasMoved) { this.X = sX; this.Y = sY; this.setup.tap && this.setup.tap(this.evt); } else { this.setup.up && this.setup.up(this.evt); } this.isDraging = false; this.isDown = false; this.hasMoved = false; this.setup.up && this.setup.up(this.evt); if (this.elem.releaseCapture) this.elem.releaseCapture(); this.evt = false; } this.pointerCancel = function(e) { if (this.elem.releaseCapture) this.elem.releaseCapture(); this.isDraging = false; this.hasMoved = false; this.isDown = false; this.bXi = this.Xi; this.bYi = this.Yi; sX = 0; sY = 0; } if ('ontouchstart' in window) { this.elem.ontouchstart = function (e) { self.pointerDown(e); return false; } this.elem.ontouchmove = function (e) { self.pointerMove(e); return false; } this.elem.ontouchend = function (e) { self.pointerUp(e); return false; } this.elem.ontouchcancel = function (e) { self.pointerCancel(e); return false;} } document.addEventListener("mousedown", function (e) { if ( e.target === self.elem || (e.target.parentNode && e.target.parentNode === self.elem) || (e.target.parentNode.parentNode && e.target.parentNode.parentNode === self.elem) ) { if (typeof e.stopPropagation != "undefined") { e.stopPropagation(); } else { e.cancelBubble = true; } e.preventDefault(); self.pointerDown(e); } }, false); document.addEventListener("mousemove", function (e) { self.pointerMove(e); }, false); document.addEventListener("mouseup", function (e) { self.pointerUp(e); }, false); document.addEventListener('gesturechange', function(e) { e.preventDefault(); if (e.scale > 1) self.scale = 0.1; else if (e.scale < 1) self.scale = -0.1; else self.scale = 0; self.setup.scale && self.setup.scale(e); return false; }, false); if (window.navigator.msPointerEnabled) { var nContact = 0; var myGesture = new MSGesture(); myGesture.target = this.elem; this.elem.addEventListener("MSPointerDown", function(e) { if (e.pointerType == e.MSPOINTER_TYPE_TOUCH) { myGesture.addPointer(e.pointerId); nContact++; } }, false); this.elem.addEventListener("MSPointerOut", function(e) { if (e.pointerType == e.MSPOINTER_TYPE_TOUCH) { nContact--; } }, false); this.elem.addEventListener("MSGestureHold", function(e) { e.preventDefault(); }, false); this.elem.addEventListener("MSGestureChange", function(e) { if (nContact > 1) { if (e.preventDefault) e.preventDefault(); self.scale = e.velocityExpansion; self.setup.scale && self.setup.scale(e); } return false; }, false); } if (window.addEventListener) this.elem.addEventListener('DOMMouseScroll', function(e) { if (e.preventDefault) e.preventDefault(); self.wheelDelta = e.detail * 10; self.setup.wheel && self.setup.wheel(e); return false; }, false); this.elem.onmousewheel = function () { self.wheelDelta = -event.wheelDelta * .25; self.setup.wheel && self.setup.wheel(event); return false; } } // ===== request animation frame ===== window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function( run ){ window.setTimeout(run, 16); }; })(); </script> <script > "use strict"; (function () { var scr, ctx, pointer, drag, boxes, dropc = 0, objects = [], contacts = [], contactsI = 0, numIterations, kTimeStep, kGravity, kFriction, mostSeparated = [0, 0, 0, 0, 0], mostPenetrating = [0, 0, 0, 0, 0]; // ==== Rectangle Constructor ==== var Rectangle = function (img, x, y, w, h, invMass, angularVel, angle) { this.img = img; this.w = w; this.h = h; this.vel = [0, 0]; this.pos = [x, y]; this.angularVel = angularVel || 0; this.invMass = invMass || 0; this.angle = angle || 0; this.matrix = [0, 0, 0, 0, 0, 0]; this.matrixNextFrame = [0, 0, 0, 0, 0, 0]; this.motionBounds = [0, 0, 0, 0, 0, 0]; // form local space points this.localSpacePoints = [ [ w / 2, -h / 2], [-w / 2, -h / 2], [-w / 2, h / 2], [ w / 2, h / 2] ]; this.localSpaceNormals = []; this.vCount = this.localSpacePoints.length; // and local space normals for (var i = 0; i < this.vCount; i++ ) { var a = this.localSpacePoints[i]; var b = this.localSpacePoints[(i + 1) % this.vCount]; var x = b[0] - a[0]; var y = b[1] - a[1]; var len = Math.sqrt(x * x + y * y); this.localSpaceNormals[i] = [-y / len, x / len]; } // world points this.worldSpaceNormals = []; this.worldSpacePoints = []; for (var i = 0; i < this.vCount; i++ ) { this.worldSpaceNormals[i] = [0, 0]; this.worldSpacePoints[i] = [0, 0]; } // calculate inverse inertia tensor this.invI = (invMass > 0) ? 1 / ((1 / invMass) * (w * w + h * h) / 6) : 0 // contact points this.c1 = [0, 0]; this.c0 = [0, 0]; } Rectangle.prototype.featurePairJudgement = function (that, fpc) { var closest, closestI, closestD, wsN, v, d, dx, dy, lsp, wsp, mfp0, mfp1, dist, centreDist; for (var edge = 0; edge < this.vCount; edge++) { // get support vertices wsN = this.worldSpaceNormals[edge]; // rotate into rectangle space dx = -wsN[0]; dy = -wsN[1]; v = [ dx * that.matrix[0] + dy * that.matrix[1], dx * that.matrix[2] + dy * that.matrix[3] ]; // get axis bits closestI = -1; closestD = -1E6; // first support for (var i = 0; i < that.vCount; i++) { lsp = that.localSpacePoints[i]; d = v[0] * lsp[0] + v[1] * lsp[1]; if (d > closestD) { closestD = d; closestI = i; } } // form point on plane of minkowski face closest = that.worldSpacePoints[closestI]; wsp = this.worldSpacePoints[edge]; mfp0 = [closest[0] - wsp[0], closest[1] - wsp[1]]; wsp = this.worldSpacePoints[(edge + 1) % this.vCount]; mfp1 = [closest[0] - wsp[0], closest[1] - wsp[1]]; // distance from origin to face dist = mfp0[0] * wsN[0] + mfp0[1] * wsN[1]; // distance to centre dx = closest[0] - this.pos[0]; dx = closest[1] - this.pos[1]; centreDist = dx * dx + dy * dy;; if (dist > 0) { // recompute distance to clamped edge this.projectPointOntoEdge([0, 0], mfp0, mfp1, 0); // recompute distance dist = this.c0[0] * this.c0[0] + this.c0[1] * this.c0[1]; if (dist < mostSeparated[0]) { mostSeparated = [dist, closestI, edge, fpc, centreDist]; } else if (dist == mostSeparated[0] && fpc == mostSeparated[3]) { // got to pick the right one - pick one closest to centre of A if (centreDist < mostSeparated[4]) { mostSeparated = [dist, closestI, edge, fpc, centreDist]; } } } else { // penetration if (dist > mostPenetrating[0]) { mostPenetrating = [dist, closestI, edge, fpc, centreDist]; } else if (dist == mostPenetrating[0] && fpc == mostPenetrating[3]) { // got to pick the right one - pick one closest to centre of A if (centreDist < mostPenetrating[4]) { mostPenetrating = [dist, closestI, edge, fpc, centreDist];.........完整代码请登录后点击上方下载按钮下载查看
网友评论0