bug challenge, I think?

Monkey Forums/Monkey Programming/bug challenge, I think?

Jesse(Posted 2016) [#1]
I have a problem, I want some object to move the same as in space invaders, from left to right and from right to left. It works fine moving right but not moving left. It goes beyond the edge of the screen which shouldn't.
the error seems to be in the aliens Update() method. I am braking my head and can't figure it out:


any help appreciated.


therevills(Posted 2016) [#2]
Hey Jesse... looks like it is checking only the far right "alien", I've made the code so you can see what is happening:



Still checking...


therevills(Posted 2016) [#3]
Ahhhhh!!!

	Method New(x:Float,y:Float)
		pos = New PVector2D(x,y)
		time = Millisecs()
		delay  = 40
		moveLeft = New PVector2D(-10,0)
		moveRight = New PVector2D(10,0)
		moveDown = New PVector2D(0,10)
		direction = moveLeft
		r = 0
		g = 0
		b = 0
	End Method


The direction object points to the last one in the list as you create the aliens! So it is the only last alien which direction will compare against successfully!

It'll have to be something like this:



Jesse(Posted 2016) [#4]
Thanks Therevills:
>Hey Jesse... looks like it is checking only the far right "alien"
what I find odd is that direction is global so if one alien goes right all of them need to go right. It also checks every alien to see if it went beyond the left edge then it switches direction as it does for the right but for some reason it only works while moving right.


therevills(Posted 2016) [#5]
It does work moving left, but you have to wait for the far right (last) alien to move past 180.

When you assign direction, you are assigning it every time when you create a new alien and so when the last alien is created it has the value of the last alien's right, therefore when you compare (If pos.x > 500 And direction = moveRight) direction is only the same as the last alien's right and then you assign it to be the same as the last alien's left. So again when you compare (Elseif pos.x < 140 And direction = moveLeft) it is only the same as the last alien's left.


Jesse(Posted 2016) [#6]
check it out, I just figured out that if I replace the pointer comparison in the alien.Update with the direction variable, the movement works. There is another bug but that I will deal with differently. There seems to be something wrong with the pointer comparison:
	Method Update:int()
		If time + delay < Millisecs()
			pos.Add(direction)
			time = Millisecs()
			If pos.x > 500 And direction.x = moveRight.x '***********************************
				direction = moveLeft
				Return True
			Elseif pos.x < 140 And direction.x = moveLeft.x	'*****************************		
				direction = moveRight
				Return True
			Endif
		Endif
		Return False
	End Method



Jesse(Posted 2016) [#7]
here it is working:

I still think there is something wrong with the pointer comparison. What do you think? I have used it in several games and works fine but for some reason it's not working there.
FYI, I just added.x to the pointer comparison and move the timer into the alien manager class. and I separated movement from comparison so it would not break the patter.
if you remove the x rom the direction comparison it should still fail which is an enigma to me.


muddy_shoes(Posted 2016) [#8]
You have direction as a global within the Alien class and moveRight and moveLeft as fields so comparing them by "pointer" would only be valid for whichever Alien instance happened to set the direction last time around as the moveLeft and moveRight references are unique for each Alien.


Jesse(Posted 2016) [#9]
yes, and all it needs is to find one thats beyond the edge for it to change direction for all and thats why I used the global movement.
I don't know if you notice but I just added x's to the comparison and it worked. so technically it would be the same comparison except that now instead of pointers is values.

Sorry Muddy but maybe I am just being stubborn but my brain logic don't want to let it go that easy.

this is technically what is going on:

if you notice they produce the same output. and it's working fine here but not in the code above.


muddy_shoes(Posted 2016) [#10]
It's not technically the same comparison as you explicitly set all the values to be the same but the "pointers" are all different as I said (and therevills seems to have tried to explain). With the value comparison any of the Alien instance tests will work and with the "pointer" comparison only one will, specifically the last created instance with the code as you have it now.


Jesse(Posted 2016) [#11]
sorry, Muddy but explain to me this one now then
wait for the second pass:



muddy_shoes(Posted 2016) [#12]
You don't say what is occurring that you don't understand so it's a little difficult to know what you want me to explain. I'd guess you've failed to notice the inconsistency in your update:

Method Update:int()
			If pos.x > 500 And direction = moveRight
				direction = moveLeft
				Return True
			Elseif pos.x < 140 And direction.x = moveLeft.x			
				direction = moveRight
				Return True
			Endif
		Return False
	End Method


Going right you test by reference and going left you test by value. The direction reference in use therefore swaps from the last alien to the first on the second pass. Just putting some prints in shows what is happening:




Jesse(Posted 2016) [#13]
Muddy and Threvills thank for you time and effort in helping me.
Muddy, well it's being working since several post above. so I don't really need a solution anymore and to continue this redundant conversation is pointless because I am being stubborn and you guys are not seeing my point. I appreciate your help. Maybe sometime in the future I will see your guy's point. and I will have one of those ahhhh! moments.


therevills(Posted 2016) [#14]
In the code I posted above you can see I created a Compare method in the PVector2D class:
Method Compare:Bool(v:PVector2D)
	Return x = v.x And y = v.y
End


Which allows you to compare the direction object and moveRight object by value:
If pos.x > 500 And direction.Compare(moveRight)



Jesse(Posted 2016) [#15]
Thanks Therevills. I guess I am guilty for not really looking at the code thoroughly and since it wasn't what I wanted to figure out I partially ignored your code. But you are right.
and thanks for your help.


therevills(Posted 2016) [#16]
Just for fun a MX2 version using a struct instead of a class for the PVector2D:



Notice that we can now do the compare using the struct directly (as structs are by value).

And if you want to live dangerously you could do operator overloading on the vector:

Operator+:PVector2D(v:PVector2D)
	Return New PVector2D(x + v.x, y + v.y)
End

Method Move()
	pos += direction
End



Jesse(Posted 2016) [#17]
all that sounds fun but I don't want to get into it until the official release. I am struggling as it is with monkey.
Thanks.