Jump to content

World wrapped camera?


GAZ082
 Share

Recommended Posts

Hi there. I want to achieve that my main camera to render the world map "wrapped".

See this example, the little top right would be the main camera and i move it to the right. As you can see, the desired effect if that it will render the opposite offset the further right the cam moves.

Ideas? Thanks!

                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
                               
Link to comment
Share on other sites

I've done this before but with vanilla JS, meaning without the Phaser framework. However, if there isn't any built-in camera feature to do this, the logic should be the same.

So here is how I did it, and how I would integrate it with Phaser 3 now:

Remove Bounds:

First of all, in Phaser you cannot give the camera any bounds because you actually want the camera to go (partly) out of bounds:
this.cameras.main.removeBounds()

Scrolling Left/ Right:

Right: In the Scene's update method, when this.cameras.main.scrollX >= map.width, you snap the camera to 0:
this.cameras.main.setScroll(0, this.cameras.main.scrollY)

Left: In the Scene's update method, when this.cameras.main.scrollX <= 0 - this.cameras.main.width, you snap the camera to map.width - camera.width:
this.cameras.main.setScroll(map.width - this.cameras.main.width, this.cameras.main.scrollY)

At this point, wrapping is working but you see a black box for the distance the camera is overlapping the map. You fix this by simply drawing into this black space! In other words, if your camera is scrolling right and reaches this area where it is overlapping but not snapping back to 0, yet, you draw the objects that have their x-coordinate between 0 and this.cameras.main.width. A crate at x = 64 would now be drawn at x = map.width + 64.

Background:

For the background, you can decide for yourself if you want to draw it only when needed (as with the objects) or...

...if you want to draw it once at the beginning of loading the level / map. That means the background you draw is BIGGER than the whole map. Where the right edge of the map ends, you draw the beginning of the map's left edge. Good thing is you only need to draw as much as the camera's width is! It will not go further than that. And opposite logic at the left edge of the map: You draw the beginning of the map's right edge.

Scrolling Remaining Directions:

Same logic applies to scrolling top / down. For diagonal scrolling you combine the methods.

Sketches:

Sorry I don't have any sketches or fiddles available to show you. Also the game where I used it was an old MMO (nowadays called IO-Games) and I don't have access to that Node server anymore.

However, I believe that if you follow along my description and make some sketches of the descriptions it should easily be visualized.

I hope it helps!

Link to comment
Share on other sites

@GAZ082 Are you using Tiled Editor? If so, you can draw at the edges the beginning of the opposite edge - as I've described above. Scrolling will work seamlessly then if you snap the camera to the opposite side.

In other words, first you draw your real map. Then at the edges you draw what would appear if you keep scrolling the camera and the world wraps. All of this you can do in Tiled Editor. Then you load the tilemap into your Phaser game and in your scene's update method, you just add the if clauses to check when you have to snap your camera to the other edge. Don't forget to adjust your player's position together with the camera when it snaps to another edge of the map.

This will also work with collision objects that you add in your Tiled Editor.

Link to comment
Share on other sites

@GAZ082 Sorry I can't quite grasp the question. What do you mean by adding multiple instances of an image? If you are using a tilemap, you are adding the same images (tiles) multiple times anyways. For your purpose, the whole tilemap becomes slightly bigger, that's all.

Regarding performance I don't really have any tests to back it up. Naturally, rendering more images requires more CPU. However, for this solution you are only increasing the tilemap's size. Therefore, this increase wouldn't cause any major change in performance. If your device can handle the current tilemap there's no reason why it shouldn't be able to handle a bigger one with the added edges. And the bigger your map was to start with, the lesser the performance difference will be percentage-wise (due to the fact that the additional edges are equal to the width & height of your camera, and the bigger the whole map to start with, the smaller these edges will be percentage-wise: ratio = camera.width / map.width).

So if map.width = 2000px and camera.width = 288px, you are increasing the whole map by 28.8%:
288 / 2000 = 0.144
percentage = 14.4 %
both sides = 28.8% total

And if map.width = 5000px and camera.width = 288px, you are increasing the whole map by 11.52%:
288 / 5000 =0.0576
percentage = 5.76%
both sides = 11.52% total

So I think in the end the question is how big of a tilemap can you load into the game without taking a performance hit.

Link to comment
Share on other sites

@GAZ082 I guess in that case you can crop the whole map using sprite.setCrop() (click for link to doc)

So you draw your map, then crop the edges with camera.width and draw them where the opposite side ends. So now I understand what you meant with drawing multiple images, in the end you draw the parts of the map again at least 4 additional times. If you allow diagonal movement you must draw the corner-cases as well (not shown in the image below) resulting in 8 additional drawings total.

world-wrapping.png.fb5a37c9245e7c746ea8421df0953c92.png

However, even if you are generating the tilemap on the server, can't you still adjust the generation code so it adds the overlapping edges as you would manually in the Tiled Editor?

Also from my experience with the Tap Racer game, performance is much better if I draw the map with tiles and don't draw the whole map image (depending on your device it's very laggy).

Link to comment
Share on other sites

1 hour ago, GAZ082 said:

I'm trying to find a way to render individual tiles as needed, the author of the Tile engine in Phaser3 wrote a series of tutorials here:

https://medium.com/@michaelwesthadley/modular-game-worlds-in-phaser-3-tilemaps-1-958fc7e6bbd6

I know this tutorial series, it's very good! I'm sure you'll find a good solution.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...