News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_ervin

pixel masks

Started by ervin, 15:19, 03 November 10

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ervin

Hi all.

I've been trying for several hours now to figure out how to do pixel masking.
And of course I'm completely stumped.  :-[

I'm trying to draw some very fast filled rectangles on the screen, and I'm using the stack to push a 16-bit value to pairs of addresses.

This is part of a mode 0 screen.
The middle-blue represents the area that I want to fill.
The dark blue is the background.

For now I'm just trying to have 5 pixels in the top-right corner filled, with magent-green-magenta-green-magenta.
So far, I've filled the first 4 pixels using by pushing the value for magenta-green.
i.e. one push is filling 2 bytes, and each of those bytes contains the value that displays magenta-green.


Now, because I have only one more pixel to fill, I can't use push (because I won't always know what colour will be "behind" the middle-blue area). I need to plot the left pixel and mask the right one.
i.e. I want this:


But I just can't figure out how to plot that last magenta pixel, and have the pixel next to it transparent.

I hope that made sense!

Can someone please point me in the right direction?
Thanks for any help.

redbox

Well with normal sprites you AND what's already on the screen and then OR it with the value you want to print.

For example, in MODE 0 you could:


ld hl,screen_address  ; screen address we're currently at
ld a,(hl)             ; read what's on screen at this location into A
and %01010101         ; ignore the right hand pixel of the byte
or &80                ; replace &80 with what you want to draw (i.e. left hand magenta pixel)
ld (hl),a             ; draw masked pixel back to screen address


If you wanted to do it the other way around, you would AND %10101010. 

Hopefully you can adapt this for your stack based routine?

Axelay

With the stack working right to left on the screen, I assume you would be starting at the right and working left?  (you refer to it as the last pixel though, so I'm not sure) If that is the case, you could initially set the SP to just 'below', or to the left of the right edge so you can pop it, modify the required pixel as redbox described, then push it back and from there continue to push your 'complete' fill pattern.

ervin

Thanks redbox, that's exactly the info I was looking for!
Top stuff.

Axelay - yes, I'm working from right to left.
That's a great idea though, thanks for the tip.

Hopefully in a few weeks I can upload a "showable" version of what I'm working on.
:)

Axelay

Quote from: ervin on 01:23, 04 November 10
Axelay - yes, I'm working from right to left.
That's a great idea though, thanks for the tip.

Hopefully in a few weeks I can upload a "showable" version of what I'm working on.
:)


D'oh!  Thinking about it today, it doesnt seem like a good idea at all!  If you always have just the one byte to worry about, a simple ld a,(hl) <do the mask> ld (hl),a is going to be faster than the pop <do the mask> push.  Maybe it could still be of value depending on how you are handling rectangles with an odd number of full bytes to fill.  But probably not.  :-\


So these fast filling rectangles, care to share what they're for yet, or do we have to wait?  :)

ervin

#5
Actually I've been thinking the same thing about the single byte.
We'll see how it goes.

I'm not writing anything special.
I was writing an updated, faster version of my adaptation of 3D-Maze that I released late last year.
It was coming along very nicely, but there was something else in the back of my mind...

So I've changed the focus of it a bit.
It's still a 3D-Maze thingy, but more of an attempt at creating a fast cell-based maze where the "blocks" can be anywhere, and unconnected. So the idea is to be able to have large open areas, tight narrow areas etc.
The main point of it all though is simply to see how fast I can make it, with filled blocks instead of wireframe blocks.

I've got the main algorithm (that determines which blocks are to be considered for display) working very well, and very quickly.
Now the fun bit is underway - displaying them.

Whether or not it becomes an actual "game" though remains to be seen.
It might be more in the realm of an "interactive demo".

redbox

Quote from: ervin on 13:28, 04 November 10
So I've changed the focus of it a bit.

This sounds cool, looking forward to seeing it.

Quote from: ervin on 13:28, 04 November 10
I've got the main algorithm (that determines which blocks are to be considered for display) working very well, and very quickly.

Did you base this on the 'grid' system that we previously spoke about?  Would be interested to see how you implemented it.

ervin

#7
No, although the concept behind that will come in handy in the program.

The grid in this program represents the floor that the player can actually move around.
It's a 50x50 array containing the maze data, so it's possible to create some pretty big mazes.
I'm also considering allowing a different colour to be assigned to each block, just by what is contained in each cell of the array that defines the maze.

The grid concept we talked about earlier (relating to only clearing/drawing parts of the screen that have changed) will come in useful when deciding whether or not to draw walls that are behind other visible walls.

At the moment, the player's direction, as well as how far they are from the edge of the 50x50 grid, is the main factor in creating the data that represents the field of view.

The next task (after spending some time drawing some blocks on the screen to test the feasibility of my ideas) is to process the field of view data more carefully, and implement the idea of only drawing "visible" blocks on the screen. This will also impact which parts of the "sky" and "ground" need to be drawn. I'm trying to avoid doing any screen clearing at all.
I'm also going for full-screen mode 0.  8)

(I hope that all made sense!)

Incidentally, the pixel masking tips you gave me are working nicely - thanks for getting me over that hurdle.

Good fun, this little project!

Axelay

Sounds like an interesting project, and aiming for full screen too.  Makes that speed goal sound ambitious!

arnoldemu

Quote from: Axelay on 09:09, 05 November 10
Sounds like an interesting project, and aiming for full screen too.  Makes that speed goal sound ambitious!
indeed. Ervin it will be interesting how fast you get it.
It would be fantastic if it was *overscan* mode 0 ;)
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

redbox

The algorithm for what's in the field of sight sounds very intriguing, will be nice to see how you do it.

ervin

#11
Overscan eh?
We shall see... memory may become a problem if I go down that path.
This'll be designed to fit into 64K.
Still, I like the idea!

The algorithm for what is in the player's field of view is already working, and it is really fast.
It's the non-drawing of hidden blocks that'll be the challenge!  :)

Sykobee (Briggsy)

What algorithm are you using for determining which blocks are in the players field of view?


One way to do a FoV is to implement a 1 dimensional depth buffer, but you need to raycast from the player position on the screen for this to work. One thing though is that this gives you the ability to view in arbitrary directions. Obviously this also requires some trigonometry.


With fixed LRUD directions, you could pre-compute the ray paths for speed, at the expense of memory for the ray paths. You just check along the paths until you hit a block, or the path runs out (ooh, too distant to see in the dark/fog ;-) ).

ervin

#13
Here's what I've done:

mazeData is a 50x50 array (well, 2500 sequential bytes).

view0 represents the blocks around the player.
It contains 3 bytes - one for a block to the left, the block the player is on, and one for a block to the right.
If there is a block to the left, view0 looks like this: 1 0 0

And so on up to view8, which represents blocks that are furthest away from the player.
The player can "see" 8 blocks into the distance.
(Incidentally, I'm trying to figure out useful colour combinations in order to simulate darkness in the distance, so that visible blocks don't just abruptly end).

view8 will contain: 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
if there is a block 8 units away, directly in line with the player.
If there are blocks to the sides of that position, it may look like 0 0 1 1 0 0 1 0 0 0 1 0 0 0 0 0 1
etc.

So if there is nothing in the player's view, the arrays will be empty, and the field of view will look like this:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    view8
    0 0 0 0 0 0 0 0 0 0 0 0 0        view7
        0 0 0 0 0 0 0 0 0            view6
          0 0 0 0 0 0 0              view5
            0 0 0 0 0                view4
              0 0 0                  view3
              0 0 0                  view2
              0 0 0                  view1
              0 0 0                  view0

The lowest row represents the player's position, and only the left and right positions can have a 1.

Anyway, the "view" arrays are populated every time the player moves or changes direction, based on reading data from the mazeData array. Offsets are used to grab data from the correct byte(s), based on the direction the player is facing (NSEW). If the relevant byte in mazeData contains something other than a 0, it means there is a block there. I'm using 1 at the moment to represent a block, but in the future, they could be values representing colour. Not sure yet.

Now, once we have a populated set of view arrays, it is easy to scan them and determine what is to be drawn on the screen. It is also very easy to say

if view7(0)=1 then don't draw view8(0) and view8(1), (i.e. set them to zero), as view7(0) will obscure them anyway.

I hope that made sense.

redbox

Yes, I understand this (only had to read it twice  8) ).

Principle seems good and am looking forward to seeing it in real time.  Are you planning on making it be turn based (1 move/stop/1 move/stop) or is it free-flowing?

ervin

Quote from: redbox on 16:04, 05 November 10
Yes, I understand this (only had to read it twice  8) ).

Principle seems good and am looking forward to seeing it in real time.  Are you planning on making it be turn based (1 move/stop/1 move/stop) or is it free-flowing?

Only turn-based I'm afraid.
My maths isn't quite good enough to make it free movement.
;D

Powered by SMFPacks Menu Editor Mod