- Title: Marquee banners and waving flags
- Description: Easily make marquee banners and waving flags using primitives and paths
- GM Version: GM 7
- Registered: Yes
- File Type: GMK
- File Size: 109kb
- File Link: http://host-a.net/ic...2b42/banner.gmk
Drawing marquee banners and waving flags is something that I always wondered how to do easily.
A marquee banner scrolls from left to right or right to left. While a flag flutter in the wind.
How to you set this up easily?
Using primitive triangle strip, you can setup a series a triangles that will define the shape of the banner or flag.
The texture mapping, a value from 0 to 1 for both u (left to right) and v (top to bottom) on the texture, is increased gradually from 0 to 1, for each triangle in the banner. If you set up say 100 triangles, you will have 100 uvs mapping 100 spots from left to right on the banner texture. The increment can be performed on u only for left to right, and the v value being 0 and 1 repeated over the length of the banner, you now have a strip of many triangles you can shape into a smooth looking banner.
To make the banner scroll, you simply need to change the uv mapping each draw to gradually move the texture inside the banner.
For example, if you have 2 triangle mapping a texture. From 0,0 0,1, 1,0 and 0,1, 1,0,1,1, if you decrease the u by .01, each draw, it will appear as though the banner is scrolling from right to left.
Defining how a banner or flag will look on the screen can be tedious as you have to define a lot of point that will translate into a series of triangle. BUT if you think about it, you can use the path system to make your banner.
You need 2 paths. 1 to define the top portion of the banner ribbon, another to define the bottom portion of the ribbon. The smoothing option of the path can turn you banner ribbon into any smooth shape you can think of.
Then you make a script that will loop though the 2 paths, getting the x and y value at an incremental position small enough to give smooth results while creating a ribbon using gm's primitive system.
Example loop
i = 0;repeat(100){ draw_vertex_texture(path_get_x(pathTOP,i),path_get_y(pathTOP,i)+yy,i,0) draw_vertex_texture(path_get_x(pathBOTTOM,i)+xx,path_get_y(pathBOTTOM,i),i,1) i+=.01;}Note that getting the path x,y values this way, using the 0 to 1 method, gets coordinates in between actual path points. It's a very useful GM feature for paths, especially for smooth and closed paths. AND, being a value from 0 to 1, incremented by .01 gives 100 points for the strip AND the value is compatible for use for the u value of the uv map. Essentially, you kill 3 birds in one stone:
1) Make shape banner
2) Smooths the banner shape
3) Maps the uv with no headaches
The next part, the scrolling marky is solved by adding an offset to the u value
Create
off = 1;
Draw
i = 0;repeat(100){ draw_vertex_texture(path_get_x(pathTOP,i),path_get_y(pathTOP,i),i+off,0) draw_vertex_texture(path_get_x(pathBOTTOM,i),path_get_y(pathBOTTOM,i),i+off,1) i+=.01;}off-=.01;Offset starts at 1, maps the texture outside GM's specs. The result is the triangle will be filled with the last pixel column of the texture. So make the texture transparent and make sure the texture has a transparent border all around to neutralize this behavior
The offset decreases, the marquee scrolls into view. When off is below 0, it scrolls out of view. When off is -1, it is done scrolling. Now the banner is filled with the pixel of the first column of the texture. Again, transparent border to fix this.
Flags fluttering in the wind or wiggling banner can be accomplished in a similar fashion. You use another path to define the wiggle.
i = 0;repeat(100){ draw_vertex_texture(path_get_x(pathTOP,i) + path_get_x(pathwiggle,i+off),path_get_y(pathTOP,i) + path_get_y(pathwiggle,i+off),i,0) draw_vertex_texture(path_get_x(pathBOTTOM,i)+ path_get_x(pathwiggle,i+off),path_get_y(pathBOTTOM,i) + path_get_y(pathwiggle,i+off),i,1) i+=.01;}off-=.01;I simplified code to explain the concept. It's actually a little more complex than that. You see now the banner is created from the first 2 paths as before but now, each point is offset from a wiggle path which the position changes over time. the position is actually kept within 0 and 1 in the actual script and mapped according to position using frac.
Like mod can be used to make sure a value rang is respected
angle = angle mod 360
frac can be use the same way
off = frac(off) to maintain the value in the respected range
if(off>1) off = frac(off)
Here are the resulting 2 script
//draw_banner(x,y,path0,path1,sprite_get_texture(sprite0,0),scrollposition(0 is start, 1 is end),vertical)//Draw a banner merging 2 paths as bannertop and banner bottom or banner left and banner right edges//x,y, the position of the first point of the banner will be at. use 0,0 for absolute// the first point of the top or left border (path0) is used to figure to absolute position//path0, path1, the 2 paths constituting the banner edges//texture, the texture of the banner//scroll position. when 0, the left or top of the texture will be at the start of the banner// when -1, the left or top of the texture will be at the last point of the banner// when 1, the right or bottom of the texture will be at the start of the banner// so, going from -1 the to 0 the banner will go from off the banner edge (invisible on the right if banner goes from left to right)// to being fully displayed the length of the banner// from 0 to -1, the banner will scroll left even more until it is gone. // Setup a variable to go from -1 to 1 step .01 to scroll the banner right to left//vertical, if true the texture is mapped vertically... If you make the paths go from top to bottom, set this to 1//use draw set color to change the color in your code//YOU MUST HAVE THIS//draw_set_color(image_blend);//Start the primitivevar i; i = 0;draw_primitive_begin_texture(pr_trianglestrip,sprite_get_texture(sprite0,0))var xx,yy;xx = 0;yy = 0;//If x,y is used, figure out where the first point is on the path and use as offestif(argument0 <> 0 or argument1 <> 0){ xx = argument0-path_get_point_x(argument2,0); yy = argument1-path_get_point_y(argument2,0);}//if horizontalif(argument6 == 0) repeat(100) { draw_vertex_texture(path_get_x(argument2,i)+xx,path_get_y(argument2,i)+yy,i+argument5,0) draw_vertex_texture(path_get_x(argument3,i)+xx,path_get_y(argument3,i)+yy,i+argument5,1) i+=.01; }else if(argument6 == 1) //if vertical repeat(100) { draw_vertex_texture(path_get_x(argument2,i)+xx,path_get_y(argument2,i)+yy,0,i+argument5) draw_vertex_texture(path_get_x(argument3,i)+xx,path_get_y(argument3,i)+yy,1,i+argument5) i+=.01; }draw_primitive_end()//draw_wiggle(x,y,path0,path1,path3,sprite_get_texture(sprite0,0),wiggleposition(0 is start, 1 is end),vertical,wiggledir)//like draw banner but this tim path 3 defines the wiggle, and position defines the wiggle position//x,y, the position of the first point of the banner will be at. use 0,0 for absolute// the first point of the top or left border (path0) is used to figure to absolute position//path0, path1, the 2 paths constituting the banner edges//texture, the texture of the banner//wiggle position. Pass a value from 0 to 1, incrementing my .01 for example, or 0 to -1 to reverse the movement... // Actually, mod is used so you simply need to pass a forever increasing or decreasing value //vertical, if true the texture is mapped vertically... If you make the paths go from top to bottom, set this to 1//The number of ripples in the flag depend on the number of point or rather waves in the wiggle path.// the wiggle path is better if it forms tiny repetitive circles//wiggledir 1 is from right to left, -1 is from left to right//use draw set color to change the color in your code//YOU MUST HAVE THIS//draw_set_color(image_blend);//Start the primitivevar i; i = 0;draw_primitive_begin_texture(pr_trianglestrip,sprite_get_texture(sprite0,0))var xx,yy;xx = 0;yy = 0;//If x,y is used, figure out where the first point is on the path and use as offestif(argument0 <> 0 or argument1 <> 0){ xx = argument0-path_get_point_x(argument2,0); yy = argument1-path_get_point_y(argument2,0);}//Get the offset of the first wiggle point so user can make the wiggle from any position withou affecting the end resultvar wx,wy,wi;wx = -path_get_point_x(argument4,0)wy = -path_get_point_y(argument4,0)//get the posiiton of the wigglwi = argument6//if horizontalif(argument7 == 0) repeat(100) { //keep wiggle within limits if (wi>1) wi = frac(wi) if (wi<0) wi = 1-frac(wi) draw_vertex_texture(path_get_x(argument2,i)+path_get_x(argument4,wi)+wx+xx,path_get_y(argument2,i)+path_get_y(argument4,wi)+wy+yy,i,0) draw_vertex_texture(path_get_x(argument3,i)+path_get_x(argument4,wi)+wx+xx,path_get_y(argument3,i)+path_get_y(argument4,wi)+wy+yy,i,1) i+=.01; //add to wiggle wi+=.01*argument8 }else if(argument7 == 1) //if verticalrepeat(100){ //keep wiggle within limits if (wi>1) wi = frac(wi) if (wi<0) wi = 1-frac(wi) draw_vertex_texture(path_get_x(argument2,i)+path_get_x(argument4,wi)+wx+xx,path_get_y(argument2,i)+path_get_y(argument4,wi)+wy+yy,0,i) draw_vertex_texture(path_get_x(argument3,i)+path_get_x(argument4,wi)+wx+xx,path_get_y(argument3,i)+path_get_y(argument4,wi)+wy+yy,1,i) i+=.01; //add to wiggle wi+=.01*argument8}draw_primitive_end()











