wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Warcraft III Modding > Developer's Corner > Triggers & Scripts
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 03-02-2010, 11:26 PM   #1
TheKid
User
 
TheKid's Avatar
 
Join Date: Mar 2009
Posts: 195

TheKid will become famous soon enough (37)TheKid will become famous soon enough (37)

Default Projectiles Library (What can I do to optimize?)

I have been working on this for a little while now and I was wondering if anybody could help me out. I'm trying to optimize the code and do things as quickly as they can be done to maximize the performance that I can get out of it.

So far the projectile's collision booleans (for unit-collision and projectile-collision) are set to off, it will not run any mid-flight collisions. The code in the projectile-collision segment is commented away anyways.

Expand JASS:

So far this library will mimic a WarCraft III missile, given an arc/speed. If the speed is 0 or the distance between the source/target is 0, then it will treat it as an instant projectile. Other than that, the projectile will fly through the air (it is able to be slowed/sped up by the use of the timescale variable) until reaching its target, at which point it will call the onFinish method.

It uses a unit to construct a "projectile" but it keeps all the functionality of the unit intact, theoretically allowing the user to make jump type effects as well. I will also post the code for a structure that extends the projectile, called rangedprojectile. This uses the dummy.mdx model with multiple pitch animations to achieve a proper looking arc. It also allows you to create various different types of projectiles easily.

Collapse JASS:
library Ranged requires Projectiles
globals
//*****************
//* Configuration
//* ŻŻŻŻŻŻŻŻŻŻŻŻŻ
//*
//*
//* The unit used to create ranged projectiles. The dummy model I am using is Vexorian's pitch animation model, so I can 
//* simulate projectile "tilt".
    public constant integer         DUMMY_ID            = 'dumy'
//*
//*
//****************************
endglobals

struct rangedprojectile extends projectile
//********************
//* Ranged Projectile
//* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
//* A structure with methods that allows the user to easily create missiles that look/act exactly like WarCraft III missiles.
//*
//*
    readonly unit       source          = null                          //* Source from which the projectile came.
    readonly effect     model           = null                          //* The effect that represents the projectile's "model".
    readonly string     modelpath
    
    private static location     p_sampleLoc         = Location(0, 0)    //* Used to optimize GetLocationZ
    
    method onDestroy takes nothing returns nothing
        call KillUnit(.toUnit)
        if (.model!=null) then
            call DestroyEffect(.model)
        endif
    endmethod
    
    // Each time the projectile is updated on the timer-loop.
    method onLoop takes nothing returns nothing
        local s_vector3d vec = .velocity
        call SetUnitFacingTimed(.toUnit, Atan2(vec.y, vec.x)*bj_RADTODEG, 0)
        call SetUnitAnimationByIndex(.toUnit, R2I(bj_RADTODEG*Atan2(vec.z, SquareRoot(vec.x*vec.x + vec.y*vec.y)+0.5)+90))
        // Since we are only given a copy of the velocity, we must destroy it.
        call vec.destroy()
    endmethod
    
    // Easy-to-use constructor method.
    static method create takes unit source, real heightoff, real targx, real targy, real speed, real pitchArc, string modelpath returns thistype
        local thistype r
        local unit u
        local real x
        local real y
        local real theta
        local s_vector3d vec
        local s_vector3d vecb
        
        set x = GetUnitX(source)
        set y = GetUnitY(source)
        set theta = Atan2(targy-y, targx-x)
        set u = CreateUnit(GetOwningPlayer(source), DUMMY_ID, x, y, theta*bj_RADTODEG)
        set r = thistype.allocate(u)
        set r.source = source
        set r.modelpath = modelpath
        set r.model = AddSpecialEffectTarget(modelpath, u, "origin")
        
        call MoveLocation(thistype.p_sampleLoc, x, y)
        set vec = s_vector3d.createEx(x, y, GetLocationZ(thistype.p_sampleLoc)+GetUnitFlyHeight(source)+heightoff)
        call MoveLocation(thistype.p_sampleLoc, targx, targy)
        set vecb = s_vector3d.createEx(targx, targy, GetLocationZ(thistype.p_sampleLoc))
        call r.doLaunch(vec, vecb, speed, pitchArc)
        call vec.destroy()
        call vecb.destroy()
        
        return r
    endmethod
endstruct

endlibrary

Last edited by TheKid : 03-04-2010 at 05:40 AM.
TheKid is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 03-03-2010, 12:12 AM   #2
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

#1: Use a single timer which iterates over every active projectile at once, instead of one timer per projectile. Just build a simple list in a static unit array, and iterate over it in a single timer callback. Much less overhead per projectile that way.

#2: onLoop is insanely slow. Virtual methods in vJass are insanely slow, so calling one n-times, many times a second is true madness.

#3: Vexorian had some magic script that calculated the collision size of units. You may wanna look in to that.
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils

Earth-Fury is offline   Reply With Quote
Old 03-03-2010, 12:40 AM   #3
TheKid
User
 
TheKid's Avatar
 
Join Date: Mar 2009
Posts: 195

TheKid will become famous soon enough (37)TheKid will become famous soon enough (37)

Default

Quote:
Originally Posted by Earth-Fury
#1: Use a single timer which iterates over every active projectile at once, instead of one timer per projectile. Just build a simple list in a static unit array, and iterate over it in a single timer callback. Much less overhead per projectile that way.

I have two versions. One that uses hashtables and multiple timers and another that uses a stack and a single timer. The one with hashtables seems to perform better.

Quote:
Originally Posted by Earth-Fury
Much less overhead per projectile that way.

It really doesn't make much difference in this situation. Its not like I'm running up thousands of projectiles (I wish).

Quote:
Originally Posted by Earth-Fury
#2: onLoop is insanely slow. Virtual methods in vJass are insanely slow, so calling one n-times, many times a second is true madness.

What do you mean "Virtual Methods"?

Quote:
Originally Posted by Earth-Fury
#3: Vexorian had some magic script that calculated the collision size of units. You may wanna look in to that.

Well if you enumerate units in a radius plus the maximum unit collision then you can use the function IsUnitInRangeXY to factor in collision. Its not magical, nor does it improve the performance of this system.
__________________

Last edited by TheKid : 03-03-2010 at 12:42 AM.
TheKid is offline   Reply With Quote
Old 03-03-2010, 01:24 AM   #4
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

Quote:
Originally Posted by TheKid
I have two versions. One that uses hashtables and multiple timers and another that uses a stack and a single timer. The one with hashtables seems to perform better.
Weird, as when I was doing physics simulation, multiple timers worked just aboot the same, if not worse.

Quote:
Originally Posted by TheKid
What do you mean "Virtual Methods"?

Interface methods (and stub methods) in vJass are virtual. When you instantiate (.create()) a class that extends from an interface, the lowest-order implementation of a virtual method is stored in a variable tied to the instance. (interface A has method Do, B extends A, C extends B. C.create() stores C's version of Do, as opposed to B's.) When the virtual method is invoked, the game has to dynamically invoke the function that was stored at creation using TriggerEvaluate(), which is VERY slow. (Why virtualization is implemented this way in vJass is a topic I'm too lazy to write aboot without being asked.)

Quote:
Originally Posted by TheKid
Well if you enumerate units in a radius plus the maximum unit collision then you can use the function IsUnitInRangeXY to factor in collision. Its not magical, nor does it improve the performance of this system.
I meant this.


---------------

Other things to note:

- Function calls in JASS (and thus vJass) are slow in the first place. Avoid them wherever possible. (JASS Helper inlines a few functions/methods, but it's inlining is very, very limited.)

- Using vector structs like that is very nice and clean, and also slower than using x/y/z members directly. It's up to you if the tradeoff in speed is worth making the code more complex.

There's probably 10 million more things I could say about writing optimized vJass/JASS code.
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils

Earth-Fury is offline   Reply With Quote
Old 03-03-2010, 01:33 AM   #5
TheKid
User
 
TheKid's Avatar
 
Join Date: Mar 2009
Posts: 195

TheKid will become famous soon enough (37)TheKid will become famous soon enough (37)

Default

Quote:
Originally Posted by Earth-Fury
Interface methods (and stub methods) in vJass are virtual. When you instantiate (.create()) a class that extends from an interface, the lowest-order implementation of a virtual method is stored in a variable tied to the instance. (interface A has method Do, B extends A, C extends B. C.create() stores C's version of Do, as opposed to B's.) When the virtual method is invoked, the game has to dynamically invoke the function that was stored at creation using TriggerEvaluate(), which is VERY slow. (Why virtualization is implemented this way in vJass is a topic I'm too lazy to write aboot without being asked.)

Okay, well despite the fact that it could possibly be slow it is the only way of achieving the functionality that I want.

Quote:
Originally Posted by Earth-Fury
I meant this.

Yea, that uses IsUnitInRangeXY. I have no real need of using a unit's collision-size anyways.

03 / 02 / 2010 (8:50)
It seems that as I create/destroy these projectiles, the memory usage on my computer goes up. I did some FPS tests and it seemed to always shoot back up to 64 after the projectiles had been destroyed, but it varies a lot depending on how many units are visible on the screen and other things.

Quote:
Originally Posted by Earth-Fury
Weird, as when I was doing physics simulation, multiple timers worked just aboot the same, if not worse.

Actually, now that I'm testing it again, the single timer seems to be working better. Much better. The hashtable is actually really slow. Weird because I swear when I was testing it before the hashtables were much quicker. I'm getting roughly 200 projectiles on a screen without any real lag issue. I still have to implement unit enumeration and projectile enumeration though, which will weigh a lot in terms of performance.

I will update the first post's code with the code used with a single-timer system.
__________________

Last edited by TheKid : 03-03-2010 at 03:12 AM.
TheKid is offline   Reply With Quote
Old 03-03-2010, 04:05 AM   #6
Kueken
User
 
Join Date: Mar 2009
Posts: 149

Kueken will become famous soon enough (41)Kueken will become famous soon enough (41)

Default

It should be the hashtable, which is slower than a stack. I tested running several thousands of timers, which seemed to have almost no effect on performance at all.

Also there was an article somewhere around here, which stated that multiple timers are actually better in the long run, because for 1 timer all callbacks concentrate on one interval, while for multiple timers, all callbacks are "smoothly" divided, while the performance loss of running multiple times is very insignificant.

For very many instances, one timer causes noticeable lag spikes and becomes unplayable earlier than multiple timers (at least thats what I read).

Last edited by Kueken : 03-03-2010 at 04:08 AM.
Kueken is offline   Reply With Quote
Old 03-03-2010, 05:09 AM   #7
TheKid
User
 
TheKid's Avatar
 
Join Date: Mar 2009
Posts: 195

TheKid will become famous soon enough (37)TheKid will become famous soon enough (37)

Default

Quote:
Originally Posted by Kueken
For very many instances, one timer causes noticeable lag spikes and becomes unplayable earlier than multiple timers (at least thats what I read).

I actually found now that using the stack yields better performance. I'm testing them both at the moment and the stack can handle 80 quite easily, while the hashtables start lagging. I hate how over-all inefficient JASS is... or at least object manipulation.

Just tested again (to make sure) and the single timer with a stack obliterates the multiple timers with a hashtable. I originally thought that the stack would be more efficient, so I coded it that way. After realizing that maybe using hashtables was the way to go, I made two versions so that I could compare them easily - I honestly thought hashtables would be much quicker : (
__________________

Last edited by TheKid : 03-03-2010 at 05:13 AM.
TheKid is offline   Reply With Quote
Old 03-03-2010, 02:28 PM   #8
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

One timer per instance is only sane to do with a method like timerutils... red?... (Initializing timers very early in map init so when you subtract the initial handle index from their GetHandleId() values, they fall below 8190 and thus can be used directly as array indexes, negating the need for hashtables.) That may spread the processing out a little bit better, but really, apples and apples at that point.

---------------

Let me stress again how slow onLoop is: It is around 7 times slower than a normal function call. Even if a projectile class does not implement the method, the overhead is _still_ there.

Really, really, if you need to be doing something every iteration, it should be part of the core system. If you just need to do something approximately every iteration, why can't it run on a separate timer and avoid the rape of virtualization? (You'd need to run one timer per type of projectile that needs something done per tick, but that shouldn't be too bad.)

-----------

Collapse JASS:
    // We don't want the projectile struct to leak so we need to remove it once its trajectory has completed.
    method onFinish takes nothing returns nothing
        call this.destroy()
    endmethod
I'm 99% sure parent virtual methods are _not_ called automatically from children's virtual methods.

-------------

If you're going to use vector classes, at least put them in to locals to reduce the overhead. (this. is an array access, p_currentPos. is another array access. By making a local "curPos" and placing p_currentPos in to it, you reduce the number of array accesses. Note that the overhead of allocating and initializing a local may dwarf the overhead of a few array accesses, so you have to be using a vector a significant number of times to warrant this.)

-------------

I would really, really suggest you remove the code that simulates projectiles from the projectile struct. It makes the code harder to follow by mixing an object's code with the code that deals with said objects. (Not at all an optimization, just a suggestion.)

-------------

Collapse JASS:
    method onCollision takes projectileinterface p returns nothing defaults nothing     //* When the projectile collides with another projectile (p = other projectile).

Why does it take projectileinterface instead of projectile? seems like you intend all concrete types to extend from projectile itself.

--------------

Collapse JASS:
if (hitDead == (IsUnitType(filt, UNIT_TYPE_DEAD) and GetUnitTypeId(filt)==0)) then
            set c=c+1
        endif
        if (hitEnemy == IsUnitEnemy(filt, GetOwningPlayer(this.toUnit))) then
            set c=c+1
        endif
        if (hitAllied == IsUnitAlly(filt, GetOwningPlayer(this.toUnit))) then
            set c=c+1
        endif
        if (hitStructure == IsUnitType(filt, UNIT_TYPE_STRUCTURE)) then
            set c=c+1
        endif
        if (c==4) then
            call this.onUnitCollision(filt)
        endif
It will be 100 times uglyer, but much faster if you condense all those conditions in to a single conditional.

Heck, even using a boolean and doing b = b and _____ would be faster, as "and" and "or" are short-circuit in JASS.

-----------------

As I said... 10 million more things.
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils

Earth-Fury is offline   Reply With Quote
Old 03-03-2010, 10:16 PM   #9
TheKid
User
 
TheKid's Avatar
 
Join Date: Mar 2009
Posts: 195

TheKid will become famous soon enough (37)TheKid will become famous soon enough (37)

Default

Quote:
Originally Posted by Earth-Fury
Why does it take projectileinterface instead of projectile? seems like you intend all concrete types to extend from projectile itself.

To be honest when I coded the interface right away knowing what functions I wanted (this is a re-write of code) and I must have used projectileinterface thinking that using projectile would have caused an error. After that point I completely overlooked it.

Quote:
Originally Posted by Earth-Fury
Let me stress again how slow onLoop is: It is around 7 times slower than a normal function call. Even if a projectile class does not implement the method, the overhead is _still_ there.

What exactly is the point of inheritance if it sucks.

More coming. Just having a smoke.

Quote:
Originally Posted by Earth-Fury
If you're going to use vector classes, at least put them in to locals to reduce the overhead. (this. is an array access, p_currentPos. is another array access. By making a local "curPos" and placing p_currentPos in to it, you reduce the number of array accesses. Note that the overhead of allocating and initializing a local may dwarf the overhead of a few array accesses, so you have to be using a vector a significant number of times to warrant this.)

Collapse JASS:
                // Scale the added acceleration based on the time-scale of the projectile.
                set this.p_currentVelocity.x = this.p_currentVelocity.x+(this.p_currentAcceleration.x*this.timescale*this.timescale)
                set this.p_currentVelocity.y = this.p_currentVelocity.y+(this.p_currentAcceleration.y*this.timescale*this.timescale)
                set this.p_currentVelocity.z = this.p_currentVelocity.z+(this.p_currentAcceleration.z*this.timescale*this.timescale)
                
                // Scale the added velocity (to position) based on time-scale.
                set this.p_currentPos.x = this.p_currentPos.x+(this.p_currentVelocity.x*this.timescale)
                set this.p_currentPos.y = this.p_currentPos.y+(this.p_currentVelocity.y*this.timescale)
                set this.p_currentPos.z = this.p_currentPos.z+(this.p_currentVelocity.z*this.timescale)

So you think I should do something like:

Collapse JASS:
                set vec1 = this.p_currentVelocity
                set vec2 = this.p_currentAcceleration
                // Scale the added acceleration based on the time-scale of the projectile.
                set vec1.x = vec1.x+(vec2.x*this.timescale*this.timescale)
                set vec1.y = vec1.y+(vec2.y*this.timescale*this.timescale)
                set vec1.z = vec1.z+(vec2.z*this.timescale*this.timescale)
                
                set vec2 = this.p_currentPos
                // Scale the added velocity (to position) based on time-scale.
                set vec2.x = vec2.x+(vec1.x*this.timescale)
                set vec2.y = vec2.y+(vec1.y*this.timescale)
                set vec2.z = vec2.z+(vec1.z*this.timescale)

Quote:
Originally Posted by Earth-Fury
I would really, really suggest you remove the code that simulates projectiles from the projectile struct. It makes the code harder to follow by mixing an object's code with the code that deals with said objects. (Not at all an optimization, just a suggestion.)

What exactly do you mean?

Also I suppose if I'm doing that I should remove the onLoop from the interface so that users can only access the projectile methods on certain events (finished, started, etc.).

Quote:
Originally Posted by Earth-Fury
if (hitDead == (IsUnitType(filt, UNIT_TYPE_DEAD) and GetUnitTypeId(filt)==0)) then
set c=c+1
endif
if (hitEnemy == IsUnitEnemy(filt, GetOwningPlayer(this.toUnit))) then
set c=c+1
endif
if (hitAllied == IsUnitAlly(filt, GetOwningPlayer(this.toUnit))) then
set c=c+1
endif
if (hitStructure == IsUnitType(filt, UNIT_TYPE_STRUCTURE)) then
set c=c+1
endif
if (c==4) then
call this.onUnitCollision(filt)
endif

This is an idea in development, I'm not really sure where I'm going to go with it.

You think I should do this?

Collapse JASS:
        // .onUnitCollision is only called if a valid target is struck.
        if (hitDead==IsUnitType(filt, UNIT_TYPE_DEAD) and GetUnitTypeId(filt)==0) and (hitEnemy==IsUnitEnemy(filt, GetOwningPlayer(this.toUnit))) and (hitAllied==IsUnitAlly(filt, GetOwningPlayer(this.toUnit))) and (hitStructure==IsUnitType(filt, UNIT_TYPE_STRUCTURE)) then
            call this.onUnitCollision(filt)
        endif
__________________

Last edited by TheKid : 03-03-2010 at 10:38 PM.
TheKid is offline   Reply With Quote
Old 03-03-2010, 10:26 PM   #10
Kueken
User
 
Join Date: Mar 2009
Posts: 149

Kueken will become famous soon enough (41)Kueken will become famous soon enough (41)

Default

There was some trick using delimited comments to create multi-line oneliners:

Collapse JASS:
    if    hitDead      == IsUnitType   (filt, UNIT_TYPE_DEAD)               /*
    */and 0            == GetUnitTypeId(filt)                               /*
    */and hitEnemy     == IsUnitEnemy  (filt, GetOwningPlayer(this.toUnit)) /*
    */and hitAllied    == IsUnitAlly   (filt, GetOwningPlayer(this.toUnit)) /*
    */and hitStructure == IsUnitType   (filt, UNIT_TYPE_STRUCTURE)          then
        call this.onUnitCollision(filt)
    endif

Still pretty ugly, but as fast as one line and at least looks a little better (since it gets compiled to one line I assume)
€ just tested and seems to compile :)

€2 :-* @ rep, sorry but I have no idea how to manipulate tesh, never tried that

Last edited by Kueken : 03-03-2010 at 11:12 PM.
Kueken is offline   Reply With Quote
Old 03-03-2010, 10:57 PM   #11
TheKid
User
 
TheKid's Avatar
 
Join Date: Mar 2009
Posts: 195

TheKid will become famous soon enough (37)TheKid will become famous soon enough (37)

Default

I'm going to rep you for that. That makes it so much neater. By the way, is there any way of changing the color of delimited comments with TESH (the recent one, with cJass implemented). Right now I use a darker background and the green comments just looks U-G-L-Y.

Lol, ftw!

Collapse JASS:
        if (hitDead==IsUnitType(filt, UNIT_TYPE_DEAD)                       /*
        */and GetUnitTypeId(filt)==0)                                       /*
        */and (hitEnemy==IsUnitEnemy(filt, GetOwningPlayer(this.toUnit)))   /*
        */and (hitAllied==IsUnitAlly(filt, GetOwningPlayer(this.toUnit)))   /*
        */and (hitStructure==IsUnitType(filt, UNIT_TYPE_STRUCTURE))         then
        
            call this.onUnitCollision(filt)
        endif

This is one of the best uses of delimiting comments I've found yet (of course sometimes I avoid their ugly hulkish charm).
__________________

Last edited by TheKid : 03-03-2010 at 11:00 PM.
TheKid is offline   Reply With Quote
Old 03-03-2010, 11:49 PM   #12
Earth-Fury
Two Blue
 
Earth-Fury's Avatar
 
Join Date: Mar 2003
Posts: 2,179

Submissions (7)

Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)Earth-Fury is just really nice (343)

Send a message via MSN to Earth-Fury
Default

Quote:
Originally Posted by TheKid
What exactly is the point of inheritance if it sucks.
It's not that slow if you're not using it too often time-wise. What is slow is spamming it as much as onLoop does, considering it's really needless as you can avoid the virtualization overhead by just running such events in a different timer in whatever library actually needs it.


Quote:
Originally Posted by TheKid
Collapse JASS:
                // Scale the added acceleration based on the time-scale of the projectile.
                set this.p_currentVelocity.x = this.p_currentVelocity.x+(this.p_currentAcceleration.x*this.timescale*this.timescale)
                set this.p_currentVelocity.y = this.p_currentVelocity.y+(this.p_currentAcceleration.y*this.timescale*this.timescale)
                set this.p_currentVelocity.z = this.p_currentVelocity.z+(this.p_currentAcceleration.z*this.timescale*this.timescale)
                
                // Scale the added velocity (to position) based on time-scale.
                set this.p_currentPos.x = this.p_currentPos.x+(this.p_currentVelocity.x*this.timescale)
                set this.p_currentPos.y = this.p_currentPos.y+(this.p_currentVelocity.y*this.timescale)
                set this.p_currentPos.z = this.p_currentPos.z+(this.p_currentVelocity.z*this.timescale)

So you think I should do something like:

Collapse JASS:
                set vec1 = this.p_currentVelocity
                set vec2 = this.p_currentAcceleration
                // Scale the added acceleration based on the time-scale of the projectile.
                set vec1.x = vec1.x+(vec2.x*this.timescale*this.timescale)
                set vec1.y = vec1.y+(vec2.y*this.timescale*this.timescale)
                set vec1.z = vec1.z+(vec2.z*this.timescale*this.timescale)
                
                set vec2 = this.p_currentPos
                // Scale the added velocity (to position) based on time-scale.
                set vec2.x = vec2.x+(vec1.x*this.timescale)
                set vec2.y = vec2.y+(vec1.y*this.timescale)
                set vec2.z = vec2.z+(vec1.z*this.timescale)

Yes. You may also wanna put timescale in a local considering how many times it's referenced. Mind you, it's still possible that the overhead of the locals is more than the overhead of the array accesses . compiles to. I doubt it in this case, though.

Quote:
Originally Posted by TheKid
What exactly do you mean?

Right now, all of your code is in one struct. What I suggest is splitting the code in two: Put the static timer loop callback as a function, and split out some other code (e.g., the stack of projectiles in to globals instead of static members) to help separate the what (a projectile) from the how (move it like a projectile should move). That should help in maintenance and in other people reading it. Just my opinion, of course.

Quote:
Originally Posted by TheKid
You think I should do this?

Collapse JASS:
        // .onUnitCollision is only called if a valid target is struck.
        if (hitDead==IsUnitType(filt, UNIT_TYPE_DEAD) and GetUnitTypeId(filt)==0) and (hitEnemy==IsUnitEnemy(filt, GetOwningPlayer(this.toUnit))) and (hitAllied==IsUnitAlly(filt, GetOwningPlayer(this.toUnit))) and (hitStructure==IsUnitType(filt, UNIT_TYPE_STRUCTURE)) then
            call this.onUnitCollision(filt)
        endif
Yes. Also, using delimited comments like that makes baby jesus cry. Of course, lines that long make baby jesus cry too, so apples and apples.
__________________
Useful Links:
My Resources:
Good Resources:
Search
Tutorials
Ability Guide

UnitMaxState
BonusMod

AutoIndex
ARGB
TimerUtils

Earth-Fury is offline   Reply With Quote
Old 03-04-2010, 02:50 AM   #13
TheKid
User
 
TheKid's Avatar
 
Join Date: Mar 2009
Posts: 195

TheKid will become famous soon enough (37)TheKid will become famous soon enough (37)

Default

Okay. Now, well at the moment I'm content with the amount of projectiles that this can handle at a time (around 200 on a single screen, I'm sure if they were separated over map it would increase a little). They are capable of being efficiently created/destroying (lots of short life-spans) but they currently lack the functionality of .onCollision and .onUnitCollision.

Quote:
Originally Posted by Earth-Fury
Right now, all of your code is in one struct. What I suggest is splitting the code in two: Put the static timer loop callback as a function, and split out some other code (e.g., the stack of projectiles in to globals instead of static members) to help separate the what (a projectile) from the how (move it like a projectile should move). That should help in maintenance and in other people reading it. Just my opinion, of course.

I will try to split it up a little better (this is just the second re-write, the first version was lame) in my next version. I really would like some tips on doing the nearby unit/projectile enumeration though.
__________________
TheKid is offline   Reply With Quote
Old 03-04-2010, 03:09 AM   #14
Saishy
User
 
Saishy's Avatar
 
Join Date: May 2008
Posts: 136

Saishy has little to show at this moment (6)

Default

It would be good if your projectiles could destroy trees in a efficient way.
__________________
Map: Anime Brawl
Terrain: IIIIIIIIII
Triggers: IIIIIIIIII
Heroes: IIIIIIIIII
Spells/Items: IIIIIIIIII
Until Beta: IIIIIIIIII
Saishy is offline   Reply With Quote
Old 03-04-2010, 03:30 AM   #15
TheKid
User
 
TheKid's Avatar
 
Join Date: Mar 2009
Posts: 195

TheKid will become famous soon enough (37)TheKid will become famous soon enough (37)

Default

They have to be enumerated separately, so I suppose they'd be methods:

Collapse JASS:
method onDestructableCollision takes destructable d returns nothing
method onItemCollision takes item i returns nothing

If I'm going to add destructables, I might as well include all of the widgets. Though, these features require lots of enumerations which can lag the game.

Doesn't the SEE engine have collision detection?
__________________

Last edited by TheKid : 03-04-2010 at 03:32 AM.
TheKid is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 01:26 PM.


Affiliates
The Hubb The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services