HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Starting a physics engine

06-16-2008, 10:52 PM#1
Feroc1ty
Yeah, I am thinking of creating an object oriented physics engine, but I have NO idea where to even start, and couldn't find any functions which find the units Z axis, except unit flying height, is that the same thing as the unit's Z location? So, if anyone could head me the right way, I would high appreciate that. I don't need any example scripts, just a basic outline of what I would have to do, which wouldn't need to be longer than a few lines. What I was thinking of creating was a single physics group, which would be affected by a timer, which would check objects velocity, move the object accordingly, change the units parameters (etc: change velocity, height, location, etc), and repeat.
06-16-2008, 10:54 PM#2
the-thingy
For a unit's Z, its unit's flying height + Z of units location I believe

That's about all I can help with though, I've never done physics :|

EDIT: Ah, found it
Collapse JASS:
function GetUnitZ takes unit u returns real
    local real x = GetUnitX (u)
    local real y = GetUnitY (u)
    call MoveLocation (temploc, x, y)
    return GetLocationZ (temploc) + GetUnitFlyHeight (u)
endfunction
06-16-2008, 11:10 PM#3
Anitarf
But wouldn't you have the z position of the unit stored somewhere along with other information (like speed etc) thus you wouldn't need to get it from the unit itself?
06-17-2008, 04:09 AM#4
Strilanc
Anitarf is right: you shouldn't be reading unit properties, you should be setting them. The only physics-related values you should be reading from the game are terrain height and user input. Divorce the physics from the game as much as possible.
06-17-2008, 06:35 PM#5
Feroc1ty
Okay, I ran into one problem. I really can't think of a way to find out what objects have been created, or how to call them in the timer. Can any genius think of a way around this, or any vague suggestions that could possibly just head me the right direction?

Collapse JASS:
globals
    group phys
endglobals

function update takes nothing returns nothing
    
endfunction

function periodic takes nothing returns nothing
    call ForGroup( phys, function update)
endfunction

function GetZ takes real X, real Y returns real
    local location L = Location(X,Y)
    local real R = GetLocationZ(L)
    call RemoveLocation(L)
    return R
endfunction

struct Ball
    real x
    real y
    real z
    real direction
    real velocity
    real resistance
    real weight
    boolean acceleration
    unit sphere
    
    method initialize takes player p, real x, real y, real z, real direction, real velocity, real resistance, real weight returns nothing
        local real fh = GetZ(x,y)
        set fh = fh - z
        set this.sphere = CreateUnit(p, 'hdhw', x, y, direction)
        call SetUnitFlyHeight(this.sphere, fh, 9999)
    endmethod
    
    method onDestroy takes nothing returns nothing
        call RemoveUnit(this.sphere)
        set this.sphere = null
    endmethod
    
endstruct

function PhysInitialize takes integer miliseconds returns nothing
    local timer t = CreateTimer()
    local real i = miliseconds / 1000
    call TimerStart(t, i, true, function periodic)
endfunction
06-17-2008, 09:23 PM#6
Themerion
Unit enters playable map area?

Unit decays? (Well, would probably be better to use PUI and alter it, since PUI also detects units which doesn't decay and Removed Units)
06-17-2008, 09:53 PM#7
Feroc1ty
Bah, I figured out a way to manage objects, but it would require a struct that's an array though, I was wondering if that was possible. I was thinking of something like this, or I shall have to wait till you can have variable arrays inside of structs.

Collapse JASS:
struct a
    real x
    real y
    real z
endstruct

struct b
  local a array i = a.array.create()
endstruct

06-17-2008, 10:00 PM#8
Themerion
Having arrays inside structs for a physics engine... naaah. :P

I'm still not quite sure what you want to do...

This?

Collapse JASS:
 // Get struct from unit?

local Ball b=Ball.create(lots,of,arguments)
call SetUnitUserData(u,b)

// Later ...

function update takes nothing returns nothing
    local Ball b =GetUnitUserData(u)
  // Do stuff with b...
endfunction

Or this?

Collapse JASS:
// Loop through structs?

struct Data
    Data next
endstruct

function Loop
    local Data d=myFirstDataPosition
    loop
         exitwhen d==null
         // Do stuff with d...
         set d=d.next
    endloop
endfunction

Or something completely different?
06-18-2008, 02:21 AM#9
grim001
just make a struct array...

Collapse JASS:
globals
    data array datas
endglobals
06-18-2008, 04:15 AM#10
Feroc1ty
Quote:
Originally Posted by grim001
just make a struct array...

Collapse JASS:
globals
    data array datas
endglobals

Just what I needed, thanks.

EDIT: Getting an error.
"Undeclared variable spheres"
set s__data_number[s___Ball_sphere[s__Ball_sphere[this]+s__Ball_spheres[this]]]=spheres

Collapse JASS:
unction GetHeight takes real X, real Y returns real
    local location L = Location(X,Y)
    local real R = GetLocationZ(L)
    call RemoveLocation(L)
    return R
endfunction

function GetSlantNS takes real X, real Y returns real
    local real Z = GetHeight(X,Y)
    local real Z2 = GetHeight(X,Y+1)
    local real D = Z2 - Z
    return D
endfunction

function GetSlantEW takes real X, real Y returns real
    local real Z = GetHeight(X,Y)
    local real Z2 = GetHeight(X+1,Y)
    local real D = Z2 - Z
    return D
endfunction

globals
    group phys
endglobals

function update takes nothing returns nothing
    
endfunction

function periodic takes nothing returns nothing
    call ForGroup( phys, function update)
endfunction

struct data
    integer number
    real x
    real y
    real z
    real direction
    real velocity
    real resistance
    real weight
    boolean accelerating
    unit sphere
endstruct

struct Ball
    data array sphere [32]
    integer spheres = 0
    
    method initialize takes player p, real x, real y, real z, real direction, real velocity, real resistance, real weight returns nothing
        local real fh = GetHeight(x,y)
        set this.spheres = this.spheres + 1
        set this.sphere[this.spheres].number = spheres
        set fh = fh - z
        set this.sphere[this.spheres].sphere = CreateUnit(p, 'hdhw', x, y, direction)
        call SetUnitFlyHeight(this.sphere[this.spheres].sphere, fh, 9999)
    endmethod
    
    method onDestroy takes nothing returns nothing
        call RemoveUnit(this.sphere[this.spheres].sphere)
        set this.sphere[this.spheres].sphere = null
    endmethod
    
endstruct

function PhysInitialize takes integer miliseconds returns nothing
    local timer t = CreateTimer()
    local real i = miliseconds / 1000
    call TimerStart(t, i, true, function periodic)
endfunction
06-18-2008, 10:50 AM#11
Anitarf
What the heck are you trying to do in there? (btw your problem is obvious, it should be this.spheres, not spheres)

Anyway, why would each ball have 32 spheres? You only need a ball, that's it.

Collapse JASS:
globals
    private ball array balls
    private integer numberOfBalls=0
endglobals

function UpdateBalls takes nothing returns nothing
    local integer i=0
    loop
        exitwhen i>=numberOfBalls

        //do stuff with balls[i] here.

        set i=i+1
    endloop
endfunction

struct ball
    vector position
    vector velocity
    ...
    unit u

    integer ballnum

    static method create takes real x, real y,... returns ball
        local ball b = ball.allocate()
        set b.position = vector.create(x,y,z)
        set b.velocity = ...
        ...
        set b.u = CreateUnit(...)
        call UnitAddAbility(b.u, 'Amrf') //make it possible to change unit's fly height
        call UnitRemoveAbility(b.u, 'Amrf')

        set balls[numberOfBalls]=b
        set b.ballnum=numberOfBalls
        set numberOfBalls=numberOfBalls+1
        return b
    endmethod

    method onDestroy takes nothing returns nothing
        call this.position.destroy()
        call this.velocity.destroy()
        ...
        call KillUnit(this.u)

        set numberOfBalls=numberOfBalls-1
        set balls[this.ballnum]=balls[numberOfBalls]
        set balls[this.ballnum].ballnum=this.ballnum
    endmethod
endstruct
06-18-2008, 06:10 PM#12
Feroc1ty
Don't worry bout it guys, decided I was not going to make a system, but simply make a sphere class.
06-19-2008, 05:54 AM#13
Spec
Jokes-on-you, I think, this is better than your current function:
Collapse JASS:
globals
    private location L = Location(0, 0)
endglobals
// ...
function GetHeight takes real X, real Y returns real
    call MoveLocation(L, X, Y)
    return GetLocationZ(L)
endfunction

Anitarf, is static variable in struct better? I mean that:
Collapse JASS:
struct ball
    static integer i = 0x00
    // ball params

    static method create takes <params> returns ball
        local ball b = ball.allocate()
        // ...
        if integer(b) > ball.i then
            set ball.i = integer(b)
        endif
        return b
    endmethod

    method onDestroy takes nothing returns ball
        // ...
        if integer(this) == ball.i then
            set ball.i = ball.i - 0x01
        endif
        set this = 0x00
    endmethod
    // ...
endstruct
moyack wrote some article about periodic spell effects, and gave example of static var usage instead of "traditional" array and counter vars usage, I think, that could be useful here.
06-19-2008, 10:57 AM#14
Anitarf
It's better for organisational purposes, I just haven't gotten used to using it yet, thanks for reminding me.
06-20-2008, 08:46 AM#15
Feroc1ty
I was wondering, can you call a method with a timer, because it's not allowing me.