About Monkey 2 › Forums › Monkey 2 Development › Sprites in Mojo3D
This topic contains 9 replies, has 4 voices, and was last updated by
Ethernaut
1 year, 7 months ago.
-
AuthorPosts
-
August 6, 2017 at 6:28 am #9744
I started diving a little more into Mojo3D, and have some questions about sprites:
- Would it be possible to have sprites more integrated in the 3d scene and render correctly when behind 3d objects? (could be an optional thing). Currently they seem to always render on top.
- I’m trying to implement animated sprites. That was easy in Mojo2D, since I could have an image array and just draw the correct image at the right time. As far as I understand, in Mojo an image is simply a rect contained in a Texture, so ultimately an image array could have images from the same texture, which is very efficient. SpriteMaterial.ColorTexture uses Texture instead of Image. Would it be inefficient to create a Texture array and replace the current SpriteMaterial.ColorTexture on every frame? Is there a better way?
- How do you set the texture flags on a sprite? Setting the flags on SpriteMaterial.ColorTexture didn’t have an effect.
- Are those things planned to be implemented in the future, and should I just wait? I’m looking for things like loading sprite sheets, setting frame rate, loop behavior and frame lists, etc.
- Bonus: it would be nice if the sprite shader had the ability to “flash” a certain color (paint all non-transparent pixels with that color) temporarily.
Thanks!
August 13, 2017 at 6:09 am #9801Yeah, sprites are very primitive right now and there are lots of changes coming. I will definitely keep your questions in mind though and try to address them as well as I can.
I just need to finish up the IAP mobile module this week, and then it’s back into the fun/interesting stuff!
August 13, 2017 at 9:20 am #9802I just need to finish up the IAP mobile module this week
I guess I have to be careful of what I wish for in the future
August 19, 2017 at 7:26 am #9917Just having a play with sprites…
How do you set the texture flags on a sprite? Setting the flags on SpriteMaterial.ColorTexture didn’t have an effect.
This should work, which flags were you trying to use.
August 19, 2017 at 7:47 am #9918I’m trying to set the flags after creating the material, like this:
Monkey123material = SpriteMaterial.Load( path )material.ColorTexture.Flags = TextureFlags.NoneLocal cat := New Sprite( material )August 19, 2017 at 8:01 am #9919Ok, cheers, turns out Texture.Flags setter was completely borked – getting some nice ‘outrun’ style pixels now!
I’ll also add a textureFlags param to SpriteMaterial.Load, but being able to modify flags is way cool.
August 22, 2017 at 6:58 am #9958Just pushed some fixes and changs to develop branch.
Sprites should now use depth buffer properly, and Texture.Flags setter now works.
Also, as a bit of an experiment, I added a TextureRect property to Sprite. This defaults to new Rectf( 0,0,1,1 ) and describes the 4 ‘texture coordinate’ corners of the sprite, ie: you could theoretically use this to pick frames out of an atlas. A better approach might be to add the rects to the material, but this is would involve coming up with a ‘SpriteFrames’ class and/or ‘SpriteAnimations’ class etc. Have to think about this a bit more!
August 23, 2017 at 3:59 am #9964Are 3D sprites same as a 3D object?
However you will have to apply a rotation to look at the camera all the time.
August 23, 2017 at 10:39 pm #9978Have a look at the sprites test.
August 27, 2017 at 8:01 am #10030Thanks Mark!
If you decide to add a SpriteFrames class or similar I’ll update my stuff, but for now I made an “AnimSprite” class that extends Sprite and stores the coordinates internally. I also have an “AnimationClip” class that simply stores a named frame sequence, so you refer to it by name and “grab” different frames from the same sprite sheet.
Here’s the class, complete with Json file loading for animation clips (use example attached at the bottom). This is more or less super untested!
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231Namespace mojo3d.graphicsClass AnimSprite Extends Sprite'Event functionsField onLastFrame :Void()Field onFirstFrame :Void()Protected'Atlas valuesField _frame:Int = 0 'The frame currently displayedField _coordinates:= New Stack<Rect<Double>> 'A stack containing the UV coordinates for each cell'Animation clip managementField _timeScale := 1.0 'Adjusts playback speed. Can be used to create slow motion effects without changing the framerate.Field _anim :AnimationClip 'The animation clip currently playingField _animations := New StringMap< AnimationClip > 'List of available animation clipsField _offset :Int 'Current frame offsetField _framerate:Double = 15.0 'Frame rate, if a clip is not provided'MiscField _firstFrame := TrueField _hasReachedEnd := FalseField _hasReachedStart := False'******************************* Public Properties *******************************Public'Current frameProperty Frame:Int()Return _frameSetter( number:Int )If number <> _frame_frame = Clamp( number, 0, _coordinates.Length-1 )TextureRect = _coordinates[ _frame ]If _frame >= LastFrameIf Not _hasReachedEndonLastFrame()_hasReachedEnd = True_hasReachedStart = FalseEndEndIf _firstFrameonFirstFrame()_firstFrame = FalseElseIf _frame = FirstFrameIf Not _hasReachedStartonFirstFrame()_hasReachedStart = True_hasReachedEnd = FalseEndEndEndEndEnd'current AnimationClipProperty Animation:String()Return _anim.nameSetter( name:String )If _animations[ name ]_anim = _animations[ name ]ElsePrint( "AnimSprite: animation '" + name + "' Not found!" )EndEnd'Map with all animations as values and their names as keysProperty AllAnimations:StringMap< AnimationClip >()Return _animationsEnd'Offsets the current frame, useful when creating multiple copies of the same spriteProperty FrameOffset:Int()Return _offsetSetter( number:Int )_offset = numberEnd'Sets the frame rate. If a clip is in use, that clip's frame rate will be set.Property FrameRate:Double()If _animReturn _anim.framerateElseReturn _framerateEndSetter( value:Double )If _anim_anim.framerate = valueElse_framerate = valueEndEnd'Duration (in seconds) of the current animation clip. If none, duration of the entire spritesheet is provided.Property Duration:Double()Local _period:Double = ( 1.0 / FrameRate ) * _timeScaleIf _animReturn _period * _anim.frames.LengthElseReturn _period * _coordinates.LengthEndEnd'First frame in clipProperty FirstFrame:Int()If _animReturn _anim.frames[ 0 ]ElseReturn 0EndEnd'Last frame in clipProperty LastFrame:Int()If _animReturn _anim.frames[ _anim.frames.Length-1 ]ElseReturn _coordinates.Length - 1EndEnd'******************************* Public Methods *******************************Method New( path:String, cellWidth:Int, cellHeight:Int, padding:Int = 0, border:Int = 0, flags:TextureFlags = TextureFlags.FilterMipmap )'Creates new Sprite with materialSuper.New( SpriteMaterial.Load( path, flags ) )Local texture := Cast<SpriteMaterial>( Material ).ColorTextureLocal _paddedWidth:Double = cellWidth + ( padding * 2 )Local _paddedHeight:Double = cellHeight + ( padding * 2 )Local _rows:Int = ( texture.Height - border - border ) / _paddedHeightLocal _columns:Int = ( texture.Width - border - border ) / _paddedWidth'Generates UV coordinates for each frameLocal numFrames := _rows * _columnsLocal w:Double = texture.WidthLocal h:Double = texture.HeightFor Local i:= 0 Until numFramesLocal col := i Mod _columnsLocal x:Double = ( col * _paddedWidth ) + padding + borderLocal y:Double = ( ( i / _columns ) * _paddedHeight ) + padding + border_coordinates.Push( New Rectf( x/w, y/h, (x+cellWidth)/w, (y+cellHeight)/h ) )Next'Defaults to frame 0Frame = 0End'Update time is in seconds (Double), not millisecondsMethod Update( time:Double )Local frameLength:Double = ( 1.0 / FrameRate ) / _timeScaletime += ( _offset * frameLength )If _animIf _anim.loopFrame = _anim.frames[ Int( ( time Mod Duration ) / frameLength ) ]ElseFrame = _anim.frames[ Int( time / frameLength ) ]EndElseFrame = Int( ( time Mod Duration ) /frameLength )EndEnd'Adds new animation clips.Method AddAnimationClip( _name:String, _loop:Bool = True, framerate:Int, _frames:Int[] )local animClip := New AnimationClipanimClip.name = _nameanimClip.loop = _loopanimClip.frames = _framesanimClip.framerate = framerate_animations.Add( _name, animClip )End'Loads Json fileMethod LoadAnimations( path:String )Local json := JsonObject.Load( path )If jsonLocal anims := json.GetObject( "animations" )If animsFor Local a := Eachin anims.ToObject()Local obj := a.Value.ToObject()Local loop := obj[ "loop" ].ToBool()Local rate := obj[ "rate" ].ToNumber()Local frameStack := obj[ "frames" ].ToArray()Local frames:Int[] = New Int[ frameStack.Length ]For Local n := 0 Until frameStack.Lengthframes[n] = frameStack[n].ToNumber()NextAddAnimationClip( a.Key, loop, rate, frames )NextEndElsePrint( "AnimSprite: Warning, json file not found or invalid" )EndEndEnd'**************************************************************************************************************************************'Class AnimationClip 'AnimationClips contain a sequence of frames to be played, its name, framerate and loop state.field name :String 'Animation namefield loop := True 'looping can be controlled per animationfield frames :Int[] 'Frame list array, contains the sequence in which the frames playField framerate := 15.0 'frame rate per clipProperty FrameCount:Int()Return frames.LengthEndEndAnd here’s an example use, with a little animated explosion sprite!
http://monkeycoder.co.nz/wp-content/uploads/2017/08/animSprite-1.zipOnly thing missing now is a way to “flash” a color on the sprite!
Cheers. -
AuthorPosts
You must be logged in to reply to this topic.