- Return to Touhou Danmakufu
Section 0: Before You Try This[]
This tutorial assumes you have a basic familiarity with Danmakufu scripting in general. If you don't understand that yet, this tutorial won't really help you. Sorry. I recommend looking at the Touhou Danmakufu section. There's also a Danmakufu-specific wiki.
It could help to have some familiarity with using objects (see Touhou Danmakufu: Object Control Functions). There is also some related information that may help in my drawing tutorial.
Section 1: Concepts of Polygon-Based Rendering[]
In order to get the most out of effect objects, you'll need to understand the basics of polygon-based rendering. This is the basic technique used to draw almost all computer graphics in games these days. To put it simply, this technique is used to draw polygons onto the screen, usually with textures (images) on them. While it generally is used in 3D, effect objects are only 2D (well, not entirely ... but for now just go with it).
Note: this section does get a bit heavy with theory. You don't need to understand every last bit of it, but I think it'll help a lot when using effect objects.
No Squares Allowed[]
The first, and arguably the most important, concept to understand about polygon rendering is that everything is made of triangles. Now, you might be thinking "But I've seen many squares, octagons, etc ... in game X ... those aren't triangles!" But, in actuality, they are.
For instance, take a square. Now, draw a line from one corner to the opposite corner. Now you have two triangles; this is exactly how computers do it.
Games create complex shapes using nothing but triangles positioned around each other in various ways.
The main reason that triangles are used is that they only have three vertices (corners. Note: 'vertices' is the plural of vertex); this is important, because it guarantees that they will all be on the same plane and, thus, any combination of three vertices will always give a flat triangle.
Texture Mapping[]
Texture mapping is the technique used to draw images on the triangles.
Each vertex of a triangle, in addition to its other data, is given a set of texture coordinates. Texture coordinates give the point on the texture (image) to draw onto the triangle that the vertex is at. So, if a vertex is given the texture coordinates of (0, 0), that vertex will have the upper-left corner of the image at that point.
The texture is drawn onto the triangle such that all of the vertices have their texture coordinates lined up with the texture on the triangle. Depending on how you set the texture coordinates, this can lead to either a very normal-looking image or some really interesting effects.
Section 2: Using Effect Objects[]
Here's the section you all probably just skipped down to; this section deals with the actual commands to use effect objects.
Basics[]
First, you need to create an effect object. If you've dealt with objects before, then it should be a piece of cake:
let objid = Create_Object(OBJ_EFFECT);
Of course, objid is a variable that holds the effect object's identifier so we can work with it later.
Now, you can set the position and such like you do with other objects. The next important function to know is how to give the object a texture:
ObjEffect_SetTexture(objid, imagefile);
This gives the effect object the texture from the file name in the variable imagefile. Remember, you must call LoadGraphic first so that the graphic is loaded into memory. You can see more on that in my drawing tutorial.
Primitive Type[]
Next you want to assign a "Primitive Type" to the object. This is a pretty important feature; it determines how the list of vertices you will later give the object will be interpreted. There are three types:
- PRIMITIVE_TRIANGLELIST - The simplest of the three. Every three vertices you give the object are considered a separate triangle.
- PRIMITIVE_TRIANGLESTRIP - This creates a strip of connected triangles. The first triangle uses the first three vertices. Every triangle after that uses the last two vertices from the previous triangle, as well as the next one.
- PRIMITIVE_TRIANGLEFAN - This creates a fan of triangles. The first vertex is used for every triangle. The second and third vertex are used for the first triangle, the third and fourth for the second triangle, and so on.
A triangle list is the easiest to work with, and the most flexible, but it comes at the cost of needing to store most vertices.
Vertices[]
Once you have selected the primitive type, it is time to add in the vertices. First, you need to decide how many vertices you want for your object. If it is a triangle list, you will need a multiple of 3 vertices; for the other two primitive types, you can have any number of vertices that is at least 3.
ObjEffect_CreateVertex(objid, 3);
This creates some space for the effect object to hold its list of vertices (in this case, it creates space for 3 vertices). You only need to do this once for each effect object.
Next, you need to set the information for each vertex. There are multiple functions that handle different parts of this. There are two that are the most important, though. The first is the one that sets the position of the vertex:
ObjEffect_SetVertexXY(objid, 0, x, y);
This example sets vertex number zero (the first vertex - remember that the vertex list starts at zero) to the position (x, y). Note that this position is relative to the effect object's own position, so if the effect object is at (100, 150) and the vertex is given coordinates of (-25, 25), then the vertex will appear on the screen at (75, 175).
Next, we want to set a texture coordinate for the vertex. This allows us to define what part of the image will be showing:
ObjEffect_SetVertexUV(objid, 0, u, v);
This sets the texture coordinate of vertex zero to the coordinates (u, v) in the effect object's image: u is the x coordinate in the image, and v is the y coordinate. (0, 0) is the upper-left corner of the image. Additionally, if you go beyond the limits of the image, the image will repeat on an infinite loop.
A sample[]
This is a quick sample of the basics I've shown above. In order to run this, you'll need an image called bg1.png in the same directory as the script file (I used the same image as from the drawing tutorial).
#TouhouDanmakufu[Stage] #Title[Effect Object Test] #Text[by Nuclear Cheese] #Player[FREE] #ScriptVersion[2] script_stage_main { // Declare the image file name as a variable. // This makes it easier to reference it in code. let imagefile = GetCurrentScriptDirectory ~ "bg1.png"; let objid; let count = 60; @Initialize { // Load the graphic file into memory. LoadGraphic(imagefile); } @MainLoop { count--; if (count == 0) { // Create the object, and give it X and Y coordinates objid = Obj_Create(OBJ_EFFECT); Obj_SetX(objid, GetCenterX()); Obj_SetY(objid, GetCenterY()); // Set the object's texture ObjEffect_SetTexture(objid, imagefile); // Set the primitive type (here, we use a simple triangle list) ObjEffect_SetPrimitiveType(objid, PRIMITIVE_TRIANGLELIST); // Create the vertex list (3 vertices - just one triangle) ObjEffect_CreateVertex(objid, 3); // Set the coordinates and texture coordinates for the first vertex (number 0) ObjEffect_SetVertexXY(objid, 0, -20, -20); ObjEffect_SetVertexUV(objid, 0, 0, 0); // Second vertex (number 1) ObjEffect_SetVertexXY(objid, 1, 20, 0); ObjEffect_SetVertexUV(objid, 1, 255, 127); // Third vertex (number 2) ObjEffect_SetVertexXY(objid, 2, -20, 20); ObjEffect_SetVertexUV(objid, 2, 127, 255); } } @DrawLoop { } @BackGround { } @Finalize { // clear the loaded image file from memory DeleteGraphic(imagefile); } }
This script creates the effect object after one second, and places it in the center of the screen. The texture will look a bit warped, since that's how the texture coordinates are assigned.
No Effect Objects in @Initialize?[]
There is a reason I wait to create the effect object. When I was first playing around with effect objects, I tried to create one in @Initialize. But every time Danmakufu would crash.
It turns out that Danmakufu can't handle object creation in @Initialize.
Section 3: Other Tricks[]
There are some other things you can do with effect objects.
Scaling[]
By using the command
ObjEffect_SetScale(objid, sx, sy);
You can scale the effect object's size by the factors sx and sy in the x and y directions, respectively. For example, if you put 2 for sx and 3 for sy, the result would be that your effect object would be twice as wide and three times as tall.
Rotation[]
The command for rotation is:
ObjEffect_SetAngle(objid, rx, ry, rz);
This will rotate the effect object in three dimensions ... this is the only way (that I've seen, at least) to have an effect object work in 3D. For more information on how rotation works, please see my drawing tutorial.
Color[]
You can also set a color on a vertex by using the command
ObjEffect_SetVertexColor(objid, vertex, alpha, red, green, blue);
The red, green, and blue values indicate the color to use, with each value going from 0 to 255. alpha indicates opacity, with 255 being fully opaque and 0 being fully transparent.
The color you set on a vertex will be blended with the texture around that vertex, trailing off as it goes closer to other vertices.
Section O: Outro (for now)[]
Hopefully this will give a hand in using effect objects. Good luck!