zacharycarter / zengine

2D | 3D Game development library
157 stars 13 forks source link

Sprites #13

Open define-private-public opened 6 years ago

define-private-public commented 6 years ago

This is now a TODO list for me. The original comment is quoted at the bottom.

TODO:

Questions I've got:


I'm interested in working on a Sprite object, so that this engine can have more 2D stuff than only the DrawTexture command.

I'm thinking about porting the Sprite object I made for my Masala engine a while back. There are a few tweaks and extra I'd like to add. How does this sound to you?

What are your opinions on the file format I designed? Example one, Example two.

I'd also like to get a Spline implementation working, but I'd rather get something simple working first. I saw that you had one in Frag. Did it go well?

zacharycarter commented 6 years ago

I think Raylib has quite a bit of sprite support we could probably port with minimal effort. I designed a texture packer for frag and a texture format which we could easily port over to this engine.

In regards to the spine implementation, yes it did go very well and I think we can also port it over here with some effort. I'll triage these shortly and get them in order that I think they can be addressed. I think this one is probably top in priority and then examples.

define-private-public commented 6 years ago

AFAICT, Raylib supports spritefonts and rendering to textures; and that's it. When I meant sprite, I mean more complex lines like animation & sequences. That's what I made in Masala.

zacharycarter commented 6 years ago

Gotcha - I was under the impression raylib had more support than that. Sure we can borrow from your work on Masala then. Feel free to take this on and if you have any questions I can try to answer them.

As far as formats go, we should pick something easily parsable and preferably parsable by existing solutions so we don't have to invent our own.

For frag I used the https://nim-lang.org/docs/parsecfg.html module and my texture packer spit out textures in this format - https://github.com/fragworks/frag/blob/master/tools/texture_packer/tinydeflate/tilesheet.atlas

Even if we have to write our own parser, that's fine, but I think using popular formats might be a better option - your thoughts?

define-private-public commented 6 years ago

I designed that format so it could be edited with a text editor. It's not the most optimal or space saving, but I think it did work pretty well for me.

As long as it's documented we should be fine for the short-term, but in the long term we should make some tools were people can do things such as select frames, order them into sequences, define origin points, pack them into one sheet, and save the file.

define-private-public commented 6 years ago

I'm editing the original comment to use it as a TODO list.

define-private-public commented 6 years ago

@zacharycarter I've got two questions that need answers for you:

  1. How are we going to deal with timing & updates? E.g. Many games engines have a float deltaTime parameter in their update() and draw() methods that are supposed to be passed down to everything that needs to be updated over a certain amount of time. I my case, this is sprite animation. How do you handle this right now with the 3D models? And what would be the best way for me to handle this with the Animated sprites?

  2. I'm making two objects right now Sprite and ZSprite. Sprite is the base class. In the future, SplineSprite will sub-object it. Does the design look good to you so far? https://github.com/define-private-public/zengine/blob/13.sprites_implementation/src/zengine/sprite.nim#L30

zacharycarter commented 6 years ago

1) I tried to make the zengine footprint as small as possible and this means that it's up to the player to implement the game loop. For animations I think for now I'm just passing sdl.getTicks() to the method that needs time adjustments, see here - https://github.com/zacharycarter/zengine/blob/5330a20ae76eadcc3e7feeac2cc9e203611418e1/src/zengine/models.nim#L554

Ideally the drawModel proc would take in as a parameter, and I think it should be the same for whatever other draw methods we have that need timing. We can build samples with example game loops.

2) Looks good to me so far 👍

define-private-public commented 6 years ago

Doing sdl.getTicks() for that is kind of living on the dangerous side:

It's not synced with the current logic frame or render frame. Say if we call sdl.getTicks() at the begging of a draw, then 4 milliseconds later we call it again sdl.getTicks(). Those time dependent drawings will be out of sync. 4 milliseconds doesn't seem like a lot but it can be.

Since it also has to go through a whole call stack, (and fetch the location in memory), it can lead to slowdown as well. It would be better to call getTicks() once at the top of an update/draw loop, store it in a variable, and then use that elsewhere. As much as I don't like global state objects, it might be a good idea to make one of those here. E.g. we create a ZApp object, and it has a member that stores this value for us.

Also IIRC, getTicks() only has millisecond resolution. While that's okay (especially for drawing), I think some people might prefer something like microsecond resolution for logic updates. I did make the stopwatch package: https://gitlab.com/define-private-public/stopwatch and it has higher resolution. It can also be stopped and started, which might be useful (for some people).

This is starting to get out of the scope of the Sprite object, shall I make a new ticket for this?

zacharycarter commented 6 years ago

I agree we shouldn't use sdl.getTicks() probably the high performance counter sdl2 offers or your stopwatch package. I think sdl2's high performance counter will work for mobile too so that's something to consider.

If anything I'd rather have a timer module which does what you're describing for us. I'll make a new issue for this and we can discuss further there.

define-private-public commented 6 years ago

Mind if I reserve 03 as the ZSprite example?

zacharycarter commented 6 years ago

Go for it.

Also feel free to put a PR in for stopwatch use, etc...

define-private-public commented 6 years ago

Little bit of an update now. I got done with the basic ZSprite file format loader done (and it's now shoved into the ZSprite object.

I think SpriteBatch is where the OpenGL and shader stuff should live. Any thoughts on that? How do you currently init the 3D stuff for model rendering what whatnot?

zacharycarter commented 6 years ago

Right now there's a default shader that gets loaded at startup. You can also load models with specific shaders, although it might make more sense to allow you to pass in a shader on a particular draw call. I'm going to be away this weekend, but when I get back let's review what you have so far (please make a PR) and we can figure out how best to integrate your changes.

To answer your question - models are loaded in model.nim and then there are two functions in zgl that have to do with them - loadModel and drawModel. All the required shader setup etc is either handled by the setup of the default shader with the zgl module initializes, or is taken care of in the example file.

define-private-public commented 6 years ago

Well, I do need to clarify that no rendering is happening at this moment. It's only loading and parsing. If you're still fine with merging that in for the moment I'll make the PR, but I'd really like to get something drawing on the screen first. I don't like saying "we have sprite, but we can't draw them at the moment."

define-private-public commented 6 years ago

I added a new question: What should we consider the origin of the sprite to be? I'm not talking about the origin within the .zsprite file format, that's already done. I'm talking about when it comes to rendering.

I know that traditionally in 2D games we used a Cartesian graph that was flipped along the X axis, with (0, 0) being the top left of the screen, and (0, 0) being origin of the sprite (which was also in the top left). But we're working in 3D, and that's where our sprites live.

I'd like to propose that we should use a normal Cartesian graph, with (0, 0) being in the center of the screen. As for the sprite, the origin of the sprite should be the absolute center. This might get slightly tricky when we have to deal with an animated sprite who's frames are non all of the same dimension, but I think this is the best solution.

What are your thoughts?

EDIT: additional discussion here: https://github.com/zacharycarter/zengine/issues/33

define-private-public commented 6 years ago

Actually, I think I'll send you a PR soon for what I have (minus some testing code).

define-private-public commented 6 years ago

PR for what I've got so far is right here: https://github.com/zacharycarter/zengine/pull/32

define-private-public commented 6 years ago

I also could use a proc in zgl to render a texture in a 3D space. So far, I only see how to draw a texture in 2D.

define-private-public commented 6 years ago

Also, sprite transparency seems to not be working. If you check the sheet for BlauGest it should be transparent in the background. I think this is fixed by a call to glBlendFunc(). Which one should we be using? Or did we forgot the alpha channel in the shader? IIRC, some depth buffer stuff might also play a role in this, but I'm a little fuzzy on this. Sample pic included of what's happening now; some of the text is getting obstructed by the whole sprite frame:

bad-blending

define-private-public commented 6 years ago

Are you fine with me using this sprite as one for a more complex example?

https://opengameart.org/content/platformer-animations

I'd like to doodle my own animation (like I did with the Blau Geist), but I'd rather get some more core stuff done first.

zacharycarter commented 6 years ago

I'm cool with that

define-private-public commented 6 years ago

Good. Later on I might replace it with an original animation.

Something I do want to note, after I get done with this issue and #34, I'm going to duck out a little bit from zengine to finish up another project I've been juggling around for the past 3-4 months. I'll come back to focus more on zengine, but I've learned that I need to do one thing at a time. If I'm lucky I should only be gone for a month or less.

I'll still probably log issues and ideas. If any issues arise from the sprite module I'll come and fix them.