Mode7 is definitely not the most simple object to master. Even when you've figured out the basics, to actually make a game with it, it takes a lot of skill. There comes the difficult parts of sprite mapping, obstacle collisions, and much many more torturous time-consuming tasks. However, I've made this article, a guide to master the powerful extension known to us as Mode7.

In this article, you'll learn the secrets of Mode7 by making 3rd person shooter game. No, I did not say FPS, I said TPS. Just think of this game we'll make as a mech-armor type game.

Some elements such as sprite animation and custom movements aren't discussed in this article to save time and to make the article shorter.

***Update, 5/16/2004: updated the information about the Mod7 angle system. Attempted to get rid of the cut-off areas due to bugs in the code tag.

The Basics: Making the Map

The Mode7 object is basically a subwindow that displays a 2D picture as a 3D map. The picture can be given height, fog, and even some fancy(but CPU hogging) antialiasing effects.

To begin, we must make the 2D map that we will be using for our level:

1)For this, just make a backdrop object and put it somewhere on the playfield that cannot be viewed by the game's window(preferrably right beside where the right edge of the game's window will be). Make sure that this object is set as not an obstacle.

2)Make a clone of that map backdrop you just made and erase everything that is not a wall. Put this backdrop directly ontop of the other one. Set this as an obstacle.

3)Create the infamous Mode7 object. For the first image in it, copy the picture from the 2D map backdrop and just slap it onto the Mode7 object. Now we have our main map. Set the use this image for attribute to main image.

4)Unless you turn on the wrapping option, the map you have in your Mode7 object will look like an object in black space. Insert another picture into the Mode7 object. Make this picture just be floor tiling and set it under use this image for as the secondary image. The secondary image automatically wraps itself in the Mode7 object's world across any space not used by the main image.

5) Now just place the Mode7 object on the playfield where it'll take up the bottom half of your game's window.


Your basic map is finished. Give yourself a pat on the back.

Walking in the Mode7th Dimension: Controlling the Character and the Camera

Right now, all you can do with your game is stand still looking at your semi-3D world. You need to create an object that the Mode7 camera will follow in the semi-3D world. Here, we'll create our player and make the camera appear like it's viewing the player from 3rd person POV.

important note: Be sure to check handle background collisions even out of window in the level's frame properties.

1) Create a real player object and place it somewhere(preferably at the level's starting point) on your level map backdop. Because this object serves is only the 2D version of the player and it cannot be viewed in the actual game, just make it a circle or somthing.

2) Give the player a movement. Give the player a custom 360 direction movement(if you want best results), a custom 32-direction movement(if you're an intermediate developer), or just a racecar movement(if you're lazy).

3) Once you've programmed the real player, click the play button to play your level in the frame editor. Do this to make sure the real player can collide with its currently 2D environment.

4) Now, we'll make it so you can explore your semi-3D world from First-person view. In the event editor, make a group called camera controls and make the following event:

>always

-set X origin of Mode7 object to X(real player)
-set Y origin of Mode7 object to Y(real player)
-set Z origin(elevation of camera) of Mode7 object to any positive multiple of 10(800 is usually good)

//This next part is tricky. It'll differ depending on
//whether you used a 360-direction movement or a 32-
//direction movement.

//360-direction movement:

-set rotation angle of Mode7 object to ((angle real player is facing)-90)

//32-direction movement:This'll convert 32-direction
//format into 360-direciton format.

-set rotation angle of Mode7 object to
360-(((1000*direction(real player)/32)*360)/1000)-90

___

Yay! Now we can move around in our 3D world and we can collide with stuff too!


A Pinch of Trig, and a Handful of Graphics: The 3rd-Person Potion

Here's where it gets tricky. If you don't have the power to make graphics and make a 3rd-person camera, you'd better skip this step and just settle for a less advanced FPS. Right now, we've got it set as a 1st-person POV.

1) Create the player graphic.This is the graphic we'll actually see in the game. Because it's a 3rd person shooter, a mech-armor type player would do well. If you have another idea for the player, you can use that too. This shouldn't be too hard because you'll really only need a stopped and a walking animation for the backview of the player. But, make sure your player isn't so big you can't see past it. For future use, put the hot spot at the foot of the sprite.

2) Now, to make it view the player from behind. Go back to the events that control the camera. make the following changes:


>always
-set X origin of Mode7 object to X(real player)-((any positive distance)*cosine(player angle))
-set Y origin of Mode7 object to Y(real player)+((same distance)*sine(player angle))

___
3) Now make it so that the player sprite's animation work when you want them to.

4) Now, for the hard part: using sprite mapping to position the player sprite. Use the following event:

>always
-set X position of player sprite to GetmapXZ( X(real player)-(X size of window), Y(real player))
-set Y position of player sprite to GetmapYZ( X(real player)-(X size of window), Y(real player))

//to find the getmapXZ and getmapYZ in the expression
//editor, go to: Mode7 > Sprite Mapping > Get on-screen
//X/Y from X,Y

//see the Mode7 html referrence file for the syntax of
//these functions.

___

Yay! Now we have a 3rd-person camera and we can see the actual player!

Waging the War: Fighting the Fiends

Now for the most difficult part, making the enemies and the weapons. This includes lots of sprite mapping and creating 3D companions for thier 2D buddies.

1) First, make the real 2D objects for the enemies and all the weapons and place them wherever you want on the 2D map backdrop. Then give them AI so they can move and shoot you.

2) Make it so that the real player can shoot back.

3) Create the enemy sprites. Make an image/animation for every direction you'll need for the enemy. Sometimes they'll be facing you, sometimes to the side, and sometimes away from you. Also, for distance purposes, make at least 3 animations for the enemy: one for normal size when it's close to you, another for when it's within mid-range of you, and another for when it's far from you.

4) Make a laser sprite for you and the enemies. Again, make 3 animations for them: close, mid-range, and far. Put the hot spot of the laser where the feet of an enemy or player would be so it'll hit their body, not their foot.

5) Use sprite mapping to correctly place the enemy sprites


>always
-spread a value in real enemy and enemy sprite objects
-start loop(enemy sprite) for (number(real enemy) loops

>On loop enemy sprite
+>if spreaded value of real enemy = loopindex(enemy sprite)
+>if spreaded value of enemy sprite = loopindex(enemy sprite)
-set X position of enemy sprite to GetmapXZ( X(real enemy)-(X size of window), Y(real enemy))
-set Y position of enemy sprite to GetmapYZ( X(real enemy)-(X size of window), Y(real enemy))

___
6) Change the animation of the enemies depending on thier real companion's distance from the real player.


//distance formula:
//D= sqr( ((Xplayer-Xenemy)^2)+((Yplayer-Yenemy)^2) )

>On loop enemy sprite
+>if spreaded value of real enemy = loopindex(enemy sprite)
+>if spreaded value of enemy sprite = loopindex(enemy sprite)
-make enemy sprite reappear
-set animation to close

>On loop enemy sprite
+>if spreaded value of real enemy = loopindex(enemy sprite)
+>if spreaded value of enemy sprite = loopindex(enemy sprite)
+>if distance > (mid-range distance)
-set animation to mid-range

>On loop enemy sprite
+>if spreaded value of real enemy = loopindex(enemy sprite)
+>if spreaded value of enemy sprite = loopindex(enemy sprite)
+>if distance > (far-range distance)
-set animation to far

>On loop enemy sprite
+>if spreaded value of real enemy = loopindex(enemy sprite)
+>if spreaded value of enemy sprite = loopindex(enemy sprite)
+>if distance > (very far-range distance)
-make enemy sprite invisible

___

7) Set the direction of the enemy sprites


>On loop enemy sprite
+>if spreaded value of real enemy = loopindex(enemy sprite)
+>if spreaded value of enemy sprite = loopindex(enemy sprite)
-set direction of enemy sprite to (direction of real enemy)-(direction of player(32-direction format))+8


sprite mapping for the lasers. Do basically the same you did with sprite mapping the enemies, only with the real lasers and laser sprites instead.

9) We want there to always be 1 enemy sprite per real enemy and 1 laser sprite per laser. Also, we want to get rid of anything without a buddy. This is easilly done:


//enemies:

>if number(enemy sprites)>number(real enemies)
+>pick one enemy sprite
-destroy the picked sprite
>if number(enemy sprites)<number(real enemies)
-create an enemy sprite object

//lasers: same thing. Remember to do this for both the player and enemy lasers!


___

10) One last step: sending stuff to the front and back


>always
-start loop font/back for (Y window size) loops
>on loop front/back
+>if Y(enemy sprite)=loop index(front/back)
-send enemy sprite to the front
>on loop front/back
+>if Y(enemy laser sprite)=loop index(front/back)
-send enemy laser sprite to the front
>on loop front/back
+>if Y(player laser sprite)=loop index(front/back)
-send player laser sprite to the front
>on loop front/back
+>if Y(player sprite)=loop index(front/back)
-send player sprite to the front

___

Now, after the long hard battle, you have finally conquered Mode7(if you survived this article that is).


Colored Sparklies and flashy poofs: Extras

-Creating map height: To add height to your level's map, insert a new image into the mode 7 object as a copy of the 2D map. Now color all walls white and the color the floor black. For any heights between, use a shade of gray. Then under render options, click advanced. Now look at the height mapping table and set the thickness to a positive multiple of 100(800-2000 works well). Now you'll have walls and towers to add to your level.

-Ceilings: For a ceiling, do the following:

1)create a clone of your finished Mode7 object

2) go to the events and do the following:


>always
-set X origin of Mode7 ceiling to X origin of Mode7 object(the floor!)
-set Y origin of Mode7 ceiling to Y origin of Mode7 object
-set Z origin of Mode7 ceiling to 0-(Z origin of Mode7 object)
-set rotation angle of Mode7 ceiling to rotation angle of Mode7 object

___

-Fog: Edit your mode 7 object and go to advanced under render options. Look at the fog table. Check Enable Fog, and set the color of the fog and the amount of fog you want.

-Simple Backgrounds: For a simple background, just use a gradient in the upper half of the visible playfield.

-Paralax Backgrounds: You can make backgrounds easilly by just using a background system object for paralax effects. Just set the X position of the bg-system object to its width*the player's angle. Make sure that you set its dimensions so there's an offscreen section of the bg-system object for paralax.

-Mode7 backgrounds: Cloud background effects can made using another mode 7 object. Be sure to turn on the wrapping feature for the sky object's render options.


>always
-set X/Y/angle origins of Mode7 sky to Mode7 object's X/Y/angle origins
-set Z origin of Mode7 sky to (0 - (Z origin of Mode7 object))
-slide X of Mode7 sky by (any increment value here)

___

Spell Books and Forgotten Lore: A few important notes on Mode7

Sometimes you can tell Mode7 to do something, but the results will be unexpected. This is very true with working with Mode7''s angle and Z origin.

1)Mode7's angle system: Usually, when we use angles, we use 0° as facing east and 90° as facing north and so forth. However, for some strange reason, Mode7's developers decided that 0° should should be facing north and that the angle should increase as it rotates left istead of right! So now when we want to set Mode7's angle, we have to go through not so much trouble to subtract 90 from our real angle and then subtract tat difference from 360 to make Mode7 be facing where we want it to.
Final formula: Angle=270-(player angle)

2)Z origin(elevation): Any positive Z origin will put Mode7's camera above the ground and Mode7's vanishing point will be at the top edge of the Mode7 camera. Any negetive Z origin will make the camera be below the ground and the vanishing point will be at the bottom edge of the Mode7 camera(this is great for clouds and ceilings!). If your Z origin is near 0 though, it'll look like you're in the ground and you'll see that your Mode7 map has some thickness to it automatically even if you didn't specify a height map.

3)Vanishing Points and towers: Because our vanishing point is either always at the bottom or top edge of the Mode7 camera, making structures like towers can become difficult. Anything that extends in height above the top edge of the Mode7 object will be cut. So a good way around this is to just make a tower sprite and a bunch of real tower objects. Then just apply sprite mapping like you did with enemies and lasers. Make sure you make it so the real player can collide with the real towers!



Now, with this extra knowledge, you'll have even more control over Mode7.


If you feel this is lacking in some areas, DCmail me about it. I ran out of time towards the end of this article thanks.

I hope this is useful.