Пример #1
0
        protected void TownsDrawStripToScreen(VirtScreen vs, int dstX, int dstY, int srcX, int srcY, int width, int height)
        {
            if (width <= 0 || height <= 0)
            {
                return;
            }

            int m = _textSurfaceMultiplier;

            var src1 = new PixelNavigator(vs.Surfaces[0]);

            src1.GoTo(vs.XStart + srcX, srcY);
            var src2 = new PixelNavigator(_textSurface);

            src2.GoTo(srcX * m, (srcY + vs.TopLine - ScreenTop) * m);
            var dst1 = new PixelNavigator(_townsScreen.GetLayerPixels(0, dstX, dstY).Value);
            var dst2 = new PixelNavigator(_townsScreen.GetLayerPixels(1, dstX * m, dstY * m).Value);

            int dp1 = _townsScreen.GetLayerPitch(0) - width * _townsScreen.GetLayerBpp(0);
            int dp2 = _townsScreen.GetLayerPitch(1) - width * m * _townsScreen.GetLayerBpp(1);
            int sp1 = vs.Pitch - (width * Surface.GetBytesPerPixel(vs.PixelFormat));
            int sp2 = _textSurface.Pitch - width * m;

            if (vs == MainVirtScreen || Game.GameId == GameId.Indy3 || Game.GameId == GameId.Zak)
            {
                for (int h = 0; h < height; ++h)
                {
                    if (Surface.GetBytesPerPixel(_gfxManager.PixelFormat) == 2)
                    {
                        for (int w = 0; w < width; ++w)
                        {
                            dst1.WriteUInt16(_16BitPalette[src1.Read()]);
                            src1.OffsetX(1);
                            dst1.OffsetX(1);
                        }

                        src1.OffsetX(sp1 / src1.BytesByPixel);
                        dst1.OffsetX(dp1 / dst1.BytesByPixel);
                    }
                    else
                    {
                        for (int i = 0; i < width; i++)
                        {
                            dst1.Write(src1.Read());
                            dst1.OffsetX(1);
                            src1.OffsetX(1);
                        }
                    }

                    for (int sH = 0; sH < m; ++sH)
                    {
                        for (int i = 0; i < width * m; i++)
                        {
                            dst2.Write(src2.Read());
                            src2.OffsetX(1);
                            dst2.OffsetX(1);
                        }
                        src2.OffsetX(_textSurface.Width - (width * m));
                        dst2.OffsetX(dst2.Width - (width * m));
                    }
                }
            }
            else
            {
                dst1 = new PixelNavigator(dst2);
                for (int h = 0; h < height; ++h)
                {
                    for (int w = 0; w < width; ++w)
                    {
                        var t = (src1.Read()) & 0x0f;
                        src1.OffsetX(1);
                        for (int i = 0; i < m; i++)
                        {
                            dst1.Write((byte)((t << 4) | t));
                            dst1.OffsetX(1);
                        }
                    }

                    dst1 = new PixelNavigator(dst2);
                    var src3 = new PixelNavigator(src2);

                    if (m == 2)
                    {
                        dst2.OffsetY(1);
                        src3.OffsetY(1);
                    }

                    for (int w = 0; w < width * m; ++w)
                    {
                        dst2.Write((byte)(src3.Read() | dst1.Read() & _townsLayer2Mask[src3.Read()]));
                        dst2.OffsetX(1);
                        dst1.Write((byte)(src2.Read() | dst1.Read() & _townsLayer2Mask[src2.Read()]));
                        src2.OffsetX(1);
                        src3.OffsetX(1);
                        dst1.OffsetX(1);
                    }

                    src1.OffsetX(sp1 / src1.BytesByPixel);
                    src2 = new PixelNavigator(src3);
                    src2.OffsetX(sp2 / src2.BytesByPixel);
                    dst1 = new PixelNavigator(dst2);
                    dst1.OffsetX(dp2 / dst1.BytesByPixel);
                    dst2.OffsetX(dp2 / dst2.BytesByPixel);
                }
            }

            _townsScreen.AddDirtyRect(dstX * m, dstY * m, width * m, height * m);
        }
Пример #2
0
        void DrawFlashlight()
        {
            int i, j, x, y;
            var vs = MainVirtScreen;

            // Remove the flash light first if it was previously drawn
            if (_flashlight.IsDrawn)
            {
                MarkRectAsDirty(MainVirtScreen, _flashlight.X, _flashlight.X + _flashlight.W,
                                _flashlight.Y, _flashlight.Y + _flashlight.H, Gdi.UsageBitDirty);

                if (_flashlight.PixelNavigator.HasValue)
                {
                    Gdi.Fill(_flashlight.PixelNavigator.Value, 0, _flashlight.W, _flashlight.H);
                }
                _flashlight.IsDrawn = false;
            }

            if (_flashlight.XStrips == 0 || _flashlight.YStrips == 0)
            {
                return;
            }

            // Calculate the area of the flashlight
            if (Game.GameId == GameId.Zak || Game.GameId == GameId.Maniac)
            {
                x = _mousePos.X + vs.XStart;
                y = _mousePos.Y - vs.TopLine;
            }
            else
            {
                var a = Actors[Variables[VariableEgo.Value]];
                x = a.Position.X;
                y = a.Position.Y;
            }
            _flashlight.W = _flashlight.XStrips * 8;
            _flashlight.H = _flashlight.YStrips * 8;
            _flashlight.X = x - _flashlight.W / 2 - _screenStartStrip * 8;
            _flashlight.Y = y - _flashlight.H / 2;

            if (Game.GameId == GameId.Loom)
            {
                _flashlight.Y -= 12;
            }

            // Clip the flashlight at the borders
            if (_flashlight.X < 0)
            {
                _flashlight.X = 0;
            }
            else if (_flashlight.X + _flashlight.W > Gdi.NumStrips * 8)
            {
                _flashlight.X = Gdi.NumStrips * 8 - _flashlight.W;
            }
            if (_flashlight.Y < 0)
            {
                _flashlight.Y = 0;
            }
            else if (_flashlight.Y + _flashlight.H > vs.Height)
            {
                _flashlight.Y = vs.Height - _flashlight.H;
            }

            // Redraw any actors "under" the flashlight
            for (i = _flashlight.X / 8; i < (_flashlight.X + _flashlight.W) / 8; i++)
            {
                Debug.Assert(0 <= i && i < Gdi.NumStrips);
                Gdi.SetGfxUsageBit(_screenStartStrip + i, Gdi.UsageBitDirty);
                vs.TDirty[i] = 0;
                vs.BDirty[i] = vs.Height;
            }

            var pn = new PixelNavigator(vs.Surfaces[0]);

            pn.GoTo(_flashlight.X + vs.XStart, _flashlight.Y);
            pn = new PixelNavigator(pn);
            _flashlight.PixelNavigator = pn;
            var bgbak = new PixelNavigator(vs.Surfaces[1]);

            bgbak.GoTo(_flashlight.X + vs.XStart, _flashlight.Y);

            Gdi.Blit(pn, bgbak, _flashlight.W, _flashlight.H);

            // Round the corners. To do so, we simply hard-code a set of nicely
            // rounded corners.
            var corner_data = new [] { 8, 6, 4, 3, 2, 2, 1, 1 };
            int minrow      = 0;
            int maxcol      = (_flashlight.W - 1);
            int maxrow      = (_flashlight.H - 1);

            for (i = 0; i < 8; i++, minrow++, maxrow--)
            {
                int d = corner_data[i];

                for (j = 0; j < d; j++)
                {
                    if (vs.BytesPerPixel == 2)
                    {
                        pn.GoTo(j, minrow);
                        pn.WriteUInt16(0);
                        pn.GoTo(maxcol - j, minrow);
                        pn.WriteUInt16(0);
                        pn.GoTo(j, maxrow);
                        pn.WriteUInt16(0);
                        pn.GoTo(maxcol - j, maxrow);
                        pn.WriteUInt16(0);
                    }
                    else
                    {
                        pn.GoTo(j, minrow);
                        pn.Write(0);
                        pn.GoTo(maxcol - j, minrow);
                        pn.Write(0);
                        pn.GoTo(j, maxrow);
                        pn.Write(0);
                        pn.GoTo(maxcol - j, maxrow);
                        pn.Write(0);
                    }
                }
            }

            _flashlight.IsDrawn = true;
        }