Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 15:10 17 Nov 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Sprite interrupt

Author Message
yock1960
Senior Member

Joined: 18/08/2020
Location: United States
Posts: 167
Posted: 02:30am 10 Feb 2021
Copy link to clipboard 
Print this post

As per usual, I'm probably doing something unexpected/wrong and I'm really not quite sure where I'm running into trouble or even if it's sprite interrupt's fault!

I'm trying to create a Qbert clone. This is something I've never remotely attempted...in fact I've never used sprites. After a month of programming, I have a 'kind of working' WIP, but now that I've added my 3rd 'character' (red ball, Qbert being 1 and Coily 2), I'm experiencing problems with 'sprite internal error', when hiding or showing sprites. I've been seeing these for a while, but just came up with the idea that perhaps it has something to do with what happens when the program returns from the interrupt and the fact that the 'interrupted' routine, was called by another interrupt.

I've been adding 'on error skip's pretty liberally...which is treating a symptom...and I think I'm suffering from 'rebound'! I originally started adding the on error skips for 'not showing' errors, which may have just been bad/sloppy coding.

The problem seems random. Sometimes I can play for a while...several rounds, but eventually, it strikes, sometimes sooner, sometimes later. I will say that it seems to have gotten worse after a rewrite, necessitated by only having 64 sprite/blit buffers, which after I progressed to a certain point, I realized I did not have the luxury of having a buffer for each character/direction/position and needed to redefine them on the fly.

Maybe if I knew what conditions generate an 'internal error'?

Steve
 
Nelno

Regular Member

Joined: 22/01/2021
Location: United States
Posts: 59
Posted: 07:02am 14 Feb 2021
Copy link to clipboard 
Print this post

It looks like SHOW, HIDE, SWAP and CLOSE all have the potential to generate the "sprite internal error" error.

From what I can tell just glancing at the MMBASIC code (I am a total noob at this code and have only spent maybe 30 minutes looking at it):

It looks like the code tracks sprites in what it calls a LIFO (Last In First Out) buffer. This sounds a bit like a stack, but it looks like it might be a sorted list of sprite numbers.

The code tracks the number of sprites in use in a separate integer variable.

The error you're seeing can be generated if:
- the number of sprites in use doesn't match the number of sprites in the LIFO buffer
OR
- the number of sprites in use doesn't match the total number of sprites in use across all layers (which I think is derived by going through each layer and counting the sprites in use, just for this test).

I suspect none of that is a great deal of help.

I don't think your error would be caused specifically by ON ERROR SKIP, but it is possible you're hiding some issue that's allowing the sprite system to get in a bad state.

Your idea of it being related to the interrupt holds some merit.

One thing you could try to do is not do any other sprite work inside of the interrupt itself, but instead set a flag or keep a list of work you should do in your frame loop based on the interrupt. This could get you around any issue that might be caused by some sort of nested interrupt scenario.

OR... set up a global variable in your sprite interrupt handler to catch when there's a nested interrupt (i.e. increment a variable when entering the interrupt handler, decrement it on exit, call ERROR or somehow log if you see that counter > 1 (put something on the screen you can see) to see if it's related to the internal error event.
Edited 2021-02-14 17:03 by Nelno
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10590
Posted: 08:43am 14 Feb 2021
Copy link to clipboard 
Print this post

The SPRITE INTERNAL ERROR was included precisely to find any problems that could cause the sprite data structures to get out of line. Up to now no-one had managed to trigger it. yock1960 is doing something that the firmware isn't handling properly, but to solve it I need a simple example program that can reliably trigger the problem otherwise I'm searching for a needle in a haystack
Edited 2021-02-14 18:48 by matherp
 
yock1960
Senior Member

Joined: 18/08/2020
Location: United States
Posts: 167
Posted: 07:31pm 14 Feb 2021
Copy link to clipboard 
Print this post

  matherp said  The SPRITE INTERNAL ERROR was included precisely to find any problems that could cause the sprite data structures to get out of line. Up to now no-one had managed to trigger it. yock1960 is doing something that the firmware isn't handling properly, but to solve it I need a simple example program that can reliably trigger the problem otherwise I'm searching for a needle in a haystack


Here you go Peter. This program is using on the fly sprite definition...well, it would if the program got that far, but it fails on the 1st collision.

I have moved away from on the fly sprite re-definition, since I discovered that sprite mirroring works fine...some other error when I tried it apparently...and now the internal error happens less frequently, but still happens, especially when I have tried to add a duplicate, but independent sprite....same sprite definitions, different sprite numbers (not a copy) and using array variables for tracking location/status.

I'm still on 5.07.00b9.

Steve


sprite_test.zip
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10590
Posted: 07:34pm 14 Feb 2021
Copy link to clipboard 
Print this post

Need the png file - thanks
 
yock1960
Senior Member

Joined: 18/08/2020
Location: United States
Posts: 167
Posted: 07:39pm 14 Feb 2021
Copy link to clipboard 
Print this post

  matherp said  Need the png file - thanks


DOH!  


qbert_creatures.zip
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10590
Posted: 07:47pm 14 Feb 2021
Copy link to clipboard 
Print this post

I'm getting immediately on running

Error in line 330: Buffer not in use

Two things though - NEVER EVER EVER use PAUSE in an interrupt routine. You don't need to disable and re-enable interrupts in the interrupt routine
Edited 2021-02-15 05:50 by matherp
 
yock1960
Senior Member

Joined: 18/08/2020
Location: United States
Posts: 167
Posted: 07:55pm 14 Feb 2021
Copy link to clipboard 
Print this post

  matherp said  I'm getting immediately on running

Error in line 330: Buffer not in use

Two things though - NEVER EVER EVER use PAUSE in an interrupt routine. You don't need to disable and re-enable interrupts in the interrupt routine


Yes, I put that in there for the demo, disabling or not disabling and removing the pause makes no difference to the internal error. I think I put the disable/enable in after I started seeing the problem. Not sure why you're getting the buffer not in use error....obviously, I don't.

Steve
 
yock1960
Senior Member

Joined: 18/08/2020
Location: United States
Posts: 167
Posted: 08:06pm 14 Feb 2021
Copy link to clipboard 
Print this post

So, with setting the sprite interrupt up before any sprites are shown and the sprite nointerrupt statement commented out, no buffer error is seen, but if you then comment out the 'sprite interrupt collision' statement inside the collision sub, the buffer not in use error occurs.

It looks like setting up the sprite interrupt routine calls it....seems like it shouldn't be called until there is a collision.
Edited 2021-02-15 06:09 by yock1960
 
yock1960
Senior Member

Joined: 18/08/2020
Location: United States
Posts: 167
Posted: 01:26am 15 Feb 2021
Copy link to clipboard 
Print this post

I fibbed. I did have the pause in the regular program sprite interrupt routine. I had to think a bit, but am now in the process of re-doing this to get rid of it. It impacts the immediacy of the collision result....at least the way I'm doing it, but in the end, it doesn't really affect game play. Perhaps this will eliminate the internal errors that I still was sometimes seeing.

Steve
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10590
Posted: 10:02am 15 Feb 2021
Copy link to clipboard 
Print this post

Found the problem

You are trying to "hide safe" a sprite that is already hidden and the firmware isn't giving an error. Try b16 and you should get the error "Not Showing" then it is up to you to fix your code

General point: you don't have to use the sprite interrupt have a look at the brownian motion demo on the welcome tape. If you do use the interrupt my recommendation is that is is used to deal with the cause of the interrupt in its entirety. Have a look at the attached.

Option explicit
Option default none
option y_axis up
Option console serial
Const stepdef=4
Dim integer i, x=1, y=160, stepsize=stepdef, last_one_gone, update
Dim float current_angle=90
Dim integer showing(64)
Mode 2,16,0,frameint
Pause 3000
Page write 1
CLS

Box 401,1,18,48,2,RGB(green),RGB(Magenta)
Box 421,1,18,48,2,RGB(red),RGB(cyan)
Box 441,1,18,48,2,RGB(yellow),RGB(blue)
Box 461,1,18,48,2,RGB(white),RGB(red)
Box 481,1,18,48,2,RGB(Magenta),RGB(GREEN)
Play modfile "cartoon"
'for i=0 to 7
SPRITE read 10+i,401,1,18,48
SPRITE read 18+i,421,1,18,48
SPRITE read 26+i,441,1,18,48
SPRITE read 34+i,461,1,18,48
SPRITE read 42+i,481,1,18,48
SPRITE copy 10,11,7
SPRITE copy 18,19,7
SPRITE copy 26,27,7
SPRITE copy 34,35,7
SPRITE copy 42,43,7

Load bmp "court"
'CLS
For i=0 To 7
SPRITE show 10+i,401,i*50,1
showing(10+i)=1
SPRITE show 18+i,421,i*50,1
showing(18+i)=1
SPRITE show 26+i,441,i*50,1
showing(26+i)=1
SPRITE show 34+i,461,i*50,1
showing(34+i)=1
SPRITE show 42+i,481,i*50,1
showing(42+i)=1

Next i
SPRITE loadpng 1,"ball"
vector 0,current_angle,0,x,y
SPRITE show 1,x,y,1
update=1
page copy 1 to 0
Do
Loop Until update=0
SPRITE INTERRUPT  collision
Do
 vector 0,current_angle,stepsize,x,y
 SPRITE show 1,x,y,1
 update=1
 Do
 Loop Until update=0
Loop Until last_one_gone
Pause 2000
Play stop
SPRITE close all
Mode 2,8 'disable the interrupt'
Option console both
End

Sub frameint
 If update Then Page copy 1 To 0
 update =0
End Sub

Sub vector(obj As integer, angle As float, distance As float, x_new As integer, y_new As integer)
 Static float y_move(9), x_move(9)
 Static float x_last(9), y_last(9)
 Static float last_angle(9)
 If distance=0 Then
   x_last(obj)=x_new
   y_last(obj)=y_new
 EndIf
 If angle<>last_angle(obj) Then
   y_move(obj)=-Cos(Rad(angle))
   x_move(obj)=Sin(Rad(angle))
   last_angle(obj)=angle
 EndIf
 x_last(obj) = x_last(obj) + distance * x_move(obj)
 y_last(obj) = y_last(obj) + distance * y_move(obj)
 x_new=Cint(x_last(obj))
 y_new=Cint(y_last(obj))
Return


Sub collision
 Local integer i
' First use the SPRITE(S) function to see what caused the interrupt
 If sprite(S) <> 0 Then 'collision of specific individual sprite
   'sprite(S) returns the sprite that moved to cause the collision
'print "Collision on sprite ",sprite(S)
    process_collision(sprite(S))
'     print ""
'
 Else '0 means collision of one or more sprites caused by background move
   ' SPRITE(C, 0) will tell us how many sprites had a collision
'    print "Scroll caused a total of ",sprite(C,0)," sprites to have collisions"
   For i=1 To sprite(C,0)
' SPRITE(C, 0, i) will tell us the sprite number of the Ith sprite
'      print "Sprite ",sprite(C,0,i)
     process_collision(sprite(C,0,i))
   Next i
'    print ""
 EndIf
End Sub
' get details of the specific collisions for a given sprite
Sub process_collision(S As integer)
 Local integer i ,j, k, m
 'sprite(C, #n) returns the number of current collisions for sprite n
'print "Total of ",sprite(C,S)," collisions"
'print SPRITE(C, S, 1)' will tell us the sprite number of the Ith sprite
   For i=1 To sprite(C,S)
   If k Then Exit For
   j=sprite(C,S,i)
   If j=&HF1 Then
     'collision with left of screen
     current_angle=360-current_angle+(Rnd-0.5)*20
     Do While (current_angle>=180 And current_angle<=359) Or current_angle=0
       current_angle=current_angle+(Rnd-0.5)*20
     Loop
   Else If j=&HF2 Then
     'collision with top of screen
       current_angle=((540-current_angle) Mod 360) +(Rnd-0.5)*20
     Do While current_angle<=90 Or current_angle>=270
       current_angle=current_angle+(Rnd-0.5)*20
     Loop
   Else If j=&HF4 Then
     'collision with right of screen
     current_angle=360-current_angle+(Rnd-0.5)*20
     Do While current_angle>=0 And current_angle<=180
       current_angle=current_angle+(Rnd-0.5)*20
     Loop
   Else If j=&HF8 Then
     'collision with bottom of screen
     current_angle=((540-current_angle) Mod 360) +(Rnd-0.5)*20
     Do While current_angle>=90 And current_angle<=270
       current_angle=current_angle+(Rnd-0.5)*20
     Loop
   Else If j=&HF3 Or j= &Hf6 Or j=&Hf9 Or j=&HfC Then
     current_angle = current_angle+180
   Else
     current_angle=360-current_angle+(Rnd-0.5)*20
     If s=1 Then
       vector 0,current_angle,stepsize,x,y
'        SPRITE hide 1
       SPRITE hide safe j:showing(j)=0

'        SPRITE show 1,x,y,1
       Play effect "gunshot"
       m=0
       For k=10 To 49
         If showing(k) Then m=m+1
       Next k
       If m=0 Then
         last_one_gone=1
       EndIf
       Page copy 1 To 0
     EndIf
   EndIf
 Next i
End Sub

Edited 2021-02-15 20:37 by matherp
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025