js实现恐龙跳跃类避障小游戏代码
代码语言:html
所属分类:游戏
代码描述:js实现恐龙跳跃类避障小游戏代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <h3 style="text-align: center">请点击这里,按键盘方向键 ↑ 开始</h3> <div id="runner-container" class="runner-container offline" style="height: 200px; width: 600px; background: #fff; margin-left: auto; margin-right: auto; margin-top: 100px; border: 1px solid hsla(0,0%,21%,1.00); box-shadow: -1px 11px 46px 5px rgba(0,0,0,0.34); -webkit-box-shadow: -1px 11px 46px 5px rgba(0,0,0,0.34); -moz-box-shadow: -1px 11px 46px 5px rgba(0,0,0,0.34);"> </div> <img id="sprite" style="display: none;" src="//repo.bfw.wiki/bfwrepo/images/game/kongllongspirte.png" alt="test" /> <script> var canvas = document.createElement('canvas'), a = document.getElementById('runner-container'), ctx = canvas.getContext('2d'); canvas.id = 'c'; canvas.width = 600; canvas.height = 150; a.appendChild(canvas); //坐标 var spriteDefinition = { CACTUS_LARGE: { x: 332, y: 2 }, //大仙人掌 CACTUS_SMALL: { x: 228, y: 2 }, //小仙人掌 CLOUD: { x: 86, y: 2 }, //云 HORIZON: { x: 2, y: 54 }, //地面 MOON: { x: 484, y: 2 }, //月亮 PTERODACTYL: { x: 134, y: 2 }, //翼龙 RESTART: { x: 2, y: 2 }, //重新开始按钮 TEXT_SPRITE: { x: 655, y: 2 }, //分数 TREX: { x: 848, y: 2 }, //霸王龙 STAR: { x: 645, y: 2 } //星星 }, FPS = 60, DEFAULT_WIDTH = 600, imgSprite = document.getElementById('sprite'); Runner.config = { ACCELERATION: 0.001, BG_CLOUD_SPEED: 0.2, BOTTOM_PAD: 10, CLEAR_TIME: 3000, CLOUD_FREQUENCY: 0.5, GAMEOVER_CLEAR_TIME: 750, GAP_COEFFICIENT: 0.6, GRAVITY: 0.6, INITIAL_JUMP_VELOCITY: 12, INVERT_FADE_DURATION: 10000, //夜晚持续时间 INVERT_DISTANCE: 700, //每700距离进行昼夜交替 MAX_CLOUDS: 6, //云最大数量 MAX_OBSTACLE_LENGTH: 3, MAX_OBSTACLE_DUPLICATION: 2, MAX_SPEED: 13, MIN_JUMP_HEIGHT: 35, MOBILE_SPEED_COEFFICIENT: 1.2, RESOURCE_TEMPLATE_ID: 'audio-resources', SPEED: 6, SPEED_DROP_COEFFICIENT: 3 }; Runner.defaultDimensions = { HEIGHT: 150, WIDTH: 600 }; Runner.classes = { CANVAS: 'runner-canvas', CONTAINER: 'runner-container', CRASHED: 'crashed', ICON: 'icon-offline', INVERTED: 'inverted', SNACKBAR: 'snackbar', SNACKBAR_SHOW: 'snackbar-show', TOUCH_CONTROLLER: 'controller' }; Runner.sounds = { BUTTON_PRESS: 'offline-sound-press', HIT: 'offline-sound-hit', SCORE: 'offline-sound-reached' }; Runner.keycodes = { JUMP: { '38': 1, '32': 1 }, // Up, spacebar DUCK: { '40': 1 }, // Down RESTART: { '13': 1 } // Enter }; Runner.events = { ANIM_END: 'webkitAnimationEnd', CLICK: 'click', KEYDOWN: 'keydown', KEYUP: 'keyup', MOUSEDOWN: 'mousedown', MOUSEUP: 'mouseup', RESIZE: 'resize', TOUCHEND: 'touchend', TOUCHSTART: 'touchstart', VISIBILITY: 'visibilitychange', BLUR: 'blur', FOCUS: 'focus', LOAD: 'load' }; function Runner(outerContainerId, opt_config) { if (Runner.instance_) { return Runner.instance_; } Runner.instance_ = this; //this.outerContainerEl = document.querySelector(outerContainerId); this.containerEl = null; this.snackbarEl = null; //this.detailsButton = this.outerContainerEl.querySelector('#details-button'); this.config = opt_config || Runner.config; this.dimensions = Runner.defaultDimensions; this.canvas = null; this.ctx = null; this.tRex = null; this.distanceMeter = null; this.distanceRan = 0; this.highestScore = 0; this.time = 0; this.runningTime = 0; this.msPerFrame = 1000 / FPS; this.currentSpeed = this.config.SPEED; this.obstacles = []; //障碍物 this.started = false; this.activated = false; this.crashed = false; this.paused = false; this.inverted = false; this.invertTimer = 0; this.resizeTimerId_ = null; this.playCount = 0; // Sound FX. this.audioBuffer = null; this.soundFx = {}; // Global web audio context for playing sounds. this.audioContext = null; // Images. this.images = {}; this.imagesLoaded = 0; this.loadImages(); } Runner.prototype = { loadImages: function() { this.spriteDef = spriteDefinition; this.init(); }, loadSounds: function() { this.audioContext = new AudioContext(); }, setSpeed: function(opt_speed) { if (opt_speed) this.currentSpeed = opt_speed; }, init: function() { this.setSpeed(); this.canvas = c; this.ctx = ctx; this.ctx.fillStyle = '#f7f7f7'; this.ctx.fill(); this.horizon = new Horizon(this.canvas, this.spriteDef, this.dimensions, this.config.GAP_COEFFICIENT); this.distanceMeter = new DistanceMeter(this.canvas, this.spriteDef.TEXT_SPRITE, this.dimensions.WIDTH); this.tRex = new Trex(this.canvas, this.spriteDef.TREX); this.startListening(); this.update(); }, //开场动画 playIntro: function() { if (!this.started && !this.crashed) { this.playingIntro = true; this.tRex.playingIntro = true; var keyframes = '@-webkit-keyframes intro { ' + 'from { width:' + Trex.config.WIDTH + 'px }' + 'to { width: ' + this.dimensions.WIDTH + 'px }' + '}'; document.styleSheets[0].insertRule(keyframes, 0); this.containerEl = document.getElementById('runner-container'); this.containerEl.addEventListener('webkitAnimationEnd', this.startGame.bind(this)); this.containerEl.style.webkitAnimation = 'intro .4s ease-out 1 both'; this.containerEl.style.width = this.dimensions.WIDTH + 'px'; this.activated = true; this.started = true; } else if (this.crashed) { this.restart(); } }, startGame: function() { this.runningTime = 0; this.playingIntro = false; this.tRex.playingIntro = false; this.containerEl.style.webkitAnimation = ''; this.playCount++; document.addEventListener('visibilitychange', this.onVisibilityChange.bind(this)); window.addEventListener('blur', this.onVisibilityChange.bind(this)); window.addEventListener('focus', this.onVisibilityChange.bind(this)); }, clearCanvas: function() { this.ctx.clearRect(0, 0, this.dimensions.WIDTH, this.dimensions.HEIGHT); }, //todo update: function() { this.drawPending = false; var now = getTimeStamp(); var deltaTime = now - (this.time || now); this.time = now; if (this.activated) { this.clearCanvas(); if (this.tRex.jumping) { this.tRex.updateJump(deltaTime); } this.runningTime += deltaTime; var hasObstacles = this.runningTime > this.config.CLEAR_TIME; //如果是第一次跳跃并且没有播放开场动画,则播放开场动画 if (this.tRex.jumpCount == 1 && !this.playingIntro) { this.playIntro(); } if (this.playingIntro) { this.horizon.update(0, this.currentSpeed, hasObstacles); } else { deltaTime = !this.started ? 0 : deltaTime; this.horizon.update(deltaTime, this.currentSpeed, hasObstacles, this.inverted); } var collision = hasObstacles && checkForCollision(this.horizon.obstacles[0], this.tRex); if (!collision) { this.distanceRan += this.currentSpeed * deltaTime / this.msPerFrame; if (this.currentSpeed < this.config.MAX_SPEED) { this.currentSpeed += this.config.ACCELERATION; } } else { this.gameOver(); } var playAchievementSound = this.distanceMeter.update(deltaTime, Math.ceil(this.distanceRan)); if (playAchievementSound) { this.playSound(this.soundFx.SCORE); } //若夜晚持续时间大于设定值则变为白天 if (this.invertTimer > this.config.INVERT_FADE_DURATION) { this.invertTimer = 0; this.invertTrigger = false; this.invert(); } else if (this.invertTimer) { this.invertTimer += deltaTime; } else { var actualDistance = this.distanceMeter.getActualDistance(Math.ceil(this.distanceRan)); if (actualDistance > 0) { this.invertTrigger = !(actualDistance % this.config.INVERT_DISTANCE); if (this.invertTrigger && this.invertTimer === 0) { this.invertTimer += deltaTime; this.invert(); } } } } if (!this.crashed) { this.tRex.update(deltaTime); this.raq(); } }, handleEvent: function(e) { return (function(evtType, events) { switch (evtType) { case events.KEYDOWN: case events.TOUCHSTART: case events.MOUSEDOWN: this.onKeyDown(e); break; case events.KEYUP: case events.TOUCHEND: case events.MOUSEUP: this.onKeyUp(e); break; } }.bind(this))(e.type, Runner.events); }, startListening: function() { document.addEventListener(Runner.events.KEYDOWN, this); document.addEventListener(Runner.events.KEYUP, this); document.addEventListener(Runner.events.MOUSEDOWN, this); document.addEventListener(Runner.events.MOUSEUP, this); }, stopListening: function() { document.removeEventListener(Runner.events.KEYDOWN, this); document.removeEventListener(Runner.events.KEYUP, this); document.removeEventListener(Runner.events.MOUSEDOWN, this); document.removeEventListener(Runner.events.MOUSEUP, this); }, onKeyDown: function(e) { if (e.target != this.detailsButton) { if (!this.crashed && Runner.keycodes.JUMP[e.keyCode]) { e.preventDefault(); if (!this.activated) { this.loadSounds(); this.activated = true; } if (!this.tRex.jumping && !this.tRex.ducking) { this.tRex.startJump(this.currentSpeed); } } } if (this.activated && !this.crashed && Runner.keycodes.DUCK[e.keyCode]) { e.preventDefault(); if (this.tRex.jumping) { // Speed drop, activated only when jump key is not pressed. this.tRex.setSpeedDrop(); } else if (!this.tRex.jumping && !this.tRex.ducking) { // Duck. this.tRex.setDuck(true); } } }, onKeyUp: function(e) { var keyCode = String(e.keyCode); var isjumpKey = Runner.keycodes.JUMP[keyCode] || e.type == Runner.events.TOUCHEND || e.type == Runner.events.MOUSEDOWN; if (this.isRunning() && isjumpKey) { e.preventDefault(); this.tRex.endJump(); } else if (Runner.keycodes.DUCK[keyCode]) { e.preventDefault(); this.tRex.speedDrop = false; this.tRex.setDuck(false); } else if (this.crashed) { e.preventDefault(); // Check that enough time has elapsed before allowing jump key to restart. var deltaTime = getTimeStamp() - this.time; if (Runner.keycodes.RESTART[keyCode] || this.isLeftClickOnCanvas(e) || (deltaTime >= this.config.GAMEOVER_CLEAR_TIME && Runner.keycodes.JUMP[keyCode])) { e.preventDefault(); this.restart(); } } else if (this.paused && isjumpKey) { // Reset the jump state e.preventDefault(); this.tRex.reset(); this.play(); } }, isLeftClickOnCanvas: function(e) { return e.button != null && e.button < 2 && e.type == Runner.events.MOUSEUP && e.target == this.canvas; }, raq: function() { if (!this.drawPending) { this.drawPending = true; this.raqId = requestAnimationFrame(this.update.bind(this)); } }, isRunning: function() { return !!this.raqId; }, gameOver: function() { //this.playSound(this.soundFx.HIT); //vibrate(200); this.stop(); this.crashed = true; this.distanceMeter.acheivement = false; this.tRex.update(100, Trex.status.CRASHED); // Game over panel. if (!this.gameOverPanel) { this.gameOverPanel = new GameOverPanel(this.canvas, this.spriteDef.TEXT_SPRITE, this.spriteDef.RESTART, this.dimensions); } else { this.gameOverPanel.draw(); } // Update the high score. if (this.distanceRan > this.highestScore) { this.highestScore = Math.ceil(this.distanceRan); this.distanceMeter.setHighScore(this.highestScore); } // Reset the time clock. this.time = getTimeStamp(); }, stop: function() { this.activated = false; this.paused = true; cancelAnimationFrame(this.raqId); this.raqId = 0; }, play: function() { if (!this.crashed) { this.activated = true; this.paused = false; this.tRex.update(0, Trex.status.RUNNING); this.time = getTimeStamp(); this.update(); } }, restart: function() { if (!this.raqId) { this.playCount++; this.runningTime = 0; this.activated = true; this.crashed = false; this.distanceRan = 0; this.setSpeed(this.config.SPEED); this.time = getTimeStamp(); this.containerEl.classList.remove(Runner.classes.CRASHED); this.clearCanvas(); this.distanceMeter.reset(this.highestScore); this.horizon.reset(); this.tRex.reset(); //this.playSound(this.soundFx.BUTTON_PRESS); this.invert(true); this.update(); } }, onVisibilityChange: function(e) { if (document.hidden || document.webkitHidden || e.type == 'blur' || document.visibilityState != 'visible') { this.stop(); } else if (!this.crashed) { this.tRex.reset(); this.play(); } }, playSound: function(soundBuffer) { if (soundBuffer) { var sourceNode = this.audioContext.createBufferSource(); sourceNode.buffer = soundBuffer; sourceNode.connect(this.audioContext.destination); sourceNode.start(0); } }, invert: function(reset) { if (reset) { a.classList.toggle(Runner.classes.INVERTED, this.invertTrigger); //document.body.classList.toggle(Runner.classes.INVERTED,false); this.invertTimer = 0; this.inverted = false; } else { this.inverted = a.classList.toggle(Runner.classes.INVERTED, this.invertTrigger); //this.inverted = document.body.classList.toggle(Runner.classes.INVERTED,this.invertTrigger); } } }; window['Runner'] = Runner; function decodeBase64ToArrayBuffer(base64String) { var len = (base64String.length / 4) * 3; var str = atob(base64String); var arrayBuffer = new ArrayBuffer(len); var bytes = new Uint8Array(arrayBuffer); for (var i = 0; i < len; i++) { bytes[i] = str.charCodeAt(i); } return bytes.buffer; } GameOverPanel.dimensions = { TEXT_X: 0, TEXT_Y: 13, TEXT_WIDTH: 191, TEXT_HEIGHT: 11, RESTART_WIDTH: 36, RESTART_HEIGHT: 32 }; function GameOverPanel(canvas, textImgPos, restartImgPos, dimensions) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.canvasDimensions = dimensions; this.textImgPos = textImgPos; this.restartImgPos = restartImgPos; this.draw(); } GameOverPanel.prototype = { /** * Update the panel dimensions. * @param {number} width New canvas width. * @param {number} opt_height Optional new canvas height. */ updateDimensions: function(width, opt_height) { this.canvasDimensions.WIDTH = width; if (opt_height) { this.canvasDimensions.HEIGHT = opt_height; } }, /** * Draw the panel. */ draw: function() { var dimensions = GameOverPanel.dimensions; var centerX = this.canvasDimensions.WIDTH / 2; // Game over text. var textSourceX = dimensions.TEXT_X; var textSourceY = dimensions.TEXT_Y; var textSourceWidth = dimensions.TEXT_WIDTH; var textSourceHeight = dimensions.TEXT_HEIGHT; var textTargetX = Math.round(centerX - (dimensions.TEXT_WIDTH / 2)); var textTargetY = Math.round((this.canvasDimensions.HEIGHT - 25) / 3); var textTargetWidth = dimensions.TEXT_WIDTH; var textTargetHeight = dimensions.TEXT_HEIGHT; var restartSourceWidth = dimensions.RESTART_WIDTH; var restartSourceHeight = dimensions.RESTART_HEIGHT; var restartTargetX = centerX - (dimensions.RESTART_WIDTH / 2); var restartTargetY = this.canvasDimensions.HEIGHT / 2; textSourceX += this.textImgPos.x; textSourceY += this.textImgPos.y; // Game over text from sprite. this.ctx.drawImage(imgSprite, textSourceX, textSourceY, textSourceWidth, textSourceHeight, textTargetX, textTargetY, textTargetWidth, textTargetHeight); // Restart button. this.ctx.drawImage(imgSprite, this.restartImgPos.x, this.restartImgPos.y, restartSourceWidth, restartSourceHeight, restartTargetX, restartTargetY, dimensions.RESTART_WIDTH, dimensions.RESTART_HEIGHT); } }; //地面 function HorizonLine(canvas, spritePos) { this.spritePos = spritePos; this.canvas = canvas; this.ctx = canvas.getContext("2d"); this.sourceDimensions = {}; this.dimensions = HorizonLine.dimensions; this.sourceXPos = [this.spritePos.x, this.spritePos.x + this.dimensions.WIDTH]; this.xPos = []; this.yPos = 0; this.bumpThreshold = 0.5; //地形系数 this.setSourceDimesions(); this.draw(); } HorizonLine.dimensions = { WIDTH: 600, //宽600 HEIGHT: 12, //高12像素 YPOS: 127 //在画布中的位置 }; HorizonLine.prototype = { setSourceDimesions: function() { for (var dimension in HorizonLine.dimensions) { this.sourceDimensions[dimension] = HorizonLine.dimensions[dimension]; this.dimensions[dimension] = HorizonLine.dimensions[dimension]; } //地面在画布上的位置 this.xPos = [0, HorizonLine.dimensions.WIDTH]; //0,600 this.yPos = HorizonLine.dimensions.YPOS; }, //随机地形 getRandomType: function() { return Math.random() > this.bumpThreshold ? this.dimensions.WIDTH : 0; }, draw: function() { this.ctx.drawImage(imgSprite, this.sourceXPos[0], this.spritePos.y, this.sourceDimensions.WIDTH, this.sourceDimensions.HEIGHT, this.xPos[0], this.yPos, this.dimensions.WIDTH, this.dimensions.HEIGHT); this.ctx.drawImage(imgSprite, this.sourceXPos[1], this.spritePos.y, this.sourceDimensions.WIDTH, this.sourceDimensions.HEIGHT, this.xPos[1], this.yPos, this.dimensions.WIDTH, this.dimensions.HEIGHT); }, updateXPos: function(pos, increment) { var line1 = pos, line2 = pos === 0 ? 1 : 0; this.xPos[line1] -= increment; this.xPos[line2] = this.xPos[line1] + this.dimensions.WIDTH; if (this.xPos[line1] <= -this.dimensions.WIDTH) { this.xPos[line1] += this.dimensions.WIDTH * 2; this.xPos[line2] = this.xPos[line1] - this.dimensions.WIDTH; this.sourceXPos[line1] = this.getRandomType() + this.spritePos.x; } }, update: function(deltaTime, speed) { var increment = Math.floor(speed * (FPS / 1000) * deltaTime); if (this.xPos[0] <= 0) { this.updateXPos(0, increment); } else { this.updateXPos(1, increment); } this.draw(); }, reset: function() { this.xPos[0] = 0; this.xPos[1] = HorizonLine.dimensions.WIDTH; } }; //云 Cloud.config = { HEIGHT: 14, MAX_CLOUD_GAP: 400, MAX_SKY_LEVEL: 30, MIN_CLOUD_GAP: 100, MIN_SKY_LEVEL: 71, WIDTH: 46 }; function getRandomNum(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function getTimeStamp() { return performance.now(); } function Cloud(canvas, spritePos, containerWidth) { this.canvas = canvas; this.ctx = canvas.getContext("2d"); this.spritePos = spritePos; this.containerWidth = containerWidth; this.xPos = containerWidth; this.yPos = 0; this.remove = false; //云间隙 this.cloudGap = getRandomNum(Cloud.config.MIN_CLOUD_GAP, Cloud.config.MAX_CLOUD_GAP); this.init(); } Cloud.prototype = { init: function() { //云的高度随机 this.yPos = getRandomNum(Cloud.config.MAX_SKY_LEVEL, Cloud.config.MIN_SKY_LEVEL); this.draw(); }, draw: function() { this.ctx.save(); var sourceWidth = Cloud.config.WIDTH, sourceHeight = Cloud.config.HEIGHT; this.ctx.drawImage(imgSprite, this.spritePos.x, this.spritePos.y, sourceWidth, sourceHeight, this.xPos, this.yPos, sourceWidth, sourceHeight); this.ctx.restore(); }, update: function(speed) { if (!this.remove) { //向左移动 this.xPos -= Math.ceil(speed); this.draw(); if (!this.isVisible()) { this.remove = true; } } }, //判断是否移出屏幕外 isVisible: function() { return this.xPos + Cloud.config.WIDTH > 0; } }; //夜晚 //todo NightMode.config = { FADE_SPEED: 0.035, //淡入淡出速度 HEIGHT: 40, //月亮高度 MOON_SPEED: 0.25, //月亮移动速度 NUM_STARS: 2, //星星数量 STAR_SIZE: 9, //星星宽度 STAR_SPEED: 0.3, //星星速度 STAR_MAX_Y: 70, //星星在画布上出现的位置 WIDTH: 20 //半个月度宽度 }; NightMode.phases = [140, 120, 100, 60, 40, 20, 0]; function NightMode(canvas, spritePos, containerWidth) { this.spritePos = spritePos; this.canvas = canvas; this.ctx = canvas.getContext("2d"); this.containerWidth = containerWidth; this.xPos = containerWidth - 50; //月亮的x坐标 this.yPos = 30; //月亮的y坐标 this.currentPhase = 0; this.opacity = 0; this.stars = []; //用于存储星星 this.drawStars = false; this.placeStars(); //放置星星 } NightMode.prototype = { update: function(activated) { if (activated && this.opacity == 0) { this.currentPhase++; if (this.currentPhase >= NightMode.phases.length) { this.currentPhase = 0; } } //淡入淡出 if (activated && (this.opacity < 1 || this.opacity == 0)) { this.opacity += NightMode.config.FADE_SPEED; } else if (this.opacity > 0) { this.opacity -= NightMode.config.FADE_SPEED; } //移动月亮 if (this.opacity > 0) { this.xPos = this.updateXPos(this.xPos, NightMode.config.MOON_SPEED); //移动星星 if (this.drawStars) { for (var i = 0; i < NightMode.config.NUM_STARS; i++) { this.stars[i].x = this.updateXPos(this.stars[i].x, NightMode.config.STAR_SPEED); } } this.draw(); } else { this.opacity = 0; this.placeStars(); } this.drawStars = true; }, updateXPos: function(currentPos, speed) { if (currentPos < -NightMode.config.WIDTH) { currentPos = this.containerWidth; } else { currentPos -= speed; } return currentPos; }, draw: function() { var moonSourceWidth = this.currentPhase == 3 ? NightMode.config.WIDTH * 2 : NightMode.config.WIDTH; var moonSourceHeight = NightMode.config.HEIGHT; var moonSourceX = this.spritePos.x + NightMode.phases[this.currentPhase]; var moonOutputWidth = moonSourceWidth; var starSize = NightMode.config.STAR_SIZE; var starSourceX = spriteDefinition.STAR.x; this.ctx.save(); this.ctx.globalAlpha = this.opacity; if (this.drawStars) { for (var i = 0; i < NightMode.config.NUM_STARS; i++) { this.ctx.drawImage(imgSprite, starSourceX, this.stars[i].sourceY, starSize, starSize, Math.round(this.stars[i].x), this.stars[i].y, NightMode.config.STAR_SIZE, NightMode.config.STAR_SIZE); } } this.ctx.drawImage(imgSprite, moonSourceX, this.spritePos.y, moonSourceWidth, moonSourceHeight, Math.round(this.xPos), this.yPos, moonOutputWidth, NightMode.config.HEIGHT); this.ctx.globalAlpha = 1; this.ctx.restore(); }, placeStars: function() { var segmentSize = Math.round(this.containerWidth / NightMode.config.NUM_STARS); for (var i = 0; i < NightMode.config.NUM_STARS; i++) { this.stars[i] = {}; this.stars[i].x = getRandomNum(segmentSize * i, segmentSize * (i + 1)); this.stars[i].y = getRandomNum(0, NightMode.config.STAR_MAX_Y); this.stars[i].sourceY = spriteDefinition.STAR.y + NightMode.config.STAR_SIZE * i; } }, r.........完整代码请登录后点击上方下载按钮下载查看
网友评论0