Kaamera: tegelasega kaasa liikumine; zoomimine

Kui tegelane liigub, siis kaamera liigub temaga kaasa

Kaamera mänguarenduses on oluline element, mis võimaldab mängijal keskenduda mängumaailma konkreetsele osale. Tavaliselt liigub kaamera mängija tegelase liikumisega kaasa, hoides tegelast ekraani keskosas. Lisaks saab kaamerat kasutada mängumaailma suurendamiseks või vähendamiseks (zoomimiseks), et pakkuda mängijale paremat ülevaadet.

Kaamera initsialiseerimine

Esmalt määrame mängumaailma mõõtmed:

private static final float WORLD_WIDTH = 100;
private static final float WORLD_HEIGHT = 100;

Kaamera loomiseks kasutatakse OrthographicCamera-t koos viewport'iga, näiteks ExtendViewport. (detailsemat juttu peatükis Viewportid). Määrame mängu vaatealaks nt pool maailmast.

gameCam = new OrthographicCamera();
gamePort = new ExtendViewport(WORLD_WIDTH / 2, WORLD_HEIGHT / 2, gameCam);

Kaamera liikumise ja zoomimise teostamine

Alljärgnev koodinäide selgitab, kuidas kaamera liikumist ja zoomimist teostada. Samuti tagab kood, et kaamera ei liiguks mängumaailmast väljapoole.

public void updateGameCam() {
    // Kaamera positsioneerimine mängija asukoha järgi
    gameCam.position.set(player.getX(), player.getY(), 0);

    // Arvutame kaamera vaate poole laiuse ja kõrguse
    float halfWidth = gameCam.viewportWidth / 2;
    float halfHeight = gameCam.viewportHeight / 2;

    // Kaamera X-telje piiramine
    gameCam.position.x = MathUtils.clamp(gameCam.position.x, halfWidth, WORLD_WIDTH - halfWidth);
    // Kaamera Y-telje piiramine
    gameCam.position.y = MathUtils.clamp(gameCam.position.y, halfHeight, WORLD_HEIGHT - halfHeight);

    // Kaamera uuendamine
    gameCam.update();
}

Koodis esmalt paigutatakse mängija koordinaatide keskmesse, nii et tegelane püsib alati ekraani keskosas. Kuna kaamera positsioon määrab vaateala keskpunkti, siis arvutatakse kaamera vaate poole laiuse ja kõrguse väärtused (halfWidth ja halfHeight). Nende väärtuste abil saab arvutada piirid, millest üle kaamera minna ei tohi.

Kaamera liikumist X- ja Y-teljel piiratakse MathUtils.clamp() meetodiga, millel on kolm parameetrit:
  1. Praegune väärtus - kaamera praegune positsioon (gameCam.position.x või gameCam.position.y)

  2. Miinimumväärtus - väikseim lubatud positsioon (halfWidth või halfHeight), mis takistab

    vasaku/alumise serva taha nägemist.

  3. Maksimumväärtus - suurim lubatud positsioon (WORLD_WIDTH - halfWidth või WORLD_HEIGHT - halfHeight),

    mis takistab parema/ülemise serva taha nägemist.

Meetod tagastab väärtuse, mis jääb alati miinimum- ja maksimumväärtuse vahele. Sellega ei välju kaamera mängumaailma piiridest. Näiteks kui mängija on mängumaailma servas, hoiab see loogika kaamera mängumaailma sees. Pärast muudatuste tegemist kutsutakse välja gameCam.update(), mis rakendab kõik tehtud muudatused. Seda meetodid saab kutsuda meetodis render.

Zoomimine

Zoomimise põhimõte seisneb kaamera vaateala (viewport) suuruse muutmises. Kui vaateala suurust vähendatakse, tundub, et kaamera suumib sisse (objektid muutuvad suuremaks). Kui suurust suurendatakse, tundub, et kaamera suumib välja (objektid muutuvad väiksemaks). Alljärgnev koodinäide näitab, kuidas lisada zoomimise funktsioon koos parameetrite piirangutega:

public void handleCameraZoom(float zoomFactor) {
    // Uuenda zoom taset
    gameCam.zoom += zoomFactor;

    // Leia max zoom tase
    float maxZoomX = WORLD_WIDTH / gameCam.viewportWidth;
    float maxZoomY = WORLD_HEIGHT / gameCam.viewportHeight;
    float maxZoom = Math.min(maxZoomX, maxZoomY);

    // Kehtesta miinimum- ja maksimumväärtused zoom tasemele
    gameCam.zoom = MathUtils.clamp(gameCam.zoom, 0.5f, maxZoom);

    // Arvutame kaamera vaate poole laiuse ja kõrguse
    float effectiveHalfWidth = gameCam.viewportWidth * gameCam.zoom / 2;
    float effectiveHalfHeight = gameCam.viewportHeight * gameCam.zoom / 2;

    // Kaamera X-telje piiramine
    gameCam.position.x = MathUtils.clamp(gameCam.position.x, effectiveHalfWidth, WORLD_WIDTH - effectiveHalfWidth);
    // Kaamera Y-telje piiramine
    gameCam.position.y = MathUtils.clamp(gameCam.position.y, effectiveHalfHeight, WORLD_HEIGHT - effectiveHalfHeight);

    // Uuenda kaamera muudatused
    gameCam.update();
}

Zoomi uuendamine:

gameCam.zoom += zoomFactor

zoomFactor määrab, kui palju kaamera suumib. Positiivne väärtus eemaldab kaamera, negatiivne toob lähemale. Zoom'i väärtusele seatakse piirangud, et vältida liiga suurt või väikest zoom'i. Maksimaalne zoom arvutatakse eraldi X- ja Y-telje jaoks, et leida, millal mahub kogu mängumaailm ekraanile. Selleks, et tagada mõlema telje puhul terve mängumaailma nähtavus, kasutatakse väiksemat väärtust(Math.min). See takistab olukorda, kus üks telg on veel nähtav, aga teine juba mängumaailma piiridest väljas. Miinimumväärtus (0.5f) tähendab suuremat lähivaatlust, maksimumväärtus (maxZoom) tähendab kaugemat vaadet.

Kaamera positsiooni piiramine: Kuna zoom muudab kaamera vaateala suurust, tuleb uuesti arvutada kaamera poole laiuse ja kõrguse väärtused. Selleks korrutatakse kaamera vaateala suurus zoom'i tasemega.

float effectiveHalfWidth = gameCam.viewportWidth * gameCam.zoom / 2;
float effectiveHalfHeight = gameCam.viewportHeight * gameCam.zoom / 2;

Kaamera uuendamine: gameCam.update() rakendab kõik muudatused, sh uus zoomi tase ja positsiooni piirangud. Kasutamine mängus: Zoom'ida saab näiteks klaviatuuri või hiire abil.

if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
    handleCameraZoom(-0.02f); // Zoom lähemale
}
if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
    handleCameraZoom(0.02f); // Zoom kaugemale
}

Pärast seda koodi implementeerimist saab zoom'ida sisse ja välja nagu on näidatud piltidel:

zoom_1 zoom_2

Lisainfo

https://libgdx.com/wiki/graphics/2d/orthographic-camera