Skip to content
This repository has been archived by the owner on Sep 19, 2021. It is now read-only.

[Note] Graphic replacement and expected problems #1159

Open
ki-foobar opened this issue Jan 15, 2019 · 0 comments
Open

[Note] Graphic replacement and expected problems #1159

ki-foobar opened this issue Jan 15, 2019 · 0 comments

Comments

@ki-foobar
Copy link
Contributor

It is not a concrete issue, only mentions about the current status and the next short-term goals for me, KI.

TL; DR

The current codebase about graphics is too awful to implement new wonderful features. It's the time to refactor.

What I want for Elona's graphics

Elona is, I strongly believe, one of the most graphical and beautiful roguelike game. Vanilla's graphics, of course, are rich enough especially in roguelikes, and additionally, Elona and its community has "graphic replacement" culture, changing character's and item's chips, map tiles, PCCs, interfaces, scenario cutscenes, and more. A new graphic pack changes not only look and feels but also your game experience much. Many people have created their works for Elona, and there are a lot of choices. It is attributed to the original Elona's graphics and its support to graphic replacement.

I think, however, the support in vanilla was not complete. In fact, most variants have added or fixed graphic replacement in some degree. I will not introduce them here (because too many), but all of them play important roles in Elona's graphic replacement culture. This variant Elona foobar, which is derived from vanilla Elona v1.22, have not reached these great variants at all, especially in that graphic replacement features. Several days ago, I, KI, took a vote about "What feature do you request for this variant next?"

  • Graphic and sound replacement (20 votes)
  • CNPC (4)
  • CItem (1)
  • CGod (0)
  • CRace (0)
  • CClass (0)
  • Save data conversion from vanilla to foobar (8)
  • Save data conversion from foobar to vanilla (0)

The result obviously shows that graphic replacement feature is very significant for Elona players.

So, let me list (part of) what I want for foobar's graphic system, borrowing ideas from other variants.

  • Character chip
    • To assign different chips to characters whose image is shared in vanilla like dragons.
    • To use different images depending on one's sex.
  • Item chip
    • To assign different chips to items whose image is shared in vanilla like cooked dishes.
  • Interface
    • To change part of interface without the original big image, graphic/interface.bmp.
  • Portrait
    • To assign different portraits to characters whose image is shared in vanilla ilke Noel and Pael.
    • To make all portraits available, even if unique NPC's.
  • PCC
    • To use walking sprites against town NPCs and monsters.
  • Map chip
    • To enable yet another map chips.
  • Loading and drawing arbitrary images for arbitary

Note: of course they are not complete list, and I have ideas about (and other variants do have) many other features for Elona graphics.

These features, however, are difficult to implement, at least for foobar. It is because that these features require me to completely understand use of texture buffers (switched via gsel()) and investigate other variants' implementations through decompiled HSP sources. For me, it is impossible to port these features correctly from other variants and establish more on the current implementation.

Current implementation and its problems

The current implementation of Elona foobar (and vanilla Elona in HSP) highly depends on HSP's built-in functions. These too primitive, stateful, and non-object-oriented functions have been removed and replaced partly in foobar, but there are still a lot of legacy code. These simple functions, indeed, helped me to port Elona from HSP to C++ (all I need was only to write some small functions which wrap SDL backend), but it is the time to rethink and replace them.

The most severe issue is these functions are stateful. Recently, color() function has completely been eliminated from foobar's codebase. It reduced one "state", but we have a lot of other "states" which are globally held and modified frequently over functions. The strongest enemy is gsel(), and the second is gmode(). gsel() function is one which switches the rendering target. There are some reserved buffers:

  • 0: render target
  • 1: item work buffer (used to be for all items)
  • 2: interface in casino/tcg
  • 3: general interface
  • 4: interface backgrounds
  • 5: characters (deprecated, now managed by this class)
  • 6: map tiles
  • 7: event window backgrounds
  • 8: message panel
  • 9: continuous action (activity) image
  • 10-19: this class
  • 20+: PCC sprites (used to be 10+). Texture id is chara.index + 20
    (quote from src/elona/pic_loader/pic_loader.hpp, the name of pic_loader comes from picload(), one of HSP functions to load picture)

0th buffer's "render target" means "the screen" you are watching. (technically speaking, because foobar uses double-buffering, it is the backward screen, i.e., the screen about to be rendered next time.)

gsel() is called so frequently everywhere that it is almost impossible to wholly understand what buffer is used where.

In addition, these reserved buffers are not immutable. For example, the region (x=0, y=960, w=48, h=48or96) of buffer 1, which all items are rendered in, is used a temporary buffer. Pseudocode is here:

foreach cell in current map:
    foreach item in cell.items:
        copy item's image to (x=0, y=960, w=48, h=48or96)
        copy the region (x=0, y=960, w=48, h=48or96) to the screen, i.e., buffer 0

It is one of the reasons why I have not totally replace the current implementation yet, that is, it is difficult to understand how these code work due to the stateful function calls.

So, what should we do?

The first step is to refactor all of HSP functions. The functions ported from HSP are listed in src/snail/hsp.hpp. The folllowings are the worst ones:

  • pos(), changing global rendering position.
  • gmode(), changing global blending mode.
  • gsel(), changing global rendering target buffer.

If we could deleted or reduced them, the code would become simple, and it would be easier to implement the above features.

The result of git grep -c:

  • pos() 763 calls
  • gmode() 410 calls
  • gsel() 231 calls
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant