Questions about optimizing code

Sorry, how do you mean?

Sorry, yeah I actually meant to remove that struct after I ended up just using the arrays, didnt mean to make things more confusing than necessary.

And as for the rest of it, I have it set up so that when each quadrant reaches its respective limits it resets the backgrounds coordinates so the backgrounds continually alternate in each axis (and by association whatever may be tied to them). I got the alien positions to work correctly by just increment them per player movement alongside the map, rather than their positions being set by adding the map increment during the draw (if that makes any more sense). But I also wasnt sure how to move from two one dimensional arrays to using a two dimensional array so ill fix that, thanks!

So basically, at the start (before any backgrounds reach their limits and reset), the player is in the top left quadrant with the backgrounds drawing down and right, and the alien locations fit within that same 2x2 rectangle now (but also dont repeat with the backgrounds). The player draw command is reflective of the same coordinate system (at this point) because it also draws from the top left, but since the player stays in the center of the screen I made the secondary object ardunautMapPos in order to keep track of it where it is in relation to the the map and alien coordinates.

I get the idea of the euclidean distance because im pretty familiar with geometry and trig, and i would think that inputting the alienX and Y and the player X and Y would just give the distance (and you could say if the distance is shorter than whatever specified distance then close that distance to chase), im just not sure how to tell it to shorten that distance in turn.

The camera and player move, the world stays where it is.

Then the backgrounds don’t move until it’s time to draw them.

At which point they temporarily ‘move’ so they can be drawn,
but they don’t actually move, you’re just calculating their screen coordinates.

That’s what I did in the StarTerrain demo.

Oh hang on, I think I know.
You’re using the Egyptian log trick.

EgyptianLogs

As the block moves off the back log, the back log is moved to the front.

Except the logs are your background(s).

Nope, still don’t get it.

The example I gave isn’t a two dimensional array.
It’s a one dimensional array of Point instead of int.

That’s good. When I started programming I’d forgotten everything and had to relearn it all.

Yes, precisely.

Vectors!

Except I don’t have time to explain them because it’s late,
so here’s (rather oddly for me) a Youtube playlist explaining various aspects of vectors:

(If it’s not showing up, click here.)

You don’t necessarily have to listen to the whole of each video, you can skip through every few seconds and still make sense of it.

1 Like

Ah, yeah, thats why I was initially trying to do what you did in the star terrain demo for this part, figured it was probably more sensible, was still just a bit too far over my head yet though, sorry.

And yeah, thats essentially what im doing, I just saw some benefits in doing it that way over just drawing the backgrounds in a different location because the egyptian log trick still retains the map values for objects tied to it (and I wasnt sure if the star terrain demo was similar).

I just meant that I was initially having issues with the alien sprites because they were tied to the background coordinates so when they got egyptian logg’d the enemy coordinates did too, so now I have them on the own coordinate system (basically overlaying the background’s) which i increment the same way I move the map via player input.

And sorry, id just gotten myself more confusing thinking the points would have two values for the array… im still not too strong on arrays and i think ive been subconsciously avoiding them so ill just go ahead and get myself better read on that too, and points for that matter.

And i forgot about vectors, but i already have some idea of that from my old job field too, luckily. Just been getting rusty with my old skillset and kind of forget since its not right in front of me. But ill definitely look more into that and get a better idea of the math involved, thanks!

And no worries, appreciate the help as it is, sorry i seem to make more of a mess than i can clean up but hopefully that should help get things straightened out more here :stuck_out_tongue: thanks again!

Which part?

If you’re still worrying about what goes on in the hash function, don’t worry about it.
You don’t have to understand how it works to understand what it does.

It could just as easily be:

uint32_t hash(uint32_t value)
{
	// 127 and 8191 are prime numbers
	// (specifically 'mersenne primes')
	return ((value + 127) * 8191);
}

uint32_t hash(uint16_t x, uint16_t y)
{
	const uint32_t x2 = x;
	const uint32_t y2 = y;
	const uint32_t value = ((x2 << 16) | (y2 << 0));

	return hash(value);
}

uint32_t hash(int16_t x, int16_t y)
{
	return hash(static_cast<uint16_t>(x), static_cast<uint16_t>(y));
}

The important thing is the job that the hash function does:

  • It takes a pair of coordinates (x and y) and returns a seemingly random value (i.e. there should be no obvious pattern to the output)
  • It provides a valid output for all possible combination of input values (i.e. it’s a ‘surjective’ function)
  • It always provides the same output for the same pair of inputs and it has no side effects (i.e. it’s a ‘pure’ function)

Any function that meets those three criteria could be used for the hash,
the only difference would be in the quality of the result.

I’m not sure what you mean by this.

Or this.

I think you might be getting the meaning of ‘coordinate system’ mangled.

Usually for a 2D game there are only two coordinate systems that need to be taken into account: world coordinates and view/camera/screen coordinates.
(For a 3D game there’s usually two other systems to take into account.)

The typical way to handle a 2D world is to give all the terrain static coordinates (i.e. non-changing coordinates),
and all movable objects/entities dynamic coordinates (i.e. changing coordinates).

Then there’s a ‘camera’ object which represents the screen,
and that object moves around the map.

Then when it’s time to render, the world coordinates are translated to screen coordinates by subtracting the camera’s position.

CameraSmall
(Excuse the hand-drawn diagrams, I find hand drawing quicker and easier than digital drawing.)

For example, if the camera object is at (16, 16) (top left coordinate), and an enemy is at (64, 64),
then when they’re translated into camera/view/screen space,
the camera will be at (0, 0) (so the camera’s top left coincides with the screen’s top left),
and the enemy will be at (48, 48) ((64 - 16) == 48).

They’re literally just a block of memory with values laid end to end.
For example, int array[4] would be 8 bytes.
In memory it would look something like this:

[0x0400] array[0], low byte
[0x0401] array[0], high byte
[0x0402] array[1], low byte
[0x0403] array[1], high byte
[0x0404] array[2], low byte
[0x0405] array[2], high byte
[0x0406] array[3], low byte
[0x0407] array[3], high byte

The hex values represent RAM addresses, I made up the address values.
The low byte comes first because AVR is ‘little endian’ (like x86),
which means lower valued bytes are stored first.

A Point consists of 2 int16_t, which are two bytes.
In memory a Point looks something like this:

[0x0500] x, low byte
[0x0501] x, high byte
[0x0502] y, low byte
[0x0503] y, high byte

So an array of two points, Point points[2], would look like this in memory:

[0x0600] points[0].x, low byte
[0x0601] points[0].x, high byte
[0x0602] points[0].y, low byte
[0x0603] points[0].y, high byte
[0x0604] points[1].x, low byte
[0x0605] points[1].x, high byte
[0x0606] points[1].y, low byte
[0x0607] points[1].y, high byte

That’s literally all there is to it,
the data is just stored in memory contiguously,
and the compiler handles all the maths needed for moving the data around.

2 Likes

I’m still trying to determine that :stuck_out_tongue: just because there are a lot of parts that are new to me, so I can follow up to a point but like I said, then it just kind of starts to blend together, but I didn’t want you to have to break it down for me step by step so to spare you a lengthy explanation I’m trying to better inform myself on what’s going on at each step by breaking down and identifying each part I don’t know.

But that definitely helps a bit knowing that about hash functions- I remember you mentioning that before but sometimes I can’t see the forest for the trees when being faced with a lot of new information (an unfortunate byproduct of adhd, like I said, but something I’m working on), but I also forgot that somewhere along the lines so when I give it another look I’ll know that I shouldn’t need to follow along with that part as much. I just want to be able to follow along with the rest of it so I can change it to use for the other part without having to ask you to change it (and because I’m trying to do as much of the work myself so I’m not asking others to do it).

And as for my looser definition of coordinate system I suppose it isn’t in the usual sense then (as is in camera and word coordinates), I just can’t help but think of it in those terms because it’s still confined to some sort of coordinate system based off the screen x/y draw origin- all my map tile coordinates are based (and placed) in relation to it and so are my objects- only initially, since I move the map coordinates for player movement, other objects were tied to the map also (because, for example, during the draw command for my launchpad or enemies the x and y values were their x and y + background x and y so they would move with it).

Although effectively there are multiple actual coordinate systems at play (for the backgrounds, player position, and enemy locations), more so now that I changed the enemy coordinates to be their own coordinate system (so when player inputs left rather than just background x + and enemy x drawn with that, player inputs left and both background x + and enemy x+).

But given how much more complicated (and convoluted) my method gets I can see the benefits of the static world and camera method, so I’ll try to review again and implement it.

Also I better organized my game by further breaking it down into more header files (one for in flight, one for on foot, one for the menu, etc) to make it easier to look at/read. Not sure why I was having difficulty with that before

My advice would be to write it down as you go.

Draw some diagrams too.
(The stacks of paper on my desk are getting ridiculous.)

Every time you understand something, give yourself a biscuit.
(Perhaps not a biscuit, you’d get through at least 100 by the end, and that can’t be good for your health. But you get the idea - keep the reward loop running.)

Ah, ok, in that case technically the enemy coordinates are local to the background coordinates,
which does sort of mean that’s a separate coordinate system.

But that’s a cause for concern because that means there’s no such thing as ‘global’ coordinates,
because everything keeps moving.

Yeah.
I think really you need to separate the background rendering from the world itself.

At some point I’ll try to sit down and figure out a way to render your backgrounds infinitely without actually ‘moving’ the backgrounds as such.

I’ve put it off because I don’t like maths.
(Saying “I don’t like maths” is probably a terrible thing for a programmer to say given the amount of maths involved in programming.)

Do you need all four backgrounds or are you happy with having just one background tiled infinitely?
(The parallax is going to complicate things, that much I’m sure of.)

1 Like

Well that’s another reason why I did it the way I did it- was to restrict/repeat the actual playable area, too (via the local background coordinates) so rather than just repeating the background tile the map itself repeats, (so that flying in the x direction always brings the player back to the launchpad and so the space station can ‘orbit’, and so on foot the player comes back around the other side of the map I’m x or y like they’re running around a small sphere/planet).

But this is also something I could just define for each part based off the same coordinate system (once I get that set up) rather than it being that way by association, so if I need to just start again from the ground up to structure everything different (because trying to change everything would make too big a mess) then I’m fine with that too, will probably do that anyway so I’m not trying to sort out a mess.

There are multiple ways of doing that, some easier than others.

In fact wrapping the player’s coordinates is easy, the hard part is actually the rendering.

Technically it would be a torus.

(There’s an article about this quirk here.)

You probably don’t need to tear everything up,
but I think having a global coordinate system will make everything easier.
Especially later when you’ve got projectiles flying across the screen.

1 Like

I’ll have to think on that a bit then, not sure how I’d go about everything now

Haven’t got parallax in, but here’s an infinitely tiling background:

The important bit is around here in drawBackground():

(Ignore the <<, I’ll explain that another time.
It’s just me being too lazy to write a long list of print calls.)


I’ll explain the maths tomorrow if you can’t figure it out.

Referring back to my diagram in this post should help:

1 Like

Sorry, I’m still lost.

I’ve started on a diagram, I’ll probably finish it tomorrow.

If in doubt, read the code as if you were the Arduboy,
and manually calculate some of values with some example inputs.

1 Like

Ah, yeah, sorry, probably should have occurred to me sooner to try to trace out what it’s doing step by step the same way on paper as trying to read it like I was the compiler, hopefully that’ll help me to compartmentalise what’s going on a bit better, thanks!

EDIT: Sorry, got a bit tied up elsewhere since and am just now able to get back to it… Im sure you dont mind the wait/have other things to do, just didnt want you to take the time/energy going too in depth if i havent done what i can yet to do the same, myself. But just now getting back to it.

Hm… so I can understand up until the first few blocks of drawBackground(), more specifically here:

	const int16_t left = (camera.getLeft() / tileWidth);
	const int16_t leftOffset = (camera.getLeft() % tileWidth);
	
	const int16_t top = (camera.getTop() / tileHeight);
	const int16_t topOffset = (camera.getTop() % tileHeight);

I can see how you make the camera object then just increment it via player input, I just dont understand the use of the modulo operator here.

Then I dont understand from here down either:

        const int16_t yStart = (top > 0) ? 0 : -1;
	const int16_t xStart = (left > 0) ? 0 : -1;

I understand how this evaluates if the first expression is true or false and then evaluates one of the following two depending on the result, i just dont quite understand what comes after it (ignoring the debug draw, of course) or just how it relates to whats above, either.

Sorry, I’ve been busy the last two days so I haven’t had chance to finish all of that diagram.
I did a few bits, then I went over them in pen because the pencil looked a bit faint,
but the pen wasn’t very good so now it’s a bit of a mess.

Here’s two parts from it that might help:

OffsetsSmall TileIndicesSmall

Basically modulo produces the remainder after division.
Dividing the camera’s x by tileWidth tells you the index of the cell that the camera is in.
Using modulo on the camera’s x by tileWidth gives you the remainder of that,
which is the offset of the camera’s x into the tile it’s currently in.

Likewise for y and tileHeight.

The reason the condition is there in the first place is because 0 and the negatives need to start from -1 rather than 0 otherwise the rendering doesn’t work properly because it’s off by one tile/cell.

I’ll explain that another day, but the (rather scruffy) diagrams I posted above might help.

(I really need to find some coloured pens. I’ve only got

1 Like

Oh no worries, it’s not goin anywhere :stuck_out_tongue: plus I keep myself busy messing around with other things in the meantime.

And that definitely helps clarify, thanks! I knew what the modulo operator was/did, just wasn’t sure if it was really being used how it seemed (as in the remainder being somewhat literal as far as the tile goes). Thanks again!

I’ve updated the code to make the names a bit more descriptive.

I’m going to redo the diagram using the new variable names becuase I’ve just realised the way I was doing it before probably doesn’t make as much sense in context.

One of the reasons you might be struggling to understand it is because I’m cheating a bit.
Normally you’d use the actual tile indices to index a map and draw the tile in the map,
but because the background is going to be all one tile and it’s going to be drawn infinitely,
but instead I’m drawing tiles from 0 (or -1) to the number of tiles on each axis.

Sorry for the delay in this but these last few days have been quite busy for me.

1 Like

Oh no worries on the wait, sorry it’s been taking me as long to grasp it, but I’ve been intermittently working on other stuff to keep busy in the meantime… I can just see the camera system being more beneficial too, so I’m also holding off on working on anything too major til I get it (so I can use it for other applications as well). I’ll get back to it tonight though and try to get it worked out. Thanks again!

Actually, now that you mention it, ive started another game and im now at a point where using the tile indices should make more sense to me (and i would need to adapt the camera for it, too) but im still have a hard time, for a few reasons…

Mainly, im trying to figure out how to change what i have so i wouldnt have to rewrite it entirely (because so much of it is dependent on how its written now)… also since i would be using it in different ways between the games ive started I dont mean to bounce around, thats just sort of why ive been having a problem…

As for this game, since i want to repeat the actual map coordinates im confused as to how id do that now too… even if i just hold off on changing the flight part for now (due to the parallax) and only try to modify the exploration part (which is simpler and also repeats the same sized tiles).

And then additionally, i have another game i just started. Just noticed the lack of RTSes on here… i know these are due to limitations but i thought why not make a simplified/one-bit RTS and started on that (which is what the rectangle question was for)… nothing too crazy considering the limitations, just something little/portable. At the moment its the just the cursor/rectangle bit, a randomly populated 2 dimensional array (filled with 16x16 rectangles for trees, rocks, or empty space, but i can maybe work this into better patterns), and a camera object (which is currently set up to scroll like this one, but i am hoping to change to an actual camera using what you have here). Since this uses the tile indices i may have better luck giving it another look over with that in mind too, though.

Here’s another drawing that may help:

This time the variable names match up:


You’d have to loop the coordinates of objects in the world when they move past the ‘edges’ of the world.

@Botisaurus was working on a turn-based strategy, but he ran out of memory,
so he’s been reworking it when he gets time spare.
(I’ve been assisting him from time to time.)

I think one of the reasons Arduboy doesn’t have many RTS games is because usually RTS games are heavily reliant on hotkeys.
I think at the very least you’d have to be able to pause combat to go through the menus,
otherwise you’d struggle to keep up with the action.

What exactly would the difference be?

One of my other drawings might help with that one:

If in doubt, have a look at the tile rendering code from the platformer I was helping with a while back:

You should notice some similarity to my earlier code,
albeit some of the variables have different names and are initialised later.

1 Like