HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

SimpleShape system, need opinion and help from user !

07-21-2009, 08:06 PM#1
Flame_Phoenix
So ... some of you may remember one of the first systems I tried to make. It should be 2D simple Shape system. However the system was not modular and so it was doomed to be ... destroyed.

But now, with recent knowledge and times, I am trying to remake it, I am trying to make that the system of my dreams, and hopefully of the user's dreams as well. So I am taking a complete new and modular approach. However I need your help, I need to know how to make some stuff and how you would like to use such a system.

Terminology:
- 2D3S (2D Simple Shape System) is made by a core trigger which has the Shape. A Shape is made by modules that the user can choose to have or not. All shapes or composed by compositions of other shapes (soon to be add).
A Shape object is a parallel array of coordinates, nothing else. I decided to take this approach because it will offer the user a great deal of freedom, but the next lines should help you understand it better.
In this example, I have the module Line made. This optional module (all modules will be optional, so the user can CHOOSE what he needs or wants) allows the user to draw a line using xefx.
So far I have a method called "draw" which creates the line, however I would also like to have an optional method called "customDraw" which should be optional (the user only creates it if he needs). I don't know how to make a method optional, so I would appreciate help here.
There will be other optional methods such as rotate and move per example.
The next example of code will try to illustrate my mind:

Collapse JASS:
//===========================================================================
//Description:
// - A system that allows the user to create many shapes in a very simple and 
//customizable way. This is simply the core of the system. To draw more shapes
//you will have to import other optional modules.
//
//Author:
// - Flame_Phoenix
//
//Credits:
// - ThredNThrash, for the main idea and math formulas
// - BubleTech, for efficiency advices
// - Pyro and Anitarf for suggestions on how to improve
//
//@version 1.1.0
//===========================================================================
library_once SimpleShapes
    
    globals 
    //this is public so other modules can access it
        public constant integer MAX_SIZE = 8191
    endglobals
    
    struct Shape
        real array COORD_X[MAX_SIZE]
        real array COORD_Y[MAX_SIZE]
        integer size
    
        implement optional LineModule
        
        method getSize takes nothing returns integer
            return .size
        endmethod
    
        method setSize takes integer newSize returns nothing
            set .size = newSize
        endmethod
        
    endstruct
    
endlibrary

This is SimpleShapes, the core. It is very, very simple as you can see.

Now, imagine that I (as a user) want to add the functionality of making a line. Then I will import the module Lines:
Collapse JASS:
//===========================================================================
//Description:
// - This optional module allows you to draw lines using xefx. 
//
//Methods:
// - To use this just have a look on the example trigger.
//
//static method createLine takes real sX, real sY, real eX, real eY, real 
//intervail returns Shape
// - Take sX and sY correspon to startX and startY where the line will start,
//eX and eY are the points where the line will end. The intervail is the distance 
//between each point, or in this case, the collision size of a xefx model unit.
//
// method drawLine takes string path returns nothing
// - draws the line using the model path suggested. This line is created using 
//xefx objects.
//
//method ereaseLine takes nothing returns nothing
// - ereases the line created by drawLine
//
//method destroyLine takes boolean ereaseLine returns nothing
// - if ereaseLine == true, then is destroy he Line object and it erease the xefx objects
//created by drawLine. If ereaseLine == false, then it simply destroys the line object but
//it lets the drawing live.
//
//Author:
// - Flame_Phoenix
//
//Credits:
// - Vexorian for xefx.
//
//@version 1.0.0
//===========================================================================
library LineModule requires xefx

module LineModule
    xefx array effects[SimpleShapes_MAX_SIZE]
    
    static method createLine takes real sX, real sY, real eX, real eY, real intervail returns Shape
        local Shape this = Shape.allocate()
        
        //the distance of the line
        local real dx = sX - eX
        local real dy = sY - eY
        local real angle = Atan2(eY - sY, eX - sX)
        local real dist = SquareRoot(dx*dx + dy*dy) 
    
        //temporary variables that will allow us to create many points
        local real x
        local real y
        local integer i = 0
        
        //setting our members
        call this.setSize( R2I(dist / (intervail ) ) )  //number of elements we will take
        
        loop
            exitwhen(i == this.getSize())
            
            //polar projection stuff            
            set this.COORD_X[i] = sX + ((i * dist) / .size) * Cos(angle)
            set this.COORD_Y[i] = sY + ((i * dist) / .size) * Sin(angle)
            
            set i = i + 1
        endloop
        
        return this
    endmethod
    
    method drawLine takes string path returns nothing
        //now we create 1 unit per each point
        local integer i = 0
        loop
            exitwhen(i == this.getSize())
            
            set .effects[i] = xefx.create(this.COORD_X[i], this.COORD_Y[i], 0)
            set .effects[i].fxpath = path

            set i = i + 1
        endloop
    endmethod
    
    method ereaseLine takes nothing returns nothing
        local integer i = 0
        
        loop
            exitwhen(i == this.getSize())
            call .effects[i].destroy()
            set i = i + 1
        endloop
        
        call this.destroy()
    endmethod
    
    method destroyLine takes boolean ereaseLine returns nothing
        if ereaseLine then
            call .ereaseLine()
        endif
        
        call this.destroy()
    endmethod

endmodule

endlibrary

Now imagine that I want to draw a complex Shape, like a Wheel.

I would have something simillar to this pseudo-code:
Collapse JASS:
library Wheel requires LineModule, CircleModule, xefx
    module WheelModule
        xefx array effects[SimpleShapes_MAX_SIZE]
        
        static method createWhell (...)
        endmethod

        method drawWheel (...)
        endmethod

        (... more stuff simillar to LineModule...)
    endmodule
endlibrary

This will now allow me to draw a line:
Collapse JASS:
scope Line initializer Init
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == 'A004'
    endfunction
//===========================================================================
    private function Actions takes nothing returns nothing
        local location spellLoc = GetSpellTargetLoc()
   
        //creating a line!
        //static method createLine takes real startX, real startY, real endX, real endY, real intervail returns Shape
        local Shape line = Shape.createLine(GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), GetLocationX(spellLoc), GetLocationY(spellLoc), 35.)
        
        //now we make a picture =D
        call line.drawLine("Environment\\SmallBuildingFire\\SmallBuildingFire2.mdl")
        
        call TriggerSleepAction(3.)
        
        //and now we destroy the line 
        //method destroyLine takes boolean ereaseLine returns nothing
        //in this case I want to erease the line, so I say true!
        call line.destroyLine(true)
        
        //nulling stuff
        call RemoveLocation(spellLoc)
        set spellLoc = null
    endfunction
//===========================================================================
    private function Init takes nothing returns nothing
        local trigger LineTrg = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( LineTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition(LineTrg, Condition( function Conditions ) )
        call TriggerAddAction(LineTrg, function Actions )
    endfunction
endscope

This is how you would use it.

So, I need your opinion:
- How can I add optional methods for the user to complete (if he wants to)?
- Do you think this is easy to use?
- Do you have any other suggestions?
07-21-2009, 08:44 PM#2
Blubb-Tec
you should check whether locations are faster than your custom Point struct. and why are you using an array and not a list?
07-21-2009, 09:13 PM#3
Flame_Phoenix
Quote:
you should check whether locations are faster than your custom Point struct. and why are you using an array and not a list?
A locations being faster then a struct !? That makes no sense to me, locations have the "Z" thing that usually makes them slow ...
How can I test such a thing? Is there any benchmark test on the database I can use?

I use an array because I think it is faster then a linked list. Besides, it is a lot easier to use and I also have a small base on an old version of 2D3S where Iron_Doors was using arrays and Pyro told me I should follow his suggestion.
07-21-2009, 09:32 PM#4
Blubb-Tec
how you can benchmark that? i guess only with japi... anyway, could you tell me about that Z things that makes locations slow? i've never heard of that, but it actually sounds interesting. I thought of locations because they're only using natives, no function calls/trigger evaluates or whatever at all. and, for whatever purposes, 8190 points might not be enough. and if you use more than that, vjass will need a function call instead of an array lookup whenever you use a struct in a certain way(method call i think, not sure about that though) which will make it even slower.

about the arrays, they are faster than lists, which is only natural, but again, incase it exceeds 8190(or even less, not sure) it might be quite slow.. then again, you would need multiple interface inheritance for that to work nicely, i guess, which currently is not availiable(vex recently mentioned he was going to implement that when he rewrote the structs-phase of jh).
07-22-2009, 09:14 AM#5
Flame_Phoenix
Afaik the reason why people usually avoid locations is because they have X, Y and Z values. The Z value is usually not needed, which is why people prefer to make the maths manually for efficiency bonus.

As for the array, I don't think someone will ever create an effect with more than 8000 xefx instances (such a thing would be highly unstable and insane, I don't think any computer would handle it anyway). I am not sure about calls and arrays though. I could use lists, but their bonus would only come in a very late stage. You should know that each shape object can have more than 8000 xefx or point instances. I agree it will be quite a waste of memory, but since all systems I studied use this way of doing things, I guess this won't be much of a problem, as programers usually say "Intel solves the problem" xD

Thx for your review though, it was very friendly!
07-22-2009, 01:02 PM#6
Anitarf
I hope we will have no more nonsense after this:
Expand Location benchmark:
Expand Struct benchmark:
Location:
5.5
Empty loop:
0.6
Struct:
11.6
07-22-2009, 02:22 PM#7
Flame_Phoenix
Holly Macarolli !!
Locations are faster then my struct Point ! They have more than the double of the speed !

It is clear I must make an array of locations instead of an array of structures !
Mmmm

Ani, Buble suggested that perhaps I should use a list because if things get bigger it may be more efficient. We didn't arrived to an comun opinion because we don't know enough details. What is the best for this situation ? An array as Pyro suggests or a List ?

rep++ !
07-22-2009, 02:38 PM#8
Anitarf
Quote:
Originally Posted by Flame_Phoenix
Holly Macarolli !!
Locations are faster then my struct Point ! They have more than the double of the speed !

It is clear I must make an array of locations instead of an array of structures !
Mmmm
You know, two real arrays for coordinates are even faster...

Quote:
Ani, Buble suggested that perhaps I should use a list because if things get bigger it may be more efficient. We didn't arrived to an comun opinion because we don't know enough details. What is the best for this situation ? An array as Pyro suggests or a List ?
No idea which is more suitable, I didn't read your code.
07-22-2009, 02:43 PM#9
Flame_Phoenix
Mmm so you are suggesting me to use a 2D array right ?
Well, I guess making a list of reals would be nonsense so ... xD
07-22-2009, 03:36 PM#10
chobibo
I think he's suggesting a parallel array, not a 2d array. If I'm correct then this is what he means:
Collapse JASS:
real array COORDINATE_X
real array COORDINATE_Y
07-22-2009, 06:24 PM#11
Blubb-Tec
right, this is even faster, forgot about that >.>
07-22-2009, 07:15 PM#12
Flame_Phoenix
Right ... on the other hand, I was thinking of a parallel array when I referred 2D arrays lol xD
Looks like I just don't know what I say anymore lol =P

Ok, I will remove struct Point and add a set of parallel arrays. Any more suggestions? DO you think the design is good? Do you think it is easy to use and update for a user?
07-22-2009, 09:29 PM#13
Blubb-Tec
hey, i think you have a bit of a misunderstanding there. When you make something, and are asking "will the user like this? is the design ok?", the "user" you should have on your mind is only ONE person: that persion is, yourself.
I once heard vex say that when making vJass syntax the only one he makes the syntax for is himself, and not any other person. do that too. make your systems for yourself. design them in a way YOU like, make its user-interface just like YOU would want to have it, and same goes for everything else. However, if someone tells you about a "mistake in design" or something similar, don't just dismiss it. think about it, put it to the test, and then decide if its better or worse than what you already have.

meh, this was a long post now, and its really off-topic, but I always have the slight tingeling feeling that you're going at it with the wrong intentions.
Fame will come to you when your works are SO great, that people simpy CAN'T ignore you anylonger. at that point, its no longer necessary to spread word about whatever you made in your signature or wherever.

meh, even more of this :P well, feels good to be writing this, something i wanted to cut into now for a long time...

anyways, have a good night, fellas :)
07-22-2009, 10:17 PM#14
chobibo
Wow Blubb, I agree to what you wrote. You can submit your resource and just add things later if someone requests it.
07-23-2009, 11:47 AM#15
Toadcop
Quote:
Locations are faster then my struct Point !
omfg it wasnt obvious !11!1! T_T