I was trying a 3D driving snippet that I picked up somewhere, and noticed that if my car_obj was colliding with 2 object(a cube and a ground plane) at the same time, the movement seems to be jittery.
I suppose this is caused by the function ObjectSphereCast and GetObjectRayCastSlideX(0) returning the cube collision on 1 frame, and the ground collision on in the next frame (though I'm not sure).
If I disable collision detection for the ground plane (so that the car_obj only collides with 1 object, the cube), the movement is smooth.
I tried to detect collision twice in a frame, and re-position the car_obj twice, but still doesn't seems to work.
Can this be considered a bug? Any possible workaround?
The codes:
remstart
3D driving game
by: 29 Games (07 sept 2013)
written in AGK v108 Beta 18
instructions:
drive your car through the city and hit all the waypoints
in the fastest time possible
you do not have to hit the way points in any particular order
the timer will start when you hit the first waypoint
when the game is over you will still be able to drive around the city
there is a green cone that marks the original start point but you don't
have to start here
controls:
A,D to turn (universal joystick)
spacekey to accelerate (button 1)
r to reset when the game is over (button 3)
q to quit (button 4)
note:
setup.agc settings when making this game were:
width=800
height=480
fullscreen=0
I've not set a virtual resolution as I didn't think it necessary when playing on windows
remend
gosub _data
gosub _create_object_and_map
gosub _starting_game_values
gosub _create_hud
`main game loop
do
gosub _move_car_and_check_collision
gosub _position_camera_and_lights
gosub _rotate_waypoint_markers
gosub _check_game_state
gosub _update_hud
`press q to quit
if getButtonPressed(4) = 1
exit
endif
Sync()
loop
gosub _delete_all_objects
end
_starting_game_values:
`car values
car_acceleration# = 0.3
car_speed_max# = 4.5
car_turn_speed# = 2.5
car_friction# = 0.98
`game world values
wall_friction# = 0.95
`game values
score = 0
game_start = 0
time# = 0.0
fastest_time# = 9999.9
return
_create_hud:
`game hud text
instruction_id = 1
instruction_text$ = "A,D to turn, space to accelerate, q to quit"
fastest_time_id = 2
fastest_time_text$ = "f"
time_id = 3
time_text$ = "t"
score_id = 4
score_text$ = "s"
createText(instruction_id,instruction_text$)
setTextPosition(instruction_id,0,0)
createText(fastest_time_id,fastest_time_text$)
setTextPosition(fastest_time_id,0,getTextTotalHeight(fastest_time_id))
createText(time_id,time_text$)
setTextPosition(time_id,0,getTextTotalHeight(time_id)*2)
createText(score_id,score_text$)
setTextPosition(score_id,0,getTextTotalHeight(score_id)*3)
`in game messages
game_over_id = 5
game_over_text$ = "O"
game_time_id = 6
game_time_text$ = "T"
reset_instruction_id = 7
reset_instruction_text$ = "press r to reset waypoints"
createText(game_over_id,game_over_text$)
setTextAlignment(game_over_id,1)
setTextVisible(game_over_id,0)
createText(game_time_id,game_time_text$)
setTextAlignment(game_time_id,1)
setTextVisible(game_time_id,0)
createText(reset_instruction_id,reset_instruction_text$)
setTextAlignment(reset_instruction_id,1)
setTextVisible(reset_instruction_id,0)
return
_move_car_and_check_collision:
`save the old car position
car_old_xpos# = getObjectX(car_obj)
car_old_ypos# = getObjectY(car_obj)
car_old_zpos# = getObjectZ(car_obj)
`accelerate
if getButtonState(1) = 1
car_speed# = car_speed# + car_acceleration#
if car_speed# > car_speed_max#
car_speed# = car_speed_max#
endif
endif
`move car
moveObjectLocalZ(car_obj,car_speed#)
`rotate car
rotateObjectLocalY(car_obj,getJoystickX()*car_turn_speed#)
`get car position and angle
car_xpos# = getObjectX(car_obj)
car_ypos# = getObjectY(car_obj)
car_zpos# = getObjectZ(car_obj)
car_xang# = getObjectAngleX(car_obj)
car_yang# = getObjectAngleY(car_obj)
car_zang# = getObjectAngleZ(car_obj)
`collision check
hit = ObjectSphereCast(0,car_old_xpos#,car_old_ypos#,car_old_zpos#,car_xpos#,car_ypos#,car_zpos#,3.5)
if hit <> 0
if hit <= building_objs
`hit a buidling, use sliding collision to reposition car
car_new_xpos# = GetObjectRayCastSlideX(0)
car_new_ypos# = car_ypos#
car_new_zpos# = GetObjectRayCastSlideZ(0)
setObjectPosition(car_obj,car_new_xpos#,car_new_ypos#,car_new_zpos#)
`reduce speed
car_speed# = car_speed#*wall_friction#
else
`hit a waypoint, turn way point "off" but turning off collision and turning it invisible
inc score
setObjectCollisionMode(hit,0)
setObjectVisible(hit,0)
endif
endif
`apply friction, this will slow the car down if the accelerator is not pressed
car_speed# = car_speed#*car_friction#
if car_speed# < 0.01
car_speed# = 0.0
endif
return
_position_camera_and_lights:
`position camera behind car
`position camera on the car and rotate camera to match the car's rotation
`move the camera back , then up and then tilt down
`setCameraPosition(1,car_xpos#,car_ypos#,car_zpos#)
setCameraPosition(1,getObjectX(car_obj),getObjectY(car_obj),getObjectZ(car_obj))
setCameraRotation(1,car_xang#,car_yang#,car_zang#)
`moveCameraLocalZ(1,-35-3*car_speed#)
moveCameraLocalY(1,10)
rotateCameraLocalX(1,5-0.2*(car_speed#))
`position point light in front of the car
`move the car forward, position the light at the new car coordinates,
`move the car back
moveObjectLocalZ(car_obj,30)
setLightPointPosition(1,getObjectX(car_obj),getObjectY(car_obj)+5,getObjectZ(car_obj))
moveObjectLocalZ(car_obj,-30)
`set direction light
`move car forward by 1, diction is calculated using the difference between new and old position
`move car back by 1
moveObjectLocalZ(car_obj,1)
setLightDirectionalDirection(1,getObjectX(car_obj)-car_xpos#,0,getObjectZ(car_obj)-car_zpos#)
moveObjectLocalZ(car_obj,-1)
return
_rotate_waypoint_markers:
for i = building_objs+1 to obj
rotateObjectGlobalY(i,2)
next i
return
_check_game_state:
`game state
if score < num_way_point_markers
`the timer will start when the player has hit any waypoint
`get the start time when the first waypoint has been hit
if score = 0
game_start_time# = timer()
endif
`record the time
if score > 0
time# = timer() - game_start_time#
endif
else
`once the player has hit all the way points the game is over
`check to see if the player has a new fastest time
if time# <= fastest_time#
`new fastest time
fastest_time# = time#
game_over_text$ = "!!! NEW FASTEST TIME !!!"
game_time_text$ = "YOUR TIME : "+ str(time#) + " SECONDS"
else
`not a new fastest time
game_over_text$ = "GAME OVER"
game_time_text$ = "YOUR TIME : "+ str(time#) + " SECONDS"
endif
`game over
setTextString(game_over_id,game_over_text$)
setTextPosition(game_over_id,50,50-getTextTotalHeight(game_over_id))
setTextVisible(game_over_id,1)
`show time
setTextString(game_time_id,game_time_text$)
setTextPosition(game_time_id,50,50)
setTextVisible(game_time_id,1)
`show reset instructions
setTextPosition(reset_instruction_id,50,50+getTextTotalHeight(reset_instruction_id))
setTextVisible(reset_instruction_id,1)
`if r is pressed
if getButtonPressed(3) = 1
`reset values
score = 0
game_start_time# = 0.0
time# = 0.0
`hide game over messages
setTextVisible(game_over_id,0)
setTextVisible(game_time_id,0)
setTextVisible(reset_instruction_id,0)
`turn way point markers back "on"
for i = building_objs+1 to obj
setObjectCollisionMode(i,1)
setObjectVisible(i,1)
next i
endif
endif
return
_update_hud:
fastest_time_text$ = "FASTEST TIME : " + str(fastest_time#)
time_text$ = "TIME : " + str(time#)
score_text$ = "WAYPOINTS REMAINING: " + str(num_way_point_markers - score)
setTextString(fastest_time_id,fastest_time_text$)
setTextString(time_id,time_text$)
setTextString(score_id,score_text$)
return
_delete_all_objects:
for i = 1 to obj
deleteObject(i)
next i
return
_create_object_and_map:
`stores object idents
obj = 0
`player starting position and facing
car_xpos# = val(left(data$[0],4))
car_zpos# = val(mid(data$[0],6,4))
facing = val(right(data$[0],4))
`create car object, position and turn to intial direction
inc obj
car_obj = obj
createObjectBox(car_obj,7,2,10)
setObjectCollisionMode(car_obj,0)
setObjectPosition(car_obj,car_xpos#,1,car_zpos#)
setObjectRotation(car_obj,0,facing,0)
`create start position cone
inc obj
cone_obj = obj
createObjectCone(cone_obj,200,150,12)
setObjectColor(cone_obj,0,255,0,0)
setObjectCollisionMode(cone_obj,0)
setObjectPosition(cone_obj,car_xpos#,5,car_zpos#)
`make ground
inc obj
ground_obj = obj
createObjectPlane(ground_obj,3000,3000)
setObjectColor(ground_obj,200,200,255,0)
setObjectCollisionMode(ground_obj,1)
setObjectPosition(ground_obj,1000,0,1000)
setObjectRotation(ground_obj,270,0,0)
`used for array index
i = 0
`create and position "buildings"
repeat
inc i
if data$[i] <> "_end_of_building_data"
inc obj
`get the width, length and position of the buildings
w = val(left(data$[i],5))
l = val(mid(data$[i],7,5))
x = val(mid(data$[i],13,5))
z = val(right(data$[i],5))
`randomize the height of the building
h = 2*(random(50,100))
`create and position building object
createObjectBox(obj,w,h,l)
setObjectColor(obj,100,50,random(0,255),200)
setObjectTransparency(obj,1)
setObjectCollisionMode(obj,1)
setObjectPosition(obj,x,h/2,z)
endif
until data$[i] = "_end_of_building_data"
`this is the last object number that is a building
building_objs = obj
`create and position way points
num_way_point_markers = 0
repeat
inc i
if data$[i] <> "_end_of_waypoint_data"
inc obj
inc num_way_point_markers
`get waypoint position
x = val(left(data$[i],5))
z = val(right(data$[i],5))
createObjectBox(obj,10,10,10)
setObjectColor(obj,255,255,100,0)
setObjectPosition(obj,x,5,z)
setObjectRotation(obj,45,0,45)
endif
until data$[i] = "_end_of_waypoint_data"
`turn lighting on for all objects
for i = 1 to obj
setObjectLightMode(i,1)
next
`create a directional light
createLightDirectional(1,1,-1,1,255,255,255)
`create a point light
createLightPoint(1,0,0,0,1500,255,255,0)
`change background color to blue
setClearColor(50,50,255)
return
_data:
dim data$[100]
`car starting position
data$[0] = "+350,-200,000"
`building data: "width,length,x_position,z_position"
data$[1] = "00100,00300,00250,00150"
data$[2] = "00100,00300,00450,00150"
data$[3] = "00100,00100,00650,00250"
data$[4] = "00100,00300,00850,00350"
data$[5] = "00100,00200,01050,00300"
data$[6] = "00100,00180,01250,00290"
data$[7] = "00080,00080,01360,00340"
data$[8] = "00220,00100,00210,00450"
data$[9] = "00160,00100,00420,00450"
data$[10] = "00100,00100,00650,00450"
data$[11] = "00100,00100,01250,00450"
data$[12] = "00180,00100,01410,00450"
data$[13] = "00100,00200,01050,00600"
data$[14] = "00340,00100,00170,00650"
data$[15] = "00140,00100,00430,00650"
data$[16] = "00100,00100,00650,00650"
data$[17] = "00100,00180,00850,00690"
data$[18] = "00200,00100,01220,00650"
data$[19] = "00260,00100,01470,00650"
data$[20] = "00200,00100,00200,00850"
data$[21] = "00300,00300,00550,00950"
data$[22] = "00100,00100,00850,00850"
data$[23] = "00140,00100,01070,00850"
data$[24] = "00180,00100,01250,00850"
data$[25] = "00140,00100,01430,00850"
data$[26] = "00100,00100,00050,01050"
data$[27] = "00100,00100,00250,01050"
data$[28] = "00100,00140,00850,01070"
data$[29] = "00100,00160,01050,01080"
data$[30] = "00100,00100,01250,01050"
data$[31] = "00100,00300,01450,01150"
data$[32] = "00100,00140,00850,01230"
data$[33] = "00100,00120,01050,01240"
data$[34] = "00100,00300,00150,01350"
data$[35] = "00200,00100,00400,01250"
data$[36] = "00100,00160,00650,01280"
data$[37] = "00100,00100,01250,01250"
data$[38] = "00200,00100,00400,01450"
data$[39] = "00100,00320,00650,01540"
data$[40] = "00100,00200,00850,01500"
data$[41] = "00300,00100,01150,01450"
data$[42] = "00200,00100,00400,01650"
data$[43] = "00100,00100,01050,01650"
data$[44] = "_end_of_building_data"
`waypoint data
data$[45] = "00350,00250"
data$[46] = "00350,00650"
data$[47] = "00350,00950"
data$[48] = "00350,01350"
data$[49] = "00850,01350"
data$[50] = "01350,01250"
data$[51] = "01050,01170"
data$[52] = "00850,00950"
data$[53] = "00950,00550"
data$[54] = "01310,00390"
data$[55] = "_end_of_waypoint_data"
return