ID:891374
 
(See the best response by Kaiochao.)
Code:
obj/_projectile
density = 1
var
mob/owner
base_damage
max_damage
damage
crit_probability
//////////////////////////////////////////////////////////////////////
default_while = 1
angle
vel_x //vector angle calculations
vel_y
acc_x = 0 //acceleration
acc_y = 0
x_init = 0 //initial position
y_init = 0
x_offset = 0
y_offset = 0
vel_multiplier = 8
direction
move_counter
move_limit

//The following is treated as if you're facing north initially with passed values and such
New(mob/o, _angle, _acc_x, _acc_y) //input angle upon owner's direction upon creation
owner = o
direction = owner.dir
angle = _angle //should be 0 to 180
acc_x = _acc_x
acc_y = _acc_y
var/own_bh = round(owner.bound_height/2)
var/own_bw = round(owner.bound_width/2)
var/bh = round(bound_height/2)
var/bw = round(bound_width/2)

y_init = owner.step_y + own_bh - bh
x_init = owner.step_x + own_bw - bw

switch(direction) //we need to alter acceleration here, too
if(NORTH)
y_init += own_bh //

if(SOUTH)
angle += 180

y_init += -own_bh //later issues could come from subtracting a negative
y_offset = -y_offset

acc_x = -acc_x
acc_y = -acc_y

if(EAST || SOUTHEAST || NORTHEAST)
angle -= 90

x_init += own_bw

x_offset += y_offset //swap values
y_offset = x_offset - y_offset
x_offset -= y_offset

acc_x += acc_y //swap values
acc_y = acc_x - acc_y
acc_x -= acc_y

if(WEST || SOUTHWEST || NORTHWEST)
angle += 90

x_init += -own_bw //later issues could come from subtracting a negative

x_offset += y_offset //swap values
y_offset = x_offset - y_offset
x_offset -= y_offset

x_offset = -x_offset //reverse x_offset

acc_x += acc_y //swap values
acc_y = acc_x - acc_y
acc_x -= acc_y

acc_x = -acc_x //reverse acc_x

vel_x = cos(angle) * vel_multiplier //velocity in the X direction
vel_y = sin(angle) * vel_multiplier //velocity in the Y direction

Create()

//this would be the start of a new proc called Create() once testing is complete
proc/Create()
loc = owner.loc

step_x = x_init + x_offset
step_y = y_init + y_offset

if(default_while)
while(src)
move_counter ++
if(move_counter > move_limit)
del src
sleep(world.tick_lag)

// shift the position by the velocity vector
step_x += vel_x + acc_x
step_y += vel_y + acc_y

// shift the velocity vector by the acceleration vector
// vel_x += acc_x
// vel_y += acc_y

fireball
density = 1
icon = 'fireball_test.dmi'
bound_width = 16
bound_height = 16
y_offset = 10
vel_multiplier = 3
move_limit = 999


Problem description:

No matter what I do, when I create one of these projectiles, their bounding boxes are not functioning. They go through everything and exit the map. I'm not sure what the problem is here. I've tried changing them to mobs. I've tried using the Cross() proc but nothing is picked up.

(Note that I am NOT using Forum_Account's Pixel Movement)

Collision is only detected automatically when you use Move() to move objects. That includes procedures like step(), which use Move().

Otherwise, you'll have to do obounds() to search for dense things, but that gets complicated and doesn't take advantage of the built-in pixel movement support (it's a lot of pre-native-pixel-movement calculation that not many people are used to).

Also, vel_multiplier is also called "speed".
In response to Kaiochao (#1)
I understand what you're saying, but why isn't it as simple as this:

                // shift the position by the velocity vector
step_x += vel_x + acc_x
step_y += vel_y + acc_y

Move(src, dir, step_x, step_y)


Because I thought it would be, but of course it doesn't work =( .
In response to Cloud Magic (#2)
Best response
Objects don't bump into things they're already inside of. That's probably something important that you need to know.

So instead, you could try this:
Move(loc, dir, step_x + vel_x + acc_x, step_y + vel_y + acc_y)


Also, I really don't want to know what you're doing at all; I don't feel like reading any of your code. Acceleration is added to velocity each tick, and velocity is added to position each tick. That's pretty much how basic "motion physics" goes in games.
//  e.g.
tick() // called each tick for every physics mover
vel_x += accel_x
vel_y += accel_y
pos_x += vel_x
pos_y += vel_y
In response to Cloud Magic (#2)
Cloud Magic wrote:
I understand what you're saying, but why isn't it as simple as this:

>               // shift the position by the velocity vector
> step_x += vel_x + acc_x
> step_y += vel_y + acc_y
>
> Move(src, dir, step_x, step_y)


Because I thought it would be, but of course it doesn't work =( .

This would work, if you used variables for the first 2 lines instead of modifying step_x and step_y, because those update automatically.
Well, I tried changing to using the Move() method and I have to say, the projectiles are now coming out very buggy and insanely fast. They stop at map boundaries, but as far as mobs go, they seem to move right through them.

Here is the updated code:

obj/_projectile
density = 1
var
mob/owner
base_damage
max_damage
damage
crit_probability
//////////////////////////////////////////////////////////////////////
default_while = 1
angle
vel_x //vector angle calculations
vel_y
pos_x //locations
pos_y
acc_x = 0 //acceleration
acc_y = 0
x_init = 0 //initial position
y_init = 0
x_offset = 0 //starter offset
y_offset = 0
vel_multiplier = 2 //speed
direction
move_counter
move_limit

//The following is treated as if you're facing north initially with passed values and such
New(mob/o, _angle, _acc_x, _acc_y) //input angle upon owner's direction upon creation
owner = o
direction = owner.dir
angle = _angle //should be 0 to 180
acc_x = _acc_x
acc_y = _acc_y
var/own_bh = round(owner.bound_height/2)
var/own_bw = round(owner.bound_width/2)
var/bh = round(bound_height/2)
var/bw = round(bound_width/2)

y_init = owner.step_y + own_bh - bh
x_init = owner.step_x + own_bw - bw

switch(direction) //we need to alter acceleration here, too
if(NORTH)
y_init += own_bh //

if(SOUTH)
angle += 180

y_init += -own_bh
y_offset = -y_offset

acc_x = -acc_x
acc_y = -acc_y

if(EAST || SOUTHEAST || NORTHEAST)
angle -= 90

x_init += own_bw

x_offset += y_offset //swap values
y_offset = x_offset - y_offset
x_offset -= y_offset

acc_x += acc_y //swap values
acc_y = acc_x - acc_y
acc_x -= acc_y

if(WEST || SOUTHWEST || NORTHWEST)
angle += 90

x_init += -own_bw

x_offset += y_offset //swap values
y_offset = x_offset - y_offset
x_offset -= y_offset

x_offset = -x_offset //reverse x_offset

acc_x += acc_y //swap values
acc_y = acc_x - acc_y
acc_x -= acc_y

acc_x = -acc_x //reverse acc_x

vel_x = cos(angle) * vel_multiplier //velocity in the X direction
vel_y = sin(angle) * vel_multiplier //velocity in the Y direction

Create()

//this would be the start of a new proc called Create() once testing is complete
proc/Create()
loc = owner.loc

//step_x = x_init + x_offset
//step_y = y_init + y_offset

Move(loc, dir, x_init + x_offset, y_init + y_offset)




if(default_while)
while(src)
sleep(world.tick_lag)
move_counter ++
if(move_counter > move_limit)
del src
//

// shift the position by the velocity vector
//step_x += vel_x + acc_x
//step_y += vel_y + acc_y
pos_x += vel_x + acc_x
pos_y += vel_y + acc_y

Move(src.loc, dir, pos_x, pos_y)


// shift the velocity vector by the acceleration vector
// vel_x += acc_x
// vel_y += acc_y

fireball
density = 1
icon = 'fireball_test.dmi'
bound_width = 16
bound_height = 16
y_offset = 10
vel_multiplier = 1
move_limit = 999


Note that when using step_x and step_y, as I did above, this system is working perfectly smooth.
You probably want to set pos_x and pos_y to their step_x and step_y after moving them.
In response to Albro1 (#6)
Wow...I'm not sure why, but your suggestion worked!!!
In response to Cloud Magic (#5)
It's because step_x and step_y are your pixel position on the current tile. As such, they only go from 0-32. So, if pos_x is 46 and you add 4, you're going to move 50 pixels.