How to create a level map?

In a game where the camera centers on the player and the scene/level is bigger than the screen I want to create a radar or map view in the screen corner. It does not have to be a complete screenshot but at least show the level with the position of a few sprites (Player, Treasure but e.g. no enemies).

How to best accomplish that? Maybe there is also some fog of war that can be added?

Minimaps with fog of war are actually quite complex because you have to do the following:

  1. Mirror the player’s movement to some sort of “minimap player” object
  2. Move the minimap when the player scrolls to a new screen (or as the player moves)
  3. Reveal parts of the map as the player reaches them.
  4. Hide parts of the map that are too big for the “Minimap window”
  5. Store the state of the map if you leave a scene and come back.

These are not simple things for any game engine, but you can do them in GDevelop.

I’ve successfully made a minimap (You can see and download my example here: GDevelop Dynamic Map by Silver-Streak), and I’ve also seen another successful map created by @RapaGameZ

If I understand right, Rapa has the map drawn out fuly, has a bunch of black boxes that hide the map, and then destroys each box the “Minimap player” comes in contact with to reveal part of the map.

Feel free to look through my example, but you’ll need to dig into a lot of dealing with positioning, layers, secondary cameras, etc.

Thank you for that response. It is excellent news that a level map can be accomplished.

I had a quick look at your demo, and it looks interesting so I downloaded the code. Will have to through details later. What I had in mind somehow was to have some canvas that I can draw on just the important parts of the level and keep it in memory. Then have it rendered through a sprite, and only the dot representing the player’s position would have to be custom painted.
Fog of war could be done by a second image acting as a fog mask that will be drawn on top of the first image. In that fog mask the pixels would loose transparency over time and thus show their real (black) color. Wherever the player runs the overlay could be painted with 100% transparent black ink.

This would just require editing images in memory. Is there such support in GDevelop, or maybe at least in JavaScript?

Now I can partly answer my own question:
Yes, JavaScript has a Canvas API that could help: Canvas API - Web APIs | MDN

However I’d still have to work out how to actually use it.

couldn’t you add another layer, create objects that represent game objects, and simply assign them the coordinates of the game objects but divided by maybe 10 or more, that way it will show the position of the objects but on a smaller scale?

This could well work although I believe it is a lot of overhead on the developer (me).

GDevelop has to render the scene anyway. Usually only the portion visible by the camera is rendered.

Now imagine you could zoom away until the whole scene fits the screen and take a screenshot to be kept in memory. If this screenshot allows some more operations as I mentioned above the topic could be closed in a generic way.
The performance penalty would be based on the speed of the machine and the idea of the developer. For my purpose it would be sufficient to create that screenshot at the beginning of the scene. When rendering that out I’d just add one point as player position, and optionally the mask resembling the fog of war.

That means in the game loop/render part there would be

  • one image blit operation (show the map)
  • one image blit operation (overlay the fog of war)
  • one filled circle drawing (indicate the player position)

During the game loop/update part there would be

  • one image blit operation (intensify the fog globally)
  • one filled circle drawing (unfog player’s vicinity)

I’m not sure whether the camera can be zoomed out, but if that assumption holds true I believe this concept could be implemented as a generic extension.

Zooming the camera is possible:
http://wiki.compilgames.net/doku.php/gdevelop5/interface/scene-editor/layers-and-cameras#zooming_with_camera

Even the screenshot is possible (although I would not see necessity to access the filesystem):
http://wiki.compilgames.net/doku.php/gdevelop5/all-features/screenshot#take_screenshot

Next would be to find out how to further process it in the game (there is JavaScript support for images, but in the end something would have to be rendered on the screen again)

I tried taking screenshots of my game, and after experimenting a while I found the file in the expected location. (Side note: If some action fails at runtime, how does GDevelop behave?)

Then I tried to zoom out the camera before taking the screenshot and yes, that also works. So this could be a cheap method to create a level map.
However when I completed the sequence to also zoom in again afterwards the screenshot would always contain the unzoomed screenshot. Not what I expected.

Screenshot

Not even adding the sound play did help.

  • Is it possible that the screenshot, much like the sound work asynchronously?
  • How could I synchronize actions?
  • Is there a way to react on ‘Sound finished playing’ or ‘Screenshot finished saving’ events?

Instead if using the screenshot action consider using the Js snippet in the example “in game screenshots”

I’d like to. What example are you referring to?
http://wiki.compilgames.net/doku.php/gdevelop5/events/js-code#code_examples
does not have anything about screenshots. The best I could find so far is

(I’ll give it a try today)

When we talk about examples we usually talk about the examples projects proposed to you when you create a new project :wink:
Here I indeed got mistaken. What I meant is a modified version of the load image from url example that uses the code snippet you quoted.

I am anything but a JavaScript expert, and looking at all these examples that I find everybody wants to save to local file. This is the case here, here and in various other places. However what I want to achieve is to have the image ready for display through a sprite. The most helpful resource is the Mozilla Canvas tutorial, which made me write this:

//-- this stuff will run as one-off
const radius = 20; // radius to unfog for the player

var mapCanvas = document.createElement('canvas');
var fogCanvas = document.createElement('canvas');

const renderer = runtimeScene.getRenderer();
const levelCanvas = renderer._pixiRenderer.view; // we have the rendered level now

//-- this stuff will run during update
// fog of war gets intense every step
var ctx = fogCanvas.getContext('2d');
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; // almost transparent black ink
ctx.fill();
// player can see vicinity, so punch a hole into fog
ctx.fillStyle = 'rgba(0, 0, 0, 0)'; // fully transparent black ink
ctx.arc(Player.X(), Player.Y(), radius, 0, 2*Math.PI)
ctx.fill()

// assemble the map for rendering
var ctx = mapCanvas.getContext('2d');
ctx.drawImage(levelCanvas, 0, 0);
ctx.drawImage(fogCanvas, 0, 0);
// mapCanvas contains our fogged level map. How to push this into the level sprite?

I’d expect to have the map ready to draw in mapCanvas. But how would I inject that into a Sprite? Or how else could this be rendered in GDevelop?

Thank you. I still have lack of such context. Indeed I found the example that switches Credits vs GDevelop logo. I also updated JavaScript Code events - GDevelop documentation

Now for the modification:
I understand the example loads something from a URL using the PIXI image manager - which I do not need. so I guess the important parts are from the callback method:

var object_texture_image = runtimeScene.getObjects("Map"); // Get all the objects called "Map"
var object_texture_image_renderer = object_texture_image[0].getRendererObject(); // get the map's renderer (PIXI sprite)
object_texture_image_renderer.texture = mapCanvas.texture; // change the texture in renderer (PIXI sprite) to the map

Somehow I am not yet convinced about type safety - especially when using a canvas like an image…