Closed Thread Icon

Topic awaiting preservation: Godot and Auto-Tiling WJ-style Pages that link to <a href="https://ozoneasylum.com/backlink?for=33334" title="Pages that link to Topic awaiting preservation: Godot and Auto-Tiling WJ-style" rel="nofollow" >Topic awaiting preservation: Godot and Auto-Tiling WJ-style\

 
Author Thread
warjournal
Maniac (V) Mad Scientist

From:
Insane since: Aug 2000

posted posted 10-11-2020 02:40

Towards the end of quarantine in my area, I was finally getting my mojo
back. I was getting into Godot, Krita, and Blender to make a game.
Little did I know that I would be heading off into a vastly wild
direction. I just wanted to make a little thing for myself, but ended
up digging down yet another hole.

Now I'm back to my regular job and don't have much time for these
things. And yet I still try my damnest to find an oasis of time to play
with the things that I love and adore.

I love manipulating data. I will look at data in multiple ways until I
see something that makes sense to me. I will then understand it and
manipulate it to my will. Mixing dimensions and all that. I also love
chaos vs. order. So many different flavors of chaos can be introduced
into an ordered system - a rogue-like hint of randomness. You know,
Loki's smirk.

Like sand through my fingers. Data is data. Chaos is chaos.

As things go, no telling when I will get to the next installment.s

---------

For many years I've been wanting to make a very specific top-down tank
game. So, not too long ago, I grabbed Godot, Krita, and Blender. Then I
got to work playing around just to see. With some mock graphics and a
dual analog controller, I was making some decent progress.

Then I got side-tracked with Godot's auto-tiling. Like, seriously side-
tracked. Why do I always seem to find an irresistible rabbit hole?

So, what's the deal with auto-tiling? Well, once you have it set up,
you can "paint" maps and levels.

Here is one that comes to mind:

https://michagamedev.wordpress.com/2018/02/24/181/

That link shows the 2x2 version of auto-tiling. As it turns out, there
is a more intensive 3x3 version. Check this out:

https://kidscancode.org/godot_recipes/2d/autotile_intro/

Surely, 3x3 is the way to go. You've got to make 47 tiles, but worth it,
right? It's got to be better than 2x2 with 16 tiles. Right?!

I set about making my first 3x3 w/ 47 tiles. I grabbed some graph paper,
some coloured pencils, and got to work. I never made it past one piece
of graph paper.

On this graph paper, I used purple and orange to colour in a single
bit mask. Then I would perm it. Then another bit mask with more purple
and orange, and perm it. Absolutely beautiful.

I had set this paper on a table near my front door. Something about it
kept nagging at me. Something about it looked odd, or familiar...
rather, oddly familiar.

One day, when I came home, I glanced at it and it hit me. Turns out that
each 3x3 is actually the sum of 4 2x2's.

To use a certain kind of notation, this:

code:
###
#.#
###



Is equal to this:

code:
## ##
#. .#

#. .#
## ##



Every single 3x3 purple and orange tile that I looked at really is the
sum of 4 2x2's. It's just a matter of changing scale a tad and changing
your thinking a tad more.

(A few days later I did find a web page that has the same observation on
it, but I can't seem to find it again. :sigh

For my uses, 3x3 is over-kill. A simple 2x2 will serve my purposes just
fine. But how to "paint" in a simple way that uses 2x2?

After two days of doing the Zen thing, I finally saw it in my head.
After another day, I understood it enough to do the code thing. I
suddenly knew how to paint a pixel map and output a 2x2 map that is
indistinguishable from a 3x3 map.

The trick is in overlapping the scanning.

In pretty much all systems, a 2x2 chunk is a 2x2 chunk and you move on
to the next. A 3x3 chunk is a 3x3 chunk and you move on to the next.

But there needs to be overlap.

Take this:

code:
###
#.#
###



The first 2x2 scan looks like this:

code:
##
#.



Moving along the x, the next scan looks like this:

code:
##
.#



Add 1 to the y, reset x, and the scan looks like this:

code:
#.
##



And the final scan looks like this:

code:
.#
##



Here is a crazy bit of code that shows the basic interation:

code:
for y in range(height-1):
	for x in  range(width-1):
		
		a=thresh0255(ping.getpixel((x,y))[3])&1
		b=thresh0255(ping.getpixel((x+1,y))[3])&2
		c=thresh0255(ping.getpixel((x,y+1))[3])&4
		d=thresh0255(ping.getpixel((x+1,y+1))[3])&8
		
		e=(a|b|c|d)



That bit of code is a bit further along than what I wanted to show, but
it does illustrate that there is overlap. Instead of stepping in
absolute chunks, it really does overlap.

(One of these days I'll put together an animation that is far more visual
than text/ascii.)

Even though I can see the algorithm in my head and can code it, I don't
know about the output. That is, how does Godot read resource files? Time
to look into Godot's file formatting. Unfortunately, the files that I am
interested in are simply "human readable" text files - no real details.
Ugh. Time to reverse-engineer some files.

Yeah, I'm built for this. Bring on the rabbit hole! Let's dig, understand,
and manipulate!

warjournal
Maniac (V) Mad Scientist

From:
Insane since: Aug 2000

posted posted 10-11-2020 14:55

Okay. I've got the algorithm and some code to play with. But I don't
know how to get it into Godot. Time to look at file formats. In
particular, *.tres for the actual tile map graphic, and *.tscn files
that hold the level map. The only information that I could find is that
the various files are "human readable" text files.

Okay. Time for my game face. Rawr!

Let's take a look at a tres file:

code:
[gd_resource type="TileSet" load_steps=3 format=2]

[ext_resource path="res://bitmask01a.png" type="Texture" id=1]
[ext_resource path="res://vector.png" type="Texture" id=2]

[resource]
0/name = "bitmask01a.png 0"
0/texture = ExtResource( 1 )
0/tex_offset = Vector2( 0, 0 )
0/modulate = Color( 1, 1, 1, 1 )
0/region = Rect2( 0, 0, 256, 256 )
0/tile_mode = 1
0/autotile/bitmask_mode = 0
0/autotile/icon_coordinate = Vector2( 0, 3 )
0/autotile/tile_size = Vector2( 64, 64 )
0/autotile/spacing = 0
0/autotile/occluder_map = [  ]
0/autotile/navpoly_map = [  ]
0/autotile/priority_map = [  ]
0/autotile/z_index_map = [  ]
0/occluder_offset = Vector2( 0, 0 )
0/navigation_offset = Vector2( 0, 0 )
0/shape_offset = Vector2( 0, 0 )
0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
0/shape_one_way = false
0/shape_one_way_margin = 0.0
0/shapes = [  ]
0/z_index = 0
1/name = "vector.png 1"
1/texture = ExtResource( 2 )
1/tex_offset = Vector2( 0, 0 )
1/modulate = Color( 1, 1, 1, 1 )
1/region = Rect2( 0, 0, 64, 64 )
1/tile_mode = 0
1/occluder_offset = Vector2( 0, 0 )
1/navigation_offset = Vector2( 0, 0 )
1/shape_offset = Vector2( 0, 0 )
1/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
1/shape_one_way = false
1/shape_one_way_margin = 0.0
1/shapes = [  ]
1/z_index = 0



I would call that fairly readable. The first texture is bitmask01.png
with id=1, and all of the various things for it are denoted with '0/'
at the beginning of the line.

(However, I did modify that a little bit. I took out the entry for
"0/autotile/bitmask_flags". That entry is 349 chars long and I didn't
feel like pulling some formatting tricks.)

Time to save some simple TileMap nodes as *.tscn files and take a look
at those. This time I am going to pull some formatting tricks because
one line in particular gets very long in a hurry. Check it out:

code:
[gd_scene load_steps=2 format=2]

[ext_resource path="res://black-n-white1.tres" type="TileSet" id=1]

[node name="Node2D" type="Node2D"]

[node name="TileMap" type="TileMap" parent="."]
tile_set = ExtResource( 1 )
cell_quadrant_size = 64
format = 1
tile_data = PoolIntArray(65537, 0, 196609, 65538, 0, 3, 65539, 0, 3,
                         65540, 0, 3, 65541, 0, 3, 65542, 0, 0, 65545, 0,
                         196609, 65546, 0, 3, 65547, 0, 3, 65548, 0, 0,
                         65549, 0, 196609, 65550, 0, 3, 65551, 0, 3,
                         65552, 0, 0, 65553, 0, 196609)



Iformatted tile_data a little Pythonicky. And, believe it or not, but
that is only a small chunk of the actual entry. The full line of data
is 2669 chars big.

For the most part, human readable. But what is up with tile_data? I
would call tile_data "human readable". Heh.

After playing around with formatting the numbers in different ways
looking for clues, I noticed that the numbers come in sets of 3. Check
this out:

code:
65537, 0, 196609
65538, 0, 3
65539, 0, 3
65540, 0, 3
65541, 0, 3
65542, 0, 0
65545, 0, 196609
65546, 0, 3
65547, 0, 3
65548, 0, 0
65549, 0, 196609
65550, 0, 3
65551, 0, 3
65552, 0, 0
65553, 0, 196609



Aha! Patterns! One of my favorite things in the world.

After a few more experiments and getting very similiar results, I
decided to start looking at the bits. The calulator that comes with
Linux has Programming Mode with a display for bits.

Let's take a look at one:

code:
65537
0000 0000 0000 0001 0000 0000 0000 0001



And a peak at another one:

code:
196609
0000 0000 0000 0011 0000 0000 0000 0001



Once I started looking at the bits, it became very apparent. Like crazy
apparent.

The first number is the position in the level map. The right 16 bits
is the x cord, and the left 16 bits is the y cord.

code:
0000 0000 0000 0001 0000 0000 0000 0001 = (1,1)
0000 0000 0000 0001 0000 0000 0000 0010 = (2,1)
0000 0000 0000 0011 0000 0000 0000 0011 = (3,3)



The second number is the index in the *.tres file. In that little sample,
all 0's, so '0/' in the *.tres file (even though has id=1). The second
number actually holds more data in the left most bits, but it's not
time to talk about that just yet.

And the third number is the indexed location in the actual tile map
graphic.

For example, my graphic is 256x256. The step is 64. That's 16 tiles in
4x4, or (0,0)-(3,3).

The upper-left tile would be:

code:
0
0000 0000 0000 0000 0000 0000 0000 0000 = (0,0)


The upper-right tile would be:

code:
3
0000 0000 0000 0000 0000 0000 0000 0011 = (3,0)


And just for fun from above:

code:
196609
0000 0000 0000 0011 0000 0000 0000 0001 = (1,3)



Kind of redundent to show it all again because the first and third
numbers operate exactly the same way. Just roll with it.

I have the algorithm. I can code it. And now I know how to get it into
Godot. Instead of doing all sorts of parsing, I'm gonna go with a
cut-n-paste approach.

- Paint a pixel map using transparency, pure black, and pure white.
- Load pixel map into Python.
- Scan it using overlap.
- Output data in terminal.
- Cut-n-paste into *.tscn file.
- Fire it up in Godot.

That is the basic technique and it does work. The only problem that I
had was with making the assumption that all pixels in the pixel map
would be #00 or #FF. I did start using Krita over Gimp because this
kind of pixel painting is so much easier in Krita. But I also doubled-up
in the code with a threshold sub-routine.

I can now pixel paint a map and get it into Godot. If I wanted to, with
a little scaling/offset magic in the code, make my pixels 12x12 and
paint as sloppy as I want.

It's amazing how much I can get done when I'm not working 50+ hrs at
my regular job.

Next I want to talk about the tile map graphic and the number work
involved - and I'm going to try to do it using all ascii. Pretty basic
stuff, but I want to go over it because will be doing coding. Gotta
have your numbers straight when coding.

warjournal
Maniac (V) Mad Scientist

From:
Insane since: Aug 2000

posted posted 10-11-2020 17:24

Things are going to get a tricky with the representations. Oh, my love
for graph paper and ascii art. I adore low-tech. While I do want to
eventually do all of this with graphics and animations, I have absolutely
no desire to secure some space. Plus my current time constraints. Just
gonna work with what I got.

So, the actual tile map graphic. My tiles are 64x64. Using 2x2 bitmasking,
so 4x4 tiles. My actual graphic will be 256x256 with a total of 16
tiles.

The lay-out that I am using is in one of the links above. It's a good
lay-out with some interesting properties(!). Using a certain kind of
notation, it looks like this:

code:
###..###
.##.....
.##.....
#......#
#......#
#####..#
#####..#
###..###



Period is walkable and pound sign (or hashtag for those late to the
party) is non-walkable.

(I really wish I could find those particular symbols for map-making
again. It was something like ascii for RPG maps or something. From what
little I can recall, it's a standard amoung the people that make such
games.)

And my favorite using X and ., but with a little extra spacing:

code:
X X  X .  . X  X X
. X  X .  . .  . .

. X  X .  . .  . .
X .  . .  . .  . X

X .  . .  . .  . X
X X  X X  X .  . X

X X  X X  X .  . X
X X  X .  . X  X X



Another look using 1=true=walkable=yes, and 0=NO!

code:
00011000
10011111
10011111
01111110
01111110
00000110
00000110
00011000



Since my tiles are 64x64 and I'm using bitmask 2x2, each one of those
symbols is 32x32.

Time for some base(2). This is my bit order:

code:
1 2
4 8



The first time I did this, I used a different bit order. But I decided
to switch because this is kind of how Godot does it. Kind of.

Okay, let's fill it in:

code:
. .  . 2  1 .  . .
4 .  . 8  4 8  4 8

1 .  . 2  1 2  1 2
. 8  4 8  4 8  4 .

. 2  1 2  1 2  1 .
. .  . .  . 8  4 .

. .  . .  . 2  1 .
. .  . 8  4 .  . .



How about this:

code:
+--+--+--+--+
|..|.2|1.|..|
|4.|.8|48|48|
+--+--+--+--+
|1.|.2|12|12|
|.8|48|48|4.|
+--+--+--+--+
|.2|12|12|1.|
|..|..|.8|4.|
+--+--+--+--+
|..|..|.2|1.|
|..|.8|4.|..|
+--+--+--+--+



Heh. Man, editing ascii to this extent is definitely interesting.

Now let's add it all up and get our index array:

code:
4 10 13 12
 9 14 15  7
 2  3 11  5
 0  8  6  1



If everything went well, should have 0-15, and it looks like we do.

So why do this? Because we need to know the positions in the tile map
for the bit indices.

Hopping over to Python and plugging that in we do this:

code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

tind=[[ 4, 10, 13, 12],
      [ 9, 14, 15,  7],
      [ 2,  3, 11,  5],
      [ 0,  8,  6,  1]]
      
tpos=[]

for col in range(4):
	for row in range(4):
		
		a=tind[row][col]
		b=(row<<16)|col
		
		tpos.append([a,b])

tpos.sort()

for i in tpos:
	print (i)



And the output should look something like this:

code:
[0, 196608]
[1, 196611]
[2, 131072]
[3, 131073]
[4, 0]
[5, 131075]
[6, 196610]
[7, 65539]
[8, 196609]
[9, 65536]
[10, 1]
[11, 131074]
[12, 3]
[13, 2]
[14, 65537]
[15, 65538]



What exactly does that give us? When we scan the pixel map for #00 and
#FF, that will give us the position of the tile in the tile map.

For example, 0 is:

code:
196608 = 0000 0000 0000 0011 0000 0000 0000 0000 = (0,3)



And 1 is:

code:
196611 = 0000 0000 0000 0011 0000 0000 0000 0011 = (3,3)



And so on.

Switching back and forth between Screen(X,Y) and Python[Row][Col] can
throw me for a loop sometimes. To me it's all the same, especially
after having worked with latin squares and orthos for so long. But it
looks like I got it right.

Now, when we scan the pixel map, we know which tile it is in the tile
map. All we need is this from the above:

code:
tilepos=[ 196608, 196611, 131072, 131073, 0, 131075, 196610, 65539,
          196609, 65536, 1, 131074, 3, 2, 65537, 65538]



Knowing where we are when generating the map itself is easy because it
is a part of the interation during scanning. Tile pos is a little
trickier, but there is all is.

OMG I've been on a rampage. All of this stuff has been sitting in me for
several months because of RL. It feels good to start getting most of it
out. And I still have yet to get to the fun part: Chaos! Of course I
have to introduce chaos into the system. But it is under certain
constrains that fit my current needs.

I'm gonna take a break and nap for a bit. When I get up, hopefully I'll
have the strength to strip some code for ya'll to look at. I'm a bit
toasty on cinnamon whiskey right now. Toasty and I can still write like
a beast.

nerd_rampage_mode = ON

(Edited by warjournal on 10-11-2020 17:27)

warjournal
Maniac (V) Mad Scientist

From:
Insane since: Aug 2000

posted posted 10-12-2020 03:45

Here comes some Python code. This is a mostly stripped version of my
working code.

Starting at the top and working down.

I am using Pillow (PIL) to import the image and read values. I think I
had to install it, but I don't remember. It seems to be fairly standard,
though.

I forgot to delete import random. I could now, but whatever.
Besides, it will come in handy soon. You know, when we inject some chaos
into the system. You knew something like this was eventually going to
happen, didn't you? Ya'll know me well.

Few more bits-n-pieces and what-not.

One of favorite things to hate is type-casting. It does come in handy,
but I noticed a few nuanced differences between versions of Python. So I
made thresh0255 far more bloated than it needs to be.

code:
float(n/255.0)


How can so much redundency be written in such a short statement? Yeah,
not taking any chances.

And then we finally come to the meaty part.

The pixel maps that I'm using are PNG and have transparency. The trans-
parent parts are the parts that I do not want. However, I do want the
opaque parts. So, check the transparency of all 4 pixels (2x2), and if
all are opaque, read from R and do the bit mask thing.

I hope that the bitwise operations that I have in there make sense. These
operations are why I want all #00 and #FF. These also follow the bit
order that I mentioned earlier. You know, this little fellow:

code:
1 2
4 8



Finally, at the very end, is an ouput hack. I want the output to be in
parenthesis because that is what Godot uses. So... tuple it. Makes it so
much easier to cut-n-paste. Let's just say that I managed to make Godot's
parser freak out a few times. Man, I love breaking things.

code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PIL import Image
import random

#          0       1      2        3     4   5       6        7        8     9    10  11    12 13   14      15
tilepos=[196608, 196611, 131072, 131073, 0, 131075, 196610, 65539, 196609, 65536, 1, 131074, 3, 2, 65537, 65538]

# for the second digit in the sequence of 3
tresindex=0

ping = Image.open('pixelmap01a.png')

fo=[] # final output

def thresh0255(n):
	# way over-the-top, but not taking any chances
	return int( float(n/255.0) + 0.5 ) * 255


for y in range(height-1):
	for x in  range(width-1):
		
		# grab transparency
		a=thresh0255(ping.getpixel((x,y))[3])&1
		b=thresh0255(ping.getpixel((x+1,y))[3])&2
		c=thresh0255(ping.getpixel((x,y+1))[3])&4
		d=thresh0255(ping.getpixel((x+1,y+1))[3])&8
		
		e=(a|b|c|d)

		# only move forward if all 4
		# pixels are opaque
		if e==15:

			# grab values from R channel
			m=thresh0255(ping.getpixel((x,y))[0])&1
			n=thresh0255(ping.getpixel((x+1,y))[0])&2
			o=thresh0255(ping.getpixel((x,y+1))[0])&4
			p=thresh0255(ping.getpixel((x+1,y+1))[0])&8
			
			inmap = (y<<16)|x
			intrans = 0 | tresindex # change this over later
			intile=tilepos[m|n|o|p]
			
			fo.extend([inmap,intrans,intile])

# output hax
print(tuple(fo))



Looking over this, I almost forgot this little guy:

code:
intrans = 0 | tresindex # change this over later



It is redundant, but it serves as a place-holder purpose.

There are 3 numbers in the *.tscn files. And I said that the second
number holds more data than the *.tres file indices. Of the 32 bits,
the last 4 bits hold data for something far more sinister and interesting.

Here is the sequence:

code:
[0, -1610612734, 1610612736, -1073741822, 536870912, -536870910, 1073741824, -2147483646]



That is the chaos that exists within the constraints that I am operating
under.

Constraints? I haven't said much about the contraints that I am working
under. Top-down graphic, but the constraint is that there is no real
directional information. No isomorphic illusions or directional lighting.
This means that I can transform and things will still fit. Take a corner,
rotate it, and it's another corner. So, I can draw 4 corners using my
lay-out, but have mucho corners with transforms. Know what I mean?

Okay, I'm starting to lose focus. I need food and another nap.
Unfortunately, this time oasis is almost at an end. Not sure when I will
be able to finally get to the really fun stuff. Not just all of that, but
I gotta completely re-build my chaos look-up table. Not an easy task
because I gotta be sober to do it. Heh.

Stay tuned because it will happen eventually.

(Edited by warjournal on 10-12-2020 03:46)

warjournal
Maniac (V) Mad Scientist

From:
Insane since: Aug 2000

posted posted 10-18-2020 13:54

Okay, I was talking slightly backwards in a few spots. If you've
noticed, know that cinnamon whiskey was involved. I still managed to
write, but not quite as cleanly as I wanted.

My tile map is a bit sloppy. I used Krita and my mouse real quick and
and dirty. Guides turned on, but no snapping. It's a bit of a mess. Why?
Because I want variations in my lines. A little more visually interesting
and not just a bunch of perfectness.

However, even with sloppy painting, even a straight hallway can become
pattern-esque, repetitive. Even a series of small alcoves will still all
look the same and defeat the purpose.

Using above lay-out and bit order, imagine a hallway like this:

code:
+--+--+--+--+--+--+--+--+
|..|..|..|..|..|..|..|..|
|48|48|48|48|48|48|48|48|
+--+--+--+--+--+--+--+--+
|12|12|12|12|12|12|12|12|
|..|..|..|..|..|..|..|..|
+--+--+--+--+--+--+--+--+



Even with imperfections in the wall tiles, it will still manage to
become repetitive.

With sloppy painting *and* transforms, that same hallway can become this:

code:
+--+--+--+--+--+--+--+--+
|..|..|..|..|..|..|..|..|
|12|48|21|41|14|48|84|48|
+--+--+--+--+--+--+--+--+
|28|12|82|21|14|81|12|42|
|..|..|..|..|..|..|..|..|
+--+--+--+--+--+--+--+--+



Suddenly, a little more visually interesting. And it tiles just fine.

However, this means that there can not be any visual directional clues
in the tile map. Which I'm okay with for two reasons. The first being
that this is a project for me and only me, and all of this suites me
just fine. The second reason is that Godot *does* support normal maps.
They can be in the environment, but I've only played with them a little
bit. If I do decide on putting in lighting information, shouldn't be too
difficult with normal maps (even if I do have to cobble it a bit).

Transforms?

When I first starting playing with tile maps in Godot, I noticed 4
little buttons: horz flip, vert flip, +90, and -90. And I was all
excited because I saw the potential of doing the above. So I
de-constructed the transforms into this sequence:

code:
transf=[ 0, -1610612736, 1610612736, -1073741824, 536870912, -536870912, 1073741824, -2147483648]



The first is no transform. The next 3 are +90, +180, and +270. The last
four are the same rotations, but with flip horz first. There are 8 unique
transforms because things become the same when flip horz and flip vert
are both used. Yes, order does matter. That is, flip before rotate.

The transform data is held in the second number using the last 4 bits
of 32.

And type-casting, one of the things that I love to hate, comes into play
a little bit. Since playing with bits, would expect unsigned ints. But
some of those numbers are negative. Linux's Calculator doesn't want to
show bits for anything other than unsigned ints, and I didn't want to
cobble some code to actually see the bits in terminal. I know that they
are there because of the sign. I don't know if this is a foible or not,
but it really did annoy me for a few minutes. But it's all good.

With that sequence of transforms, I had to make an equivalency table. If
you transform a tile a certain way, what tile does it become? I see this
process backwards in my head and it took me a few tries to get it
straightened out. And this little beastie looks like this:

code:
transm= [[ 0,  0,  0,  0,  0,  0,  0,  0],
                 [ 1,  4,  8,  2,  2,  8,  4,  1],
                 [ 2,  1,  4,  8,  1,  2,  8,  4],
                 [ 3,  5, 12, 10,  3, 10, 12,  5],
                 [ 4,  8,  2,  1,  8,  4,  1,  2],
                 [ 5, 12, 10,  3, 10, 12,  5,  3],
                 [ 6,  9,  6,  9,  9,  6,  9,  6],
                 [ 7, 13, 14, 11, 11, 14, 13,  7],
                 [ 8,  2,  1,  4,  4,  1,  2,  8],
                 [ 9,  6,  9,  6,  6,  9,  6,  9],
                 [10,  3,  5, 12,  5,  3, 10, 12],
                 [11,  7, 13, 14,  7, 11, 14, 13],
                 [12, 10,  3,  5, 12,  5,  3, 10],
                 [13, 14, 11,  7, 14, 13,  7, 11],
                 [14, 11,  7, 13, 13,  7, 11, 14],
                [15, 15, 15, 15, 15, 15, 15, 15]]



Take the transform sequence, the equivalency table, and plug them into
the code to for the final Python script:

code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PIL import Image
import random

# positions of individual tiles in the tile map
#          0       1      2        3     4   5       6        7        8     9    10  11    12 13   14      15
tilepos=[196608, 196611, 131072, 131073, 0, 131075, 196610, 65539, 196609, 65536, 1, 131074, 3, 2, 65537, 65538]

# the transforms
transf=[ 0, -1610612736, 1610612736, -1073741824, 536870912, -536870912, 1073741824, -2147483648]

# transform equivalency table
transm= [[ 0,  0,  0,  0,  0,  0,  0,  0],
                 [ 1,  4,  8,  2,  2,  8,  4,  1],
                 [ 2,  1,  4,  8,  1,  2,  8,  4],
                 [ 3,  5, 12, 10,  3, 10, 12,  5],
                 [ 4,  8,  2,  1,  8,  4,  1,  2],
                 [ 5, 12, 10,  3, 10, 12,  5,  3],
                 [ 6,  9,  6,  9,  9,  6,  9,  6],
                 [ 7, 13, 14, 11, 11, 14, 13,  7],
                 [ 8,  2,  1,  4,  4,  1,  2,  8],
                 [ 9,  6,  9,  6,  6,  9,  6,  9],
                 [10,  3,  5, 12,  5,  3, 10, 12],
                 [11,  7, 13, 14,  7, 11, 14, 13],
                 [12, 10,  3,  5, 12,  5,  3, 10],
                 [13, 14, 11,  7, 14, 13,  7, 11],
                 [14, 11,  7, 13, 13,  7, 11, 14],
                [15, 15, 15, 15, 15, 15, 15, 15]]

# for the second digit in the sequence of 3
# modify as needed as per *.tres file
tresindex=0

# pixel map
ping = Image.open('pixelmap01a.png')

# image dimensions
width,height=ping.size

# final output
fo=[] 

def thresh0255(n):
	# way over-the-top, but not taking any chances
	return int( float(n/255.0) + 0.5 ) * 255


# start grabbing bits for transparency
for y in range(height-1):
	for x in  range(width-1):
		
		a=thresh0255(ping.getpixel((x,y))[3])&1
		b=thresh0255(ping.getpixel((x+1,y))[3])&2
		c=thresh0255(ping.getpixel((x,y+1))[3])&4
		d=thresh0255(ping.getpixel((x+1,y+1))[3])&8
		
		e=(a|b|c|d) 

		if e==15: # only if all 4 bits are opaque

			m=thresh0255(ping.getpixel((x,y))[0])&1
			n=thresh0255(ping.getpixel((x+1,y))[0])&2
			o=thresh0255(ping.getpixel((x,y+1))[0])&4
			p=thresh0255(ping.getpixel((x+1,y+1))[0])&8
			
			curtile=m|n|o|p
			rn=random.randint(0,7)
			
			newtile=transm[curtile][rn]
			newtrans=transf[rn]
			newpos=tilepos[rn]
			
			inmap = (y<<16)|x
			intrans = newtrans | tresindex
			intile=tilepos[newtile]
			
			fo.extend([inmap,intrans,intile])

# output for easy cut-n-paste
print("tile_data = PoolIntArray{}".format(tuple(fo)))



It's so cute. Nothing terribly fancy. Some information, some bitwise ops,
scanning with overlap, and a hint of randomness. Boom. Done. It amazes
me that such a short and straight-forward script can do what this little
guy does.

"That's a neat system you got there. Mind if I play with it?"

So... what have I got?

I can pixel paint maps using bitmask(2x2) for 16 tiles instead of
bitmask(3x3) for 47 (48?) tiles. And my 2x2 does everything that a
3x3 can do. It can even do a little bit more. Why create 47 (48?) tiles
when I only need 16? Yes?

I've also got a better understanding of how Godot handles certain kinds
of information. I have de-constructed (or reverse-engineered) a few other
things, and I can do even more tricks for when I feel the need.

Okay, I'm starting to get angry and I need to call it a night. I should
be drunk on power, but certain things about all of this really piss me
off. Yeah, I'm leaning in that direction right about now (and it has
nothing to do with cinnamon whiskey... I promise).

I really did enjoy all of this. Having a bit of my mojo back, even if for
a small oasis.

Thank you, Doc, for keeping the lights on. And thanks to the rest of you
for listening to me rant, ramble, and rampage.

play.fiddle.learn

edit: tabs vs spaces... ugh
edit2: omg, can you figure it out? I hope so because my rampage
mode is OFF


(Edited by warjournal on 10-18-2020 14:04)

(Edited by warjournal on 10-18-2020 14:06)

NoJive
Maniac (V) Inmate

From: The Land of one Headlight on.
Insane since: May 2001

posted posted 10-18-2020 19:38

Hey there...

This is not meant as a hijack but I thought you might find at least part of this vid interesting. It has to do with global maximum - local maximum - local minimum and global minimum.

the link should take you to the 20 min mark. He explains why he's redesigning his marble machine... if you find that of interest you can go back and watch the whole thing.

Enjoy or not... I don't really know other than you both seem obsessed, in a good way, with solving puzzles.

CliveK

https://youtu.be/M4jwmAB3wpM?t=1200

___________________________________________________________________________
Sometimes I sits & Think -Sometimes I just sits.

warjournal
Maniac (V) Mad Scientist

From:
Insane since: Aug 2000

posted posted 10-25-2020 15:00

Hey, NJ. I lost several replies due to a different keyboard. It's a
little bit smaller than what I am used to and I kept hitting all sorts
keys (including some hotkeys that I didn't know existed).

Putting Sisyphus in a local minimum is completely brilliant. Absolutely
made me chuckle. Thanks for that.

When I went to uni, my major was computer science applications and my
minor was math. When it comes to YT videos, I actually watch far more
math vids than computer ones. For example, I can watch (listen to)
Numberphiles all day long, but I've only seen a few Computerphile
videos. So many amazing math vids on YT. I recently discovered that
Veritasium has some supremely amazing math vids.

Here is one example of Veritasium blowing my mind with math:
https://www.youtube.com/watch?v=ovJcsL7vyrk

And there are *sooo* many others from other content creators.

Even though I don't watch as many computer vids, I do have a few
favorites that I kind of follow. Code Bullet and Code Train come to
mind. As does Two Minute Papers (!so amazing!).

Love software stuff and algorithms. Love math. Love it even more when
they come together with a sense of humour.*

* I'ld rather talk about important things, like tabs vs. spaces.

« BackwardsOnwards »

Show Forum Drop Down Menu