Skip to content

Commit

Permalink
Begin support for parallax scrolling backgrounds in web client
Browse files Browse the repository at this point in the history
  • Loading branch information
AntumDeluge committed Apr 8, 2024
1 parent 31a900e commit cfe7596
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 1 deletion.
4 changes: 4 additions & 0 deletions buildtools/ant_modules/dist.xml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@
<exclude name="logic/layer/"/>
</fileset>
</copy>
<mkdir dir="${maps}/parallax"/> <!-- in case no parallax images available -->
<copy todir="${build_client_data}/data/maps/parallax">
<fileset dir="${maps}/parallax" includes="**/*.png"/>
</copy>
<copy todir="${build_client_data}/data/font">
<fileset dir="data/font"/>
</copy>
Expand Down
4 changes: 3 additions & 1 deletion src/js/stendhal/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,9 @@ export class Client {
const musicVolume = parseFloat(zoneinfo["music_volume"]);
stendhal.ui.soundMan.playSingleGlobalizedMusic(zoneinfo["music"],
!Number.isNaN(musicVolume) ? musicVolume : 1.0);

// parallax background
stendhal.data.map.parallax.setImage(zoneinfo["parallax"]);
// zone coloring
if (zoneinfo["color"]) {
const hsl = Color.hexToHSL(Color.numToHex(Number(zoneinfo["color"])));
// workaround until able to get right saturation level from color methods
Expand Down
4 changes: 4 additions & 0 deletions src/js/stendhal/data/Map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Paths } from "./Paths";

import { LandscapeRenderingStrategy, CombinedTilesetRenderingStrategy } from "../landscape/LandscapeRenderingStrategy";
import { IndividualTilesetRenderingStrategy } from "../landscape/IndividualTilesetRenderingStrategy";
import { ParallaxBackground } from "../landscape/ParallaxBackground";


export class Map {
Expand Down Expand Up @@ -63,6 +64,8 @@ export class Map {
Paths.tileset + "/item/blood/small_stains"
];

private parallax: ParallaxBackground;

/** Singleton instance. */
private static instance: Map;

Expand All @@ -86,6 +89,7 @@ export class Map {
} else {
this.strategy = new CombinedTilesetRenderingStrategy();
}
this.parallax = ParallaxBackground.get();
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/js/stendhal/data/Paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class Paths {
public static readonly weather = Paths.sprites + "/weather";
public static readonly achievements = Paths.sprites + "/achievements";
public static readonly tileset = Paths.data + "/maps/tileset";
public static readonly parallax = Paths.data + "/maps/parallax";
public static readonly ws = Paths.extractPath("data-ws");

/**
Expand Down
77 changes: 77 additions & 0 deletions src/js/stendhal/landscape/ParallaxBackground.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/***************************************************************************
* Copyright © 2024 - Faiumoni e. V. *
***************************************************************************
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation; either version 3 of the *
* License, or (at your option) any later version. *
* *
***************************************************************************/

import { singletons } from "../SingletonRepo";


export class ParallaxBackground {

/** Tiled image to be drawn. */
private image?: HTMLImageElement;

/** Singleton instance. */
private static instance: ParallaxBackground;


/**
* Retrieves singleton instance.
*/
static get(): ParallaxBackground {
if (!ParallaxBackground.instance) {
ParallaxBackground.instance = new ParallaxBackground();
}
return ParallaxBackground.instance;
}

/**
* Hidden singleton constructor.
*/
private constructor() {
// do nothing
}

/**
* Sets image to be drawn.
*
* @param name {string}
* Relative path (exluding .png filename suffix) to image inside "data/maps/parallax" directory
* or `undefined` to unset.
*/
public setImage(name?: string) {
if (!name) {
this.image = undefined;
return;
}
const fullPath = singletons.getPaths().parallax + "/" + name + ".png";
this.image = singletons.getSpriteStore().get(fullPath);
}

draw(ctx: CanvasRenderingContext2D, offsetX: number, offsetY: number) {
if (!this.image || !this.image.height) {
return;
}
// FIXME: jumps when shifting tiles
const tilesX = Math.max(Math.ceil(ctx.canvas.width / this.image.width) + 1, 1);
const tilesY = Math.max(Math.ceil(ctx.canvas.height / this.image.height) + 1, 1);
const clipLeft = (offsetX / 2) % ctx.canvas.width;
const clipTop = (offsetY / 2) % ctx.canvas.height;
for (let ix = 0; ix < tilesX; ix++) {
for (let iy = 0; iy < tilesY; iy++) {
ctx.drawImage(this.image,
0, 0, this.image.width, this.image.height,
(ix*this.image.width)+offsetX-clipLeft,
(iy*this.image.height)+offsetY-clipTop,
this.image.width, this.image.height);
}
}
}
}
1 change: 1 addition & 0 deletions src/js/stendhal/ui/ViewPort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ export class ViewPort {

// FIXME: filter should not be applied to "blend" layers
this.applyFilter();
stendhal.data.map.parallax.draw(this.ctx, this.offsetX, this.offsetY);
stendhal.data.map.strategy.render(this.ctx.canvas, this, tileOffsetX, tileOffsetY, this.targetTileWidth, this.targetTileHeight);

this.weatherRenderer.draw(this.ctx);
Expand Down

0 comments on commit cfe7596

Please sign in to comment.