Help me with C++ for my game


#163

I’m following this video on how to do this with C++

At first I couldn’t find a good video.

Right now I’m using PyxelEdit, it exports in a nice and simple .txt format which fits directly into an array (a 1D array). I’ll write a second post explaining what I want to do with it

Here’s what the export looks like:

tileswide 48
tileshigh 32
tilewidth 8
tileheight 8

layer 0
0,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,11,11,11,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,
1,12,13,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,12,13,0,0,0,0,0,1,1,1,1,0,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0,0,0,0,
1,14,15,0,0,0,1,1,1,12,13,0,0,0,0,1,1,1,14,15,0,0,0,0,0,1,5,5,5,0,0,11,11,11,11,0,0,0,0,0,0,0,12,13,0,0,0,0,
0,1,0,0,0,1,1,1,1,14,15,0,0,0,11,0,1,1,1,1,1,0,0,0,0,0,5,5,5,1,0,11,11,11,0,0,1,1,0,0,1,1,14,15,0,0,0,0,
0,0,0,0,0,1,12,13,1,1,1,0,0,1,11,11,0,1,1,0,0,0,1,1,1,1,6,7,6,1,0,11,11,0,1,1,1,0,0,0,1,1,1,1,1,0,0,0,
0,0,0,0,0,1,14,15,1,1,0,0,1,11,11,11,0,0,0,0,0,2,2,2,2,2,2,2,1,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,
0,0,0,0,0,0,1,1,0,0,0,0,1,0,11,0,0,1,1,0,1,2,1,0,1,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,1,0,0,0,0,0,1,1,0,2,1,1,0,0,0,0,0,0,0,11,0,0,0,0,
0,0,1,0,0,1,1,1,0,0,0,0,1,0,0,0,1,1,0,0,0,2,0,0,1,1,0,12,13,1,1,11,0,2,1,0,5,5,5,1,0,0,11,11,11,0,0,0,
0,0,12,13,0,1,1,1,1,12,13,1,1,1,1,0,0,5,5,5,0,2,1,12,13,4,4,4,15,0,11,11,11,2,0,5,5,5,5,1,0,0,11,11,1,1,0,0,
0,1,14,15,1,0,0,1,1,14,15,1,1,0,0,0,0,5,5,5,5,2,1,14,15,4,4,4,1,0,11,11,11,2,0,5,5,5,6,0,0,0,1,11,1,1,0,0,
0,1,0,0,0,12,13,0,1,1,1,0,0,0,0,0,1,6,5,5,5,2,1,1,0,6,7,6,1,1,1,1,0,2,0,6,7,6,1,1,0,0,1,1,1,1,0,0,
0,0,1,1,1,14,15,1,1,1,1,0,0,1,1,1,1,1,6,7,6,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,0,1,1,1,1,1,1,
0,0,0,1,1,1,1,1,1,0,0,1,1,2,2,2,2,2,2,2,2,2,1,1,1,0,0,1,1,1,0,0,1,1,2,2,2,2,2,1,0,11,11,1,1,1,1,0,
0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,1,0,0,11,11,0,0,0,0,1,0,0,1,1,2,2,1,0,11,11,11,11,1,1,0,0,
0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,2,1,0,11,11,1,1,1,1,1,1,0,1,12,13,1,1,0,0,11,11,11,11,11,0,0,0,
0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,1,0,0,0,0,1,1,1,1,0,0,0,14,15,1,1,1,0,0,1,11,11,0,0,0,0,
0,1,1,0,1,0,0,12,13,1,1,1,0,0,0,12,13,0,0,0,1,2,1,4,4,4,0,0,0,0,0,0,0,0,1,1,1,0,12,13,1,0,0,0,0,0,0,0,
0,12,13,1,1,0,0,14,15,1,1,1,1,0,1,14,15,0,0,0,1,2,1,4,4,4,0,5,5,5,1,0,0,1,0,0,0,1,14,15,1,0,0,0,1,0,0,0,
0,14,15,1,1,0,1,1,1,1,12,13,1,0,1,1,1,0,0,0,1,2,0,4,4,4,1,5,5,5,1,0,1,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,
1,0,1,1,1,0,0,0,1,1,14,15,0,1,1,1,1,12,13,0,1,2,0,6,7,6,1,5,5,5,1,0,0,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,
0,1,0,0,12,13,0,0,1,1,1,1,0,1,1,1,1,14,15,0,1,2,0,0,2,1,1,6,7,6,1,0,0,1,0,0,1,1,1,0,1,1,0,1,1,1,0,1,
0,0,0,0,14,15,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,2,2,2,2,2,2,2,2,2,2,1,0,1,0,0,1,0,1,1,1,0,11,11,1,1,1,1,
0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,0,0,1,1,0,0,0,0,1,1,1,1,1,1,11,11,11,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,0,11,11,11,11,1,1,1,
0,0,0,12,13,0,0,0,1,1,12,13,1,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,12,13,0,0,1,1,0,0,0,0,0,0,11,11,11,11,11,11,1,0,
0,0,1,14,15,0,0,12,13,1,14,15,0,0,0,0,0,12,13,0,0,1,0,0,1,1,1,1,14,15,1,0,0,1,0,0,0,0,0,0,11,11,11,11,11,11,0,0,
0,0,0,1,1,1,1,14,15,1,1,0,0,1,1,1,1,14,15,0,0,0,0,0,1,12,13,1,1,1,1,0,0,1,1,0,0,1,1,1,1,11,11,11,11,11,0,0,
0,0,1,0,0,1,1,1,0,0,0,0,0,12,13,1,1,1,0,0,0,0,0,0,1,14,15,1,1,1,1,0,1,1,0,0,1,11,11,1,0,0,11,11,11,0,0,0,
0,1,12,13,1,1,0,0,0,0,0,0,0,14,15,1,0,0,0,1,1,0,0,0,0,1,1,1,1,1,0,0,1,0,0,11,11,11,11,11,1,0,0,0,0,0,0,0,
0,0,14,15,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,1,1,0,0,0,11,11,11,1,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

#164

I need to

  1. load it into a 1d array

  2. convert it into multiple 1d arrays (one screen = one array)

  3. take each section, take the left half, bitshift each value to the left by 4. Take each value from the second half, add it to the corresponding value of the first half

  4. export it back into one big 1D array.

There are others ways to go about it and I can export it into a different format, but I like flat arrays as you’ve probably noticed.

Also, I’m open to using something else like Tiled but it’s such a pain to learn. I would literally have an easier time making my own editor which by the way I would love to make in C++

Edit: just letting you know the other video series had only the 6 minutes video I linked, so I’m onto a different series

Edit2 what I got so far:

#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main()
{
    ifstream inFile;

    //inFile.open("C:\\Users\\Alex\\Downloads\\arduboy rpg tilemaps\\tilemap_8x12screens.txt", ios::out);
    inFile.open("C:\\Users\\Alex\\Downloads\\arduboy rpg tilemaps\\numbers.txt");

    if (inFile.fail()) {
        cerr << "Opening File Failed" << endl;
        exit(1);
    }

    int x, y;
    inFile >> x >> y;

    cout << "X: " << x << endl;
    cout << "Y: " << y << endl;

    inFile.close();
    return 0;
}

#165

Just letting you know I’m 90% done, I ended up settling on GameMaker for this

Here’s how it looks like to take a string argument and turn it into a list of numbers in GameMaker (they’re still strings)

///string_get_integers(string)
///@arg string

// Sam SIbbens
// 2018/NOVEMBER/18
// Takes a string and returns a list with all the correct integer values

var _string = argument0;
var _list0 = ds_list_create();

// Add every single character
for(var i = 1; i <= string_length(_string); i++) {
	var _char = string_char_at(_string, i);
	ds_list_add(_list0, _char);
}

// Rebuild numbers based on the right digits to the new list, and also add whatever garbage characters were originally in between
var _list1 = ds_list_create();
var _newListIndex = 0;
for(var i = 0; i < ds_list_size(_list0); i++) {
	
	var _char = string_digits(_list0[| i]);
	
	if _char == "" {
		_list1[| _newListIndex] = _list0[| i];
		_newListIndex++;
	} else {
		if i != 0 && string_digits(_list1[| _newListIndex-1]) != "" {
			_list1[| _newListIndex-1] += _char;
		} else {
			_list1[| _newListIndex] = _char;
			_newListIndex++;
		}
	}
	
}

// clean up the mess, add only numbers to the last list
var _list2 = ds_list_create();
for(var i = 0; i < ds_list_size(_list1); i++) {
	var _digits = string_digits(_list1[| i]);
	if _digits != "" {
		ds_list_add(_list2, _digits);
	}
}

ds_list_destroy(_list0);
ds_list_destroy(_list1);
return _list2;

(Pharap) #166

I could write something tommorow.

If you were happy with C# I’d write it in C# because C# is much easier for rapid development, but if not I can do Lua or C++.
Unfortunately C++'s file API isn’t the best


A few notes about your code:

  • #include <stdlib.h> should be #include <cstdlib> from C++11 onwards, the old style was deprecated
  • using namespace std is considered bad practice, isocpp recommends either including specific names locally within a function (e.g. using std::ifstream) or just fully qualifying the names
  • you should use '\n' rather than std::endl
  • In this case return 1 would have been better than std::exit(1) because you’re at the top level (i.e. directly in main), but that’s not too much of an issue.

Overall the general idea is there, but you’re not discarding the text data.
Like I say the C++ file API is notoriously awkward to work with.

I think your best bet would be to just read the whole file in as a char array or a std::string and then operate on it using character manipulation.


I made a start on writing a Lua one. If you still want it then I’ll finish it tomorrow

-- Get command line argument
local filename = arg[1];

-- If there's no argument, complain
if (filename == nil) then
	error("Usage: command <filename>");
end

-- Open file in readonly mode
local file = io.open(filename, "r");

local wideLine = file:read();
print(wideLine);

local wideString = string.match(wideLine, "tileswide (%d+)");

if (wideString == nil) then
	error('Invalid data: "tileswide (%d+)" not matched');
end

print(wideString);

The ("%d+") is Lua’s variation on regexes. %d+ means ‘one or more digits’ and the brackets mark it as a capture, so string.match returns either the matched value as a string or nil if the pattern didn’t match.

The prints are just there for debugging.


#167

Yeah I think you’re right about that, for things like this

I actually had went through the whole C# thing on SoloLearn, so I should be able to understand it if you did it with C#

Lua or C# is cool but…

I got it working with GMS2! And I might make a world editor in it. If I can load it, I can edit it and export it.

Right after I said I got it working, I had to spend another hour or two making the saving work lol. But now it does work, all I got left to do is… the actual thing to edit the level. But that can wait, the only urgent thing is the compression thing, which should be easy enough


#168

Ok, I’m getting headaches from this…
I initially wanted to “move” the right half of a section on top of the left side of a section. But that’s giving me headaches, so I’m thinking about just interlacing it like I’m doing here

Am I doing this right?

for(var i = 0; i < ds_grid_width(data); i++) {
	if (i % 2 == 0) {
		for(var j = 0; j < ds_grid_height(data); j++) {
			var _value_left = ds_grid_get(data, i, j) << 4;
			var _value_right = ds_grid_get(data, (i*+1), j);
			var _value = _value_left + _value_right;
			ds_grid_set(dataCompressed, i/2, j, _value);
		}
	}
}

Edit: yeah! I am doing this right! It’s working! Now all I’ll need to do is load it on the Arduboy


(Pharap) #169

I’m not sure what you mean by this.

By interlacing do you mean like this?:
Interlace

If so, I don’t think that’s going to be very efficient for the Arduboy to decode.

If you’ve got one tile per nibble then to get the high nibble the assembly would be (assume the tile byte has been loaded into r1):

LSR r1
LSR r1
LSR r1
LSR r1

And to get the low nibble, just:

ANDI r1, $0F

Interlacing would require far more than that.


#170

What I mean by interlacing is

index 0, right nibble. index 1, left nibble of index 0. index 2, right nibble. Index 3, left nibble of index 2

I initially wanted it to be

index 0, left nibble of index 0. index 1, left nibble of index 2. 0 to 7 lef nible of 0 to 7, and 8 to 15 right nibble from 0 to 7.

But in the end it’s pretty much the same thing, it’s a 16x8 area into a 8x8 area, each section contains only nibbles from itself so it’s ok.


(Pharap) #171

That’s the better way. It’s easier to work with logically and you end up having each byte representing tiles that are next to each other.

(They’re usually called high & low rather than left & right. High = left, low = right.)

That’s much less efficient. It’s better to have a byte store an odd-and-even pair.

That said, here’s how you’d read that:

constexpr uint8_t span = 8;

const uint8_t worldData[span] PROGMEM = { /*...*/ };

uint8_t getTile(uint8_t index)
{
	uint8_t data = pgm_read_byte(&worldData[index / 2]);
	return (index < span) ? ((data >> 4) & 0x0F) : ((data >> 0) & 0x0F);
}

As opposed to the better method of:

const uint8_t worldData[] PROGMEM = { /*...*/ };

uint8_t getTile(uint8_t index)
{
	uint8_t data = pgm_read_byte(&worldData[index / 2]);
	return ((index % 2) == 0) ? ((data >> 0) & 0x0F) : ((data >> 4) & 0x0F);
}

The side-by-side approach (or ‘interlacing’ as you called it) is better because it works regardless of the array size.
The former approach requires increasing the integer size after a certain point.
I.e. if span was 256 you’d have to go up to uint16_t.


If you were doing this on a CPU with a cache then the second approach would also possibly be much slower after it reached a certain size, because the CPU would be constantly reloading the cache (a.k.a. cache thrashing).

See also: Locality of reference.


I’m not sure this could be described as interlacing.

Interlacing is when you take two sets of source data and combine them into one by alternating the data.

(Image taken from here.)

A bit like how Sprites::drawPlusMask's draw mode works: one byte of the image, one byte of the mask, one byte of the image, one byte of the mask etc.

In this case, there’s only one block of data, so although you’re zipping two things into a single byte, they’re from the same source rather than two difference sources.


#172

Interesting! The ‘high byte’ means the first 4 bits (the first nibble) ?

Hum it wouldn’t go bigger infinitely, it’d be 0-8, 1-9, 2-10… and later 16-24, 17-25 basically an offset of 8. It’s not really important anyway, the pair-odd thing works just as well if not better, it will make it easier to program for.

My world is 1024x768 (I didn’t pick this on purpose but it is a nice coincidence) which means I have 8x12 screens of 128x64, or 16x8 tiles.

8 * 16 = 128
12 * 8 = 96

So I think I’ll be able to store entities’ positions in a single byte using the same method. Then there’s the entity id which I guess will use one byte. If I need more tiles later, I might make trees be an entity stored sperately (the trees take 4 tiles for themselves). I have 4 tiles left to design some type of cave entrence/brick walls or something alike.

As for the dungeons, I think I’ll need only 16 bytes per section, plus a few more bytes for entities (which includes traps) stored in them. I’ll use a dungeon wall tileset and an auto-tiling thing so it will look good even with only “floor” and “wall” as tiles.

I’ll probably up the entities number in ram to 20 to allow for traps and other extras. To avoid the design problem that city41 ran into when making Ardynia, the dungeons will be stored separately and will probably not be on a 2d array layout. instead it will be a flat array of all the sections in the dungeons, and I’ll somehow store the index it needs to teleport the player to when entering certain doors

I think that’s how I’ll design it. First I need to make my player have a sword attack and make some enemies, right now I’ve got a world but no game. So I think I’ll work on this first


(Pharap) #173

The “high nibble” is the first 4 bits.

To clear things up (or possibly make them more confusing):
Terminology

If you fixed it at 8 then it wouldn’t be much of an issue, but then you’d be forced to have maps that were multiples of 8.

That used to be a common monitor resolution. :P

((16 * 8) / 2) = 64 bytes per chunk

(I’ll call them ‘chunks’ because that’s what Minecraft calls its world sub-sections.)

64 * 96 = 6144 bytes of progmem

If it’s local to the ‘chunk’ then yes, you would. And you’d even have a bit left over.

struct LocalPoint
{
private:
	static constexpr uint8_t yMask = 0x07;
	static constexpr uint8_t yShift = 0;
	
	static constexpr uint8_t xMask = 0x0F;
	static constexpr uint8_t xShift = 3;

private:
	uint8_t value;
	
	constexpr static uint8_t combine(uint8_t x, uint8_t y)
	{
		return (((x & xMask) << xShift) | ((y & yMask) << yShift));
	}

public:
	constexpr LocalPoint(uint8_t value)
		: value(value)
	{
	}

	constexpr LocalPoint(uint8_t x, uint8_t y)
		: value(combine(x, y))
	{
	}
	
	uint8_t getX() const
	{
		return ((this->value >> xShift) & xMask);
	}
	
	uint8_t getY() const
	{
		return ((this->value >> yShift) & yMask);
	}
};

Don’t forget, you don’t have to have a global tile set, you can make the tile set local to the area.
E.g. the overworld can have grass, trees and rocks, dungeons can have brick walls but no grass or trees.

If you do that then you can start playing around with the indices to make dungeons disobey the laws of physics:

StrangeWarps

Edit:
This is basically how the lost woods worked in the earlier Zelda games.


#174

Good idea! I guess I’m extremely nostalgic of Prince of Persia because I’m gonna bring it up again. In one area you have to find your friend, there’s a ton of doors and most teleport you back to the door you came from. I was able to find a gameplay video where the person doesn’t know the answer to the puzzle… maybe you’ll be able to figure it out, here you go

(it really was one of my favorite games, I beat it many times over)

Yes I know, but I still need a few tiles for dungeon entrences. And if I want ‘bigger trees’ like this it might be difficult to do. (Although I suppose if I use 2 or 4 tilesets per chunk instead of 1, I’ll be able to add a lot of variety and make transitions pretty smooth)

For now I’m using the wheat thingy to make walls and borders, but I might allow the player to cut those. So if I had a better way to close off certain areas that’d be great. A big plain wouldn’t be too much fun, one thing that makes a lot of Zelda games great I noticed, was the level design

That’s also the case in Ardynia, you can’t just run in a straight line to go where you want to go. (and I think that’s one thing that makes Minecraft a bit boring, you just run in one direction if you want. You don’t have real obstacles. If I made a Minecraft clone, I’d focus on structure generation to make it quite the adventure)

I’ll go make some sprites and see if I come up with something. Maybe I’ll need only one tile for big trees and let auto tiling handle the rest


(Pharap) #175

Typical sound puzzle. :P
I had guessed the first time he went past the door, but couldn’t say for definite until he went back the second time at around 2:00.

The bit at the begining reminded me of Mario 64’s infinite staircase.

It could work. Technically that sort of means you’d using sub-chunks.

Trees, rocks, cliffsides and water are usually what people use.

Some of the areas are more open than others.

I actually quite like that about Minecraft.
(And you do run into mountains eventually.)

What lets it down is the terrain generation (I’m forever struggling to find world seeds that I like), and the lack of a decent objective.
(I think it’s probably more fun with friends.)

That’s sort of what Lego Worlds did, but even that gets repetative.

Now I think about it, what most sandbox games lack are proper objectives and fine-grained control of world generation.

(Pretty much all survival games lack dcent objectives.)

Trees don’t have to be massive. Usually 4 tiles is enough.


#176

With four tiles I end up with this, and maybe it’s totally fine and I’m just a perfectionist, but I very much prefer the way both Link’s awakening and A link to the past make their trees tileable. (I tried doing the same thing with the tree mush to the left)


#177

I modified the shape of the tree, using 4 tiles here’s how it looks (much better)


(Pharap) #178

To do that you’d need 8 tiles instead of 4. I’m not sure it’s worth the extra progmem.

You could save some space by using one of the libraries that have bitmap flipping support,
since then you wouldn’t have to store symmetric tiles,
but then you’d need an extra bit per tile to store the flip,
so you’d end up increasing the size of your map.

Although if you went up to a full byte per tile, you could use some of the extra bits to do other things.
E.g. you could store whether the tile is solid, you could have flipping and/or rotation.

But then you have to ask yourself:
“what’s more important, good graphics or good gamplay?”

Like I say, I hope it’s worth it, because that’s 4 tiles you won’t be able to use for other things.

If you do your “4 tilesets per chunk” thing then it might not be too bad I guess.


#179

I was able to do it with 4 but I’d need 2 extra tiles if I want to improve the pumpkin looking tree. If I only use the apple trees at the bottom, those are only 4 tiles (by the way they’re all 8x8 sprites, so it doesn’t take as much as Arduventure’s sprites which are 16x16)

I can use autotiling to free 3 tiles of space. When loading an area, if there’s a clump of tree tiles, some calculations and boom nice trees. It would mean however that each chunk takes more space in RAM, and I haven’t thought about that a lot. In RAM a chunk would take twice it’s compressed size

I bet I can have both. I needed something to keep the player from going anywhere he wanted, and tileable trees is a great way to do it. I had already planned on 4 tiles for trees, because they really make the world look better and be more immersive

I made another tree that tiles a bit better but doesn’t look evil

Right now I have 3 tiles for walkable tiles, 4 tiles for houses (two tiles for two roof types), 4 tiles for fences (I forgot to show you the fences I made!) and 4 tiles for the trees. With this I can make a good and fun overworld already, even without dungeons. In an area without houses I’d have 4 more tiles

Oh and, I think each tileset will be of 4 tiles. This way if I want to replace a tree with something else that takes 4 tiles, it’d be easy to do.

What’s really cool if I have enough space is that I can have different tree types for different atmospheres. Evil trees for the evil forest, and the nice apple-tree looking trees for more peaceful areas. I might be too ambitious here but it might be feasible in the end. I also made castle/dungeon walls but it’s taking a lot of tiles, I think I’ll have to modify it a lot or get rid of it

house, the original tree and some fences

castle and dungeon stuff, that I might need to remove entirely unless my sub-chunk thing works really well

Edit: it makes for nice world borders


(Pharap) #180

I meant 8 in total, including the ‘plain’ tree tiles.

How exactly are you doing the ‘autotiling’?

But only to a certain degree.

One of the golden rules of programming is that everything is a trade-off.
Every feature you add has a cost.
That rule applies even more so to the Arduboy.

If you focus too much on making the world look good then when it comes to add gameplay features you’re going to hit a point where you have to start cutting things out, and that can get painful if you’ve become emotionally attached to certain features.

If you start off with getting everything running at a basic level and then fleshing things out, it’s less painful than cutting out things you’ve already worked hard on.

I speak from experience, particularly with Dark & Under.
There were a lot of things we really liked the idea of, but there had to be compromises and things got cut.
That’s why when I did minesweeper I kept it simple to start with and fleshed it out after the functional mechanics were implemented.

Like I say, it’s better to get the gameplay working first and make it pretty later - functionality before aesthetics.
It’s surprising how fast you run out of memory, and graphics do eat quite a lot of memory.

You can always release the ‘director’s cut’ on another system.


#181

If we’re talking about having 6 tiles for a tree, simply checking if “above here == top left tree corner” && “above to the right == top righ tree” (if ‘here’ is a top part of a tree)

It might not be as easy as I think now that I have trees that tile with each other.

If I were to use a 16 tileset just for the trees (I probably wouldn’t do that, that’d be 16 * 8 bytes == 128 for the tree sprites) then I could use a traditional autotiling

My HTML5 version of the game uses autotiling, here’s the code:

for(var i = 0; i < _grid_width; i++) {
    for(var j = 0; j < _grid_height; j++) {
        var _grid_value = ds_grid_get(_grid, i, j);
        
        if _grid_value != -1 {
            var _i_offset, _j_offset;
            var _up, _right, _down, _left;
            var _closed_borders = true;
            
            _i_offset = 0;
            _j_offset = -1;
            if ds_grid_out_of_bounds(_grid, i+_i_offset, j+_j_offset) {
                _up = _closed_borders;
            } else {
                _up = ds_grid_get(_grid, i+_i_offset, j+_j_offset);
            }
            
            _i_offset = 1;
            _j_offset = 0;
            if ds_grid_out_of_bounds(_grid, i+_i_offset, j+_j_offset) {
                _right = _closed_borders;
            } else {
                _right = ds_grid_get(_grid, i+_i_offset, j+_j_offset);
            }
            
            _i_offset = 0;
            _j_offset = 1;
            if ds_grid_out_of_bounds(_grid, i+_i_offset, j+_j_offset) {
                _down = _closed_borders;
            } else {
                _down = ds_grid_get(_grid, i+_i_offset, j+_j_offset);
            }
            
            _i_offset = -1;
            _j_offset = 0;
            if ds_grid_out_of_bounds(_grid, i+_i_offset, j+_j_offset) {
                _left = _closed_borders;
            } else {
                _left = ds_grid_get(_grid, i+_i_offset, j+_j_offset);
            }
            
            
            //up, right, down, left
            var _img = 0;
            if(_up) _img += 1;
            if(_right) _img += 2;
            if(_down) _img += 4;
            if(_left) _img += 8;
            
            ds_grid_set(global.level, i, j, _img);
            
        }
    }
}

I would use autotiling for the dungeons, as each section will probably be 16 bytes +/- a few bytes for entities


#182

I’ll keep that in mind. It’s true that there’s a lot left that I haven’t thought about yet, like the tileset I’ll use for inside the houses and the sprites for the enemies

Something I might struggle with/need to start over with is my sword attack animation. It looks really good and works well on the prototype I made but I’ll need to make it work as a few 8x8 sprites instead of multiple 24x24 sprites (there’s a ton of transparent pixels being wasted, and the animation being multiple frames, and the need for 4 directions, that all gets costly quickly)