Discuss and collaborate on GML scripts

You are not logged in.

- Topics: Active | Unanswered

Lots of interesting ideas here, thanks for sharing!

Can anyone recommend a good (fast/comfortable) coding keyboard?

Nice solution!

I don't think you would want to use any buffer-filling approach to generate a 3D diagram. Even with with a good OpenCL implementation on a modern GPU, filling the 3D buffer would be orders of magnitude slower than filling a 2D buffer, and the RAM consumption could quickly go into the gigabytes.

It could work if you only need a low-resolution grid, but the traditional algorithms for generating Voronoi diagrams would be more flexible, since their time complexity is affected only by the number of regions and not by desired precision.

Very clever!

Another issue is blend mode 13. Is it really something different as 1 to 11? Or is it only a tale?

Yeah, 12 and 13 have been obsolete for a long time. I suppose if we were interacting with the D3D API directly, we could save a line of code by calling

`d->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BOTHSRCALPHA);`

instead of

```
d->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
d->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
```

But presumably GM sets the source mode and then the destination mode in response to draw_set_blend_mode_ext, so mode 13 should have the same effect as bm_src_alpha. (Unless it's used illegally as the destination mode. I think it would be ignored in that case.)

Great story, xot, thanks for sharing.

`This read-only variable indicates whether the game is running in debug mode.`

debug_mode

Better late than never...

It had to happen... yet another GML highlighter!

=[] !

I don't know the architecture too well, but I see a few approaches --

- You could have a page action (essentially a button in the URL bar that shows up for certain pages and does something when pressed). This would be tedious because the script which is triggered upon clicks can't access the DOM of the current page directly, so you'd need to set up a "content script" (as I understand it, these are loaded for each page and can access the DOM of the page) and have the two components communicate with messages.

- You could have a content script associated with tutorial pages which inserts an html button into the page. It might look something like

`<a href="javascript: a lot of code involving XMLHttpRequest">Reject this tutorial</a>`

I don't think browsers will allow external scripts to make XMLHttpRequest calls to the gmc.yoyogames.com domain, so you might need to stuff all the javascript in the link.

- Actually open the pages using window.location.href="some URL" calls, as if you were clicking the buttons. I believe content scripts themselves are not persistent (as in they go out of scope when pages do), but you could use a "background script" to keep track of the state of the automation.

I think the third approaches would be most viable, but I might be overlooking some difficulty since, again, I don't know the architecture too well.

Hm, it seems to work for me... are you sure you're using "Filter by Member Name" as opposed to "Search by Keywords"?

The other thing I'm planning to automate is authentication. Wouldn't it be cool if login screens went away the moment they popped up? Especially for websites with "security features" like autocomplete=off to prevent browsers from helping. Of course, this would mean storing clear text passwords on disk. But who would want to get into my PayPal account anyway? Not like they'd find any money there.

**xDanielx**- Replies: 8

I don't post too much on the GMC these days, but I have this weird addiction to keeping track of old discussions, so I often search my own name in the advanced search form. Problem is, I do this a lot and, though I have the advanced search bookmarked, I don't like all the typing. Other problem is, I needed an excuse to try out Chrome's extension framework!

The solution turned out to be pretty trivial. We just create a directory with two text files:

manifest.json wrote:

{

"name": "GMC Search Form Automator",

"version": "1.0",

"description": "Automatically fills out and submits the Game Maker Community advanced search form.",

"content_scripts": [

{

"matches": ["http://*.gmc.yoyogames.com/index.php*act=Search&mode=adv"],

"js": ["gmcs.js"]

}

]

}

gmcs.js wrote:

document.getElementById("entered_name").value = "YOUR USERNAME HERE";

document.sForm.submit();

Then from the extensions page, expand "Developer mode" and click "Load unpacked extension." Select the directory containing the extension. All done!

Note that the extension framework hasn't made its way into the stable release yet, so this requires the beta version.

I'll try my hand at an explanation. I don't know too much about your background, so I'm probably assuming much less than I could... but perhaps someone else will benefit from the basic overview.

In single variable calculus, we do all kinds of things with functions in 2D space by treating them as if they were made up of (infinitely) many of straight lines. We can do the same thing with a 3D object by thinking of it as a bunch of tiny polygons. Think of taking a rigid mesh in a traditional modeler and smoothing it more and more until the polygons are so small that the model might as well be continuous.

When we're shading a vertex, we really want to know the orientation of one of the tiny polygons in the neighborhood of that vertex. (For those not familiar with the physics, the shader needs to know the angle of incidence -- that is, the angle at which light hits the surface -- to compute how much light is emitted.)

But since we're not actually storing these tiny polygons in memory, we don't actually give the shader a polygon. Planes are nice simple objects, so instead we give the shader a description of a plane which has the same orientation as the tiny polygons near our vertex. This is called the tangent plane, and is illustrated below:

There are different ways of describing a plane -- we could list three distinct points on it, for example -- but for most purposes we want a normal (aka orthogonal) vector. Orthogonality between vectors and planes is essentially like perpendicularity between lines, we just generalize the concept by adding a dimension.

So for shading a vertex, we want the vector that's normal to our surface at that point, as this vector describes the tangent plane which describes the direction of the surface at that particular point. How then do we compute the normal vector?

One fairly general approach to computing normal vectors involves finding partial derivatives. These are just multivariable calculus's generalized version of simple derivatives. If we have a single variable function [tex]f(x)[/tex], the derivative [tex]\frac{df}{dx}[/tex] describes how f varies with respect to x (the slope of f in a plot of f against x). Given some multivariable function [tex]f(x,y)[/tex], the partial derivative [tex]\frac{\partial f}{\partial x}[/tex] describes how f varies with respect to x, while [tex]\frac{\partial f}{\partial y}[/tex] describes how f varies with respect to y. Note that the partial derivates may potentially still have x and/or y terms, just as the slope of a single-variable function might depend on where we are on the curve.

Given a surface function [tex]f(x,y)[/tex], we are usually interested in the partial derivative for some particular (x, y) (compare to the slope of a single-variable function at a particular x). Say we want to find [tex]\frac{\partial f}{\partial x}[/tex]. This is really another function of x and y, but we might want to evaluate it at (x=a, y=b). Since we're only interested in a particular y value, we can take the cross section of the surface with respect to the plane y=b. Algebraically, this like like substituting b for y in the equation for f. (We can't do this with x yet because we are differentiating f with respect to x.) Now we are left with a simple two-dimensional curve, of which we can easily find the slope at (x=a). This is illustrated below:

Notice that the black line, whose slope is [tex]\frac{\partial f}{\partial x}(a,b)[/tex], is tangent to the surface at (a, b). If we also compute [tex]\frac{\partial f}{\partial y}[/tex], we will get a second vector tangent to the surface at (a, b).

Now, let's accept without proof that the cross product of any two vectors, [tex]u \times v[/tex], yields a third vector which is orthogonal (informally, "perpendicular") to both u and v. Say we need to shade the vertex (x=a, y=b). Since [tex]\frac{\partial f}{\partial x}(a, b)[/tex] and [tex]\frac{\partial f}{\partial y}(a, b)[/tex] are both tangent to the surface f at (a, b), their cross product must be normal to the surface at (a, b). And this normal vector describes the tangent plane at (a, b), which describes the "direction" of the surface at (a, b), which is what the shader needs.

Now let's talk about Bézier surfaces specifically. We can describe a Bézier surface as

[tex]f(u, v) = \sum_{i=0}^n \sum_{j=0}^m B_i^n(u) \; B_j^m(v) \; P_{i,j},[/tex]

where

[tex]B_i^n(u) = {n \choose i} \; u^i (1-u)^{n-i}.[/tex]

We would like to find two partial derivatives; we can write the first one as

[tex]\frac{\partial f}{\partial u} = \frac{\partial}{\partial u} \left( \sum_{i=0}^n \sum_{j=0}^m B_i^n(u) \; B_j^m(v) \; P_{i,j} \right)[/tex]

From here we must apply some rules of calculus, which I assert without proof. First, the derivative of a sum is the sum of the derivatives. This is usually stated as

[tex]\frac{\partial (f + g)}{\partial x} = \frac{\partial f}{\partial x} + \frac{\partial g}{\partial x},[/tex]

but it holds for sums in general. So,

[tex]\frac{\partial f}{\partial u} = \sum_{i=0}^n \sum_{j=0}^m \frac{\partial}{\partial u} \left( B_i^n(u) \; B_j^m(v) \; P_{i,j} \right)[/tex]

Next, the derivative of a scaled function is the scaled derivative of that function, i.e.,

[tex]\frac{\partial (c f)}{\partial x} = c \frac{\partial f}{\partial x}[/tex]

Thus we can "bring out" constant multipliers. More generally, if we're differentiating with respect to u, we can "bring out" any terms which have no u dependence. Conceptually, this makes sense since when we partially differentiate a function with respect to u, we are only interested in its u dependence; unrelated variables might as well be constant. Thus we have

[tex]\frac{\partial f}{\partial u} = \sum_{i=0}^n \sum_{j=0}^m B_j^m(v) \; P_{i,j} \; \frac{\partial}{\partial u} ( B_i^n(u) )[/tex]

[tex]= \sum_{i=0}^n \sum_{j=0}^m B_j^m(v) \; P_{i,j} \; \frac{\partial}{\partial u} \; \left( {n \choose i} u^i (1-u)^{n-i} \right)[/tex]

To deal with the exponents, we must combine the power rule,

[tex]\frac{\partial (x^n)}{\partial x} = n x^{n-1},[/tex]

with the product rule,

[tex]\frac{\partial}{\partial x}(f g) = f \frac{\partial g}{\partial x} + g \frac{\partial f}{\partial x},[/tex]

and the chain rule, which we use to use to differentiate "chains" of functions:

[tex]\frac{\partial y}{\partial x} = \frac{\partial y}{\partial u} \frac{\partial u}{\partial x}.[/tex]

If these rules are unfamiliar, you might want to read about them elsewhere (unless you're just interested in the result).

Applying these rules yields

[tex]\frac{\partial f}{\partial u} = \sum_{i=0}^n \sum_{j=0}^m B_j^m(v) \; P_{i,j} \; \left(\frac{n!}{i! \; (n-i)!}\right) \left( i \; u^{i-1} \; (1-u)^{n-i} - (n-i) \; u^i \; (1-u)^{n-i-1} \right)[/tex]

[tex]= \sum_{i=0}^n \sum_{j=0}^m B_j^m(v) \; P_{i,j} \; \left( \frac{n! \; i \; u^{i-1} \; (1-u)^{n-i}}{i! \; (n-i)!} - \frac{n! \; (n-i) \; u^i \; (1-u)^{n-i-1}}{i! \; (n-i)!} \right)[/tex]

[tex]= \sum_{i=0}^n \sum_{j=0}^m B_j^m(v) \; P_{i,j} \; n \; \left( \frac{(n-1)! \; i \; u^{i-1} \; (1-u)^{n-i}}{i \; (i-1)! \; (n-i)!} - \frac{(n-1)! \; (n-i) \; u^i \; (1-u)^{n-i-1}}{i! \; (n-i) \; (n-i-1)!} \right)[/tex]

[tex]= \sum_{i=0}^n \sum_{j=0}^m B_j^m(v) \; P_{i,j} \; n \; \left( {n-1 \choose i-1} u^{i-1} \; (1-u)^{n-i} - {n-1 \choose i} u^i \; (1-u)^{n-i-1} \right)[/tex]

[tex]= \sum_{i=0}^n \sum_{j=0}^m B_j^m(v) \; P_{i,j} \; n \; \left( B_{i-1}^{n-1}(u) - B_i^{n-1}(u) \right).[/tex]

By the same process, we find that

[tex]\frac{\partial f}{\partial v} = \sum_{i=0}^n \sum_{j=0}^m B_i^n(u) \; P_{i,j} \; m \; \left( B_{j-1}^{m-1}(v) - B_j^{m-1}(v) \right).[/tex]

So, a vector normal to the surface at (u=a, v=b) is given by

[tex]\textbf{n} = \frac{\partial f}{\partial u} \times \frac{\partial f}{\partial v} = \left( \sum_{i=0}^n \sum_{j=0}^m B_j^m(v) \; P_{i,j} \; n \; \left( B_{i-1}^{n-1}(u) - B_i^{n-1}(u) \right) \right) \; \times \; \left( \sum_{i=0}^n \sum_{j=0}^m B_i^n(u) \; P_{i,j} \; m \; \left( B_{j-1}^{m-1}(v) - B_j^{m-1}(v) \right) \right)[/tex]

I suspect that this could be simplified a bit with some more combinatorics, but it's about my bedtime. I hope this is helpful to someone.

Nice polish!

I signed up for OnLive's beta long ago, but haven't heard anything back... can't wait to try it out.

Gaikai has been looking pretty promising also -- check out their slightly old demo.

I have just the solution for you:

`rm -r ~`