0
votes

I'm playing around with phaserJS to make a simple example of top to down car game. I thought it would be nice, add to the car some drift marks when accelerating. So I came up adding a two graphics elements and then update their position on each frame.

Something like this:

var game = new Phaser.Game(500, 500, Phaser.AUTO, 'game');
	var mainState = { 
		preload:function(){
			game.load.image('car', 'notfound');

		},
	 	create: function() {
	 		game.stage.backgroundColor = '#ffffff'
			game.physics.startSystem(Phaser.Physics.P2JS);

			car = game.add.sprite(window.innerWidth/2, window.innerHeight/2, 'car');


			game.physics.p2.enable(car, false);
			car.anchor.setTo(0.5, 0.8);

			this.graphics = game.add.graphics(0,0);
			this.graphics2 = game.add.graphics(0,0);
			this.graphics.moveTo(car.body.x+(Math.cos(this.math.degToRad(car.body.angle))*5),car.body.y+(Math.sin(this.math.degToRad(car.body.angle))*5));
		    this.graphics2.moveTo(car.body.x+(Math.cos(this.math.degToRad(car.body.angle))*(-5)),car.body.y+(Math.sin(this.math.degToRad(car.body.angle))*(-5)));
		    this.trololo;
		},	
		update: function() {
			car.body.damping = 0.9;
		    car.body.setZeroRotation();
		    
          
		    if (game.input.keyboard.isDown(Phaser.Keyboard.UP)){
		    	
		    	this.graphics.lineStyle(2, 0x111111, 1);
		    	this.graphics2.lineStyle(2, 0x111111, 1);
		    	
		    	this.graphics.lineTo(car.body.x+(Math.cos(this.math.degToRad(car.body.angle))*5),car.body.y+(Math.sin(this.math.degToRad(car.body.angle))*5));
		    	this.graphics2.lineTo(car.body.x+(Math.cos(this.math.degToRad(car.body.angle))*(-5)),car.body.y+(Math.sin(this.math.degToRad(car.body.angle))*(-5)));

		    	
		    	if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
					car.body.rotateLeft(100);
				}
			    else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)){
			    	car.body.rotateRight(100);
			    }
		    	car.body.thrust(400);
		    }
		    else{
		    	this.graphics.moveTo(car.body.x+(Math.cos(this.math.degToRad(car.body.angle))*5),car.body.y+(Math.sin(this.math.degToRad(car.body.angle))*5));
		    	this.graphics2.moveTo(car.body.x+(Math.cos(this.math.degToRad(car.body.angle))*(-5)),car.body.y+(Math.sin(this.math.degToRad(car.body.angle))*(-5)));
		    	if(Math.abs(car.body.velocity.x) > 6 || Math.abs(car.body.velocity.y) > 6){
			    	if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
						car.body.rotateLeft(10);
					} 
				    else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)){
				    	car.body.rotateRight(10);
				    }
			    }
		    } 
			    
		}


	};
	game.state.add('main', mainState);  
	game.state.start('main');
<div id="game"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/2.4.8/phaser.min.js"></script>

Now, I would like this marks to disappear progressively... Any clue on how to achieve that?

1
I see two approaches: 1. particle engine - fading out each track particle after some time, 2. paint tracks on dedicated (offscreen) canvas and apply blur filter / incremend alpha values / ... - le_m
Thanks for the suggestions... something like you said in your second point it's what I was trying now, just having 2 different lines and changing alternatively the opacity of them to 0 (by tweening it). See here: jsfiddle.net/jolmos/jg8ojL2u For now it's ok, but what I really want is fade out the line from the begin to the end, following the path... - jolmos
This seems more like approach 1 - particle engine (with only 2 particles) to me. I added a snippet demonstrating approach 2 below (as an answer). - le_m
I have found that by reducing the darkness and making it proportional to the amount of wheel slippage can negate the need for removal. Only extreme event will produce dark lines, most of the others are barely noticeable, but build up to show good lines through corners. - Blindman67
Thanks for the comment @Blindman67. Yes, I also want to make the marks opacity proporcional to the acceleration (but I don't think this would be a problem). What I want now it's more like a fade out of the path of the car. - jolmos

1 Answers

1
votes

I see two approaches:

  1. particle engine - fading out each track particle after some time
  2. paint tracks on dedicated (offscreen) canvas and apply blur filter / decrement alpha values

Demonstration of approach 2 in pure JS:

var bgCanvas = document.getElementById('bg-canvas'),
    bgContext = bgCanvas.getContext('2d'),
    fgCanvas = document.getElementById('fg-canvas'),
    fgContext = fgCanvas.getContext('2d');

function bgFade() {
  var imageData = bgContext.getImageData(0, 0, bgCanvas.width, bgCanvas.height);
  var data = imageData.data;
  for (var i = 3; i < data.length; i += 4) {
    data[i] -= 5;
  }
  bgContext.putImageData(imageData, 0, 0);
}

function update() {
  bgFade();

  bgContext.beginPath();
  bgContext.arc(Math.random() * bgCanvas.width, Math.random() * bgCanvas.height, 4, 0, Math.PI * 2);
  bgContext.fillStyle = '#000000';
  bgContext.fill();

  fgContext.beginPath();
  fgContext.arc(Math.random() * fgCanvas.width, Math.random() * fgCanvas.height, 4, 0, Math.PI * 2);
  fgContext.fillStyle = '#ff0000';
  fgContext.fill();

  requestAnimationFrame(update);
}

requestAnimationFrame(update);
#stage canvas {
  position: absolute;
  left: 0;
  top: 0;
}
<div id="stage">
  <canvas id="bg-canvas"></canvas>
  <canvas id="fg-canvas"></canvas>
</div>

Note that everything that gets painted on the background canvas fades out, while everything painted on the foreground canvas remains.