TheSachin / cocos2d-iphone

Automatically exported from code.google.com/p/cocos2d-iphone
0 stars 0 forks source link

Streaks/Ribbons inclusion into future Cocos2d version.. #171

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
    Attached you'll find code for the streak/ribbon system I've developed for Cocos2d, which 
seems useful enough to include in a future version. I'd appreciate a solid code 
review on this, as 
I'm not sure if I'm doing everything the best way possible. However, the system 
works well 
enough in my tests to submit this first pass so we can start talking about 
potential changes and 
improvements.

What it is:

Ribbon
     A ribbon is a dynamically constructed series of polygons with texture. You create a ribbon 
with an initial start position, width, texture, length, and color. Each point 
creates a new quad at a 
new position and can change the width of the ribbon at said point.

MotionStreak
    A motion streak is a specific style of ribbon used for game effects; the trail of a sword slash or 
arrow flying though the air, as an example. You construct a motion streak in 
much the same way 
as a ribbon, but also give it a fade time and segment threshold. You parent the 
object to another 
object in your scene.
    When the parent object moves about the segment threshold distance, it will add a segment to 
the ribbon. As time progresses, the tail of the ribbon will fade out (based on 
fade time).

General code concerns:
    As I'm still pretty new to Objective C, I'm sure there are some common mistakes made. 
However, I'd like to point out a few of the areas I'm less confident about. 
   First we have the way ribbons are constructed and drawn. When the user calls addPoint on a 
ribbon, it generates a new set of verts and coordinates and adds them to a 
NSMutableArray. 
When the draw function is called, these vert and coordinate arrays are passed 
to openGL for 
drawing. 
    However, it would be possible to keep a single vert and coordinate array for the entire mesh, 
which could be significantly faster than constructing it each frame. However, I 
wasn't sure how to 
pass anything but a C style array as a glVertexPointer. Additionally, C style 
arrays can't be 
expanded without doing lots of copy operations, which doesn't seem ideal. So, 
some guidance on 
container choice and use would be wonderful. That said, the next point could 
complicate things:
   Next, when a ribbon is drawn it creates an array of colors to apply to the verts. It does this to 
allow the ribbon to fade with time. We could allow the ribbon to have different 
colors per section, 
but I didn't think this was of high priority.
   Ok, another potential issue is how a MotionStreak is updated. The way it works now is by 
looking at the position of it's parent and updating the ribbon accordingly, 
then it offsets itself by 
the inverse of the parents position. I'm pretty sure there's a better way to do 
this, as this is pretty 
brittle. 
    For one, you can't offset the streak from an object, because it'll keep getting blown away. 
Second, it only works if the parenting chain is one level deep. Third, the 
streak will always be 
drawn as a child of the object thats "creating" it, which may not be desirable. 
    What I'd ideally like is:
A) a way to draw in absolute screen space instead of in my own space
   - to avoid counter moving the streak object
B) a way to determine an objects absolute screen space
   - so I can track my parent without worrying about the entire parenting chain
C) a way to have the streak track a target instead of it's parent object

regarding C: I actually had this written with a StreakMgr class at first, and 
streaks were created 
through it and contained a reference to a target object. This solved B and C, 
but had one little 
problem; the manager class had no way of knowing if that target object was 
deleted, because 
nothing would set that pointer back to nil. There might be an easy way around 
this?

One last thing; a doc on how to create a new demo in the demo app would be 
useful; I tried to 
create one for this class but it kept giving me a "won't run in the simulator" 
error. I'm sure I'm 
missing something simple, but I couldn't figure out what. 

Anyway, when you have some time I'd love some feedback on this. I think it 
would be a really 
useful addition to Cocos as there are many cases where you want to draw 
connected polygon 
segments in games. I'm going to stop working on it for a day or two and get 
back to my game, 
then do a document/comment/cleanup pass on it.

Original issue reported on code.google.com by slipster...@gmail.com on 29 Jan 2009 at 5:45

Attachments:

GoogleCodeExporter commented 9 years ago
changing status to new instead of accepted

Original comment by slipster...@gmail.com on 29 Jan 2009 at 5:46

GoogleCodeExporter commented 9 years ago
Ok, talked over some of this with a friend at work. I've got a plan to convert 
the
drawing code to strips instead of individual polygons, move towards statically
allocating larger sections of the ribbon, and generally speed up performance. 

Original comment by slipster...@gmail.com on 29 Jan 2009 at 4:50

GoogleCodeExporter commented 9 years ago
Awesome work

Original comment by doctorsg...@gmail.com on 30 Jan 2009 at 3:43

GoogleCodeExporter commented 9 years ago
Ok, I've cleaned this up quite a bit. The ribbon class now much more efficient, 
drawing with Triangle Strips 
instead of drawing individual quads. Additionally, the ribbon segment class 
statically allocates enough 
memory for a strip of 50 segments (100 triangles) and only allocates new 
segments (in static chunks of 50) 
when needed. It even pools the old ones to avoid reallocating memory. Because a 
motion streak cannot 
determine a maximum amount of vertices needed, I figured this would be the best 
way to keep flexibility 
while maintaining performance.

The only issue I have now is how to best handle the motion class. In an ideal 
situation, I'd be able to create 
these things and have them track objects separate from their drawing order. I'd 
like to simply have them track 
an object so you can place them anywhere in the draw tree that you like rather 
than parenting them to an 
object that's moving; but if that object gets deleted, I have no way of knowing.

Smart Pointers would be nice!

Original comment by slipster...@gmail.com on 31 Jan 2009 at 6:54

GoogleCodeExporter commented 9 years ago
Ok, everything is cleaned up now and ready to go. Here's the latest versions of 
the two classes..

Original comment by slipster...@gmail.com on 1 Feb 2009 at 3:21

Attachments:

GoogleCodeExporter commented 9 years ago
could you commit them Ribbon and MotionStreak to the repository ?
I've created an 'experimental' directory to tests these kind of new feature.

could you also add a new example name, for example, "exp - MotionStreakDemo" or
"MotionStreakDemo (exp)" ?

thanks

Original comment by ricardoq...@gmail.com on 2 Feb 2009 at 9:19

GoogleCodeExporter commented 9 years ago

Original comment by ricardoq...@gmail.com on 2 Feb 2009 at 9:21

GoogleCodeExporter commented 9 years ago
thanks.
Could you also commit an example that shows how to use it ?
The idea is that these files (MotionStreak,Ribbon) belongs to the example 
target, and
not to cocos2d.
Let me know if you have the time to do it.
If you don't have the time could you post here some code that shows how to use 
it ?
thanks

Original comment by ricardoq...@gmail.com on 4 Feb 2009 at 8:58

GoogleCodeExporter commented 9 years ago
Yeah, started working on a demo today over lunch. Should have it done tonight.. 
To
use a streak, use the convenience constructor and parent it to a moving object 
in the
scene. It will emit a ribbon of polygons behind it, textured with the image you
specified and the UV mapping implied by the length parameter. 

Original comment by slipster...@gmail.com on 4 Feb 2009 at 10:40

GoogleCodeExporter commented 9 years ago
Demo added to svn. Note that it exposes a bug with the absolutePosition 
function on CocosNode, which I 
entered into the issue tracker. Absolute Position doesn't account for parent 
object rotation or scale, which makes 
it far from absolute.

Original comment by slipster...@gmail.com on 5 Feb 2009 at 4:45

GoogleCodeExporter commented 9 years ago
thanks!
I've create the 'project' in xcode.

r505

Original comment by ricardoq...@gmail.com on 5 Feb 2009 at 11:05

GoogleCodeExporter commented 9 years ago
hey,
after playing a while with the demo, I don't know what's the benefit of having 
the
motion streak and ribbon in cocos2d.
excuse my ignorance, but how would you use it in a game ?

Original comment by ricardoq...@gmail.com on 15 Feb 2009 at 4:00

GoogleCodeExporter commented 9 years ago
I personally use it to create motion trails behind arrows shot in one of my 
games, and to create a streak of butter 
following an object in another. At Turbine, we used streaks for sword slashing 
effects and other stuff - at 
Harmonix, we use them for all kinds of effects such as motion trails and such.

Basically, if you don't have a predefined path, or want the object to fade over 
time, there's no way to do those 
types of effects without a streak system. For instance, how would you create 
the effect in the demo in cocos 
without them?

Original comment by slipster...@gmail.com on 15 Feb 2009 at 5:19

GoogleCodeExporter commented 9 years ago
A ribbon could also be useful in generated terrains if I'm not mistaken.

Original comment by RobertBl...@gmail.com on 18 Feb 2009 at 6:19

GoogleCodeExporter commented 9 years ago
I didn't even think of that robert.. I might add some features to the ribbon 
class to
make that easier to manage, as right now it's based around width from a center 
point.
I have a terrain in one of my games that could be using a ribbon right now..

Original comment by slipster...@gmail.com on 18 Feb 2009 at 9:18

GoogleCodeExporter commented 9 years ago
I have attached the streak to a sprite which is rotating as it moves in a 
single direction which causes the streak to 
rotate with it but i don't want this to happen as the streak should always be 
from the direction where the sprite 
came. Is this possible? 

Original comment by nick.des...@gmail.com on 9 Mar 2009 at 2:19

GoogleCodeExporter commented 9 years ago
Yes, in fact I had wanted Streaks to work that way originally, but Objective 
C's lack of reference tracking 
makes it much harder than it should be. Also, absolute position doesn't 
function correctly in Cocos2d (doesn't 
take scale/rotation hierarchy into account yet) which would have also helped. 
Some possible ways to fix this:

1) Change your display hierarchy so that the rotating sprite is a child of a 
cocosNode, and the streak is also a 
child of the cocosNode. Move the parent node, but only rotate the sprite. 
Depending on what your doing this 
might be easy or hard.

2) Schedule a per-frame function and have it set the position of the streak to 
the position of the sprite. This 
also allows you to parent the streaks to a different place in the display list, 
which can be very useful.

Original comment by slipster...@gmail.com on 9 Mar 2009 at 4:47

GoogleCodeExporter commented 9 years ago
I am actually attempting to implement this into one of my games. Seems like a 
really
great tool! I do have a question though. I want my streak to be just white, but 
when
I set the color to 0xFFFFFF it is light blue? I can't seem to get around it, 
all I
ever get is various shades of blue. My original sprite is a white PNG file with 
some
transparency.

Original comment by Yur...@gmail.com on 15 May 2009 at 5:56

GoogleCodeExporter commented 9 years ago
I did not have alpha blending enabled. I will try again to see if that solved my
issue. I figured out how to tweak the color to my liking, now I just have a 
black
border around my sprites (where transparency should be). So there! Thanks for a 
great
tool!

Original comment by Yur...@gmail.com on 19 May 2009 at 2:14