RobLoach / node-raylib

Node.js bindings for Raylib
https://robloach.github.io/node-raylib/
Other
256 stars 20 forks source link

WIP: retro rpg template #142

Closed konsumer closed 2 years ago

konsumer commented 2 years ago

This is the start of a retro RPG (like SNES/GBA Final Fantasy, Pokemon, or Zelda.)

The idea is that you mostly edit in tiled to lay things out, edit your interactions (dialog and logic) in markdown and add some sprites, for a content/asset driven game-engine.

It doesn't really do anything yet, but I made a support lib for dialogs/gameplay and tiled map-loading, and included them. Once I finish a basic demo, I will remove WIP/draft-status.

RobLoach commented 2 years ago

This is really cool! Mind if we have it in its own repository with a link to it in the README? That would allow different versioning strategies against each project :wink:

I really like the Tiled integration you're working on too :+1:

konsumer commented 2 years ago

This is really cool! Mind if we have it in its own repository with a link to it in the README? That would allow different versioning strategies against each project 😉

Yep, sounds good. Where should we put it?

I really like the Tiled integration you're working on too 👍

Thanks! It's basically the data-part that I did with kaboom, with some minor improvements. I think I will probly update the kaboom thing to use it, just to centralize "properly load a tiled map in javascript". Might make other ones, too, like phaser, at some point.

konsumer commented 2 years ago

I put it up here will close this.

RobLoach commented 2 years ago

Ooo animations too... Added a projects section. Do you think it could be named better? https://github.com/RobLoach/node-raylib/pull/143

konsumer commented 2 years ago

Do you think it could be named better?

Not sure. I was trying to keep it generic, so it's clear it's not really a game, but could be used to make one pretty easily. Can you think of a better name? I'm down.

I was thinking I might port lol to it, too (originally written in godot.) I never really completed that, but it serves as a testing-ground for ideas around "an rpg adventure type game." Like the basic need of NPCs, portals, dialog (that triggers variable actions) and map-loading seems pretty re-occurring. I will probly save that for null0, but similar ideas can be shared between the 2.

Screen Shot 2022-05-10 at 7 46 49 PM
konsumer commented 2 years ago

I didn't see raylib-tmx which looks awesome!

I will probably base the drawing routine off of this (ported to js), if it works how you think it should. Basically, I made something that gives you what tmx lib does (LoadTMX) in js, although I standardized on the JSON versions of files instead of XML (but I could do both, if people want that.)

@RobLoach does the tile-drawing work how you would like it to, like do you think it's efficient & the same way you would make it today? Should I make a separate npm module that is a port of that using my tiled lib (maybe called raylib-tmx?)

RobLoach commented 2 years ago

The big problem with raylib-tmx is that it depends on tmx and libxml2 (and possibly zlib), which can be a pain to embed. Was wanting to get it working with cute_header's cute_tiled.h in raylib-tiled, but it was proving difficult. Cute_tiled has zero dependencies :wink:

What you've taken on with tiled-load is likely the easiest approach if you're using Node.js. Along with re-implementing the drawing methods. Other packages I've seen....

konsumer commented 2 years ago

The big problem with raylib-tmx is that it depends on tmx and libxml2 (and possibly zlib) What you've taken on with tiled-load is likely the easiest approach if you're using Node.js.

Yep. I used pako to handle layer compression (in js) and no need for XML (although I could add it, as it's pretty simple to translate it into the same JSON format)

Other packages I've seen....

Yeh, I looked at all those, and they mostly seem to rely on XML (even though the JSON format has become standard as native source formats for tiled, and is easier to parse) and often don't resolve external tilesets, relative paths, handle compressions/base64, etc. I looked at all of them when I made the kaboom lib, and ended up just making my own, and now I pulled the parsing routines out and made them more generic (which I will probly add back to the kaboom loader.)

I guess I meant more like "Do you feel good about how you draw tiles there?" Like maybe there is some other fancy (node-)raylib method I don't know about to draw a preloaded list of tiles. I will just start with a renderer based on that, and can tune it later.

RobLoach commented 2 years ago

"Do you feel good about how you draw tiles there?"

Kind of? It seems to work. There's a lot that Tiled does, and that drawing is pretty rudimentary :laughing:

konsumer commented 2 years ago

Sounds good. Realized maybe it sounded like I didn't think it was good, and it wasn't that at all. I think I would do it exactly the same, so if there isn't any better way, I'll stick with it.

twuky commented 2 years ago

If you convert the tilemap to a buffer of texture coordinates it should be possible to render the whole tilemap on the gpu in a single draw call with the right shader. implementing things like animations would need some logic to update sections of that buffer. I think all of that should be possible with the raylib Image functions, then calling TextureFromImage() to pass the buffer to the shader. I'd be happy to contribute that down the line, or add a node-raylib-tmx to the awesome.md section, though i think for something like that it would be kind of awkward to seperate the TMX parsing from the rendering parts into two packages

konsumer commented 2 years ago

If you convert the tilemap to a buffer of texture coordinates it should be possible to render the whole tilemap on the gpu in a single draw call with the right shader.

I have done this in the past (like using this technique) and although it works pretty well up to a point, I couldn't get it actually usable for a game. Do you know of any complete examples of this working? Since raylib batches draw calls, does it actually improve performance that much? If we did go this route, for tiled specifically, I wonder if this might be a better usecase for a tiled output plugin (I worked on the tiled javascript plugin engine, it's pretty good, and could generate an image, I think.) If we can't generate the images in a tiled plugin directly, I think it could also be an external CLI tool to "compile" tiled maps into the right format. It would mean people could use it in any engine that supports GLSL, if we worked on a shader to make it work. It might have awesome repercussions for 2D game-dev in general (like you could use same shader/assets in C raylib, or a webgl thing, for example.) I remember talking to Bjorn (the person who made Tiled) about it, and he said that it's a cool technique, but covers so little of the Tiled feature-set that you would need to parse it a few times on the fly to get it working, and the passes between runtime-computed stuff on CPU, and GPU costs would outweigh the benefits. I discovered similar, and couldn't even get it work right for a single layer, so I kinda got demotivated to work in that direction, but it's a cool trick I would be happy to explore more, if you have new ideas.

I'd be happy to contribute that down the line, or add a node-raylib-tmx to the awesome.md section,

I'm working on the rpg thing now, but I'd be totally down to collab, in the future.

though i think for something like that it would be kind of awkward to seperate the TMX parsing from the rendering parts into two packages

If I understand you, you are saying that they should all be in 1 raylib tiling lib? I disagree. Basically, I notice there are a lot of cross-engine shared things for parsing tiled maps (I prefer the tiled-native JSON format to TMX, as a sidenote.) All the existing generic npm tiled-parsing libraries I evaluated didn't have the features I needed (compression, binary, linked tilemaps, packaging issues, etc), so I ended up making my own parsing on the kaboom lib, and tiled-load includes that and more, and seems to cover the most features. I basically pulled ideas I had from other places and put it all together in a generic "read tiled maps correctly" lib, that I think is helpful for building other js-based parsers (that turn the parsed object into whatever the graphics engine does.) Surprisingly, it should work fine in browsers directly from CDN, in native node/deno things (like node-raylib) and other places.

konsumer commented 2 years ago

I modernized that GLSL tilemap demo and started work on using it in some other GL context here. I did something to mess up scaling, but everything else works well with ESM and more modern syntax, and the same source should work in any other bundler (or no bundler) now, It was using requirejs. I think maybe next step is trying to isolate the code in webgl-tilemap.js to work in other GL contexts (node-raylib) but I will probly just leave it as-is for now, as I have a lot of work to do on the rpg demo. I think it would be good to have a "normal sprite" version to compare with, too.

twuky commented 2 years ago

i think when I wrote that it hadn't occurred to me that the tilemap rendererer could just depend on the tilemap loader. i was focusing on avoiding a user needing to have to mix code from multiple projects themselves and convert the output from one into something the other works with.

for the GLSL part, honestly it just sounds like a cool project to try with raylib! I don't have to include it with anything. I think for the case of node-raylib - it will batch render the tiles, but making fewer calls to the native addon would still help, particularly for big maps. Like so far all the "benchmarking" we've been focusing on is the bunnymark - which applies the most to either tilemaps or particles for most games. there are definitely ways to make it fast without glsl, like you could cull tiles outside of the camera, or render to a rendertexture once and use the cached result. but things like that may be dependent on how the game is implemented and hard to work into a general use library

konsumer commented 2 years ago

i think when I wrote that it hadn't occurred to me that the tilemap rendererer could just depend on the tilemap loader. i was focusing on avoiding a user needing to have to mix code from multiple projects themselves and convert the output from one into something the other works with.

Ah, yeh, I am just importing them. Very easy.

for the GLSL part, honestly it just sounds like a cool project to try with raylib!

Agreed! I couldn't get it to work in a game I was making on regular webgl (trying to keep all the rendering in shaders, so it would be easier to port to other things) but I think it's a super-cool idea.

tiles outside of the camera, or render to a rendertexture once and use the cached result. but things like that may be dependent on how the game is implemented and hard to work into a general use library

Yeh, I think it could done in a generic way by rendering the portions of the layers you choose. This way, a basic unoptimized version would just render it all and move it around, but an optimized version could choose a sub-rect of the full map (based on the screen) and it would only add a little code. I think this technique could be applied to the shader too: pass it a uniform for x, y, w, h and return bg-color for stuff outside that.

Another idea I had was making tile-tiles on the fly as images, from the source map file. Like you could setup a chunk-size of 1 screen, and generate/cache each one as needed, and send it to the GLSL. if you rendered 1 plane per screen and sent the visible planes to GPU for render, you could make it pretty seamless, and caching would mean it never had to make very many screens at any given time. I dunno, I will think about it more, after I get a basic demo working.

I think for the case of node-raylib - it will batch render the tiles, but making fewer calls to the native addon would still help, particularly for big maps.

Yeh, for sure. I think I'm going to initially just get it working, and not focus on optimization to the detriment of finishing it. We can tune the render method later, and maybe end up using GLSL or just better 2D.

konsumer commented 2 years ago

Looks like libtmx has a nice raylib example, now, too.

RobLoach commented 2 years ago

Yup!!! That's the source for most of the raylib-tmx code :stuck_out_tongue: ... Hoped to make using it a bit easier to grok.