Phaser3 Game Objects - With Video Support

In case anyone is interested, here is a video gameobject solution. This is a very passionate topic for me, as I’ve needed it for many months.

Phaser3 Video Game Object

Quick Look

/* video typedef. */                                                                         
video_t=function(scene, id, x, y, texture, file, width, height, loop) {                      
  /* set texture pointer to new canvas. */                                                   
  scene.textures.createCanvas(texture, width, height);                                       
  Phaser.GameObjects.Image.call(this, scene, x, y, texture);                                 
                                                                                             
  /* gameobject data. */                                                                     
  this.id=id;                                                                                
  this.x=x;                                                                                  
  this.y=y;                                                                                  
  this.width=width;                                                                          
  this.height=height;                                                                        
                                                                                             
  /* video data. */                                                                          
  this.loaded=false;                                                                         
  this.loop=false;                                                                           
  if (loop)                                                                                  
    this.loop=true;                                                                          
                                                                                             
  /* create video as html5 video element. */                                                 
  this.video=document.createElement('video');                                                
  this.video.muted=true;                                                                     
  this.video.src=file;                                                                       
                                                                                             
  /* laziness - should use .call(this, ...) */                                               
  var _this=this;                                                                            
                                                                                             
  /* hook video event listener into animation. */                                            
  this.video.addEventListener('loadeddata', function() {                                     
    this.play();                                                                             
    _this.texture.context.drawImage(this, 0, 0);                                             
    _this.texture.refresh();                                                                 
    _this.loaded=true;                                                                       
  });                                                                                        
  /* loop by playing on 'end' event listener. */                                             
  if (this.loop) {                                                                           
    this.video.addEventListener('ended', function() {                                        
      this.play();                                                                           
    });                                                                                      
  }                                                                                          
                                                                                             
  /* dragging. */                                                                            
  this.setInteractive({draggable:true});                                                     
  this.on('dragstart', function (gameobject) {                                               
    this.setTint(0xff0000);                                                                  
  });                                                                                        
  this.on('drag', function (gameobject, drag_x, drag_y) {                                    
    this.x=drag_x;                                                                           
    this.y=drag_y;                                                                           
  });                                                                                        
  this.on('dragend', function (gameobject) {                                                 
    this.clearTint();                                                                        
  });                                                                                        
                                                                                             
  scene.add.existing(this);                                                                  
                                                                                             
  return this;                                                                               
}                                                                                            
video_t.prototype.constructor=video_t;                                                       
video_t.prototype=Object.create(Phaser.GameObjects.Image.prototype);                         
                                                                                             
video_t.prototype.update=function() {                                                        
  /* phaser's update call. */                                                                
  if (this.loaded) {                                                                         
    this.texture.context.drawImage(this.video, 0, 0);                                        
    /* beware of refresh and issues with overloading the GPU  - need more research here. */  
    this.texture.refresh();                                                                  
    //this.texture.update();                                                                 
  }                                                                                          
}                                                                                            
8 Likes

Very nice. Slows things up quite a bit though. I put this as part of a platformer level and it looks great but the character animation suffers. I don’t see any way to improve this though.

Possible small improvements: make dragging optional since you hardly ever need to drag videos. Also add this.width and this.height to the drawImage after 0, 0 to make the video scale to right size.

This is awesome! thanks a lot for this code!

For future readers, I do want to point out that Phaser 3.20 added built-in Video objects, which are likely going to be easier to use than this solution.

2 Likes

Right, I wrote this code simply as a workaround because I needed it right away. Video game objects have now been formalized in phaser3. This code is now obsolete.

See video object documentation here: Phaser.GameObjects.Video

1 Like

this does not works on iphone . netither chrome nor safari