| 05-15-2009, 01:58 AM | #1 |
Hey, Does anyone know of a tutorial or such that explains how to make units slide on ice? Or does anyone know how to do it? Thanks |
| 05-15-2009, 07:18 AM | #2 |
Perhaps this is what you're searching for.. http://www.3ice.hu/blog/3ice-sliding-system-for-roc-v3/ |
| 05-15-2009, 09:09 AM | #3 |
there are several ways... i would do a custom unit movement system and do reduced friction on ice =) for example... it's also possible just do a triggered movement when you enter such area. (like in most cases it's done) |
| 05-15-2009, 12:37 PM | #4 |
Made this a while ago but got a bit tired of it. You can have it if you want: Object (requires UnitIndexingUtils):library Object initializer Init requires UnitIndexingUtils globals private constant real TIMEOUT = 0.03 private constant real FRICTION = 50 private object array O private integer NO = 0 object array UO endglobals struct object integer n real m real x real y real vx = 0 real vy = 0 // indicators unit u static method create takes real x, real y, real m, integer uid, player p returns object local object o = object.allocate() local integer z set o.m = m set o.x = x set o.y = y set O[NO] = o set o.n = NO set NO = NO+1 // indicators set o.u = CreateUnit(p, uid, x, y, 0) set z = GetUnitId(o.u) set UO[z] = o return o endmethod method onDestroy takes nothing returns nothing set NO = NO-1 set O[.n] = O[NO] set .n = NO call ReleaseUnitId(.u) call RemoveUnit(.u) endmethod endstruct function UnitIsObject takes unit u returns boolean return UO[GetUnitId(u)].u == u endfunction private function TimerActions takes nothing returns nothing local integer i = 0 local real a local real v local real vx local real vy loop exitwhen i == NO // friction set v = TIMEOUT * FRICTION / SquareRoot(O[i].vx*O[i].vx + O[i].vy*O[i].vy) set O[i].vx = O[i].vx - O[i].vx * v set O[i].vy = O[i].vy - O[i].vy * v // movement set O[i].x = O[i].x + O[i].vx * TIMEOUT set O[i].y = O[i].y + O[i].vy * TIMEOUT call SetUnitPosition(O[i].u, O[i].x, O[i].y) set i = i+1 endloop endfunction private function Init takes nothing returns nothing local timer t = CreateTimer() call TimerStart(t, TIMEOUT, true, function TimerActions) endfunction endlibrary Step:scope Step initializer Init private function Conditions takes nothing returns boolean return UnitIsObject(GetFilterUnit()) endfunction private function Actions takes nothing returns nothing local unit u = GetTriggerUnit() local real a = Atan2(GetOrderPointY()-GetUnitY(u), GetOrderPointX()-GetUnitX(u)) local integer z = GetUnitId(u) call SetUnitFacing(u, bj_RADTODEG*a) set UO[z].vx = UO[z].vx + Cos(a) * 100 set UO[z].vy = UO[z].vy + Sin(a) * 100 endfunction private function Init takes nothing returns nothing local trigger trig = CreateTrigger() call TriggerRegisterPlayerUnitEvent(trig, Player(0), EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, Condition(function Conditions)) call TriggerAddAction(trig, function Actions) endfunction endscope Not sure if it's the most efficient way to do it but it surely gets the job done. |
| 05-15-2009, 06:21 PM | #5 |
i'd class sliding as an extension of some physics/vector/whatever system, but the common method implemented in maps ive played with this concept - and i assume that this is what youre looking for - just involves just noting when a unit steps on (a) particular type(s) of tileset(s) that correspond to ice and moving it until it is no longer on ice a la Are You A Retard, Area of *Whatever* Escape, etc. so, know when a unit is on ice and move it as it is so. you can have units as a subject and monitor them, checking if they are on ice; or you can have icy regions as a subject and monitor then, checking when units are on them. the latter case affords A) TriggerRegisterEnterWhatever() and TriggerRegisterEnterLeaveWhatever(), which i think is convenient, since the alternative monitoring method - also for the case with units as subjects - would probably involve B) checking-up on the subject regularly in time, w/c seems like a hassle - i don't know if this regular checkup is really bad tho maybe ask someone who knows more than i do. if you go for A), then you must register icy areas and setup the trigger for them; consider the registration/unregistration 'dynamic' (if thats the correct word) icy areas if your map creates and destroys them throughout the game. if you go for B) method then i'd use just 1 timer that iterates through every (contingent) unit. then for moving youd probably wanna do it differentially with respect to time so id use a timer to run the move function for every sliding unit (registered by A) or B)). if you go for A) then you'd need to checkup regularly on all sliding units, checking if they are no longer on ice. this can be done w/ the same timer used in the moving part, perhaps, since the moving part is necessarily simultaneous with this checkup. if you go for B) then just use TriggerRegisterLeaveRegion to check when a (registered) sliding unit leaves a (registered) ice area (as a region) then unregister it as a sliding unit. but maybe there are better alternative methods i oversaw/didnt consider |
