Announcement

Collapse
No announcement yet.

Using Canvas.Project & scaleform to create health bars above players

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Using Canvas.Project & scaleform to create health bars above players

    Hey all

    I am trying to create health bars with other information like player names above players heads.

    Now I basically have this working except the scaleform movie clip isn't lining up correctly enough.

    How it looks is that when you are very close to another player, it lines up at roughly half the players height, and too far to the right. So I figured if I just adjusted the X & Y values this would solve the problem.

    It did, but only if you are standing right next to the player. As you get further and further away from the player, the health bar location becomes more and more wrong.

    This is my code for attaching the the MC to the player:

    My Hudwrapper class:
    Code:
    event PostRender()
    {
        local PHVehicle Beacon;
        local vector loc;
        super.PostRender();
        
        foreach WorldInfo.AllActors(class'PHVehicle',Beacon )
        {    
            if (Beacon.HealthBeacon != none && WorldInfo.GRI.OnSameTeam(PlayerOwner, Beacon) == true && Beacon.Controller != PlayerOwner )
            {
                loc = Canvas.Project(Beacon.Location);
                //loc.Y += -300;
               // loc.X += -100;
                Beacon.HealthBeacon.UpdatePosition(Beacon,loc);
            }
            
        }
    }
    and this is the actual movieclip class:

    Code:
    class PHGFxHUD_Beacons extends GFxMoviePlayer;
    
    var int Width, Height;
    var string UserName;
    var GFxObject PlayerName_TF, HealthBarMC;
    
    
    
    function bool Start(optional bool StartPaused = false)
    {    
        local float x0, y0, x1, y1;
        local PlayerReplicationInfo PRI; 
        local PlayerController PC; 
    
        super.Start();
        Advance(0);
         self.SetViewPort(10000000,100000000,10,10);
    
        // Get width & height of Movie
        GetVisibleFrameRect(x0, y0, x1, y1);
        Width = x1-x0;
        Height = y1-y0;
        
        PC = GetPC(); 
        PRI = PC.PlayerReplicationInfo; 
        
        UserName = PRI.PlayerName;
        
        PlayerName_TF = GetVariableObject("_root.UserName"); 
        PlayerName_TF.setText(UserName); 
        
        HealthBarMC = GetVariableObject( "_root.HealthBar" );
        
        return true;    
    }
    
    function UpdatePosition(PHVehicle o, Vector ScreenPos)
    {
        self.SetViewPort(ScreenPos.X,ScreenPos.Y,Width,Height);
    }
    
    
    DefaultProperties
    {
        bDisplayWithHudOff=false
        MovieInfo=SwfMovie'PHHUD.HealthBeacon'
        bAutoPlay = true
        bCloseOnLevelChange = true
    }
    and finally, I am creating the movieclip inside the vehicle that the player is in


    Code:
    class PHVehicle extends UTVehicle;
    
    
    var PHGFxHUD_Beacons         HealthBeacon;
    
    simulated function CreateMovie()
    {
        HealthBeacon = new class'PHGFxHUD_Beacons';
        HealthBeacon.MovieInfo = SwfMovie'PHHUD.HealthBeacon';
        
        HealthBeacon.SetTimingMode(TM_Real); 
        HealthBeacon.Start();
        
    }
    
    
    simulated function PostBeginPlay()
    {
        Super.PostBeginPlay();
        CreateMovie();
        
    }
    I am thinking that maybe the origin of my swf is wrong perhaps, or maybe I am just going about this the wrong way.

    Any suggestions would be most helpful!
    Thankyou!

    #2
    Hey man, I was actually wanting migrate my messy Canvas healthbar/nametag to Scaleform so I figured I'd give it a go starting off with your method. I've modified it, and this works for me:

    EDIT:
    Sorry if you read this before I made this edit I accidentally submitted the post too soon.

    In my pawn's post begin play I call this function:

    Code:
    simulated function CreateBeacon()
    {
    	PlayerBeacon = new class'PlayerBeaconMoviePlayer';
    	PlayerBeacon.SetTimingMode(TM_Real);
    	PlayerBeacon.Init();
    }
    Then in my Movie class I have (It's empty right now...I was just trying to get it to show the movie correctly.)

    Code:
    class PlayerBeaconMoviePlayer extends GFxMoviePlayer;
    
    var GFxObject PlayerBeacon, beaconName, beaconHealth;
    
    function Init(optional LocalPlayer PC)
    {
    	Start();
    	Advance(0.f);
    	
    	PlayerBeacon = GetVariableObject("_root.PlayerBeacon");
    	beaconName = GetVariableObject("_root.PlayerBeacon.beaconName");
    	beaconHealth = GetVariableObject("_root.PlayerBeacon.beaconHealth");
    		
    	super.Init(PC);
    }
    function TickHUD()
    {
    }
    DefaultProperties
    {	
    	MovieInfo=SwfMovie'DHud.beacon'
    }
    In my HUD class I call this function from Post Render

    Code:
    function DrawBeacons()
    {
        local AwesomePawn P;
        local Vector loc;
    
        foreach WorldInfo.AllPawns(class'AwesomePawn',P )
        {    
    		if(P!=none)
    		{
    			loc = Canvas.Project(P.Location);
    			//Right here is where you would offset your Loc, by default it will use the movieplayer's top left corner as the "origin".
    			P.PlayerBeacon.SetViewPort(loc.X,loc.Y,120*RatioX,120*RatioX);   //I multiplied it by RatioX because you want to scale it depending on the window size.
            }
        }
    }
    I'm going to keep working on it and get my functionality in there, I'll let you know if I come up with any problems with this method.


    EDIT: The major problem I have is that it doesn't really move smoothly with the player's mesh in multiplayer if you have fast moving pawns and looks rather ugly when someone is strafing really fast back and fourth, this happened with Canvas too, so it's something to do with the Project function or something.

    Comment


      #3
      So what happens if i have a very slow PC and i can barely render at 10fps ?

      downloading this code for the HUD and stripping it down is much easier (my result is here: http://epicserver.nl/hp.jpg)
      http://udn.epicgames.com/Three/Devel...ndicators.html

      It keeps the last render time in mind, so that it may skip a few frames to catch up. Also, it keeps in mind that when you don't see that bot, you dont see the indicator either, or rather set the opacity to 0.0 with a lerp to blend out, and blend in when you can see him again.

      I thought flash would be easier too, but if you download that gem kit and implement it, it works immediately, then just modify it. you can add your textures to the material as well! (NOTE: MASKED images do not work in flash>scaleform>udk. images in flash MUST be 24-bit on export, and for materials in udk, TGA files with a alpha channel must be exported as 32 bit.)

      Otherwise it's just another tick that passes alot of things through to flash, and flash itself is not really good at performance if you have ALL game elements added to the HUD.

      if you do pass it on, go for a Struct with all needed info such as HP, name, level, and whatnot, and make an array that holds the struct, and in flash, create an array to instance the nameplates. So what you're doing is much more programming.

      but i am sure you can make it in flash, that is no problem. costs more time to do, that is all

      Comment

      Working...
      X