Ancient language - World map

Started by
24 comments, last by Stainless 8 years, 1 month ago

My first post so hello to all smile.png

It's not that I can't do it but I know I won't do it efficiently and it really matters this time. I tend to complicate too much in programming areas I'm not very experienced with so I come to ask your help guys.

But before I start to present you my question let me explain please a very important thing. I'm creating a program in an ancient BASIC like language called AMOS for AMIGA computers. It's important because I aim to 2 MB of RAM configuration. Yes, two MEGABYTES, not gigabytes smile.png. This changes a lot as you surly agree.

I have a world map 2400 x 2400 pixels. It's simply too large to load it complete to the memory (apart from this map I have other graphics, a lot of code and also need a room for music and sound samples.) I decided to divide and split it into smaller sections:

World_divided_draft.jpg

I created files called by the following order:
world_ne_1a.iff
world_ne_1b.iff
world_ne_1c.iff
...
world_ne_5a.iff
world_ne_5b.iff
world_ne_5c.iff

world_se_1a.iff
...
world_se_5c.iff

world_nw_1a.iff
...
world_nw_5c.iff

world_sw_1a.iff
...
world_sw_5c.iff


Those files are about 40kB each and have resolution 400 x 240 pixels.

This is how I'd do it (it might not be the best way but this what came to my mind):

Input: A spot on the map using real N/W/E/S coordinates.
1. Convert to pixel coordinates (geo to pixel - already fully functional in my program).
2. Check to which of the four sections of the world it corresponds. For instance, if it's NE section of the globe/map then the program determines on which box 400 x 240 pixels it appears on.
3. Load that file (e.g. world_ne_2b.iff)
4. Copy whole image and store it as blocks 50 x 30 pixels (400/50=8, 240/30=8 - I need those to be divisible by 8 pixes and these values fit perfectly my need)
5. Having X,Y converted data pixel from point 1. center corresponding block (50 x 30 pixel) on the screen (200 x 176 (on my sketch it's 200 x 180 but it should be 200 x 176)) and fill the rest of the visible screen around it with other appropiate blocks of the map.
6. New data input: GoSub 1., GoSub 2., GoTo 7.
7. If new coordinates do not correspond to the actual section displayed on the screen and other map blocks stored in RAM erase those blocks from memory and GoTo point 2.

That's the main idea. But there can be a more RAM memory hungry scenario where a spot appears on the map close to the "corner" of a 400 x 240 box. Then the program needs to load two or even four pictures depending on the X,Y axis. But even four images (~160kB) loaded into RAM is not a problem.

Now goes my question: How to program it using BASIC like code? How would you do it guys? In a pseudo code or whatever language you prefer (except references to API or DLLs)

Thank you in advance and if you need me to clarify some of my description please let me know.

Advertisement

I don't think anyone's going to touch your question dude. Without meaning to be rude - it sounds like you need to learn BASIC / AMOS yourself and then you'll be able to answer your own question. Maybe start with a test program that shows a map that is just two screens big or something.

BTW it sounds like you need a tile map - dont store whole screens worth of background images. Tiles (assuming you've got lots of repeating graphics) are much more efficient memory wise. If AMOS is anything like STOS (Atari ST precursor to AMOS) then there should be lots of plugins that can handle this for you, if the language doesn't do it directly.

Storm Clouds over the Western Front - 2D aerial combat WIP | DarklightXNA on Twitter | 2DFlightSim on Youtube

So firstly why are you not using a Tilemap?

Secondly as you stated AMOS is Ancient. I did play around with it in like 91 - 92 but, nowadays Ive forgotten it, I couldn't even tell you how to write a Hello World using AMOS. I don't think you'll get much help on Gamdev but, there is a "Commodore Amiga" group on Facebook. A bunch of guys on there still develop games in AMOS so if you joined there and asked for help you'd get a better response.

I know nothing about AMOS. But can't you just load part of a file in AMOS? If so, then no need to divide your world map into several small ones. Just open the file and read in what's needed. That way you'll avoid having to load 4 minimaps when close to edges. I know this doesn't answer your question but I hope it helps you some.

Site: Hexmind.com Twitter: @HexmindGames Facebook: /hexmind Working on upcoming game, Reapertom.

you're talking about implementing terrain chunks. when the world map is too big to fit in ram all at once, you divide it into chunks (squares), and page them off of disk into a cache with a LRU discard algo. and yes, when you approach an edge you need two chunks to draw, and four chunks for corners. you may need even more chunks, depending on chunk size and visual range. chunks in caveman (a fpsrpg) are about the size of visual range, so typically at most four are visible in the viewing frustum. the cache size is 60 or 90 chunks shared between 1 to 50 PCs. i'd like a cache size big enough to store all chunks around the max possible number of PCs (say 9 chunks times 50 players), but it would take up too much ram.

you can do a google search and ask questions here about how to design a chunk system.

but you'll probably need to goto the amiga sites for help with AMOS basic syntax.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Thanks Norman, I'll look into that, it's interesting but maybe I'll point you and others to what I think could work - with your help guys of course.

@Hexmind I can't load whole map because 2MB of RAM is not enough for it. But I'm starting to think that I could simplify it a bit more that I though. See below.

@xbattlestation I know AMOS very well, it's not an issue. I did ask how would you do in BASIC like code but It really doesn't matter much what language it is. Pseudo code can be adapted to practically any language. I know C++ (I created a game in OpenGL) so even if it was in it's pure code (no API nor other stuff like dlls, etc.) that would do too. Yes, AMOS is based on STOS, you're correct. But there is no need to use any plugin because AMOS has sufficient graphics commands built in. I already have a routine that stores blocks and draws them onto the screen but it's just displaying, it doesn't interact with the rest of my code. I keep those blocks as tilemap, as Buster2000 also suggested. But now I need to access them according to the pixel X,Y position. I thought I could store this tilemap in an array, but how to define it and how to access it by given input coordinates?

World_map.jpg

2400 x 2400 pixels

If it was just a simple array, let's call it world[5,9]...

--NW-----NE--
world[0,1,2 | 3,4,5]
world[1,n,n | n,n,n]
world[2,n,n | n,n,n]
world[3,n,n | n,n,n]
world[4,n,n | n,n,n]
--SW--|--SE--
world[5,n,n | n,n,n]
world[6,n,n | n,n,n]
world[7,n,n | n,n,n]
world[8,n,n | n,n,n]
world[9,n,n | n,n,n]


...I'd do the following thing (I'm open to any suggestion/correction):

The axis "cuts" the world map and divides it horizontally and vertically. First the program needs to determine which of four sections the given coordinates apply to. That's an easy part: N0°-N90° and E0°-E180° corresponds to upper right (NE), N0°-N90° and W0°-W180° is upper left (NW), S0°-S90° and E0°-E180° is lower right section (SE), S0°-S90° and W0°-W180° is lower left (SW). So I'd do a simple check:

If coordinate_X <=2 AND coordinate_Y <=4 Then section of the map is NW
If coordinate_X >=3 AND coordinate_Y <=4 Then section of the map is NE
If coordinate_X <=2 AND coordinate_Y >=5 Then section of the map is SW
If coordinate_X >=3 AND coordinate_Y >=5 Then section of the map is SE


Let's assume for this example we want to display Sri Lanka island which lays in the NE section 1b zone:

NE_section.jpg

Knowing the section and pixel position X,Y from geo2pixel routine the program needs to determine now the image file which is 400 x 240 pixels. That doesn't seem to be complicated either. The center of Sri Lanka is more or less at X=538 adn Y=1152 (remember that each section of the world is 1200 x 1200 pixels). I'd do this checking:

If coordinate_X <=400 AND coordinate_Y <=240 Then load image world_ne_5a.iff
If coordinate_X >400 AND coordinate_X <=800 AND coordinate_Y <=240 Then load image world_ne_5b.iff
If coordinate_X >800 AND coordinate_Y <=240 Then load image world_ne_5c.iff
If coordinate_X <=400 AND coordinate_Y >240 AND coordinate_Y <=480 Then load image world_ne_4a.iff
If coordinate_X >400 AND coordinate_X <=800 AND coordinate_Y >240 AND coordinate_Y <=480 Then load image world_ne_4b.iff

...and so on until X=538 and Y=1152 fulfill the condition:
If coordinate_X >400 AND coordinate_X <=800 AND coordinate_Y >960 Then load image world_ne_1b.iff


At this moment I have the section and the image file. Should I create another array? If so it could be map[7,7] (400/8 x 240/8 = 64 blocks 50 x 30).
Now some calculations:

local_X = X (538) - 400 (1a is out of range so do not count it) = 138
local_Y = Y (1152) - 960
(5b to 2b are out of range, do not count their Y) = 192


New local coordinates are X=138 and Y=192. So far so good. Now let's find the tile:

tile_X = Int ((138 / 50) * 0.5)
tile_Y = Int ((192 / 30) * 0.5)

(tile_X = 3, tile_Y = 7)

Now I'd have to center it on the display area 200 x 176 (although the screen size is 320 x 256 I use limited area due to the graphic panel and other data).
At a time there can be only 4 or 5 visible horizontal tiles and 6 or 7 vertical (depending on the point at the centered tile):

NE_1b.jpg

But maybe I don't have to create any tiles but simply center the whole 400x240 image? And in case if some of the map pases onto another section (like in this case of Sri Lanka where I'd need to attach another image from SE section bcause it is too low on the screen) simply load it from another picture(s) and stick them to it in order to fill the area? Sounds like a solution somehow. It wouldn't be pro but I'm starting to think that I'd be OK with it...

Any (constructive) thoughts regarding?

Just jumping in right here, but why don't you organize your filenames in pixel-base coordinates?

In X direction you use chunks of 400 pixels, and in y in chunks of 240 pixels

world_x0_y0.iff

world_x400_y0.iff

..

world_x2000_y2160.iff

No idea about your language, but something like


xbase = 400 * int(xpos / 400);
ybase = 240 * int(ypos / 240);
filename = "world_x" + str(xbase) + "_y" + str(ybase) + ".iff"

(xpos, ypos) is the pixel coordinate, "int(xpos / 400)" does integer division (rounding down), "str(xbase)" converts number to string.

That's why I posted here - to hear suggestions desismileys_3254.gif. Thanks for your tip Alberth, seems to be a good idea s0801.gif

if the world is 2400x2400, and your images are 400x240, then your obvious choice for chunk size should be 400x240.

so your world is 6 chunks wide, by 10 chunks tall.

you'll need to be able to convert between world coordinates and chunk number plus coordinates in that chunk.

world2chunk:

cx = wx / 400

cy = wy / 240

x = wx-cx*6

y = wy-cy*10

chunk2world:

wx = cx*400+x

wy = cy*240+y

where wx,wy are the world coordinates,

cx,cy are the chunk number

and x,y are the coordinates in the chunk.

to draw, you take the camera's world coordinates, and determine the chunk number (cx,cy) and location in the chunk (x,y).
the chunk number (cx,cy) tells you which chunks must be drawn: chunk cx,cy, and enough chunks around it to fill the screen. how many chunks radius around it you must draw depends on the current zoom. do a trivial check for entirely offscreen, and draw the rest. you might just use a brute force algo that simply draws all chunks with a trivial offscreen rejection check first. you only have 60 chunks, the rejection test would only be like four greater than or less than checks. so 60 * 4 = 240 greater than or less than checks total - that's nothing on today's PCs. from the chunk number and location in the chunk, you can determine the x and y scroll offset used for the entire map to center the location on the screen.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Do you need rendering speed?

If you don't then all is good.

If you do then the approaches above are not going to work.

The approach I used on the Amiga was to scan the map and break it down to unique 8 by 8 tiles.

The first thing you notice is that the Earth has a lot of water. A hell of a lot of water, I mean I wouldn't want to try and drink it even if it was beer.

So all the areas of the map that are solid water can be broken down into a single 8 by 8 tile.

The same basic idea is used to extract all the unique tiles you need to to display the whole map. When I did it I was a bit brutal in the comparison tool and got it down to 187 tiles.

So 187 * 8 * 8 = 11968 pixels. A hell of a lot less than 2400 by 2400

Then you need a map. 2400/8 * 2400/8 is 90,000 so you could just use that, but I needed ram for game code as well.

So I then ran the code again on the generated map to create macro areas which contain 8 by 8 tiles. Each macro tile is then 64 by 64 pixels, which was perfect for me a large play area in a small amount of bytes.

I can't remember how many tiles that generated, it wasn't a huge improvement like the first run, but I think it saved me a couple of K.

Anyway, this is only if you need speed. The technique you are currently using will be fine otherwise.

This topic is closed to new replies.

Advertisement