This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Geforce Fan's profile picture

PokeCC & Game-Engine(map/tile-based engine) - What do YOU want to see?

Started by Geforce Fan, 15 June 2014 - 01:00 AM
Geforce Fan #1
Posted 15 June 2014 - 03:00 AM
PokeCCI'm starting another project called PokeCC. Basically, it's going to be like the pokemon games(probably more like Gold) in CC. This means you there will be 2 reigions, a giant map for you to explore and beat the gym badges and yadha yadha yadha. But I'd like to know:
1. What annoyed the the MOST in pokemon, and what do you think I should do to not repeat this?
2. What features from Pokemon do you really want to see in PokeCC
3. What features that was NOT in Pokemon do you want in PokeCC
You only need to fill out the ones you want, you could do 1 and 3, 3 and 2, 1,2 and 3, etc. etc.
I will also be posting betas, when they're available, here. For the first 3 towns I probably won't give save game converters, you'll simply loose your progress–but seeing as how that probably won't be much it'll be okay. The point is to test, not to play. There is a good chance save games won't become obsolete in the first 3 versions.
Game-EngineGame-Engine will be a map-based game engine that will allow you to easily make a topviewer or sidescroller with little code. This will make making games a breeze. This is not intended for simple games like pong or 2048. This is for complex games with, well, maps. This will support advanced things such as water, clifts, seamless(no map loading at all) TARDIS-like buildings, collision detection, and multiplayer.
Level EditorNOTE: Major format changes are happening. I'd recommend you'd wait to use this.
Thought I'd put this out there for anyone to use. I made a level editor for pokemon. It's not well-written, has global spam, inefficient code, and a confusing UI, but the levels it makes are clean and efficient and all in a single file as a serialized table. You can even have pixels call functions when something that is up to you happens. Anyhow, here it is:
pastebin get QuX6ucKF leveleditor
If you find a minor bug (graphic, rare crash, or something that should be changed because it's confusing) then do NOT report it. If it's a major bug(bad crash that reoccurs, graphical bug that renders the program unusable) then do submit it. But I don't really want to fix bugs in this program. It's a mess and I feel like it doesn't need to be polished.
Note: This has bad blinking when dragging. Not that I'm going to fix it. I'm just telling you. It's also really lagy.
New format(coming soon)
This will work with the bit API. theoriginalbit already explained what colors are what values and what each bit represents, but I'd also like to say something else
Obviously the way saving currently works is serializing a table. The table consists of y tables containing x tables containing that pixel's properties. theoriginalbit designed a way to convert this into 1s and 0s. But, how do I represent the end of a Y table? Simple. Since you cannot have water that is also solid(doesn't even make sense), I will simply pass the color white and solid and water to the converter and use that to represent the end of a Y table, and then, let's say, blue solid water could represent nothing. Any additional data will be stored in a serialized table. Yes, this means there are 2 files per map.
try not to make solid water :)/>
Nothing
btw, if you've managed to stumble upon this, it's not dead yet, just been waiting for me to pick it back up. And I have, and making huge progress.
Edited on 11 January 2015 - 02:26 AM
Csstform #2
Posted 15 June 2014 - 05:01 AM
Not sure if you are aware, but this has been tried before. http://www.computercraft.info/forums2/index.php?/topic/16979-pokecc-looking-for-artist/

Before you start, I should warn you, this is a MAJOR task, one that (obviously) I failed at first try. I was planning on revisiting this at some point, but now it appears I dont have to. PM me if you want any of the code from the previous version, it isnt in a working condition, but has a working (iirc) damage system, and multiple pokemon incorporated. (Probably other things I cant remember, but yeah)

EDIT: also, good luck with only 16 colors! :P/>
Edited on 15 June 2014 - 03:02 AM
Geforce Fan #3
Posted 15 June 2014 - 05:25 AM
Oh. I don't like using other peoples code, I like code in a very particular style and structure, it would be a hastle to resume from someone else's code. I typically like to make a lot of functions, and make each function do a very very specific task. I also like to use a lot of tables, and if I where to continue listing I might break the forum :P/>. I also plan to make each pokemon a separate file, or maybe run a program to condense them–we'll see.
The idea of onlying having 16 colors in computercraft is true. Colors powers of 2 and are numbers. There are a lot more colors than you'd think, however some are a bit harder to use.
You're not the only one to attempt, there is also Craftmon, however it does not seem to want to incorporate the idea of an world, just battles.
Btw, do you want me to change the name?
Edit: Nevermind, I guess colors now rounds to the nearest one. It didn't used to be that way. I really wish they'd give us more colors, this is rediculace. But either way, I'm going to make pokemon in CC, even if it's graphics are horrible.
Edited on 03 August 2014 - 02:16 AM
theoriginalbit #4
Posted 15 June 2014 - 05:30 AM
The idea of onlying having 16 colors in computercraft is not true. Colors powers of 2 and are numbers. There are a lot more colors than you'd think, however some are a bit harder to use.
ummm. no. there are only 16 colours, period.
Geforce Fan #5
Posted 15 June 2014 - 05:55 AM
Read the entire post.
By the way, technicly there are only 3 colors: green, blue, and red. That's all you're looking at when you read this post. Green, blue, and red.
Oh, and there's another colors if you're on an LED LCD: black. The monitor should be able to turn off certain pixels and their backlighting. So if you're on a newer monitor it's 4 colors: green, blue, red, and black.
Edited on 15 June 2014 - 04:00 AM
theoriginalbit #6
Posted 15 June 2014 - 06:12 AM
Read the entire post.
which part in particular am I meant to read?
Bomb Bloke #7
Posted 15 June 2014 - 06:23 AM
In ComputerCraft, 16 different powers of two are available as "colours". Granted, you could combine these values together, but that doesn't mean it'll render the results. Basically it's a 16 colour palette - the reason for using powers of two to index into it likely has more to do with RedPower's bundled cables (which accept 16 bit signals) than anything else.

If you wanted to be pedantic, I suppose you could say that the foreground version of "black" doesn't match the one used for background rendering. For bonus points you might assert that black and white aren't colours, but shades. The fact remains that when specifying a text or background colour for use in ComputerCraft, you've got 16 options.
Geforce Fan #8
Posted 15 June 2014 - 06:40 AM
Read the entire post.
which part in particular am I meant to read?
Edit: Nevermind, I guess colors now rounds to the nearest one. It didn't used to be that way. I really wish they'd give us more colors, this is rediculace. But either way, I'm going to make pokemon in CC, even if it's graphics are horrible.
In ComputerCraft, 16 different powers of two are available as "colours". Granted, you could combine these values together, but that doesn't mean it'll render the results. Basically it's a 16 colour palette - the reason for using powers of two to index into it likely has more to do with RedPower's bundled cables (which accept 16 bit signals) than anything else.

If you wanted to be pedantic, I suppose you could say that the foreground version of "black" doesn't match the one used for background rendering. For bonus points you might assert that black and white aren't colours, but shades. The fact remains that when specifying a text or background colour for use in ComputerCraft, you've got 16 options.
on
my
monitor
It
is
the
same
Edited on 15 June 2014 - 04:50 AM
theoriginalbit #9
Posted 15 June 2014 - 06:56 AM
Edit: Nevermind, I guess colors now rounds to the nearest one. It didn't used to be that way. I really wish they'd give us more colors, this is rediculace. But either way, I'm going to make pokemon in CC, even if it's graphics are horrible.
oh that post. I see. no ComputerCraft has never allowed any other colours. these 2x numbers do not map perfectly to a HEX/RGB value, they're simply logic that follows a similar setup to Minecraft and each of the real RGB colours exist in a lookup table that ComputerCraft uses this 2x number to find. a way to replicate what ComputerCraft does in Lua is as follows

local real = 2 ^ math.floor( math.log(providedColour) / math.log(2) )
the math.floor replicates the Java logic of casting a Double to an Integer.

the only time that ComputerCraft did, and still does, allow composite colours is with the bundled cable support like so

rs.setBundledOutput("right", colours.combine(colours.white, colours.orange))
Geforce Fan #10
Posted 15 June 2014 - 06:57 AM
Huh. I must have a false/altered memory of it then.
Like how I did that entire post with quotes? 2 of them aren't real btw. :P/> I was talking about the thing where he said text black isn't the same as background black. I have a high-quality 1080 LED IPS and they're the same.(for those of you who don't know, IPS is the highest quality LCD panels.)
Edited on 15 June 2014 - 05:00 AM
theoriginalbit #11
Posted 15 June 2014 - 07:02 AM
I was talking about the thing where he said text black isn't the same as background black. I have a high-quality 1080 LED IPS and they're the same.
well then I suppose your 1080p LED IPS display has its contrast set too low, 'cause they're definitely two different colours, the source of ComputerCraft says so.
Geforce Fan #12
Posted 15 June 2014 - 07:17 AM
Hmm. I have contrast at 70. Maybe I'm just tired.was looking at the wrong thing
So… anyone care to fill out the thing?
Edited on 23 August 2014 - 12:03 AM
Geforce Fan #13
Posted 16 June 2014 - 07:28 AM
MAJOR issue: The file sizes are HUGE!!! A level that fills a screen is about 40KB. I might have to make the game grab them from pastebin on the fly and not write them, or maybe require you to have a blank computer to start. Is there a way I could make them lighter by changing my level editor code? At this rate, a few towns would fill a computer!
edit: I've majorly reduced the file sizes by making variables single letters. However, I still feel it's not enough.
edit: it's now 39KB on the largest file size ever without use of events and only filling the screen. Again, that's not small enough. It'd only allow for like 10 towns. I want like 15.
Edited on 16 June 2014 - 05:56 AM
theoriginalbit #14
Posted 16 June 2014 - 07:35 AM
that's not too bad of a problem, the default computer HDD size is larger now. I think the largest program I've ever made was about 250KB. i think your best solution would be to make templates of houses and roads and such, then generate the levels in code, applying colour masks and such to the templates to make it seem unique. that could potentially reduce file sizes a lot.
Geforce Fan #15
Posted 16 June 2014 - 08:00 AM
First of all, did you look at the program?
Well, second of all I could make trees the default pixel, so trees would simply be empty space(the pokemon world is made up mostly of trees xD. Lots of oxygen!)
The problem is is that the format does not support objects. It's similar to the first cc paint program made, it's a serialized table full of pixel colors, and on the level editor, weather or not the pixel is solid(like, can I walk through it or not). I've ran actual tests by putting these on disks and subtracting the max disk size from current disk space left and I've found the largest screen-filling(which they can get bigger than the screen) level is about 39kb. It was a screen almost filled with red, the almost largest number in colors.
I soppose worst comes to worst I could make the towns toward the end either need a floppy or grab them off pastebin. I would really love a way around this.
For me the default HD size is 1MB
Edited on 16 June 2014 - 06:04 AM
theoriginalbit #16
Posted 16 June 2014 - 08:03 AM
I think making the level editor use objects could be better, this would allow the designer of the level to also specify properties of things too, i.e. canCollide or stuff like that.

another optimisations you could easily make are compressing the colours down in the save file so that two background colours are stored in a single byte.
Geforce Fan #17
Posted 16 June 2014 - 08:15 AM
How would I go about compressing them?
The level designer already specifies properties. The only two I need are solid, and what function is called when they're stepped on(which I will do a lot with)/spacebar or something is pressed while looking at them(for pcs)
The problem is with objects is that it adds complexity to making levels. I want it to be something fun, not something I dread doing and end up playing TF2 half the time I'm "developing"(the story of what happened while making the level editor. the 2 other times I'd attempted to make one failed because I wouldn't actually get to it. I'll probably just port this one forever :D/>)
Hmmmm… What about compressing the entire file? Is there an open-source utility I could use for that? I know this has a lot of patterns that could but shrunken down to a byte. Heck, they'd probably fit in 1/4 of the space!
Edited on 16 June 2014 - 06:24 AM
theoriginalbit #18
Posted 16 June 2014 - 08:43 AM
well what do we know about colours? that they're a 2x number, meaning what's unique about them? the x. we know there are 16 possible colours. how many bits can represent 16 states? that's right 4 bits. how many bits in a byte? that's right, 8. therefore we can store two colours in one byte.


local function log2( n )
  return math.floor( math.log(n) / math.log(2) )
end

local function compressColor( c1, c2 )
  local low = bit.band( log2( c1 ), 0xF )
  local high = bit.band( log2( c2 ), 0xF )
  local color = bit.bor( bit.blshift( high, 4 ), low )
  return color
end

local function uncompressColor( color )
  local low = bit.band( b, 0xF )
  local high = bit.brshift( b, 4 )
  return 2^high, 2^low
end

you could also compress the entire file, though I don't know of any that would do this effectively.
Edited on 16 June 2014 - 06:43 AM
Geforce Fan #19
Posted 16 June 2014 - 08:49 AM
pretty sure that'd only save a few kilobytes. I'd really need to compress the whole thing to save a ton of memory. Compressing the whole thing would make true(4 bytes) the numbers(x bytes) and },(2 bytes) into 1 byte each…
Maybe if I just compressed true AND the numbers? a lot of the things have s=true. You could fit 8 trues/falses in 1 byte. 1/0. Also, what if I removed whitespace?
edit: yeah, I think whitespace takes up the majority of the space. There's SO MUCH of it! There's more whitespace than information! Plus unserialize reads the data fine with or without whitespace.
edit2:I was able to remove the whitespace in two lines. Everything works perfectly, the only downside is illegibility. If I could condense true and the color numbers I will hopefully have enough space in 1MB for the entire pokemon map. You know, Ruby was 5MB… best use of space. But not quite ever. 32KB landed man on the moon. That–that was the BEST use of space. 1 of my maps takes up more space than that and doesn't even come close to its complexity.
Edited on 16 June 2014 - 07:24 AM
theoriginalbit #20
Posted 16 June 2014 - 09:00 AM
pretty sure that'd only save a few kilobytes.
it'd half the size of your stored pixels.
Geforce Fan #21
Posted 16 June 2014 - 09:26 AM
oh… Well, i'll add that then. What about doing true/false?
theoriginalbit #22
Posted 16 June 2014 - 09:48 AM
can I see the format of your level files? specifically that 40kb one? PM it to me if you don't want to post it here.
Edited on 16 June 2014 - 08:11 AM
Lyqyd #23
Posted 16 June 2014 - 05:10 PM
He mentioned that they are serialized tables, so that's both the file format and the size problem in one.

You really need to come up with an actual file format that just stores the minimum information you need to reconstruct the data the game needs.
Geforce Fan #24
Posted 16 June 2014 - 08:56 PM
Unfortunately I always find I/O(specifically interfaces and data storage) hard. I don't quite know how to do what you're saying. I know the paint program does it, but I have no idea how and when I look at the save/load code it makes no sense. I do have an idea for the format, and that's this: keys q-d are solids and what colors(like q is white w is orange etc.) and keys f-, are nonsolid colors. Then a second file would contain events. Using this method I could convert everything back to a table and would not require major changes and it would still be easy to draw things to the screen. On top of this, the way the actual game will work will only need to draw each map 1 time, then it will simply move the buffer while putting your character in the center given that he's not running into solid objects.
Here's the new format: http://www.pastebin.com/mr5EJtq9
It's 10KB, it's the newest format. It removes whitespace and variables are single letters. It could get a little bigger had I draw black, but since the background is black it would have made it a lot harder. I should also mention that's not the largest, since I didn't make them solid.
edit: here's the actual largest version. 16KB for filling the screen with solid red.
http://www.pastebin.com/iWx7z2g2
Edited on 16 June 2014 - 07:11 PM
CometWolf #25
Posted 16 June 2014 - 09:22 PM
That's an awful waste of space. Each color should be represented by a character, which is converted to a color when loaded or drawn. Ideally, it should look something like the lower layers of this
http://pastebin.com/t6erfyeu
This is huge, but it's a 90 block tall tower, so it's to be expected :P/>
Infact, you could handle this much the same way i do. In Turtle Architect, a built block is represented by an uppercase letter, while an unbuilt block is a lowercase. Using this same technique, you could represent solids with uppercase and non-solids with lowercase. Even while keeping your format as a serialized table(bad idea) it would save lots of space.
Edited on 16 June 2014 - 07:23 PM
Geforce Fan #26
Posted 16 June 2014 - 10:53 PM
That's the idea I have, but instead of lower/upper, I will just use seperate characters. There are plenty to go arround, and this allows for use of []\;', . The problem is I don't know how to save or load files like that.
Edited on 16 June 2014 - 08:55 PM
CometWolf #27
Posted 16 June 2014 - 11:34 PM
Using the lower/upper method makes it very simple to convert between the 2 states, but your call i guess. Saving this stuff is pretty straight forward. You just loop the table and write out each character.

local tLines = {}
local size = 0
for iX,vX in pairs(tMap) do
  tLines[iX] = ""
  size = math.max(size,iX)
  for iZ,vZ in pairs(vX) do
	local line = tLines[iX]
	tLines[iX] = (
	  iZ > #line 
          and line..string.rep(" ",math.max(0,iZ-#line-1))..vZ
	  or line:sub(1,iZ-1)..vZ..line:sub(iZ+1)
	)
  end
end
local file = fs.open("mapFile","w")
for line=1,size do
  file.writeLine(tLines[line] or "")
end
file.close()
Then loading it back again is pretty much just the same stuff in reverse.
Edited on 17 June 2014 - 03:34 AM
Lignum #28
Posted 17 June 2014 - 01:20 AM
This situation inspired me to write an API that aims to create small map files (68 bytes for a 18x8 map with 3 solids). I'm not going to release it properly, because it's nothing too special but feel free to do whatever you want with it. You can get it here.
How to use it:
Spoilermap.save(file, map, solids):
file: The file to save to (name, not fs.open handle).
map: A table containing the map. Note that the table contains rows, not columns.
The tables returned by paintutils.loadImage will work just fine.
solids: A table containing tables with pairs of coordinates, which specify the solids.
E.g: { { 1, 2 }, { 5, 3 } } means there's a solid at (1|2) and (5|3).

map.load(file):
file: The file to load from (name, not fs.open handle).
returns: A table containing the map formatted exactly like your format (http://pastebin.com/iWx7z2g2).
theoriginalbit #29
Posted 17 June 2014 - 03:13 AM
here's the actual largest version. 16KB for filling the screen with solid red.
http://www.pastebin.com/iWx7z2g2
okay so to prove how small the file can get, I took that file (the largest one) and encoded it out into a much smaller file.
the large file was showing as 15 KB (116 on disk), my smaller encoded version was showing as 838 bytes (4 KB on disk). it stores the information about the colour and the state (true/false) in each byte, there's actually a spare 3 bits in each byte that could be used to store more data; not much data, but more!
Geforce Fan #30
Posted 17 June 2014 - 05:23 AM
First of all, that program has a ' that causes it to error, and second of all, why are there "or"s and "and"s when there's not an if statement?
When I run the code it just crashes. There are a lot of errors in this, and it doesn't make any sense. I think it's best that I figure this out on my own.
Edited on 17 June 2014 - 03:37 AM
CometWolf #31
Posted 17 June 2014 - 05:31 AM
Lol idk how that got in there, but "that program" is just an example i wrote real quick to show you how i do it. I wasn't expecting you to actually use it. The and and ors is called ternary operations, have a look around the forums if you don't understand it.
theoriginalbit #32
Posted 17 June 2014 - 06:13 AM
Here is the program that I used to create the tiny file I mentioned, like I said I could get it down to 838 bytes in size. link.
here is a commented version. link.
and here is the code I used to test that it was reading the save file correctly. link.
Edited on 17 June 2014 - 04:14 AM
Geforce Fan #33
Posted 17 June 2014 - 08:12 AM
Thanks. I'll definitely get arround to including that, though I've joined and am server hosting for a hacker map(my idea in idea sharing topic thing, but Csstform is kinda the leader since he decided to do it. It's a group project with 3 people.)
I think I will use another bit to store weather or not the pixel is a clift(those things you can jump off but not climb up). I could definitely just use events, but since I have extra space, why not? I could use yet another to say weather or not it's water, and my last bit will determine weather or not you will encounter wild ccmon while walking in it! This way I fill every bit and don't waste space. Also, it's pretty necessary, not sure why I didn't think of it before.
Edited on 17 June 2014 - 06:27 AM
theoriginalbit #34
Posted 17 June 2014 - 08:30 AM
while that code I provided works and functions correctly, I hope it provides you with a proof of concept where you could easily make it store lots of data in a small space. since that code is storing a colour and a boolean, and still has space left in each byte.
Edited on 17 June 2014 - 06:31 AM
Geforce Fan #35
Posted 17 June 2014 - 08:39 AM
I do really appreciate it. I'll look up a tutorial on the bit library and look at your code. Pretty cool how you can have your own binary system, and I understand it too. I haven't checked, but I'm guessing white is 1000, so a white tile that's nonsolid, not a clift, is water, but could enter you into a wild ccmon battle would be 10000011.
Edited on 17 June 2014 - 06:41 AM
theoriginalbit #36
Posted 17 June 2014 - 09:03 AM
in ComputerCraft white is 0000000000000000 'cause its a 16 bit integer. in comparison red is 0100000000000000. a list of these can be seen here. however since there's 16 states we can represent these in 4 bits (a nibble), making the nibble for each colour as follows

white       0000
orange      0001
magenta     0010
lightBlue   0011
yellow      0100
lime        0101
pink        0110
gray        0111
lightGray   1000
cyan        1001
purple      1010
blue        1011
brown       1100
green       1101
red         1110
black       1111
but you don't really need to worry about these nibble values as my code automatically generates these bytes for you, as long as you understand how the values were created then you don't need to know the values.

now to what you said with the byte, assuming the variable `s` you have in your tables defines all those other states then no it would not be 10000011 it would be 00010000 since the right most bit on the high nibble is the boolean value, and white is all 0's… now obviously this means that those 3 bits on the very left will be always 0, meaning its extra space that could be used for something else, meaning you could actually represent all those conditions you just stated (isSolid, isCliff, isWater, canBattle) on each bit like so



we'd need to tweak my pack and unpack byte functions in order to do the above though…
Edited on 17 June 2014 - 07:18 AM
Geforce Fan #37
Posted 17 June 2014 - 09:08 AM
Oh. Thanks. So a real example for that would be:
00110000
Edited on 17 June 2014 - 07:17 AM
theoriginalbit #38
Posted 17 June 2014 - 09:17 AM
obviously I should say though, using the image I provided there, that in the current schematic I made (1) (2) and (3) are nothing, (4) represents the variable `s` that you had in those tables, and (5) is the colour.

EDIT: if you do have any further questions about optimising saving of data, or anything to do with that, feel free to shoot me a PM, I'm almost permanently on the forums, except during the hours of about 1am — ~10am AEST (GMT+10/11).
Edited on 17 June 2014 - 07:19 AM
Geforce Fan #39
Posted 17 June 2014 - 09:25 AM
Anyone have suggestions though? this is a suggestions topic :P/>
Edited on 17 June 2014 - 02:09 PM
theoriginalbit #40
Posted 17 June 2014 - 09:31 AM
well what I was helping you with was a suggestion, a suggestion to make your file encoding better :P/>
Bomb Bloke #41
Posted 17 June 2014 - 09:59 AM
I've been keeping sorta half an eye on this thread, and I suppose I would like to suggest "half decent graphics". At the moment I get the impression you're gunning for something that Dwarf Fortress would put to shame.

The way I see it, you could probably get away with square 9x6 character "sprites".

You dump these sprites into a table (along with the properties of the tiles that go with them), then your map consists of indexes pointing into that tile table. You could even attach sets of sprites to a given tile (which the game would run through in sequence, eg in order to animate a wave on the beach).

There are two obvious issues here:

One is that this just isn't workable unless you're playing on a monitor - something like 5x5 with the smallest text scale, at the least. Obviously, I'm proposing that a monitor be put to good use: it'd be simple to control your character by clicking a tile, and having him/her pathfind there.

The other is that, even with a monitor, this adds up to an awful lot of data being rendered to the screen. I would say that it's worth it, though, and could be mitigated by a complete lack of map scrolling - similar to ye olde games of yore, the full display need only be updated when you hit a map edge.
theoriginalbit #42
Posted 17 June 2014 - 10:23 AM
in addition to what Bomb Bloke is saying, you could define more detail in sprites through use of coloured texts as well as coloured backgrounds (yes the save file I have could be modified for that too, each tile would take up more than 1 byte though).

Oh. Thanks. So a real example for that would be:
00110000
well again, no.

having `s` as true in the table, and having `c` as colours.white, would yield 00010000

EDIT: I got bored, and the boredom yielded this.
Improved State Packer

local function log2( n )
  return math.floor(math.log(n) / math.log(2))
end

local function packBoolean( nibble, bool )
  return bit.bor(bit.blshift(nibble, 1), bool and 1 or 0)
end

local function unpackBoolean( byte, mask )
  return bit.band(byte, mask) == mask
end

local function packByte( color, solid, cliff, water, battle )
  return bit.bor(bit.blshift(packBoolean(packBoolean(packBoolean(packBoolean(0, solid), cliff), water), battle), 4), log2(color))
end

--# returns in the order color, solid, cliff, water, battle
local function unpackByte( byte )
  return 2^bit.band(byte, 0xF), unpackBoolean(byte, 128), unpackBoolean(byte, 64), unpackBoolean(byte, 32), unpackBoolean(byte, 16)
end

Test code to make sure it reads bytes back correctly

local t1 = {colors.orange, true, true, false, false}
local t2 = {colors.red, true, false, true, false}

local t3 = {unpackByte(packByte(unpack(t1)))}
local t4 = {unpackByte(packByte(unpack(t2)))}

for i,v in ipairs(t1) do
  if t3[i] ~= v then
    error("t1: something went wrong", 0)
  end
end
for i,v in ipairs(t2) do
  if t4[i] ~= v then
    error("t2: something went wrong", 0)
  end
end

I would like to point out again that all this extra info has been added at no extra expense to file size ;)/>
Edited on 17 June 2014 - 02:10 PM
Geforce Fan #43
Posted 28 June 2014 - 06:57 AM
I've been keeping sorta half an eye on this thread, and I suppose I would like to suggest "half decent graphics". At the moment I get the impression you're gunning for something that Dwarf Fortress would put to shame.

The way I see it, you could probably get away with square 9x6 character "sprites".

You dump these sprites into a table (along with the properties of the tiles that go with them), then your map consists of indexes pointing into that tile table. You could even attach sets of sprites to a given tile (which the game would run through in sequence, eg in order to animate a wave on the beach).

There are two obvious issues here:

One is that this just isn't workable unless you're playing on a monitor - something like 5x5 with the smallest text scale, at the least. Obviously, I'm proposing that a monitor be put to good use: it'd be simple to control your character by clicking a tile, and having him/her pathfind there.

The other is that, even with a monitor, this adds up to an awful lot of data being rendered to the screen. I would say that it's worth it, though, and could be mitigated by a complete lack of map scrolling - similar to ye olde games of yore, the full display need only be updated when you hit a map edge.
Unfortunately I have to deny this request. I'll tell you this right now: they graphics are going to be pretty bad. The character will be one pixel. The character will be controlled by wasd. The map will scroll. Changing this would make it no longer a pokemon-feeling game. It's just not what I envisioned…
The game works by writing the map to a buffer– the entire map–then writing the buffer to the screen then writing the character. The character never moves; if you tap w once, the map just moved back 1. The reason this works is b/c buffers write extremely fast. The level editor does not work this way, however, due to me being lazy. That's why it has massive screen tearing, and horrible refresh rate and lag.
Edited on 28 June 2014 - 05:05 AM
Geforce Fan #44
Posted 29 June 2014 - 08:50 PM
in addition to what Bomb Bloke is saying, you could define more detail in sprites through use of coloured texts as well as coloured backgrounds (yes the save file I have could be modified for that too, each tile would take up more than 1 byte though).

Oh. Thanks. So a real example for that would be:
00110000
well again, no.

having `s` as true in the table, and having `c` as colours.white, would yield 00010000

EDIT: I got bored, and the boredom yielded this.
Improved State Packer

local function log2( n )
  return math.floor(math.log(n) / math.log(2))
end

local function packBoolean( nibble, bool )
  return bit.bor(bit.blshift(nibble, 1), bool and 1 or 0)
end

local function unpackBoolean( byte, mask )
  return bit.band(byte, mask) == mask
end

local function packByte( color, solid, cliff, water, battle )
  return bit.bor(bit.blshift(packBoolean(packBoolean(packBoolean(packBoolean(0, solid), cliff), water), battle), 4), log2(color))
end

--# returns in the order color, solid, cliff, water, battle
local function unpackByte( byte )
  return 2^bit.band(byte, 0xF), unpackBoolean(byte, 128), unpackBoolean(byte, 64), unpackBoolean(byte, 32), unpackBoolean(byte, 16)
end

Test code to make sure it reads bytes back correctly

local t1 = {colors.orange, true, true, false, false}
local t2 = {colors.red, true, false, true, false}

local t3 = {unpackByte(packByte(unpack(t1)))}
local t4 = {unpackByte(packByte(unpack(t2)))}

for i,v in ipairs(t1) do
  if t3[i] ~= v then
	error("t1: something went wrong", 0)
  end
end
for i,v in ipairs(t2) do
  if t4[i] ~= v then
	error("t2: something went wrong", 0)
  end
end

I would like to point out again that all this extra info has been added at no extra expense to file size ;)/>/>
I don't want to add ASCII art as, in my opinion, it doesn't look "clean". It's not completely connected and I don't think it quite fits what I want this game to be.


Here's the new format's first test: http://pastebin.com/WqjTy18Y
Can't be sure it worked; I havn't wrote a load function yet. It looks messed up but it might be fine.
edit: tried a single gray dot at the top and got 135. something is wrong. probably something simple, too.
edit: it's something with the pack function. Do note I'm passing nil for boolean values.
Edited on 29 June 2014 - 09:23 PM
theoriginalbit #45
Posted 30 June 2014 - 01:47 AM
Here's the new format's first test: http://pastebin.com/WqjTy18Y
Can't be sure it worked; I havn't wrote a load function yet. It looks messed up but it might be fine.
well the first thing to note is you can't use the HTTP API with that file format, unless you make use of base64 encoding, a LuaJ bug stops you sadly from having bytes >127

edit: tried a single gray dot at the top and got 135. something is wrong. probably something simple, too.
edit: it's something with the pack function. Do note I'm passing nil for boolean values.
colors.gray should give a result of 7, what's the code you're using? also it should be noted that passing nil will inevitably converted to false, with the logic I've used. there's no way to store nil, it's either true or false.
Geforce Fan #46
Posted 30 June 2014 - 03:00 AM
Here's the new format's first test: http://pastebin.com/WqjTy18Y
Can't be sure it worked; I havn't wrote a load function yet. It looks messed up but it might be fine.
well the first thing to note is you can't use the HTTP API with that file format, unless you make use of base64 encoding, a LuaJ bug stops you sadly from having bytes >127

edit: tried a single gray dot at the top and got 135. something is wrong. probably something simple, too.
edit: it's something with the pack function. Do note I'm passing nil for boolean values.
colors.gray should give a result of 7, what's the code you're using? also it should be noted that passing nil will inevitably converted to false, with the logic I've used. there's no way to store nil, it's either true or false.
Why wouldn't I be able to use http?
what was posted and what was wrote are the same.
in the program nil is used for false.
Edited on 30 June 2014 - 01:02 AM
Geforce Fan #47
Posted 30 June 2014 - 03:06 AM
http://pastebin.com/W7wH8T3B - code being used to make the save



I don't understand. I thought the data was going to be packed into a single byte; it's in 3 bytes from what I can see. Why is it not in one? Could you not lay it out in binary (ex. 10001000) then use whatever character that would be(for this example, it would be the ˆ character.) I want it in text, not char/dec binary. To be honest, I don't even know this system is even remotely not adding more bytes when increased size(more booleans). It just adds numbers. The issue is that this is not converting down to the binary that is used to store the file; it's not efficient.
Edited on 30 June 2014 - 01:27 AM
theoriginalbit #48
Posted 30 June 2014 - 03:21 AM
Why wouldn't I be able to use http?
unless you make use of base64 encoding, a LuaJ bug stops you sadly from having bytes >127
with the LuaJ bug anything >127 comes up as 127. it only occurs in events though, meaning the HTTP API cannot support binary strings.

http://pastebin.com/W7wH8T3B - code being used to make the save

I don't understand. I thought the data was going to be packed into a single byte; it's in 3 bytes from what I can see.
it shouldn't be… how are you 'seeing' how many bytes it is stored in?
Edited on 30 June 2014 - 01:21 AM
Geforce Fan #49
Posted 30 June 2014 - 03:29 AM
I want something like this:
That's an awful waste of space. Each color should be represented by a character, which is converted to a color when loaded or drawn. Ideally, it should look something like the lower layers of this
http://pastebin.com/t6erfyeu
This is huge, but it's a 90 block tall tower, so it's to be expected :P/>
Infact, you could handle this much the same way i do. In Turtle Architect, a built block is represented by an uppercase letter, while an unbuilt block is a lowercase. Using this same technique, you could represent solids with uppercase and non-solids with lowercase. Even while keeping your format as a serialized table(bad idea) it would save lots of space.
but with binary. Basically, I want it in a similar format to the way paint does stuffs. 1 char is 1 pixel.
Why wouldn't I be able to use http?
unless you make use of base64 encoding, a LuaJ bug stops you sadly from having bytes >127
with the LuaJ bug anything >127 comes up as 127. it only occurs in events though, meaning the HTTP API cannot support binary strings.

http://pastebin.com/W7wH8T3B - code being used to make the save

I don't understand. I thought the data was going to be packed into a single byte; it's in 3 bytes from what I can see.
it shouldn't be… how are you 'seeing' how many bytes it is stored in?
1 character, regardless of what it is is 1 byte. Like, that last sentance is ~48 bytes(probably off, but it proves the point regardless.)
Edited on 30 June 2014 - 01:32 AM
theoriginalbit #50
Posted 30 June 2014 - 04:29 AM
1 character, regardless of what it is is 1 byte. Like, that last sentance is ~48 bytes(probably off, but it proves the point regardless.)
that doesn't answer my question. how are you seeing how many bytes it is stored in.

EDIT: also your code is, well, horrendous to read, and I'm still trying to completely understand what you're doing, but I'm noticing a huge lack of variable localisation and a massive lack of optimisation.

[namedspoiler=for example here's just two optimisations you can make]
[b]Your code[/b]
[code]
paintutils.drawPixel(51,1,colors.white)
paintutils.drawPixel(51,2,colors.orange)
paintutils.drawPixel(51,3,colors.magenta)
paintutils.drawPixel(51,4,colors.lightBlue)
paintutils.drawPixel(51,5,colors.yellow)
paintutils.drawPixel(51,6,colors.lime)
paintutils.drawPixel(51,7,colors.pink)
paintutils.drawPixel(51,8,colors.gray)
paintutils.drawPixel(51,9,colors.lightGray)
paintutils.drawPixel(51,10,colors.cyan)
paintutils.drawPixel(51,11,colors.purple)
paintutils.drawPixel(51,12,colors.blue)
paintutils.drawPixel(51,13,colors.brown)
paintutils.drawPixel(51,14,colors.green)
paintutils.drawPixel(51,15,colors.red)
paintutils.drawPixel(51,16,colors.black)
[/code]

[b]Improved code[/b]
[code]
for i = 1, 16 do
paintutils.drawPixel(51, i, 2^(i-1))
end
[/code]

[b]Your code[/b]
[code]
if events[4] == 1 then
currentColor=colors.white
elseif events[4] == 2 then
currentColor=colors.orange
elseif events[4] == 3 then
currentColor=colors.magenta
elseif events[4]==4 then
currentColor=colors.lightBlue
elseif events[4]==5 then
currentColor=colors.yellow
elseif events[4] == 6 then
currentColor=colors.lime
elseif events[4]==7 then
currentColor=colors.pink
elseif events[4]==8 then
currentColor=colors.gray
elseif events[4] == 9 then
currentColor=colors.lightGray
elseif events[4] == 10 then
currentColor=colors.cyan
elseif events[4] ==11 then
currentColor=colors.purple
elseif events[4] ==12 then
currentColor=colors.blue
elseif events[4]==13 then
currentColor=colors.brown
elseif events[4]==14 then
currentColor=colors.green
elseif events[4] ==15 then
currentColor=colors.red
elseif events[4] ==16 then
currentColor=colors.black
elseif events[4] ==17 then–erasing
currentColor=nil
end
[/code]

[b]Improved code[/b]
[code]
if events[4] == 17 then
currentColor = nil
elseif events[4] > 0 and events[4] < 17 then
currentColor = 2^(events[4] - 1)
end
[/code]
[/namedspoiler]
Edited on 30 June 2014 - 03:24 AM
Geforce Fan #51
Posted 30 June 2014 - 05:22 AM
by opening the file in edit and counting the characters…
So how should I go about doing my method?
Edited on 30 June 2014 - 03:22 AM
theoriginalbit #52
Posted 30 June 2014 - 05:58 AM
well the problem is you can't really accurately check by eye with the save file. in any point, I think the problem is in your save, possibly in your packEntireMap I'm not even sure what you're trying to do in that.

EDIT: also your code is, well, horrendous to read, and I'm still trying to completely understand what you're doing, but I'm noticing a huge lack of variable localisation and a massive lack of optimisation.
[namedspoiler=for example here's just two optimisations you can make]
[b]Your code[/b]
[code]
paintutils.drawPixel(51,1,colors.white)
paintutils.drawPixel(51,2,colors.orange)
paintutils.drawPixel(51,3,colors.magenta)
paintutils.drawPixel(51,4,colors.lightBlue)
paintutils.drawPixel(51,5,colors.yellow)
paintutils.drawPixel(51,6,colors.lime)
paintutils.drawPixel(51,7,colors.pink)
paintutils.drawPixel(51,8,colors.gray)
paintutils.drawPixel(51,9,colors.lightGray)
paintutils.drawPixel(51,10,colors.cyan)
paintutils.drawPixel(51,11,colors.purple)
paintutils.drawPixel(51,12,colors.blue)
paintutils.drawPixel(51,13,colors.brown)
paintutils.drawPixel(51,14,colors.green)
paintutils.drawPixel(51,15,colors.red)
paintutils.drawPixel(51,16,colors.black)
[/code]

[b]Improved code[/b]
[code]
for i = 1, 16 do
paintutils.drawPixel(51, i, 2^(i-1))
end
[/code]

[b]Your code[/b]
[code]
if events[4] == 1 then
currentColor=colors.white
elseif events[4] == 2 then
currentColor=colors.orange
elseif events[4] == 3 then
currentColor=colors.magenta
elseif events[4]==4 then
currentColor=colors.lightBlue
elseif events[4]==5 then
currentColor=colors.yellow
elseif events[4] == 6 then
currentColor=colors.lime
elseif events[4]==7 then
currentColor=colors.pink
elseif events[4]==8 then
currentColor=colors.gray
elseif events[4] == 9 then
currentColor=colors.lightGray
elseif events[4] == 10 then
currentColor=colors.cyan
elseif events[4] ==11 then
currentColor=colors.purple
elseif events[4] ==12 then
currentColor=colors.blue
elseif events[4]==13 then
currentColor=colors.brown
elseif events[4]==14 then
currentColor=colors.green
elseif events[4] ==15 then
currentColor=colors.red
elseif events[4] ==16 then
currentColor=colors.black
elseif events[4] ==17 then–erasing
currentColor=nil
end
[/code]

[b]Improved code[/b]
[code]
if events[4] == 17 then
currentColor = nil
elseif events[4] > 0 and events[4] < 17 then
currentColor = 2^(events[4] - 1)
end
[/code]
[/namedspoiler]
[/quote]
Geforce Fan #53
Posted 30 June 2014 - 06:22 AM
I don't optimize too much on developer tools. I know the code is horrible; I just don't care. If it works without serous bugs or crashed, then I'm not really going to change it no matter how inefficient, spammy, crappy, or unreadable it is. Obviously I'm not going to do this in the game itself, but for a level editor I certainly am. I had no plans to release this when I started it, and in my defense the code works perfectly fine.
Variable localization… yeah it's so much easier to just throw a global and just leave it there… Sure, if I where to be working on an actual thing I'm going to release for everybody, but the thing is–it's just a developer tool, only designed to be ran rarely. I just don't feel like putting effort into making it more efficient or less spammy.
overall I think it's fine how it is, I know it could be much more efficient. Wouldn't be too hard to fix it, but meh. Not like it's end result even looks nice, that gui has a horrible color scheme(I picked the colors only to stand out) and there is massive screen tearing &amp; lag caused by horribly inefficient drawing methods.
Also btw the fact that the map is a global variable is a really good thing. it allows for easy restores when the thing crashes + easy testing. overall the way it's designed makes it really easy (for me) to edit and fix it. I can easily hunt down and fix a bug by looking at the table contents.

The function's purpose is to make a file that contains the positions and data of the pixels in the most efficient way possible–to draw them out as characters(made of *BINARY CODE* –meaning you can take the ordinary level save data and make it into a character to draw it)and make sure they're spaced appropriately. Obviously that doesn't work because I thought the encode function worked differently. On top of this this makes it easy to fix small bugs without needing to load the level(e.x. fix them w/o reuploading to Pastebin.
By the way, you're 1 post away from 6,600 posts!
Edited on 30 June 2014 - 04:47 AM
Beeskee #54
Posted 01 July 2014 - 07:59 AM
This is a pretty cool idea. :)/>

As far as what to do or what not to do, check out Yahtzee's review of Pokemon on Zero Punctuation. :D/> I think he covered everything in that.
theoriginalbit #55
Posted 01 July 2014 - 08:15 AM
-snip-
well I'm not seeing exactly what you're doing with the packed byte, it didn't even look like you're using it. and you're also doing something with strings, and you don't open the file handle in binary write mode, etc, etc. very confusing code to follow.
Geforce Fan #56
Posted 01 July 2014 - 09:49 PM
as I have said, take a look at how paint handles this situation. if a binary character is made of 1s and 0s, and our map is made of 1s and 0s, why not simply write those 1s and 0s as their normal binary cahracters on a save file at their actual locations? so if I have a dot at 2,1 it'd be: " x". or a dot at 5,1 would be " x".
what kind of save type did you have in mind? how can I store the entire map by packing 1 byte? or did you have in mind another function to complete the save file?
Edited on 01 July 2014 - 07:53 PM
Bomb Bloke #57
Posted 02 July 2014 - 01:54 AM
Paint saves data by creating an ASCII representation of a hex representation of the powers applied to two to get the correct colour values to represent each position in the image. This makes it easy for the human eye to read, and isn't terribly inefficient; the files are only about twice the size they could be.

You could do something similar, but you'd be limited to something like less than a hundred different sorts of tiles to play with. Though I'm getting a sinking feeling that you'll probably end up devoting just one character on the screen to each tile anyway…

Writing actual zeros and ones to your file in ASCII (as opposed to packing eight of those bits into each byte) would bloat your files by 8x, however. So, um, don't do that.
theoriginalbit #58
Posted 02 July 2014 - 02:02 AM
yeah definitely don't write 1s and 0s. and as Bomb Bloke stated the paint file format serves a different purpose.
again your main problem is the fact you're opening the file in write mode ('w') instead of binary write mode ('wb')
Geforce Fan #59
Posted 02 July 2014 - 09:06 PM
So just open it in wb and problems are solved…?
edit: that is not exactly the result. when using binary write mode it simply does not write anything at all… do I need to modify the packEntireMap() function?

Paint saves data by creating an ASCII representation of a hex representation of the powers applied to two to get the correct colour values to represent each position in the image. This makes it easy for the human eye to read, and isn't terribly inefficient; the files are only about twice the size they could be.

You could do something similar, but you'd be limited to something like less than a hundred different sorts of tiles to play with. Though I'm getting a sinking feeling that you'll probably end up devoting just one character on the screen to each tile anyway…

Writing actual zeros and ones to your file in ASCII (as opposed to packing eight of those bits into each byte) would bloat your files by 8x, however. So, um, don't do that.
as mentioned before, almost no ascii will be used. It does not fit the look I'm aiming for. Think about the real pokemon game. Now imagine porting it to a 51x19 display. It would not have ACSCII. Plus, it couldn't with an actual 51x19. I want to use all mechanics from the normal game.


It's been like a month since I started this project. I don't mean to offend, but I really need a simple answer, not a 1/2 answered question. This project has been preventing me from moving on, I really want to get on to other projects. I can't figure out this binary stuff, and I need help. How do I make a full save file with binary?
Edited on 02 July 2014 - 07:30 PM
theoriginalbit #60
Posted 03 July 2014 - 03:27 AM
It would not have ACSCII. Plus, it couldn't with an actual 51x19. I want to use all mechanics from the normal game.
well yes ASCII could be used with 'an actual 51x19', haven't you seen Bomb Blokes Tetris game? he makes use of ASCII to make the tetromino look 3D.

It's been like a month since I started this project. I don't mean to offend, but I really need a simple answer, not a 1/2 answered question. This project has been preventing me from moving on, I really want to get on to other projects. I can't figure out this binary stuff, and I need help. How do I make a full save file with binary?
look, here is the simplest and most brutal answer; go back to the way you were doing it and deal with the fact your save files are 'massive', it gets to a point where without more information on what you're storing in the save file and stuff I just can't help you correctly. so just go back to the way you were doing it, it will be two lines of code, and it will work, you'll just have to put up with large file sizes.
Geforce Fan #61
Posted 03 July 2014 - 03:45 AM
Alright… I guess I can always convert them later if needed…
btw I was talking about a real life screen with the resolution of 51x19. You couldn't get ascii the size off CC's, because 1 cc pixel would be one real pixel on that display thus making it impossible to display because it'd require higher resolution than what is available.
Edited on 03 July 2014 - 01:49 AM
Bomb Bloke #62
Posted 03 July 2014 - 03:53 AM
Well, more what I was getting at was the "singular" use of characters per tile - bearing in mind that everything CC lets you render counts as a "character", spaces included, drawings with paintutils definitely included.

As mentioned, I realise this would necessitate the use of a monitor to increase the display resolution, but I won't repeat myself too much.
Geforce Fan #63
Posted 09 July 2014 - 02:59 AM
Well, more what I was getting at was the "singular" use of characters per tile - bearing in mind that everything CC lets you render counts as a "character", spaces included, drawings with paintutils definitely included.

As mentioned, I realise this would necessitate the use of a monitor to increase the display resolution, but I won't repeat myself too much.
the issue with adding characters is when I do get to making the files more compact(trust me I will, the fact that they're so large bugs the crap out of me) this would require an entire extra file full of characters… Then again, I'll already need a file for storing events… Maybe, we'll see. I can always add them later.
Geforce Fan #64
Posted 19 July 2014 - 08:17 PM
sorry for the delay in the project, I'm back to working on it again.
Geforce Fan #65
Posted 26 July 2014 - 05:43 AM
I've decided to make an engine, or a massive API for (all) my game(s) that will be called Game Engine or Game for short, so I'll probably not work on this for a little bit, but when I get around to it it should be much easier to make and not take very long. It's current planned features are:
-Console system with error tracking
-Logs
-Something to make pause menus easier
-Windows
-Easy maps
-MP(will not be in 1.0)
-Projectiles(probably not in 1.0 either)
And possibly a keypress and release system, though it might not be possible without serous input lag.
Edited on 26 July 2014 - 03:47 AM