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