Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

Sprites #13

Open
7 of 14 tasks
define-private-public opened this issue Aug 12, 2017 · 22 comments
Open
7 of 14 tasks

Sprites #13

define-private-public opened this issue Aug 12, 2017 · 22 comments

Comments

@define-private-public
Copy link
Collaborator

define-private-public commented Aug 12, 2017

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

TODO:

  • Write up a spec file and get it approved
  • Port simple data structures and basic features over from Masala
  • Write the loader
  • Create a SpriteBatch object for rendering. Give it some extra fun things like blending options and whatnot
  • be able to display an animated sprite
  • ensure that origins and rotations are working.
  • Write an simple example of the "Blau Geist"
  • Port the more complicated features of the Sprite from Masala
  • Write a more complex example. A character that walks, attacks, jumps
  • An example with multiple sprites.
  • copy constructors
  • fix the origin of the Blau Geist example to use (0, 0). Ensure that it's in the correct spots for both 2D and 3D mode.

Questions I've got:

  • How to deal with sending timing updates?
  • Where should we place the sprite's origin? And what about the coordinate system in general?

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
Copy link
Owner

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
Copy link
Collaborator Author

define-private-public commented Aug 12, 2017

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
Copy link
Owner

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
Copy link
Collaborator Author

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
Copy link
Collaborator Author

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

@define-private-public
Copy link
Collaborator Author

@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
Copy link
Owner

  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 -
    boneTransform(model, float(getTicks()) * 0.001, transforms)

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.

  1. Looks good to me so far 👍

@define-private-public
Copy link
Collaborator Author

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
Copy link
Owner

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
Copy link
Collaborator Author

define-private-public commented Aug 23, 2017

Mind if I reserve 03 as the ZSprite example?

@zacharycarter
Copy link
Owner

zacharycarter commented Aug 23, 2017

Go for it.

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

@define-private-public
Copy link
Collaborator Author

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
Copy link
Owner

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
Copy link
Collaborator Author

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
Copy link
Collaborator Author

define-private-public commented Sep 2, 2017

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: #33

@define-private-public
Copy link
Collaborator Author

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

define-private-public added a commit to define-private-public/zengine that referenced this issue Sep 2, 2017
At this moment we are able to read and parse in a very minimal .zsprite
file.  So far we can do things like define frames, sequences, add
looping modifiers, etc.

Righut now there is a `Sprite` object, and a `ZSprite` object (which is a
child of `Sprite).  They are mainly ment to be dumb data containters
that only are for managing the state of a sprite object (e.g. timing,
which frame to show, etc).  In the futur we plane to have sprites that
are defined by the `Spline` format, so that's why I made the common
`Sprite` base object.  In case a game dev also wants to make their own
custom sprite they can two sub-object it too.

The rendering logic (and OpenGL state) is going to be put inside the
`SpriteBatch` object.  Right now it's only going to support ZSprites,
but in the future will support SplineSprites.  Since at the moment there
are some other things that need to be decided on (such as sprite
coordinate systems) and some other code implemented(e.g. a timing
system, instead of using `sdl.getTicks()`), they are only rendering
their spritesheets at the moment, as proof that we can load up a ZSprite
and show something.

The example `03` for sprites isn't also done yet either, so I decided
not to include the code.  I'm only reserving the name.

Don't consider issue zacharycarter#13 done yet.  This is only the first step.
@define-private-public
Copy link
Collaborator Author

PR for what I've got so far is right here: #32

define-private-public added a commit to define-private-public/zengine that referenced this issue Sep 4, 2017
At this moment we are able to read and parse in a very minimal .zsprite
file.  So far we can do things like define frames, sequences, add
looping modifiers, etc.

Righut now there is a `Sprite` object, and a `ZSprite` object (which is a
child of `Sprite).  They are mainly ment to be dumb data containters
that only are for managing the state of a sprite object (e.g. timing,
which frame to show, etc).  In the futur we plane to have sprites that
are defined by the `Spline` format, so that's why I made the common
`Sprite` base object.  In case a game dev also wants to make their own
custom sprite they can two sub-object it too.

The rendering logic (and OpenGL state) is going to be put inside the
`SpriteBatch` object.  Right now it's only going to support ZSprites,
but in the future will support SplineSprites.  Since at the moment there
are some other things that need to be decided on (such as sprite
coordinate systems) and some other code implemented(e.g. a timing
system, instead of using `sdl.getTicks()`), they are only rendering
their spritesheets at the moment, as proof that we can load up a ZSprite
and show something.

The example `03` for sprites isn't also done yet either, so I decided
not to include the code.  I'm only reserving the name.

Don't consider issue zacharycarter#13 done yet.  This is only the first step.
@define-private-public
Copy link
Collaborator Author

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
Copy link
Collaborator Author

define-private-public commented Sep 4, 2017

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
Copy link
Collaborator Author

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
Copy link
Owner

I'm cool with that

@define-private-public
Copy link
Collaborator Author

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.

define-private-public added a commit to define-private-public/zengine that referenced this issue Sep 14, 2017
At this moment we are able to read and parse in a very minimal .zsprite
file.  So far we can do things like define frames, sequences, add
looping modifiers, etc.

Righut now there is a `Sprite` object, and a `ZSprite` object (which is a
child of `Sprite).  They are mainly ment to be dumb data containters
that only are for managing the state of a sprite object (e.g. timing,
which frame to show, etc).  In the futur we plane to have sprites that
are defined by the `Spline` format, so that's why I made the common
`Sprite` base object.  In case a game dev also wants to make their own
custom sprite they can two sub-object it too.

The rendering logic (and OpenGL state) is going to be put inside the
`SpriteBatch` object.  Right now it's only going to support ZSprites,
but in the future will support SplineSprites.  Since at the moment there
are some other things that need to be decided on (such as sprite
coordinate systems) and some other code implemented(e.g. a timing
system, instead of using `sdl.getTicks()`), they are only rendering
their spritesheets at the moment, as proof that we can load up a ZSprite
and show something.

The example `03` for sprites isn't also done yet either, so I decided
not to include the code.  I'm only reserving the name.

Don't consider issue zacharycarter#13 done yet.  This is only the first step.
@define-private-public define-private-public added this to In Development in Sprite Implementation Oct 2, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
Development

No branches or pull requests

2 participants