|
Forum Index : Microcontroller and PC projects : Micromite eXtreme: Sprite magic
| Author | Message | ||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
Check the video Here is the very simple code option explicit option default none cls load image "tiger640" sprite load 1,"apple" sprite load 2,"apple" dim float x1,y1,x2, y2, i box 8,98,304,304,2 box 328,98,304,304,2 sprite show 1,200,200,1 sprite show 2,450,200,1 do for i=0 to PI*2-pi/50 step PI/50 x1=sin(i)*100+160-sprite(w,2)\2 y1=cos(i)*100+250-sprite(h,2)\2 x2=sin(i)*100+480-sprite(w,2)\2 y2=-cos(i)*100+250-sprite(h,2)\2 sprite next 1,x1,y1 sprite next 2,x2,y2 sprite scrollr 10,100,300,300,1,1 sprite scrollr 330,100,300,300,-1,-1 next i loop I need to do some tidying and documenting before I release the firmware but hopefully this meets the needs of the "scrolling region" advocates. The firmware also now includes the ability to scroll an area or the complete screen without "wrapping" the picture and allows the user to specify what colour should fill the vacated area. The SCROLL NEXT command is new and specifies where the sprite will move to when the next scroll command occurs. This makes the scroll and move a single atomic action so as seen in the video there are absolutely no tearing effects |
||||
| robert.rozee Guru Joined: 31/12/2012 Location: New ZealandPosts: 2463 |
peter, this looks really impressive is there any chance you could post the syntax of the SPRITE, BLIT, and other related functions? just the extract from the manual would suffice. is it possible that SPRITE may end up rendering BLIT redundant, or that the functionality of both could be rolled into the one function? i notice you have load image... and sprite load.... could the syntax perhaps be tweaked to instead use LOAD sprite...? also, i assume you are still using double buffering? could the need for this be avoided by having graphics commands queued (internally) and only executed during the VBI? just an idea i had floating round in the back of my mind. cheers, rob :-) |
||||
| Azure Guru Joined: 09/11/2017 Location: AustraliaPosts: 446 |
That would mean the syntax for the other "sprite <subcommand> <parameters>" would be inconsistent. |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
Slowly working though the bugs. Another demo this time showing collision detection. Note how the centre of the screen flashes with a block coloured to indicate which sprites collided. To get the performance all the manipulations of graphics data have been converted from bit-based to word-based. This has much more convoluted logic for things like handling the sprites when partially off the screen when each colour in the sprite can appear anywhere across a number of words in memory. I've enabled both SPRITE and BLIT are synonyms with identical functionality. Some commands make more sense as a BLIT (e.g. scrolling" ) and some as a SPRITE (e.g. "showing") I'm still tweaking syntax as I work more with the code so don't want to release anything yet. Code for this demo option explicit option default none cls load image "tiger640" load sprite 1,"apple" load sprite 2,"apple" load sprite 3,"apple" load sprite 4,"apple" dim float x1,y1,x2, y2, i, crash=0 box 8,98,304,304,2 box 328,98,304,304,2 sprite show 3,170,200,1 sprite show 1,200,200,2 sprite show 2,450,200,1 sprite show 4,400,200,2 blit read 5, 310,240,20,30 do for i=0 to PI*2-pi/50 step PI/50 x1=sin(i)*230+220-sprite(w,2)\2 y1=cos(i)*230+250-sprite(h,2)\2 x2=sin(i)*230+420-sprite(w,2)\2 y2=-cos(i)*230+250-sprite(h,2)\2 sprite next 1,x1,y1 sprite next 2,x2,y2 ' sprite move sprite scrollr 10,100,300,300,2,2 if sprite(s)<>-1 and crash=0 then if sprite(c,0,1)=1 then box 311,241,18,18,,rgb(red),rgb(red) if sprite(c,0,1)=2 then box 311,241,18,18,,rgb(blue),rgb(blue) timer=0 crash=1 endif if sprite(s) = -1 and crash = 1 and timer > 500 then blit write 5,310,240 crash=0 endif sprite scrollr 330,100,300,300,-2,-2 next i loop Background and sprite 2018-02-05_005226_apple.zip |
||||
| IanT Senior Member Joined: 29/11/2016 Location: United KingdomPosts: 115 |
Do you ever sleep Peter? Regards, IanT |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
The scrolling region capability also works nicely on the SSD1963 to create a real time chart Watch another boring video here Again the new functionality makes the code very simple and I hope I'm getting to the end of the bugs - found another bizarre one this morning - right hand end of a sprite not displaying when left hand x coordinate satisfies x= 16+ n*32 const scrollxstart=100, scrollxwidth=280,newpoint=scrollxstart+scrollxwidth-2 const scrollystart=20,scrollyheight=232, scrolldirection=0 dim integer i, j, rp=130, bp=100, yp=160, wp=190, cp=70, xp=40, zp=220 cls text scrollxstart+scrollxwidth\2,0,"Micromite eXtreme V5.4.13 with SSD1963",C,1,,rgb(white),rgb(black) text newpoint+16,scrollystart-13+(scrollyheight\2),"Fixed",,2,,rgb(green),rgb(black) text newpoint+16,scrollystart+13+(scrollyheight\2),"Area",,2,,rgb(green),rgb(black) text 10,scrollystart-13+(scrollyheight\2),"Fixed",,2,,rgb(green),rgb(black) text 10,scrollystart+13+(scrollyheight\2),"Area",,2,,rgb(green),rgb(black) text scrollxstart+scrollxwidth\2,scrollystart+scrollyheight+5,"Demonstration of scrolling data",C,1,,rgb(white),rgb(black) BOX scrollxstart-1,scrollystart-1,scrollxwidth+2, scrollyheight+2,1,rgb(white),rgb(gray) do ' scroll an area defined by the x-y coordinates of the top left point ' the width of the area to be scrolled ' the height of the are to be scrolled ' the scroll driection ' define the colour of the scroll background rp=nextpos(rp)'get the new data points bp=nextpos(bp) yp=nextpos(yp) xp=nextpos(xp) zp=nextpos(zp) wp=nextpos(wp) cp=nextpos(cp) box newpoint,xp,2,2,1,rgb(yellow) 'write them to the space left box newpoint,rp,2,2,1,rgb(blue) box newpoint,yp,2,2,1,rgb(red)) box newpoint,bp,2,2,1,rgb(green) box newpoint,wp,2,2,1,rgb(magenta) box newpoint,cp,2,2,1,rgb(cyan) box newpoint,zp,2,2,1,rgb(white)) blit scrollr scrollxstart,scrollystart,scrollxwidth,scrollyheight,-2,0,rgb(gray) loop ' function nextpos(d as integer) as integer nextpos=d+(rnd()*4)-2 if nextpos<=scrollystart then nextpos=scrollystart+1 if nextpos>=scrollystart+scrollyheight then nextpos=scrollystart+scrollyheight-1 end function Here is the current SPRITE/BLIT syntax |
||||
| Azure Guru Joined: 09/11/2017 Location: AustraliaPosts: 446 |
Fantastic work Peter. A couple of questions, clarifications and suggestions. 1. I might be reading the commands incorrectly but it seems like sprites cannot be placed partially off wholly off screen in the minimum X and Y side but can be on the maximum X and Y directions (where they will be clipped). Is that correct? 2. For the following commands the horizontal move range is less than the vertical move range for these commands: SPRITE SCROLLH n {,col} Scrolls the background and any sprites on layer 0 n pixels to the right. n can be any number between -31 and 31... SPRITE SCROLLV n {,col} Scrolls the background, and any sprites on layer 0, n pixels up. n can be any number between -MM.VRES-1 and MM.VRES-1... 3. Following description may contain a typo: SPRITE(N,n) I think it should be:Returns the number of displayed (active) sprites on layer l SPRITE(N,n) Returns the number of displayed (active) sprites on layer N 4. I think I have missed something but for collision detection do sprites on all layers collide with the background (layer 0)? So you can't have the background scrolling passively without it causing collisions (eg planes flying high over a city not detecting background collisions)? 5. Is there any way to add flags to the sprites like: SPRITE FLIP {#}n XF YF Where n is the sprite number and XY and YF are flag to cause the sprite to be drawn mirrored in the horizontal and/or vertical directions (default 0,0). This is great to allow a sprite to change direction (and invert its image) as it encounters something or when the screen is inverted (2nd player). Another option that could achieve a similar result and not impact other logic might be a command to invert a sprite #n image in the X or Y direction. Great work, still trying tp process it all. |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
No they can be placed anywhere as long as they overlap the screen to some extent Yes, because of the way the bitshift works Should be: Returns the number of displayed (active) sprites on layer "n" The background image scrolls without any collisions. Sprites on layer 0 will collide but that can be ignored in the program Certainly do-able if worth the effort |
||||
MicroBlocks![]() Guru Joined: 12/05/2012 Location: ThailandPosts: 2209 |
I always wonder what the phrase "if worth the effort" means? Isn't that a very personal thing? Here is my opinion. To save resource it is very helpful to be able to flip, rotate an image or sprite. This enables a lot of reuse of resources saving precious memory. Even in high end 3D game engines, reusing the same resource is very efficient. Rating, scaling etc the object is used very often to build landscapes. On 2D it can be used to build backgrounds,several characters with common parts etc. Microblocks. Build with logic. |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
Another demo Watch it here I've implemented sprite mirroring as a new parameter on the sprite show command SPRITE SHOW {#}n, x, layer {,orientation} Displays sprite n on the screen with the top left at coordinates x, y. Sprites will only collide with other sprites on the same layer, layer zero, or with the screen edge. If a sprite is already displayed on the screen then the SPRITE SHOW command acts to move the sprite to the new location. The display background is stored as part of the command such that it can be replaced when the sprite is hidden or moved further. The orientation is an optional parameter, valid values are: 0 - normal display (default if omitted) 1 - mirrored left to right 2 - mirrored top to bottom 3 - rotated 180 degrees (= 1+2) I've also implemented SPRITE CLOSE ALL This closes all sprites and frees up all used memory. It does not change the screen. If I can get away without any more requirements I should be able to release the firmware soon as it is now starting to become pretty stable Basic program for the above demo demonstrates the new functionality + collision detection interrupt handling. Note how the collision interrupt has to do something to clear the "collision" - in this case a scroll in the opposite direction. Otherwise the interrupt will re-occur when the second unrelated scroll is actioned. option explicit option default none const leftbar = 1, rightbar = 2, topbar=3, bottombar=4, rightapple=5, leftapple=6 dim integer moveright=1, movedown=1 box 250,100,10,280,,rgb(magenta),rgb(magenta) box 50,50,150,10,,rgb(cyan),rgb(cyan) blit read leftbar,250,100,10,280 sprite copy leftbar, rightbar, 1 'make one copy blit read topbar,50,50,150,10 sprite copy topbar, bottombar, 1 'make one copy load sprite rightapple,"apple" sprite copy rightapple,leftapple,1 'make one copy load image "tiger640" sprite interrupt collision blit show rightapple,300,200,0 blit show leftapple,100,200,0,2 blit show leftbar,250,100,1 blit show rightbar,580,100,1 blit SHOW topbar,50,50,2 blit SHOW bottombar,50,420,2 do if moveright then sprite scrollr 259,100,322,280,2,0 else sprite scrollr 259,100,322,280,-2,0 endif if movedown then sprite scrollr 50,59,150,362,0,-2 else sprite scrollr 50,59,150,362,0,2 endif loop ' ' sub collision local integer i, c(10), j if sprite(S) = 0 then 'collisions caused by scroll j=sprite(c,0) for i=1 to j 'store the collisions because a clearing scroll move will clear them from the list c(i)=sprite(C,0,i) next i for i=1 to j 'now process them process_collision(c(j)) next i endif end sub ' get details of the specific collisions for a given sprite sub process_collision(S as integer) select case S case leftbar sprite scrollr 259,100,322,280,2,0 'make a move to clear the collision sprite show rightapple,sprite(x,rightapple),sprite(y,rightapple),0,0 'normal orientation moveright=1 case rightbar sprite scrollr 259,100,322,280,-2,0 'make a move to clear the collision sprite show rightapple,sprite(x,rightapple),sprite(y,rightapple),0,1 'mirror the sprite moveright=0 case topbar sprite scrollr 50,59,150,362,0,-2 'make a move to clear the collision sprite show leftapple,sprite(x,leftapple),sprite(y,leftapple),0,3 'rotate the sprite 180 degrees movedown=1 case bottombar sprite scrollr 50,59,150,362,0,2 'make a move to clear the collision sprite show leftapple,sprite(x,leftapple),sprite(y,leftapple),0,0 'normal orientation movedown=0 case else end select end sub |
||||
| Azure Guru Joined: 09/11/2017 Location: AustraliaPosts: 446 |
Peter, Wonderful work. You have done an amazing job putting together a software platform for doing sprite and graphics animation. Apologies for asking basic questions, but I do not have access to an MMX at the moment so can't play to answer these questions myself. I am sure I am missing something but I do not see how you can place a sprite off the left and/or top of the screen (before the min X,Y values) and slowly make it appear on screen. I hope that makes sense. The only other feature that comes to mind is sprite wrapping. Can you clarify that there is no wrapping of the sprite at the screen edge it just gets clipped at the screen boundaries. So to wrap a sprite you would create a second sprite that is as much on screen as the one that is off screen (during the wrapping). Please ignore if I am asking stupid questions, just trying to get a good understanding of how this will work based on my previous work in the arcade game industry and high end graphics work on computers. Again great work, can't wait to get onto a MMX and have a play. |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10569 |
You can place a sprite anywhere as long as some part of it overlaps the screen so SPRITE SHOW #1, -SPRITE(W, #1)+1, 100,1 will place the sprite with just one column of pixels showing at the left of the screen. NB, if the rightmost column of the sprite contains the background colour then you won't see it at all SPRITE HIDE #1 has, of course, no pixels showing I've played with several variants of this and am still not convinced what is best. At the moment the spite will disappear off the edge of the screen until it is half gone, at that point it will appear half on at the other side of the screen. Better ideas on this appreciated but too much flexibility risks making the syntax even more complicated |
||||
| Azure Guru Joined: 09/11/2017 Location: AustraliaPosts: 446 |
My first though is if it is too difficult (given the number of sprites supported), have no wrapping. Any needed wrapping should be able to be easily handled in the application. That said my suggestion (if it is possible) would be that each sprite has a flag (like orientation) that specifies if it wraps or not. This can always be added later if it is wanted but too much work now. If wrapping is supported it should wrap so that it wraps in only the X or Y like the orientation option, but without the option for both X and Y. |
||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |