| 07-21-2009, 08:06 PM | #1 |
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: 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: 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: 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: 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 |
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 | |
Quote:
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 |
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 |
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 | |||
I hope we will have no more nonsense after this: Location benchmark:scope Test initializer Init globals private integer iterations=0 private real totaltime=0.0 endglobals private function RunTest takes nothing returns nothing local location l local integer sw = StopWatchCreate() local real t0 local real t1 local integer i = 0 set t0 = StopWatchMark(sw) loop exitwhen i>=1000 set l=Location(0.0,0.0) call RemoveLocation(l) set l=null set i = i + 1 endloop set t1 = StopWatchMark(sw) set iterations=iterations+1 set totaltime=totaltime+(t1-t0) call BJDebugMsg("Result: "+R2S(1000*(t1-t0))+" Average of "+I2S(iterations)+" cases: "+R2S(1000*(totaltime/iterations))) call StopWatchDestroy(sw) endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger t = CreateTrigger( ) call TriggerRegisterPlayerEventEndCinematic( t, Player(0) ) call TriggerAddAction( t, function RunTest ) endfunction endscope Struct benchmark:scope Test initializer Init private struct loc real x real y static method create takes real x, real y returns loc local loc this=loc.allocate() set .x=x set .y=y return this endmethod endstruct //=========================================================================== globals private integer iterations=0 private real totaltime=0.0 endglobals private function RunTest takes nothing returns nothing local loc l local integer sw = StopWatchCreate() local real t0 local real t1 local integer i = 0 set t0 = StopWatchMark(sw) loop exitwhen i>=1000 set l=loc.create(0.0,0.0) call l.destroy() set i = i + 1 endloop set t1 = StopWatchMark(sw) set iterations=iterations+1 set totaltime=totaltime+(t1-t0) call BJDebugMsg("Result: "+R2S(1000*(t1-t0))+" Average of "+I2S(iterations)+" cases: "+R2S(1000*(totaltime/iterations))) call StopWatchDestroy(sw) endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger t = CreateTrigger( ) call TriggerRegisterPlayerEventEndCinematic( t, Player(0) ) call TriggerAddAction( t, function RunTest ) endfunction endscope
|
| 07-22-2009, 02:22 PM | #7 |
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 | ||
Quote:
Quote:
|
| 07-22-2009, 02:43 PM | #9 |
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 |
I think he's suggesting a parallel array, not a 2d array. If I'm correct then this is what he means: JASS:real array COORDINATE_X real array COORDINATE_Y |
| 07-22-2009, 06:24 PM | #11 |
right, this is even faster, forgot about that >.> |
| 07-22-2009, 07:15 PM | #12 |
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 |
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 |
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 | |
Quote:
|
