EntityInView with types

Blitz3D Forums/Blitz3D Programming/EntityInView with types

spriteman(Posted 2008) [#1]
Thanks so far for your help so far folks. I was a little rusty with Types and have just again had a look into using them.

At the moment I would like to use Entityinview to detect if one of the many type objects (ships) have been seen by the camera. What seems to happen is that it will only detect the last one in the type list. Probably something silly but here is a bit of code,

Function updateships()
For s.ship = Each ship

Do stuff here.

If EntityInView ( SIMAGE,camera )=True then shipseen=1

Next

The question is, Should I place the EntityInView check within the For, next loop as at the moment the last ship in the list is detected but not all the others when they pass in camera view.?

Thanks,


Mortiis(Posted 2008) [#2]
Function UpdateShip()
    For s.ship = Each ship
        If EntityInView( s\ship, camera ) = True then ShipSeen = 1
    Next
End Function



spriteman(Posted 2008) [#3]
Hi Mortiis,

Thanks for that, However, I still get the last ship in the list detected,

The little bit of code I placed in the For next loop was,

If EntityInView( S\SIMAGE, camera ) = True Then
Shipseen=1
Else
shipseen=0
End If

The S\SIMAGE element in the type holds a sprite as below,

S\SIMAGE = LoadSprite(SIMAGE$,7)

Not sure why its not working...I will have another go...


Mortiis(Posted 2008) [#4]
Are you using the UpdateShip() function in main loop?

Can you provide the full source code?


Sledge(Posted 2008) [#5]
Should not ShipSeen be a field of the type Ship, that way you could keep track of whether or not each individual instance had been seen or not.


Charrua(Posted 2008) [#6]
Hi

I agree with sledge, in the way it is, Shipseen only tells you that at least one is seen, but nothing about which or whose are seen.

only for debug purposes:

global strTmp$

rest of your code
if EntityInView( S\SIMAGE, camera ) = True Then
          Shipseen=1
          strTmp$ = strTmp$ + S\SIMAGE + ", "
Else
          shipseen=0
End If

Outside the loop:
debuglog strTmp (or print strTmp or Text x,y,strTmp what ever)

strTmp$ accumulate a list of Ships seen by the camera


Juan


spriteman(Posted 2008) [#7]
Hi there,

Thanks Mortiis/Sledge

UpdateShip() is being called from the main loop.

I also have an extra Field in the ship Type which holds the Ships ID
Field SID% ; Ship ID

So going along with what Sledge says then would it be possible to check each individual ship using the S/SID% value along with Entityinview or check the S\SIMAGE (sprite) to see if it is in view.

Just not sure how

Regds,


Sledge(Posted 2008) [#8]
Yeah I was thinking of something along these lines:




spriteman(Posted 2008) [#9]
Hi There,

Thanks for the feedback on this one. Interesting example sledge.

After messing around I am still having trouble using Entityinview to detect any of my ship types when it passes the camera. Still getting it to detect the last one in the type list.

I include a bit more code that last time,

I have this type with various elements

Type SHIP
Field SID% ; Ship ID
Field SNAME$ ; The name of ship eg distroyer
Field SIMAGE$ ; Image of ship (.png)
Field SPOINT% ; Ship Points
Field SDSAM% ; Ship Damage
Field SW% ; Ship Length
Field SH% ; Ship Height
Field SCX# ; x Center point for ship rotation
Field SX# ; Initial x co-ord of ship
Field SY# ; y co-ord of ship
Field SZ# ; Initial z co-ord of ship
Field SCZ# ; z Center point for ship rotation
Field SDS# ; Starting distance for ship
Field SDE# ; Randomised end distance for the ship
Field SP# ; Speed and direction of ship around circle
Field SA# ; Ships Starting Angle (Degrees)
End Type

In the for next iteration below I am going through the ship types and using entityinview to pick up the ships that are seen by the camera. It only detects the last one in the list.?

Function updateships()
For s.ship = Each ship

;Do stuff here to move ship in a circle around camera

If EntityInView (S\SIMAGE,CAMERA) = True
shipseen=1
Else
shipseen=0
End If

Next

End Function

In the main loop I have text placed on screen to tell when a ship is detected,

If shipseen=1 Then
Text 0,0, "Ship in view"
Else If shipseen=0 Then
Text 0,0, "Ship out of view"
End If

Any other ideas.

Thanks,


Sledge(Posted 2008) [#10]
Any other ideas.
Hmmmm. Is shipseen actually global? Is the pick mode for every ship instance correctly set?


spriteman(Posted 2008) [#11]
Hi Sledge,

Sorry fot the delay. Your previous bit of code was a great example of EntityInView.

I did a little mod on it below to iterate text to the screen to tell when a ship(Sphere) was in view. It only picks up 1 of the 2 entitys. Sorry for my ignorance but is it possible to report to the screen every time a ship(sphere) passes in front.

Regds,

Const NUMBER_OF_SHIPS = 2

Graphics3D 800,600,0,2
SetBuffer BackBuffer()
cam = CreateCamera()
PositionEntity cam,0,5,-20
light = CreateLight()
PositionEntity light,100,100,-100

Global shipseen
Type ship
Field geom
Field seen
End Type
CurrentShip.Ship = Null

Function CreateShip.Ship()
NewShip.Ship = New ship
NewShip\geom = CreateSphere(8)
EntityPickMode NewShip\geom,1
Return NewShip.Ship
End Function

Function CheckShipsAgainst(player_arg.player)
For CurrentShip.ship = Each ship
If EntityInView(CurrentShip\geom,player_arg\cam)
CurrentShip\seen = True
Else
CurrentShip\seen = False
EndIf
Next
End Function

Function ColourShips()
For CurrentShip.ship = Each ship
If CurrentShip\seen
EntityColor CurrentShip\geom,100,255,255
shipseen=1
Else
shipseen=0
EntityColor CurrentShip\geom,100,100,100
EndIf
Next
End Function


Type player
Field cam
Field geom
End Type

Function CreatePlayer.Player(viewX_arg, viewY_arg)
Local NewPlayer.Player = New player
NewPlayer\cam = CreateCamera()
CameraViewport NewPlayer\cam,viewX_arg,viewY_arg,256,256
CameraClsColor NewPlayer\cam,10,10,10
NewPlayer\geom = CreateCone()
RotateEntity NewPlayer\geom,90,0,0
EntityParent NewPlayer\geom,NewPlayer\cam
Return NewPlayer
End Function
CurrentPlayer.Player = CreatePlayer(0,0)


worldPiv = CreatePivot()
PointEntity cam,worldPiv
For i = 1 To NUMBER_OF_SHIPS
CurrentShip = CreateShip()
PositionEntity CurrentShip\geom,0,0,15
EntityParent CurrentShip\geom, worldPiv
TurnEntity worldPiv, 0, 360/NUMBER_OF_SHIPS, 0
Next



While Not MouseHit(1)
TurnEntity worldPiv,0,1,0
TurnEntity CurrentPlayer\cam,0,-.5,0

CheckShipsAgainst(CurrentPlayer)
ColourShips()

RenderWorld
If shipseen=0 Then
Text 0,0, "Ship out of view"
Else If shipseen=1 Then
Text 0,0, "Ships in view"
End If

Flip True
Cls
Delay 1
Wend


Sledge(Posted 2008) [#12]
At a quick glance, this is your problem:
Function ColourShips()
For CurrentShip.ship = Each ship
If CurrentShip\seen
EntityColor CurrentShip\geom,100,255,255
shipseen=1
Else
shipseen=0
EntityColor CurrentShip\geom,100,100,100
EndIf
Next
End Function


Imagine you can see the first ship in the collection -- shipseen gets set to one and all is well. But now imagine the next ship is out of view, the code says to set shipseen to zero if this is the case -- in effect you are telling shipseen to forget about every result except the very last.

What you really want to do is set shipseen to zero before you enter the For...Each loop, and then the only change you make to shipseen within the loop is to set it to one should the current ship be in view; if not, just leave it.


spriteman(Posted 2008) [#13]
Sledge,

Thanks again for the example. Had one of many dull moments. This now works for me.....

Function shipinview()

shipseen=0

For s.ship = Each ship

If EntityInView ( S\SIMAGE,camera )
shipseen=1
ID=S\SID%
End If

Next
End Function


IPete2(Posted 2008) [#14]
Spriteman,

Just remember that a type is like a set of properties for every instance of any object you like. So obviously when you were setting a variable earlier in this thread, that variable was always set using the last tpe object instance.

As sledge and co said and provided nice examples, ou need every object to maintain its own (can I be seen) flag. not one generic variable.
The example shown above is only using a generci variable to keep shipseen set to 1 if any of the ships even more than one is seen. I am not really undertsanding what your mission is with the code, but it does seem an odd way of doing things currently.

Also keep in mind that you can use handle and object along with types to get exact reference to any object direcltly, without having to run trhough each instance every time.

IPete2.


Sledge(Posted 2008) [#15]
I am not really undertsanding what your mission is with the code

He wants shipseen to be set true if any one ship has come into view.

Spriteman, the next step would be to get rid of the shipseen variable altogether -- it's currently acting as a global bridge between the ColourShips() function and the main code that decides which text message to present. To tidy things up I would delete the shipseen stuff from ColourShips() and write an extra function that directly returns the information that shipseen is currently being used to store: