ClementSparrow / Pattern-Script

Open Source HTML5 Game Engine based on PuzzleScript
20 stars 2 forks source link

Allow for sprites that are bigger (or smaller) than the cell that contains them #8

Closed ClementSparrow closed 2 years ago

ClementSparrow commented 3 years ago

One benefit would be to allow for easier implementations of pseudo-3D effects (like a wall partially masking the cell behind it), thanks to PuzzleScript's rendering of levels' grids from top to bottom.

The idea comes from this fork by @m-ender, implemented in https://github.com/broken-sign-games/PuzzleScript/commit/8cd4338a459cfc0d2edd9c2a0af1ca6c3ade84a7, with some polish in error messages in https://github.com/broken-sign-games/PuzzleScript/commit/bbcc59f5bb03db97a828153a5a0a22dd560ded76.

ClementSparrow commented 3 years ago

Can we generalize the feature to bring even more new usages? One obvious way to generalize it would be to specify the alignment of the sprite. In m-ender's fork, the sprite has to be aligned with the bottom of the cell, but other options might be interesting.

For instance, aligning with the top of the cell could help implementing cast shadows, but only if the cast shadow is not overwritten by the content of the cell below. In that case, we might want to change the rendering method so that it draws the scene collision_layer by collision_layer, from background to the top layer (Also, alpha channel in colors would be useful).

The sprite also does not have to be aligned with a cell's border. For instance, if one wants to make a game with a pseudo-3D effect and two floor levels, the sprites for the objects at the bottom level could be aligned with the bottom edge of the cell, but the sprites for the objects at the upper floor would have their bottom edge higher than the cell's bottom edge. The same effect can be achieved with transparent pixels at the bottom of a sprite aligned with the cell's bottom edge, but then we cannot simply copy the lower-floor sprites into the upper-floor ones.

So, we can consider arbitrary origin points in the cell and sprite to cover all alignment possibilities.

A possible usage of the technique would be to make animated solid objects (e.g., a big boss monster): although the collision system would still require to have markers in all cells occupied by the object, the rendering of the object could be done with a single oversized sprite, which would considerably simplify the input of the sprite pixel grid, and would ease the implementation of animations (one big sprite by animation frame instead of one sprite by animation frame and cell covered, one animated object instead of multiple objects that have to be kept synchronized in the same animation frame).

We can also consider adding an integer scale factor to render the sprite (especially since I already have the code for that in createSprite). This could help with the definition of sprites that are naturally at a lower resolution (writing a 15x15 pixel grid for something that could be described with a 5x5 grid is not fun), and would allow decisions like "I need 15x15 sprites instead of 5x5" without requiring an immediate manual rewriting of all sprites at the new sprite_size. Finally, used in animations, it could allow for nice pixelated 'zoom in' and 'zoom out' effects.

ClementSparrow commented 3 years ago

Technical questions:

Other comment: sprite_size should probably be renamed cell_size or something like that.

m-ender commented 3 years ago

I think I had mentioned this to you on Discord, but for an arbitrary origin per sprite, I had considered a syntax like this (and omitting the origin marks would place the origin at the bottom left corner):

Thingy
purple
00000
00000
00000<
00000
 ^

Rendering the sprites layer by layer could have weird side effects I think, but it might work if you design your sprites around it.

Multi-floor tiles can technically be done without a custom origin by simply adding some transparent rows to the bottom of the sprite.

ClementSparrow commented 3 years ago

I think I had mentioned this to you on Discord, but for an arbitrary origin per sprite, I had considered a syntax like this [...]

Yeah, I was about to mention that. But I had some second thought about this syntax, realizing it would not work well with another feature, but I cannot remember what it was :-( So, until I remember what the issue was, I prefer not to implement the syntax.

Rendering the sprites layer by layer could have weird side effects I think, but it might work if you design your sprites around it.

Yeah, I guess it might not be intuitive for the game dev. Maybe we will need something like layer groups in the end (drawing layer group by layer group, but inside a layer group, drawing cell by cell).

Multi-floor tiles can technically be done without a custom origin by simply adding some transparent rows to the bottom of the sprite.

Yeah, I mentioned that already :-)

ClementSparrow commented 2 years ago

I'm starting to work on this, and have decided that I would not use a special syntax to specify the position of the origin of the sprite. Instead, I will use special sprite transformations to translate (and also, to scale) the sprite as we want, building upon the syntax suggested in #14. The benefit is that we get the possibility to use directional tags expansion for free if needed.