ImagesCollide

BlitzMax Forums/BlitzMax Beginners Area/ImagesCollide

Zacho(Posted 2009) [#1]
I have a quick question. When calling ImagesCollide, I get an error "unable to access null value" or something of that nature. I think the problem lies in my image code:
Global bulletSnipe:TImage = LoadImage("mypic.bmp")

Global aquaIdle = LoadImage("mypic.bmp")
[code]
If ImagesCollide(bulletSnipe:TImage,b.x,b.y,0,aquaImage,aqua_x,aqua_y,0)
	ListRemove bulletSlist, b
			'	'do something
				'...
EndIf

[/code]
Note: The first image "bulletSnipe" is a list so that is why there is a "b.x" and "b.y" there. Also, the aqua instance is created before the "ImagesCollide" func is passed.

To fix the problem do you think I should add a colon after aquaIdle and put TImage there?


Dreamora(Posted 2009) [#2]
the problem is b.x, b.y
you don't have an object b there so accessing bs field will fail.


the other thing is that you don't define the type of aquaIdle
never program in BM without strict / superstrict at the start


Zacho(Posted 2009) [#3]
Um, I forgot to tell you something. B is defined and all of that earlier in my program, if you want to see the actual code tell me. And for aquaIdle, its values are created and the type is also defined earlier in my program as well. (Ask me for the code if you need/want it)


Zacho(Posted 2009) [#4]
I know this code is what most people call 'messy'. I learned the use and importance of strict and superstrict after I started to write this code, so... I probably won't re-fix the code with strict until I totally finish my game.



Zacho(Posted 2009) [#5]
I read some posts on Images Collide and have some additional questions:

Function CollideImage:Object[](image:TImage,x,y,frame,collidemask%,writemask%,id:Object=Null)


- Do you have to call CollideImage before you test if the images collide using ImagesCollide?

-In the function CollideImage, if there is no frame field can I type a 0?

-Do I have to change collidemask% to anything?

-Would I have to put something in writemask% if my images have multiple frames with different motions?


Volker(Posted 2009) [#6]
Hi Zacho,

I made a quick attempt to convert your code to strict-mode, finding
a lot of problems. Example:
You are using aqua_x in a funtion in the Type TBullet.
You have defined aqua_x =650.
But because it is defined outside the function, Blitzmax
sets the value to 0, because it is defined on the fly new in the function.
Do you really want to test an ImageCollide at position 0? No.
And there are a lot of such things.
So my advice to you:Click here!


Jesse(Posted 2009) [#7]
@Volker, LOL.

@Zacho
I'll show you how to use images collide. to tell you the truth that is the least of your problems and that is not going to help you at all. you don't understand any concept of types and you wont understand anything until you learn the basics which you won't get it until you at least understand the tutorials. Even if you get all of the syntax error resolved(like 200 and i am being optimistic), you have ten times as many logic problems but if that is what you want I am just going to humor you.

if you press f1 when the cursor is under the word imagescollide in the bmax IDE you get this at the bottom of the ide:
Function ImagesCollide(image1:TImage,x1,y1,frame1,image2:TImage,x2,y2,frame2)

if you press f1 again it sends you to the help page and displays some basic information on how to use it. I'm shure you knew that.
the same goes for collideimage or any other hilited word you see in the ide. this is the definition for CollideImage:
Function CollideImage:Object[](image:TImage,x,y,frame,collidemask%,writemask%,id:Object=Null)
and you can get more information if you press f1 twice. It actually has an example but it's complicated to understand.

imagesCollide is the simples one to use all you have to do is fill fields with the information and you are set. True, you can put a 0 if the image don't have frames. this function is more like a rectangle collision than anything else.
the collideImage function is a pixel pefect collision that detects pixels with a color value and masks. it is a little bit more complicated than any basic tile collision function in Blitzmax. ther is also a tutorial for it but I am shure you are not going to take the time to read it so I wont waste my time posting a link for you. if you want to look for it is in the tutorials section written by Asari.


Zacho(Posted 2009) [#8]
@Volker- Thats why
I'm hoping to make the conversion when I am done. Hopin to save some time.

Btw: funny pic :)

@Jesse?- So basically I have the right idea? So before the ImagesCollide I would put a "For b.TBullet EachIn Bulletslist" statement, right? Or am I headed in the wrong direction?


Gabriel(Posted 2009) [#9]
@Volker- Thats why I'm hoping to make the conversion when I am done. Hopin to save some time.

How do you figure that leaving the single most important change you could make to help you fix most of the problems in your code until after you've already fixed those problems the hard way is going to save you time?


Zacho(Posted 2009) [#10]
Um, well maybe because my code works atm. And also I am not aware of the 'right' way to organize my code. All functions? Types? Methods? Constants/Globals? I don't know


Gabriel(Posted 2009) [#11]
Um, well maybe because my code works atm.

No it doesn't. You just think it does because you're intentionally telling the compiler not to report errors. Volker already pointed out one example.

And also I am not aware of the 'right' way to organize my code. All functions? Types? Methods? Constants/Globals? I don't know

None of that has any bearing on the use (or not) of SuperStrict. SuperStrict doesn't care how you organize your code. It just cares if you try to use a variable you haven't declared. If you mean that using SuperStrict will force you to define a scope for your variables, then I regret to inform you that your variables already have a scope whether you define it or not and whether you like it or not. The compiler knows the scope either way. Currently, you may not, which is also making life harder for you.


Jesse(Posted 2009) [#12]

So basically I have the right idea?



yes, for the collision only.


So before the ImagesCollide I would put a "For b.TBullet EachIn Bulletslist" statement, right? Or am I headed in the wrong direction?


yes, you are headed in the wrong direction.

At the rate you are going it is going to take you the whole year and you are not going to get anywhere with that code.

note: I can feel the frustration on these guys trying to help you and not getting anywhere with you.

I recomend you "nuke" that code and start from scratch with SuperStrict.

I would like to help you get a proper game started but you have start from scratch otherwise I guarantee, you'll give up before you get it done. there are so many bugs and incosistencies in your code that it buffles my mind. You really don't understand types and that mekes it imposible to code and frustrates anyone trying to help you. we don't know where to get started. no matter where you point to fix it, it won't run.


Zacho(Posted 2009) [#13]
.......sigh.........

ah.

I guess if my code is too messy I will try to rewrite it in superstrict for the sole purposes:
-to hopefully learn something :)
-to make my code 'proper'
-and to finally get some tips/help on my game >.<


Jesse(Posted 2009) [#14]
I recomend start by first creating one type. Sence objects(types) are more or less self contained, you can create one object(type) at a time and test it with some simple code.
first try to understand how a simple type work:
first the real basic ones:
a:int = 3
temp:float = 3.4
b:double = 3.4
f:long = 3
g:string = "abcd123"

but I am shure you knew this ones allready.

Now to a more complex one.
besides those types, there are made up types. These one you create yourself and can be made up of basic types(as described above) and/or 'made up' types.
first you have to define it:
Type Tmytype
End type

You can create a type with whatever name you want to give it. I use the capital "T" at the beginning of "Tmytype" to remind me or anyone that reads my code that it is a 'Type'.

When you crate a type for a game, most of them will have an x and a y for any thing you want to move so lets create it:
Type Tmytype
     Field x:int
     field y:int
end type

There I have crated a type like 'int', 'float', 'long'... etc. and I can use it the same way:
local a:Tmytype

Now when I do that, all I am doing is create an address on memory for "a" but not for x and y. if I try to use it in this state, I will get an error.
created types have to be initialized(there are exeptions but lets skip that for now) before using and this is how it's done:
 a:Tmytype = new Tmytype

Now the x and y have an address in memore and now I can do this:
a.x = 3
a.y = 4

You can reuse the 'Tmytype' like any other type but this ones have to be initialized all of the time. Lets create another "instance" of the same type:
Local player:Tmytype = new Tmytype

Notice I did in one line what I did with 'a' in two lines. You can do it either way.
Now I can use it like this:
player.x = 7
player.y = 4


I can create another one the same way:
local bullet:Tmytype = new Tmytype
bullet.x = 3
bullet.y = 9


And another one:
local lazer:Tmytype  = new Tmytype
lazer.x = 27
lazer.y = 51

notice I used the same type("Tmytype") for all of the instances I created and they all can coexist in the same program. The "New" command find a different area of memory in the computer to store each one.
If you understand this, you will be able to see a lot of the errors in your code. If you don't, ask question. Myself or others will be here to help you.

I will keep on adding to the types but I need to know you understand these first.


Zacho(Posted 2009) [#15]

a:int = 3
temp:float = 3.4
b:double = 3.4
f:long = 3
g:string = "abcd123"

but I am shure you knew this ones allready.


Ya, I did. Except double and long. What are those?

local a:Tmytype

That is saying that a variable 'a' has the same fields as type Tmytype and will refer to Tmytype for local functions, right?

a.x = 3
a.y = 4

This is saying that the variable a uses the field of x and y from the type which is refrenced to it. (which is Tmytype)

Local player:Tmytype = new Tmytype

Creates a player with the fields/functions/etc of Tmytype

Am I getting this?


Jesse(Posted 2009) [#16]
local a:Tmytype

this is just saying reserve a single address in memory for when an 'instance' of "Tmytype" is created.

you got the second one correct

Local player:Tmytype = new Tmytype

it will create new fields everytime, it reuses the functions with the cureent "instance" of the type.

see if this makes more sence to you:



this is very similar to what really happens. The 'a' and 'ship' is only representative of what happens but not exactly.


Volker(Posted 2009) [#17]
Ya, I did. Except double and long. What are those?


From the help:
Description Syntax Minimum value Maximum value
8 bit unsigned integer Byte 0 255
16 bit unsigned integer Short 0 65535
32 bit signed integer Int -2^31 +2^31-1
64 bit signed integer Long -2^63 +2^63-1
32 bit floating point Float (+/-)10^-38 (+/-)10^38
64 bit floating point Double (+/-)10^-308 (+/-)10^308

If you don't alread own it, here is a blitzmax helpfile
in .chm format (windows helpfile)
http://www.finipa.de/resources/blitzmax/blitzmax128.zip


Zacho(Posted 2009) [#18]
@Jesse - No. The pic really confuses me

@Volker - Ok, thanks.


Jesse(Posted 2009) [#19]
try understanding this code:
type Tmytype
   Field x:int
   Field y:int
End Type

local a:Tmytype = new Tmytype
a.x = 30
a.y = 45
local ship:Tmytype = new Tmytype
ship.x = 20
ship.y = 2
print "this is the a instance"
print "a.x = "+a.x
print "a.y = "+a.y
print "this is the ship instance"
print "ship.x = "+ship.x
print "ship.y = "+ship.y

notice that I only crated one type for both objects, object 'a' and object 'ship'
pay attentiont to the output and compare.


Zacho(Posted 2009) [#20]
Ok, so you create a type called Tmytype. It has fields x and y, which are integers (no decimals).

You create a new instance which
reserves a single address in memory for when an 'instance' of "Tmytype" is created.
And puts the value of x @ 30 and y @ 45. Then creates a different instance of Tmytype in the address of "ship", whose values are 20 (for x) and 2 (for y).

Then you print:
this is the a instance
a.x = 30
a.y = 45
this is the ship instance
ship.x = 20
ship.y = 2


Makes sense. You use Tmytype for the fields then assign different objects to the same field but use different values for each object, right?


Jesse(Posted 2009) [#21]
no, you still got it wrong. 'a' is like 'ship' the value 30(for x) and the value 45(for y)


Zacho(Posted 2009) [#22]

no, you still got it wrong. a is like ship the value 30(for x) and the value 45(for y)



I'm a little confused with your wording. Are you trying to say "No, you still got it wrong. "A" is like the ship, with the value of x @ 30 and the value of y @ 45"


Jesse(Posted 2009) [#23]
in your code you have this:
Type DiscoBall
	Field x,y
	Field frame
EndType
Type Sensor
	Field x,y
	Field frame
	'Field   Array
EndType
Type Sensor2
	Field x,y
	Field frame
	'Field   Array
EndType
Type Sensor3
	Field x,y
	Field frame
	'Field   Array
EndType
Type Sensor4
	Field x,y
	Field frame
	'Field   Array
EndType

discoB_DiscoBall = New DiscoBall
discoB_x = 330
discoB_y = 150
discoB_frame = 0 
'
' S E N S O R   1
sensor_Sensor = New Sensor
sensor_x = 132
sensor_y = 574 
sensor_frame = 0
'
' S E N S O R   2
sensor2_Sensor2 = New Sensor2
sensor2_x = 372
sensor2_y = 574
sensor2_frame = 0
'
' S E N S O R   3
sensor3_Sensor3 = New Sensor3
sensor3_x = 611
sensor3_y = 574
sensor3_frame = 0
'
' S E N S O R   4
sensor4_Sensor4 = New Sensor4
sensor4_x = 160
sensor4_y = 574
sensor4_frame = 0

that is wrong
it should be like this:
Type Tmytype
	Field x:int
        Field y:int
	Field frame:int
EndType

discoB:Tmytype = New Tmytype
discoB.x = 330
discoB.y = 150
discoB.frame = 0 
'
' S E N S O R   1
sensor:Tmytype = New Tmytype
sensor.x = 132
sensor.y = 574 
sensor.frame = 0
'
' S E N S O R   2
sensor2:Tmytype = New Tmytype
sensor2.x = 372
sensor2.y = 574
sensor2.frame = 0
'
' S E N S O R   3
sensor3:Tmytype = New Tmytype
sensor3.x = 611
sensor3.y = 574
sensor3.frame = 0
'
' S E N S O R   4
sensor4:Sensor4 = New Tmytype
sensor4.x = 160
sensor4.y = 574
sensor4.frame = 0


notice, I replaced all of your types with one type "Tmytype" and used it for all of your objectst.


Zacho(Posted 2009) [#24]
Ok. Ya I get that. It makes sense to me. Since all of the types have a x,y, and frame field, it makes it eaiser to link them all to the Tmytype, right?


Jesse(Posted 2009) [#25]
correct, and that is the purpose of user types. now see if you understand this(more compact code)
Type Tmytype
     Field x:int
     Field y:int
     Field f:int

     Method init(a:int, b:int,q:int)
           x = a
           y = b
           f = q
     End Method
End Type

discoB:Tmytype = New Tmytype
discoB.init(330,150,0) 
'
' S E N S O R   1
sensor:Tmytype = New Tmytype
sensor.init(132,574,0)
'
' S E N S O R   2
sensor2:Tmytype = New Tmytype
sensor2.init(372,574,0)
'
' S E N S O R   3
sensor3:Tmytype = New Tmytype
sensor3.init(611,574,0)
'
' S E N S O R   4
sensor4:Tmytype = New Tmytype
sensor4.init(160,574,0)

this is the same code as above.
can you figure out what I did?


Zacho(Posted 2009) [#26]
Um...well....

First you create a type "Tmytype" with fields x= an integer, y=an integer, and f=an integer. Also in this type you delclare a method (which is a func inside of a type right?) with values "a" and "b". "a" being the first value inside the parameters and "b" the second. BUT you have
x = a
y = b

following the declaration of the method, which means that the field x and y (which you called when you created the type) could also be called with "a" and "b".

So when you type
sensor4:Sensor4 = New Tmytype
sensor4.init(160,574,0)

You are telling the compiler to create a new instance of Tmytype with the handle of 'sensor4'. Sensor4's x value is 160 and sensor's y value is 574, while the 'f' value stays at zero. Correct?


Jesse(Posted 2009) [#27]
you pretty much figured it out. I made a mistake when I created the method. I forgot to add the last field to accept the frame. if you had tried to run that code it would have given a syntax error. I also made a mistake when I created sensor4. It should have been "sensor4:Tmytype". I just corrected them.
now lets see if you understand this:
Type Tmytype
     Field x:Int
     Field y:Int
     Field frame:Int

     Method init(a:Int, b:Int,q:Int)
           x = a
           y = b
           frame = q
     End Method

     Method draw()
           DrawRect x,y,10,10
     End Method
End Type

discoB:Tmytype = New Tmytype
discoB.init(330,150,0) 
'
' S E N S O R   1
sensor:Tmytype = New Tmytype
sensor.init(132,574,0)
'
' S E N S O R   2
sensor2:Tmytype = New Tmytype
sensor2.init(372,574,0)
'
' S E N S O R   3
sensor3:Tmytype = New Tmytype
sensor3.init(611,574,0)
'
' S E N S O R   4
sensor4:TmyType = New Tmytype
sensor4.init(160,574,0)

Graphics 800,600
discoB.draw()
sensor.draw()
sensor2.draw()
sensor3.draw()
sensor4.draw()
Flip()
WaitKey()




Zacho(Posted 2009) [#28]
Don't worry bout' your mistakes. Everyone makes em' (and it seems to be me >.<)

Code time....Ok so you create a type "Tmytype" with fields x=integer, y=integer, and frame=integer. Then you create a method called init with values of x, y, and frame to be in parentheses. As before x = a, y = b, and a NEW addition!!! ... frame = q. You also have another method called draw(). This draws a rectangle @ the x value, y value, and ___ and ___ [Don't know drawrect() function really well...]

Then you create a discoball with the handle of discoB which is linked to Tmytype. (discoB has all the fields that Tmytype has) and the value of x of discoB is 330, and y @ 150, and the frame @ 0....[So on and so forth for the other types and creation of new instances of types and handles]

Then [EXCITING PART!!] we start a graphics mode. The graphics mode is a screen that is 800 pixels wide by 600 deep (long) and call the draw() method for each new instance of a type that we created. This
___.draw()
draws a rectangle at the values that were called by ___.init(xvalue,yvalue,frame). Then we flip buffers and wait for the user to press a key.


Jesse(Posted 2009) [#29]
you got it. Now you got the basics! there are a lot more thing you need to learn about OO. Now when you read the OO tutorial you'll have an idea what you are reading.

now about SuprStrict:
the reason to use superstrict is that it help you with your syntax errors. If you use SuperStrict or strict and if you declare a variable such as Local or Global it will store its existence then if you misspell it somewhere else the comiler will give you an error. the same code with out SuperStrict or Strict and you misspell something in a place other than where you declared it the compiler will not know you miss spelled and just recognize it as a new variable. it may not be to much of a deal if your code is small because you might be able to find it right away. but if your code is large you might never be able to find it. Take that in consideration when writing your code.


Zacho(Posted 2009) [#30]
Jesse, that is just what I needed to grasp this OO stuff, examples. I was originally going to ask if you could give me some, but I'm guessing you already knew that I needed them. :)

I guess I will try with SuperStrict first, then Strict if SuperStrict doesn't work out. Thanks so much for all your help! I really truly appreciate it. :)