Bullet direction

Blitz3D Forums/Blitz3D Programming/Bullet direction

mintybreath(Posted 2007) [#1]
I am making a 2d birds eye view cam shooting game. I already made the character, bullet, and reciticle, there is only one problem. How do i make the bullets shoot towards the reciticle? I have tried a number of things that havent seemed to work, so if someone could give me a little help that would really be great. :)

The game is a 2d game also, so obviously no 3d commands will work. And the reciticle is attached to the mouse, so where that moves, the reciticle moves.

Thank you everyone for your help!

- Kevin


Chroma(Posted 2007) [#2]
Here ya go. Just plug in your own bullet and gun graphics. This is from a LONG time ago and it's got some unnecessary stuff in there but it'll work. :)


Graphics 800,600,32,0

Global ShotList:TList = New TList

SetBlend ALPHABLEND

Local bow:TImage =LoadImage("gun.png")
MidHandleImage(bow)

Global arr:TImage = LoadImage("bullet.bmp")
MidHandleImage arr

While Not KeyHit(KEY_ESCAPE)
Cls

Local MX:Int = MouseX()
Local MY:Int = MouseY()
Local LMH:Int = MouseHit(1)
Local LMD:Int = MouseDown(1)
Local RMH:Int = MouseHit(2)
Local RMD:Int = MouseDown(2)

a:Int = MouseX() - 400
b:Int = 300 - MouseY()
r:Float = ATan2(a,b)

SetRotation r
SetScale .5,.5
DrawImage bow,400,300

SetScale .75,1.5

If LMH TShot.Create(400,300,r,.25)

Local s:TShot
For s = EachIn ShotList
	s.Update()
Next

Flip 0
Wend
End

Type TShot
	Field img:TImage
	Field x:Float,y:Float,r:Float
	Field spd:Float

	Function Create:TShot(x:Float,y:Float,r:Float,spd:Float)
		Local s:TShot = New TShot
		s.img = arr
		MidHandleImage s.img
		s.x = x
		s.y = y
		s.r = r
		s.spd = spd
		ShotList.AddLast s
	End Function
	
	Method Update()
		SetRotation self.r
		self.x = self.x + (Sin(self.r) * self.spd)
		self.y = self.y - (Cos(self.r) * self.spd)
		DrawImage self.img,self.x,self.y
		
		If self.x < 0 kil = 1
		If self.x >800 kil = 1
		If self.y < 0 kil = 1
		If self.y > 600 kil = 1
		If kil = 1 ShotList.Remove(Self)
	End Method
End Type



mintybreath(Posted 2007) [#3]
Thanks alot man! :D

Ill test this out, and post back if there seems to be any error.


Chroma(Posted 2007) [#4]
Np at all, if you do have a problem I can strip it down to the bare necessities if needed.

Eh, I just realized I posted BMax code in the B3D forum. It should be somewhat easy to convert I think.


mintybreath(Posted 2007) [#5]
ya thanks again. Havent had much time to try it out yet though.

I got back from my soccer game at about 9:30(we tied), was tired, didnt do much coding and just went to sleep, and now am in my computer class.

But when i get home ill try it. If i need help, ill just email you for the bare code. :)


mintybreath(Posted 2007) [#6]
Well there seems to be one error. In the beginning of the loop. Where it says "Local MX:Int = MouseX()", it highlights " Int = MouseX()" and says Expecting 'Wend'.

If you dont have a solution for this, then the bare code may work better.


mintybreath(Posted 2007) [#7]
.


b32(Posted 2007) [#8]
The problem is, that that function is written with BMax. It is not compatible with Blitz3D.

Basically, the idea is to use Atan2 to determine the angle between the ship and the aiming point:
angle# = atan2((aim_y - ship_y), (aim_x - ship_x))

and then use Cos and Sin to move the bullet:
bullet_x# = ship_x
bullet_y# = ship_y

Repeat

  bullet_x# = bullet_x# + Cos(angle#)
  bullet_y# = bullet_y# + Sin(angle#)

Forever



big10p(Posted 2007) [#9]
Yeah. You'll probably also want to multiply the cos/sin values by speed though, or they'll be mighty slow bullets. :)


mintybreath(Posted 2007) [#10]
ok that really seems to help, but there seems to be one problem. I believe i did it right, but obviously i didnt, because everytime i try to test launch the game, the window opens, stays black, my mouse disapears, and then it times out.
I dont know if any of you would have a solution for this, but if you do, i would really like to hear it.

here is the code for the program if that helps at all.

;Freeroamer
;Created by Mintybreath

Graphics 800,600,16,2
SetBuffer BackBuffer()

;Constants
Const upkey = 200	;move the player up
Const downkey = 208 ;move the player down
Const leftkey = 203 ;move the player left
Const rightkey = 205;move the player right
Const humanspeed = 3  ;the speed of the human
Const bulletspeed = 2

;Loaded Images
Global playerimage=LoadImage("player smallest.png")
Global aimimage=LoadImage("reciticle.png")
Global bulletimage=LoadImage("bullet.png")
Global backimage=LoadImage("Full Ground.png")

AutoMidHandle bulletimage
AutoMidHandle playerimage
MaskImage playerimage,0,255,255
AutoMidHandle aimimage
MaskImage aimimage,0,255,255

Type player

	Field x,y
	
End Type

Type bullet
	Field x,y

End Type

Type back
	Field x,y
End Type

Type aim
	Field x,y
End Type

Function initializelevel()

	player\y = 250
	player\x = 250
	
End Function

;update the bullets
Function updatebullet()
	
	;for each bullet, move it up 5 pixels
	;if it goes off screen delete it
	For bullet.bullet = Each bullet
	bullet\y = bullet\y - 5
		;if bullet moves offscreen, delete it, otherwise draw it onscreen
		If bullet\y<0
			Delete bullet
		Else
			DrawImage bulletimage,bullet\x,bullet\y  ;draw the image
		EndIf
	Next
End Function


;Controls
Function Controls()


DrawImage (backimage,back\x,back\y)
DrawImage (playerimage,player\x,player\y)
DrawImage aimimage,aim\x,aim\y
HidePointer 


;point and shoot
angle#=ATan2((aim\y - player\y), (aim\x - player\x))
Repeat 
	bullet\x=bullet\x + Cos(angle#)
	bullet\y=bullet\y + Sin(angle#)
Forever

If KeyDown(rightkey)
	back\x = back\x - humanspeed
	playerimage=LoadImage("player Right.png")
	MaskImage playerimage,0,255,255
EndIf

If KeyDown(leftkey)
	back\x = back\x + humanspeed
	playerimage=LoadImage("player left.png")
	MaskImage playerimage,0,255,255
EndIf

If KeyDown(downkey)
	back\y = back\y - humanspeed
	playerimage=LoadImage("player down.png")
	MaskImage playerimage,0,255,255
EndIf

If KeyDown(upkey)
	back\y = back\y + humanspeed
	playerimage=LoadImage("player smallest.png")
	MaskImage playerimage,0,255,255
EndIf
	
End Function



Global aim.aim = New aim
Global back.back = New back
Global player.player = New player
Global bullet.bullet = New bullet

initializelevel()

;________________________________________________________
;______________________Main Loop_________________________
;________________________________________________________

While Not KeyDown(1)
Cls 

aim\y=MouseY()
aim\x=MouseX()

If MouseHit(1) Then	
	bullet.bullet=New bullet
	bullet\x = player\x
	bullet\y = player\y
		
	
EndIf

;Functions
Controls()
updatebullet()

If KeyHit(30)
	
EndIf

Flip

Wend

End



b32(Posted 2007) [#11]
First of all, remove the Repeat..Forever commands around the bullet's movement.
Then, change all the fields in the types to floats, by adding "#":
Field x#, y#
Then, the code for the bullet movement should go in place where it now says:
bullet\y = bullet\y - 5

Finally, the angle# should be calculated for each bullet, when the "New bullet" is created.
So the bullet type needs a new field, that is angle#, and that angle should be used when the bullet is moved.


mintybreath(Posted 2007) [#12]
Thanks for all your help, that worked really good.

One other thing if you dont mind and have the time.
How do i make the bullets faster? i tried putting a 2 in front of cos and sin to multiply them by 2. That made the bullet faster, but it kept the bullet moving the the bottom right corner only.
If you have any advice on this i would really like to hear it.

And sorry about asking for so much help. I just cant see how to do it. :)

-Kevin


big10p(Posted 2007) [#13]
It should work as long as you multiply sin and cos by the same amount.

Post the code as you have it so far.


mintybreath(Posted 2007) [#14]
Here it is:

;Freeroamer
;Created by Mintybreath

Graphics 800,600,16,2
SetBuffer BackBuffer()

;Constants
Const upkey = 200	;move the player up
Const downkey = 208 ;move the player down
Const leftkey = 203 ;move the player left
Const rightkey = 205;move the player right
Const humanspeed = 3  ;the speed of the human
Const bulletspeed = 2

;Loaded Images
Global playerimage=LoadImage("player smallest.png")
Global aimimage=LoadImage("reciticle.png")
Global bulletimage=LoadImage("bullet.png")
Global back=LoadImage("Ground.png")

AutoMidHandle bulletimage
AutoMidHandle playerimage
MaskImage playerimage,0,255,255
AutoMidHandle aimimage
MaskImage aimimage,0,255,255

Type player

	Field x,y
	
End Type

Type bullet
	Field x#,y#
	Field angle#
End Type

Type aim
	Field x,y
End Type

Function initializelevel()
	player\y=300
	player\x=300
End Function

;update the bullets
Function updatebullet()
	
	;for each bullet, move it up 5 pixels
	;if it goes off screen delete it
	For bullet.bullet = Each bullet
	bullet\x# = bullet\x# + 2Cos(angle#)
	bullet\y# = bullet\y# + 2Sin(angle#)
	angle#= ATan2((aim\y - player\y), (aim\x - player\x))
		;if bullet moves offscreen, delete it, otherwise draw it onscreen
		If bullet\y#<0
			Delete bullet
		Else
			DrawImage bulletimage,bullet\x#,bullet\y#  ;draw the image
		EndIf
	Next
End Function


;Controls
Function Controls()

camerax=player\x -(800/2)
cameray=player\y -(600/2)

DrawImage (playerimage,player\x,player\y)
DrawImage aimimage,aim\x,aim\y
HidePointer 



If KeyDown(rightkey)
	player\x = player\x + humanspeed
	playerimage=LoadImage("player Right.png")
	MaskImage playerimage,0,255,255
EndIf

If KeyDown(leftkey)
	player\x = player\x - humanspeed
	playerimage=LoadImage("player left.png")
	MaskImage playerimage,0,255,255
EndIf

If KeyDown(downkey)
	player\y = player\y + humanspeed
	playerimage=LoadImage("player down.png")
	MaskImage playerimage,0,255,255
EndIf

If KeyDown(upkey)
	player\y = player\y - humanspeed
	playerimage=LoadImage("player smallest.png")
	MaskImage playerimage,0,255,255
EndIf
	
End Function



Global aim.aim = New aim
Global player.player = New player

initializelevel()




;________________________________________________________
;______________________Main Loop_________________________
;________________________________________________________

While Not KeyDown(1)
Cls 

DrawImage back,0,0

aim\x=MouseX()
aim\y=MouseY()



If MouseHit(1) Then	
	bullet.bullet=New bullet
	bullet\x# = player\x
	bullet\y# = player\y
	
EndIf


;Functions
Controls()
updatebullet() 

If KeyHit(30)
	
EndIf

Flip

Wend

End



big10p(Posted 2007) [#15]
bullet\x# = bullet\x# + 2Cos(angle#)
bullet\y# = bullet\y# + 2Sin(angle#)

What's that?! Does that even compile?

it should be:
bullet\x# = bullet\x# + (Cos(angle#) * 2)
bullet\y# = bullet\y# + (Sin(angle#) * 2)



mintybreath(Posted 2007) [#16]
ooohhh i see. ill try that. I guess i figured that it would see it as 2*cos, or basically 2cos.

thanks alot :)

EDIT: Ya that worked great. thanks everyone for all your help.


Edit: I really feel wierd asking more help of all of you, but there is one minor problem i am still not sure about. When the bullets are shot out, they continue to follow the aimer, giving the user controll over the bullets while they are in flight, which i dont really like the idea of. If anyone has any idea how to fix that it would really help me. Once i get the weapons system down and camera system down, i know pretty much how to do the rest.

Thanks alot everyone!

-Kevin


Eviltoes(Posted 2007) [#17]
What I do to fix this is something like this:


if mousehit(1) then
bullets.bullet=new bullet
bullets\destx=mousex()
bullets\desty=mousey()
endif

for bullets.bullet=each bullet
angle#=atan2((bullets\desty-player\y),(bullets\x-player\x))
bullets\x=bullets\x+(cos(angle#)*2)
bullets\y=bullets\y+(sin(angle#)*2)
next


That might fix it.


Stevie G(Posted 2007) [#18]


p.s. Loading and masking an image each time you press a key is slow. Load & mask them outwith the main loop and simply display the one you need.


mintybreath(Posted 2007) [#19]
Ill try that code out. Thanks everyone!

Edit: Worked great! thanks alot!