PDA

View Full Version : Script Drawing Functions Explained.



jman2050
01-05-2007, 05:38 PM
Okay, I think it's high time to explain the new drawing functions to all of you. So first, I'll start with a basic explanation, then the ZScript implementation, then the ZAsm implementation.

The drawing functions basically allow you to draw primitives or tiles on any layer, at any location on screen (save for subscreens), as well as apply rotation and scaling to said drawn objects. Right now, you can draw rectangles, circles, arcs, ellipses, lines, pixels, tiles, and combos. Spline support will be added in the future. The system works by calling each applicable drawing command. When done, this puts the command and the information it uses into a queue (which is 1000 commands long, more than enough unless you're doing seven million putpixel commands). When the screen is drawn, this queue is processed, drawing everything in it at once onto the screen. This queue is cleared every time the screen is drawn, so if you want to do continuous drawing, take this into account. Alternatively, we might allow an option to keep the queue in its current state between frames, but don't quote me on that.

Now, the ZScript implementation. Every function takes exactly 9 arguments. No more, no less. You'll notice that in some functions an argument does nothing. This is to keep the opportunity open for added arguments to said command. However, do note this: the implementation of both the ZScript and ZAsm drawing functions are subject to change before release, maybe dramatically. This may require you to rewrite and recompile your scripts in a later beta. Keep that in mind and you should be fine.

Anyway, here's an explanation of each command and its arguments:

Rectangle(float xy, float color, float xy2, float layer, float scale, bool fill, float rotation, float nothing, float nothing);

xy - This is the position on screen of the top-left corner of the rectangle. This is kinda hard to explain. Basically, for this argument and the xy2 argument, you'll need to pass both the X and Y values in one argument. How? Basically, the value to the left of the decimal point is the X value, while the value to the right is the Y value. As for how to handle negative Y values, just use the high end of the decimal range. For example, if you want -1, you'd use .9999, and if you want -4, you'd use .9996, etc. Remember that the whole decimal range is taken into account, so if you want a Y value of 2, you do .0002, NOT .2. The latter will be interpreted as 2000. So for example, a rectangle starting at 100,50 will use the value 100.0050. This scheme is LIKELY to change before release in order to simplify matters.
color - This is the physical palette color, not cset color. So to use cset 2 color 3 (the fourth color in the row), you'd use value 35 in here (2nd cset is the third row, thus color 0 is 32. Color 3 thus is 35).
xy2 - See above. This refers to the lower right corner of the rectangle.
layer - The layer to draw it on. Only valid values are 0-6. Self-explanatory.
scale - The scale factor. A scale of 1.0 is actual size. Note that when a primitive is scaled, it does not scale towards or from the center, but from the upper-left corner expressed in xy. If you want it to scale from the center, you'll have to do some math yourself.
fill - a bool value expressing whether you want a filled rectangle or not.
rotation - The rotation angle of the primitive. note that a full circle is NOT 360 degrees, it is in fact 256 "degrees". Thus, 64 is a right angle, 32 is a 45 degree angle, etc. The rotation is clockwise.
nothing - For now, anything with an argument as 'nothing' should be filled with 0s or false, depending on the type of argument it is.

Circle(float xy, float color, float radius, float layer, float scale, bool fill, float rotation, float nothing, float nothing);

radius - The radius of the circle. Self-explanatory.
others - See above

Arc(float xy, float color, float radius, float layer, float scale, bool fill, float rotation, float start, float end);

start - The angle in which to start drawing the arc.
end - The angle in which to end drawing the arc.
Note that the above, unlike the rotation angle, go counterclockwise.

Ellipse(float xy, float color, float radxy, float layer, float scale, bool fill, float rotation, float nothing, float nothing);

radxy - The X radius and the Y radius of the ellipse. This has the same format as xy, except Y shouldn't be negative in any case.

Line(float xy, float color, float xy2, float layer, float scale, bool nothing, float rotation, float nothing, float nothing);

xy2 - See above. The line is created with xy being the first coordinate and xy2 being the second, drawing a line between the two.

PutPixel(float xy, float color, float nothing, float layer, float nothing, bool nothing, float nothing, float nothing, float nothing);

Self-explanatory

DrawTile(float xy, float tilecset, float wh, float layer, float scale, bool nothing, float rotation, float flip, float nothing);

tilecset - Has the same format as xy, except the right of the decimal point shouldn't be negative. The left of the decimal point is the starting tile to draw, while the right is the cset to use.
wh - Same format as xy, except the y portion shouldn't be negative. Refers to the width and height of the drawn area in tiles. For w it'll draw the tiles consecutively after the first. For h, each row of tiles starts 20 tiles from the origin, consecutively 9so the third row would start 40 tiles from the origin. Neither of these can be less than 1 or greater than 20.
flip - The flip value. It will be ANDed with 3 before processing. The result: if 0, no flip, if 1, horizontal flip, if 2, vertical flip, if 3, both flip. I may have mixed up the flips, but you'll figure it out :/

DrawTile(float xy, float combocset, float wh, float layer, float scale, bool nothing, float rotation, float nothing, float nothing);

combocset - Same as above, except referring to the combo number.

Hopefully, that wasn't too complicated. Now, in ZAsm, it's a tad more difficult to get things going. Basically, you have to take all 9 arguments, in order, INCLUDING NOTHINGS, push them to the stack, call the applicable function (RECT, CIRCLE, ARC, ELLIPSE, LINE, PUTPIXEL, DRAWTILE, DRAWCOMBO), then pop the 9 arguments from the stack. Example code is like this

PUSHV 1.0001
PUSHV 17
PUSHV 10.0010
PUSHV 0
PUSHV 1
PUSHV 1
PUSHV 0
PUSHV 0
PUSHV 0
RECT
POP d0
POP d0
POP d0
POP d0
POP d0
POP d0
POP d0
POP d0
POP d0

Simple, no? That should be it for now. If you have any questions (and you will), ask them here.

Revfan9
01-05-2007, 05:49 PM
A question about the Zasm part: Is that exactly how the code would look? I'm a tad confused about the PUSH and POP functions. If it does work how I think it does (you push and pop every last one of those arguments and they are all loaded into d0?) then I'm all set.

jman2050
01-05-2007, 05:58 PM
Basically, there's a stack for each script, that holds values temporarily. Think of it as a queue. You 'push' elements to the top of the stack, sort of like you put a piece of paper on top of a stack. You pop each element by taking the top element and taking it off of the queue, or stack. What's going on here is that the 9 arguments are pushed into the stack, then read by the function when it's executed. The popping them into d0 is just to clear the stack off. d0 doesn't have any other purpose than as filler.

Revfan9
01-05-2007, 06:06 PM
Okay, I have that down now. From what I understand... This would put a solid block (combo 86) in the upper-left corner on layer 0, correct?

PUSHV 0
PUSHV 86
PUSHV 1.1
PUSHV 0
PUSHV 1
PUSHV 0
PUSHV 0
PUSHV 0
PUSHV 0
DRAWCOMBO
POP d0
POP d0
POP d0
POP d0
POP d0
POP d0
POP d0
POP d0
POP d0

jman2050
01-05-2007, 06:30 PM
1.0001. Remember, .1 will be interpreted as 1000 by the compiler.

blue_knight
01-06-2007, 04:19 AM
Rectangle() seems to work properly but I can't seem to get DrawCombo() to work correctly. In my script (as a test) I have
DrawCombo(1.0001, 3.0003, 1.0001, 0, 1, false, 0, 0, 0);
x = 1, y = 1.
Combo = 3, CSet = 3
ComboWidth=1, ComboHeight=1
Layer = 0
Scale = 1
Rotation = 0
I've tried larger ComboWidth/Height, larger scale, but nothing ever shows up. However as I said before the rectangle works fine. Do I have the arguments right? I have the exact same problems with DrawTile() as well.

_L_
01-06-2007, 06:44 AM
Basically, there's a stack for each script, that holds values temporarily. Think of it as a queue.*stifled chortle*

But anyways, congratulations on implementing all of these Game Maker-style drawing functions.

(Thinks: if only there way some way that the Farore's Wind particle system could also be harnessed...)

jman2050
01-06-2007, 11:37 AM
I'm an idiot. DrawTile and DrawCombo should be fixed in beta 17.