Bullet direction
Blitz3D Forums/Blitz3D Programming/Bullet direction| 
 | ||
| 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 | 
| 
 | ||
| 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
 | 
| 
 | ||
| Thanks alot man! :D Ill test this out, and post back if there seems to be any error. | 
| 
 | ||
| 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. | 
| 
 | ||
| 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. :) | 
| 
 | ||
| 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. | 
| 
 | ||
| . | 
| 
 | ||
| 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 | 
| 
 | ||
| Yeah. You'll probably also want to multiply the cos/sin values by speed though, or they'll be mighty slow bullets. :) | 
| 
 | ||
| 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 | 
| 
 | ||
| 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. | 
| 
 | ||
| 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 | 
| 
 | ||
| It should work as long as you multiply sin and cos by the same amount. Post the code as you have it so far. | 
| 
 | ||
| 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 | 
| 
 | ||
| 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) | 
| 
 | ||
| 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 | 
| 
 | ||
| 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. | 
| 
 | ||
| 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. | 
| 
 | ||
| Ill try that code out. Thanks everyone! Edit: Worked great! thanks alot! |