ID:144334
 
Hokai, so here is my vector-movement pixel engine, it's like a major hybrid off of Theodis' Alt Move Demo, 'cause I learnt most of my pixel stuff from him - anywho, my system has a major flaw... whenever you try to take some large turnings it likes to be a bitch - I need to sorta speed it up a little and remove the bugs where it doesn't end up turning the way you need fast enough - you'll see if you try it - or for the gurus, you'll see when you look at it. It's mostly commented.

Code:
#define NUM_SHIP_IMAGES     90
#define TURN_RATE 5
#define MAX_VELOCITY 200
#define ACCELERATION 5
#define TILE_RADIUS 100

var
ShipIcon[]
Ships[]

world
New()
var/icon/pi
var/i
ShipIcon = new /list()
Ships = new /list()
for(i = 1; i < NUM_SHIP_IMAGES + 1; i++)
pi = new('Ships.dmi')
pi.Turn(360/NUM_SHIP_IMAGES*(i-1))
ShipIcon.Add(pi)
spawn()
MoveShips()
return ..()
proc
MoveShips()
var/atom/movable/M
for(M in Ships)
M.MoveForward()

spawn(1)
MoveShips()

atom/movable
icon ='Ships.dmi'
animate_movement = NO_STEPS

var

accelerating = 0 //The current state of accleration
thrust_angle = 0 //The current heading of the atom
ship_angle = 0 //The current angle the atom is pointing
velocity = 0 //The current velocity of the atom
dx = 0 //The current delta X (or change in X per tick) of the atom
dy = 0 //The current delta Y (or change in Y per tick) of the atom
icon_int //The intial icon of the atom pointing north


New(loc)
Ships += src // Add the new mob to the players list so that the mob can move
..(loc)
src.icon_int = src.icon // Give it the base icon so that it can use something to determine the rotation icon from.


proc
Accelerate()
//Determine the current vectors
var/cdx = sin(thrust_angle) * velocity
var/cdy = cos(thrust_angle) * velocity

//Determine the change in vectors
var/ddx = sin(ship_angle)
var/ddy = cos(ship_angle)

//determine the new vectors
cdx+=ddx
cdy+=ddy

//determine the new velocity and heading
velocity = sqrt(cdx*cdx + cdy*cdy)
velocity = round(velocity+0.5)
if(velocity <= 0)
velocity = 0
thrust_angle = ship_angle
else if(cdx < 0 && cdy >= 0)
thrust_angle = arcsin(cdx/velocity)
else if(cdx < 0 && cdy < 0)
thrust_angle = arcsin(cdx/velocity) - 90
else
thrust_angle = arccos(cdy/velocity)

while(thrust_angle < 0)
thrust_angle+=360
while(thrust_angle > 360)
thrust_angle-=360

Deccelerate()
if(velocity==0)
return
//Determine the current vectors
var/cdx = sin(thrust_angle) * velocity
var/cdy = cos(thrust_angle) * velocity

//Determine the change in vectors
var/ddx = sin(thrust_angle-180)
var/ddy = cos(thrust_angle-180)

//determine the new vectors
cdx+=ddx
cdy+=ddy

//determine the new velocity and heading
velocity = sqrt(cdx*cdx + cdy*cdy)
velocity += 0.01
thrust_angle = arccos(cdy/velocity)
velocity = round(velocity)
if(velocity < 1)
velocity = 0
CheckEdges()
if(src.x == world.maxx && src.thrust_angle < 180 && src.thrust_angle > 0)
if(src.velocity>1)
src.x=1
src.pixel_x=-15
if(src.y == world.maxy && ((src.thrust_angle < 360 && src.thrust_angle > 270)||(src.thrust_angle<90)))
if(src.velocity>1)
src.y=1
src.pixel_y=-15
if(src.x == 1 && src.thrust_angle < 360 && src.thrust_angle > 180)
if(src.velocity>1)
src.x=world.maxx
src.pixel_x=15
if(src.y == 1 && src.thrust_angle < 270 && src.thrust_angle > 90)
if(src.velocity>1)
src.y=world.maxy
src.pixel_y=15

Turn(left = 0)
if(left)
ship_angle -= TURN_RATE
else
ship_angle += TURN_RATE
while(ship_angle >= 360)
ship_angle -= 360
while(ship_angle < 0)
ship_angle += 360
src.icon = turn(src.icon_int,src.ship_angle)


MoveForward()
CheckEdges()

var/turf/T
var/cx
var/cy

dx += sin(thrust_angle) * velocity
dy += cos(thrust_angle) * velocity

while(dx > TILE_RADIUS)
dx -= TILE_RADIUS * 2
cx++
while(dx < -TILE_RADIUS)
dx += TILE_RADIUS * 2
cx--
while(dy > TILE_RADIUS)
dy -= TILE_RADIUS * 2
cy++
while(dy < -TILE_RADIUS)
dy += TILE_RADIUS * 2
cy--
while(abs(cx) > 0 || abs(cy) > 0)
var/i
var/j
if(cx > 0)
i++
cx--
if(cx < 0)
i--
cx++
if(cy > 0)
j++
cy--
if(cy < 0)
j--
cy++
T = locate(x+i,y+j,z)

if(T)
Move(T)
pixel_x = (dx*16/TILE_RADIUS)
pixel_y = (dy*16/TILE_RADIUS)

client
Northeast()
Northwest()
Southeast()
Southwest()
North()

mob.Accelerate()
East()
mob.Turn(0)
West()
mob.Turn(1)
South()
mob.Deccelerate()


Problem description:
See above. :P
AZA wrote:
whenever you try to take some large turnings it likes to be a bitch - I need to sorta speed it up a little and remove the bugs where it doesn't end up turning the way you need fast enough

i think i get what you're saying, but i'm not sure...

since the turning rate is constant and only occurs when client.East/West are called, the rate of turning relies on the rate at which you press left/right. when you hold down the key, the strokes aren't repeatedly made until your key repeat delay (as determined by windows) is over. holding down left will turn you left once, have a short delay, then keep turning you left.

something like loduwijk's keystate library will fix this. it will also allow you to accelerate while turning.


edit:

since you explained to me in wiz_chat what you mean, i see what your problem is.

don't keep track of your velocity as a speed and an angle. instead, keep track of your velocity as two speeds: one being your speed in the x direction and the other being your speed in the y direction. it really simplifies a lot. you keep breaking velocity and thrust_angle down into the component x and y parts, just store them as x and y parts and compute the total velocity and thrust_angle when you need to know them.

for example, in MoveForward() you no longer need this:
dx += sin(thrust_angle) * velocity
dy += cos(thrust_angle) * velocity

since you already have your separate x and y velocities because thats how thay are stored.

acceleration is easier too, it becomes this:
x_velocity += cos(ship_angle) * ACCELERATION
y_velocity += sin(ship_angle) * ACCELERATION