whats wrong here

Blitz3D Forums/Blitz3D Beginners Area/whats wrong here

grimx(Posted 2006) [#1]
for some reason unknown too me i get ( object does not exist ) when i kill an enemy.
Please Help.
theres no media so you can copy and paste to see what i'm talkin about.
*********************************************
Type Player
Field x
Field y
End Type

Type Enemy
Field x
Field y
End Type

Type Bullet
Field x
Field y
End Type

SeedRnd MilliSecs()
Graphics 600,400
SetBuffer BackBuffer()

Global BulletTimer=MilliSecs()

create_player()
create_enemy()

While Not KeyHit(1)

update_player()
update_enemy()
update_bullet()
kills()

Flip
Cls
Wend
End

Function kills() ;NEEDS WORK... BAD REAL BAD
For e.enemy=Each enemy
For b.bullet=Each bullet
If RectsOverlap(e\x,e\y,10,10,b\x,b\y,10,10)
Delete e
End If
Next
Next
End Function

Function create_player()
p.Player=New Player
p\x=300
p\y=350
End Function
Function update_player()
For p.Player=Each Player
Color 100,100,100
Rect p\x,p\y,20,20
If KeyDown(203) p\x=p\x-2
If KeyDown(205) p\x=p\x+2
If KeyHit(57) And MilliSecs()>BulletTime Then Create_Bullet(p\x,p\y)
Next
End Function

Function create_enemy()
For i=1 To 5
e.Enemy=New Enemy
e\x=Rnd(10,500)
e\y=Rnd(10,100)
Next
End Function
Function update_enemy()
For e.Enemy=Each Enemy
Color 200,200,200
Rect e\x,e\y,10,10
Next
End Function

Function create_bullet(x,y)
b.Bullet=New Bullet
b\x=x+5
b\y=y-15
BulletTimer=MilliSecs()
End Function
Function update_bullet()
For b.Bullet=Each Bullet
Color 200,0,0
Rect b\x,b\y,10,10
b\y=b\y-3
If b\y<1 Then Delete b
Next
End Function


degac(Posted 2006) [#2]
Type Player
Field x
Field y
End Type

Type Enemy
Field x
Field y
Field destroy ; <<<<------------------ add to check
End Type

Type Bullet
Field x
Field y
End Type

SeedRnd MilliSecs()
Graphics 600,400
SetBuffer BackBuffer()

Global BulletTimer=MilliSecs()

create_player()
create_enemy()

While Not KeyHit(1)

update_player()
update_enemy()
update_bullet()
kills()

Flip
Cls
Wend
End

Function kills() ;NEEDS WORK... BAD REAL BAD
For e.enemy=Each enemy
	For b.bullet=Each bullet
		If RectsOverlap(e\x,e\y,10,10,b\x,b\y,10,10)
			e\destroy=1 ;<<<<<< ----------------------
		End If
	Next
	If e\destroy=1 Delete e; <<<<< ------ destroy 'safely'
Next
End Function

Function create_player()
p.Player=New Player
p\x=300
p\y=350
End Function
Function update_player()
For p.Player=Each Player
Color 100,100,100
Rect p\x,p\y,20,20
If KeyDown(203) p\x=p\x-2
If KeyDown(205) p\x=p\x+2
If KeyHit(57) And MilliSecs()>BulletTime Then Create_Bullet(p\x,p\y)
Next
End Function

Function create_enemy()
For i=1 To 5
e.Enemy=New Enemy
e\x=Rnd(10,500)
e\y=Rnd(10,100)
Next
End Function
Function update_enemy()
Color 200,200,200

	For e.Enemy=Each Enemy
	num=num+1
	Rect e\x,e\y,10,10
	Text e\x,e\y+10,num
	Next
End Function

Function create_bullet(x,y)
b.Bullet=New Bullet
b\x=x+5
b\y=y-15
BulletTimer=MilliSecs()
End Function
Function update_bullet()
	Color 200,0,0

	For b.Bullet=Each Bullet
		Rect b\x,b\y,10,10
		b\y=b\y-3
		If b\y<1 Then Delete b
	Next
End Function 

I add a new field to check the 'destroy' of the enemy, and the last check in the last loop will destroy 'safely' the type.
In your example you destroyed the type and THEN it will be looked for the next loop...


Nicstt(Posted 2006) [#3]
copied and pasted what u posted works ok for me, no matter i changed the resolution so i had all five aliens on screen, got an error on one

the error occurs when two bullets are on the screen

a work round whilst you figure it out is to use another field called 'visible' flagged as true/false.


Type Player
Field x
Field y
End Type

Type Enemy
Field x
Field y
Field vis ; added this
End Type

Type Bullet
Field x
Field y
End Type

SeedRnd MilliSecs()
Graphics 600,600
SetBuffer BackBuffer()

Global BulletTimer=MilliSecs()

create_player()
create_enemy()

While Not KeyHit(1)

update_player()
update_enemy()
update_bullet()
kills()

Flip
Cls
Wend
End

Function kills() ;NEEDS WORK... BAD REAL BAD
For e.enemy=Each enemy
For b.bullet=Each bullet
If RectsOverlap(e\x,e\y,10,10,b\x,b\y,10,10)
e\vis = False ; added this - removed delete
End If
Next
Next
End Function

Function create_player()
p.Player=New Player
p\x=300
p\y=350
End Function

Function update_player()
For p.Player=Each Player
Color 100,100,100
Rect p\x,p\y,20,20
If KeyDown(203) p\x=p\x-2
If KeyDown(205) p\x=p\x+2
If KeyHit(57) And MilliSecs()>BulletTime Then Create_Bullet(p\x,p\y)
Next
End Function

Function create_enemy()
For i=1 To 5
e.Enemy=New Enemy
e\x=Rnd(10,500)
e\y=Rnd(10,100)
e\vis = True ; added this
Next
End Function

Function update_enemy()
For e.Enemy=Each Enemy
Color 200,200,200
If e\vis = True ; added this
Rect e\x,e\y,10,10
EndIf; added this
Next
End Function

Function create_bullet(x,y)
b.Bullet=New Bullet
b\x=x+5
b\y=y-15
BulletTimer=MilliSecs()
End Function

Function update_bullet()
For b.Bullet=Each Bullet
Color 200,0,0
Rect b\x,b\y,10,10
b\y=b\y-3
If b\y<1 Then Delete b
Next
End Function


grimx(Posted 2006) [#4]
thax.


Sir Gak(Posted 2006) [#5]
Hi, when posting code, it helps to set the code off in the posting commands [ code ] and [ /code ] (without the blanks between the brackets).


GfK(Posted 2006) [#6]
Solution is to swap your nested For/Each's around in your collision code:

Function kills() ;NEEDS WORK... BAD REAL BAD
  For b.bullet=Each bullet
    For e.enemy=Each enemy
      If RectsOverlap(e\x,e\y,10,10,b\x,b\y,10,10)
        Delete e
      End If
    Next
  Next
End Function

Alternatively, just exit the For/Each loop after deleting the enemy:
Function kills() ;NEEDS WORK... BAD REAL BAD
  For e.enemy=Each enemy
    For b.bullet=Each bullet
      If RectsOverlap(e\x,e\y,10,10,b\x,b\y,10,10)
        Delete e
        Exit
      End If
    Next
  Next
End Function
Basically what you were doing wrong - when the first bullet collides with the enemy, you delete the enemy type itself. Your original code then proceeded to check the rest of the bullets for collisions against the now non-existent enemy.

This is why it only caused an error if there was more than one bullet active at the time of collision.