ocanvas sprite hue change

时间:2015-05-28 23:21:45

标签: javascript html5-canvas ocanvas

我正在使用ocanvas设计游戏,我想知道是否有某种方法可以改变精灵的色调。如果没有,有没有办法整合html5画布的方式来改变精灵的色调到ocanvas?

2 个答案:

答案 0 :(得分:1)

我没有关于ocanvas的信息,但这里是如何更改绘制到html5画布上的精灵的色调。

此方法使用context.getImageData来获取画布上每个像素的颜色数据。然后任何具有蓝色色调的像素都会变为绿色色调。

注意:如果你的精灵有更多离散的颜色(f.ex:精灵有一个特定的蓝色,你希望改变为特定的绿色),那么你不需要转换为和来自HSL颜色格式。

如有必要,您可以将此重新塑造的html5画布转换为精灵图像,以使用.toDataURL包含在ocanvas中。

enter image description here

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

var img=new Image();
img.crossOrigin="anonymous";
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/marioStanding.png";
function start(){
  ctx.drawImage(img,0,0);
  ctx.drawImage(img,150,0);
  // shift blueish colors to greenish colors
  recolorPants(-.33);   
}

function recolorPants(colorshift){

  var imgData=ctx.getImageData(150,0,canvas.width,canvas.height);
  var data=imgData.data;

  for(var i=0;i<data.length;i+=4){
    red=data[i+0];
    green=data[i+1];
    blue=data[i+2];
    alpha=data[i+3];

    // skip transparent/semiTransparent pixels
    if(alpha<230){continue;}

    var hsl=rgbToHsl(red,green,blue);
    var hue=hsl.h*360;

    // change blueish pixels to the new color
    if(hue>200 && hue<300){
      var newRgb=hslToRgb(hsl.h+colorshift,hsl.s,hsl.l);
      data[i+0]=newRgb.r;
      data[i+1]=newRgb.g;
      data[i+2]=newRgb.b;
      data[i+3]=255;
    }
  }    
  ctx.putImageData(imgData,150,0);
}


function rgbToHsl(r, g, b){
  r /= 255, g /= 255, b /= 255;
  var max = Math.max(r, g, b), min = Math.min(r, g, b);
  var h, s, l = (max + min) / 2;

  if(max == min){
    h = s = 0; // achromatic
  }else{
    var d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch(max){
      case r: h = (g - b) / d + (g < b ? 6 : 0); break;
      case g: h = (b - r) / d + 2; break;
      case b: h = (r - g) / d + 4; break;
    }
    h /= 6;
  }

  return({
    h:h,
    s:s,
    l:l,
  });
}


function hslToRgb(h, s, l){
  var r, g, b;

  if(s == 0){
    r = g = b = l; // achromatic
  }else{
    function hue2rgb(p, q, t){
      if(t < 0) t += 1;
      if(t > 1) t -= 1;
      if(t < 1/6) return p + (q - p) * 6 * t;
      if(t < 1/2) return q;
      if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
      return p;
    }

    var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
    var p = 2 * l - q;
    r = hue2rgb(p, q, h + 1/3);
    g = hue2rgb(p, q, h);
    b = hue2rgb(p, q, h - 1/3);
  }

  return({
    r:Math.round(r * 255),
    g:Math.round(g * 255),
    b:Math.round(b * 255),
  });
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<p>Example shifting color Hue with .getImageData</p>
<p>(Original: left, Recolored: right)</p>
<canvas id="canvas" width=300 height=300></canvas>

答案 1 :(得分:1)

另一种流行的解决方案是使用灰度图像并通过canvas中的globalCompositeOperation在JS中对它们进行着色。这里详细描述:http://buildnewgames.com/global-composit-operations/#colored-sprite-masks-with-codesource-atopcode

我汇总了一个如何与oCanvas一起完成的例子:http://jsfiddle.net/g0tj7vrv/

HTML:

<script src="https://cdnjs.cloudflare.com/ajax/libs/ocanvas/2.7.4/ocanvas.min.js"></script>

<canvas id="canvas" width="400" height="400"></canvas>

JS:

var canvas = oCanvas.create({
    canvas: '#canvas',
    background: '#000'
});

canvas.display.register('colorizedImage', {
    hue: '',
    path: '',
    width: 0,
    heigth: 0,
    _renderNewColor: function(tempImage) {
        if (!this._tempCanvas) {
            this._tempCanvas = document.createElement('canvas');
        }
        this._createColorizedImage(this._tempCanvas, tempImage, this.hue);
        var self = this;
        setTimeout(function() {
            self.core.redraw();
        }, 0);
    },
    _createColorizedImage: function(tempCanvas, imageElement, hue) {
        var tempContext = tempCanvas.getContext('2d');

        tempCanvas.width = imageElement.width;
        tempCanvas.height = imageElement.height;

        tempContext.drawImage(imageElement, 0, 0);
        tempContext.fillStyle = 'hsla(' + hue + ', 50%, 50%, 0.5)';
        tempContext.globalCompositeOperation = 'source-atop';
        tempContext.fillRect(0, 0, tempCanvas.width, tempCanvas.height);
    }
}, function(context) {
    if (this._tempCanvas) {
        var origin = this.getOrigin();
        var x = this.abs_x - origin.x;
        var y = this.abs_y - origin.y;
        var w = this.width || this._tempCanvas.width;
        var h = this.height || this._tempCanvas.height;
        context.drawImage(this._tempCanvas, x, y, w, h);
    }

    if (this.path !== this._lastPathBeingLoaded) {
        this._lastPathBeingLoaded = this.path;
        var tempImage = new Image();
        tempImage.src = this.path;
        var self = this;
        tempImage.onload = function() {
            if (self.path === this.src) {
                self._renderNewColor(tempImage);
            }
        };
        this._lastImageElement = tempImage;
    }

    if (this.hue !== this._lastHueBeingLoaded) {
        this._lastHueBeingLoaded = this.hue;
        this._renderNewColor(this._lastImageElement);
    }
});

var colorizedImage = canvas.display.colorizedImage({
    hue: 0,
    path: 'https://dl.dropboxusercontent.com/u/2645586/gco/cobra-primary.png',
    origin: {x: -60, y: 0},
    width: 120,
    height: 120,
    x: canvas.width / 2,
    y: canvas.height / 2
});

canvas.addChild(colorizedImage);

canvas.setLoop(function() {
    colorizedImage.hue = (colorizedImage.hue + 10) % 360;
    colorizedImage.rotation -= 2;
}).start();