Menu

Animation Canvas interactive [Résolu]

- - Dernière réponse :  magit - 24 avril 2019 à 23:03
Bonjour à tous,
je veux déplacer un carré dessiné sur un canvas avec .rect et je ne comprends pas pourquoi il n'efface pas l'ancien mais l'ajoute.
Un HTML basique:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>test jeu action</title>
<style type="text/css" rel="stylesheet" >
body{margin:0;padding:0;background-color:#000;overflow:hidden;}
</style>
</head>
<body>
<script>/* voir script JS qui suit pour plus de clarté */
</script>

</body>
</html>

et le contenu de la balise script:

/** global fn as tools */
function isReal(v){return v!='undefined' && v!=null ? true:false; }

/** animation loop */
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
//let countloop=0;
function animate(){
//	countloop++;console.log('countloop: '+countloop);
	if(ctrls.input.states.up==true){rc.y-=moveSpeed;}
	if(ctrls.input.states.down==true){rc.y+=moveSpeed;}
	if(ctrls.input.states.left==true){rc.x-=moveSpeed;}
	if(ctrls.input.states.right==true){rc.x+=moveSpeed;}
	cnv.ctx.fillStyle = '#c0ffc0';
	cnv.ctx.clearRect(0, 0, cnv.w, cnv.h);//-- remplis le fond
	drawRect(cnv.ctx, rc.x,rc.y,rc.w,rc.h,'#ff0000', '#0000ff');
	
	
	//if(countloop<10){
	requestAnimationFrame(animate);
	//}else{
	//this.window.cancelAnimationFrame(this);
	//}
}
/** graphic as sketching Canvas 2d */
function addCanvas(id,ancestor,w,h){
	let c=document.createElement('canvas');
	c.setAttribute('WIDTH', w);
	c.setAttribute('HEIGHT', h);
	ancestor.appendChild(c);
	return {tag:c, ctx:c.getContext('2d'), w:w, h:h};//-- suppose that CANVAS and CanvasRendere2d are supported in running script environment//
}

function drawRect(ctx,x, y, w, h, stk='#ffffff', fll='#ffffff'){//-- set stk or fll to false(or null) to set drawing options
	if(typeof ctx== typeof document.createElement('canvas').getContext('2d')){
		ctx.rect(x,y,w,h);
		if(isReal(stk) && stk!=false){
			ctx.strokeStyle=stk;
			ctx.stroke();
			console.log('drawRect stroke '+x+','+y+','+w+','+h+' '+stk);
		}
		if(isReal(fll) && fll!=false){
			ctx.fillStyle=fll;
			ctx.fill();
			console.log('drawRect fill '+x+','+y+','+w+','+h+' '+fll);

		}
		
		return ctx;
	}
	console.log('WRONG Drawing Context: '+ctx+' must be CanvasRenderer2D');
	return;
}


let cnv=addCanvas('cnv',document.body, window.innerWidth,window.innerHeight );
console.log('window canvas size: '+cnv.w+'X'+cnv.h);
function testItem(){let tmp=Math.round(cnv.w/50);return {w:tmp, h:tmp, x:tmp,y:tmp}}
let rc=testItem();
console.log('('+rc.x+' '+rc.y+')');


/** INPUTs MANAGEMENT : Controls (keyboard) */
function Controls(id){
return{
	id:id,
	input:{
		states:{},
		keys:{
			up:38,
			down:40,
			right:39,
			left:37
			}
		}
	}
}

let moveSpeed=2;
let ctrls = Controls('controler');
document.addEventListener('keydown', function(e){
	switch(e.keyCode){
		case ctrls.input.keys.up:
			ctrls.input.states['up']=true;
		break;
		case ctrls.input.keys.right:
			ctrls.input.states['right']=true;
		break;
		case ctrls.input.keys.down:
			ctrls.input.states['down']=true;
		break;
		case ctrls.input.keys.left:
			ctrls.input.states['left']=true;
		break;
		default:/* no assigned control, do nothing*/;
		break;
	}
	console.log('states\n up:'+ctrls.input.states.up+'\t right:'+ctrls.input.states.right+'\t down:'+ctrls.input.states.down+'\t left:'+ctrls.input.states.left);
});
document.addEventListener('keyup', function(e){
	switch(e.keyCode){
		case ctrls.input.keys.up:if(isReal(ctrls.input.states['up'])){ctrls.input.states.up=false;}
		break;
		case ctrls.input.keys.right:if(isReal(ctrls.input.states['right'])){ctrls.input.states.right=false;}
		break;
		case ctrls.input.keys.down:if(isReal(ctrls.input.states['down'])){ctrls.input.states.down=false;}
		break;
		case ctrls.input.keys.left:if(isReal(ctrls.input.states['left'])){ctrls.input.states.left=false;}
		break;

		default:;break;
	}
});

let anim=animate();



Il y a bien un déplacement mais l'ancien 'dessin' ne s'efface pas.
C'est probablement trivial mais là je bloque.
Merci de vos réponses.

Configuration: Windows / Firefox 66.0
Afficher la suite 

Votre réponse

3 réponses

0
Merci
Personne à une idée? Mon code est pas beau ni optimisé car c'est juste un test pour quelques choses qui sera plus structuré...on peut voir pour les quelques objets que pas tout est rempli ou utilisé.
J'ai testé avec .beginPath() .closePath() autour du dessin ça change bien quelque chose mais pas ce qu'il faut. Le soucis à l'air de venir de la fonction pour recouvrir/rendre le canvas vierge .clearRect(...) pourtant j'ai suivit à la lettre un exemple. C'est bien mon code, commentaires en anglais car c'est plus rapide à écrire assez souvent.
Help si quelqu'un s'y connait en Canvas
Commenter la réponse de magit
Messages postés
88
Date d'inscription
mardi 21 août 2018
Statut
Membre
Dernière intervention
22 mai 2019
18
0
Merci
Salut, tu avais oublié le
cnv.ctx.beginPath();
et le
cnv.ctx.fill();
.

function animate(){
 if(ctrls.input.states.up==true){rc.y-=moveSpeed;}
 if(ctrls.input.states.down==true){rc.y+=moveSpeed;}
 if(ctrls.input.states.left==true){rc.x-=moveSpeed;}
 if(ctrls.input.states.right==true){rc.x+=moveSpeed;}
    cnv.ctx.beginPath();//C'est ici que ta oublié
 cnv.ctx.fillStyle = '#c0ffc0'; 
 cnv.ctx.clearRect(0, 0, cnv.w, cnv.h);
    cnv.ctx.fill();//Et là 
 drawRect(cnv.ctx, rc.x,rc.y,rc.w,rc.h,'#ff0000', '#0000ff');
 requestAnimationFrame(animate);
}
ok merci j'ai finit pas trouver tout seul :)
En fait il manque le beginPath() closePath() dans ma function drawRect qui utilise .rect() mais .clearRect() n'a pas besoin de .fill() et ne supporte pas .fillStyle non plus
voir ici : https://www.w3schools.com/TAgs/canvas_clearrect.asp
merci ; résolu
Commenter la réponse de SioGabx
0
Merci
ça prends forme :p

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>test shoot'em up (old school)</title>
<style type="text/css" rel="stylesheet" >
body{margin:0;padding:0;background-color:#000;overflow:hidden;
}
canvas#cnv{

background-image:url(https://apod.nasa.gov/apod/image/1410/ngc7331fieldAeW.jpg);
background-size:auto;
background-color:rgba(0,0,0,0.5);

}
</style>
</head>
<body>
<script>
/** global fn as tools */
document.body.onLoad=function(){//-- preloader only !!
	preloadImages('https://apod.nasa.gov/apod/image/1410/ngc7331fieldAeW.jpg');//-- ouais bof faudrait placer dans head, et forcément utiliser fichier externe .JS
}
function preloadImages(){//-- from functional.CURRENT_VERSION.js//
	if(document.images){
		let tabimages=new Array();
		for(let i= 0;i<preloadImages.arguments;i++){
			tabimages[i]=new Image();
			tabimages[i].src=preload.arguments[i];
			console.log(i+' preloaded ',tabimages[i].src);
		}
		return tabimages;
	}
}

function isReal(v){return v!='undefined' && v!=null ? true:false; }
function randomInt(max,min=0){return Math.floor(Math.random()*(max))+min;}

/** animation loop */
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
let listStar=[];
let listPlayerShoot=[],
listEnnemies=[], listEnnemiesShoot=[];

function animate(){
	let thisTime=new Date().getTime();
	console.log('\t --------- delai time: '+(thisTime-lastTime));
	lastTime=thisTime;
	//-- mouvements 
	if(ctrls.input.states.up==true){rc.y-=moveSpeed;}
	if(ctrls.input.states.down==true){rc.y+=moveSpeed;}
	if(ctrls.input.states.left==true){rc.x-=moveSpeed;}
	if(ctrls.input.states.right==true){rc.x+=moveSpeed;}
	//-- tir (ajouter un tir)
	if(ctrls.input.states.shoot==true){
		listPlayerShoot.push(shootItem(rc.x+(rc.w), rc.y+(rc.h/2)));
		ctrls.input.states.shoot = false;
		addPlaySound('shootsound' , 'beep-08b.mp3');
	}
	cnv.ctx.save();
	cnv.ctx.fillStyle = '#c0ffc0';
	cnv.ctx.clearRect( 0 , 0 , cnv.w , cnv.h );//-- remplis le fond
	//-- draw le starfield
	for(let i=0;i<listStar.length;i++){	//function drawCircle(ctx,x,y,r,stk='#ffffff',fill='#ffffff')
		drawCircle( cnv.ctx , listStar[i].x , listStar[i].y , listStar[i].r );
		listStar[i].x-=starSpeed();
		if(listStar[i].x<0){listStar[i].x=window.innerWidth;		}
		listStar[i].y+=Math.sin(listStar[i].x)*Math.sin(listStar[i].x);
		if(listStar[i].y>window.innerHeight){listStar[i].y=0;		}
	}
	
	drawRect(cnv.ctx, rc.x,rc.y,rc.w,rc.h,'#ff0000', '#0000ff');//-- draw le spaceship
	
	//-- draw player shoot
	if(listPlayerShoot.length>0){
		for(let i = 0; i<listPlayerShoot.length;i++){
			if(listPlayerShoot[i]!=null){
			drawRect(cnv.ctx, listPlayerShoot[i].x, listPlayerShoot[i].y, listPlayerShoot[i].w, listPlayerShoot[i].h, '#ffffff', '#ffcc00');
			listPlayerShoot[i].x+=18;
			if(listPlayerShoot[i].y>window.innerWidth){
				listPlayerShoot[i]=null;
				}
			}
		}
		//-- trim the Array
		let tmp=[];
		for(let i=0;i<listPlayerShoot.length;i++){
			if(listPlayerShoot[i]!=null){
				tmp.push(listPlayerShoot[i]);
				}
		}
		listPlayerShoot=tmp;
	}
	cnv.ctx.restore();
	console.log('duration: '+((lastTime-startTime)/1000)+'s');
	thisAnim = requestAnimationFrame(animate);
}
/** 
add and play a sound (mp3/mpeg only)
*/
function addSound(id, target, src){
	let s = document.createElement('audio');
	s.id=id;
	let sr=document.createElement('source');
	sr.setAttribute('type', 'audio/mpeg');
	sr.src=src;
	s.appendChild(sr);
	s.autoplay=true;
	target.appendChild(s);
	return s;
}
function addPlaySound( id, src ){
	if(!document.getElementById('playsound')){
		let soundholder = document.createElement('div');
		soundholder.id='playsound';
		document.body.appendChild(soundholder);
	}
	document.getElementById('playsound').innerHTML='';
	return addSound( id , document.getElementById('playsound') , src );
}
/** graphic as sketching Canvas 2d */
function addCanvas(id,ancestor,w,h){
	let c=document.createElement('canvas');
	c.id=id;
	c.setAttribute('WIDTH', w);
	c.setAttribute('HEIGHT', h);
	ancestor.appendChild(c);
	return { tag:c , ctx:c.getContext('2d') , w:w , h:h };//-- suppose that CANVAS and CanvasRenderer2d are supported in running script environment//
}
function drawRect(ctx,x, y, w, h, stk='#ffffff', fll='#ffffff'){//-- set stk or fll to false(or null) to set drawing options
	if(typeof ctx== typeof document.createElement('canvas').getContext('2d')){
		ctx.beginPath();
		ctx.rect(x,y,w,h);
		if(isReal(stk) && stk!=false){
			ctx.strokeStyle=stk;
			ctx.stroke();
			console.log('drawRect stroke '+x+','+y+','+w+','+h+' '+stk);
		}
		if(isReal(fll) && fll!=false){
			ctx.fillStyle=fll;
			ctx.fill();
			console.log('drawRect fill '+x+','+y+','+w+','+h+' '+fll);

		}
		ctx.closePath();
		return ctx;
	}
	console.log('WRONG Drawing Context: '+ctx+' must be CanvasRenderer2D');
	return;
}
//context.arc(x,y,r,sAngle,eAngle,counterclockwise);
function drawCircle(ctx,x,y,r,stk='rgba(255,100,200,0.8)',fill='rgba(255,100,255,0.6)'){
	ctx.beginPath();
	ctx.arc(x,y,r,0,2*Math.PI);
	if(isReal(fill) && fill!=false){
		ctx.fillStyle=fill;
		ctx.fill();
	}
	if(isReal(stk) && stk!=false){
		ctx.strokeStyle=stk;
		ctx.stroke();
	}
	ctx.closePath();
}
function createStars(count){//-- it's the starfield, see in function animate for the move animation
	for(let i=0;i<count;i++){
		listStar.push(starfieldItem(randomInt(window.innerWidth), randomInt(window.innerHeight), Math.floor( (Math.random()*3)*10 )/10 ));
	}
}

//-------------------------------------------------
createStars(randomInt(10,4));

let cnv=addCanvas('cnv',document.body, window.innerWidth,window.innerHeight );
console.log('window canvas size: '+cnv.w+'X'+cnv.h);
function starfieldItem(x,y,r){return {r:r,x:x,y:y}};
function testItem(){let tmp=Math.round(cnv.w/50);return {w:tmp*2, h:tmp, x:tmp,y:tmp}};
function shootItem(x,y){return{w:8,h:3,x:x,y:y}};
let rc=testItem();//-- replace by a better spaceship image !!!
console.log('('+rc.x+' '+rc.y+')');

/** INPUTs MANAGEMENT : Controls (keyboard) */
function Controls(id){
return{
	id:id,
	input:{
		states:{},
		keys:{
			up:38,
			down:40,
			right:39,
			left:37,
	//		enter:13,
			shoot:32
			}
		}
	}
}
let moveSpeed=2;
let starSpeed=function(){return randomInt(8,4);}
let ctrls = Controls('controler');
document.addEventListener('keydown', function(e){
	//alert(e.keyCode);
	switch(e.keyCode){
		case ctrls.input.keys.up:			ctrls.input.states['up']=true;			break;
		case ctrls.input.keys.right:		ctrls.input.states['right']=true;		break;
		case ctrls.input.keys.down:			ctrls.input.states['down']=true;		break;
		case ctrls.input.keys.left:			ctrls.input.states['left']=true;		break;
		case ctrls.input.keys.shoot:		ctrls.input.states['shoot']=true;		break;
		default:/* no assigned control, do nothing*/;
		break;
	}
	console.log('states\n up:'+ctrls.input.states.up+'\t right:'+ctrls.input.states.right+'\t down:'+ctrls.input.states.down+'\t left:'+ctrls.input.states.left);
});
document.addEventListener('keyup', function(e){
	switch(e.keyCode){
		case ctrls.input.keys.up:if(isReal(ctrls.input.states['up'])){ctrls.input.states.up=false;}				break;
		case ctrls.input.keys.right:if(isReal(ctrls.input.states['right'])){ctrls.input.states.right=false;}	break;
		case ctrls.input.keys.down:if(isReal(ctrls.input.states['down'])){ctrls.input.states.down=false;}		break;
		case ctrls.input.keys.left:if(isReal(ctrls.input.states['left'])){ctrls.input.states.left=false;}		break;
		case ctrls.input.keys.shoot:if(isReal(ctrls.input.states['shoot'])){ctrls.input.states.shoot=false;}	break;
		default:/** what else? Nescafe or the real shit ? */;break;
	}
});

let startTime=new Date().getTime();
let lastTime=startTime;
let anim = animate();

</script>

</body>
</html>


Commenter la réponse de magit