The second class to look at is Pawn. The Pawn class extends the Object and Actor class and is responsible for most in-game entities. PostBeginPlay() is the method that is called when all engine-side initialisation of an actor is complete, so we usually do setup in here. In the case of the player, this means also spawning a default controller.
In BubblePawn, we are also initalising a material instance, an instance of a Material created with the Material Editor and given some named parameters within that editor. Creating a Material Instance lets us vary those parameters on a per-instance basis without creating a whole new material. This is what this looks like in the content browser.
..and in the Material Editor.
Tick() is the routine called every time the game state is updated. Overriding it enables you to completely alter the behavior of a given Pawn. In our case we are simply moving the bubble upward and varying it's scale to give a throbbing effect.
We are using dynamic lighting in our environment and thus we define properties for dynamic lighting of the object in our default properties. To aid speed we also turn off as many collision checks as possible. The static mesh component that we add is the mesh drawn by the renderer for this Pawn. The components are simply entries in a dynamic array of components and may be created or destroyed dynamically. The sprite removal is to simply remove a default placeholder sprite automatically added by the system, as this is a placeable and can actually be placed in the editor in the scene.
class BubblePawn extends Pawn placeable;
var float accumulatedTime;
var StaticMeshComponent BubbleMesh;
var MaterialInstanceConstant MatInst;
simulated event PostBeginPlay()
{
local LinearColor specularColor;
accumulatedTime = FRand() * 180.0;
super.PostBeginPlay();
`log("spawning bubble ... ");
SpawnDefaultController();
MatInst = new(None) Class'MaterialInstanceConstant';
MatInst.SetParent(BubbleMesh.GetMaterial(0));
BubbleMesh.SetMaterial(0, MatInst);
MatInst.SetScalarParameterValue('LavaEmissiveMultiplier', FRand());
MatInst.SetScalarParameterValue('LavaSpecularPower', FRand() * 16.0);
specularColor = makeLinearColor(FRand(), FRand(), FRand(), 1.0);
MatInst.SetVectorParameterValue('LavalSpecularColor', specularColor);
}
event Tick(float DeltaTime)
{
accumulatedTime += DeltaTime;
SetDrawScale( 1.0 + 0.75 * Sin(accumulatedTime) );
Move(self.Velocity);
super.Tick(DeltaTime);
}
defaultproperties
{
WalkingPhysics=Phys_NONE
bCollideActors=false
bCollideWorld=false
DrawScale3D=(X=32.0,Y=32.0,Z=32.0)
bNoEncroachCheck = true
bIgnoreEncroachers = true
ControllerClass=class'LavaLamp.BubbleController'
Begin Object Class=DynamicLightEnvironmentComponent Name=BubbleLightEnvironment
ModShadowFadeoutTime=0.25
MinTimeBetweenFullUpdates=0.2
AmbientGlow=(R=.25,G=.25,B=.25,A=1)
AmbientShadowColor=(R=0.15,G=0.15,B=0.15)
LightShadowMode=LightShadow_ModulateBetter
ShadowFilterQuality=SFQ_High
bSynthesizeSHLight=TRUE
End Object
Components.Add(BubbleLightEnvironment)
Begin Object Class=StaticMeshComponent Name=InitialMesh
StaticMesh=StaticMesh'Lava.Meshes.Bubble'
bOwnerNoSee=false
LightEnvironment=BubbleLightEnvironment;
BlockRigidBody=false
CollideActors=false
BlockZeroExtent=false
BlockNonZeroExtent=false
End Object
Components.Add(InitialMesh);
Components.Remove(Sprite);
BubbleMesh = InitialMesh
name='Bubble';
}