Thanks VN, that works excellent.
And that's too easy to be a hack.
EDIT:
SetObjectLookAt() was the key to getting it working. It's a very versatile command. Thanks again Virtual Nomad. I should check the online help as it seems to have more than the built in help.
There is a bullet holes demo below people are free to use.
It's set up for static targets but maybe it could work on mobile targets if the bullet hole plane is set as child of the moving target.
// Project: bullet holes
// Created: 22-01-23
SetErrorMode(2)
SetWindowSize( 1024, 768, 1 )
SetWindowAllowResize( 1 )
SetDisplayAspect(-1.0)
SetSyncRate(30, 0 )
SetScissor( 0,0,0,0 )
UseNewDefaultFonts( 1 )
SetPrintSize(3)
SetGenerateMipmaps(1)
SetSkyboxVisible(1)
SetSkyBoxHorizonColor(120,120,200)
SetSkyBoxSkyColor(80,80,200)
SetAmbientColor(180,180,180)
maxBullets=100
Type bullets
ID as integer
EndType
dim bullet[maxBullets] as bullets
bulletcount=0
terrain=CreateObjectBox(1000,5,1000)
SetObjectPosition(terrain,0,-5,0)
SetObjectColor(terrain,170,170,170,255)
terraintex=LoadImage("dirt5.png")
SetObjectImage(terrain,terraintex,0)
SetObjectUVScale(terrain,0,150,150)
SetImageWrapU(terraintex,1)
SetImageWrapV(terraintex,1)
SetObjectCollisionMode(terrain,1)
cam1=1
SetCameraRange(cam1, 0.1, 50000 )
SetCameraposition(cam1,0,5,0)
SetCameraRotation(cam1,0,0,0)
man1=CreateObjectsphere(2,6,12)
SetObjectposition(man1,0,5,0)
setobjectvisible(man1,0)
SetObjectRotation(man1,0,0,0)
sights=CreateSprite(LoadImage("sights2.png"))
SetSpriteSize(sights,3,5)
SetSpritePosition(sights,50-getspritewidth(sights)/2,50-getspriteheight(sights)/2)
box1=createobjectbox(10,10,10)
setobjectposition(box1,20,5,20)
//setobjectrotation(box1,50,20,30)
setobjectcolor(box1,50,150,200,255)
SetObjectCollisionMode(box1,1)
ball1=createobjectsphere(10,180,180)
setobjectposition(ball1,-20,5,30)
setobjectcolor(ball1,50,200,150,255)
SetObjectCollisionMode(ball1,1)
target=createobjectbox(1,1,1)
setobjectvisible(target,0)
bulletTex=LoadImage("bullethole1.png")
gunSound=LoadSound("pistol.wav")
setrawmousevisible(0)
SetRawMousePosition(50,50)
do
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx camera controls
mouseX# = (GetRawMouseX()-50)
mouseY# = (GetRawMouseY()-50)
RotateCameraLocalX(cam1,mouseY#)
RotateObjectLocalY(man1,mouseX#)
SetCameraRotation(cam1,GetCameraAngleX(cam1),GetObjectAngleY(man1),0)
If GetCameraAngleX(cam1)>80 Then SetCameraRotation(cam1,80,GetCameraAngleY(cam1),0)
If GetCameraAngleX(cam1)<-80 Then SetCameraRotation(cam1,-80,GetCameraAngleY(cam1),0)
If GetRawKeyState(87) // W
MoveObjectLocalZ(man1,2)
EndIf
If GetRawKeyState(83) // S
MoveObjectLocalZ(man1,-2)
EndIf
If GetRawKeyState(65) // A
MoveObjectLocalX(man1,-2)
EndIf
If GetRawKeyState(68) // D
MoveObjectLocalX(man1,2)
EndIf
SetCameraPosition(cam1,GetObjectX(man1),GetObjectY(man1),GetObjectZ(man1))
// xxxxxxxxxxxxxxxxxxxxxxxxxxxx left mouse button to fire (bullet hole)
if GetRawMouseLeftPressed()
// target is an invisible box used for end of ray coords
setobjectposition(target,GetCameraWorldX(cam1),GetCameraWorldY(cam1),GetCameraWorldZ(cam1))
setobjectrotation(target,GetCameraAngleX(cam1),GetCameraAngleY(cam1),GetCameraAngleZ(cam1))
moveobjectlocalZ(target,500)
inst=playsound(gunSound)
ray1=ObjectRayCast(0,GetCameraWorldX(cam1),GetCameraWorldY(cam1),GetCameraWorldZ(cam1),GetObjectWorldX(target),GetObjectWorldY(target),GetObjectWorldZ(target))
targetHit=GetObjectRayCastHitID(0)
if targetHit > 0 and targetHit <> target
XhitPos#=GetObjectRayCastX(0)
YhitPos#=GetObjectRayCastY(0)
ZhitPos#=GetObjectRayCastZ(0)
XhitAng#=GetObjectRayCastNormalX(0)
YhitAng#=GetObjectRayCastNormalY(0)
ZhitAng#=GetObjectRayCastNormalZ(0)
bulletCount=bulletcount+1
if bulletCount=maxBullets+1 then bulletCount=1
if bullet[bulletCount].ID=0
bullet[bulletCount].ID=createobjectplane(0.5,0.5)
SetObjectCollisionMode(bullet[bulletCount].ID,0)
setobjectimage(bullet[bulletCount].ID,bulletTex,0)
SetObjectTransparency(bullet[bulletCount].ID,1)
endif
setobjectposition(bullet[bulletCount].ID,XhitPos#,YhitPos#,ZhitPos#)
SetObjectLookAt(bullet[bulletCount].ID,XhitPos#+XhitAng#,YhitPos#+YhitAng#,ZhitPos#+ZhitAng#,0)
rotateobjectlocalZ(bullet[bulletCount].ID,random(1,360))
moveobjectlocalZ(bullet[bulletCount].ID,0.01)
endif
endif
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Print(" WSAD and LMB ")
Print(" XhitPos# "+str(XhitPos#))
Print(" YhitPos# "+str(YhitPos#))
Print(" ZhitPos# "+str(ZhitPos#))
Print(" XhitAng# "+str(XhitAng#))
Print(" YhitAng# "+str(YhitAng#))
Print(" ZhitAng# "+str(ZhitAng#))
SetRawMousePosition(50,50)
if GetrawKeyPressed(27) then end
Sync()
loop
BASIC appeared in May 1964. Lightning flashed, the wind roared and the Earth moved.
And nine months later I was born.
So here I am.
I am Basic.
Code is in my genes.