Sprite Plotting in Window
Bill Antonia (2466) 124 posts |
I’m having difficulty in plotting a sprite in a window, I’ve done this before a long time ago and the C code is currently sitting on my mothballed RiscPC’s hard drive. My question is, is there any source where there is sample C code I can download and examine? I’m currently writing a DDE C++ application using a library I’ve also been writing using the DDE C++ compiler. Basically, what I need to find is which fields do I need to use in the toolbox h.Wimp WimpRedrawBlock structure and the equations to work out the x,y values to plot the sprite? I have an application working with a window but the sprite is being plotted erratically within it. I’ve looked and tried to follow the PRM’s, I have the originals, but have not had any breakthroughs. Thanks in advance |
Gavin Cawley (8462) 70 posts |
I’ve a (very) simple implementation of the game !centipede in C that runs in a desktop window, which you can find here: https://github.com/usr-bin-gcc/Centibug It doesn’t use toolbox though, just basic riscos_lib. |
Bill Antonia (2466) 124 posts |
Thanks, I see from line 785 in main is the code I’m probably looking for. The inital settings of r.box, are they mode dependent? I’m using the toolbox for the window but the wimp library is included in the toolbox as well, so all ok. |
Rick Murray (539) 13747 posts |
I’m sitting in the car right now (not driving!) so just a few thoughts. Your sprite origin has to be worked out by determining where the window is relative to the screen. The x min y min stuff will tell you that. A gotcha is that usually the window Y dimension is negative, and sort of goes backwards to what you might expect. I think in the Wimp, the position 0,0 is the top left of the screen, whereas for the VDU system (and sprite plotting) it’s the bottom left. So you’ll need to adjust for this. When you have worked out the pixel position of where the sprite needs to be placed, you’ll then need to fudge the plot location by the eigen values (turning pixels into OS coords). If it’s appearing too far to the left/bottom, try pasting in Oh, and if the colours are coming out weird, look at That’s all that comes to mind right now, I hope it’s useful in some small way. |
Stuart Swales (8827) 1323 posts |
Unless you’re looking for ultimate performance, let the Wimp do the mode-independent work for you: SWI Wimp_PlotIcon |
Rick Murray (539) 13747 posts |
Put it into an icon and plot it on demand during redraw? Oh, that’s devious! |
Steve Fryatt (216) 2095 posts |
Curiously, I wrote some code to do that the other day… It’s not the toolbox (it’s OSLib), but you should be able to convert the fields fairly easily. Here’s the redraw loop: and the calls into the and here: I’ll now wait for people to review it and tell me what I’ve done wrong. |
Steve Fryatt (216) 2095 posts |
No, they’re work area coordinates. They will depend on the size of your sprite when plotted in the window, but should not vary by mode unless you’re changing the size of the plotted area by mode (which I don’t think you should be doing, in most cases at least). |
Steve Fryatt (216) 2095 posts |
While we’re here… one thing that I’m not 100% sure about. I’ve been assuming – since there doesn’t appear to be much in the API to allow the user to do it directly – that the OS will clip the sprite redraw down to fit in the clip window that the Wimp has set for redraw? Otherwise that redraw code is probably very inefficient. :-) |
Rick Murray (539) 13747 posts |
I think the Wimp just sets an OS clipping rectangle. It’s a shame there was never a SWI to plot a part of a sprite… |
Steve Fryatt (216) 2095 posts |
But surely1 OS_SpriteOp isn’t daft enough to expend time on the areas outside the clipping rectangle, is it? So it will respect the Wimp’s clip area, and not waste time plotting outside of the redraw area? I suppose I could just look at the code, but it’s probably impenetrable assembler with numeric labels and few, cryptic comments.
Indeed. It was the lack of one that started this train of thought the other week as I wrote the code linked in above. 1 I’d like to assume it couldn’t be, but the PRMs don’t seem to say that it isn’t. |
Stuart Swales (8827) 1323 posts |
OS_SpriteOp certainly used to efficiently reject sprite rows above and below the OS clip area, working out the offsets to the start and end data once per plot, applying those to each row.
Indeed, but for other reasons. |
Steve Fryatt (216) 2095 posts |
That’s great – thanks for confirming that it does!
Although it can be achieved with a clip rectangle, presumably, so it’s “just” a nice API that’s missing. |
Bill Antonia (2466) 124 posts |
redrawWindowRequest() is an overloaded member function, WimpRedrawWindowBlock is the standard structure for a redraw, getPollBlock() does what it says, again a member function of the tasks object. I know the following lines are incorrect as I get the problems I’m having: The bits which are wrong I think are The PRM’s show:
What is it I have to replace those two lines with? |
Steve Fryatt (216) 2095 posts |
I think you have the wrong direction. The lines that you show are for converting from a screen coordinate (eg. a mouse click) to a work area coordinate. You need to go the other way: from the work area to the screen. In the example that I linked above, the lines are
which I think in your library is
Your window is not moving around during redraw, so the screen origin for its work area will not vary depending on the bits being redrawn. Your sprite’s corner will always be at the same place on the screen, but (as discussed in my tangent above) the bit being redrawn will shift around. That “shifting around” is handled by the OS only plotting the bit of the sprite that falls within the clip window set by the Wimp on that iteration of the redraw loop. On a separate note, should that final line be a call to For comparison, here’s the code that I linked in above (with the irrelevant stuff removed):
Note that I’m calculating X and Y once, before entering the loop, as they don’t change once the redraw has started – they can’t, unless the window moves or scrolls. And the window can’t move or scroll while you’re redrawing it. Edit For clarity, if you do the conventional "origin at the top left of the window’s work area, with Y coordinates negative, the Y origin is at the top left of the window when you calculate it. So you have to subtract the window height in OS Units, as OS_SpriteOp is expecting the coordinates of the bottom left corner. ( |
Bill Antonia (2466) 124 posts |
Thank you, I’ll investigate further tomorrow. I see what you mean about x & y not changing. |
Bill Antonia (2466) 124 posts |
Just tried the following outside the loop |
Bill Antonia (2466) 124 posts |
Found the following worked, 1440 is twice the value of the current display mode for the Y direction at 720, so each pixel is 2×2 units. |
Rick Murray (539) 13747 posts |
Like I said, eigen. Get the screen X and Y. Then Try Here’s the SWI: Here are the numbers of interesting things: |
Stuart Swales (8827) 1323 posts |
SWI OS_ReadVduVariables is your friend. See YWindLimit and YEigFactor in https://www.riscosopen.org/wiki/documentation/show/Mode%20Variable%20Numbers |
Steve Fryatt (216) 2095 posts |
Get the screen X and Y. If we’re talking about the sprite dimensions here, then is this necessary? First, the dimensions will be the dimensions of the sprite, and not the screen, so there’s no need to read those back. You just need to know (or look up using OS_SpriteOp and/or poking in the sprite definition) the size of the sprite. Then, depending on where the sprite comes from, the mode may be already defined and so the eigenvalues will also already be known. For example, in Puzzles (the code I’ve quoted above), I know that the sprite will be Mode 21 (because that’s what I will be creating it as), so I know that there are two OS units per pixel in each direction. But if the sprite mode isn’t known, then you do need to pass its mode to OS_ReadVduVariables and read the units-per-pixel back. Edit Oh, Textile. |
Bill Antonia (2466) 124 posts |
All sorted earlier, I used OS_ReadModeVariable, to work out the information I needed, and OS_SpriteOp to get the size and mode of the sprite. |
Rick Murray (539) 13747 posts |
Generally you don’t need to worry about the sprite plotting as the OS knows its modes and colour depths so can tell how big the sprite is. But you do have to jump through all of these hoops if you want to draw it in the right place on the screen, especially given as all of the placements are OS units rather than pixels. |