PDA

View Full Version : AI for hovercraft



Petr Schreiber
26-09-2008, 21:41
Hi all,

here is just basic test of "AI" for aircraft, it is currently just about hovercraft parametrization of taking waypoints seriously.
I would like to have quite interesting AI implemented in the game, based on racer "psychology" - when somebody is last, he will try to drive more risky and so on...

But this demo does implement just following for now:

Following waypoints in correct order
Having speed and steering reactions parametrized


What are your thoughts on AI? In which racing game you liked, in which hated?


Petr

Michael Clease
26-09-2008, 22:03
If you are going to make new commands you need to let us have them :P

TBGL_EntityGetDistance

Lionheart008
26-09-2008, 22:15
hi petr, hi all:)

- uhps! Thanks for the nice 'aircraft' AI, I will check it and build in perhaps one or two or three (I see!) simple dummy objects for testing it... I like the different velocity and the cruising around hurdles ;) that smells after a race structure! good one :)

3 Triangles: yellow = very fast, green = fast, red = slow. They are starting at the same time I have seen, very good... hovercraft race around buoys I can imagine... I support such basically ideas of a game... although I am not a real gamer profi ;)

other improvements of game modus could follow if the team like it:)

best regards, Lionheart, jump into bed...

Michael Hartlef
26-09-2008, 22:23
If you are going to make new commands you need to let us have them :P

TBGL_EntityGetDistance


Mike, I think you need the lastest preview of 1.7.0.0, as the script runs fine here.

Petr, nice job. Once there will a randomization of the steering behaviour and alternativ path settings, this could really work. It is really strange how you have the same thoughts like I do.


I would like to have quite interesting AI implemented in the game, based on racer "psychology" - when somebody is last, he will try to drive more risky and so on... Thsi should be not a general rule. We should define different AI characters. Some would do that, some would react different.

Petr Schreiber
26-09-2008, 22:37
Hi,

@Abraxas, I am very sorry, as Mike said, it is from 1.7.0.0. I will be using this version, as it has some nice touches out of TBGL as well. If you do not want to go for this preview2, you can simply use TBGL_EntityGetPos for 2 entities and calculate the distance on your own.

@LionHeart, I originally wanted to put your hovercraft there, but then I decided for more symbolic look and smaller download for others.

@Mike, good idea. One thing I like about FlatOut 2 budget ( but probably the best :o ) car racing game is that there are 8 opponents with face and name, each driving differentely. Would be nice to have it in our game as well.


Petr

Michael Clease
26-09-2008, 22:42
Sorry I didnt realise until I read Eros's update that he didnt update the link, I had to.

Lionheart008
26-09-2008, 22:47
:o... can I ask for meaning specific words? ;)


randomization of the steering behaviour and alternativ path settings

... puh!

and


steering reactions parametrized

sorry...

- I can build some new objects, you are right, petr, the hovercraft model was simple too big for such little scene... there will come some better crafts and lower poly objects:)

best regards, lionheart

Petr Schreiber
26-09-2008, 22:55
Lionheart,

no too big, I like it! Just at this phase it is not necessary. We can develop AI on simple model, and then just bind the models in final release. I also like the fact that when script does not use any external resources, I can launch it directly in browser ( click + open ).

Randomization of the steering behaviour = to not make the pilots of hovercraft too precise, but make them a bit inprecise
alternativ path settings = tracks will have some parts where they split, so AI will choose which path to take

steering reactions parametrized = as you can see in the AI routine, I basically retrieve heading angle from one entity to other, and take it as base to make ship go left/right. The parametrization consists just in multiplying the angle fraction by some constant, determining pilot driving style ( higher number, more sharp steering )

If you have time for next ships I will be only happy :)


Petr

Lionheart008
27-09-2008, 00:01
ok:) hi all, now the final and last post...

=> I include here three simple dummy car objects, yellow, blue, red one ;)

try to use it and please say if they are too big...

good night, lionheart

Michael Hartlef
27-09-2008, 00:51
If you have time for next ships I will be only happy :)




=> I include here three simple dummy car objects, yellow, blue, red one


;D guys, I think you should work on your communication skills too! :D

Simone
27-09-2008, 09:42
HI all,

@ Petr the Demo works very well, idea of waypoints sounds good for me i will check it.

@ Michael i agree with you we can study an algorithm that assign to the AI different actions at the situation

if there is a team for study communications i subscribe into it ;D

Petr Schreiber
27-09-2008, 10:17
guys, I think you should work on your communication skills too!


;D, ok shall we call it hovercraft, no aliases allowed :) ?

@Lionheart, nice models, but we need ... hover craft. I am sorry if I did not put it correctly, I know my demo could make impression we are doing car race game.

Hovercraft is mean of transport levitating in the air thanks to various mechanisms - magnetic field / strooong jets directed down / other. So it usually does not have any wheels.

Example of hovercraft from Star Wars: Landspeeder (http://starwars.wikia.com/images/5/54/X34-landspeeder.jpg)


Petr

Lionheart008
27-09-2008, 10:44
good morning, dear guys:)

dear petr, michael, simone...
- yes, of course, that was my mistake... but I have worked with this idea only for a dummy example to see more, but that doesn't matter... I was too tired to see the problem... discussions and good communication are very welcome... also for me;)

- yes:)


If you have time for next ships I will be only happy

I design some hovercraft objects ;) need only time...

QT again (sorry):
=> What size does this hovercraft object files have? It's ok if they are needs per object about 580-600 kbyte??? Michael told me some days ago, cannot find the post... ;)

- the construction of models isn't the problem, only the 'details' and polygon amount increase, so I must find my best golden way in the middle of the road;)


Hovercraft is mean of transport levitating in the air thanks to various mechanisms - magnetic field / strooong jets directed down / other. So it usually does not have any wheels.

oh yes, I have seen some hovercrafts in real life e.g. at bodensee, east sea, england, spain (barcelona)... and more... :D I like this noisy racing ships...

nice day, more will come, I am sure...

ps: take the little 'three cars' and take them into the garage for poor times without fuel and oil:)

lionheart

Petr Schreiber
27-09-2008, 10:56
Hi Lionhead,

I will spawn new thread to not go offtopic, ok :)?


Petr

ErosOlmi
27-09-2008, 16:28
Petr,

nice nice job. Looking the 3 triangles is like sitting in front of fire: you get hypnotized !

I played a little with parameters and seems there are some point where hovercraft goes into a loop.
For example in %eHovercraftPrecise the following parameters create a loop after the first round


.minSpeed = 5
.maxSpeed = 100
.steerFactor = 3


Again, very clever code, a pleasure to experiment t with.

Eros

Petr Schreiber
27-09-2008, 17:26
Hi Eros,

you are right, but it is more thing of parameter tuning than bug, let me explain :P

min/max speed are clear. The angle is ability to turn fast ( higher number, higher ability ).
But if you let the tolerance ( radius around point which is considered enough to go through instead of exactly passing point ) on such a low number, the hovercraft could not finish the race, because it was not possible to get near enough ( at distance 1m ).

Just try your setting, with tolerance raised to 2.

But you are right, hovercrafts should not be stuck for so long ( infinitely ) on one place.
Solutions are two - design tracks in way it will not make such a problems :D, or just detect how long does it take to hovercraft to reach waypoint. In case it is too long, it will temporarily raise tolerance for example.

I will work on it.


Thanks,
Petr

Michael Hartlef
30-09-2008, 12:40
Hi Petr,

here is an idea about how the AI and also the player vessel can auto react on a track, maybe even without any waypoints used.

For this we need the ability to cast rays from the vessel in a direction and get back the distance to a model. Here are some pictures that show you which rays (the red things) I mean. The front ray could detect if the vessel runs into something and so change its heading. The side rays would check if something comes from the side like the track walls or opponents. The bottom rays would be used to check for the banking and the slope of a track. Also the front side rays could detect which direction a track is turning to.

What do you think?

Michael

Petr Schreiber
30-09-2008, 18:27
Hi,

9 rays for model, that sounds good.
It will be interesting to come up with AI based on sensors.

But it would still need to know some target point I think - imagine the hovercraft will be turned 180° in crash, then it can go back the road by accident :).

I will try to code out fast ray-triangle code, I have something in the works, just need more time.

As entity system allows to track global point position of point located on arbitrary rotated model, I was thinking of some testing volumes as well ( is point in box ... ). But the ray way is more flexible and needs no postprocessing of models ( like defining bounding volumes for track ). Will see how fast can I make it :)


Petr

kryton9
01-10-2008, 01:10
The limited times I have had the pleasure of using collision detection in DarkBasicPro, the ray cast solutions seemed to work the best.

Michael Hartlef
01-10-2008, 06:22
But it would still need to know some target point I think - imagine the hovercraft will be turned 180° in crash, then it can go back the road by accident :).

I will try to code out fast ray-triangle code, I have something in the works, just need more time.


Maybe once it turns upsite down, you can set a state where the body will be handled differently. Also remember, that we have mostly quads, so I hope the ray casting works with quads too.

ISAWHIM
03-10-2008, 03:55
Ok, I edited this post, because I played around with some more changes, and the original post was junk.

Ignore the "Speed", though it is roughly scale to about 40 MPH on a 1/4 mile track.

There is a slight change to the formula that determines PUSH and TURN...

Oh, and it has the ships as an array... 30 to 330 (0 to 21 is the boxes?!?) Might be a bug, or just my bad programming. Seems the constants share the same values, with seporate names?

Took me a few tries to figure out why the triangles were chasing the boxes, and the boxes were chasing the boxes!

Just remember, there are two locations to change the value for the ships... One for the objects, and one for the motions.


'
' Test of hovercraft AI
' Petr Schreiber, started on 09-26-2008
'

Uses "TBGL"

BEGIN CONST
' -- Scene IDs
%sScene = 1

' -- Entity IDs
%eCamera = 1
%eLight
%eHovercraft
%eWayPointStart
END CONST

GLOBAL FrameRate AS DOUBLE

FUNCTION TBMAIN()
LOCAL hWnd As DWORD

' -- Create and show window
hWnd = TBGL_CreateWindowEx("Test for hovercraft elemental AI", 800, 600, 32, %TBGL_WS_WINDOWED or %TBGL_WS_CLOSEBOX)
TBGL_ShowWindow

' -- Create scene
TBGL_SceneCreate(%sScene)

' -- Create basic entities
' -- Create camera to look from 15, 15, 15 to 0, 0, 0
TBGL_EntityCreateCamera(%sScene, %eCamera)
TBGL_EntitySetPos(%sScene, %eCamera, 0, 0, 30)
TBGL_EntitySetTargetPos(%sScene, %eCamera, 0, 0, 0)

' -- Create point light
TBGL_EntityCreateLight(%sScene, %eLight)
TBGL_EntitySetPos(%sScene, %eLight, 15, 10, 5)

TBGL_NewList 1
TBGL_UseLighting %FALSE
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex -0.07, -0.14
TBGL_Vertex 0.07, -0.14
TBGL_Vertex 0.00, 0.14
TBGL_ENDPOLY
TBGL_UseLighting %TRUE
TBGL_EndList

' -- Create something to look at
TYPE tHoverCraft
nextWayPoint AS LONG
numWayPoint AS LONG
tolerance AS double ' -- Tolerance to reach waypoint
minSpeed AS double
maxSpeed AS double
steerFactor AS double
END TYPE
dim HoverInfo as tHoverCraft

LOCAL x AS LONG
FOR x = %eHovercraft + 30 TO %eHovercraft + 330
TBGL_EntityCreateDLSlot(%sScene, x, 0, 1)
TBGL_EntitySetColor(%sScene, x, RND(0,255), RND(0,255), RND(0,255))
' -- Assign data to it
with HoverInfo
.nextWayPoint = %eWayPointStart
.numWayPoint = 21
.tolerance = 0.7
.minSpeed = RND(100,150)*0.01
.maxSpeed = RND(400,450)*0.01
.steerFactor = RND(20,40)*0.01
END WITH
TBGL_EntitySetUserData(%sScene, x, HoverInfo)
next

local i as long
for i = %eWayPointStart to %eWayPointStart + 21
TBGL_EntityCreateBox(%sScene, i, 0, 0.1, 0.1, 0.1)
TBGL_EntitySetColor(%sScene, i, 255, 128, 0)
next

' -- Hardcoded waypoints
TBGL_EntitySetPos(%sScene, %eWayPointStart+0, -2, 2, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+1, 0, 6, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+2, 4, 8, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+3, 6, 5, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+4, 10, 0, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+5, 13, 1, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+6, 14, 6, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+7, 13, 8, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+8, 8, 11, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+9, -6, 10, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+10, -12, 8, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+11, -13, 6, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+12, -10, 3, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+13, -7, 1, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+14, -8, -3, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+15, -10, -6, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+16, -8, -8, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+17, -1, -9, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+18, 11, -10, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+19, 12, -8, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+20, 11, -6, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+21, 3, -2, 0)

' -- Resets status of all keys
TBGL_ResetKeyState()

' -- Main loop
While TBGL_IsWindow(hWnd)
FrameRate = TBGL_GetFrameRate

TBGL_ClearFrame

LOCAL z AS LONG
' NOTE: Pointer offset from track-points
FOR z = %eHovercraft + 30 TO %eHovercraft + 330
HoverCraft_AI(z)
NEXT
'HoverCraft_AI(%eHovercraftMedium)
'HoverCraft_AI(%eHovercraftLazy)
TBGL_SceneRender(%sScene)

TBGL_DrawFrame

' -- ESCAPE key to exit application
If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While

Wend

TBGL_DestroyWindow
END FUNCTION

Sub HoverCraft_AI( entity AS LONG )
local hoverData AS tHoverCraft ptr

' -- Retrieve data from entity
hoverData = TBGL_EntityGetUserDataPointer(%sScene, entity)

' -- Get angle and distance to next waypoint
LOCAL angle AS DOUBLE = TBGL_EntityGetAngleXY(%sScene, entity, hoverData.nextWayPoint, %TBGL_Y) ' -- The front part is on Y axis
local distance as double = TBGL_EntityGetDistance(%sScene, entity, hoverData.nextWayPoint)

' -- Move according to parametrization
TBGL_EntityTurn(%sScene, entity, 0, 0, (hoverData.steerFactor*(min(hoverData.minSpeed+(distance*9), hoverData.maxSpeed*3))*angle)/FrameRate)
TBGL_EntityPush(%sScene, entity, 0, min(hoverData.minSpeed+(distance*9), hoverData.maxSpeed)/FrameRate, 0)

' -- Check for next waypoints
IF distance < hoverData.tolerance then
if hoverData.nextWayPoint < %eWayPointStart+hoverData.numWayPoint then
incr hoverData.nextWayPoint
else
hoverData.nextWayPoint = %eWayPointStart
END IF
END IF

END SUB

ErosOlmi
03-10-2008, 08:37
Nice variation.

Redimensioning the window seems getting crazy some vehicle for a while but it's a nice looking situation :D

ISAWHIM
03-10-2008, 09:15
Eros, I just reposted an update...

The values before... were throwing the vehicles into "Slow mode" about 1/2 way between points. Once they passed a point, they sling-shot into full speed again. (That still needs adjustment.)

I altered the code, so they are about 80% near a point, before they attempt to slow-down, for the turn.

I also used a similar adjustment, taking the speed/distance into the turn/steer value... They have slight more control, if they are going slower... (Unless I did that backwards, then they are loosing control by going slower.)

I don't know how to get the speed value yet, so I just guessed.

It looks correct, as a flock. (Remember that is not full-scale, so a width the size of a triangle is actually about 2 cars wide.)

They pull tight on a line, and sling-shot with good variation on an attempted turn. (I like the swirls when the code is buggy, an they can't turn enough. LOL... Hover-vortex!)

ErosOlmi
03-10-2008, 11:20
uuuhh very nice looking :o
A lot of ... cars :D

There are still AI problems when window is sized or even moved but it is a pleasure to look at this example.
I can see cars move into some kind of groups maybe because they share similar behaves.

Petr Schreiber
03-10-2008, 11:38
Hi Jason,

nice tweak! To get "real speed" is very easy.

I would recommend to stick with SI units for this project - so then 1.0 length unit = 1.0 meter.
Then when you


TBGL_EntityPush(%scene, %entity, 0, 0, 10/Framerate)


... your vehicle moves at 10 meters/second.

One thing you will like, instead of:


.minSpeed = RND(100,150)*0.01


you can use floating point random number generator:


.minSpeed = RNDF(1,1.5)


Each entity should have different id, you can simply do following instead of hardcoding numeric literals:


BEGIN CONST
' -- Scene IDs
%sScene = 1

' -- Limits
%maxHoverCrafts = 100 ' -- Set how many hovercrafts do you want here
%maxWayPoints = 21 ' -- Set how many waypoints do you want here

' -- Entity IDs
%eCamera = 1
%eLight

%eHovercraftStart
%eHovercraftEnd = %eHovercraftStart + %maxHoverCrafts - 1

%eWayPointStart = %eHovercraftEnd + 1
%eWayPointEnd = %eWayPointStart + %maxWayPoints - 1
END CONST


Then the final code ( now with random track, heh ) looks like:


'
' Test of hovercraft AI, v2
' Petr Schreiber, started on 09-26-2008
'

Uses "TBGL"

BEGIN CONST
' -- Scene IDs
%sScene = 1

' -- Limits
%maxHoverCrafts = 100 ' -- Set how many hovercrafts do you want here
%maxWayPoints = 21 ' -- Set how many waypoints do you want here

' -- Entity IDs
%eCamera = 1
%eLight

%eHovercraftStart
%eHovercraftEnd = %eHovercraftStart + %maxHoverCrafts - 1

%eWayPointStart = %eHovercraftEnd + 1
%eWayPointEnd = %eWayPointStart + %maxWayPoints - 1
END CONST

GLOBAL FrameRate AS DOUBLE

FUNCTION TBMAIN()
LOCAL hWnd As DWORD

' -- Create and show window
hWnd = TBGL_CreateWindowEx("Test for hovercraft elemental AI, v2", 800, 600, 32, %TBGL_WS_WINDOWED or %TBGL_WS_CLOSEBOX)
TBGL_ShowWindow

' -- Create scene
TBGL_SceneCreate(%sScene)

' -- Create basic entities
' -- Create camera to look from 15, 15, 15 to 0, 0, 0
TBGL_EntityCreateCamera(%sScene, %eCamera)
TBGL_EntitySetPos(%sScene, %eCamera, 0, 0, 30)
TBGL_EntitySetTargetPos(%sScene, %eCamera, 0, 0, 0)

' -- Create point light
TBGL_EntityCreateLight(%sScene, %eLight)
TBGL_EntitySetPos(%sScene, %eLight, 15, 10, 5)

%listVehicle = 1
TBGL_NewList %listVehicle
TBGL_UseLighting %FALSE
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex -0.07, -0.14
TBGL_Vertex 0.07, -0.14
TBGL_Vertex 0.00, 0.14
TBGL_ENDPOLY
TBGL_UseLighting %TRUE
TBGL_EndList

' -- Create random waypoints
local w as long
for w = %eWayPointStart to %eWayPointEnd
TBGL_EntityCreateBox(%sScene, w, 0, 0.1, 0.1, 0.1)
TBGL_EntitySetColor(%sScene, w, 255, 128, 0)
TBGL_EntitySetPos(%sScene, w, rndf(-15, 15), rndf(-10, 10), 0)
next


' -- Create something to look at
TYPE tHoverCraft
nextWayPoint AS LONG
numWayPoint AS LONG
tolerance AS double ' -- Tolerance to reach waypoint
minSpeed AS double
maxSpeed AS double
steerFactor AS double
END TYPE
dim HoverInfo as tHoverCraft


LOCAL h AS LONG
local x, y, z as double
TBGL_EntityGetPos(%sScene, %eWayPointStart, x, y, z)
FOR h = %eHovercraftStart TO %eHovercraftEnd
TBGL_EntityCreateDLSlot(%sScene, h, 0, %listVehicle)
TBGL_EntitySetColor(%sScene, h, RND(0,255), RND(0,255), RND(0,255))

' -- Start position relative to first waypoint
TBGL_EntitySetpos(%sScene, h, x+RNDf(-0.1,0.1), y-RNDf(0.1,0.2), 0)

' -- Assign data to it
with HoverInfo
.nextWayPoint = %eWayPointStart
.numWayPoint = %maxWayPoints
.tolerance = 0.7
.minSpeed = RNDF(1.0,1.5)
.maxSpeed = RNDf(4,4.5)
.steerFactor = RNDf(0.2,0.4)
END WITH
TBGL_EntitySetUserData(%sScene, h, HoverInfo)
next




' -- Resets status of all keys
TBGL_ResetKeyState()

' -- Main loop
While TBGL_IsWindow(hWnd)
FrameRate = TBGL_GetFrameRate

TBGL_ClearFrame

FOR h = %eHovercraftStart TO %eHovercraftEnd
HoverCraft_AI(h)
NEXT
TBGL_SceneRender(%sScene)

TBGL_DrawFrame

' -- ESCAPE key to exit application
If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While

Wend

TBGL_DestroyWindow
END FUNCTION

Sub HoverCraft_AI( entity AS LONG )
local hoverData AS tHoverCraft ptr

' -- Retrieve data from entity
hoverData = TBGL_EntityGetUserDataPointer(%sScene, entity)

' -- Get angle and distance to next waypoint
LOCAL angle AS DOUBLE = TBGL_EntityGetAngleXY(%sScene, entity, hoverData.nextWayPoint, %TBGL_Y) ' -- The front part is on Y axis
local distance as double = TBGL_EntityGetDistance(%sScene, entity, hoverData.nextWayPoint)

' -- Move according to parametrization
TBGL_EntityTurn(%sScene, entity, 0, 0, (hoverData.steerFactor*(min(hoverData.minSpeed+(distance*9), hoverData.maxSpeed*3))*angle)/FrameRate)
TBGL_EntityPush(%sScene, entity, 0, min(hoverData.minSpeed+(distance*9), hoverData.maxSpeed)/FrameRate, 0)

' -- Check for next waypoints
IF distance < hoverData.tolerance then
if hoverData.nextWayPoint < %eWayPointEnd then
incr hoverData.nextWayPoint
else
hoverData.nextWayPoint = %eWayPointStart
END IF
END IF

END SUB



Petr

Michael Hartlef
03-10-2008, 11:39
Nice Jason. With 10 vessels I get around 320 FPS. That is a good value.

Michael Clease
03-10-2008, 13:34
Interesting that some of them go on a different path on some points but on the whole very good.

ErosOlmi
03-10-2008, 17:13
To ISAWHIM

I was discussing with Petr about an abnormal memory consumption produced by your script (see task manager when script is under execution).
At first we thought is was thinCore engine or TBGL module not releasing all the memory. But Petr discover you have the following line inside WHILE/WEND:


LOCAL z AS LONG

The above line inside a WHILE/WEND loop continuously allocates bytes.
I'm making changes to thinBasic Core engine in order to generate a runtime error and trap this situation.
In the meantime, can you move the above line outside the WHILE/WEND loop?

Ciao
Eros

ISAWHIM
03-10-2008, 21:38
I didn't realize that %constantval = 100 was the same as MyVal(100)... (That is where I was having trouble, it kept saying constant exists, or it used %constant1 as %constant2, even though I typed %constant1 when trying to use %constatnt1+x)

LOCAL DIM situation noted... (I just put that there, to play with the path code.) Also noted the Float Random version. (Comes in handy for testing. But old habits die hard. TY.)

I have a more suitable set of code with slight more physics. (Should output non-scaled values, which would be scaled.) Once the game has set limits... But until then, I am using time and size as my only scale. (1 in my code is closer to 10 yards.)

How is collision detection coming? Until that becomes a generic function, I will use that XY_Distance for quick bubble collision. (Going back to 8 cars... I put about 1000 to check for track/formula spread, and to try to catch LOOPERS.)

The new code will never have a looper... I am adjusting the speed so if the ABS(ANGLE) is > (DISTANCE * Xmod), they attempt to slow-down and being slower has a formula trait of being able to turn more, but not beyond a certain point. In the game, that would only be a suggestion of possible moves. The actual AI output, depending on SKILL_VALUE would take a value close, but not exactly that value. The greatest attribute I have added is POWER and SPEED and WEIGHT. (Power being the engine size factor, Speed being the actual velocity, and Weight being a mod of all the physics as mass. Thus, the AI now has a physics code to react to.)

I am also creating a second "tolerance", but those are now part of the track values.

The point is irrelevant, except as a suggestive location/point value. The point has three levels, only two values. PointTargetArea, and PointTrackWidth. The third level is just larger than PointTrackWidth, and it is just the remainder of distance to travel. I am reversing the formula a little, and using the... (DISTANCE(XY_LAST to XY_NEW) - PointTrackWidth) to determine the area where the AI tries to find a new point. That draws a large circle around the last point, and once that point has been left, within the new point limit... it is safe to find a new point to chase, depending on the new points angle, from the point being chased now. (That allows them to change direction faster on an outside turn, where the tend to LOOP now.)


I am having the AI look ahead one more point, to see if the track is turning or going in a line. If it is turning, it adjusts speed, and begins to turn early. Otherwise it is going in a line, and will attempt to MAX speed.

ISAWHIM
06-10-2008, 09:28
Ok, here is another modification/setup...

This uses SOME of what I believe will be the required craft elements. (You don't have to save it, but you might be able to use something from it.)

I made note of most of the changes, and where I was headed for the physics part. For the AI part, I have added part of the one-point ahead looking. (I tried to use petr's method for the height, but I did not have any luck with it.)

Until I have a map-file to test, I will be adding a raised map from a BMP image. The points work within +/- 3 meters, for the most part. (The "Looping", is a side-effect, which I mention in the code, of using FrameTime to change the angle. That is why they looped on some systems, but not on mine. The faster the frame-time, the more precise the turn. The slower the FrameTime, the more sloppy the turn. Physics will fix that.)

System resources with only 8 cars, was 2% to 5% AVG. (Added a DoEvents to return the loop processing to the PC. Working on a better arrangement for that main loop. But this is OK for my testing.)

Added a real counter, to display the FPS on the title bar, and added some CHASE code, for a camera, to watch the paths. Instructions on the title bar, mouse controls.

AVG FPS with 300 cars, is 53.10 FPS (CPU near 85%)
AVG FPS with 100 cars, is 140.78 FPS (CPU near 55%) (Graphics begin to drop-out? Triangle holes in floor.)
AVG FPS with 8 cars, is 630.45 FPS (CPU near 2%) (Didn't see as much graphic drop-out.)

Full width is about 700 meters or about 0.44 miles wide... Not sure what craft-speed is... but that is the world and view dimensions/scale. (AI crafts are 1 meter wide and tall, and 2 meters long.)

Once the physics are in place, you only have to define the world values.
General world values, to all...
- Gravity Force (GF = 1.0000) Airbourn fall acceleration.
- Air Resistance (AF = 1.0000) Time decay of all forces except gravity.
- Collision AngleForce (CA = 1.0000) Specific to (Player/AI to World).

Player specific values, of world...
- MaxImpact Force (IF = 1.000) More = we are solid, Less = we are rubber. Specific to (Player to Player).
- MaxEngine Force (EF = 400.0) Power, not speed.
- - MaxPush Force (PF = calculated) 50% + Percent unused from diversions below.
- - MaxTurn Force (TF = 100.0) Limit of power used from engine as a percent. (100 is 25% of E)
- - MaxDrift Force (D = 100.0) Limit of power used from engine as a percent. (100 is 25% of E)

Speed is calculated in the game, not a value.
Damage value is calculated, not specific.
etc...

Beyond that, there is only the thinking left to do... (Where to go, and how to get there.)


'
' Test of hovercraft AI
' Petr Schreiber, started on 09-26-2008
'

Uses "TBGL"

HiResTimer_Init
GLOBAL xHRT_Old, xHRT_New AS QUAD ' Used to calculate actual frame rate.
xHRT_Old = HiResTimer_Get

' NOTE: Having a frame upper limit, helps to ensure that sufficient time has passed
' before doing further calculation on insignificant game factors. Collision, Gravity,
' Air Resistance, Memory Dumping, Interruption, Key Calls, Drawing...

GLOBAL xGFV AS QUAD = (1/60)*1000000 ' Frame value, calculated for the QUAD HighResTimer loop
GLOBAL xGFR AS DOUBLE ' Game Frame Rate (Time-Slice)

GLOBAL PointCount AS LONG = 21 ' Change with new points, also change %eWayPointStart value
GLOBAL CraftCount AS LONG = 8 ' Change with new crafts, also change %eHovercraft value
GLOBAL TrackWidth AS DOUBLE = 8 ' 5 meters wide 10 meter diameter
GLOBAL cX, cY, cZ AS DOUBLE ' Used for camera positions
GLOBAL hWnd AS DWORD

' -- Scene IDs
BEGIN CONST
%sScene = 1
END CONST

' -- Entity IDs
BEGIN CONST
%eCamera = 1
%eLight = 2
%eGroundBase = 3
%eWayPointStart = 21
%eHovercraft = 8
END CONST

FUNCTION TBMAIN()

' -- Create and show window
hWnd = TBGL_CreateWindowEx("Test for hovercraft elemental AI", 800, 600, 32, %TBGL_WS_WINDOWED OR %TBGL_WS_CLOSEBOX OR %TBGL_WS_DONTSIZE)
TBGL_ShowWindow
TBGL_UseTexturing %TRUE

' -- Create scene
TBGL_SceneCreate(%sScene)
TBGL_SetDrawDistance(800)

' -- Create camera
TBGL_EntityCreateCamera(%sScene, %eCamera)
TBGL_EntitySetPos(%sScene, %eCamera, 0, 0, 700)
TBGL_EntitySetTargetPos(%sScene, %eCamera, 0, 0, 0)

' -- Create light
TBGL_EntityCreateLight(%sScene, %eLight)
TBGL_EntitySetPos(%sScene, %eLight, 0, -100, 100)

' -- Create Ground
'TBGL_LoadTexture("ground.bmp", 1, %TBGL_TEX_MIPMAP)
TBGL_EntityCreateBox(%sScene, %eGroundBase, 0, 800, 600, 10) ' Change to "(%sScene, %eGroundBase, 0, 800, 600, 3, 1)" for texture map.
TBGL_EntitySetColor(%sScene, %eGroundBase, 100, 155, 100)
TBGL_EntitySetPos(%sScene, %eGroundBase, 0, 0, -7)

' -- Craft Model Data
TBGL_NewList 1
TBGL_UseLighting %FALSE
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex -1, -2, 0
TBGL_Vertex 1, -2, 0
TBGL_Vertex 0, 2, 0
TBGL_ENDPOLY
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex -1, -2, 0
TBGL_Vertex 0, -2, 1
TBGL_Vertex 0, 2, 0
TBGL_ENDPOLY
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex 0, -2, 1
TBGL_Vertex 1, -2, 0
TBGL_Vertex 0, 2, 0
TBGL_ENDPOLY
TBGL_UseLighting %TRUE
TBGL_EndList

' -- Create Craft Format
TYPE tHoverCraft
nextWayPoint AS LONG
thisWayPoint AS LONG
numWayPoint AS LONG
mass AS double
velocity AS double
force AS double
angleXY AS double
angleXZ AS double
angleYZ AS double
END TYPE
DIM HoverInfo AS tHoverCraft

' -- Create Random Crafts
LOCAL x AS LONG
FOR x = %eHovercraft TO %eHovercraft + CraftCount
TBGL_EntityCreateDLSlot(%sScene, x, 0, 1)
TBGL_EntitySetColor(%sScene, x, RND(0,255), RND(0,255), RND(0,255))
' -- Assign data to it
WITH HoverInfo
.nextWayPoint = %eWayPointStart+RND(1,21) ' Where am I going next
.thisWayPoint = %eWayPointStart-1 ' Where am I now
.numWayPoint = PointCount ' Not sure if this is used, or relevant (Game value not craft value.)
.mass = RNDF(0.80, 1.00) ' Not used yet
.velocity = RNDF(0.80, 1.00) ' Not used yet
.force = RNDF(0.10, 1.00) ' Not used yet
.angleXY = RND(-180, 180) ' Not used yet
.angleXZ = RND(-180, 180) ' Not used yet
.angleYZ = RND(-180, 180) ' Not used yet
END WITH
TBGL_EntitySetUserData(%sScene, x, HoverInfo)
TBGL_EntitySetPos(%sScene, x, 0, 0, 0)
NEXT

' -- Setup Track Points
LOCAL i AS LONG
FOR i = %eWayPointStart TO %eWayPointStart + PointCount
TBGL_EntityCreateBox(%sScene, i, 0, 1, 1, 4)
TBGL_EntitySetColor(%sScene, i, 255, 128, 0)
NEXT

' -- Hardcoded waypoints
' This is a SUPER LONG track. 1 = 1 meter. Full width is about 700 meters or about 0.44 miles wide.
' Scale speed
TBGL_EntitySetPos(%sScene, %eWayPointStart+0, -50, 50, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+1, 0, 150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+2, 100, 200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+3, 150, 125, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+4, 250, 0, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+5, 325, 25, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+6, 350, 150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+7, 325, 200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+8, 200, 275, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+9, -150, 250, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+10, -300, 200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+11, -325, 150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+12, -250, 75, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+13, -175, 25, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+14, -200, -75, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+15, -250, -150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+16, -200, -200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+17, -25, -225, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+18, 275, -250, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+19, 300, -200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+20, 275, -150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+21, 175, -50, 0)

' -- Resets status of all keys
TBGL_ResetKeyState()

' -- Main loop
xGFR = TBGL_GetFrameRate ' Initializes framerate, or value = 1, That is bad.
GLOBAL z AS LONG
GLOBAL xFrameTimeCount AS DOUBLE
GLOBAL xFrameTimeTotal AS DOUBLE
While TBGL_IsWindow(hWnd)
DoEvents
xGFR = TBGL_GetFrameRate
IF xGFR < 2 THEN xGFR = TBGL_GetFrameRate ' Stops FrameMove issue

xHRT_New = HiResTimer_Get
INCR xFrameTimeCount
xFrameTimeTotal += xGFR
IF xHRT_New - xHRT_Old >= (xGFV * 60) THEN
TBGL_SetWindowTitle(hWnd, "(Hold LMB = Follow Car#1), (Hit RMB = Reset TopView), " & "(AVG FPS: " & FORMAT$(xFrameTimeTotal/xFrameTimeCount, "#0.00") & "), (SECONDS: " & FORMAT$(xFrameTimeTotal, "#0.00") & " / FRAMES: " & STR$(xFrameTimeCount) & " )")
xFrameTimeCount = 0
xFrameTimeTotal = 0
xHRT_Old = xHRT_New
END IF

TBGL_ClearFrame

FOR z = %eHovercraft TO %eHovercraft + CraftCount
HoverCraft_AI(z)
NEXT

' This is NOT the camera-follow I am looking for, but it works for now.
IF TBGL_GetWindowKeyState(hWnd, %VK_LBUTTON) THEN
TBGL_SetDrawDistance(400)
TBGL_EntityGetPos(%sScene, %eHovercraft, cX, cY, cZ, %TRUE)
TBGL_EntitySetPos(%sScene, %eCamera, cX, cY -80, cZ +40)
TBGL_EntitySetTarget(%sScene, %eCamera, %eHovercraft)
END IF

IF TBGL_GetWindowKeyState(hWnd, %VK_RBUTTON) THEN
TBGL_SetDrawDistance(800)
TBGL_EntitySetPos(%sScene, %eCamera, 0, 0, 700)
TBGL_EntitySetTargetPos(%sScene, %eCamera, 0, 0, 0)
END IF

TBGL_SceneRender(%sScene)
TBGL_DrawFrame

' -- ESCAPE key to exit application
If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While
Wend

TBGL_SceneDestroy(%sScene)
TBGL_DestroyWindow
END FUNCTION

Sub HoverCraft_AI( entity AS LONG )
LOCAL hoverData AS tHoverCraft PTR

' -- Retrieve data from entity
hoverData = TBGL_EntityGetUserDataPointer(%sScene, entity)

' -- Get angle and distance to next waypoint
' This will be the LOOKING that the vehicles will do, to determine if they are going to veer left/right
' also, the distance from will be compared to the distance between points, to determine if the vehicle
' should speed-up or slow-down, and identify how far off-track they are.
LOCAL angle AS DOUBLE = TBGL_EntityGetAngleXY(%sScene, entity, hoverData.nextWayPoint, %TBGL_Y) ' -- The front part is on Y axis
LOCAL distanceTo AS DOUBLE = TBGL_EntityGetDistance(%sScene, entity, hoverData.nextWayPoint)
LOCAL distanceFrom AS DOUBLE = TBGL_EntityGetDistance(%sScene, entity, hoverData.thisWayPoint)

' This is my crude point cycle code and general direction adjustments.
' TrackWidth is the radius of the point-elbow. The above code, when finished, will not use a simple
' radius to make a destination change, it will know that a point has been passed, not neared.
' The ELSE is a simple check, which will also be modified, and used to trigger a slow-down and turn
' as it approaches a destination point, prior to reaching it.
IF distanceTo < TrackWidth THEN
incr hoverData.thisWayPoint
incr hoverData.nextWayPoint
IF hoverData.thisWayPoint > %eWayPointStart + PointCount THEN hoverData.thisWayPoint = %eWayPointStart
IF hoverData.nextWayPoint > %eWayPointStart + PointCount THEN hoverData.nextWayPoint = %eWayPointStart
ELSE
' Bad code, trying to keep them from looping... Almost works as expected, I am using the wrong points
IF distanceFrom > (distanceFrom - (TrackWidth * 2)) THEN distanceTo = xGFR * 0.6
END IF

' This is NOT the physics, just code to keep them moving...
' This is where all the translated physics will output. The result will be the new "Forces", which will
' be used to determine the NEXT locations. The physics will also perform the collision of the expected
' output location, and those adjustments will be the final output which is used for movement.

' PUSH will be the output of FORCE, including Velocity and Mass.
' TURN XZ will be the output of FORCE-ANGLE, including Velocity and Mass.
' TURN Y will be the output of GROUND-ANGLE or GRAVITY, whichever applies.
' The camera should follow the player, with a little lag on TARGET and on POSITION
' but should always be between the player and the OLD point, along the track.
' The player should be able to spin-around 360deg, and the camera looks forward,
' in the direction that the player should be driving. That will help with slightly better
' conrol, and should reduce screen jitter from hard overturning.
TBGL_EntityTurn(%sScene, entity, 0, 0, (angle * distanceTo * 0.1)/xGFR)
' Dividing the angle by framerate causes issues...
' If frame rate is high, you turn fast and sharp, if framerate is low, you turn wide (Seen by adding many cars.)
' That would result in two people playing the same game, but the faster computer will have more precision.
' This will be replaced by a calculation of FORCE, and the AI selection of controls to combat that force over time.
TBGL_EntityPush(%sScene, entity, 0, (hoverData.velocity * 50 + (distanceTo * 0.1))/xGFR, 0)

END SUB

Petr Schreiber
06-10-2008, 20:07
Hi Jason,

I am in hurry, so fast reply:



BEGIN CONST
%eCamera = 1
%eLight = 2
%eGroundBase = 3
%eWayPointStart = 21
%eHovercraft = 8
END CONST

This is not safe coding, presuming the number of waypoints is user defined and number of hovercrafts as well.
I would do this part as:


BEGIN CONST
%eCamera = 1
%eLight
%eGroundBase
%eWayPointStart
%eHovercraft = %eWayPointStart + PointCount + 1
END CONST


Again, I would appreciate screen of drop-out, no idea what it should be :)


Thanks,
Petr

ISAWHIM
06-10-2008, 23:04
Ok, I think I have captured all the potential values needed for more development.

I have re-aligned all the values, so Y is height, X is N/S, and Z is L/R (Think I have that order correct now.)

I have reduced notation to the minimum... Added a real scale/MPH (Using Meters per second as the base)

The area for AI, when that is complete, is sectioned. (No user input setup yet.)

I have added the area for the collision and physics, (Separate of the AI).

All constants and base-values can be adjusted from the opening GLOBALS. (Corrections noted.)

Just waiting for a sample track. (Looking at the track edit tool now.)


'
' Test of hovercraft AI
' Petr Schreiber, started on 09-26-2008
'

Uses "TBGL"

HiResTimer_Init
GLOBAL xHRT_Old, xHRT_New AS QUAD ' Used to calculate actual frame rate.
xHRT_Old = HiResTimer_Get ' Generic start value, so it is not ZERO

GLOBAL xGFV AS QUAD = (1/60)*1000000 ' Frame value, calculated for the QUAD HighResTimer loop
GLOBAL xGFR AS DOUBLE ' Game Frame Rate (Time-Slice) for TITLE update and real frame-rate values

GLOBAL AI_Count AS BYTE = 50 ' Number of cars to track
GLOBAL PointCount AS BYTE = 22 ' Change with new points 0-21 = 22 points
GLOBAL PointRadius AS DOUBLE = 5 ' 5 meters radius (10 meter diameter)
GLOBAL xUPH AS DOUBLE = 40 ' Kilometers per hour, or Miles per hour, select xKMPH TRUE/FALSE
GLOBAL xKMPH AS BOOLEAN = %FALSE

GLOBAL xMPS AS DOUBLE = 0 ' Converted Meters Per Second (Used for game time-scale do not touch!) 1 unit is one meter.
GLOBAL xMTT AS DOUBLE = 0 ' Meters Total Travel Distance (Recorded for speed calculation checking.)

GLOBAL hWnd AS DWORD

' Convert UPH as Miles or Kilometers, into Meters per second
IF xKMPH THEN
xMPS = (xUPH * 0.277777778) ' 80 units * 0.277777778 = 22.222 meters per second
ELSE
xMPS = (xUPH * 0.44704) ' 50 units * 0.44704 = 22.352 meters per second
END IF

PointCount -= 1 ' Forces 0-X not 1-X count
AI_Count -= 1 ' Forces 0-X not 1-X count

' -- Scene IDs
BEGIN CONST
%sScene = 1
%eCamera ' TopView
%eCamera2 ' Player0 View
%eLight
%eGround ' Waiting for a model track
%eHovercraft ' AI and Player0
%ePointID = %eHovercraft + AI_Count + 1' AI guide marks, for now...
END CONST

FUNCTION TBMAIN()

' -- Create and show window
hWnd = TBGL_CreateWindowEx("Test for hovercraft elemental AI", 800, 600, 32, %TBGL_WS_WINDOWED OR %TBGL_WS_CLOSEBOX OR %TBGL_WS_DONTSIZE)
TBGL_ShowWindow

' -- Create scene
TBGL_SceneCreate(%sScene)
TBGL_UseLighting %TRUE
TBGL_BackColor(0,0,0)
'TBGL_UseTexturing %TRUE
'TBGL_UseBlend %TRUE
TBGL_SetupFog(0,0,0,0,1) ' Sets attributes of fog: R, G, B, Alpha, and density in percents
TBGL_UseFog %FALSE ' Turns on with camera2 view in control area

' -- Create camera
TBGL_SetDrawDistance(500) ' Initial start-up view. Changes with camera in control area
TBGL_EntityCreateCamera(%sScene, %eCamera, 0)
TBGL_EntitySetPos(%sScene, %eCamera, 0, 450, 0)
TBGL_EntitySetTargetPos(%sScene, %eCamera, 0, 0, 0)

' -- Setup viewpoint start
TBGL_EntitySetUse(%sScene, %eCamera, %TRUE) 'Camera is up in the air, fixed on center (X = LR) (Y = UD) on ground
TBGL_EntitySetUse(%sScene, %eCamera2, %FALSE) 'Camera2 is attached to Player0

' -- Create light
TBGL_EntityCreateLight(%sScene, %eLight, 0, %TBGL_LIGHTTYPE_POINT)
TBGL_EntitySetPos(%sScene, %eLight, 0, 200, 0)
TBGL_EntitySetTargetPos(%sScene, %eLight, 0, 0, 0)
'TBGL_SetLightParameter(%GL_LIGHT0, %TBGL_LIGHT_SPECULAR, 1, 1, 1, 1)
'TBGL_UseLightSource(%GL_LIGHT0, %TRUE)

' -- Create Ground
'TBGL_LoadTexture("ground.bmp", 1, %TBGL_TEX_MIPMAP)
TBGL_EntityCreateBox(%sScene, %eGround, 0, 500, 20, 400) ' Change to "(%sScene, %eGroundBase, 0, 800, 600, 3, 1)" for texture map.
TBGL_EntitySetColor(%sScene, %eGround, 80, 80, 80)
TBGL_EntitySetPos(%sScene, %eGround, 0, -11, 0)

' -- Craft Model Generic Data
TBGL_NewList 1
TBGL_UseLighting %FALSE
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex -0.5, 0, -1
TBGL_Vertex 0.5, 0, -1
TBGL_Vertex 0, 0, 1
TBGL_ENDPOLY
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex -0.5, 0, -1
TBGL_Vertex 0, 0.5, -1
TBGL_Vertex 0, 0, 1
TBGL_ENDPOLY
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex 0, 0.5, -1
TBGL_Vertex 0.5, 0, -1
TBGL_Vertex 0, 0, 1
TBGL_ENDPOLY
TBGL_UseLighting %TRUE
TBGL_EndList

' -- Create Craft Format (Expected values for all players and AI)
TYPE tHovercraft
nextPoint AS BYTE ' Point AHEAD
lastPoint AS BYTE ' Point AT, or EXITING
weaponA AS BYTE ' Attributes from value
weaponB AS BYTE ' Attributes from value
weaponC AS BYTE ' Attributes from value
powerD AS BYTE ' Drive (Forward thrust and breaking)
powerT AS BYTE ' Turn (Rotation of vehicle for drive-reposition in turn)
powerS AS BYTE ' Straff (Side drifting, turn bumper)
powerA AS BYTE ' AutoControl (More = precision turn without straff)
shield AS DOUBLE ' Solid number of points (Damage control)
mass AS DOUBLE ' Solid number of pounds (Multiple uses)
height AS DOUBLE ' Y value, Gravity decay based on airTime, when not grounded
airTime AS DOUBLE ' Time off ground (Decay multiplier for gravity)
velocity AS DOUBLE ' Velocity of travel (Rate of Speed)
forceJ AS DOUBLE ' Force of jump (Anti-gravity mod)
angleJ AS DOUBLE ' Angle of jump (Anti-gravity mod)
forceV AS DOUBLE ' Force of velocity (Power of Speed)
angleV AS DOUBLE ' Angle of velocity (Only XY forces, Height is gravity/airTime/jump)
END TYPE

DIM AI_Craft AS tHovercraft

' -- Create Random Crafts
LOCAL x AS BYTE
FOR x = %eHovercraft TO %eHovercraft + AI_Count
TBGL_EntityCreateDLSlot(%sScene, x, 0, 1)
TBGL_EntitySetColor(%sScene, x, RND(0,255), RND(0,255), RND(0,255))
' -- Assign data to it
WITH AI_Craft
.nextPoint = %ePointID+RND(1,PointCount) ' Where am I going next
.lastPoint = %ePointID-1 ' Where am I now, or was I
.weaponA = RND(0, 1) ' Game Option
.weaponB = RND(0, 1) ' Game Option
.weaponC = RND(0, 1) ' Game Option
.powerD = RND(1, 255) ' Game Option
.powerT = RND(1, 255) ' Game Option
.powerS = RND(1, 255) ' Game Option
.powerA = RND(1, 255) ' Game Option
.shield = RND(2000, 1500) ' Game Option
.mass = RND(2000, 1500) ' Game Option
.height = 0 ' Program set in play action
.airTime = 0 ' Program set in play action
.velocity = RNDF(-2.00,2.00) + xMPS ' Program set in play action
.forceJ = 0 ' Program set in play action
.angleJ = 0 ' Program set in play action
.forceV = 0 ' Program set in play action
.angleV = 0 ' Program set in play action
END WITH
TBGL_EntitySetUserData(%sScene, x, AI_Craft)
TBGL_EntitySetPos(%sScene, x, 0, 1, 0)
NEXT

' -- Setup follow camera on Player0
TBGL_EntityCreateCamera(%sScene, %eCamera2, %eHovercraft)
TBGL_EntitySetPos(%sScene, %eCamera2, 0, 5, -12)
TBGL_EntitySetTargetPos(%sScene, %eCamera2, 0, 0, 6)

' -- Setup Track Points
LOCAL i AS BYTE
FOR i = %ePointID TO %ePointID + PointCount
TBGL_EntityCreateCylinderCapped(%sScene, i, 0, PointRadius, PointRadius, 0.5)
TBGL_EntitySetColor(%sScene, i, 255, 128, 0)
NEXT

' -- Hardcoded waypoints
' This is a SUPER LONG track. 1 = 1 meter. Full width is about 700 meters or about 0.44 miles wide.
' Scale speed
TBGL_EntitySetPos(%sScene, %ePointID+0, -50, 0, 100)
TBGL_EntitySetPos(%sScene, %ePointID+1, 0, 0, 100)
TBGL_EntitySetPos(%sScene, %ePointID+2, 0, 0, 150)
TBGL_EntitySetPos(%sScene, %ePointID+3, 50, 0, 150)
TBGL_EntitySetPos(%sScene, %ePointID+4, 50, 0, 100)
TBGL_EntitySetPos(%sScene, %ePointID+5, 100, 0, 100)
TBGL_EntitySetPos(%sScene, %ePointID+6, 100, 0, 50)
TBGL_EntitySetPos(%sScene, %ePointID+7, 100, 0, 0)
TBGL_EntitySetPos(%sScene, %ePointID+8, 150, 0, 0)
TBGL_EntitySetPos(%sScene, %ePointID+9, 200, 0, -50)
TBGL_EntitySetPos(%sScene, %ePointID+10, 200, 0, -100)
TBGL_EntitySetPos(%sScene, %ePointID+11, 150, 0, -150)
TBGL_EntitySetPos(%sScene, %ePointID+12, 100, 0, -150)
TBGL_EntitySetPos(%sScene, %ePointID+13, 50, 0, -100)
TBGL_EntitySetPos(%sScene, %ePointID+14, 0, 0, -150)
TBGL_EntitySetPos(%sScene, %ePointID+15, -50, 0, -100)
TBGL_EntitySetPos(%sScene, %ePointID+16, -125, 0, -50)
TBGL_EntitySetPos(%sScene, %ePointID+17, -150, 0, 0)
TBGL_EntitySetPos(%sScene, %ePointID+18, -200, 0, 0)
TBGL_EntitySetPos(%sScene, %ePointID+19, -200, 0, 50)
TBGL_EntitySetPos(%sScene, %ePointID+20, -150, 0, 50)
TBGL_EntitySetPos(%sScene, %ePointID+21, -75, 0, 75)

' -- Resets status of all keys
TBGL_ResetKeyState()

' -- Main loop
xGFR = TBGL_GetFrameRate ' Initializes framerate, or value = 1, That is bad.
LOCAL z AS BYTE
LOCAL xFTC AS DOUBLE
LOCAL xFTT AS DOUBLE
While TBGL_IsWindow(hWnd)
DoEvents
xGFR = TBGL_GetFrameRate
IF xGFR < 15 THEN xGFR = 15 ' Stops FrameMove issue

xHRT_New = HiResTimer_Get
INCR xFTC
xFTT += xGFR
IF xHRT_New - xHRT_Old >= (xGFV * 60) THEN
TBGL_SetWindowTitle(hWnd, "(LMB = Player), (RMB = Top), " & "(AVG FPS: " & FORMAT$(xFTT/xFTC, "#0.00") & "), (SECONDS: " & FORMAT$(xFTT, "#0.00") & " / FRAMES: " & STR$(xFTC) & " ), (SPD MPH: " & FORMAT$((xMTT/(AI_Count+1))*2.23693629, "#0.0000") & " )")
xFTC = 0
xFTT = 0
xMTT = 0
xHRT_Old = xHRT_New
END IF

'TBGL_ClearFrame

' -- Quick AI, just to push them around the track. (AI INPUT after user input, before next draw.)
' -- May use (Collision Detection 1 MOD, Collision Detection 2 MOD) functions directly
FOR z = %eHovercraft TO %eHovercraft + AI_Count
HoverCraft_AI(z)
NEXT

' -- Location for PHYSICS and COLLISION loops (Reaction to USER and AI input.)
' -- Once AI has decided what move to make... Collision and Physics take over.
' -- AI is only a reaction to the situation presented by physics and collision.
' -- AI is subject to all control and game physics that any player is subjet to.
' General loop is (0-1, 0-2, 0-3, 1-2, 1-3, 2-3)
' Physics Decay MOD, User Input MOD, Collision Decay MOD
' Collision Detection 1 MOD, Collision Detection 2 MOD
'
' MOD APPLY
' DRAW SCREEN
' COLLECT USER INPUT (Reaction to view)
' NEXT LOOP


' Quick video control
' NON GAME INPUT, View, Pause, Mute
IF TBGL_GetWindowKeyState(hWnd, %VK_RBUTTON) THEN
TBGL_EntitySetUse(%sScene, %eCamera2, %FALSE)
TBGL_EntitySetUse(%sScene, %eCamera, %TRUE)
TBGL_SetDrawDistance(800)
TBGL_UseFog %FALSE
END IF

IF TBGL_GetWindowKeyState(hWnd, %VK_LBUTTON) THEN
TBGL_EntitySetUse(%sScene, %eCamera, %FALSE)
TBGL_EntitySetUse(%sScene, %eCamera2, %TRUE)
TBGL_SetDrawDistance(400)
TBGL_UseFog %TRUE
END IF

TBGL_ClearFrame
TBGL_SceneRender(%sScene)
TBGL_DrawFrame

' -- TRUE GAME INPUT FROM USER HERE (Away from the thinking code)
' -- RESERVED

' -- ESCAPE key to exit application
If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While
Wend

TBGL_SceneDestroy(%sScene)
TBGL_DestroyWindow
END FUNCTION

Sub HoverCraft_AI(entity AS LONG)
LOCAL AI_Craft AS tHovercraft PTR

' -- Retrieve data from entity
AI_Craft = TBGL_EntityGetUserDataPointer(%sScene, entity)

' -- Get angle and distance to next waypoint (Might want to change to global values)
LOCAL angle AS DOUBLE = TBGL_EntityGetAngleXZ(%sScene, entity, AI_Craft.nextPoint, %TBGL_Z)
LOCAL distanceTo AS DOUBLE = TBGL_EntityGetDistance(%sScene, entity, AI_Craft.nextPoint)
LOCAL distanceFrom AS DOUBLE = TBGL_EntityGetDistance(%sScene, entity, AI_Craft.lastPoint)

IF distanceTo < PointRadius THEN
incr AI_Craft.lastPoint
incr AI_Craft.nextPoint
IF AI_Craft.lastPoint > %ePointID + PointCount THEN AI_Craft.lastPoint = %ePointID
IF AI_Craft.nextPoint > %ePointID + PointCount THEN AI_Craft.nextPoint = %ePointID
ELSE
' Bad code, trying to keep them from looping... Almost works as expected, I am using the wrong points
IF distanceFrom > (distanceFrom - (PointRadius * 2)) THEN distanceTo = xGFR * 0.3
END IF

TBGL_EntityTurn(%sScene, entity, 0, (angle * distanceTo * 0.08)/xGFR, 0)
TBGL_EntityPush(%sScene, entity, 0, 0, (AI_Craft.velocity)/xGFR)
xMTT += (AI_Craft.velocity)/xGFR ' Fixed velocity for testing scale

END SUB

Petr Schreiber
07-10-2008, 16:26
Hi Jason,

thanks for the code.
Just few details, not important for functionality but good for learning TBGL:

As help file says, "Please notice it is NOT necessary to call TWICE TBGL_BeginPoly / TBGL_EndPoly to create two triangles".
So if you compose hovercraft from 3 triangles, you can still use TBGL_BeginPoly / TBGL_EndPoly once, and just define 3 triplets of vertex data.

To create floor, you can use %GL_QUAD primitive type.

Keep up the nice updates.


Petr

P.S. I added back side to vehicles, so Z-Fighting of hovercrouft floor and ground is not visible.



'
' Test of hovercraft AI
' Petr Schreiber and Jason, started on 09-26-2008
'
'

Uses "TBGL"

HiResTimer_Init
GLOBAL xHRT_Old, xHRT_New AS QUAD ' Used to calculate actual frame rate.
xHRT_Old = HiResTimer_Get

' NOTE: Having a frame upper limit, helps to ensure that sufficient time has passed
' before doing further calculation on insignificant game factors. Collision, Gravity,
' Air Resistance, Memory Dumping, Interruption, Key Calls, Drawing...

GLOBAL xGFV AS QUAD = (1/60)*1000000 ' Frame value, calculated for the QUAD HighResTimer loop
GLOBAL xGFR AS DOUBLE ' Game Frame Rate (Time-Slice)

GLOBAL PointCount AS LONG = 21 ' Change with new points
GLOBAL CraftCount AS LONG = 500 ' Number of cars to draw
GLOBAL TrackWidth AS DOUBLE = 8 ' 5 meters wide 10 meter diameter
GLOBAL cX, cY, cZ AS DOUBLE ' Used for camera positions
GLOBAL hWnd AS DWORD

' -- Scene IDs
BEGIN CONST
%sScene = 1
%eCamera
%eCamera2
%eLight
%eGroundBase
%eWayPointStart
%eHovercraft = %eWayPointStart + PointCount + 1

END CONST

' Display lists
begin const
%listVehicle = 1
%listGround
end const

'MSGBOX 0, %sScene & CRLF & %eCamera & CRLF & %eCamera2 & CRLF & %eLight & CRLF & %eGroundBase & CRLF & %eWayPointStart & CRLF & %eHovercraft & CRLF & %eHovercraft+1

FUNCTION TBMAIN()

' -- Create and show window
hWnd = TBGL_CreateWindowEx("Test for hovercraft elemental AI", 800, 600, 32, %TBGL_WS_WINDOWED OR %TBGL_WS_CLOSEBOX OR %TBGL_WS_DONTSIZE)
TBGL_ShowWindow

' -- Create scene
TBGL_SceneCreate(%sScene)
TBGL_UseLighting %TRUE
TBGL_BackColor(0,0,0)
'TBGL_UseTexturing %TRUE
'TBGL_UseBlend %TRUE
TBGL_SetupFog(0,0,0,0,1) ' Sets attributes of fog: R, G, B, Alpha, and density in percents
TBGL_UseFog %FALSE

' -- Create camera
TBGL_SetDrawDistance(800)
TBGL_EntityCreateCamera(%sScene, %eCamera, 0)
TBGL_EntitySetPos(%sScene, %eCamera, 0, 0, 700)
TBGL_EntitySetTargetPos(%sScene, %eCamera, 0, 0, 0)
TBGL_EntitySetUse(%sScene, %eCamera, %TRUE)
TBGL_EntitySetUse(%sScene, %eCamera2, %FALSE)

' -- Create light
TBGL_EntityCreateLight(%sScene, %eLight, 0, %TBGL_LIGHTTYPE_POINT)
TBGL_EntitySetPos(%sScene, %eLight, 0, 0, 300)
TBGL_EntitySetTargetPos(%sScene, %eLight, 0, 0, 0)
'TBGL_SetLightParameter(%GL_LIGHT0, %TBGL_LIGHT_SPECULAR, 1, 1, 1, 1)
'TBGL_UseLightSource(%GL_LIGHT0, %TRUE)

' -- Create Ground

TBGL_NewList %listGround
TBGL_UseLighting %FALSE
TBGL_BeginPoly %GL_QUADS
TBGL_Vertex -1, -1
TBGL_Vertex 1, -1
TBGL_Vertex 1, 1
TBGL_Vertex -1, 1
TBGL_ENDPOLY

TBGL_UseLighting %TRUE
TBGL_EndList

'TBGL_LoadTexture("ground.bmp", 1, %TBGL_TEX_MIPMAP)
TBGL_EntityCreateDLSlot(%sScene, %eGroundBase, 0, %listGround)
TBGL_EntitySetColor(%sScene, %eGroundBase, 80, 80, 80)
TBGL_EntitySetscale(%sScene, %eGroundBase, 400, 300, 1)
TBGL_EntitySetPos(%sScene, %eGroundBase, 0, 0, 0)

' -- Craft Model Data
TBGL_NewList %listVehicle
TBGL_UseLighting %FALSE
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex -1, -2, 0
TBGL_Vertex 1, -2, 0
TBGL_Vertex 0, 2, 0

TBGL_Vertex -1, -2, 0
TBGL_Vertex 0, -2, 1
TBGL_Vertex 0, 2, 0

TBGL_Vertex 0, -2, 1
TBGL_Vertex 1, -2, 0
TBGL_Vertex 0, 2, 0

TBGL_Vertex 0, -2, 1
TBGL_Vertex -1, -2, 0
TBGL_Vertex 1, -2, 0

TBGL_ENDPOLY
TBGL_UseLighting %TRUE
TBGL_EndList

' -- Create Craft Format
TYPE tHoverCraft
nextWayPoint AS LONG
thisWayPoint AS LONG
numWayPoint AS LONG
mass AS double
velocity AS double
force AS double
angleXY AS double
angleXZ AS double
angleYZ AS double
END TYPE
DIM HoverInfo AS tHoverCraft

' -- Create Random Crafts
LOCAL x AS LONG
FOR x = %eHovercraft TO %eHovercraft + CraftCount
TBGL_EntityCreateDLSlot(%sScene, x, 0, 1)
TBGL_EntitySetColor(%sScene, x, RND(0,255), RND(0,255), RND(0,255))
' -- Assign data to it
WITH HoverInfo
.nextWayPoint = %eWayPointStart+RND(1,21) ' Where am I going next
.thisWayPoint = %eWayPointStart-1 ' Where am I now
.numWayPoint = PointCount ' Not sure if this is used, or relevant (Game value not craft value.)
.mass = RNDF(0.80, 1.00) ' Not used yet
.velocity = RNDF(0.80, 1.00) ' Not used yet
.force = RNDF(0.10, 1.00) ' Not used yet
.angleXY = RND(-180, 180) ' Not used yet
.angleXZ = RND(-180, 180) ' Not used yet
.angleYZ = RND(-180, 180) ' Not used yet
END WITH
TBGL_EntitySetUserData(%sScene, x, HoverInfo)
TBGL_EntitySetPos(%sScene, x, 0, 0, 0)
NEXT

TBGL_EntityCreateCamera(%sScene, %eCamera2, %eHovercraft)
TBGL_EntitySetPos(%sScene, %eCamera2, 0, -40, 40)
TBGL_EntitySetTargetPos(%sScene, %eCamera2, 0, 30, 0)

' -- Setup Track Points
LOCAL i AS LONG
FOR i = %eWayPointStart TO %eWayPointStart + PointCount
TBGL_EntityCreateBox(%sScene, i, 0, 1, 1, 4)
TBGL_EntitySetColor(%sScene, i, 255, 128, 0)
NEXT

' -- Hardcoded waypoints
' This is a SUPER LONG track. 1 = 1 meter. Full width is about 700 meters or about 0.44 miles wide.
' Scale speed
TBGL_EntitySetPos(%sScene, %eWayPointStart+0, -50, 50, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+1, 0, 150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+2, 100, 200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+3, 150, 125, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+4, 250, 0, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+5, 325, 25, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+6, 350, 150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+7, 325, 200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+8, 200, 275, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+9, -150, 250, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+10, -300, 200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+11, -325, 150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+12, -250, 75, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+13, -175, 25, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+14, -200, -75, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+15, -250, -150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+16, -200, -200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+17, -25, -225, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+18, 275, -250, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+19, 300, -200, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+20, 275, -150, 0)
TBGL_EntitySetPos(%sScene, %eWayPointStart+21, 175, -50, 0)

' -- Resets status of all keys
TBGL_ResetKeyState()

' -- Main loop
xGFR = TBGL_GetFrameRate ' Initializes framerate, or value = 1, That is bad.
GLOBAL z AS LONG
GLOBAL xFrameTimeCount AS DOUBLE
GLOBAL xFrameTimeTotal AS DOUBLE
While TBGL_IsWindow(hWnd)
DoEvents
xGFR = TBGL_GetFrameRate
IF xGFR < 2 THEN xGFR = TBGL_GetFrameRate ' Stops FrameMove issue

xHRT_New = HiResTimer_Get
INCR xFrameTimeCount
xFrameTimeTotal += xGFR
IF xHRT_New - xHRT_Old >= (xGFV * 60) THEN
TBGL_SetWindowTitle(hWnd, "(LMB = Follow Car#1), (RMB = TopView), " & "(AVG FPS: " & FORMAT$(xFrameTimeTotal/xFrameTimeCount, "#0.00") & "), (SECONDS: " & FORMAT$(xFrameTimeTotal, "#0.00") & " / FRAMES: " & STR$(xFrameTimeCount) & " )")
xFrameTimeCount = 0
xFrameTimeTotal = 0
xHRT_Old = xHRT_New
END IF

TBGL_ClearFrame

FOR z = %eHovercraft TO %eHovercraft + CraftCount
HoverCraft_AI(z)
NEXT

' Quick video control
IF TBGL_GetWindowKeyState(hWnd, %VK_RBUTTON) THEN
TBGL_EntitySetUse(%sScene, %eCamera2, %FALSE)
TBGL_EntitySetUse(%sScene, %eCamera, %TRUE)
TBGL_SetDrawDistance(800)
TBGL_UseFog %FALSE

END IF

IF TBGL_GetWindowKeyState(hWnd, %VK_LBUTTON) THEN
TBGL_EntitySetUse(%sScene, %eCamera, %FALSE)
TBGL_EntitySetUse(%sScene, %eCamera2, %TRUE)
TBGL_SetDrawDistance(200)
TBGL_UseFog %TRUE

END IF

TBGL_SceneRender(%sScene)
TBGL_DrawFrame

' -- ESCAPE key to exit application
If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While
Wend

TBGL_SceneDestroy(%sScene)
TBGL_DestroyWindow
END FUNCTION

Sub HoverCraft_AI( entity AS LONG )
LOCAL hoverData AS tHoverCraft PTR

' -- Retrieve data from entity
hoverData = TBGL_EntityGetUserDataPointer(%sScene, entity)

' -- Get angle and distance to next waypoint
' This will be the LOOKING that the vehicles will do, to determine if they are going to veer left/right
' also, the distance from will be compared to the distance between points, to determine if the vehicle
' should speed-up or slow-down, and identify how far off-track they are.
LOCAL angle AS DOUBLE = TBGL_EntityGetAngleXY(%sScene, entity, hoverData.nextWayPoint, %TBGL_Y) ' -- The front part is on Y axis
LOCAL distanceTo AS DOUBLE = TBGL_EntityGetDistance(%sScene, entity, hoverData.nextWayPoint)
LOCAL distanceFrom AS DOUBLE = TBGL_EntityGetDistance(%sScene, entity, hoverData.thisWayPoint)

' This is my crude point cycle code and general direction adjustments.
' TrackWidth is the radius of the point-elbow. The above code, when finished, will not use a simple
' radius to make a destination change, it will know that a point has been passed, not neared.
' The ELSE is a simple check, which will also be modified, and used to trigger a slow-down and turn
' as it approaches a destination point, prior to reaching it.
IF distanceTo < TrackWidth THEN
incr hoverData.thisWayPoint
incr hoverData.nextWayPoint
IF hoverData.thisWayPoint > %eWayPointStart + PointCount THEN hoverData.thisWayPoint = %eWayPointStart
IF hoverData.nextWayPoint > %eWayPointStart + PointCount THEN hoverData.nextWayPoint = %eWayPointStart
ELSE
' Bad code, trying to keep them from looping... Almost works as expected, I am using the wrong points
IF distanceFrom > (distanceFrom - (TrackWidth * 2)) THEN distanceTo = xGFR * 0.6
END IF

' This is NOT the physics, just code to keep them moving...
' This is where all the translated physics will output. The result will be the new "Forces", which will
' be used to determine the NEXT locations. The physics will also perform the collision of the expected
' output location, and those adjustments will be the final output which is used for movement.

' PUSH will be the output of FORCE, including Velocity and Mass.
' TURN XZ will be the output of FORCE-ANGLE, including Velocity and Mass.
' TURN Y will be the output of GROUND-ANGLE or GRAVITY, whichever applies.
' The camera should follow the player, with a little lag on TARGET and on POSITION
' but should always be between the player and the OLD point, along the track.
' The player should be able to spin-around 360deg, and the camera looks forward,
' in the direction that the player should be driving. That will help with slightly better
' conrol, and should reduce screen jitter from hard overturning.
TBGL_EntityTurn(%sScene, entity, 0, 0, (angle * distanceTo * 0.1)/xGFR)
' Dividing the angle by framerate causes issues...
' If frame rate is high, you turn fast and sharp, if framerate is low, you turn wide (Seen by adding many cars.)
' That would result in two people playing the same game, but the faster computer will have more precision.
' This will be replaced by a calculation of FORCE, and the AI selection of controls to combat that force over time.
TBGL_EntityPush(%sScene, entity, 0, (hoverData.velocity * 50 + (distanceTo * 0.1))/xGFR, 0)

END SUB

ISAWHIM
07-10-2008, 22:15
I will merge the changes into the new file format from my last post...

I was wondering about the vertice thing. (Hehe, it was your code. ;) )

I know, it was originally only a demo... But I am turning it into a development playground, for general use now.

I will be moving all SCENE items into a SUB at the bottom, to move them out of the way, so new development stays on top, and can be added as functions or subs to this file. (Or includes) which would be merged later.

Be back tonight with the changes, and hopefully some of that promised physics translated into thinBasic.

I changed the code to this... but can't seem to get the texture to load now... It worked before?

I tried setting to the poly, and to the ground object... Just turns the ground red... (Image is white with red-border 512x512 BMP)


'
' Test of hovercraft AI
' Petr Schreiber, started on 09-26-2008
'

Uses "TBGL"

HiResTimer_Init
GLOBAL xHRT_Old, xHRT_New AS QUAD ' Used to calculate actual frame rate.
xHRT_Old = HiResTimer_Get ' Generic start value, so it is not ZERO

GLOBAL xGFV AS QUAD = (1/60)*1000000 ' Frame value, calculated for the QUAD HighResTimer loop
GLOBAL xGFR AS DOUBLE ' Game Frame Rate (Time-Slice) for TITLE update and real frame-rate values

GLOBAL AI_Count AS BYTE = 50 ' Number of cars to track
GLOBAL PointCount AS BYTE = 22 ' Change with new points 0-21 = 22 points
GLOBAL PointRadius AS DOUBLE = 5 ' 5 meters radius (10 meter diameter)
GLOBAL xUPH AS DOUBLE = 40 ' Kilometers per hour, or Miles per hour, select xKMPH TRUE/FALSE
GLOBAL xKMPH AS BOOLEAN = %FALSE

GLOBAL xMPS AS DOUBLE = 0 ' Converted Meters Per Second (Used for game time-scale do not touch!) 1 unit is one meter.
GLOBAL xMTT AS DOUBLE = 0 ' Meters Total Travel Distance (Recorded for speed calculation checking.)

GLOBAL hWnd AS DWORD

' Convert UPH as Miles or Kilometers, into Meters per second
IF xKMPH THEN
xMPS = (xUPH * 0.277777778) ' 80 units * 0.277777778 = 22.222 meters per second
ELSE
xMPS = (xUPH * 0.44704) ' 50 units * 0.44704 = 22.352 meters per second
END IF

PointCount -= 1 ' Forces 0-X not 1-X count
AI_Count -= 1 ' Forces 0-X not 1-X count

' -- Scene IDs
BEGIN CONST
%sScene = 1
%eCamera ' TopView
%eCamera2 ' Player0 View
%eLight
%eGround
%eHovercraft ' AI and Player0
%ePointID = %eHovercraft + AI_Count + 1' AI guide marks, for now...
END CONST

' Display lists
BEGIN CONST
%listHovercraft = 1
%listGround
END CONST

' Image lists
BEGIN CONST
%iGround = 1
END CONST

FUNCTION TBMAIN()

' -- Create and show window
hWnd = TBGL_CreateWindowEx("Test for hovercraft elemental AI", 800, 600, 32, %TBGL_WS_WINDOWED OR %TBGL_WS_CLOSEBOX OR %TBGL_WS_DONTSIZE)
TBGL_ShowWindow

' -- Create scene
TBGL_SceneCreate(%sScene)
TBGL_UseLighting %TRUE
TBGL_BackColor(0,0,0)
TBGL_UseTexturing %TRUE
'TBGL_UseBlend %TRUE
TBGL_SetupFog(0,0,0,0,1) ' Sets attributes of fog: R, G, B, Alpha, and density in percents
TBGL_UseFog %FALSE ' Turns on with camera2 view in control area

' -- Create camera
TBGL_SetDrawDistance(500) ' Initial start-up view. Changes with camera in control area
TBGL_EntityCreateCamera(%sScene, %eCamera, 0)
TBGL_EntitySetPos(%sScene, %eCamera, 0, 450, 0)
TBGL_EntitySetTargetPos(%sScene, %eCamera, 0, 0, 0)

' -- Setup viewpoint start
TBGL_EntitySetUse(%sScene, %eCamera, %TRUE) 'Camera is up in the air, fixed on center (X = LR) (Y = UD) on ground
TBGL_EntitySetUse(%sScene, %eCamera2, %FALSE) 'Camera2 is attached to Player0

' -- Create light
TBGL_EntityCreateLight(%sScene, %eLight, 0, %TBGL_LIGHTTYPE_POINT)
TBGL_EntitySetPos(%sScene, %eLight, 0, 200, 0)
TBGL_EntitySetTargetPos(%sScene, %eLight, 0, 0, 0)
'TBGL_SetLightParameter(%GL_LIGHT0, %TBGL_LIGHT_SPECULAR, 1, 1, 1, 1)
'TBGL_UseLightSource(%GL_LIGHT0, %TRUE)

' -- Create Ground
TBGL_NewList %listGround
TBGL_UseLighting %FALSE
TBGL_BeginPoly %GL_QUADS
TBGL_Vertex -10, 0, -10
TBGL_Vertex 10, 0, -10
TBGL_Vertex 10, 0, 10
TBGL_Vertex -10, 0, 10
TBGL_EndPoly
TBGL_UseLighting %TRUE
TBGL_EndList

TBGL_EntityCreateDLSlot(%sScene, %eGround, 0, %listGround)
'TBGL_LoadTexture("ground.bmp", %iGround, %TBGL_TEX_MIPMAP)
'TBGL_EntitySetTexture(%sScene, %eGround, %iGround)
TBGL_EntitySetColor(%sScene, %eGround, 80, 80, 80)
TBGL_EntitySetscale(%sScene, %eGround, 30, 1, 25)
TBGL_EntitySetPos(%sScene, %eGround, 0, 0, 0)

' -- Craft Model Generic Data
TBGL_NewList %listHovercraft
TBGL_UseLighting %FALSE
TBGL_BeginPoly %GL_TRIANGLES
TBGL_Vertex -0.5, 0, -1
TBGL_Vertex 0.5, 0, -1
TBGL_Vertex 0, 0, 1

TBGL_Vertex -0.5, 0, -1
TBGL_Vertex 0, 0.5, -1
TBGL_Vertex 0, 0, 1

TBGL_Vertex 0, 0.5, -1
TBGL_Vertex 0.5, 0, -1
TBGL_Vertex 0, 0, 1

TBGL_Vertex 0, 0.5, -1
TBGL_Vertex -0.5, 0, -1
TBGL_Vertex 0.5, 0, -1
TBGL_ENDPOLY
TBGL_UseLighting %TRUE
TBGL_EndList

' -- Create Craft Format (Expected values for all players and AI)
TYPE tHovercraft
nextPoint AS BYTE ' Point AHEAD
lastPoint AS BYTE ' Point AT, or EXITING
weaponA AS BYTE ' Attributes from value
weaponB AS BYTE ' Attributes from value
weaponC AS BYTE ' Attributes from value
powerD AS BYTE ' Drive (Forward thrust and breaking)
powerT AS BYTE ' Turn (Rotation of vehicle for drive-reposition in turn)
powerS AS BYTE ' Straff (Side drifting, turn bumper)
powerA AS BYTE ' AutoControl (More = precision turn without straff)
shield AS DOUBLE ' Solid number of points (Damage control)
mass AS DOUBLE ' Solid number of pounds (Multiple uses)
height AS DOUBLE ' Y value, Gravity decay based on airTime, when not grounded
airTime AS DOUBLE ' Time off ground (Decay multiplier for gravity)
velocity AS DOUBLE ' Velocity of travel (Rate of Speed)
forceJ AS DOUBLE ' Force of jump (Anti-gravity mod)
angleJ AS DOUBLE ' Angle of jump (Anti-gravity mod)
forceV AS DOUBLE ' Force of velocity (Power of Speed)
angleV AS DOUBLE ' Angle of velocity (Only XY forces, Height is gravity/airTime/jump)
END TYPE

DIM AI_Craft AS tHovercraft

' -- Create Random Crafts
LOCAL x AS BYTE
FOR x = %eHovercraft TO %eHovercraft + AI_Count
TBGL_EntityCreateDLSlot(%sScene, x, 0, %listHovercraft)
TBGL_EntitySetColor(%sScene, x, RND(0,255), RND(0,255), RND(0,255))
' -- Assign data to it
WITH AI_Craft
.nextPoint = %ePointID+RND(1,PointCount) ' Where am I going next
.lastPoint = %ePointID-1 ' Where am I now, or was I
.weaponA = RND(0, 1) ' Game Option
.weaponB = RND(0, 1) ' Game Option
.weaponC = RND(0, 1) ' Game Option
.powerD = RND(1, 255) ' Game Option
.powerT = RND(1, 255) ' Game Option
.powerS = RND(1, 255) ' Game Option
.powerA = RND(1, 255) ' Game Option
.shield = RND(2000, 1500) ' Game Option
.mass = RND(2000, 1500) ' Game Option
.height = 0 ' Program set in play action
.airTime = 0 ' Program set in play action
.velocity = RNDF(-2.00,2.00) + xMPS ' Program set in play action
.forceJ = 0 ' Program set in play action
.angleJ = 0 ' Program set in play action
.forceV = 0 ' Program set in play action
.angleV = 0 ' Program set in play action
END WITH
TBGL_EntitySetUserData(%sScene, x, AI_Craft)
TBGL_EntitySetPos(%sScene, x, 0, 1, 0)
NEXT

' -- Setup follow camera on Player0
TBGL_EntityCreateCamera(%sScene, %eCamera2, %eHovercraft)
TBGL_EntitySetPos(%sScene, %eCamera2, 0, 5, -12)
TBGL_EntitySetTargetPos(%sScene, %eCamera2, 0, 0, 6)

' -- Setup Track Points
LOCAL i AS BYTE
FOR i = %ePointID TO %ePointID + PointCount
TBGL_EntityCreateCylinderCapped(%sScene, i, 0, PointRadius, PointRadius, 0.5)
TBGL_EntitySetColor(%sScene, i, 255, 128, 0)
NEXT

' -- Hardcoded waypoints
' This is a SUPER LONG track. 1 = 1 meter. Full width is about 700 meters or about 0.44 miles wide.
' Scale speed
TBGL_EntitySetPos(%sScene, %ePointID+0, -50, 0, 100)
TBGL_EntitySetPos(%sScene, %ePointID+1, 0, 0, 100)
TBGL_EntitySetPos(%sScene, %ePointID+2, 0, 0, 150)
TBGL_EntitySetPos(%sScene, %ePointID+3, 50, 0, 150)
TBGL_EntitySetPos(%sScene, %ePointID+4, 50, 0, 100)
TBGL_EntitySetPos(%sScene, %ePointID+5, 100, 0, 100)
TBGL_EntitySetPos(%sScene, %ePointID+6, 100, 0, 50)
TBGL_EntitySetPos(%sScene, %ePointID+7, 100, 0, 0)
TBGL_EntitySetPos(%sScene, %ePointID+8, 150, 0, 0)
TBGL_EntitySetPos(%sScene, %ePointID+9, 200, 0, -50)
TBGL_EntitySetPos(%sScene, %ePointID+10, 200, 0, -100)
TBGL_EntitySetPos(%sScene, %ePointID+11, 150, 0, -150)
TBGL_EntitySetPos(%sScene, %ePointID+12, 100, 0, -150)
TBGL_EntitySetPos(%sScene, %ePointID+13, 50, 0, -100)
TBGL_EntitySetPos(%sScene, %ePointID+14, 0, 0, -150)
TBGL_EntitySetPos(%sScene, %ePointID+15, -50, 0, -100)
TBGL_EntitySetPos(%sScene, %ePointID+16, -125, 0, -50)
TBGL_EntitySetPos(%sScene, %ePointID+17, -150, 0, 0)
TBGL_EntitySetPos(%sScene, %ePointID+18, -200, 0, 0)
TBGL_EntitySetPos(%sScene, %ePointID+19, -200, 0, 50)
TBGL_EntitySetPos(%sScene, %ePointID+20, -150, 0, 50)
TBGL_EntitySetPos(%sScene, %ePointID+21, -75, 0, 75)

' -- Resets status of all keys
TBGL_ResetKeyState()

' -- Main loop
xGFR = TBGL_GetFrameRate ' Initializes framerate, or value = 1, That is bad.
LOCAL z AS BYTE
LOCAL xFTC AS DOUBLE
LOCAL xFTT AS DOUBLE
While TBGL_IsWindow(hWnd)
DoEvents
xGFR = TBGL_GetFrameRate
IF xGFR < 15 THEN xGFR = 15 ' Stops FrameMove issue

xHRT_New = HiResTimer_Get
INCR xFTC
xFTT += xGFR
IF xHRT_New - xHRT_Old >= (xGFV * 60) THEN
TBGL_SetWindowTitle(hWnd, "(LMB = Player), (RMB = Top), " & "(AVG FPS: " & FORMAT$(xFTT/xFTC, "#0.00") & "), (SECONDS: " & FORMAT$(xFTT, "#0.00") & " / FRAMES: " & STR$(xFTC) & " ), (SPD MPH: " & FORMAT$((xMTT/(AI_Count+1))*2.23693629, "#0.0000") & " )")
xFTC = 0
xFTT = 0
xMTT = 0
xHRT_Old = xHRT_New
END IF

'TBGL_ClearFrame

' -- Quick AI, just to push them around the track. (AI INPUT after user input, before next draw.)
' -- May use (Collision Detection 1 MOD, Collision Detection 2 MOD) functions directly
FOR z = %eHovercraft TO %eHovercraft + AI_Count
HoverCraft_AI(z)
NEXT

' -- Location for PHYSICS and COLLISION loops (Reaction to USER and AI input.)
' -- Once AI has decided what move to make... Collision and Physics take over.
' -- AI is only a reaction to the situation presented by physics and collision.
' -- AI is subject to all control and game physics that any player is subjet to.
' General loop is (0-1, 0-2, 0-3, 1-2, 1-3, 2-3)
' Physics Decay MOD, User Input MOD, Collision Decay MOD
' Collision Detection 1 MOD, Collision Detection 2 MOD
'
' MOD APPLY
' DRAW SCREEN
' COLLECT USER INPUT (Reaction to view)
' NEXT LOOP


' Quick video control
' NON GAME INPUT, View, Pause, Mute
IF TBGL_GetWindowKeyState(hWnd, %VK_RBUTTON) THEN
TBGL_EntitySetUse(%sScene, %eCamera2, %FALSE)
TBGL_EntitySetUse(%sScene, %eCamera, %TRUE)
TBGL_SetDrawDistance(800)
TBGL_UseFog %FALSE
END IF

IF TBGL_GetWindowKeyState(hWnd, %VK_LBUTTON) THEN
TBGL_EntitySetUse(%sScene, %eCamera, %FALSE)
TBGL_EntitySetUse(%sScene, %eCamera2, %TRUE)
TBGL_SetDrawDistance(400)
TBGL_UseFog %TRUE
END IF

TBGL_ClearFrame
TBGL_SceneRender(%sScene)
TBGL_DrawFrame

' -- TRUE GAME INPUT FROM USER HERE (Away from the thinking code)
' -- RESERVED

' -- ESCAPE key to exit application
If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While
Wend

TBGL_SceneDestroy(%sScene)
TBGL_DestroyWindow
END FUNCTION

Sub HoverCraft_AI(entity AS LONG)
LOCAL AI_Craft AS tHovercraft PTR

' -- Retrieve data from entity
AI_Craft = TBGL_EntityGetUserDataPointer(%sScene, entity)

' -- Get angle and distance to next waypoint (Might want to change to global values)
LOCAL angle AS DOUBLE = TBGL_EntityGetAngleXZ(%sScene, entity, AI_Craft.nextPoint, %TBGL_Z)
LOCAL distanceTo AS DOUBLE = TBGL_EntityGetDistance(%sScene, entity, AI_Craft.nextPoint)
LOCAL distanceFrom AS DOUBLE = TBGL_EntityGetDistance(%sScene, entity, AI_Craft.lastPoint)

IF distanceTo < PointRadius THEN
incr AI_Craft.lastPoint
incr AI_Craft.nextPoint
IF AI_Craft.lastPoint > %ePointID + PointCount THEN AI_Craft.lastPoint = %ePointID
IF AI_Craft.nextPoint > %ePointID + PointCount THEN AI_Craft.nextPoint = %ePointID
ELSE
' Bad code, trying to keep them from looping... Almost works as expected, I am using the wrong points
IF distanceFrom > (distanceFrom - (PointRadius * 2)) THEN distanceTo = xGFR * 0.3
END IF

TBGL_EntityTurn(%sScene, entity, 0, (angle * distanceTo * 0.08)/xGFR, 0)
TBGL_EntityPush(%sScene, entity, 0, 0, (AI_Craft.velocity)/xGFR)
xMTT += (AI_Craft.velocity)/xGFR ' Fixed velocity for testing scale

END SUB

Petr Schreiber
07-10-2008, 23:12
Hi,

check SampleScripts folder first to see how should you use TBGL_TexCoord2D for texturing polygonal objects.


Petr

ISAWHIM
08-10-2008, 10:45
Ok, I have a solid velocity control now. (For the most part.)

Lights-on, Fog-on, Image ground (512x512)...

Does 800 crafts, 300 miles an hour, at 21FPS... No loopers... (Not easy to play. LOL. Push it to 600MPH!)
Does 400 crafts, 300 miles an hour, at 42FPS...
Does 200 crafts, 300 miles an hour, at 71FPS...
Does 100 crafts, 300 miles an hour, at 130FPS...
Does 10 crafts, 300 miles an hour, at 292FPS...

Faster frame rate does not alter physics. It does make them more accurate.

Slower velocity, translates into more ability to function, without change in settings. (As opposed to altering speed and control, or measuring distances, or tracking time.)

I know that 60 MPH looks like it is on the slow side, but that is due to the nature of no scale objects in the scene. Thus, my ghetto flat-track. The "Bleacher View", is a modest representation of good scale. 200 MPH looks like 200 MPH, while 20 MPH looks like 20 MPH. (The speed is formulated based off real values, with a game-scale of 1 = 1 meter.)

This is not AI brains yet... (The track physics are still only a guide for them to use. No "Thinking" has been programmed.)

Next comes MASS and Thrust forces... We should be able to drive around soon.

For testing, I may introduce a direction indicator or a destination flag for each segment cleared, and next to clear. (Without walls, and the tiny track turns... it is easy to loose direction of which segment you triggered. EG, if you made it to the finish, and missed a trigger point, you did not finish. They will need to know they missed a zone/location, if the map is not constrained to a tube-area.)

Not sure how high we want to jump, so gravity for now, will be super loose...

Hope this attaches... The image makes it more fun!

Michael Clease
08-10-2008, 13:43
Just though I would let you know that on my 6800GS i am getting about 80 FPS with 10 cars at all speeds.

I will try my work computer to compare but given that my work computer has an intel OnBoard Gfx card i dont hold out much hope.

ISAWHIM
08-10-2008, 14:03
Just though I would let you know that on my 6800GS i am getting about 80 FPS with 10 cars at all speeds.

I will try my work computer to compare but given that my work computer has an intel OnBoard Gfx card i dont hold out much hope.

Odd... Might be the DoEvents is a little taxing... Have you tried playing with the code to see what is bogging it down? (The code I added is hardly tuned. I used the duct-tape method, but I use scissors to cut the tape, so it looks neat.)

Have you tried any of the demo-programs with this new 1.7.0.0 version? (The updated 1.7 in the link above, in the news.)

I do use FOG on the game... for looks... That might be the first thing to kill. (I just use it for testing, since there are no shadows, I use the FOG for a depth reference.)

Do you have any funny settings on your graphics card, specific to GL? (Like force v-Sync, Force compatibility triple-buffer, force mip-map, performance settings on high, colors set to something other than 32K, forced anti-alias settings, anti-virus running in the background doing an "Active scan". Latest GL reference drivers. LOL... can't be me... Hehe...)

Seriously though, move the DoEvents into the "Timer loop" that has the code that updates the title-menu. Try moving the "Clear screen" back to the front of all the thinking code, just after the "Main Loop", inside the function.

Not sure what else I may have done, which would have that much of a performance hit. What framerate do you show for top-down3D?

ErosOlmi
08-10-2008, 14:23
I get an AVG of:
22 FPS with 800 cars
36 FPS with 500 cars
160 FPS with 100 cars
282 FPS with 50 cars

ISAWHIM, just to let you know that WHILE/WEND loops already fire an internal DOEVENTS so maybe you can avoid to fire it (I know, I know, it is not mentioned in the help :-[ I will add it)

Great and interesting job, just a little dark when first person camera.

Ciao
Eros

Petr Schreiber
08-10-2008, 15:54
Hi,

MichaelClease, try adding "tbgl_UseVsync 0" before main loop.
I got also about 75 FPS max without it.

Jason, thanks for very nice demo!
Just one thing - fog means no speed issue for speed monster like GF 6800 :) That could output reality at 25FPS :D
I have 6150, superlowend and it works very fast there too.


Petr

Michael Clease
08-10-2008, 16:47
thanks Petr. I get 175 fps at work so I will try again at home.

added TBGL_USEVSYNC 0.

Result on my Main Computer now are

17 fps with 800 cars.
27 fps with 500 cars.
123 fps with 100 cars.
220 fps with 50 cars
620 fps with 8 cars.

Petr Schreiber
08-10-2008, 20:53
Hi Michael,

I confirm very similar results.
For 800 hovercrafts I get 20FPS, if I turn off rendering by commenting out TBGL_SceneRender I get 21 FPS - that means we are reaching some speed limits, rendering is not the break. But I guess as in the final race there will be max 8 racers = 100x less, then it is no problem.

The bottleneck was calling AI function 800x per frame.
When I use STATIC variable in it, I get 30% better performance ( savings from no need for repeated allocation ), if I move whole loop inside function I get 50% more computional performance comparing to original code.


Petr

Michael Clease
08-10-2008, 21:04
I suppose we could do it as sub/functions for now then move all the code (if possible) into one routine, it will look nasty but it should be faster.

I forgot to add to my post that it was using about 50 % cpu (task manager, thinbasic).

Petr Schreiber
08-10-2008, 21:22
Hi Michael,

I know, good idea. It is definitely better to optimize in the end of dev. cycle.
For now we can keep it easy to understand, to not get into trouble.

Just wanted to say the speed can be always improved by various tricks.


Petr

ErosOlmi
08-10-2008, 21:26
I forgot to add to my post that it was using about 50 % cpu (task manager, thinbasic).


Almost all process driven by WHILE/WEND loops have this problem.
One solution is to go with timers, maybe inside a dialog.

ISAWHIM
08-10-2008, 22:20
I forgot to add to my post that it was using about 50 % cpu (task manager, thinbasic).

Almost all process driven by WHILE/WEND loops have this problem.
One solution is to go with timers, maybe inside a dialog.

Without the DoEvents... my system runs 100% CPU in any thinBasic code that uses "TBGL"...

There may be a DoEvents in the WHILE loop... but it is not working with the TBGL in the file. If I put the DoEvents at the beginning of the loop, CPU drops to 2%. If I put it in the title-refresh code (Which fires only once ever second), CPU goes to 50%... Removing it... Drives CPU up to 100%...

It may be programmed to fire... but it is not firing the event.

Figured it was a vsync issue... I force my vsync off in my graphic settings for my graphics card. (Didn't realize that they were on by default in the program.)

Vsync has its own "DoEvents"... which may be what you are seeing Eros... Thus, it would look like it is working, when it is not actually working.

I am looking into the other issues mentioned. (Again, I am just building off the sample code. You guys know more about the events than I do. The samples are not a big help on this matter, since they just roll-out code and have limited input and screen control, as they are just samples.)

ErosOlmi
08-10-2008, 22:31
ISAWHIM,

I re-checked WHILE/WEND loop and you are right 100% but I'm 50% wrong ;D
WHILE/WEND loops are performing a different timing events compared to DOEVENTS keyword.

When WEND keyword is encountered, thinBasic tells Windows events manager to perform all waiting Windows events but if there are no events, nothing will happen and the processor will continue to be busy with thinBasic. This is done in order to avoid to hang thinBasic in infinite loops difficult to control from windows task manager in case you want to stop thinBasic from there.

Instead DOEVENTS perform the same as WEND but adds a "SLEEP 1" command so it tells the processor to rest for 1 millisecond. This 1ms sleep is enough to give some rest to the processor and give time to other process.

Ciao
Eros

ISAWHIM
08-10-2008, 22:51
Gotcha...

I knew something was buggy, when it didn't perform better in the timed-loop...

When I have 10 cars now... with the v-sync off... no doevents in the loop, but one before the EXIT where GL drops off... That seemed to help. (Might be a tiny loading and unloading issue.)

It says you can't have two windows open, but I can get multiple widows. (I forget to close my old ones sometimes.)

DoEvents has been dropped in the loop.

I will shorten a lot of the math tonight. (I have it expanded for easy reading. It reduces well in a lot of areas. Not as much processing is required for the formulas. Some of it is just for the testing. Like adding a fixed velocity... would be replaced with Mass * Velocity.)

ErosOlmi
08-10-2008, 23:02
I knew something was buggy

Well, not really buggy. Different behaves for different purposes.
I just gave you ... wrong indication :-[
My fault.

Petr Schreiber
09-10-2008, 08:59
Hi Jason,



It says you can't have two windows open, but I can get multiple widows. (I forget to close my old ones sometimes.)


Don't do it. The behavior will be undefined.
I have plans for multiple TBGL controls at least, but it is not supported now.
So keep just one window OR control at one time.


Petr

ISAWHIM
09-10-2008, 10:47
I swear... I thought I was closing them... 8)

Ok, So I am still using the "TestingAI2" as my primary development, but developed code there, is being arranged into my Sand-Box program.

The original runs full-open, so I can throw in 5000 at a time, and test the variation from player to player, instead of watching one car do 5000 laps.

The "PreGame-SandBox", I am treating as if it were the game...

Limited to 8 crafts... in-game camera settings, controls, limits...

In both, I have added buildings for some scale and view-filling. I just with the fog-depth was able to be pushed back, and the camera view made more realistic. (View is too narrow, but seems to be a limit.) Would be neat if the camera could change position while you drive... If you go slower, it pulls up and back, giving you a nice area view. Letting you see more where you are looking. While going faster, would pull down and focus more ahead, as opposed to top-down. (The camera doesn't like to behave when the parent it is created off of, has also moved.)

You can now slow down to 0 and race up to 150, for now. (But you are still on the track. I am separating the first car from the AI control, for full user control.)

I think I may move the car data out of the element. It does not make for easy code when trying to compare three cars, X, Y, and Z, but also three separate values... carX.angle with carY.force with carZ.height. (I may be doing that wrong also, but arrays are needed for multi-car comparison.) I have sort-of started doing that...

For code clean-up...
I have created a universal "GLOBAL xTempLong AS LONG", and others will follow.
I did as instructed, and moved the AI to an outside location, and setup a global matching PTR for the crafts.
I renamed some elements to a more neutral name.
Created another camera, and one more camera view. (Top Center), (Top Start), (Player), and (Bleachers)...
I figure the views could be recycled for some dramatic transition, or for game-backdrops in start-up, pause, etc...
Shortened a lot of the odd looking code I added. Some replaced with more functional code.

Added air-resistance now... (Sort of fast decay)

I still need the DoEvents to stop my CPU from melting, while doing nothing. I have not found a better solution yet.

ErosOlmi
09-10-2008, 23:26
That is really something. Thanks.

I get more than 1000 FPS at 150MPH
CPU usage is not bad, around 30 to 50 % but I'm on a Core 2 so not indicative.

kryton9
10-10-2008, 04:36
Jason, that is really a lot that you did and the performance is really great. I was getting around 1900 fps with 150mph.

Michael Hartlef
10-10-2008, 07:30
What the hell have FPS to do with the simulation of speed, means what have the FPS to do with MPH?

ErosOlmi
10-10-2008, 07:58
What the hell have FPS top do with the simulation of speed mean what have the FPS to do with MPH?


In reality nothing ;D
Just nice to report.

Petr Schreiber
10-10-2008, 08:27
I get around 300-400 FPS.

Very nice, maybe the ground could be made brighter by setting it from RGB 80, 80, 80 to 255, 255, 255.

One remark - to call function, you do not need to use CALL keyword. This is useful only when you call function by name componed from string. So you in this example, instead of:


CALL GameSetup()

' -- Resets status of all keys
TBGL_ResetKeyState()

CALL CameraView() ' -- Call EMPTY for reset to start-line view

SLEEP(10)


you can go for:


GameSetup()

' -- Resets status of all keys
TBGL_ResetKeyState()

CameraView() ' -- Call EMPTY for reset to start-line view

SLEEP(10)


But this is detail.


Petr

ISAWHIM
10-10-2008, 17:57
LOL... I was wondering why they were mentioning speed (MPH)??? (Thinking the same thing myself.)

Though, speed will become an issue when the collision is set into place. (Faster speed = more pixels/distance moved per frame. Slower frame-rate = longer distance moved per frame.)

But for now, it is irrelevant. (Number of cars is the ultimate test, as that is loops iterated.)

I have moved the "TBGL_userdata" out of the entities... just too difficult to manage cross-checking of data. (Requires another array for pointers, and it depends on communication with TBGL to get info that is only for the program. (EG, TBGL does not use that info internally to calculate drawing or motion.)

That added a little speed-gain also...

But once object to object cross-checking begins, the gains should be exponential. (One ms becomes 8 to the 8th power ms, in a cross-checking setup array matrix.)

Now, we can compare car X to Y and car(x).value to car(y).value... and move car(x) without any values. I am not sure I like that all arrays have a fixed range (1-x)... because I am not sure if that creates actual dummy-cells in memory, or if that only creates the index pointers, for memory to be allocated. (Dummy-cells being empty values, but physical blocks of pre-allocated memory.) I am using the constant as the array count, so objects and array cells match. With only 8 cars, that isn't a problem, unless the constant is at the end of the constant list of objects.

I am now moving the ships and the camera's into pivot-elements. There will be only one camera again, for main view. The location and position will be set as needed. The vehicles will be attached to a pivot, so that the vehicle can be raised and lowered and turned on the Y-axis (xz-flat), without altering the xyz(Rot) of the actual ship. We should be able to tilt, lean without having to re-orient every axis and angle and direction with a complex formula. Height has no impact on tilt, when rotated on Y, but attempting to rotate x or z does not result in leaning left, when the ship has been turned 90-deg, it results in a nose-dive... since the axis stays aligned to the world, even when Y is turned on the object with an ANGLE call.

(I knew it could be without them... Figured it was an optional thing. I was using the coloring it creates as a visual marker while scrolling, otherwise the dark-blue just blends in with the rest of the functions and code. I will remove them if they are not needed, or may impact performance.)

I will repost the modified code tonight. I needed the modified code for the rest of the physics.

I was wondering if adding zones, along with way-points, would be better. Use the points as entrance and exit markers, while the zones are the areas between. That would allow you to "Physically" enter a zone, but not be "In the zone" until you have passed through the entrance, which would then reveal the exit. (Not visually seen in the game, but for the AI.)

EG, If the point was a hole in a giant sheet of paper, and the zone was a box/area on the other side, away from you... visually, you know that you can only select a point in the area, through the hole as a target. Being in the zone, but not having passed through the entrance, would turn your target back into your prior zone. Which the exit would be known, so the back side of the box would not be there, you could select any location in the prior zone, but the prior zone needs to be selected, so you can enter into the next zone. (That comes into play more with physics, where a spot "In the next zone", was selected through the "Entrance", but someone knocks the player off the track before the zone was reached, and they fly into the next zone, but off the track. Or that could be assumed as advancement, but the area through the entrance, is only a selectable area, if not knocked into the zone by the game.)

The map editor could create the zones and entrance/exit locations of each section. The AI could actually run around in a created map, at the time of creation, and set-up its own "track", using the map data before the game. Once the game/map is loaded, the AI uses that "track" as a guide. (Unbound to the physical center track.)

If they think like chess, and use the game physics to calculate which move will have the best desired results... they could setup a path that handles varying speeds, banks inside turns (Since that is naturally the shortest path, and banking on a turn is also a shortest path.) It would only have to setup two points per area, one being high-speed, and one being low-speed... It would still only sort-of know an idea where to go, since speed changes with impact from other players, and ship-stats change. But it could choose a point which best suits the speeds they are going. Selecting a point between points would be a natural option based on speed/velocity. (That would have to include code that penalizes for "Bouncing off walls" which may mathematically show it as a viable high-speed short-path. LOL... Good way to get around corners, but if penalized for damage, they will not save that position as a possible path-point for selection.)

The reason I bring that up, is because the paths which mark the center, or any paths, will change shape with velocity. Since velocity is not a constant, nor is mass, it is impossible to setup any single track for all variations. (Other than for the camera, which has a fixed mass, and no collision.)

Having the AI attempt to do this, in-game, may not be wise. As they should only be reacting to impacts and selecting predefined short-paths as a guide. Not doing actual calculations, or following one set zone-target. (To ensure that they are passing through all sequential zones, as we will be expected to do in the race.)