Value controlled rain code: Difference between revisions

From EDukeWiki
Jump to navigation Jump to search
Mblackwell (talk | contribs)
mNo edit summary
 
LordMisfit (talk | contribs)
mNo edit summary
 
(5 intermediate revisions by 2 users not shown)
Line 1: Line 1:
This shows how to use [[Eduke]] to create a nice rain effect, allowing you to [[spawn]] and retain a certain amount of rain within a map. The way this works, is we create both rain, and a [[spawn]]er for the rain. The "rain [[spawn]]er" can then be given a [[hitag]] by the mapper, equal to the amount of rain they want to [[spawn]]. The rain itself [[spawn]]s in a limited area, but "spreads out", allowing you to easily modify overall density.  
This shows how to create a nice rain effect, allowing you to [[spawn]] and retain a certain amount of rain within a map. This works by creating both rain and a [[spawn]]er for the rain. The "rain [[spawn]]er" can then be given a [[hitag]] by the mapper, equal to the amount of rain they want to [[spawn]]. The rain itself [[spawn]]s in a limited area, but "spreads out", allowing you to easily modify overall density.


First we will create the rain [[actor]] itself:
First we will create the rain [[actor]] itself:




These are afew [[gamevar]]s we will need in the course of this code:
The following [[gamevar]]s will be needed during the course of this code:
<pre>
<pre>
gamevar TEMP 0 2
gamevar TEMP 0 2
gamevar RAND_DIST 0 2
gamevar RAND_DIST 0 2
gamevar COUNTER 0 2
gamevar COUNT 0 2
gamevar MHITAG 0 2
gamevar MHITAG 0 2
gamevar ORIGRAINPOSX 0 2
gamevar ORIGRAINPOSX 0 2
Line 14: Line 14:
</pre>
</pre>


Of course, then we need [[actor]] tile definitions. Change these appropriately:
A couple of [[actor]] tile definitions are also required. Change these appropriately:
<pre>
<pre>
define RSPAWN 3879
define RAIN1 3890   
define RAIN1 3890   
define RAINRIPPLE 3880
define RAINRIPPLE 3880
</pre>
</pre>


Here's our relevant [[move]] commands (remember, positive verticle values mean downward motion):
Here are our relevant [[move]] commands (remember, positive vertical values mean downward motion):
<pre>
<pre>
move RAINDOWN 0 800
move RAINDOWN 0 800
Line 39: Line 40:
ifaction 0
ifaction 0
{
{
cstat 32768
cstat 32768
action INIT
action INIT
getactor[THISACTOR].x ORIGRAINPOSX  
getactor[THISACTOR].x ORIGRAINPOSX  
getactor[THISACTOR].y ORIGRAINPOSY
getactor[THISACTOR].y ORIGRAINPOSY
}  
}  
</pre>
</pre>
You probably noticed we used "ifaction 0". This allows us to do things on what is basically actor intialization, and without wasting an action. You may have noticed we saved the original x/y of the actor.
You may have noticed we used "ifaction 0." This allows us to do things on what is basically actor intialization without wasting an action. Note that we saved the original x/y coordinates of the actor.


<pre>
<pre>
sizeat 10 40
sizeat 10 40
</pre>
</pre>
This sets the size of the sprite. In this case I wanted it taller than it is wide. Adjust accordingly.
This sets the size of the sprite. In this case, I wanted it to be taller than it is wide. Adjust accordingly.


<pre>
<pre>
ifaction INIT
ifaction INIT
{
{
cstat 32768
cstat 32768
ifoutside { }
ifoutside
else { setactor[THISACTOR].x ORIGRAINPOSX setactor[THISACTOR].y ORIGRAINPOSY }
nullop
move RAINSKY geth randomangle
else  
ifrnd 96 { action RAINDROP }
{
setactor[THISACTOR].x ORIGRAINPOSX  
setactor[THISACTOR].y ORIGRAINPOSY
}
move RAINSKY geth randomangle
ifrnd 96
action RAINDROP
}
}
else ifaction RAINDROP
else ifaction RAINDROP
{
{
ifoutside { }
ifoutside
else { setactor[THISACTOR].x ORIGRAINPOSX setactor[THISACTOR].y ORIGRAINPOSY } </pre>
nullop
You probably noticed this last statement above as well. Incase the rain goes indoors, this will reset to it's original position. This is seen later as well.
else  
{  
setactor[THISACTOR].x ORIGRAINPOSX  
setactor[THISACTOR].y ORIGRAINPOSY  
}  
</pre>
If the rain sprite goes indoors, it resets its position.


<pre>
<pre>
cstat 2
cstat 2
move 0 fall
move 0 fall
move 0
</pre>
</pre>
This makes the rain transparent, and stops any horizontal movement.
Setting the sprite's cstat to 2 causes the sprite to be rendered with translucency level 1, "move 0" tells the actor not to execute any movement and "fall" simply tells the actor to move downward vertically until hitting the ground.
 
<pre>
<pre>
move RAINDOWN getv
move RAINDOWN getv
iffloordistl 4
iffloordistl 4
{
{
  sizeat 20 20
sizeat 20 20
  action RAINSPLASH
action RAINSPLASH
  move 0 fall
move 0 fall
}
}
}
}
else ifaction RAINSPLASH
else ifaction RAINSPLASH
{
{
sizeat 20 20
sizeat 20 20
</pre>
</pre>
This sizeat command alters the size of the sprite to account for the fact that it is now a "splash".
The sizeat command alters the size of the sprite.  We're changing our sprite's size to account for it now being a "splash."
 
<pre>
<pre>
cstat 2
cstat 2
ifactioncount 5
ifactioncount 5
{
{
  cstat 32768
cstat 32768
  ifonwater { espawn RAINRIPPLE }
ifonwater  
  getsector[THISACTOR].ceilingz TEMP
spawn RAINRIPPLE
  setactor[THISACTOR].z TEMP
getsector[THISACTOR].ceilingz TEMP
  action INIT
setactor[THISACTOR].z TEMP
}
action INIT
}
}
}
enda
enda
</pre>
</pre>


You may have realized, I coded to account for the fact that the rain may end up on water, in which case it will spawn a ripple. Here's some quick code for that:
The rain sprite is set up to spawn a ripple when it hits the water. Here's some quick code for that:
<pre>
<pre>
action RIPPLING 0 9 1 1 4
action RIPPLING 0 9 1 1 4


useractor notenemy RAINRIPPLE 0
useractor notenemy RAINRIPPLE 0
ifaction 0
{
{
sizeat 20 20
ifaction 0
cstat 34
{
action RIPPLING
sizeat 20 20
move 0 fall
cstat 34
action RIPPLING
move 0 fall
}
ifactioncount 9
killit
iffloordistl 4 nullop
else killit
}
}
ifactioncount 9 { killit }
iffloordistl 4 { } else { killit }
enda
enda
</pre>
</pre>


Now comes the part where we make the rain spawner. First we can make a quick state to handle where the rain spawns.
Now comes the part where we make the rain spawner. First, we make a quick state to handle where the rain spawns:
<pre>
<pre>
state spawnrain
state spawnrain
cstat 32768
ifvarvare MHITAG COUNT { setvar COUNT 0 killit }
else
{
{
addvar COUNT 1
cstat 32768
espawn RAIN1
ifvarvare MHITAG COUNT
getactor[THISACTOR].pal TEMP
{
setactor[RETURN].pal TEMP
setvar COUNT 0
killit
}
else
{
addvar COUNT 1
espawn RAIN1
getactor[THISACTOR].pal TEMP
setactor[RETURN].pal TEMP


ifrnd 64
ifrnd 64
{
{
getactor[RETURN].x TEMP
getactor[RETURN].x TEMP
randvar RAND_DIST 2048
randvar RAND_DIST 2048
addvar RAND_DIST 2048
addvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
addvarvar TEMP RAND_DIST
setactor[RETURN].x TEMP
setactor[RETURN].x TEMP
}
}
ifrnd 64
ifrnd 64
{
{
getactor[RETURN].x TEMP
getactor[RETURN].x TEMP
randvar RAND_DIST -2048
randvar RAND_DIST -2048
subvar RAND_DIST 2048
subvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
addvarvar TEMP RAND_DIST
setactor[RETURN].x TEMP
setactor[RETURN].x TEMP
}
}
 
ifrnd 64
{
getactor[RETURN].y TEMP
randvar RAND_DIST 2048
addvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
setactor[RETURN].y TEMP
}
ifrnd 64
{
getactor[RETURN].y TEMP
randvar RAND_DIST -2048
subvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
setactor[RETURN].y TEMP
}


ifrnd 64
{
getactor[RETURN].y TEMP
randvar RAND_DIST 2048
addvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
setactor[RETURN].y TEMP
}
ifrnd 64
{
getactor[RETURN].y TEMP
randvar RAND_DIST -2048
subvar RAND_DIST 2048
addvarvar TEMP RAND_DIST
setactor[RETURN].y TEMP
}
}
}
}
ends
ends
</pre>
</pre>
You may have noticed I cleverly added a bit of code at the beginning to cause the rain to be the same palette as the spawner. This would allow you to create, for instance, a rainbow colored rainfall, or that of blood, if you so choose, all while using the same rain actor. The range I used is (as you could probably tell), 2048x2048x2048. You can change this as you wish, but this is a good number.


And the actor itself:
And the actor itself:
<pre>
<pre>
action NORSPAWN 0 1 1 1 1
action NORSPAWN 0 1 1 1 1
useractor notenemy RSPAWN 0 RNOT 0
useractor notenemy RSPAWN 0
 
ifaction 0  
{
{
getactor[THISACTOR].hitag MHITAG
ifaction 0
setvar TEMP 0
{
setactor[THISACTOR].hitag TEMP
getactor[THISACTOR].hitag MHITAG
action NORSPAWN
setvar TEMP 0
 
setactor[THISACTOR].hitag TEMP
action NORSPAWN
}
state spawnrain
}
}
state spawnrain
enda
enda
</pre>
</pre>


The advantages of this method are quite obvious, in that it lowers the amount of potential actors that will be in the map (the only time it would increase beyond what you defined is if the rain hits water, which should have a negligable effect), and makes it quite easy to edit the rain in a map. Also, rain is prevented from going indoors, except at the edges, limiting potential bugs, while providing a realistic effect.
The advantages of this method are quite obvious in that it lowers the amount of potential actors that will be in the map (the only time it would increase beyond what you defined is if the rain hits water, which should have a negligible effect) and makes it quite easy to edit the rain in a map. Also, rain is prevented from going indoors, except at the edges, limiting potential bugs, while providing a realistic effect.


Try it yourself.
Try it yourself.
[[Category: Tutorials]]

Latest revision as of 11:14, 24 September 2006

This shows how to create a nice rain effect, allowing you to spawn and retain a certain amount of rain within a map. This works by creating both rain and a spawner for the rain. The "rain spawner" can then be given a hitag by the mapper, equal to the amount of rain they want to spawn. The rain itself spawns in a limited area, but "spreads out", allowing you to easily modify overall density.

First we will create the rain actor itself:


The following gamevars will be needed during the course of this code:

gamevar TEMP 0 2
gamevar RAND_DIST 0 2
gamevar COUNT 0 2
gamevar MHITAG 0 2
gamevar ORIGRAINPOSX 0 2
gamevar ORIGRAINPOSY 0 2

A couple of actor tile definitions are also required. Change these appropriately:

define RSPAWN 3879
define RAIN1 3890   
define RAINRIPPLE 3880

Here are our relevant move commands (remember, positive vertical values mean downward motion):

move RAINDOWN 0 800
move RAINSKY 800 0

And here are our actions, including a 5 frame splash:

action INIT 0 1 1 1 1
action RAINDROP 0 1 1 1 1
action RAINSPLASH 1 5 1 1 5

And now on to the actual actor code:

useractor notenemy RAIN1 0

ifaction 0
{
	cstat 32768
	action INIT
	getactor[THISACTOR].x ORIGRAINPOSX 
	getactor[THISACTOR].y ORIGRAINPOSY
} 

You may have noticed we used "ifaction 0." This allows us to do things on what is basically actor intialization without wasting an action. Note that we saved the original x/y coordinates of the actor.

sizeat 10 40

This sets the size of the sprite. In this case, I wanted it to be taller than it is wide. Adjust accordingly.

ifaction INIT
{
	cstat 32768
	ifoutside
		nullop
	else 
	{
		setactor[THISACTOR].x ORIGRAINPOSX 
		setactor[THISACTOR].y ORIGRAINPOSY
	}
	move RAINSKY geth randomangle
	ifrnd 96
		action RAINDROP
}
else ifaction RAINDROP
{
	ifoutside
		nullop
	else 
	{ 
		setactor[THISACTOR].x ORIGRAINPOSX 
		setactor[THISACTOR].y ORIGRAINPOSY 
	} 

If the rain sprite goes indoors, it resets its position.

	cstat 2
	move 0 fall

Setting the sprite's cstat to 2 causes the sprite to be rendered with translucency level 1, "move 0" tells the actor not to execute any movement and "fall" simply tells the actor to move downward vertically until hitting the ground.

	move RAINDOWN getv
	iffloordistl 4
	{
		sizeat 20 20
		action RAINSPLASH
		move 0 fall
	}
}
else ifaction RAINSPLASH
{
	sizeat 20 20

The sizeat command alters the size of the sprite. We're changing our sprite's size to account for it now being a "splash."

	cstat 2
	ifactioncount 5
	{
		cstat 32768
		ifonwater 
			spawn RAINRIPPLE
		getsector[THISACTOR].ceilingz TEMP
		setactor[THISACTOR].z TEMP
		action INIT
	}
}
enda

The rain sprite is set up to spawn a ripple when it hits the water. Here's some quick code for that:

action RIPPLING 0 9 1 1 4

useractor notenemy RAINRIPPLE 0
{
	ifaction 0
	{
		sizeat 20 20
		cstat 34
		action RIPPLING
		move 0 fall
	}
	ifactioncount 9 
		killit
	iffloordistl 4 nullop
	else killit
}
enda

Now comes the part where we make the rain spawner. First, we make a quick state to handle where the rain spawns:

state spawnrain
{
	cstat 32768
	ifvarvare MHITAG COUNT 
	{ 
		setvar COUNT 0 
		killit 
	}
	else
	{
		addvar COUNT 1
		espawn RAIN1
		getactor[THISACTOR].pal TEMP
		setactor[RETURN].pal TEMP

		ifrnd 64
		{
			getactor[RETURN].x TEMP
			randvar RAND_DIST 2048
			addvar RAND_DIST 2048
			addvarvar TEMP RAND_DIST
			setactor[RETURN].x TEMP
		}
		ifrnd 64
		{
			getactor[RETURN].x TEMP
			randvar RAND_DIST -2048
			subvar RAND_DIST 2048
			addvarvar TEMP RAND_DIST
			setactor[RETURN].x TEMP
		}

		ifrnd 64
		{
			getactor[RETURN].y TEMP
			randvar RAND_DIST 2048
			addvar RAND_DIST 2048
			addvarvar TEMP RAND_DIST
			setactor[RETURN].y TEMP
		}
		ifrnd 64
		{
			getactor[RETURN].y TEMP
			randvar RAND_DIST -2048
			subvar RAND_DIST 2048
			addvarvar TEMP RAND_DIST
			setactor[RETURN].y TEMP
		}
	}
}
ends

And the actor itself:

action NORSPAWN 0 1 1 1 1
useractor notenemy RSPAWN 0
{
	ifaction 0 
	{
		getactor[THISACTOR].hitag MHITAG
		setvar TEMP 0
		setactor[THISACTOR].hitag TEMP
		action NORSPAWN
	}
	state spawnrain
}
enda

The advantages of this method are quite obvious in that it lowers the amount of potential actors that will be in the map (the only time it would increase beyond what you defined is if the rain hits water, which should have a negligible effect) and makes it quite easy to edit the rain in a map. Also, rain is prevented from going indoors, except at the edges, limiting potential bugs, while providing a realistic effect.

Try it yourself.