Scenes, Layers and Camera - Madour/pyNasNas GitHub Wiki

How it works

Scene, Layers and Camera system is used to display things on the window.

It is relatively simple, a Scene can have multiple Layers, a Layer can contain multiple Drawables (or Entities).

In reverse : Drawables (or Entities) are drawn on a Layer and Layers are drawn on the Scene.

To be able to see the scene, you have to tell the Camera to look at that Scene.

Here is an image that explains how it is organized: img/scene_layers_camera.png

If you still don't understand, imagine you are looking through your window (Camera), you'll see only a part of the landscape (Scene). In that landscape, you can see things that are closer (top red Layer) or farther (back yellow and blue Layer) to you.

Scene

First of all, you need to create a Scene. By default, a Scene of size w_width x w_height is created. You'll probably need to create a bigger Scene if you want to make a scrolling level for example.

Scene should be created in the __init__ of Game :

import NasNas as ns

class Game(ns.App):
    def __init__(self):
        super().__init__(title="My SFML Project", w_width=800, w_height=450, fps=60)
        # let's create a scene 2 times wider than the window
        self.myscene = self.create_scene(1600, 450)

That's it, you created a Scene. If you run the game, you will not see anything because we didn't add a Layer yet.

Notes :

  1. Scene background color is Transparent
  2. You can create multiple scenes (for example : one scene for each level)

Layers

A Layer has a name and contains a list of Drawables that will be drawn on the Layer.

Once created, you have to add the layer to the scene and specify the order of the layer you are adding. The order determines which Layer will be drawn first.

For example, in the image, the blue layer's order is 0, the yellow is 1 and the red is 2.

import NasNas as ns
from sfml import sf

class Game(ns.App):
    def __init__(self):
        super().__init__(title="My SFML Project", w_width=800, w_height=450, fps=60)
        # let's create a scene 2 times wider than the window
        self.myscene = self.create_scene(1600, 450)
        
        # creating a Layer called background
        self.bg_layer = ns.Layer("background")
        # adding a Drawable to the layer
        circle = sf.CircleShape(50)
        circle.fill_color = sf.Color.GREEN
        self.bg_layer.add(circle)
        # adding the layer to the scene
        self.myscene.add_layer(self.bg_layer, order=0)

If you run the game, you will not see anything, because we didn't tell the camera to look at the scene we created yet !

Notes :

  1. You can add multiple drawables at the same time : self.bg_layer.add(drawable1, drawable2, ...)
  2. You can even add drawables directly in the constructor : self.layer = ns.Layer("name", drawable1, drawable2, ...). This allow to create and add a layer to the scene in one line : self.scene.add_layer(ns.Layer("name", drawable1, ...), 0)
  3. Layers are very useful when well organized, keep in mind the order of your layers

Camera

Camera class takes 4 parameters :

  1. name (str): The name of the new Camera, should be unique.
  2. order (int): The order of display. 0 will be displayed first, 1 will be displayed over 0, etc
  3. camwindow (ns.Rect): The position and size (width, height) of the camera.
  4. viewport (ns.Rect): The position and size (v_width, v_height) the camera will take on the game window.

Just like layers, Camera has a name, and an order. The name is used when you want to get a specific Camera, the order determines the order of drawing (same as Layers)

Camwindow is the rectangle your Camera is looking through. It will determine what it will see (the camera rectangle in the image)

Viewport position and size is in percentage of the game window :

  • A viewport of ((0, 0), (1, 1)) will take the whole window
  • A viewport of ((0.5, 0), (0.5, 0.5)) will take the top right corner of the window.

By default one camera is already created: self.game_camera = Camera( "game", 0, Rect((0, 0), (v_width, v_height)), Rect((0, 0), (1, 1)) )

Where v_width and v_height are the parameters you can pass to ns.App.__init__()

To tell the camera to look at a specific scene : self.game_camera.scene = self.myscene

Let's go back at our example and add a Camera :

import NasNas as ns
from sfml import sf

class Game(ns.App):
    def __init__(self):
        super().__init__(title="My SFML Project", w_width=800, w_height=450, fps=60)
        # let's create a scene 2 times wider than the window
        self.myscene = self.create_scene(1600, 450)
        
        # creating a Layer called background
        self.bg_layer = ns.Layer("background")
        # adding a Drawable to the layer
        circle = sf.CircleShape(50)
        circle.fill_color = sf.Color.GREEN
        self.bg_layer.add(circle)
        # adding the layer to the scene
        self.myscene.add_layer(self.bg_layer, order=0)

        # creating our own Camera (you can also use self.game_camera)
        self.mycamera = self.create_camera(
                                "mycamera", 0,
                                ns.Rect((0, 0), (400, 225)),
                                ns.Rect((0, 0), (1, 1))
                        )
        self.mycamera.scene = self.myscene

Run the game, now you should see a green circle on the screen. Try changing mycamera size and see how it affects the view.

Now, let's move the camera around, add this method to your Game class:

    def update(self):
        if ns.Keyboard.is_key_pressed(ns.Keyboard.RIGHT):
            self.mycamera.move(1, 0)
        if ns.Keyboard.is_key_pressed(ns.Keyboard.LEFT):
            self.mycamera.move(-1, 0)
        if ns.Keyboard.is_key_pressed(ns.Keyboard.UP):
            self.mycamera.move(0, -1)
        if ns.Keyboard.is_key_pressed(ns.Keyboard.DOWN):
            self.mycamera.move(0, 1)

You can also use other Camera methods provided by pySFML, like zoom() and rotate().

To control Camera's position, you can use the properties center, left, right, top and bottom.

Take your time and test with multiple layers, multiple drawables, multiple cameras to understand exactly how it work before going to next pans. Also, don't hesitate to take a look at the code of the framework if you want, you'll learn a lot about the system.


<- [Resource Loader and Manager]] ](/Madour/pyNasNas/wiki/[[Entities,-Sprites-and-Animations) ->