Special Effects for a Tile Engine
Michael Dowling (typosoft@hotmail.com)
http://www.geocities.com/typosoft/
May 29, 2002
----------------------------------------------------------------------------------

Here are some special effects you can use with your own tile engine.  Some of the
things here I've never seen in any other tutorials.

1.  Animated Objects
2.  Particle System
3.  Water flow and reflections
4.  High Grass (over tiles)
5.  Other FX
6.  Closing words

-------------------
1. Animated Objects
-------------------
										
Animated objects is one of the easiest effects that you can use in your rpg.
First off, your objects have to have TYPE to them.  In the TYPE will be a Frame
variable, Frames, FrameWait, and Delay.
																			
The best way to explain something is to show someone, so here is an example
program.

=ANIM.BAS=
DEFINT A-Z

TYPE Object
 X         AS INTEGER
 Y         AS INTEGER
 Tile      AS INTEGER
 Frame     AS INTEGER
 Frames    AS INTEGER
 FrameWait AS INTEGER
 Delay     AS INTEGER
END TYPE

DIM Object(1 TO 100) AS Object

'Randomly set up the objects

FOR I = 1 TO 100
 Object(I).X = INT(RND * 303)
 Object(I).Y = INT(RND * 182)
 Object(I).Tile = 1
 Object(I).Frame = 0
 Object(I).Frames = 3
 Object(I).FrameWait = 0
 Object(I).Delay  = INT(RND * 12) + 1
NEXT

DO
 FOR I = 1 TO 100
  Object(I).FrameWait = Object(I).FramWait + 1
  IF Object(I).FrameWait => Object(I).Delay THEN
   Object(I).FrameWait = 0
   Object(I).Frame = Object(I).Frame + 1
   IF Object(I).Frame = Object(I).Frames THEN Object(I).Frame = 0
  END IF
  'Then you would draw the objects here
  'the objects tile to draw would = Objectile(I).Tile + Object(I).Frame
 NEXT
LOOP UNTIL INKEY$ <> ""

------------
2. Particles
------------

Particles are a very very cool effect that almost every game should have.  They
aren't that hard to put in your own game.  If you think about it, all you are
doing is:  creating particles, drawing particles, and handling particles.  The
first thing you will have to do is make a TYPE for the particles.
											
'=particle.bas='

'$INCLUDE: 'DirectQB.BI'

'Particle Engine Demonstration
'Michael Dowling (typosoft)
' homepage: www.geocities.com/typosoft/

'This is how you make a particle engine.  You can play around with the way
'you add particles in, like make them go in a straight line, a circle,
'similar to what I did here, or make them fall from the top of the screen
'like leaves by playing with the RX and RY variable.
'to see the leafs, change the Parts to 1 and unREM that one line up there.

DECLARE SUB UpdateParticles (Layer%)
DECLARE SUB CreateParticle (x%, y%, AX%, AY%, rx%, ry%, Col%, Dtype%, Life%)

TYPE particle
 x     AS INTEGER 'X position of the particle
 y     AS INTEGER 'Y position of the particle
 AX    AS INTEGER 'X pixels the particle will travel each time it is updated
 AY    AS INTEGER 'Y pixels the particle will travel each time it is updated
 LX    AS INTEGER 'Location the particle was last at
 LY    AS INTEGER 'Location the particle was last at
 rx    AS INTEGER 'Random x movement
 ry    AS INTEGER 'Random y movement
 Col   AS INTEGER 'color of the particle
 Dtype AS INTEGER 'draw type.  0 = block 1 = sprite 2 = line etc...
 Life  AS INTEGER 'how many frames the particle will be on the screen
END TYPE

DIM SHARED particle(1 TO 100) AS particle  'DIM the particle

'Initialise the screen and DirectQB
SCREEN 13
IF DQBinit(1, 0, 0) THEN PRINT DQBerror$: END
DQBinitVGA

Parts = 8 'change this for more or less particles

DO
 DQBclearLayer 1                        'clear the buffer layer
 DQBpset 1, DQBmouseX, DQBmouseY, 15    'draw the mouse
 CALL UpdateParticles(1)                'handle/draw the particles
 IF DQBmouseLB THEN                     'if you click a button
  'Going to add 8 particles at the mouse position in an explosion
  FOR a = 1 TO Parts
   AX = INT(RND * 2) - INT(RND * 2) 'x movement
   AY = INT(RND * 2) - INT(RND * 2) 'y movement
   rx = 2                           'random x movement
   ry = 0                           'random y movement
   L = INT(RND * 12) + 15           'random Life for the particle
   XX = DQBmouseX: YY = DQBmouseY   'Set the origin X and Y to the mouse
   C = 14                           'color of the particle
   'Use this below for a leaf like particle
   'AX = 0: AY = 1: RX = 2: RY = 0: C = 2: L = INT(RND * 40) + 20: XX = INT(RND * 10) - INT(RND * 10) + DQBmouseX
   CALL CreateParticle(XX, YY, AX, AY, rx, ry, C, 0, L)
  NEXT
 END IF
 DQBcopyLayer 1, 0    'Copy the buffer layer to the video layer
LOOP UNTIL DQBmouseRB 'if you right click, then the program ends

DQBclose

SUB CreateParticle (x, y, AX, AY, rx, ry, Col, Dtype, Life)
 'This sub basically takes all the variables above and puts them
 'into the variables used for the particles
 DEFINT A-Z
 FOR I = 1 TO 50
  IF particle(I).x > 315 OR particle(I).x < 4 THEN particle(I).Life = 0
  IF particle(I).y > 196 OR particle(I).y < 4 THEN particle(I).Life = 0
  IF particle(I).Life = 0 THEN P = I: EXIT FOR
 NEXT
 IF P > 100 OR P < 1 THEN EXIT SUB
 particle(P).x = x: particle(P).y = y
 particle(P).AX = AX: particle(P).AY = AY
 particle(P).rx = rx: particle(P).ry = ry
 particle(P).Col = Col: particle(P).Dtype = Dtype
 particle(P).Life = Life
END SUB

SUB UpdateParticles (Layer) 'If you are using DQB
 'This sub handles where the particles are going and also draws them
 DEFINT A-Z

 FOR I = 1 TO 50
  'Only handle the particle if it is alive
  IF particle(I).Life THEN
  
   'This reduces the particles life left on the screen
   particle(I).Life = particle(I).Life - 1
  
   'This checks if the particle is no longer visible. If so it kills it
   IF particle(I).x <= 3 OR particle(I).x >= 316 OR particle(I).y <= 1 OR particle(I).y >= 198 THEN particle(I).Life = 0
  
   'This handles the particles movement
   IF particle(I).AX THEN particle(I).x = particle(I).x + particle(I).AX
   IF particle(I).AY THEN particle(I).y = particle(I).y + particle(I).AY
  
   'Random particle movement.  Can look cool if used right
   rx = INT(RND * particle(I).rx) - INT(RND * particle(I).rx)
   ry = INT(RND * particle(I).ry) - INT(RND * particle(I).ry)
   particle(I).x = particle(I).x + rx   'Add the random x in
   particle(I).y = particle(I).y + ry   'Add the random y in
  
   'Draw the particle a certain way depending on its dtype variable
   SELECT CASE particle(I).Dtype
    CASE 0
     'this what is in this program
     DQBboxf Layer, particle(I).x, particle(I).y, particle(I).x + 1, particle(I).y + 1, particle(I).Col
    CASE 1
     'Could be used for sprites
    CASE 2
     'Could be used for lines
   END SELECT
 
  END IF

 NEXT

END SUB
											
The particles can be added in any pattern you want.  You could make a random
explosion, a circular explosion, particles going in a straight line, or anything
you can think of.  You could make a butterfly out of a particle, leaves falling
from a tree, or even rain.  Just try to be creative.

I'm pretty sure that should work for a particle system, but all I've written so
far was off the top of my head...

--------------------------------------
3. Flowing water and water reflections
--------------------------------------

This one will require me to look some stuff up...Ok I'm back.  You will need to
have water layer with nothing on it but a repeating water tile.
									
FOR X = 1 TO 20
FOR Y = 1 TO 12
 DQBput 2, X, Y, WaterTile
NEXT
NEXT

Next, go through all your tiles and anything that is supposed the be water,
blacken (color 0) all the pixels that are water.  The reason for this is so you
can do water effects and reflections.  You will copy the water layer after you
made it flowing (explained later) to layer 1.  Then you will loop through all
the players and draw them upside down on their pixel location on layer 1.  Then
you will draw the map on layer 2.  Then DQBtransCopy layer 2, to layer 1.  Then
copy layer 1 to layer 0 and viola!

DQBcopyLayer 3, 1 'Water layer
FOR I = 1 TO WorldMap.Players 'number of players
 DQBmPut 1, PX, PY, Ptile, VER 'Vertically flip the player and put him on layer 1
NEXT
DrawMap 2
DQBcopyTransLayer 2, 1

and there is how to do reflections.  You can do other editing to the player's
sprite, such as transparency or blurring.

To make the water wavey, isn't really something to learn.  This is pretty much cut
and paste.  

DIM SHARED WAA, WBB
DIM SHARED wavesl(318) AS LONG, wavesr(2) AS LONG

SUB WaveyWater (L) ' the layer the water is on
DEFINT A-Z
  WAA = WAA + 1
  IF WAA = 96 THEN WAA = 0
  WBB = WBB + 15
  IF WBB >= 189 THEN WBB = 1
  C% = (WAA% + WBB%) MOD 197
  DQBget L, 0, C%, 317, C% + 3, VARSEG(wavesl(0)), VARPTR(wavesl(0))
  DQBget L, 318, C%, 319, C% + 3, VARSEG(wavesr(0)), VARPTR(wavesr(0))
  DQBfPut L, 0, C%, VARSEG(wavesr(0)), VARPTR(wavesr(0))
  DQBfPut L, 2, C%, VARSEG(wavesl(0)), VARPTR(wavesl(0))
  C% = (WAA% + WBB% + 10) MOD 197
  DQBget L, 2, C%, 319, C% + 3, VARSEG(wavesl(0)), VARPTR(wavesl(0))
  DQBget L, 0, C%, 1, C% + 3, VARSEG(wavesr(0)), VARPTR(wavesr(0))
  DQBfPut L, 318, C%, VARSEG(wavesr(0)), VARPTR(wavesr(0))
  DQBfPut L, 0, C%, VARSEG(wavesl(0)), VARPTR(wavesl(0))
END SUB 

You would then call waveyWater every frame with the specified water layer.

-------------------------
4. High Grass (over tiles
-------------------------

If you have ever played Zelda 3, then you have walked through high grass.  This
effect is easy and can be achieved many different ways.  Here is how I do it.
											
First I make a list of tiles that if you walk on them, then there is a tile that
is placed over the player.  This will require another TYPE.

TYPE Overt
 Tile  AS INTEGER
 OT    AS INTEGER
END TYPE

DIM SHARED Overt(1 TO 10) AS Overt

Overt(1).Tile = 1 'If the player steps on this tile then...
Overt(1).OT = 12  'this tile is placed over him

FOR I = 1 TO 10
 IF OverTile = Overt(I).Tile THEN
  PUT (X, Y), Overt(I).OT
 END IF
NEXT

---------------------------
5. Other Ideas to play with
---------------------------

In Ped Xing's Quest, I had a lot of fun with SIN and COS for spell effects.

Palette manipulation can always be cool, but don't overdo it.  Be sure to set the
palette back to normal after changing it up, so your tiles look the way they
should.  You could darken the screen a bit, add some rain, a repeating rain
sound, and you would have a nice rain effect.

Scrolling between maps is also very cool.  If you are making a Zelda style RPG,
then scrolling between screens would be very cool eye candy.
										
Shadows beneath the NPCs

----------------
6. Closing Words
----------------

I doubt that the source I wrote in this tut will work perfectly, but it is a good
start.  If you need better examples or more help, download the Ped Xing's Quest
source code.
										
Michael Dowling

    Source: geocities.com/typosoft