Skip to content

Commit

Permalink
Change logic to improve fog drawing performance
Browse files Browse the repository at this point in the history
Double check in from ES6 branch #150
  • Loading branch information
gloomyson committed Aug 5, 2016
1 parent 7089fde commit d3110e8
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 100 deletions.
137 changes: 42 additions & 95 deletions Characters/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ var Map={
batchSize:0,//Draw fog by each batch
miniCxt:$('canvas[name="mini_map"]')[0].getContext('2d'),
fogCanvas:document.createElement('canvas'),
miniFogCanvas:document.createElement('canvas'),
shadowCanvas:document.createElement('canvas'),//Pre-render for fog shadow
insideStroke:{
width:0,
Expand All @@ -28,8 +27,9 @@ var Map={
Map.insideStroke.height=(130*Game.VBOUND/Map.getCurrentMap().height)>>0;
//Init fog relative
Map.fogCxt=Map.fogCanvas.getContext('2d');
Map.miniFogCanvas.width=Map.miniFogCanvas.height=130;
Map.miniFogCxt=Map.miniFogCanvas.getContext('2d');
Map.fogCanvas.width=130;
Map.fogCanvas.height=Math.round(130*Map.getCurrentMap().height/Map.getCurrentMap().width);
Map.fogCanvas.ratio=130/Map.getCurrentMap().width;
Map.shadowCanvas.width=Map.shadowCanvas.height=100;
Map.shadowCxt=Map.shadowCanvas.getContext('2d');
//Prepared fog shadow for quick render
Expand All @@ -46,98 +46,48 @@ var Map={
getCurrentMap:function(){
return sourceLoader.sources['Map_'+Map.currentMap];
},
refreshFogs:function(immediate){
var N=immediate?1:10;
//Initial if needed
if (Map.refreshFogs.step==null){
//Reset composite operation
Map.fogCxt.globalCompositeOperation=Map.miniFogCxt.globalCompositeOperation='source-over';
//Brush black fog to clean old fog
Map.fogCxt.fillStyle=Map.miniFogCxt.fillStyle='rgba(0,0,0,1)';
Map.fogCxt.fillRect(0,0,Map.fogCanvas.width,Map.fogCanvas.height);
Map.miniFogCxt.fillRect(0,0,130,130);
//Other things have sight
var parasitedEnemies=Unit.allEnemyUnits().filter(function(chara){
return chara.buffer.Parasite==Game.team;
});
var scannerSweeps=Burst.allEffects.filter(function(anime){
return Animation.getName(anime)=="ScannerSweep" && anime.team==Game.team;
});
var addInObjs=parasitedEnemies.concat(scannerSweeps);
//Clear fog
Map.fogCxt.globalCompositeOperation=Map.miniFogCxt.globalCompositeOperation='destination-out';
//Initial
Map.allUnits=Unit.allOurUnits().concat(Building.ourBuildings()).concat(addInObjs);
Map.fogUnits=Map.allUnits.filter(function(chara){
return chara.sightInsideScreen();
});
Map.batchSize=Math.ceil(Map.fogUnits.length/N);
Map.refreshFogs.step=0;//Initial step
Map.fogReady=false;
}
var batchUnits=[];
if (Map.fogUnits.length>Map.batchSize) {
batchUnits=Map.fogUnits.slice(0,Map.batchSize);
Map.fogUnits=Map.fogUnits.slice(Map.batchSize);
}
else {
batchUnits=Map.fogUnits;
Map.fogUnits=[];
}
//Draw interface call
drawFogAndMinimap:function(){
Map.refreshFog();
//Draw fog on main map
var ratio=Map.fogCanvas.ratio;
Game.fogCxt.clearRect(0,0,Game.HBOUND,Game.VBOUND);
Game.fogCxt.drawImage(Map.fogCanvas,Math.round(Map.offsetX*ratio),Math.round(Map.offsetY*ratio),
Math.round(Game.HBOUND*ratio),Math.round(Game.VBOUND*ratio),0,0,Game.HBOUND,Game.VBOUND);
//Draw mini-map
Map.drawMiniMap();
},
//Used by drawFogAndMinimap
refreshFog:function(){
//Reset composite operation
Map.fogCxt.globalCompositeOperation='source-over';
//Brush black fog to clean old fog
Map.fogCxt.fillStyle='rgba(0,0,0,1)';
Map.fogCxt.fillRect(0,0,Map.fogCanvas.width,Map.fogCanvas.height);
//Other things have sight
var parasitedEnemies=Unit.allEnemyUnits().filter(function(chara){
return chara.buffer.Parasite==Game.team;
});
var scannerSweeps=Burst.allEffects.filter(function(anime){
return anime.constructor.name=="ScannerSweep" && anime.team==Game.team;
});
var addInObjs=parasitedEnemies.concat(scannerSweeps);
//Clear fog
Map.fogCxt.globalCompositeOperation='destination-out';
//Initial
Map.allUnits=Unit.allOurUnits().concat(Building.ourBuildings()).concat(addInObjs);
//Draw fog
//console.log('BeforeInsideScreen:'+(new Date().getTime()));//test
Map.fogCxt.fillStyle='rgba(0,0,0,1)';
batchUnits.forEach(function(chara){
var ratio=Map.fogCanvas.ratio;
Map.allUnits.forEach(function(chara){
//Clear fog on screen for our units inside screen
var centerX=chara.posX()-Map.offsetX;
var centerY=chara.posY()-Map.offsetY;
var radius=chara.get('sight')<<1;//*2
var centerX=Math.round(chara.posX()*ratio);
var centerY=Math.round(chara.posY()*ratio);
var radius=Math.round(chara.get('sight')*ratio<<1);
Map.fogCxt.drawImage(Map.shadowCanvas,0,0,100,100,centerX-radius,centerY-radius,radius<<1,radius<<1);
});
Map.refreshFogs.step++;
if (Map.refreshFogs.step==N) {
delete Map.refreshFogs.step;//Return to initial
Map.fogReady=true;
}
//console.log('AfterInsideScreen-BeforeMinimap:'+(new Date().getTime()));//test
if (Map.fogReady){
Map.allUnits.forEach(function(chara){
//Clear fog on mini-map for all our units
var offsetX=(chara.posX()*130/Map.getCurrentMap().width)>>0;
var offsetY=(chara.posY()*130/Map.getCurrentMap().height)>>0;
var sight=(chara.get('sight')*130/Map.getCurrentMap().height)>>0;
Map.miniFogCxt.beginPath();
Map.miniFogCxt.drawImage(Map.shadowCanvas,0,0,100,100,offsetX-(sight<<1),offsetY-(sight<<1),sight<<2,sight<<2);
});
//console.log('AfterMinimap:'+(new Date().getTime()));//test
}
},
drawFogAndMinimap:function(immediate){
if (Map.fogFlag){
//Peformance: Refresh fog by 10 steps
Map.refreshFogs(immediate);
//Fogs are ready, now draw main fog and mini-map
if (Map.fogReady) {
//Draw fog on main map
Game.fogCxt.clearRect(0,0,Game.HBOUND,Game.VBOUND);
Game.fogCxt.drawImage(Map.fogCanvas,0,0);
//Draw mini-map
Map.drawMiniMap();
}
}
else {
if (immediate) Map.drawMiniMap();
else {
if (Game.mainTick%10==1) Map.drawMiniMap();
}
}
},
//Bad performance, very slow operation
drawFogsImmediate:function(){
delete Map.refreshFogs.step;
Map.drawFogAndMinimap(true);
},
//Red-Green block and white stroke
//Used by drawFogAndMinimap: draw red&green block and white stroke
drawMiniMap:function(){
//Selected map size
var mapWidth=Map.getCurrentMap().width;
Expand All @@ -155,11 +105,8 @@ var Map={
rectSize=(chara instanceof Building)?4:3;
Map.miniCxt.fillRect(miniX,miniY,rectSize,rectSize);
});
//Re-draw fog on mini-map
if (Map.fogFlag && Map.miniFogCxt){
//Draw fog on mini-map
Map.miniCxt.drawImage(Map.miniFogCanvas,0,0);
}
//Draw fog on mini-map
Map.miniCxt.drawImage(Map.fogCanvas,0,0,Map.fogCanvas.width,Map.fogCanvas.height,0,0,130,130);
//Re-draw inside stroke
Map.miniCxt.strokeStyle='white';
Map.miniCxt.lineWidth=2;
Expand Down Expand Up @@ -237,7 +184,7 @@ var Map={
}
Map.drawBg();
//Need re-calculate fog when screen moves
if (!onlyMap) Map.drawFogsImmediate();
if (!onlyMap) Map.drawFogAndMinimap();
},
clickHandler:function(event){
//Mouse at (clickX,clickY)
Expand Down
2 changes: 1 addition & 1 deletion GameRule/Cheat.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var Cheat={
//Clear old fog on screen
Game.fogCxt.clearRect(0,0,Game.HBOUND,Game.VBOUND);
//Redraw mini-map
Map.drawFogsImmediate();
Map.drawFogAndMinimap();
}
break;
case "something for nothing":
Expand Down
4 changes: 1 addition & 3 deletions GameRule/Game.js
Original file line number Diff line number Diff line change
Expand Up @@ -1117,8 +1117,6 @@ var Game={
//Resize canvas
$('#GamePlay>canvas').attr('width',Game.HBOUND);//Canvas width adjust
$('#GamePlay>canvas').attr('height',Game.VBOUND-Game.infoBox.height+5);//Canvas height adjust
Map.fogCanvas.width=Game.HBOUND;
Map.fogCanvas.height=Game.VBOUND-Game.infoBox.height+5;
//Resize panel_Info
$('div.panel_Info')[0].style.width=((Game.HBOUND-295)+'px');
if (Map.ready){
Expand All @@ -1128,7 +1126,7 @@ var Game={
//Redraw background
Map.drawBg();
//Need re-calculate fog immediately
Map.drawFogsImmediate();
Map.drawFogAndMinimap();
}
},
getCurrentTs:function(){
Expand Down
3 changes: 2 additions & 1 deletion GameRule/Referee.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ var Referee={
}
},
coverFog:function(){
Map.drawFogAndMinimap();
//No need to set interval as 1sec
if (Game.mainTick%10==0) Map.drawFogAndMinimap();
},
alterSelectionMode:function(){
//GC after some user changes
Expand Down
12 changes: 12 additions & 0 deletions SVN.log
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
Revision: 151
Author: gloomyson
Date: 17:19:42, 2016-8-5
Message:
Double check in to main branch from ES6 for #150:
Change logic to improve fog drawing performance
----
Modified : /StarCraft/Characters/Map.js
Modified : /StarCraft/GameRule/Cheat.js
Modified : /StarCraft/GameRule/Game.js
Modified : /StarCraft/GameRule/Referee.js

Revision: 142
Author: gloomyson
Date: 9:49:09, 2016-7-16
Expand Down

0 comments on commit d3110e8

Please sign in to comment.