Jump to content
Andrew Davie

Wen hop? The Search for Planet X

Recommended Posts

Here's a new binary (Stella only, for now) with zooming/scanline, and a bunch of planets.

Use hold-SELECT to switch to next planet.  LEFT/RIGHT to change rotation speed.  UP/DOWN to zoom in and out.

 

 

So, how is it done?

 

Well firstly, it uses the engine that I'd previously shown - that one for drawing the Wen Hop game screen with all the flashy character animations and scrolling. It's exactly the same to start with - a "level" is unpacked to a screen buffer which is just a bunch of character #s used to define that screen. Whereas the wenhop playfield was 40 x 24 characters, with a scrolling 10 x 8 (ish) window viewport onto that, for the planets we have a 40 x 12 character area with a scrolling 10 x 12 (invisible) window onto that.  I copy the leftmost 10 character columns to column 30 onwards, so I get a "wrap-around" in terms of when I'm scrolling into that 40 x 12 area.

 

So now I have the planet texture unpacked into that 40x12 area ("the board") it behaves exactly as for WenHop itself.  That is, all the objects on the board animate and are processed, participate in collisions etc.  This is why you see dogecoin on some of the planets as they rotate, and the dogecoin are animating. It's just the original system in action.

 

So the "texture" is the same as the original WenHop screen that you play on, in technical terms. But in this case, it's hidden and just used as source data. So, based on the X scroll, I first "draw" the texture as a 10x12 window into that 40x12 "board" representing the planet surface. It's a rectangular, flat, scrolling window.

 

The next part is wrapping that texture onto the surface of a sphere. So, for this I wrote a small python utiltiy to generate some mathematically correct data.  All it is really doing is rendering a selected subsection of the rectangular texture map and showing it on the screen. That sounds difficult, but the technique is quite straightforward.

 

Let's cover verticals, first.  If you think about a sphere, and as you step down each scanline in a sphere, then the textured surface wraps around - of course. But the mapping of the scanline position to the texture pixel is actually quite straightforward. On a line-by-line basis, we know that ALL pixels on the line come from the same horizontal line in the texture map. So the real task here is just to find which horizontal line of the texture we're looking at, for each scanline. It comes down to some simple trigonometry; based on the curve of a sphere we can use pythagoras and trig to figure out the distance down from the top of the texture. That's done for each scanline, and so we effectively now ONLY display those texture lines which each scanline points to. And with that, we how have a horizontal cylinder onscreen.

 

Now it gets tricky. But not too much more so. The screen is drawn in two halves (left/right).  Each half is effectively a mirror in terms of the calculations, but with just a different texture offset (mirrored). So we'll look at only the right-side.  Now the earlier scrolling code took the rendered window-into-the-board to create the correct PF0 PF1 PF2 bytes.  In the planet code this is done slightly differently.  Rather than unpacking the potential 6 characters (catering for scroll) that we might see in this half, and copying 20 of those 24 pixels (with scroll 0..3 dropping off some) directly to the PF bytes (taking account of the weird PF format)... instead we only copy SOME of those 20 pixels. Consider the texture itself being a whole screen wide (i.e., 40 pixels for the sphere). We want to wrap this rendered 40 pixels onto the sphere itself, which varies in width from maybe 0 up to 30 or so pixels.  In other words, SOME of those pixels need to be used, and some discarded.

 

So, for each scanline I first calculate the width (in screen pixels) of that half of the scanline from the center. I know that I need to map those 20 pixels of the texture into that many pixels in the final screen display, and I'll have wrapped the texture around the sphere - for that line.  Trigonometry comes to the rescue again, and if you consider a single scanline half, but instead of looking head-on, we look top-down at it. We see half a hemisphere, i.e., a 90 degree sweep across the sphere. And we know that the 20 pixels of the texture map evenly onto the curved outer edge of that half-hemisphere.  So if for each pixel onscreen we know where it intersects that curved outer edge, we get a distance (horizontally) into the texture/surface map. We already know the line, from the vertical calcs, so now we are just getting the correct pixel in that line.

 

So, the python program aforementioned also creates a table for each scanline which is effectively a mask. It starts from the center, and specifies on/off for 20 bits horizontally. If a bit is ON, then we add a pixel from the texture. If OFF, then we skip that pixel.  And so, we get an effective gradated selection of pixels being dense towards center-screen, and sparser as it gets to the edge.

 

Put these two together - first the wrapping to a horizontal cylinder as described, and then on each line of that cylinder wrapping around a vertical cylinder (effectively) we get the combined effect of the both of them together forming a sphere. So, horizontal cylinder x vertical cylinder = sphere, I guess :). Anyway, that's how I did it. The actual calculations on the ARM are simple enough that i can scroll/animate/render the entire planet every single frame.

 

The rotation is achieved simply by scrolling over the original board, and letting the draw system draw from a window into the (wrapped) board as described earlier. When the scroll position becomes < 0 then I just flip it to the right edge (30). When it goes past the right edge, I flip it to the left edge (0).  It's seamless because earlier I'd copied the left 10 character columns to the right side.

 

To add to the explanation above, the scaling is achieved by first doing all of the above, but then after we've wrapped the texture onto each scanline half we post-process those 20 pixels with a simple linear scale.  Step through the pixels not one-by one, but by a scale factor and generate a new 20 pixels to use instead.  Similarly for the scanline->texture masking. So the joystick now controls a simple scale/multiplier and thus you get your zooming.

 

The principle here, in the whole engine basically, is to build layer upon layer of capability and use those to abstract away the hardware and difficult things by writing engines/systems, and then work at a higher level which is simpler and more capable.

 

 

WENHOP20210811b.bin

  • Like 8

Share this post


Link to post
Share on other sites
On 8/5/2021 at 5:56 PM, Andrew Davie said:

It uses the CDFJ bankswitch scheme that is supported already by emulators such as Stella and Gopher2600.  Gopher2600 is the more accurate in terms of timing, and perhaps in terms of hardware emulation too.  But they are both excellent and suitable for playing/testing CDFJ games. 

As a third choice, 6502.ts works fine, too (it does not emulate ARM cycles, though)

Share this post


Link to post
Share on other sites

I've made a start at tying the player sprite to the background. This is rudimentary stuff right now - in fact all it's doing is checking the character the player is over, and then 1) moving down if it's blank, otherwise moving up.  That's it. In the video all I am doing is moving left or right, and we see very rudimentary falling, and positioning upwards when "in something".  It's doing OK for such a simple start. The scroll is locking nicely to the player position, too. Bonus crash at the end!

 

 

  • Like 4

Share this post


Link to post
Share on other sites
4 hours ago, Bomberman94 said:

Any plans for a demo for „the real machine“ - maybe a PAL60 version, too? 🤗

Yes, sometime soon. The planet spinner works on the real thing now. I want to get some gameplay going before releasing a demo for that. But it's really close and although it might jump occasionally because the timing isn't as refined as it needs to be, the fundamentals are working fine on hardware now. I have long-term plans for PAL, but that will be late in the piece.

  • Like 2

Share this post


Link to post
Share on other sites

Hi Andrew,

 

Your planet-spin demo had me thinking:

  • is it possible to have a planet scroll up/down besides left/right?
  • does the background have to be black, or could it be another solid color, or even a textured background?

The reason I ask-- there may be some simple mechanics here that could make for an interesting "roll the ball" kind of game.  Since Playfield is a bit tedious to scroll sideways, I was thinking it might be interesting to try a simple vertical scroller, where the ball "rolls".  It rolls over certain power-ups, it gets bigger or smaller.  The ball could get smaller to fall into holes/tubes and pop out the other side, and get bigger to "climb over" walls.  Before thinking about it too hard though, I thought I'd see if any of the above is possible with the current engine idea.

 

Great demos so far, btw!

 

 

  • Like 1

Share this post


Link to post
Share on other sites
9 hours ago, Propane13 said:

is it possible to have a planet scroll up/down besides left/right?

More difficult because of the axis of spin. It's possible, but not with my current code.  The math is slightly different. Remember I'm just effectively "drawing" into a bitmap, so just about anything is possible if you can figure out the math and make it fast enough.

 

9 hours ago, Propane13 said:
  • does the background have to be black, or could it be another solid color, or even a textured background?

The background can be textured, with some minor modifications to the existing code

 

9 hours ago, Propane13 said:

The reason I ask-- there may be some simple mechanics here that could make for an interesting "roll the ball" kind of game.  Since Playfield is a bit tedious to scroll sideways, I was thinking it might be interesting to try a simple vertical scroller, where the ball "rolls".  It rolls over certain power-ups, it gets bigger or smaller.  The ball could get smaller to fall into holes/tubes and pop out the other side, and get bigger to "climb over" walls.  Before thinking about it too hard though, I thought I'd see if any of the above is possible with the current engine idea.

Well, sideways scrolling isn't tedious anymore with CDFJ.  It's pretty straightforward, actually.  I'd encourage you to pick up @SpiceWare's demo code and go from there.  Takes a little while to wrap your head around it, but worth the effort. I think my coding-head is wired differently because both that code, and some of the other code I've worked with recently (e.g., PlusCart) are just different to how I do stuff. Not wrong, just very different architecturally.

 

9 hours ago, Propane13 said:

Great demos so far, btw!

TY, it's been fun.

 

 

 

  • Like 1

Share this post


Link to post
Share on other sites

Hi Andrew,

 

any news about your fantastic tech demos - maybe a bin file for the „real thing“ and (let me dream) a PAL60 version? 🥳

Share this post


Link to post
Share on other sites
3 hours ago, Bomberman94 said:

any news about your fantastic tech demos - maybe a bin file for the „real thing“ and (let me dream) a PAL60 version? 🥳

I will come back to this sometime; I think it has a lot of potential and was fun.

But for the short/medium term I will probably not be working on it; I have studies which should be taking up my time for the foreseeable future.

 

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...