For direct access use https://forums.oldunreal.com
It's been quite a while since oldunreal had an overhaul, but we are moving to another server which require some updates and changes. The biggest change is the migration of our old reliable YaBB forum to phpBB. This system expects you to login with your username and old password known from YaBB.
If you experience any problems there is also the usual "password forgotten" function. Don't forget to clear your browser cache!
If you have any further concerns feel free to contact me: Smirftsch@oldunreal.com

Sprite Animation

The section related to UnrealScript and modding. This board is for coders to discuss and exchange experiences or ask questions.
User avatar
LannFyre
OldUnreal Member
Posts: 157
Joined: Fri Mar 13, 2015 7:01 am

Sprite Animation

Post by LannFyre »

I am having a. . .  Bitmap issue I think?

I'll post my understanding of the code, but first here is the issue I am having:

Code: Select all

Anims[i].Animated.Texture = Anims[i].Animation.GetByPosition(1); // Error, Type mismatch in '='
I am having a type mismatch error, in that an actor is attempting to set another actor's texture to a certain texture for each tick, conditions varying and applying.

If you're with me beyond that, here are the three actors:

Code: Select all

class SpriteAnimation expands Object;

struct AnimNotify
{
    var name CallOnFrame;
    var int PlayOnFrame;
};
var float DefaultAnimTime;
var array AnimFrames;
var array AnimNotifies; // Accesses the data DIRECTLY FROM AnimNotify


final function BitMap GetByPosition( float InPos)
{
    local int aSize;
    aSize = Array_Size( AnimFrames);
    return AnimFrames[ int(InPos*float(aSize)) % aSize ];
}

Code: Select all

//=============================================================================
// SpriteAnimationManager.
// In charge of updating the animations independantly, pooled into an animation manager.
//=============================================================================
class SpriteAnimationManager expands Actor;

struct AnimRegister
{
    var Actor Animated;
    var SpriteAnimation Animation;
    var float AnimRate;
    var float CurPosition;
    var int RepeatCount;
    var bool bLooping;
    var bool bNotify;
    var name FinishNotify;
}; // Establish an AnimRegister

var private array Anims;

event Tick( float DeltaTime)
{
    local int i, Max;
    local float OldPosition;
    local bool bRemove;

    Max = Array_Size( Anims);
    for ( i=0 ; i= 1) ) // Animation has completed a cycle
        {
            if ( !Anims[i].bLooping && (Anims[i].RepeatCount-- = 0 )
        Array_Remove( Anims, Idx, 1);
    return Idx >= 0;
}

function ChangeRate( Actor sAnimated);
function SetNotifyState( Actor sAnimated, bool bEnable, optional name NewOptNotify);

//RepeatCount = -1 means loop (default = 0, one shot)
// Rate is (1/Time) anim takes to complete, feel free to call the function like that
// EndNotify = '' (or unspecified) means no callback
function PlayAnimation( Actor sAnimated, SpriteAnimation sAnimation, float Rate, optional int RepeatCount, optional name EndNotify )
{
    local int Num;

    Num = GetByActor( sAnimated);
    if ( Num == -1 )
    {
        Num = Array_Size( Anims);
        if ( !Array_Insert( Anims, Num, 1) )
        {
            Log("ERROR: Failed to allocate animation register for "$sAnimated.Name);
            return;
        }
    }
    Anims[Num].Animated = sAnimated;
    Anims[Num].Animation = sAnimation;
    Anims[Num].AnimRate = Rate;
    Anims[Num].CurPosition = 0;
    Anims[Num].bLooping = (RepeatCount == -1);
    Anims[Num].RepeatCount = RepeatCount;
    Anims[Num].bNotify = (EndNotify != '');
    Anims[Num].FinishNotify = EndNotify;
      sAnimated.Texture = sAnimation.GetByPosition(0); // Error, Type mismatch in '='
}

// return -1 means no index, no animation for this actor
// Good way to see if an actor is being animated by THIS manager
final function int GetByActor( Actor sAnimated)
{
    local int i;

    for ( i=Array_Size(Anims)-1 ; i>=0 ; i-- )
        if ( Anims[i].Animated == sAnimated )
            return i;
    return -1;
}

Code: Select all

class DummyAnimActor expands Actor;

#exec OBJ LOAD FILE=..\Textures\RPG_Test_Sprite.utx

var SpriteAnimationManager AnimManager;
var SpriteAnimation WalkTest;

//Actor has been summoned
event PostBeginPlay()
{
      ForEach AllActors (class'SpriteAnimationManager', AnimManager) //Find a animmanager
            break;
      if ( AnimManager == None ) //Create if not found
            AnimManager = Spawn(class'SpriteAnimationManager');

      //Hardcoded create
      WalkTest = new( None, 'DummyAnimationObj') class'SpriteAnimation'; // ERROR: Error, Type mismatch in 'new' parent object
      //Hardcoded time
      WalkTest.DefaultAnimTime = 0.8;
      //Hardcoded frames (dynamic arrays should allow this kind of accessors)
      WalkTest.AnimFrames[0] = Texture'DownRightWalk3';
      WalkTest.AnimFrames[1] = Texture'DownRightWalk4';
      WalkTest.AnimFrames[2] = Texture'DownRightWalk5';
      WalkTest.AnimFrames[3] = Texture'DownRightWalk6';
      WalkTest.AnimFrames[4] = Texture'DownRightWalk7';
      WalkTest.AnimFrames[5] = Texture'DownRightWalk8';
      WalkTest.AnimFrames[6] = Texture'DownRightWalk1';
      WalkTest.AnimFrames[7] = Texture'DownRightWalk2';
      //Hardcoded two notifies
      Array_Insert( WalkTest.AnimNotifies, 0, 2);
      WalkTest.AnimNotifies[0].PlayOnFrame = 2;
      WalkTest.AnimNotifies[0].CallOnFrame = 'FootstepSound';
      WalkTest.AnimNotifies[1].PlayOnFrame = 6;
      WalkTest.AnimNotifies[1].CallOnFrame = 'FootstepSound';
      SetTimer( 10, true);
}

event Timer()
{
      AnimManager.PlayAnimation( self, WalkTest, 1, 3, 'EndWalk' );
}
If my understanding of what he has written is correct, in this example DummyAnimActor spawns, SpriteAnimationManager is instantiated then SpriteAnimation.  SpriteAnimationManager runs on tick, first establishing an array then either checking if an animation needs to be removed or if the animation should cycle.  If it should cycle X amount of times, do so until X is met then terminate.  You have a few functions that can be called, either choosing to StopAnimation() or PlayAnimation().

Now here we are at a part of where I feel my understanding of code is too shaky to be confident.  SpriteAnimation is a smaller actor, which is supposed to contain an array of bitmaps and AnimNotifies (structs, containing a name [CallOnFrame] and int [PlayOnFrame]).  This is where the issue lies, in SpriteAnimation with its only function, GetByPosition, which is supposed to return a float.  At this point, I am left wondering what the issue is, but what should be happening is the current actor's texture is set to what ever should be occupying the result of GetByPosition's math, in its AnimFrames Bitmap Array.  DummyAnimActor has set what should be in AnimFrames.
Last edited by LannFyre on Wed Nov 09, 2016 10:12 pm, edited 1 time in total.
i tryin'a be a gud boi
User avatar
.:..:
OldUnreal Member
Posts: 1637
Joined: Tue Aug 16, 2005 4:35 am

Re: Sprite Animation (Cross post, I am sorry)

Post by .:..: »

Well from first look, GetByPosition returns BitMap and not Texture. Since BitMap is a parent class of Texture, you need to metacast it to Texture:

Code: Select all

Anims[i].Animated.Texture = Texture(Anims[i].Animation.GetByPosition(1));
But then again, why use Bitmap in the first place since there is no practical use of it?

Also, at your dummy DummyAnimActor, why not instead of generating SpriteAnimation object in code, define it in defaultproperties:

Code: Select all

defaultproperties
{
    Begin Object Class=SpriteAnimation name=DummyAnimationObj
            DefaultAnimTime=0.8
            AnimFrames.Add(Texture'DownRightWalk3')
            AnimFrames.Add(Texture'DownRightWalk4')
            AnimFrames.Add(Texture'DownRightWalk5')
            AnimFrames.Add(Texture'DownRightWalk6')
            AnimFrames.Add(Texture'DownRightWalk7')
            AnimFrames.Add(Texture'DownRightWalk8')
            AnimFrames.Add(Texture'DownRightWalk1')
            AnimFrames.Add(Texture'DownRightWalk2')
            AnimNotifies.Add((PlayOnFrame=2,CallOnFrame='FootstepSound'))
            AnimNotifies.Add((PlayOnFrame=6,CallOnFrame='FootstepSound'))
    End Object
    WalkTest=DummyAnimationObj
}
Last edited by .:..: on Sun Sep 04, 2016 7:14 am, edited 1 time in total.
1823223D2A33224B0 wrote:...and now im stuck trying to fix everything you broke for the next 227 release xD :P
(ಠ_ಠ)
User avatar
LannFyre
OldUnreal Member
Posts: 157
Joined: Fri Mar 13, 2015 7:01 am

Re: Sprite Animation (Cross post, I am sorry)

Post by LannFyre »

Thanks mate, I actually never even considered it could be a typecasting issue. The actor is now working, so would anyone like to see an animated Xenogears character sprites in Unreal?
https://youtu.be/CbfaRsJwkD4
i tryin'a be a gud boi
User avatar
gopostal
OldUnreal Member
Posts: 1007
Joined: Thu Jul 31, 2008 9:29 pm

Re: Sprite Animation (Cross post, I am sorry)

Post by gopostal »

I'm kind of spitballing here but I have a question about method. If this were me I'd consider creating a pawn subclass that calls texture assignments depending on the action of the pawn. Something like "if physics=phys_flying then set the sprite texture to jumping". If the sprite is running then set it to a looping run texture, etc. Bob and I talked at length about this and it wouldn't be too tough to create a master sprite pawn that you could create many textures to assign to it, creating any number of monsters/enemies.

Is it the fact that the looping rate can't be absolutely controlled that makes your method more appealing?
I don't want to give the end away
but we're all going to die one day
User avatar
LannFyre
OldUnreal Member
Posts: 157
Joined: Fri Mar 13, 2015 7:01 am

Re: Sprite Animation (Cross post, I am sorry)

Post by LannFyre »

That's the entire idea behind how the sprites will be displayed on pawns and players actually. Right now, DummyAnimPawn is just being used to see the other two actors in action to preview how sprite manager functions can be called.

As far as I know, sprites are going to be loaded through either import commands or by loading .INI files (though I'm waiting on Higor for that, he is looking at source code as I code in the ability for sprites to be rotated properly in-game). They will just be swapped out depending on player movement or pawn movement and direction. We'll see where that goes, both will have to have different conditions due to player control, but I think it is possible.

> Have group of imported sprites in pawn
> Assign specific imported sprites to arrays (ie. WalkForward, StandForward, JumpForward)
> Change array number in supporting sprite manager depending on how many sprites are in a group, to decide how they should play (if it has 1 frame, constantly loop one frame, otherwise execute all other frames then loop sequence, or don't loop, which can be called via calls to SpriteAnimationManager from pawn or PlayerPawn, or any actor real that spawns the two).

I'm also going to be studying maths operators so I can set make it so sprites that are animated will change to a rotated sprite depending on the x and y coordinates of the camera. However I am not a math guy, so this may also take some time for me to understand. Because I have to take into account the position of the pawn tied to SpriteAnimationManager (but not the manager itself) and the local player camera. What I have to do when checking the positions of the camera and pawn will take place in SpriteAnimationManager, with the SpriteAnimationManager checking camera's position: if the pawn is diagonal or in any of four directions to the pawn, it should change accordingly. Think of Doom and how sprite rotation works in that game, exactly like this person did: https://www.youtube.com/watch?v=juBmjE3PAbI
i tryin'a be a gud boi
User avatar
LannFyre
OldUnreal Member
Posts: 157
Joined: Fri Mar 13, 2015 7:01 am

Re: Sprite Animation (Cross post, I am sorry)

Post by LannFyre »

Okay so sprite animation works, I have to do some debugging to figure out why sprite animation notifies on frame are crashing my game though. lol

That isn't what I want to bring here though. I have a theory that I'd like some input on. Okay so I have the actor that already handles the sprite animation of actors, and a Native that would hold necessary textures for the sprite animation manager. Now that actor that is handling the sprite animation is running on tick:

Code: Select all

event Tick( float DeltaTime)
{
    local int i, j, Max;
    local float OldPosition;
    local bool bRemove;
      local int NewFrame;
      local name NotifyFunc;
      local string RTN;
And I need to do sprite billboarding for pawns. Sprites are being displayed as they would normally, always facing the player but they don't change direction because they would need an array of textures to decide what should face toward you, which has been solved. The issue now is that I am not sure what math would need to be done in order to figure out where the camera is located in relation to the pawn in question. I have a way to access said pawn:

Code: Select all

struct AnimRegister
{
    var Actor Animated; // This would normally be a pawn
    var SpriteAnimation Animation;
    [...]
}; // Establish an AnimRegister
And in that pawn, I can find a camera. Or to prevent looking for functions in pawns that don't have them, I can do a foreach to find a camera and throw in a boolean function check for sanity. But this is where my issue is. While I can gather the XYZ of both camera and pawn, I don't know how to judge rotation. I posted a link in my previous post (above this one) which exemplifies this point to a T. So my question is after I have gotten the XYZ and PITCH/YAW/ROLL of both actors, how do I compare their rotations and arbitrary coordinates to each other? Comparing X/Y coordinates is as simple as an if elseif list.

My idea so far was to have the actor with Tick in it check the X/Y coordinates of whatever actor that is stored as "Animated" in the above struct, compare it to where the camera is, and then check the rotation of both and with both sets of data decide if the camera is diagonal or aligned on an axis to the pawn, but then I don't know what I'd do with rotation. If I can get someone to point out how to do this, I can do the rest. This is a maths question I assume. While I did some work with the stationary turret from Unreal Tournament, all I can do is sit and gawk at some rotational code and wonder if Rotator(pawn - camera) would be how I make this work. Any thoughts? Here is a snippet of code from the stationary turret:

Code: Select all

            else
            {
                  DesiredRotation = rotator(Enemy.Location - Location);
                  DesiredRotation.Yaw = DesiredRotation.Yaw & 65535;
                  if (LineOfSightTo(Enemy))
                  {
                        if (bFired && DesiredRotation.Pitch < 2000 &&
                              (Abs(DesiredRotation.Yaw - (Rotation.Yaw & 65535)) < 1000 ||
                               Abs(DesiredRotation.Yaw - (Rotation.Yaw & 65535)) > 64535))
                        {
                              Shoot();
                        }
                        else
                        {
                              bFired = true;
                              SetTimer(FireRate, true);
                        }
                  }
            }
i tryin'a be a gud boi
User avatar
LannFyre
OldUnreal Member
Posts: 157
Joined: Fri Mar 13, 2015 7:01 am

Re: Sprite Animation

Post by LannFyre »

A bump to the topic, found out it was a loop that would continuously attempt to process information.  So now I want to start working on sprite rotation, I have to make something on a test actor so their animation code is always gathering their relative position to the local camera to set their rotation.  Here is what I have so far, works in four directions and if need be I'll add a simpler rotator subtraction check to make sure the camera position is well registered.  I need to divide the sections up into 8, so the second rotator actually might be useful.

Code: Select all

            TargetActor = pawn(other);
            GetAxes( TargetActor.Rotation, X, Y, Z );
            //log(""$X);
            //log(""$Level.TimeSeconds);
            v = LocalCam.location - Anims[i].Animated.location;
            r = rotator(v);
            /*if (r.yaw >=  && r.yaw =  && r.yaw =  && r.yaw =  && r.yaw =  && r.yaw =  && r.yaw =  && r.yaw =  && r.yaw
Last edited by LannFyre on Thu Nov 10, 2016 9:08 am, edited 1 time in total.
i tryin'a be a gud boi
User avatar
LannFyre
OldUnreal Member
Posts: 157
Joined: Fri Mar 13, 2015 7:01 am

Re: Sprite Animation

Post by LannFyre »

Sprite animation is working on and now has directional sprites. I need to implement more than basic math in my script when needed. After I get the sprite animation code into my custom pawn, I want to see about editing the code I have already written and see if I can't improve what I have. That being said, no video to show off the sprite rotation this time, due to my hard drive being close to dying (had a scare recently). That being said, check out this sprite texture I'm working on:

[url][/url]
i tryin'a be a gud boi

Return to “UScript Board”