ID:1963229
 
Hope you had a good Bartolomé Day this week.

This week saw a couple of new 509 releases, and I'm aiming for the next one to come out on Monday. A couple of issues came up on the compiler end a short while back, so I recommend compiling with 509.1304 if you need any of the beta features in your game; 1308 should finally take care of the remaining issues there.

One of the thorns in my side with 509 has been the DirectX implementation--namely, that some newer systems inexplicably don't support the version we're using. Fortunately, I finally have a solution for that: The installer for 509.1308 will fix that problem too. I still have to test the installer used by the standalone as well.

Webclient work continues, and in particular I'm still trying to trim down the CPU usage so that it can achieve high FPS with high view. I found a few places today I was able to make a few modest improvements, and the search continues for more. Chrome users: keep the CPU profile results coming as new versions emerge! Those are incredibly helpful.

Looking ahead to 510, I intend to add a breaking change: HUD objects will no longer be able to interleave with map objects, but must appear above or below--on a different virtual plane. This is already the case for SIDE_MAP and ISOMETRIC_MAP modes, and TOPDOWN_MAP is going to get this treatment too just because there's really no reason to allow some map objects to appear above the HUD and some below--not when we've had EFFECTS_LAYER and BACKGROUND_LAYER forever, and now have the far superior plane var. I may include exceptions--with the downside that this complicates the drawing code--for games built prior to 510.

The reason for this change is that I had an idea of how I could extend the engine to allow for more immersive games, and effects like simple lighting. The concept I have is that a particular plane can be marked as special, and it will have a "master" atom with its own blend_mode, color, transform, etc. All other atoms on the plane will be drawn normally onto a blank surface, and then the master atom's settings will determine how that surface is drawn on the map. (Short version: You could have a master atom with BLEND_MULTIPLY on plane 1, and then draw "lights" onto plane 1 with BLEND_ADD mode. The lights all get added together and then the whole thing is multiplied over the map.) And that's more than just an idea; I ran a proof-of-concept test on it.

In miscellany, I'm going to add savefile.Flush() in 510. I'm also strongly considering some more text manipulation functionality, as a number of games would benefit from a native implementation of things like joining lists, splitting, tokenizing, etc. All of that can be done with text in soft code, and often is, but I know a number of games find string manipulation to be a drag on their performance.

Keep working on your Halloween games, and please don't forget to hit us with a donation or Membership. I'd encourage anyone with a Halloween game, finished or not, new or not, to send info and screenshots to Higoten. He's been doing a bang-up job with the Within BYOND posts, and if I'm right on my timing his next one should be coming on the night of the 28th. He's always looking for new material, so let's give him some!
nice job keep up with the good work
Good work!
There you go getting me all excited and whatnot again!
Could we get an ETA on when the plane blend_mode is going to be rolled out?
I really want it for 510. What I'm trying to figure out is what kind of syntax I'll be looking at for the master plane object.
The only one I know of is Pokemon Z by Zete.
There were a couple isometric games being made, but I think they all got cancelled. I'm pretty sure there are no isometric games released, ever, aside from more or less test of concept stuff.

I've been hoping to change this in the not too distant future, if I get time, but I suspect it may be a challenge. Otherwise I would think more people would make isometric.
I always thought Zen would've been better as an iso game. You could've done more with the wall crafting elements.
In response to Lummox JR
Lummox JR wrote:
I really want it for 510. What I'm trying to figure out is what kind of syntax I'll be looking at for the master plane object.

How about a /planeEffects datum that holds all of the attributes you mentioned above. And then getter and setter functions under /client for these things?

To be frank, I don't see much point of making this an atom.
Lummox I would be really interested(and I suspect I'm not the only one) in knowing how to use the color matrices and what exactly is the best way to use them(as well as most of the BLEND features). If you happen to do any cool effects with the game you are working on, maybe you can post a picture and code example of it at work. It would be amazing to get examples right from the 'source' and see exactly what the capabilities and limitations of things really are.
In response to Exentriks Gaming
I'm afraid that's not quite how it works, whilst I fully expect Lummox JR to be an incredible DM guru, I doubt he's better than a few other faces. Mostly because he doesn't have time to play around, though I do believe his game - http://www.byond.com/games/LummoxJR/SotS2 - is supposed to showcase the engine's capabilities (Don't quote me on that!) it hasn't been updated in a while.

Lummox might be great at making hammers and chisels, but he isn't a master sculptor, so to speak.
In response to Rushnut
I only brought it up because he said he is currently messing around with a game of his. I figured he's probably going to be adding on and testing these features on there regardless; so it would be really nice if he gave us an idea of what can be done. Also, it's not really fair to assume that Lummox can't make a proper, fun and professional game... If you look through his creations, his games are actually pretty well done for how old they are.
The matrix given as an example in MapColors() (although that's as args, rather than a list) is a good example. Apply that to client/color and you have a nice nighttime moonlight effect.

client/proc/Night()
color = list(0.2,0.05,0.05, 0.1,0.3,0.2, 0.1,0.1,0.4)

In this simplified RGB-only form (which leaves out an alpha column and row), every three values represents a row in the matrix. The first row is what color the red component will become; the next is what green becomes; the last is what blue becomes. All of the result color values get added together.

In this matrix, full red rgb(255,0,0) becomes rgb(255*0.2,255*0.05,255*0.05). It's darkened a lot, and a little bit of blue and green are added to pull it closer to gray. Blue goes through something similar, except it isn't darkened nearly as much. Green does the same, but a little more blue is added so it experiences a hue shift. As a result of this, yellow rgb(255,255,0) becomes rgb(255*0.2+255*0.1+0*0.1, 255*0.05+255*0.3+0*0.1, 255*0.05+255*0.2+0*0.4), or rgb(77,89,64), a very dark and desaturated yellow-green.

Here are some real examples from SotS II.

In the original game code, I had a lot of icons that were shades of dark gray. The wall icons for instance were mostly dark colors, and they were colorized like so:

var/icon/I = new('wall.dmi')
I.Blend(rgb(255-r,255-g,255-b), ICON_MULTIPLY)
I.Blend(rgb(r,g,b), ICON_ADD)

In this way, any white in the original icon stays white, and black becomes the color. 509's matrix support let me change this by simply applying a color to the wall instead of changing its whole icon:

color = list(1-r/255,0,0,0, 0,1-g/255,0,0, 0,0,1-b/255,0, 0,0,0,1, r/255,g/255,b/255,0)

That's the full format that uses an alpha column and an alpha row. The first row is what red becomes, which is the inverse of the red color I actually want. Green and blue get the same treatment. The last row is the constant row that gets added to everything, so that's what I expect to see when the original color is black. I actually built this into a proc so that it's a little easier to work with.

// black becomes color, white stays white
var/list/_whitematrix = new
proc/WhiteMatrix(c)
. = _whitematrix[c]
if(!. && c)
var/image/I = new
I.color = list("#ff0",null,null,null,c) // use yellow to force a matrix
var/list/L = I.color
L[2] = 0
// rgb * (1-color) + color
L[ 1] = 1-L[17]
L[ 6] = 1-L[18]
L[11] = 1-L[19]
. = L
_whitematrix[c] = .

This is basically using a "cheat" to let the internal matrix parsing do most of the work for me, avoiding the need to parse the RGB() values of a color string and divide by 255. First I create a new color matrix on a temporary image. The first row is set so that red becomes yellow, so that the result will always be a matrix. (If the target color c is black, that wouldn't have been guaranteed.) The green, blue, and alpha rows are left as the defaults, and the constant row is c, the target color. I then grab the matrix into a list, make adjustments, and send that list back as the result.

This matrix is very similar to a typical inverse matrix:

// inverse color
// alpha is left alone, but use negatives for r,g,b and add to white
color = list(-1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1, 1,1,1,0)

In SotS II, I don't actually use that WhiteMatrix() proc very often. I use a more complex matrix, where I can add blue pixels to the walls that will become black, for cracks and (for effects) outlines.

Here's another matrix I use, when I want to have one icon become a colored version that has highlights. I've often stated my fondness for this sort of thing, which I did in Incursion a lot:

var/icon/colored = new('myicon.dmi')
colored.Blend(c, ICON_MULTIPLY)
colored.Blend('myicon-highlights.dmi', ICON_ADD)

Unfortunately this technique either requires two icons, or it at least requires the color and highlight parts to be separate states in the same icon. A different approach is to combine them, using the red component for your target color and the green for highlights. That would have looked like this before 509:

var/icon/colored = new('myicon.dmi')
colored.MapColors(c, "#ffffff", "#000000")

But in 509, you don't need to do any icon math. You can simply set the atom's color to list(c,"#fff","#000") instead, and all the highlights are created.
Man, I really need to spend some time wrapping my head around matrices. I should've known skipping math classes would bite me in the ass one day.
In response to Kumorii
Kumorii wrote:
Man, I really need to spend some time wrapping my head around matrices. I should've known skipping math classes would bite me in the ass one day.

Seriously. I'm kicking myself in the ass for sleeping through 11th grade math...
In response to Kats
Joining the club here. Wishing I were starting remedial math in college sooner than I am, which having to take it to begin with is messed up as is. Damn math...
Matrices are not, in principle, a very difficult concept. The simple case of a function in n variables is a good illustrating example. That is, say you have a function f(x) = a1 x1 + ... + an xn, where x is a vector with x = <x1, ..., xn>.

Then you can rewrite this as a product of two matrices as

                         [ x1 ]
                         [  .  ]
 f(x) = [ a1  ... an ] . [  .  ]
                         [  .  ]
                         [ xn ]

In this case, matrix multiplication is essentially simply the application of coefficients to another vector. More specifically, when you have a row vector and a column vector, your result is a 1x1 matrix (mathematically, you would say it's isomorphic to an element of your field—but a simpler way of stating it is that it becomes something that acts 'the same' as a function or a number).

That is, the row vector tells the column vector how to change. If you want to make, say, x3 twice as big and x9 a third as big, then you set a3 = 2 and a9 = ⅓.

Likewise, if you have a left-hand side matrix with, say, three rows, you get

                [ x1 ]
  [ a1 ... an ] [  .  ]   [ a1 x1 ... an xn ]
  [ b1 ... bn ] [  .  ] = [ b1 x1 ... bn xn ]
  [ c1 ... cn ] [  .  ]   [ c1 x1 ... cn xn ]
                [ xn ]


Now, you have something similar to above, but instead it's saying that your result is a vector in three dimensions instead of one, and the row vector <a1, ..., an> wants the output to behave in one way in the first dimension, the row vector <b1, ..., bn> tells it to behave another way in the second dimension, and <c1, ..., cn> tells it to behave a third way in the third dimension.

This is related to an extremely important result of linear algebra, which says that if you have a transformation T with certain restrictions (specifically, that T(a x + b y) = a T(x) + b T(y) for all a, b in the base field and all x, y in your vector space, so that T is what is called a linear transformation), then once you have chosen what is called a basis, you can represent the linear transformation as a matrix acting on that basis.

An example of how useful these techniques are can be see here, where I was able to build up a new function from an initial function C'(t) = <sin(t), -½ cos(t) + ½> by knowing the necessary transformations—that all you had to do was squish the function down, stretch it out, and rotate it.

As another example, imagine you have a function f(x) = 3x3 + x2 that describes the motion of a particle in your game, and you like how it looks but you'd like to be able to change it on the fly a bit (maybe stretch it out, or squish it, or flip it around). There are a couple ways to do this, but matrices are one of them. This may be confusing at first if you've been paying attention, as f is clearly not a linear function of x: f(2x) = 24x3 + 4x2 ≠ 6x3 + 2x2 = 2 f(x). The difference is, you view it in another way, as a function g(a, b) = a x3 + b x2 at the point (3, 1). Why does this make sense? We want to keep the general shape of f, but that is dictated by x3 and x2, not by its coefficients which indicate the 'scale' or the function, or more like its specific appearance.

Thus, we can treat g as a two dimension function where a is its first-dimensional component (influencing the x3 term) and b its second-dimensional component (influencing its x2 term). What if we want to flip it around in the x2 component and make it half as big, and make the x3 component four times larger? The suitable matrix for this is
  T = [4  0]
      [0 -½]

and then we have the result given by T(<a, b>)as,
  T(<a, b>)

  = [4  0] [ a ]
    [0 -½] [ b ]

  = [  4a ]
    [ -½b ]

Using the linearity of g, then we have g(T(<a, b>)) = g(4a, -½b) = 4a x3 - ½ b x2, and recalling that we were at the point (3, 1) our final result for our transformed function f* is then: f*(x) = 12x3 - ½x2.
In response to Lummox JR
Lummox JR wrote:
// black becomes color, white stays white
> var/list/_whitematrix = new
> proc/WhiteMatrix(c)
> . = _whitematrix[c]
> if(!. && c)
> var/image/I = new
> I.color = list("#ff0",null,null,null,c) // use yellow to force a matrix
> var/list/L = I.color

> L[2] = 0
> // rgb * (1-color) + color
> L[ 1] = 1-L[17]
> L[ 6] = 1-L[18]
> L[11] = 1-L[19]
> . = L
> _whitematrix[c] = .


I just have a couple questions:
So with this you would turn an icon completely white? Was this not possible before by just doing src.color = rgb(255,255,255)?

Also, in your example what is "c", and why are you passing it to the proc?

What is happening with the matrix exactly, what is L[ 1] = 1-L[17] doing and what would be the result of that subtraction?

edit: Also a big question that I have is: Would it be possible to use this color matrix to have a multi colored client.screen?

Everything else was really helpful, I have a good idea of how I will make use of this now. I apologize for the questions but I think it'll help me a lot and others here too.
In response to Exentriks Gaming
Exentriks Gaming wrote:
I just have a couple questions:
So with this you would turn an icon completely white? Was this not possible before by just doing src.color = rgb(255,255,255)?

Also, in your example what is "c", and why are you passing it to the proc?

My WhiteMatrix() proc, which returns a color matrix, is not designed to make an icon white. If you wanted to make an icon completely white, all you'd need is this:

// put white in the constant row; all other rows are default
color = list(null, null, null, null, "#fff")

That matrix will specifically alter only the rgb, but the alpha will be left alone.

WhiteMatrix() on the other hand was designed so that the range black -> white would become c -> white instead, where c is the color I want the wall icon to be. Since my wall icon is mostly dark shades of gray with a crayon-drawn look to it, it looks like I took a c-colored crayon and drew on a white background.

What is happening with the matrix exactly, what is L[ 1] = 1-L[17] doing and what would be the result of that subtraction?

Let's go through the proc line by line. First, let's say the target color I want the wall to be is purple, "#8000FF" (which is the result of rgb(128,0,255)). That's the value of c that's being passed in.

First, I create a new image and assign it a color matrix of list("#ff0",null,null,null,c). This is the matrix that results:

//L = list(1,1,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 128/255,0,1,0)

The first row (red) got the yellow value; basically, I forced L[2] to be something other than 0 because this way I.color is definitely a matrix. The green, blue, and alpha rows are the defaults which means those color components will be left alone. The constant row has my purple color, which is added to the result.

Now the proc changes L[2] to 0, since the only purpose in setting it was just to force a matrix.

L[2] = 0
//L = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 128/255,0,1,0)

At this point the matrix is equivalent to taking the original color and adding purple.

Next, I want to change what the red, green, and blue rows will do. I want the red in the original icon to add whatever's missing to make white from a base color of purple, so that'd be 1-128/255. Likewise for green, and blue.

L[ 1] = 1-L[17]
L[ 6] = 1-L[18]
L[11] = 1-L[19]
//L = list(127/255,0,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,1, 128/255,0,1,0)

And that's my finished matrix.

Now, if I set a wall to use this color, it's basically the same as saying rgb * (white-purple) + purple. The black parts become purple. The white parts become (white-purple)+purple which is just white. And any shade in between is somewhere between purple and white.

edit: Also a big question that I have is: Would it be possible to use this color matrix to have a multi colored client.screen?

I don't follow. The client.color value is basically map-wide, if that's what you mean.
Page: 1 2