Seriously!

Go Back   Seriously! Forums > Serious Sam Series > Serious Sam Classic > Serious Sam Classic Workshop > Serious Sam Classic Mods

Serious Sam Classic Mods General mod discussion for Serious Sam 1 goes in this forum, also any tutorials/tutorial requests that have not been added to Serious Sam Wiki yet.

Reply
 
Thread Tools Search this Thread Rate Thread Display Modes
Old 01-01-2003, 04:50 AM   #1   Add To Ignore List  
Kamikaze
 
hot_sleeper's Avatar
 
Joined: Dec 2002
Location: Australia
 
hot_sleeper is offline
Default Mapping - Random Selection

Random Selection Tutorial for Serious Sam


Have you ever been bored by a FPS level that was exactly the same every time you played?
Ever wanted to design a level that could be different each time the player starts?

Then this tutorial is for you.


Introduction

The basic idea is to find or create a random value that can be captured and used to adjust various things around the map.

There are not many random values available to mappers and very few ways to manipulate them without code. The only sources of random data come from the players input and choices. All the Enemy AI is totally deterministic. If the player is not there to insert some chaos the Enemy should be pretty predictable. This is both a good thing and a bad thing. Its a good thing for debugging a level, but a bad thing for replay-ability.

So how to capture some of the players randomness and use it?


There are a couple of potential angles here. We could try to get the player to make a choice. For instance put a couple of touch fields in their path and see which one they touch first. Or some variation on this. The problem is that the player may always make the same choice and there is very little you can do about that. Except make the path more complicated.... You can make the path as complicated as you wish, which will slow the player and possibly add a little more randomness. Eventually the player will figure out a successful path and stick to it. There goes your randomisation!

There is one other problem that has to be taken into account. Granularity or resolution. How may touch fields will you need?
How much space will each touch field take up. If each touch field is 2X2 and you want to select between 15 options then you need space to arrange 15 touch fields in such a way that the player has equal chance of touching any of them first. Difficult. How long will the player enjoy jumping through your hoops just to generate a random number? This method is still, when all is said and done, predictable. Not what we want!


Another option is to use time. How long does it take the player to get from one point to another? If its not a straight run, then it should always be slightly different. (Plus or minus a couple of seconds for complex paths with some obstacles or enemies.)
This also has the benefit of being much easier to capture. All you need is a touch field or a switch at the start and the end and a way to find the time difference in between.

This brings us to the problem. When mapping, you have very little ability to manipulate anything like logic or numbers. I demonstrated in an earlier tutorial how to use the trigger units to represent digital logic. By using similar principles I will demonstrate how to capture and use a random time interval.



Setup.


To keep things simple we will build a system that can generate a random selection from five possibilities. It will be very simple to extend to any number of selections. There are a couple of things to keep in mind.

Depending on the number of selections relative to the resolution of your sampling, will determine how random the system truly is. If you have a very low resolution, the randomness of the system will go down. This is easy to adjust.


1) Make the touch fields
The first part of the demo world is the two touch field Entities. Name these TF_Start and TF_Stop. Each has a trigger just for simplicity. Name the triggers Trig_Start and Trig_Stop.

Set the Properties like this...

TF_Start:EnterTarget->Trig_Start
TF_Stop:EnterTarget->Trig_Stop

This notation means...

Set the TF_Start touch field entity's "Enter Target" property to Trig_Start.
Set the TF_Stop touch field entity's "Enter Target" property to Trig_Stop.

2) Make the clock.
If you have done any digital logic course for a math class or a computer class this will be familiar. If not, a clock is something that releases a pulse at regular intervals. It does not keep time.
We construct a clock out of two trigger entities. Call One Trig_Clock and the other Trig_Clock_Delay.

Set the properties...

Trig_Clock:Target01->Trig_Clock_Delay
Trig_Clock_Delay:Target01->Trig_Clock
Trig_Clock_Delay:Wait->1

This operates on the principle of feedback. Trig_Clock sends a pulse to Trig_Clock_Delay. Trig_Clock_Delay waits 1 second then sends it back. This causes Trig_Clock to repeat the cycle. And we have a clock. You can adjust the resolution of your system by setting the wait property of Trig_Clock_Delay to a higher or lower value.



3) Connect the start and stop touch fields to the clock.
Easy...

Trig_Start:Target01->Trig_Clock
Trig_Stop:Target01->Trig_Clock
Trig_Stop:EventTargetType01->Deactivate Event

The start trigger starts the clock ticking, and the stop trigger deactivates it.
The arrangement I have described will make this a one use setup. If you want to use it number of times or make it start and stop each time the player walks through each touch field just add send an activate event to Trig_Clock.



Now we get to the complex part. How to use this to measure a random value.
If you were doing this in code, you may measure the time difference, interpret the value against the number of random options you wished to select amongst, then do whatever the random option was.

Since we have no way to manipulate time, we will do this in a different way. The basic idea is to have a trigger that represents each of the random options.
These will be arranged in a continuous loop. We will make them active, one at a time, leave them active for a short period and then switch to the next one. When the player reaches the stop Touch field, whichever option trigger is active is the winner.


The option triggers are the easy part. The tricky part of the system is the selectors that swap from one option to the next. These will be driven by the ticking of our clock.

4) Building the selectors.

Each selector will have to perform a couple of tasks.
* Switch the previous Option Trigger into the Deactive State.
* Switch the Current Option Trigger into the Active state.
* Switch the next Selector into the Active State.
* Switch Itself into the Deactive State.

The last step is a little unpredictable so I have used a second trigger entity with each selector to Make sure each selector is Deactivated correctly.

To create a selector you will need two Triggers name them Trig_Selector and Trig_Selector_Off

Set the properties...

Trig_Selector:Target01->Trig_Selector_Off
Trig_Selector_Off:Target01->Trig_Selector
Trig_Selector_Off:wait->0.001
Trig_Selector_Off:Event Type Target01-> Deactivate event

This will cause the Trig_Selector_Off to switch the Trig_Selector into the Deactive state 1 millisecond after the Trig_Selector has finished its work.

You will need a selector and selector_off trigger Pair for each Random option you want.

In this tutorial I am using five. Because it makes it clearer what is going on via repetition.

So build each of the selector trigger pairs and spread them out neatly. Name them appropriately (Trig_selector_01, Trig_selector_02 etc.)


5) Connecting the selectors in a ring.
Remember that each of the selectors will turn its neighbour on ready for the next clock pulse. So the first one turns the second on. The second turns the third on, the third turns the fourth on and the fifth turns the first on. And it all starts again.


Set the properties of the selectors

Trig_Selector1:Target02->Trig_Selector2
Trig_Selector1:Event type Target02->Activate Event

Trig_Selector2:Target02->Trig_Selector3
Trig_Selector2:Event type Target02->Activate Event

Trig_Selector3:Target02->Trig_Selector4
Trig_Selector3:Event type Target02->Activate Event

Trig_Selector4:Target02->Trig_Selector5
Trig_Selector4:Event type Target02->Activate Event

Trig_Selector5:Target02->Trig_Selector1
Trig_Selector5:Event type Target02->Activate Event

Now because we only want one selector active at a time we will set all but one selector to the Deactive State. Its up to you which one you leave active, it should not matter unless you have the resolution of the clock set too low.
I choose to leave Trig_Selector1 Active.


Set the active properties of the selectors...

Trig_Selector2:Active->False
Trig_Selector3:Active->False
Trig_Selector4:Active->False
Trig_Selector5:Active->False


6) Connect the clock to the selectors.

The clock must send a pulse to each selector. If the selector is active it will do its work. If itís deactivated it will ignore the clock pulse.

Set the Trig_Clock properties...

Trig_Clock:Target02->Trig_Selector1
Trig_Clock:Target03->Trig_Selector2
Trig_Clock:Target04->Trig_Selector3
Trig_Clock:Target05->Trig_Selector4
Trig_Clock:Target06->Trig_Selector5



7) Making stuff happen.

In the demo world I have provided two versions of the system. One has the selectors activating and deactivating moving brushes, so you can see exactly what is happening. The other has the selectors activating and deactivating option triggers. The state of the system only becomes obvious once the player passes through the stop touch field. Itís quite possible to integrate both theses systems, and would be quite useful for testing and debugging purposes. But for clarity of illustration I have kept them separate. I will first describe setting up the moving brush version. Then describe setting up the Trigger version.



7a) Setting up moving brushes.

Drag in a moving brush and add a small simple CSG solid to it. (2x2x1 is fine)
Clone the brush 4 times to create 5 Moving brush entities.
Space them out so there is lots of room to see each of them clearly. Arranging them in order is a good idea.
Create two markers (keyboard d then move the Moving brush and hit d again)
Name the moving brushes MB_01, MB_02 etc.

Now connect the Selectors to the moving brushes....

Trig_Selector1:Target03->MB_01
Trig_Selector1:Event type Target03-> Start Event
Trig_Selector1:Target04->MB_05
Trig_Selector1:Event type Target04->Stop Event

The trigger will send a start event to the current moving brush and a stop event to the previous moving brush.

Set all the other selectors...

Trig_Selector2:Target03->MB_02
Trig_Selector2:Event type Target03-> Start Event
Trig_Selector2:Target04->MB_01
Trig_Selector2:Event type Target04->Stop Event

Trig_Selector3:Target03->MB_03
Trig_Selector3:Event type Target03-> Start Event
Trig_Selector3:Target04->MB_02
Trig_Selector31:Event type Target04->Stop Event

Trig_Selector4:Target03->MB_04
Trig_Selector4:Event type Target03-> Start Event
Trig_Selector4:Target04->MB_03
Trig_Selector41:Event type Target04->Stop Event

Trig_Selector5:Target03->MB_05
Trig_Selector5:Event type Target03-> Start Event
Trig_Selector5:Target04->MB_04
Trig_Selector5:Event type Target04->Stop Event



You can now test the system. Drag in a player start Entity and walk through the start touch field. Watch the moving brushes and you should see them move in sequence. Walk through the stop touch field and you should see one of the moving brushes continue to move while the others have stopped.

This concludes the construction of the moving brush version of the system. The steps described below are for the construction of the second version. They follow step 6.


7b) Building the Option Triggers

Each of the options is represented by a Trigger Entity. They will be named Trig_Option1, Trig_Option2 etc.

Add another trigger Entity and call it Trig_Option_Test. This will represent the final test to see which random option has been selected.(This can be optimised away if desired, but helps clarify the description)

Now similar to the setup in step 7a, we will connect the selectors to the option trigger entities.

Trig_Selector1:Target03->Trig_Option1
Trig_Selector1:Event type Target03->Activate event
Trig_Selector1:Target04->Trig_Option5
Trig_Selector1:Event type Target04->Deactivate event

This will activate the current Option and deactivate the previous option. Set the rest of the selectors similarly.

Trig_Selector2:Target03->Trig_Option2
Trig_Selector2:Event type Target03->Activate event
Trig_Selector2:Target04->Trig_Option1
Trig_Selector2:Event type Target04->Deactivate event

Trig_Selector3:Target03->Trig_Option3
Trig_Selector3:Event type Target03->Activate event
Trig_Selector3:Target04->Trig_Option2
Trig_Selector3:Event type Target04->Deactivate event

Trig_Selector4:Target03->Trig_Option4
Trig_Selector4:Event type Target03->Activate event
Trig_Selector4:Target04->Trig_Option3
Trig_Selector4:Event type Target04->Deactivate event

Trig_Selector5:Target03->Trig_Option5
Trig_Selector5:Event type Target03->Activate event
Trig_Selector5:Target04->Trig_Option4
Trig_Selector5:Event type Target04->Deactivate event



Now hook up the Trig_Option_Test Entity.


Trig_Stop:Target02->Trig_Option_Test

Trig_Option_Test:Target01->Trig_Option1
Trig_Option_Test:Target02->Trig_Option2
Trig_Option_Test:Target03->Trig_Option3
Trig_Option_Test:Target04->Trig_Option4
Trig_Option_Test:Target05->Trig_Option5

When the Player crosses the stop Touch field, the stop trigger will send a pulse to this Trigger, which will trigger all the Options. Only one should be active and it will be the Lucky winner.


To show what has happened we will use moving brushes again.

Create five moving brushes with short paths as above. Name them MB_01, MB_02 etc.


Hook the Option triggers to the

Trig_Option1:Target01->MB_01
Trig_Option1:Event type Target01->Start Event

Very simply, if this option is active and receives a trigger, then the moving brush will start moving.


Set the other options and brushes.

Trig_Option2:Target01->MB_02
Trig_Option2:Event type Target01->Start Event

Trig_Option3:Target01->MB_03
Trig_Option3:Event type Target01->Start Event

Trig_Option4:Target01->MB_04
Trig_Option4:Event type Target01->Start Event

Trig_Option5:Target01->MB_05
Trig_Option5:Event type Target01->Start Event


You can now test the system. Drag a player start entity into place. Walk through the first touch field to start the selectors cycling. Walk through the second touch field to stop the selectors and trigger the Option test. One of the moving brushes should start moving. Test it a few times and see if you can predict which one you will start moving.



Finishing touches.


The current resolution of the system is controlled by the clock.(1 second intervals) this means that it takes 5 seconds to cycle completely. As the demonstration world shows, itís quite conceivable to walk straight through one touch field and through the other and be fairly sure that you will get the same result each time. This is due to the fact that Sam walks at a constant predictable speed.
If there was a simple obstacle between the two touch fields then the path that the player chooses to take to navigate the space between the touch fields becomes much less predictable. With the large time slices in the selector, itís still quite feasible to arrive in approximately the same time and thus end up with fairly consistent results. This will not do.

To correct this problem, increase the resolution of the clock.

Set the clock delay ...

Trig_clock_delay:wait->0.01

This will mean that the selection cycle has gone from 5 seconds to 5 100ths of a second. Letís see how predictable that is now. Even a slight variation in the path the player chooses will have a major effect on the final outcome.

Remember that the resolution of the clock can not be smaller than the timing of the Trig_Slector_Delay:wait property. If you have that set at 1 millisecond you can use just about anything larger than a millisecond for your clock.


Remember to make sure to switch the clock off. Especially if you have it at a very small resolution. You donít want a couple of these whirring away in the background wasting your CPU cycles for no reason.



How to use this.

The final options can be used to add a random effect anyway you like.

Use the system to select between different doors that may be open in a room.

Select which enemy appears at a certain point.

Select where the enemy appears in critical rooms.

Change the distribution of supplies and weapons.

Change the results of buttons and switches. (Measure the time between button pushes)

Bring a little chaos to your playerís life! :-)



I hope you find this useful.


Hot_sleeper


The file attached has both versions of the system, with the resolution set to ...um 1/10th of a second if memory serves. Smaller than 1 second anyway.

Enjoy.
__________________
"Every time I open my mouth, a little of my stupid collection escapes!"

Last edited by hot_sleeper; 01-24-2003 at 02:57 AM.
  Reply With Quote
Old 01-01-2003, 04:55 AM   #2   Add To Ignore List  
Kamikaze
 
hot_sleeper's Avatar
 
Joined: Dec 2002
Location: Australia
 
hot_sleeper is offline
Default

The demo world file....

Hot_Sleeper
Attached Files
File Type: zip poc_randomselect.zip (7.7 KB, 21 views)
__________________
"Every time I open my mouth, a little of my stupid collection escapes!"
  Reply With Quote
Old 01-03-2003, 07:12 AM   #3   Add To Ignore List  
Hey ladies
 
Fiendian's Avatar
 
Glowing Red Stove Top
Joined: Nov 2002
Location: Iceland
 
Fiendian is offline Send a message via ICQ to Fiendian Send a message via MSN to Fiendian
Default

Nice tut, HotSleeper.
  Reply With Quote
Reply

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
I have a problem with UV mapping Apocalypse_Soon Serious Modeler 6 06-24-2004 09:42 AM
Random mapping techniques Shrinker Serious Editor 35 09-05-2003 06:03 PM
Mapping: Terrain Optimisation hot_sleeper Serious Sam Classic Mods 2 01-14-2003 02:57 AM
ILLEGAL TESTING!!!! (bump mapping) Lancelot du lac Serious Modeler 9 11-11-2002 03:08 PM
Texture Mapping in Serious Modeler Neostorm Serious Modeler 4 03-01-2002 03:29 AM


All times are GMT -4. The time now is 12:06 PM.