在webview中,javascript计时器在android上运行得太快了

时间:2014-02-21 02:11:06

标签: javascript android html5 webview

编辑:我找到了解决方案。见下面的答案

<小时/> 我用html5写了一个游戏。我使用setTimeout(func,1000 / FPS)运行游戏。然后我回想起超时,从而制作一个循环。 (FPS设置为30)。在我的Android手机上,一切都运行得很好,但是当我把它放到Android上的webview中时,计时器的运行速度比浏览器中的速度快了10倍。我该如何解决这个/为什么会发生这种情况?谢谢!

<html>
<head>
<title>...</title>

<style>
...
</style>

</head>
<body style="-webkit-user-select:none; cursor:default; margin:0px; padding:0px; overflow:hidden; position : fixed;">
<script>
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width  = 480;
canvas.height = 800;
canvas.style.width = window.innerWidth;
canvas.style.height = window.innerHeight;
canvas.style.float = "left";

//canvas.style.transform = "translate3d(0,0,0)";
document.body.appendChild(canvas);

var started = 0;
var vy = 0;

var startImage = new Image();
startImage.src = "img/start.png";
startImage.onload = function(){
    ctx.drawImage(startImage,0,0);
    //touchstart
    addEventListener("touchstart",function(e) {
        if(started == 0){
            loadGame();
            started = 1;
        }else{
            vy = -15;
        }
    },false);
};
var bgImage;
function loadGame(){
    bgImage = new Image();
    bgImage.src = "img/background.png";
    bgImage.onload = function(){
        loadPlayer();
    };
}

var player;
var playerX = 64;
var playerY = 0;
var playerHeight = 60;
var playerWidth = 76;

var stopTime = false;
var stopFall = false;

function loadPlayer(){
    player = new Image();
    player.src = "img/hero.png";
    player.onload = function() {
        loadwalls();
    };
}

var walls;
function loadwalls(){
    wall = new Image();
    wall.src = "img/wall.png";
    wall.onload = function() {
        loadGameover();
    };
}

var gameO;
function loadGameover(){
    gameO = new Image();
    gameO.src = "img/gameover.png";
    gameO.onload = function() {
        init();
    };
}

var walls = [];

function draw(){
    canvas.width = 480;
    canvas.height = 800;
    ctx.drawImage(bgImage,0,0);
    ctx.drawImage(player,playerX,playerY);
    for(var i=0;i<walls.length;i++){
        if(walls[i][0] > -200){
            ctx.drawImage(wall,walls[i][0],walls[i][1]);
            ctx.drawImage(wall,walls[i][0],walls[i][1]-839-3.25*playerHeight);
            walls[i][0] -= 4;
            if((walls[i][1] < 785 || vy < 0) && (walls[i][1] > 15 || vy > 0)){
                walls[i][1] += vy;
            }
            if(vy < 10){
            vy += 2;
            }
        }
        if(playerX > walls[i][0]+128-playerWidth && walls[i][2] == 0){
            walls[i][2] = 1;
            score += 1;
        }
        if(playerX < walls[i][0]+128 && playerX > walls[i][0]-playerWidth){
            if(playerY < walls[i][1]-3.25*playerHeight-5 || playerY > walls[i][1]-playerHeight+5){
                gameOver();
            }
        }
    }
}

function drawFall(){
    canvas.width = 480;
    canvas.height = 800;
    ctx.drawImage(bgImage,0,0);

    for(var i=0;i<walls.length;i++){
            ctx.drawImage(wall,walls[i][0],walls[i][1]);
            ctx.drawImage(wall,walls[i][0],walls[i][1]-839-3.25*playerHeight);
    }
    ctx.scale(1, -1);
    ctx.drawImage(player,playerX,-playerY-playerHeight);
    ctx.scale(1, -1);    
var score = 0;

var highscore = 0;
var state = window.localStorage.getItem("...."); 
if (state) { 
    highscore = parseInt(state); 
}

var FPS = 30;

function init(){
    var time = 0;
    var wallTime = 0;
    stopTime = false;
    stopFall = false;
    setTimeout(function (){
        if(started == 1){
        playerY = playerHeight/2*Math.sin(time)+canvas.width/2+playerHeight;
        draw();
        time+=0.1;
        wallTime += 0.1;
        if(time > Math.PI*2){
            time = 0;
        }
        if(wallTime >= 10){
            walls.push([480,Math.random()*(800-3.25*playerHeight*2)+5*playerHeight,0]);
            wallTime = 0;
        }
        }
        if(!stopTime){
            setTimeout(arguments.callee, 1000/FPS);
        }
    },1000/FPS);
    setTimeout(function(){
        var advert=document.getElementById("ad");
        advert.style.top = "0";
    },1000);
    document.getElementById('iad').src += '';
}

function gameOver(){
    stopTime = true;
    var fallSpeed = 5;
    var fall = setTimeout(function(){
        playerY+=fallSpeed;
        fallSpeed += 1;
        playerX+=5;
        drawFall();
        if(playerY>800+50){
            stopFall = true;
            canvas.width = 480;
        canvas.height = 800;
        canvas.style.width = window.innerWidth;
    canvas.style.height = window.innerHeight;
        ctx.drawImage(gameO,0,0);
        walls = [];
        if(score > highscore){
            window.localStorage.setItem(".....", ""+score);
            highscore = score;
        }
        score = 0;
        vy = 0;
        playerX = 64;
        playerY = 0;
        started = 0;
        var advert=document.getElementById("ad");
        advert.style.top = ""+parseInt(canvas.style.height);
        }
        if(!stopFall){
            setTimeout(arguments.callee, 1000/FPS);
        }
    },1000/FPS);
}
</script>
<div id="ad" style="height:200px; overflow:hidden; position:absolute; top:-200;left:0;"><iframe src="ads/ad.html" scrolling="no" frameBorder="0" id="iad" onload="this.width = window.innerWidth;" height="200"></iframe></div>
</body>
</html>

1 个答案:

答案 0 :(得分:1)

出于某种原因,requestAnimationFrame()在Android上运行正常,但setTimeout()的运行速度比预期的要快。对于有此问题的其他人,并且因为requestAnimationFrame()比设置间隔/超时更准确和有效,只需替换所有

setTimeout(func,1000/FPS);

//it will (try to) run at a constant 60 FPS
requestAnimationFrame(func);