[Client 7.0] Fullscreen/MScale

Posts 1–2 of 2 · Page 1 of 1
[Client 7.0] Fullscreen/MScale
Hello! I am pleased to bring what I think is possibly the best MScale ever made. It's relatively simple to implement, works perfectly for both software and hardware rendering, any game size AND there's no need for any UI scaling as it just works So let's get to it!

Starting off in WebMain.as add these three variables.
Code:
public static var StageWidth:int;
public static var StageHeight:int;
private var resized_:Boolean;
Then in private function setup() after STAGE.addEventListener(Event.ENTER_FRAME, onEnterFrame);
Code:
STAGE.addEventListener(Event.RESIZE, updateStageSize);
setStageSize();
Don't worry about the red, that will be fixed eventually. Replace private static function onEnterFrame(event:Event) with this
Code:
private function onEnterFrame(event:Event) : void
{
   SoundEffectLibrary.clear();
   if (!resized_){
      setStageSize();
   }
      resized_ = false;
}

private function updateStageSize(event:Event) : void
{
   setStageSize();
   resized_ = true;
}

private function setStageSize() : void
{
   StageWidth = stage.stageWidth / Parameters.data_.mScale;
   StageHeight = stage.stageHeight / Parameters.data_.mScale;
}
After, go to Parameters.as and inside public static function setDefaults() add
Code:
setDefault("mScale", 1);
Now in Camera.as replace public function configureCamera(object:GameObject, isHallucinating:Boolean) with
Code:
public function configureCamera(object:GameObject, isHallucinating:Boolean) : void
{
   var screenRect:Rectangle = correctCameraView();
   var cameraAngle:Number = Parameters.data_.cameraAngle;
   this.configure(object.x_,object.y_,12,cameraAngle,screenRect,false);
   this.isHallucinating_ = isHallucinating;
}

private function correctCameraView() : Rectangle
{
   var width:int = WebMain.StageWidth - 200 * (WebMain.StageWidth / 800);
   var height:int = WebMain.StageHeight;
   var y:int = Boolean(Parameters.data_.centerOnPlayer)?height*(CENTER_SCREEN_RECT.y/600):height*(OFFSET_SCREEN_RECT.y/600);
   var x:int = width / 2;
   return new Rectangle(-x, y, width, height);
}
Now for the software MAGIC!! In Map.as replace the entire public function draw(camera:Camera, time:int) with
Code:
public function draw(camera:Camera, time:int) : void
{
   var isGpuRender:Boolean = Parameters.isGpuRender(); // cache result for faster access
   Parameters.GPURenderFrame = isGpuRender;
   if (wasLastFrameGpu != isGpuRender) {
      var context:Context3D = WebMain.STAGE.stage3Ds[0].context3D;
      if (wasLastFrameGpu && context != null &&
              context.driverInfo.toLowerCase().indexOf("disposed") == -1) {
         context.clear();
         context.present();
      }
      else {
         map_.graphics.clear();
      }
      signalRenderSwitch.dispatch(wasLastFrameGpu);
      wasLastFrameGpu = isGpuRender;
   }

   var filter:uint = 0;
   var render3D:Render3D = null;
   var i:int = 0;
   var square:Square = null;
   var go:GameObject = null;
   var bo:BasicObject = null;
   var yi:int = 0;
   var dX:Number = NaN;
   var dY:Number = NaN;
   var distSq:Number = NaN;
   var b:Number = NaN;
   var t:Number = NaN;
   var d:Number = NaN;
   var screenRect:Rectangle = camera.clipRect_;
   x = 300;
   y = Boolean(Parameters.data_.centerOnPlayer)?-Camera.CENTER_SCREEN_RECT.y:-Camera.OFFSET_SCREEN_RECT.y;
   stage.scaleMode = StageScaleMode.NO_SCALE;
   scaleX = 800 / WebMain.StageWidth;
   scaleY = 600 / WebMain.StageHeight;
   var distW:Number = (-screenRect.y - screenRect.height / 2) / 50;
   var screenCenterW:Point = new Point(camera.x_ + distW * Math.cos(camera.angleRad_ - Math.PI / 2),camera.y_ + distW * Math.sin(camera.angleRad_ - Math.PI / 2));
   if(this.background_ != null)
   {
      this.background_.draw(camera,time);
   }

   this.visible_.length = 0;
   this.visibleUnder_.length = 0;
   this.visibleSquares_.length = 0;
   this.topSquares_.length = 0;

   var delta:int = camera.maxDist_;
   var xStart:int = Math.max(0,screenCenterW.x - delta);
   var xEnd:int = Math.min(this.width_ - 1,screenCenterW.x + delta);
   var yStart:int = Math.max(0,screenCenterW.y - delta);
   var yEnd:int = Math.min(this.height_ - 1,screenCenterW.y + delta);

   this.graphicsData_.length = 0;
   this.graphicsDataStageSoftware_.length = 0;
   this.graphicsData3d_.length = 0;

   // visible tiles
   for(var xi:int = xStart; xi <= xEnd; xi++)
   {
      for(yi = yStart; yi <= yEnd; yi++)
      {
         square = this.squares_[xi + yi * this.width_];
         if(square != null)
         {
            dX = screenCenterW.x - square.center_.x;
            dY = screenCenterW.y - square.center_.y;
            distSq = dX * dX + dY * dY;
            if(distSq <= camera.maxDistSq_)
            {
               square.lastVisible_ = time;
               square.draw(this.graphicsData_,camera,time);
               this.visibleSquares_.push(square);
               if(square.topFace_ != null)
               {
                  this.topSquares_.push(square);
               }
            }
         }
      }
   }

   // visible game objects
   for each(go in this.goDict_)
   {
      go.drawn_ = false;
      square = go.square_;
      if(!(square == null || square.lastVisible_ != time))
      {
         go.drawn_ = true;
         go.computeSortVal(camera);
         if(go.props_.drawUnder_)
         {
            if(go.props_.drawOnGround_)
            {
               go.draw(this.graphicsData_,camera,time);
            }
            else
            {
               this.visibleUnder_.push(go);
            }
         }
         else
         {
            this.visible_.push(go);
         }
      }
   }

   // visible basic objects (projectiles, particles and such)
   for each(bo in this.boDict_)
   {
      bo.drawn_ = false;
      square = bo.square_;
      if(!(square == null || square.lastVisible_ != time))
      {
         bo.drawn_ = true;
         bo.computeSortVal(camera);
         this.visible_.push(bo);
      }
   }

   // draw visible under
   if(this.visibleUnder_.length > 0)
   {
      this.visibleUnder_.sortOn(VISIBLE_SORT_FIELDS,VISIBLE_SORT_PARAMS);
      for each(bo in this.visibleUnder_)
      {
         bo.draw(this.graphicsData_,camera,time);
      }
   }

   // draw shadows
   this.visible_.sortOn(VISIBLE_SORT_FIELDS,VISIBLE_SORT_PARAMS);
   if(Parameters.data_.drawShadows)
   {
      for each(bo in this.visible_)
      {
         if(bo.hasShadow_)
         {
            bo.drawShadow(this.graphicsData_,camera,time);
         }
      }
   }

   // draw visible
   for each(bo in this.visible_)
   {
      bo.draw(this.graphicsData_,camera,time);
      if (isGpuRender) {
         bo.draw3d(this.graphicsData3d_);
      }
   }

   // draw top squares
   if(this.topSquares_.length > 0)
   {
      for each(square in this.topSquares_)
      {
         square.drawTop(this.graphicsData_,camera,time);
      }
   }

   // draw breath overlay
   if(this.player_ != null && this.player_.breath_ >= 0 && this.player_.breath_ < Parameters.BREATH_THRESH)
   {
      b = (Parameters.BREATH_THRESH - this.player_.breath_) / Parameters.BREATH_THRESH;
      t = Math.abs(Math.sin(time / 300)) * 0.75;
      BREATH_CT.alphaMultiplier = b * t;
      this.hurtOverlay_.transform.colorTransform = BREATH_CT;
      this.hurtOverlay_.visible = true;
      this.hurtOverlay_.x = screenRect.left;
      this.hurtOverlay_.y = screenRect.top;
   }
   else
   {
      this.hurtOverlay_.visible = false;
   }

   // draw side bar gradient
   if(this.player_ != null)
   {
      this.gradientOverlay_.visible = true;
      this.gradientOverlay_.x = screenRect.right - 10;
      this.gradientOverlay_.y = screenRect.top;
      this.gradientOverlay_.height = 600 * (600 / scaleY);
   }
   else
   {
      this.gradientOverlay_.visible = false;
   }

   // draw hw capable screen filters
   if(isGpuRender && Renderer.inGame)
   {
      filter = this.getFilterIndex();
      render3D = StaticInjectorContext.getInjector().getInstance(Render3D);
      render3D.dispatch(this.graphicsData_,this.graphicsData3d_,width_,height_,camera,filter);
      for(i = 0; i < this.graphicsData_.length; i++)
      {
         if(this.graphicsData_[i] is GraphicsBitmapFill && GraphicsFillExtra.isSoftwareDraw(GraphicsBitmapFill(this.graphicsData_[i])))
         {
            this.graphicsDataStageSoftware_.push(this.graphicsData_[i]);
            this.graphicsDataStageSoftware_.push(this.graphicsData_[i + 1]);
            this.graphicsDataStageSoftware_.push(this.graphicsData_[i + 2]);
         }
         else if(this.graphicsData_[i] is GraphicsSolidFill && GraphicsFillExtra.isSoftwareDrawSolid(GraphicsSolidFill(this.graphicsData_[i])))
         {
            this.graphicsDataStageSoftware_.push(this.graphicsData_[i]);
            this.graphicsDataStageSoftware_.push(this.graphicsData_[i + 1]);
            this.graphicsDataStageSoftware_.push(this.graphicsData_[i + 2]);
         }
      }
      if(this.graphicsDataStageSoftware_.length > 0)
      {
         map_.graphics.clear();
         map_.graphics.drawGraphicsData(this.graphicsDataStageSoftware_);
         if(this.lastSoftwareClear)
         {
            this.lastSoftwareClear = false;
         }
      }
      else if(!this.lastSoftwareClear)
      {
         map_.graphics.clear();
         this.lastSoftwareClear = true;
      }
      if(time % 149 == 0)
      {
         GraphicsFillExtra.manageSize();
      }
   }
   else
   {
      map_.graphics.clear();
      map_.graphics.drawGraphicsData(this.graphicsData_);
   }

   // draw filters
   this.map_.filters.length = 0;
   if(this.player_ != null && (this.player_.condition_ & ConditionEffect.MAP_FILTER_BITMASK) != 0)
   {
      var filters:Array = [];
      if(this.player_.isDrunk())
      {
         d = 20 + 10 * Math.sin(time / 1000);
         filters.push(new BlurFilter(d,d));
      }
      if(this.player_.isBlind())
      {
         filters.push(BLIND_FILTER);
      }
      this.map_.filters = filters;
   }
   else if(this.map_.filters.length > 0)
   {
      this.map_.filters = [];
   }

   this.mapOverlay_.draw(camera,time);
   this.partyOverlay_.draw(camera,time);

   stage.scaleMode = StageScaleMode.EXACT_FIT;
}
Now if you play, you should see the game scale with your screen size. However, you'll notice it doesn't work with hardware accel. So let's do the hardware MAGIC, go to Renderer.as and replace private function renderScene with
Code:
private function renderScene(graphicsDatas:Vector.<IGraphicsData>, grahpicsData3d:Vector.<Object3DStage3D>, mapWidth:Number, mapHeight:Number, camera:Camera) : void
{
   var test:int = 0;
   var graphicsData:IGraphicsData = null;
   this.context3D.clear();
   var finalTransform:Matrix3D = new Matrix3D();
   var index3d:uint = 0;
   this.widthOffset_ = -mapWidth / 2;
   this.heightOffset_ = mapHeight / 2;
   this.UpdateCameraMatrix(camera);
   for each(graphicsData in graphicsDatas)
   {
      this.context3D.GetContext3D().setCulling(Context3DTriangleFace.NONE);
      if(graphicsData is GraphicsBitmapFill && !GraphicsFillExtra.isSoftwareDraw(GraphicsBitmapFill(graphicsData)))
      {
         try
         {
            test = GraphicsBitmapFill(graphicsData).bitmapData.width;
         }
         catch(e:Error)
         {
            trace("ERROR CAUGHT -- Invalid Bitmap Data");
            continue;
         }
         this.graphic3D_.setGraphic(GraphicsBitmapFill(graphicsData),this.context3D);
         finalTransform.identity();
         finalTransform.append(this.graphic3D_.getMatrix3D());
         finalTransform.appendScale(1 / Stage3DConfig.HALF_WIDTH,1 / Stage3DConfig.HALF_HEIGHT,1);
         finalTransform.appendScale(800 / WebMain.StageWidth, 600 / WebMain.StageHeight, 1);
         finalTransform.appendTranslation(this.tX / Stage3DConfig.WIDTH,this.tY / Stage3DConfig.HEIGHT,0);
         this.context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,finalTransform,true);
         this.graphic3D_.render(this.context3D);
      }
      if(graphicsData is GraphicsGradientFill)
      {
         this.context3D.GetContext3D().setProgram(this.shadowProgram_);
         this.graphic3D_.setGradientFill(GraphicsGradientFill(graphicsData),this.context3D,Stage3DConfig.HALF_WIDTH,Stage3DConfig.HALF_HEIGHT);
         finalTransform.identity();
         finalTransform.append(this.graphic3D_.getMatrix3D());
         finalTransform.appendScale(800 / WebMain.StageWidth, 600 / WebMain.StageHeight, 1);
         finalTransform.appendTranslation(this.tX / Stage3DConfig.WIDTH,this.tY / Stage3DConfig.HEIGHT,0);
         this.context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,finalTransform,true);
         this.context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT,4,Vector.<Number>([0.5,0.25,0,0]));
         this.graphic3D_.renderShadow(this.context3D);
      }
      if(graphicsData == null && grahpicsData3d.length != 0)
      {
         try
         {
            this.context3D.GetContext3D().setProgram(this.program2);
            this.context3D.GetContext3D().setCulling(Context3DTriangleFace.BACK);
            grahpicsData3d[index3d].UpdateModelMatrix(this.widthOffset_,this.heightOffset_);
            finalTransform.identity();
            finalTransform.append(grahpicsData3d[index3d].GetModelMatrix());
            finalTransform.append(this.cameraMatrix_);
            finalTransform.append(this._projection);
            finalTransform.appendScale(800 / WebMain.StageWidth, 600 / WebMain.StageHeight, 1);
            finalTransform.appendTranslation(this.tX / Stage3DConfig.WIDTH,this.tY / Stage3DConfig.HEIGHT * 11.5,0);
            this.context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,finalTransform,true);
            this.context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,8,grahpicsData3d[index3d].GetModelMatrix(),true);
            grahpicsData3d[index3d].draw(this.context3D.GetContext3D());
            index3d++;
         }
         catch(e:Error)
         {
            trace("ERROR CAUGHT -- Invalid Bitmap Data");
            continue;
         }
      }
   }
}
Whew that was a lot, almost there! Now you should see the same effect for both rendering modes. Nice! Now it's time for the final bit, actively changing the mscale. Go to MapUserInput.as and replace private function onMouseWheel(event:MouseEvent) with
Code:
private function onMouseWheel(event:MouseEvent) : void
{
   if (event.ctrlKey)
   {
      if(event.delta > 0)
      {
         Parameters.data_.mScale = Math.min(Parameters.data_.mScale + 0.05, 2);
      }
      else
      {
         Parameters.data_.mScale = Math.max(Parameters.data_.mScale - 0.05, 0.5);
      }
      return;
   }
   if(event.delta > 0)
   {
      this.miniMapZoom.dispatch(MiniMapZoomSignal.IN);
   }
   else
   {
      this.miniMapZoom.dispatch(MiniMapZoomSignal.OUT);
   }
}
And that it! The perfect mscale. All UI is based on the 800x600 window so no need for extra scaling, and all filter effects work to.
Hey, are you able to help me set up your updated version of skillys educational source? Finally found the right AIR SDK however there are still errors all over the place.
Got it to work. By the way, default client you released doesn't let this mscale work unless you add import flash.display.StageScaleMode

Thanks tho.
Posts 1–2 of 2 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Talk with us