PDA

View Full Version : Shooting at the Player

robert83
08-12-2015, 12:33 PM
Hi All,

I am trying to make the enemy shoot the bullet in the Players direction :

Bullet.Direction:=90-radtodeg(Math.arctan2(PlayerSprite.Y - Enemy.Y, PlayerSprite.X - Enemy.X));

I found this online, it was used to turn a turret to face the Player ... it almost works.... but I think this is probably not what I want.

Can anynone tell me how can I calculate Direction ( which is FxVelocity ) for the bullet so that it goes in the direction of the Player ?

I guess I Need to calculate somehow the Direction which is based on the length it must travel to the Player and the Velocity of the Bullet .

I tried to draw the Problem . I am not even sure if that is the correct way . I would Need to calculate like this if the Player X is smaller then Enemy X,
and reversed if the Player X is greater then enemy X .

UPDATE :

I created a test Level with only one enemy,

1st stationary... 2nd moving straight down , 3rd... moving left and right

Bullet.Direction:=(90-radtodeg(Math.arctan2(PlayerSprite.Y - Enemy.Y, PlayerSprite.X - Enemy.X)))/12;

I dont know why but if I divide the number which I get by twelve I get perfect hit on every Position for 1st test and 3rd test , on 2nd test when It goes straight down... after a while it shoots at incorrect angel...
So I guess this arctan2 could still be the correct way.. but I am missing something here... something that I should be calculating with...but what....

UPDATE 2:

Bullet.Direction:=(90-radtodeg(Math.arctan2(PlayerSprite.Y - Self.Y, PlayerSprite.X - Self.X)))/12;

Self.X and Self.Y is the proper way... if I have multiple enemy ships.... this works... but the precision is still a bit off....

THanks. Robert

SilverWarior
08-12-2015, 06:03 PM
Hi Robert!

Are you trying to simply shoot the bullet toward Player current position? Or are you perhaps also trying to implement some sort of "Target prediction" algorithm so that you can also accurately shoot at moving targets?

robert83
09-12-2015, 05:31 AM
Hi SilverWarrior!,

I am trying to shoot toward the target... this works :

Bullet.Direction:=(90-radtodeg(Math.arctan2(PlayerSprite.Y - Self.Y, PlayerSprite.X - Self.X)))/12;

But I have no idea why.... why do I Need to divide by 12.... I guess 12 should be calculated but from what ?
I would like a bit of Explanation... otherwise it is functioning perfectly.... I tried yesterday a complete Level... the Shooting was great....

Thanx

SilverWarior
09-12-2015, 04:57 PM
But I have no idea why.... why do I Need to divide by 12.... I guess 12 should be calculated but from what ?
I would like a bit of Explanation... otherwise it is functioning perfectly.... I tried yesterday a complete Level... the Shooting was great....

I have no idea why you have to divide everything by 12. I guess the answer to this might be in your code that is using this information.
Also after preparing a quick test case for your approach (calculating angle of y mouse cursor position to a fixed point on the form) I'm getting wrong results even when I remove division by 12.

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var Direction: Single;
begin
Form1.Canvas.Brush.Color := clBtnFace;
Form1.Canvas.FillRect(Form1.ClientRect);
Form1.Canvas.Brush.Color := clBlack;
Form1.Canvas.MoveTo(Form1.Width div 2, Form1.Height div 2);
Form1.Canvas.LineTo(X,Y);
Direction :=(90-radtodeg(Math.arctan2(Form1.Height div 2 - Y, Form1.Width div 2 - X)));
Form1.Caption := Format('Direction = %n', [Direction]);
end;

It kinda works when mouse cursor is top left, bottom left or bottom right in relation to center position but when I move mouse cursor to top right position in relation to center position I get a negative value.
Also the angle is increasing in counter-clockwise direction but generally should do so in clockwise direction.

If I change my code to :

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var Direction: Single;
begin
Form1.Canvas.Brush.Color := clBtnFace;
Form1.Canvas.FillRect(Form1.ClientRect);
Form1.Canvas.Brush.Color := clBlack;
Form1.Canvas.MoveTo(Form1.Width div 2, Form1.Height div 2);
Form1.Canvas.LineTo(X,Y);
Direction :=(180-radtodeg(Math.arctan2(Form1.Height div 2 - Y, Form1.Width div 2 - X)));
Form1.Caption := Format('Direction = %n', [Direction]);
end;

I'm getting correct results and the angle is at 0 degrees when mouse cursor is directly left of the center point.

robert83
10-12-2015, 09:03 AM
It must be in the code... because if I try it with your calculation it is not working. Anyway it does not matter. I'll figure it out sometime later :) It works. And it always does... so I managed to hit it somehow. Beginers Luck I guess.

I have bigger Problem now... game is progressing nicely, two Levels are done. "AI" Functioning . Enemies have different Attack types. The BOSSes have multiple attack Patterns . Music Sound working... but after testing it yesterday
I started out with 120 MB Memory... on Level 2 end I was at 600MB.... and I almost went out the window in my happynes .

At first I thought the Framework is bugged... which would unfortunately mean utter failure again... since I am still not good enough to do this myself...

But I may be lucky... because I checked an earlier Version... and the error is not present .... so I guess I am Clearing the map Array incorrectly.. or maybe the BASS.DLL is causing Memory leak with mp3... I'll Play with it later....

Thank you.

robert83
10-12-2015, 11:23 AM
Hi,

The good News is that I found the Memory leak... it is indeed BASS . For example I have in menu the Cursor with Sound. Simply by moving trough the menu... Memory goes higher by every Sound played.

THis is what I am doing in the doMenu procedure :

begin
// up arrow
begin
PlaySound(ExtractFilePath(Application.Exename)+'so unds\choice.mp3');
end;
// down arrow
begin
PlaySound(ExtractFilePath(Application.Exename)+'so unds\choice.mp3');
end;
1 : MarsCursor.Y:= 320;
2 : MarsCursor.Y:= 352;
3 : MarsCursor.Y:= 416;
end;
// enter
begin
1:
begin
// game
GameState:=gsReset;
end;
2:
begin
// info
end;
3:
begin
// exit
end;
end;
end;

end;

Nothing fancy... the Playsound procedure Looks like this :

procedure PlaySound(const SampleFilename : String);
var mySound : HStream;
begin
// free both MOD and stream, it must be one of them! :)
BASS_MusicFree(mySound);
BASS_StreamFree(mySound);

mySound := BASS_StreamCreateFile(FALSE, PChar(SampleFilename), 0, 0, BASS_SAMPLE_FX {\$IFDEF UNICODE} or BASS_UNICODE {\$ENDIF});
// BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, 4000);
BASS_ChannelPlay(mySound, False);
end;

Is there some obvious error here ? I must confess the bass Thing I did in quiet a haste :) . I googled now... found someone else mentioning some Problems related to BASS.dll free Version with mp3 ... from year 2012.... I am not
sure if it's that same bug still present. Or I am just doing something totaly wrong here.

Thank you

robert83
10-12-2015, 12:02 PM
Solved it I think :

procedure PlaySound(const SampleFilename : String);
var mySound : HStream;
begin
// free both MOD and stream, it must be one of them! :)
// BASS_MusicFree(mySound);
// BASS_StreamFree(mySound);
mySound := BASS_StreamCreateFile(FALSE, PChar(SampleFilename), 0, 0, BASS_SAMPLE_FX {\$IFDEF UNICODE} or BASS_UNICODE {\$ENDIF} or BASS_STREAM_AUTOFREE);
// BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, 4000);
BASS_ChannelPlay(mySound, False);
if BASS_ChannelIsActive(mySound) = 0 then
begin
BASS_ChannelStop(mySound);
BASS_Streamfree(mySound);
end;
end;

BASS_STREAM_AUTOFREE was needed , note though it stops it correctly but it was not freed no idea why....

Thanx

Super Vegeta
11-12-2015, 10:02 AM
It's been a while since I used BASS, but unless the workflow has changed, you shouldn't really free streams while the program is running. Calling StreamCreateFile basically reads the file again from the disk, and that's bad. Instead, what you want is:
1. Load file at program start
2. Use channels to play the sound (the BASS Stream). If you want to change the volume, stop, pause, or however manipulate the playing sound, keep the channel number and use the BASS_ChannelSomething() functions. You don't have to free channels manually, as managing memory for channels is done automatically by BASS.
3. Only free the Stream when you're closing the application, or for some reason need to load a different file to the same stream handle (say, your game hero underwent a transformation and now uses a different sound set)

robert83
11-12-2015, 11:44 AM
Super Vegeta , thank you!

Now that you told me , it makes sense ... and a lot of sense. Especially the disk io part . My game hangs for a sec when the Music changes.

I Need to rewrite the functions.

Load all Sound and Music effects on Startup . And then just Play the appropriate channel instead.
So if a Bullett is shoot by 5 different alliens instead of wasting disk i/o I just Play the channel from Memory when needed.

Thank you for this great advice!!! :)

robert83
21-01-2016, 06:38 PM
Hi all,

Just wanted to post, I managed to solve the bullet calculation . Not alone unfortunately... google helped. And I don't understand it 100%.... I think I may end up taking private Math Classes :)

vx := (PlayerSprite.X+(PlayerSprite.ImageWidth/2)) - (Self.X+(Self.ImageWidth/2));
vy := (PlayerSprite.Y+(PlayerSprite.ImageHeight/2)) - (Self.Y+(Self.ImageHeight/2));

len := sqrt(sqr(vx) + sqr(vy));

vx := vx / len;
vy := vy / len;

Bullet.Direction:= vx * 4;
Bullet.MoveSpeed:= vy * 4;

What happens here is the vector lenth is calculated... then normalised , I understand what it does... goes from 0 to 1 .... but this formula is something I would have never figured out :(

Also I realised my mistake...I need to alter the speed on both X and Y axis in order to work perfectly :) ... it even shots backwards...

Greetings...

ps.: I dont have any new material, I have level 1 done... altered the background, enemies use different attacks... level 2 is done..it turned out quiet cool... level 2 ending is done
It took a while to come up with a crazy story... Its god damn hard, but I will try and not post anything until done....4 more levels :)