Jetpac laser problem

Blitz3D Forums/Blitz3D Beginners Area/Jetpac laser problem

Can anyone help me? I am trying to recreate the laser routine from Jetpac, the problem I have is understanding how to get a fixed position to fire the laser from (if I fire the laser & move the player, the laser follows!)

Have a temp Var that when you press the mouse button stores the position in it only once.

ie

if moushit 1
tempx = mousex()
endif

tempx:+5

that means it's only updated when the mouse is hit and then goes on its travels.

Thanks Amon, you've made that sound so simple! Cheers.

JetPac allows many laser shots to be fired at once, though.

I'd probably create a laser type for this and create a new instance every time fire is pressed - then have a function that updates all the types, every update.

This is in the showcase forum, why??

Oops!

Yeah Big10p's is a good extension of Amon's one shot deal.

Heh - I didn't even notice this was in the wrong forum. Anyway, quick and dirty example:

	Graphics 800,600,0,1
	SetBuffer BackBuffer()

	SeedRnd MilliSecs()

	Const LASER_LEN = 500

	Type laserT
		Field x,y
		Field len_ang#
	End Type
	
	fps_timer = CreateTimer(60)
	
	While Not KeyHit(1)
		frame_start = MilliSecs()

		mouse_x = MouseX()
		mouse_y = MouseY()
		
		If MouseHit(1) Then create_laser(mouse_x, mouse_y)
		
		Cls
		
		draw_lasers()
		
		Color 255,255,255
		Oval mouse_x-4,mouse_y-4,9,9,True
		
		WaitTimer(fps_timer)
		Flip True
	Wend

	End


;
;
;
Function create_laser(start_x, start_y)

	this.laserT = New laserT

	this\x = start_x
	this\y = start_y
	
	this\len_ang = 0.0
		
End Function


;
;
;
Function draw_lasers()

	For this.laserT = Each laserT
		cur_len = (Sin(this\len_ang) * LASER_LEN)
		
		If cur_Len >= LASER_LEN
			Delete this
		Else
			Color Rand(0,255),Rand(0,255),Rand(0,255)
			Line this\x,this\y,this\x+cur_len,this\y
		
			this\len_ang = this\len_ang + 2.0
		EndIf
	Next

End Function


BlitzMax version with Delta Timing (of sorts). Try with Flip 0 instead of Flip 1, it runs the same speed. Personally I normally keep the logic separate from the drawing.

Strict

'Init
Graphics 800,600,0 'windowed mode
SeedRnd MilliSecs()

'Types
Type TLaser
	Global LASER_LEN = 500
	
	Field x,y
	Field len_ang#
End Type

Type TLaserList Extends TList
	
	Method Add(startx, starty)
		Local L:TLaser = New TLaser
		
		L.x = startx 
		L.y = starty		
		L.len_ang = 0.0
		AddLast(L)
	End Method 
	
	Method Draw()
		For Local L:TLaser = EachIn Self
			Local cur_len = (Sin(L.len_ang) * TLaser.LASER_LEN)
			If L.len_ang > 90 Then 'don't let it go beyond 90 degrees or it'll shrink!
				Remove(L)
			Else
				SetColor Rand(0,255),Rand(0,255),Rand(0,255)
				DrawLine L.x,L.y,L.x+cur_len,L.y
			
				L.len_ang = L.len_ang + (3.0*Delta)
			EndIf		
		Next
	End Method	
End Type

'Variables
Local LaserList:TLaserList = New TLaserList

'Timing
Const FRAME_LENGTH=10 'in millisecs
Global Delta#
Local LastTime = MilliSecs()

'Main Loop
While Not KeyHit(Key_escape)
	Local Current = MilliSecs()
	Local elapsed# = Current-LastTime 'float for future calcs
	'Compare elapsed against one frame which we want to be 10ms (100FPS)
	Delta = elapsed/FRAME_LENGTH	
	LastTime=Current 'keep track
	
	Local mx = MouseX()
	Local my = MouseY()
	
	If MouseHit(1) Then LaserList.Add(mx,my)	
	
	Cls		
	LaserList.Draw()
	SetColor 255,255,255
	DrawOval mx-4,my-4,9,9
	DrawText Delta,0,0
	
	Flip 1 'Vsync on
'	Flip 0 'Vsync off (note how it runs the same speed)
Wend

End


With autofire and separate laser logic and drawing:

Strict

'Init
Graphics 800,600,0 'windowed mode
SeedRnd MilliSecs()

'Types
Type TPlayer
	Field Reload#
	Field ReloadLength = 10 'in frames

	Method Manage()
		Reload:-Delta
		If Reload<=0 Then Reload=0 'safety
	End Method

	Method Fire(mx,my)
		If Reload <=0 Then 
			LaserList.Add(mx,my)		
			Reload = ReloadLength
		EndIf
	End Method	
End Type
	
Type TLaser
	Global LASER_LEN = 500
	
	Field x,y
	Field len_ang#
End Type

Type TLaserList Extends TList
	
	Method Add(startx, starty)
		Local L:TLaser = New TLaser
		
		L.x = startx 
		L.y = starty		
		L.len_ang = 0.0
		AddLast(L)
	End Method 

	Method Manage()
		For Local L:TLaser = EachIn Self
			If L.len_ang > 90 Then 'don't let it go beyond 90 degrees or it'll shrink!
				Remove(L)
			Else
				L.len_ang = L.len_ang + (3.0*Delta)
			EndIf
		Next	
	End Method
		
	Method Draw()
		For Local L:TLaser = EachIn Self
			Local cur_len = (Sin(L.len_ang) * TLaser.LASER_LEN)
			SetColor Rand(0,255),Rand(0,255),Rand(0,255)
			DrawLine L.x,L.y,L.x+cur_len,L.y
		Next
	End Method	
End Type

'Variables
Global Player:TPlayer = New TPlayer
Global LaserList:TLaserList = New TLaserList

'Timing
Const FRAME_LENGTH=10 'in millisecs
Global Delta#
Local LastTime = MilliSecs()

'Main Loop
While Not KeyHit(Key_escape)
	Local Current = MilliSecs()
	Local elapsed# = Current-LastTime 'float for future calcs
	'Compare elapsed against one frame which we want to be 10ms (100FPS)
	Delta = elapsed/FRAME_LENGTH	
	LastTime=Current 'keep track
	
	Local mx = MouseX()
	Local my = MouseY()

	'Logic
	Player.Manage()		
	If MouseDown(1) Then Player.Fire(mx,my)
	LaserList.Manage()

	'Drawing
	Cls		
	LaserList.Draw()	
	SetColor 255,255,255
	DrawOval mx-4,my-4,9,9
	DrawText Delta,0,0	

	Flip 1 'Vsync on
'	Flip 0 'Vsync off (note how it runs the same speed)
Wend

End



Oh come on, Post an emit sound event

please write the code, I don't know it :-)

Now with moving aliens and explosions via collision detection + enhanced laser and ship graphics.

Press R to summon more aliens.

Strict

'Init
Const ScreenWidth = 800
Const ScreenHeight = 600
Graphics ScreenWidth,ScreenHeight,0 'windowed mode
SeedRnd MilliSecs()

'Types
Type TPlayer
	Field x#
	Field y#
	Field front=15
	Field back=15
	Field height=10
	Field Reload#
	Field ReloadLength = 10 'in frames

	Method Manage()
		Reload:-Delta
		If Reload<=0 Then Reload=0 'safety
	End Method

	Method Fire()
		If Reload <=0 Then 
			LaserList.Add(x,y)		
			Reload = ReloadLength
		EndIf
	End Method	
	
	Method Draw()
		SetColor 100,100,255
		Local tri#[]=[x-back,y-height,x+front,y,x-back,y+height]
		DrawPoly tri
	End Method
End Type
	
Type TLaser
	Global LASER_LEN = 500
	Global SUB_LENGTH = 50
		
	Field x,y
	Field startx 'for laser beam start coord.
	Field len_ang#
	Field cur_len#
	
	Method SetStartX()
		cur_len = (Sin(len_ang) * TLaser.LASER_LEN)
		startx = x+cur_len-TLaser.SUB_LENGTH	
	End Method
	
	Method Draw()
		SetColor Rand(0,255),Rand(0,255),Rand(0,255)
		DrawLine startX,y,x+cur_len,y
		Local radius = 3
		Local tempx = x
		DrawOval tempx+cur_len-radius,y-radius,radius*2+1,radius*2+1
		tempx:-8
		radius = 2
		DrawOval tempx+cur_len-radius,y-radius,radius*2+1,radius*2+1
		tempx:-8
		radius = 1
		DrawOval tempx+cur_len-radius,y-radius,radius*2+1,radius*2+1
	End Method
End Type

Type TLaserList Extends TList
	
	Method Add(startx, starty)
		Local L:TLaser = New TLaser
		
		L.x = startx+TLaser.SUB_LENGTH 'offset 
		L.y = starty		
		L.len_ang = 0.0
		L.SetStartX()
		AddLast(L)
	End Method 

	Method Manage()
		For Local L:TLaser = EachIn Self
			L.SetStartX()
			If L.len_ang > 90 Then 'don't let it go beyond 90 degrees or it'll shrink!
				Remove(L)
			Else
				L.len_ang = L.len_ang + (3.0*Delta)
			EndIf
		Next	
	End Method
			
	Method Draw()
		For Local L:TLaser = EachIn Self
			L.Draw()
		Next
	End Method	
End Type

Type TAlien
	Field Speed#=0.05
	Field x#
	Field y#
	Field dx#
	Field dy#
	Field size#
	Field halfsize#

	Method SetSize()
		size = Rand(5,20)
		halfsize = size/2
	End Method
		
	Method Manage()		
		If Rnd(0,1)<Delta Then
			Select Rand(1,4)
				Case 1
					dx:-speed
				Case 2
					dx:+speed
				Case 3
					dy:-speed
				Case 4
					dy:+speed
			End Select					
		EndIf
		x:+dx*delta
		y:+dy*delta
		'constrain
		If x<0 Then x=0	ElseIf x>screenwidth-1 Then x=screenwidth-1
		If y<0 Then y=0	ElseIf y>screenheight-1 Then y=screenheight-1
	End Method
	
	Method Draw()	
		SetColor 0,255,0
		DrawOval x-halfsize,y-halfsize,size,size
	End Method
End Type

Type TAlienList Extends TList
	Method Add(x,y)
		Local a:TAlien = New TAlien
		a.x=x
		a.y=y
		a.SetSize()
		
		AddLast(a)
	End Method
	
	Method Fill(Qty)
		For Local i=1 To Qty
			Add(Rand(ScreenWidth-(ScreenWidth/3),ScreenWidth-1), Rand(0,ScreenHeight-1))
		Next
	End Method
	
	Method Manage()
		For Local A:TAlien = EachIn Self
			A.Manage()
		Next
	End Method
	
	Method Collide()
		'Have any aliens been hit by lasers? (not very efficient)		
		For Local a:TAlien = EachIn Self
			For Local L:TLaser = EachIn LaserList
				'pretend laser is 3 pixels thick and aliens are square.
				If ccRectsOverlap(a.x-a.halfsize,a.y-a.halfsize,a.size,a.size,L.startx,L.y-1,TLaser.SUB_LENGTH,3) Then
					Explosionlist.Add(a.x,a.y,a.size*2)
					remove(a)
					'Uncomment the next line if you want the laser to be destroyed
					'on contact with an alien.
					'LaserList.Remove(L)
					Exit 'don't scan rest of lasers
				EndIf
			Next
		Next
	End Method

	Method Draw()
		For Local A:TAlien = EachIn Self
			A.Draw()
		Next
	End Method
End Type

Type TExplosion
	Field x#
	Field y#
	Field speed#=1
	Field size#
	Field halfsize#
	
	Method Manage()
		'shrink
		size:-speed*delta
		halfsize = size/2
		If size <=0 Then ExplosionList.Remove(Self)			
	End Method
	
	Method Draw()
		SetColor 255,0,0
		DrawOval x-halfsize,y-halfsize,size,size
		SetColor 255,128,0
		DrawOval x-(halfsize/2),y-(halfsize/2),size/2,size/2
	End Method
End Type

Type TExplosionList Extends TList
	Method Add(x#,y#,size#)
		Local e:TExplosion = New TExplosion
		e.x=x
		e.y=y
		e.size=size
		AddLast(e)
	End Method
	
	Method Manage()
		For Local e:TExplosion = EachIn Self
			e.Manage()
		Next
	End Method		
	
	Method Draw()
		For Local e:TExplosion = EachIn Self
			e.Draw()
		Next
	End Method		
End Type

'Variables
Global Player:TPlayer = New TPlayer
Global LaserList:TLaserList = New TLaserList
Global AlienList:TAlienList = New TAlienList
Const ALIENS = 100
AlienList.Fill(ALIENS)
Global ExplosionList:TExplosionList = New TExplosionList

'Timing
Const FRAME_LENGTH=10 'in millisecs
Global Delta#
Local LastTime = MilliSecs()

'Main Loop
While Not KeyHit(Key_escape)
	Local Current = MilliSecs()
	Local elapsed# = Current-LastTime 'float for future calcs
	'Compare elapsed against one frame which we want to be 10ms (100FPS)
	Delta = elapsed/FRAME_LENGTH	
	LastTime=Current 'keep track
	
	Player.x = MouseX()
	Player.y = MouseY()

	'Restart?/Refill?
	If KeyHit(Key_R)
		'AlienList.Clear() 'could clear but I'll just add to the existing ones.
		AlienList.Fill(ALIENS)
	EndIf
	
	'Logic
	Player.Manage()		
	LaserList.Manage()
	If MouseDown(1) Then Player.Fire() 'important to come after before AlienList.Collide()
	AlienList.Manage()
	AlienList.Collide()	
	ExplosionList.Manage()	
	'Drawing
	Cls		
	ExplosionList.Draw()
	AlienList.Draw()
	LaserList.Draw()	
	Player.Draw()	
	SetColor 200,200,0
	DrawText "x="+Player.x,0,0	
	DrawText "y="+Player.y,0,20
	DrawText "delta="+Delta,0,40	

	Flip 1 'Vsync on
'	Flip 0 'Vsync off (note how it runs the same speed)
Wend

End

' -----------------------------------------------------------------------------
' ccRectsOverLap
' -----------------------------------------------------------------------------
Function ccRectsOverlap%(x0, y0, w0, h0, x2, y2, w2, h2)
	If x0 >= (x2 + w2) Or (x0 + w0) <= x2 Then Return False
	If y0 >= (y2 + h2) Or (y0 + h0) <= y2 Then Return False
	Return True
End Function


You are just showing off now

Ok, now add network multiplayer. =)

just having fun. bah now it's been moved into the B3D thread.

Thanks to all for speedy replies, looking through them now!

bah now it's been moved into the B3D thread
lol, isnt Mick a B+ user?

@Mick, what language are you using?

Yes, using Blitz Plus.