iT邦幫忙

0

使用Javascript控制Canvas座標問題

大家好,最近正在練習HTML5
使用CANVAS畫布做克隆賽車遊戲的動畫
流程: 倒數10秒後,3部車子會開跑,每次前進跟後退的距離不一定,
比賽後10秒會到達終點並排名名次。

但是一直卡在開跑後的問題,我是直接改變其X座標的方式讓他前進後退,
寫了3個FUNCTION(move、move2、car1)都是會直接瞬移@@...
沒辦法像動畫那樣一格一格前進,嘗試使用for迴圈return給他
還是會瞬移(我用console.log去看他return的結果是沒錯?座標+1+1+1或座標-1
懇請前輩提點 謝謝

以下擷取部分程式碼:


<script>
function loadImage(scrList, runImg) {
		var obj = new Object(); 
		for (var i = 0; i < scrList.length; i++) {
			var img = obj[scrList[i].id] = new Image(); 
			img.onload = function() {
				runImg(); 
			}
		}
		img.src = scrList[i].url; 
		return obj; 
	
	}
	var imgs;
	var context;
	
	
	function init() {
		var game = document.getElementById("elem");
	
		game.width = 1920;
		game.height = 520;
		document.body.appendChild(game);
		context = game.getContext("2d");
		
		var arr = [
		
		
		{
			id: "car1",
			url: "car1.png"},	
		{
			id: "car2",
			url: "car2.png"},	
		
		{
			id: "car3",
			url: "car3.png"},	
		
		
			
		]
		
		
		imgs = loadImage(arr, runImg);
		
	}
	
	

	function runImg() {
		
		context.drawImage(imgs.car1, car1(), 5,160,44);
		context.drawImage(imgs.car2, move(1745), 50,164,44);
		context.drawImage(imgs.car3, move2(1737), 95,170,47);
			
		var timeTick;
		function tick(){
			clearTimeout(timeTick);
			timeTick= setTimeout(runImg,100);		
		}
		tick();
	}
	
	

	function move(number){
	
		
		var aaa;
		if( number >= 1500){aaa = Math.floor(Math.random()*2000)+300;}
		aaa = Math.floor(Math.random()*2000)+300;
		
		if( number < 1500){aaa=Math.floor(Math.random()*200)+100;}
		if( number < 300 ){aaa =Math.floor(Math.random()*50)+50;}
		var i=0;
		while(i<aaa){
			number =number-1;
			i++;
		}
		
		return number;
		
	}
	
	function move2(number){
		var i;
		for(i=0;i<1500;i++){
			number-=1;
		return number;

		}
	}
	
	function car1(){
		var car1Left=1760;
		var fast1=100;
		
		for(var i=0;i<fast1/2;i++){
			car1Left=car1Left+10;
			return car1Left;
		}
	
	}
</script>

TWLuke iT邦新手 4 級 ‧ 2018-08-15 11:22:54 檢舉
"但就是不知為何會瞬移"
因為 您的電腦等級太好了,
您去換一個 奔騰III(Pentium III) CPU
試試看看 會不會瞬移了


您每次移動 停個 0.5秒 試試看
fillano iT邦超人 1 級 ‧ 2018-08-16 14:37:29 檢舉
補充參考:
https://developer.mozilla.org/zh-TW/docs/Web/API/Window.requestAnimationFrame

setTimeout的時間不精確,效能也比較差。如果移動的距離跟時間是已知的,建議改用requestAnimationFrame來做。
1
shijung
iT邦新手 5 級 ‧ 2018-08-16 12:01:21
最佳解答

setTimeout 執行一次 結束 可用遞迴方式重複執行
setInterval 每隔幾毫秒執行一次
照你原本的改寫

<!DOCTYPE html>
<html>
<body>
<canvas id="elem" width="500" height="350" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<p><button onclick="init()">比賽開始</button></p>
<script>   
    function loadImage(scrList) {
		var obj = new Object(); 
		for (var i = 0; i < scrList.length; i++) {
			var img = obj[scrList[i].id] = new Image(); 
            img.src = scrList[i].url; 			
		}		
		return obj; 	
	}
	var imgs;
	var context;
	
	
	function init() {
		var game = document.getElementById("elem");	
		game.width = 1920;
		game.height = 520;
		document.body.appendChild(game);
		context = game.getContext("2d");
		
		var arr = [				
		{
			id: "car1",
			url: "C1.png"},	
		{
			id: "car2",
			url: "C2.png"},	
		
		{
			id: "car3",
			url: "C3.png"},								
		]
				
		imgs = loadImage(arr);
        
		runImg();
	}
	
	var car1Left =0;
    var seconds =100;
    var number = 0;
    var numbers = 0;
	function runImg() {
        var c = document.getElementById("elem");	
		context.clearRect(0, 0, c.width, c.height);      
		context.drawImage(imgs.car1, car1(), 5,160,100);
		context.drawImage(imgs.car2, move(1746), 50,160,100);
		context.drawImage(imgs.car3, move2(), 95,160,100);       
		var timeTick;
		function tick(){
            
			clearTimeout(timeTick);
			if(seconds>0){
                timeTick= setTimeout(runImg,100);		
            }
            else{
                var c = document.getElementById("elem");	
                context.clearRect(0, 0, c.width, c.height);      
                context.drawImage(imgs.car1, 1395, 5,160,100);
                context.drawImage(imgs.car2, 1395, 50,160,100);
                context.drawImage(imgs.car3, 1395, 95,160,100);

            }
		}
		tick();
        seconds--;
	}		
	function move(number){			
		var aaa;
		if( number >= 1500){aaa = Math.floor(Math.random()*2000)+300;}
		aaa = Math.floor(Math.random()*2000)+300;		
		if( number < 1500){aaa=Math.floor(Math.random()*200)+100;}
		if( number < 300 ){aaa =Math.floor(Math.random()*50)+50;}
		var i=0;
		while(i<aaa){
			number =number-1;
			i++;
		}
		
		return number;
		
	}	
	function move2(){
        var dir = Math.floor(Math.random()*40)%2;//0 or 1  前進或後退
        if(dir==0)
		    numbers+=(Math.floor(Math.random()*50));
        else if(Math.floor(Math.random()*40)%2 ==0)
            numbers+=(Math.floor(Math.random()*50));
        else
            numbers-=(Math.floor(Math.random()*40));
		return numbers;
        //給x座標值		
	}
	
	function car1(){				
		car1Left=car1Left+15;
		return car1Left;		
	}
</script>
</body>
</html>

另外setInterval 車子隨機跑到終點線判斷誰第一第二第三

<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="500" height="350" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<p><button onclick="run()">比賽開始</button></p>
<script>
    var win = new Image(50,50);    
    win.src = 'win.png';
    var second = new Image(50,50);    
    second.src = 'second.png';
    var third = new Image(50,50);    
    third.src = 'third.png';
    var carimg = new Image(100,100);    
    carimg.src = 'C1.png';
    var y = document.getElementById("myCanvas").height-(carimg.height);   
    var x = 0;
    var carimg2 = new Image(100,100);    
    carimg2.src = 'C2.png';    
    var y2 = document.getElementById("myCanvas").height-(carimg2.height*2);   
    var x2 = 0;
    var carimg3 = new Image(100,100);    
    carimg3.src = 'C3.png';    
    var y3 = document.getElementById("myCanvas").height-(carimg3.height*3);   
    var x3 = 0;
    //終點線
    var endline = document.getElementById("myCanvas").width-carimg.width;
    function myCanvas() {
        var c = document.getElementById("myCanvas");
        var ctx = c.getContext("2d");  
        ctx.clearRect(0, 0, c.width, c.height);      
        ctx.drawImage(carimg,x,y,100,100);
        ctx.drawImage(carimg2,x2,y2,100,100);
        ctx.drawImage(carimg3,x3,y3,100,100);
        if(list[0]!=null){
            ctx.drawImage(win,endline+25,list[0]-25,50,50);
        }
        if(list[1]!=null){
            ctx.drawImage(second,endline+25,list[1]-25,50,50);
        }
        if(list[2]!=null){
            ctx.drawImage(third,endline+25,list[2]-25,50,50);
        }
    }
    var list = [null,null,null];
    window.onload  = function(){
        myCanvas();
    }
    var timerun;    
    function run(){
        //timerun= setInterval(runcar , 33);//每五百毫秒車子設定會移動到哪個Y

       
		clearTimeout(timerun);
		timerun= setTimeout(runcar,33);		
		
		
        //人眼能识别的最低帧数是24帧/秒 1000/30 == 33
    }
    function runcar(){
        var c = document.getElementById("myCanvas");
        var ctx = c.getContext("2d");  
        if(x<endline){
            //向右走
            x+=randommove();
            if(x>endline || x==endline){
                //第一台到終點                
                x=endline;    
                reachline(y);           
            }
        }
        if(x2<endline){
            x2+=randommove(); 
            if(x2>endline || x2==endline){
                //第二台到終點
                x2=endline;
                reachline(y2);
            }
        }
        if(x3<endline){
            x3+=randommove();  
            if(x3>endline || x3==endline){
                //第三台到終點
                x3=endline;
                reachline(y3);
            }
        }
        myCanvas();//畫出座標
        if(x ==endline && x2 == endline && x3 ==endline){
                clearInterval(timerun);
        }   
        run();             
    }
    function reachline(y){
        if(list[0]==null){
            list[0]=y;
        }else if (list[1]==null){
            list[1]=y;
        }else if(list[2]==null){
            list[2]=y;
        }
    }
    function randommove(){
        return Math.floor(Math.random()*36)+1;
    }
</script>
</body>
</html>

使用setInterval方法 您看看

<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="500" height="350" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<p><button onclick="run()">比賽開始</button></p>
<script>
    var win = new Image(50,50);    
    win.src = 'win.png';
    var second = new Image(50,50);    
    second.src = 'second.png';
    var third = new Image(50,50);    
    third.src = 'third.png';
    var carimg = new Image(100,100);    
    carimg.src = 'C1.png';
    var y = document.getElementById("myCanvas").height-(carimg.height);   
    var x = 0;
    var carimg2 = new Image(100,100);    
    carimg2.src = 'C2.png';    
    var y2 = document.getElementById("myCanvas").height-(carimg2.height*2);   
    var x2 = 0;
    var carimg3 = new Image(100,100);    
    carimg3.src = 'C3.png';    
    var y3 = document.getElementById("myCanvas").height-(carimg3.height*3);   
    var x3 = 0;
    //終點線
    var endline = document.getElementById("myCanvas").width-carimg.width;
    function myCanvas() {
        var c = document.getElementById("myCanvas");
        var ctx = c.getContext("2d");  
        ctx.clearRect(0, 0, c.width, c.height);      
        ctx.drawImage(carimg,x,y,100,100);
        ctx.drawImage(carimg2,x2,y2,100,100);
        ctx.drawImage(carimg3,x3,y3,100,100);
        if(list[0]!=null){
            ctx.drawImage(win,endline+25,list[0]-25,50,50);
        }
        if(list[1]!=null){
            ctx.drawImage(second,endline+25,list[1]-25,50,50);
        }
        if(list[2]!=null){
            ctx.drawImage(third,endline+25,list[2]-25,50,50);
        }
    }
    var list = [null,null,null];
    window.onload  = function(){
        myCanvas();
    }
    var timerun;    
    function run(){
        timerun= setInterval(runcar , 33);//每五百毫秒車子設定會移動到哪個Y
        //人眼能识别的最低帧数是24帧/秒 1000/30 == 33
    }
    
    function runcar(){
        var c = document.getElementById("myCanvas");
        var ctx = c.getContext("2d");  
        if(x<endline){
            //向右走
            x+=randommove();
            if(x>endline || x==endline){
                //第一台到終點                
                x=endline;    
                reachline(y);           
            }
        }
        if(x2<endline){
            x2+=randommove(); 
            if(x2>endline || x2==endline){
                //第二台到終點
                x2=endline;
                reachline(y2);
            }
        }
        if(x3<endline){
            x3+=randommove();  
            if(x3>endline || x3==endline){
                //第三台到終點
                x3=endline;
                reachline(y3);
            }
        }
        myCanvas();//畫出座標
        if(x ==endline && x2 == endline && x3 ==endline){
                clearInterval(timerun);
        }                
    }
    function reachline(y){
        if(list[0]==null){
            list[0]=y;
        }else if (list[1]==null){
            list[1]=y;
        }else if(list[2]==null){
            list[2]=y;
        }
    }
    function randommove(){
        return Math.floor(Math.random()*36)+1;
    }
</script>

</body>
</html>
shijung iT邦新手 5 級 ‧ 2018-08-16 12:01:53 檢舉

記得更改圖片

謝謝大大用心的回覆/images/emoticon/emoticon12.gif
正在消化您的代碼中~很謝謝您!!

1
Homura
iT邦研究生 5 級 ‧ 2018-08-15 10:54:16

你的for迴圈要加入延遲啊...
不然瞬間就跑完了
當然會順移...

0
joneshong
iT邦新手 5 級 ‧ 2018-08-18 12:14:51

像橘色方塊這樣嗎?
Yes

比較類似像這種賽馬遊戲
https://www.youtube.com/watch?v=ba-gCTKkmwg

我要發表回答

立即登入回答