Presentation is loading. Please wait.

Presentation is loading. Please wait.

Sega 500 Creating a New Game Jeff “Ezeikeil” Giles

Similar presentations


Presentation on theme: "Sega 500 Creating a New Game Jeff “Ezeikeil” Giles"— Presentation transcript:

1 Sega 500 Creating a New Game Jeff “Ezeikeil” Giles jgiles@artschool.com http://gamestudies.cdis.org/~jgiles

2 So far… Ok, we’ve looked at how to access properties of the game to influence how it looks and plays by modifying the HUD and passing around the Udamage. In short, we looked at the pieces…not the whole.

3 Today… We’re going to build on what we learnt so far and further modify the gametype rules and objects to create a complete new game. That’s right…a complete gametype.

4 So here’s the plan We’re going to run with the idea of the passing the UDamage around between players, but we’re going to change the *how*. First off, the player who is killed first will drop the doubler for others to pickup.

5 So here’s the plan The player who picks up the doubler is the only player who will be able to score points. Anytime a player is killed, the doubler is recharged and informs all players in the game.

6 So here’s the plan There will only ever be one of these *special* doublers in play at one time…we’re going to leave the regular pickup in game. Anytime a player who has, the doubler is killed, all players in the game are informed that it has been dropped.

7 So here’s the plan And, we’re going to modify the bot pathing information to give a high priority to acquiring this new damage doubler.

8 Getting started As with any project, we need to figure out what we need to build. Since we know the functionality we’re after, what kind things do we need to build or modify? Anyone?….anyone?

9 Getting started We can roll this all up into a set of 4 files to cover our game rules, our menu interface, a new item ( the doubler ) the messages.

10 The new Gametype This one is going to be similar to the one we’ve already created, but we’re going to modify it to influence the scoring. In short have the double to score points. This is also where we will cause the Doubler to be “dropped”.

11 The New UDamage We’ll have to create a new UDamage class so that is plays nicely in our world. It can’t respawn It sends messages to the players

12 The New Message class Sending messages in UT203 is done a bit differently to allow for network optimization. In effect, we don’t send a sting across the wire, but an index value…more on this shortly

13 The New int file Nothing really fancy here, just creating a new int file so that our game shows up in the menu as an option.

14 Building the Game Just for good OOP I’m building from scratch. Create a new package for our code and in goes our gametype. To keep it crazy, we’re going to derive from xDeathMatch.

15 Building the Game This will create the basics game definition, no rules yet… So lets get the int done so that we can select it from the menu and play test. [Public] Object=(Class=Class,MetaClass=Engine.GameInfo,Name=Eze.EzeGame, Description="DM|King of the hill MK2|xinterface.Tab_IADeathMatch |xinterface.MapListDeathMatch|false")

16 Building the Game And at this point, it will play like a regular deathmatch. So, lets go about changing that.

17 Building the Game As always, start simple. We’re going to override the Killed function again so that whenever a player is a doubler is created into the game.

18 Building the Game So what’s this Spawn thingy and how’s it work? function Killed( Controller Killer, Controller Killed, Pawn KilledPawn, class damageType ) { spawn(class'UDamagePack',,,KilledPawn.location); super.Killed( Killer, Killed, KilledPawn, damageType ); }

19 Building the Game Well, Spawn is defined in the actor class as: native(278) final function actor Spawn ( class SpawnClass, optional actor SpawnOwner, optional name SpawnTag, optional vector SpawnLocation, optional rotator SpawnRotation );

20 Building the Game Well, isn’t that just dandy, fortunate the header tells us a bit more: Spawn an actor. Returns an actor of the specified class, not of class Actor (this is hardcode in the compiler). Returns None if the actor could not be spawned

21 Building the Game Ah, ok…so a spawn a UDamage pickup….cool. But what’s this optional keyword stuff and how do I get it to be created where I want it?

22 Building the Game Well, time to consult the good old UDN: With the "optional" keyword, you can make certain function parameters optional, as a convenience to the caller. For Unreal Script functions, optional parameters which the caller doesn't specify are set to zero. For native functions, the default values of optional parameters depends on the function. For example, the Spawn function takes an optional location and rotation, which default to the spawning actor's location and rotation.

23 Building the Game In other words, you don’t have to pass in optional parameters…cool. So in our spawn call, we’re telling to create the new object at the pawns location. spawn(class'UDamagePack',,,KilledPawn.location);

24 Building the Game The result is, whenever you kill a bot, a doubler is spawned at that location. Cool….nes-pas?

25 Building the Game But this causes a small problem, very quickly we get a sea of damage doublers to play with. Not exactly what we want, time to add some game logic to fix that.

26 Building the Game Actually, the logic that we’re adding is surprisingly simple. We’re going to use a similar method to the last king of the hill gametype.

27 Building the Game In our global space for the gametype, we need a handle to the pawn who has the doubler: var pawn HasUDam;

28 Building the Game And then, in the killed function, we add some logic… if(killedpawn == HasUDam) { HasUDam=none; } if(HasUDam == none) { spawn(class'UDamagePack',,,KilledPawn.location); } else { HasUdam.EnableUDamage(30); } If the killed pawn had it, it’s now free for the taking No one has it so drop one with this kill Someone else has made a kill

29 Building the Game And this should work…But…like always, there’s a problem Any ideas? Anyone?….anyone?

30 Building the Game The damage doublers respawn…and this gonzo’s our “one doubler” rule. NUTZ!

31 Building the Game Don’t panic, we’re not dead yet. All this means is that we need a customized damage doubler class…not a problem. All we need to do is derive a new class from the current damage doubler.

32 Building the Game Digging this fella out of the class tree, we find it here, under pickups and derive a class off of it.

33 Building the Game And there are 2 areas of interest the defaults and the touch function. Don’t’ worry about the “auto state Pickup” line for now. We’ll be discussing states in great detail later on. For the moment, it’s sufficient to know that the touch function gets called like any other function.

34 Building the Game Copy and paste the entire state group from UDamagePack into your new class. auto state Pickup { function Touch( actor Other ) { local Pawn P; if ( ValidTouch(Other) ) { P = Pawn(Other); P.EnableUDamage(30); AnnouncePickup(P); SetRespawn(); }

35 Building the Game In order to prevent the respawn, there’s one line we need to kill and one we need to add. Comment out or delete the SetRespawn line. function Touch( actor Other ) { local Pawn P; if ( ValidTouch(Other) ) { P = Pawn(Other); P.EnableUDamage(30); AnnouncePickup(P); SetRespawn(); }

36 Building the Game And add a call to the destroyed function. In effect, when the object is pickup up, the pickup item is removed from the game. function Touch( actor Other ) { local Pawn P; if ( ValidTouch(Other) ) { P = Pawn(Other); P.EnableUDamage(30); AnnouncePickup(P); //SetRespawn(); Destroy(); }

37 Building the Game And in the defaults, we just change the pickup message PickupMessage="Eze DOUBLE DAMAGE!"

38 Building the Game And now going back into the gametype, we change the line where we spawn he UDamagepickup to spawn our own. spawn(class'EzeUDam',,,KilledPawn.location);

39 Building the Game HAZA!!!! It works! Pickup message Broadcast message… Well talk about this in a minute

40 Building the Game Now, we need to do one last thing to ensure that we can’t have multiple EzeUDam’s in play. In our game type, we create a global handle to it. var EzeUDam dam;

41 Building the Game And in our killed function, we modify it to check if anyone has it… Remember, Spawn returns us an object. if(HasUDam == none && dam == none) { //toss the UDamage in to the air dam=spawn(class'EzeUDam',,,KilledPawn.location);

42 Building the Game And don’t forget to add this line to the EzeUdam’s Touch function. What were doing here is accessing the gametype and setting this parameter to which pawn made the pickup. EzeGame(level.Game).HasUDam=P;

43 Building the Game All that this line does is access the current game and type cast it into our gametype so we can access the HasUDam parameter. And, yes. We really should do some sanity checking here…Well cover this when we look at he “isa” function. EzeGame(level.Game).HasUDam=P;

44 Building the Game Great! Now we on ever have on in play. But this is kind of boring…just spawning the pickup like that… Now that we have a hold of the object, what say we manipulate it some…

45 Building the Game Just by adding a few lines to this function, we can fling it into the air when the player is killed. if(HasUDam == none && dam == none) { dam=spawn(class'EzeUDam',,,KilledPawn.location); dam.Velocity= 500*VRand(); dam.Velocity.Z= RandRange(500,800); dam.SetPhysics(PHYS_Falling); }

46 Building the Game So what’s going on? Well, we’re changing some of its physics properties to give it a velocity dam.Velocity= 500*VRand(); dam.Velocity.Z= RandRange(500,800);

47 Building the Game The VRand function returns to us a random direction. In fact a unit vector. Multiply this by a scalar to determine just where to toss it. RandRange(500,800); gives us a number between 500 and 800 for the height. We over ride this since we don’t want to throw it downwards

48 Building the Game And since we want to have this thing behave as thought there is gravity affecting it, we need to change it’s physics properties. dam.SetPhysics(PHYS_Falling);

49 Building the Game Now, all the physics types are defined in the actor class…as you can see there are just a few to choose from. var(Movement) const enum EPhysics { PHYS_None, PHYS_Walking, PHYS_Falling, PHYS_Swimming, PHYS_Flying, PHYS_Rotating, PHYS_Projectile, PHYS_Interpolating, PHYS_MovingBrush, PHYS_Spider, PHYS_Trailer, PHYS_Ladder, PHYS_RootMotion, PHYS_Karma, PHYS_KarmaRagDoll, PHYS_Hovering, PHYS_CinMotion, } Physics;

50 Building the Game Also, although we can see the physics property in the editor, it’s defined as const so the assignment operator will not work. You have to use the SetPhysics function.

51 Building the Game And now to make the object land properly, we need to reset it’s physics value to PHYS_Rotating (it default) to make it spin properly. Fortunately, there’s a Landed function defined for us…

52 Building the Game This function gets called when an object stops moving…in this case when it lands. Hence, we need to override this function too.

53 Building the Game All we need to worry about here is to call the parent class where most of the functionality lives, and set the physics… function Landed(vector HitNormal) { super.Landed(HitNormal); SetPhysics(PHYS_Rotating); }

54 Building the Game Now ain’t that just a bit more interesting… Body goes one way, the pickup another Isn’t math grand

55 Building the Game Lastly, we need to tell all the players that the doubler has been dropped/picked up/ recharged…whatever. We send them a message to do so.

56 Building the Game Now as I mentioned, the way this works is a *bit* different. You don’t send the message itself across the wire but an index value. E.g. The message is ALREADY present on the other machine.

57 Building the Game This has to do with network optimisations since it’s much smaller to send a single in value that it is an entire string of several characters.

58 Building the Game From the LocalMessage header: LocalMessages are abstract classes which contain an array of localized text. The PlayerController function ReceiveLocalizedMessage() is used to send messages to a specific player by specifying the LocalMessage class and index. This allows the message to be localized on the client side, and saves network bandwidth since the text is not sent.

59 Building the Game Actors (such as the GameInfo) use one or more LocalMessage classes to send messages. The BroadcastHandler function BroadcastLocalizedMessage() is used to broadcast localized messages to all the players.

60 Building the Game So what does this mean to us? Well, we need to create a local message class, which we derive from LocalMessage.

61 Building the Game In this class, we essentially have a couple of strings for our text and assign them in the defaults. var localized stringGottheDam; var localized stringDroppedtheDam; var localized stringrecharged; DefaultProperties { GottheDam="The Doubler has been picked up!" DroppedtheDam="The Doubler has been picked Dropped!" recharged="The Doubler has been Recharged!" bFadeMessage=True PosY=0.7 }

62 Building the Game Now, we need a way of accessing this index value. Localized messages come with a get sting function just for this…it’s really not much more than a switch statement.

63 Building the Game Well play with the optional PlayerReplicationInfo parameters at a later date…for now, we just need to know that they are there. static function string GetString(optional int Switch, optional PlayerReplicationInfo RelatedPRI_1, optional PlayerReplicationInfo RelatedPRI_2, optional Object OptionalObject)

64 Building the Game And here’s my function body… switch(Switch) { case 0: return Default.GottheDam; break; case 1: return Default.DroppedtheDam; break; case 2: return Default.recharged; break; }

65 Building the Game In effect, when this function get called, it receives an index and returns a specific string…AKA our message.

66 Building the Game That being said, we just add a line to each important function In the EzeUDam touch: BroadcastLocalizedMessage( class'EzeGameMSG', 0 );

67 Building the Game What this is doing is saying “send a message to everyone…make it an EzeGameMSG and get the string from index 0” BroadcastLocalizedMessage( class'EzeGameMSG', 0 );

68 Building the Game Sends message index 0 to the screen

69 Building the Game And then put one in the landed function for index 1 and in the gametype, one for index 2…when the doubler gets recharged.

70 Building the Game Sweetness! We’re almost there…But there’s one last thing…The dumb bots run right past the pickup! Needless to say, this is kinda lame.

71 Building the Game So somehow, we need to add it to the navigation network. And believe it or not, its an easy fix…a one liner as a matter of fact.

72 Building the Game If you root through the EzeUDam’s parent classes, you’ll eventually find a native function in the pickup base class called AddToNavigation. And it does just that, it adds this object to the navigation network.

73 Building the Game So, I added this to my Landed function, which now looks like: function Landed(vector HitNormal) { super.Landed(HitNormal); SetPhysics(PHYS_Rotating); AddToNavigation(); BroadcastLocalizedMessage( class'EzeGameMSG', 1 ); }

74 Building the Game And lastly, you may want to turn up the likelihood of the bots desire to pickup the EzeUDam. To do so, in the EzeUDam Class, just turn up this parameter in the defaults MaxDesireability=4.0 //default is 2.0

75 Building the Game And lastly, we need too change the scoring. This was a real simple override of the gametype.

76 Building the Game In the DeathMatch class, there’s a function called score kill. All we need to do is add an if condition it. function ScoreKill(Controller Killer, Controller Other) { if(Killer.Pawn== HasUDam) super.ScoreKill(Killer, Other); }

77 Building the Game And now, only the player with the doubler can score points on a kill.

78 Voila! One complete gametype with affect on the game rules and Bot AI. How you found this interesting…

79 Next time We’re going to start manipulating the HUD some more to build our radar.


Download ppt "Sega 500 Creating a New Game Jeff “Ezeikeil” Giles"

Similar presentations


Ads by Google