Drawimage memory acess error.

Monkey Forums/Monkey Beginners/Drawimage memory acess error.

ElRageO(Posted 2015) [#1]
I am new to class and method/ object oriented programming.

I was a wiz at darkbasic but im having a bit of trouble here. In my very short program I am just trying to get the bullet object drawn on screen when I click the mouse. I keep getting memory access error though when I put the DrawImage command.

Can you tell me what Im doing wrong here ?

Import mojo

Class Game Extends App
Field b:bullet

Method OnCreate ()

SetUpdateRate 60

End


Method OnRender ()

Cls 32, 64, 128 ' Clear screen

DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25


End

Method OnUpdate ()

If MouseHit(MOUSE_LEFT) Then
b = New bullet
b.image2 = LoadImage ("bullet.png", 1, Image.MidHandle)
'DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25
Print "Mouse Clicked"
End If
End


End

Class bullet

Field x:Float = 100
Field y:Float = 100
Field image2:Image

End

Function Main ()

New Game
End


Pharmhaus(Posted 2015) [#2]
Hello,

The problem occurs because the Methods OnUpdate() and OnRender() are executed at about 60 frames.
When you try to access the image of your bullet (first frame) the chance that you already clicked and an bullet object has been created is very low.
You can simply check if a bullet has been created before using.
Instead of this
Method OnRender ()

Cls 32, 64, 128 ' Clear screen

DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25

End 


you would use something like this.
Method OnRender ()

Cls 32, 64, 128 ' Clear screen

    If b<> null then ' Check if bullet has been created
        DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25
    Endif
End 



I am new to class and method/ object oriented programming.


The most important thing to understand is probably to realize that two bullets created via new are unrelated to each other. The best way to see this yourself is to use DebugStop() (glfw / desktop only) which halts the program and allows you to see the differences.
Import mojo

Class Game Extends App
	Field b1:bullet
	Field b2:bullet

	Method OnCreate ()

		SetUpdateRate 60
		b1 = New bullet
		b2 = New bullet
		
		b1.x = 100
		b2.x = 200
		
		DebugStop()
		
	End

	Method OnRender ()
		Cls()

	End

	Method OnUpdate ()
	End


End

Class bullet

	Field x:Float = 100
	Field y:Float = 100
	Field image2:Image

End

Function Main ()

	New Game
End



ElRageO(Posted 2015) [#3]
ah got it thanks that did the trick! I was trying to draw the image that did not exist.

BTW how are you posting the code block ? /code ?


Pharmhaus(Posted 2015) [#4]
There is a little forumcodes button just above the answer box ;)
EDIT: I updated the above post, please take a look.


ElRageO(Posted 2015) [#5]
I did and thanks :)


ElRageO(Posted 2015) [#6]
Well Im making progress and I am loving monkey x. So much so I bought it all ignition, rube and jungle :)

I have another question though. How do I destroy an object ? Bear with me I am new to object oriented programming.

In my program I want to kill the bullet once it reaches the top of the screen so that another can be created. I tried to Null the handle but monkey does not like that.

I Noted the point in the code where I am trying to destroy the object/class. Thanks for the help!

 If b <> Null Then
             
           	 		 If b.y > 0 Then
					 DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25
			 		 Else
			 		 b = Null ' HOW DO I DESTROY THIS ???????????????????????????????
					 End
			 
					 If b.y > 0 Then
					 b.y = b.y - 10
					 End
			 
					
			 
	 	     End 


The whole program

 Import mojo

Class Game Extends App
	Field b:bullet
    Field created:Int = 0
 	Field mx:Float
 	Field my:Float
 	
 	Method OnCreate ()
	  		
	  		 SetUpdateRate 60

	  End
	  

	Method OnRender ()

	 		Cls 32, 64, 128						' Clear screen
             
             If b <> Null Then
             
           	 		 If b.y > 0 Then
					 DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25
			 		 Else
			 		 b = Null ' HOW DO I DESTROY THIS ???????????????????????????????
					 End
			 
					 If b.y > 0 Then
					 b.y = b.y - 10
					 End
			 
					
			 
	 	     End

	  End 

	  Method OnUpdate ()
			
	  	 	
			If b = Null
			If MouseHit(MOUSE_LEFT) Then
				 ' b = New bullet
				  'b.image2 = LoadImage ("bullet.png", 1, Image.MidHandle)
				  'DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25
				
				b = New bullet
	  		    b.image2 = LoadImage ("bullet.png", 1, Image.MidHandle)
				created = 1
				  Print "Mouse Clicked"
			End If
			End
	  End
	  
	  
End

	

Class bullet 

Field x:Float = MouseX()
Field y:Float = MouseY()
Field image2:Image
	
	
End	
	

Function Main ()

New Game
End



Pharmhaus(Posted 2015) [#7]
Hello,

The problem comes from the fact that once the object has been set to null, none of its contents (fields) are accessible anymore.
A hotfix would be to check for null before performing anyaction.
Import mojo

Class Game Extends App
	Field b:bullet
	Field created:Int = 0
	Field mx:Float
	Field my:Float
 	
	Method OnCreate ()
	  		
		SetUpdateRate 60

	End
	  

	Method OnRender ()

		Cls 32, 64, 128						' Clear screen
             
		If b <> Null Then
             
			If b.y > 0 Then
				DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25
			Else
				b = Null ' HOW DO I DESTROY THIS ???????????????????????????????
			End
			 
			If b <> Null and b.y > 0 Then
				b.y = b.y - 10
			End
			 
					
			 
		End

	End

	Method OnUpdate ()
			
	  	 	
		If b = Null
			If MouseHit(MOUSE_LEFT) Then
				' b = New bullet
				'b.image2 = LoadImage ("bullet.png", 1, Image.MidHandle)
				'DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25
				
				b = New bullet
				b.image2 = LoadImage ("bullet.png", 1, Image.MidHandle)
				created = 1
				Print "Mouse Clicked"
			End If
		End
	End
	  
	  
End

	

Class bullet

	Field x:Float = MouseX()
	Field y:Float = MouseY()
	Field image2:Image
	
	
End
	

Function Main ()

	New Game
End

That being said, it is advisable to use collections of multiple objects.
One of the things thats makes programming with objects much better than conventional programming is the idea to move actions from your Game class to the object itself (the bullet updates itself).
This way you know if bullet misbehaves that the error is very likely to be found in bullet itself and no where else.
Compared with classical programming were you have a lot of global variables that are accessible from everywhere you can now better determine whos fault what is and the scalability of your programs increase. In this example a bullet list has been introduced to hold multiple bullets.
Please also note that calling LoadImage() when ever you click will also very likely slow down your game. It should also be stated that putting behaviour/thinking/logic into onrender in not advisable as OnRender will slow down/ some misbehaviour might occur due to the fact that OnRender is sometimes called without reason and then your games continues to play but is also paused (e.g. OnUpdate is paused but OnRender() not because the window needs to be redrawn).
Import mojo

Class Game Extends App
	Field bulletList:List<bullet> = New List<bullet> ' A list of multiple bullets
	Field bulletImage:Image
	Field created:Int = 0
	Field mx:Float
	Field my:Float
 	
	Method OnCreate ()
	  		
		SetUpdateRate 60
		bulletImage = LoadImage("bullet.png", 1, Image.MidHandle) ' Dont reload the same image, we only need it once
	End
	  

	Method OnRender ()

		Cls 32, 64, 128						' Clear screen
            
		' take each bullet stored in bulletlist and step-by-step but them into i
		For Local i:bullet = EachIn bulletList' i changes as we store bullets here temporary
			i.OnRender()
		Next
	End

	Method OnUpdate ()
		
		' take each bullet stored in bulletlist and step-by-step but them into i
		For Local i:bullet = EachIn bulletList ' i changes as we store bullets here temporary
			i.OnUpdate() '
		Next
	
		If bulletList.Count() < 10 Then
			If MouseHit(MOUSE_LEFT) Then
				' b = New bullet
				'b.image2 = LoadImage ("bullet.png", 1, Image.MidHandle)
				'DrawImage b.image2, b.x, b.y, 0, 0.25, 0.25
				
				Local b:bullet = New bullet
				b.image2 = bulletImage
				created = created + 1
				
				b.listEntry = bulletList.AddLast(b) ' add b to the list; the list returns a listentry where b has been put into
				Print "Mouse Clicked"
			End If
		EndIf
	End
	  
	  
End

	

Class bullet

	Field x:Float = MouseX()
	Field y:Float = MouseY()
	Field image2:Image
	Field listEntry:list.Node<bullet> ' Store a list entry for bullets
	
	Method OnRender()
		DrawImage image2, x, y, 0, 0.25, 0.25
	End
	
	Method OnUpdate()
		If y > 0 Then
			y = y - 10
		ElseIf listEntry <> Null
			listEntry.Remove() ' Remove this exact bullet from the list
		End
	End
	
	
End
	

Function Main ()

	New Game
End



ElRageO(Posted 2015) [#8]
Thanks very much for the restructure.

As I am new I was not sure if I could load the image just 1 time and I was unsure as to where best to put the actions. I tried unsuccessfully to
re arrange the code in a better fashion but was struggling due to my lack of experience with this type of language. (Hence the reason of just trying a small program to get things moving and working the way I want)

The list also solves the next problem I was looking at which is multiple bullets.

A++ for the comments this is exactly what I needed to help me get my head around the structure! This will keep me bust for a while and saved me a ton of head scratching moments.
Thanks again!