Diskuze: Pohyb s objektem

C# .NET .NET (C# a Visual Basic) Pohyb s objektem American English version English version

Avatar
davous267
Člen
Avatar
davous267:

Nazdar,

začínám s XNA a napadlo mě udělat malé sestře hru, kde si bude vyskládávat domečky na travnatou plochu. Ale kvůli tomu sem nepíšu :D
Základní funkčnost hry mám, ale narazil jsem na problém.

Všechny domky (každý domek = objekt se svým Rectanglem a Texture2D) mám vyskládané v panelu. Takto mám uděláno "vezmutí" domku a přenesení na místo, kde ho chci postavit:

if ((hra.mys.LeftButton == ButtonState.Pressed))
            {
                for (int i = 0; i < mbItems.Count; i++)
                {
                    if (mbItems[i].Pozice.Contains(hra.mys.X, hra.mys.Y))
                    {
                       mbItems[i].Pozice = new Rectangle(hra.mys.X - 20, hra.mys.Y - 20, mbItems[i].Pozice.Width, mbItems[i].Pozice.Height);

                        break;
                    }
                }


            }

A takto jeho položení:

if (hra.mys.LeftButton == ButtonState.Released && !menuBarRect.Contains(hra.mys.X, hra.mys.Y))
            {
                for (int i = 0; i < mbItems.Count; i++)
                {
                    if (mbItems[i].Pozice.Contains(hra.mys.X, hra.mys.Y))
                    {
                        mbItems[i].Pozice = mbItems[i].puvPozice;
                        bigItems.Add(new mbItem(bigItems[i].Textura,new Rectangle(hra.mys.X-40, hra.mys.Y-40, bigItems[i].Pozice.Width, bigItems[i].Pozice.Height)));

                        // useknutí cyklu
                        break;
                    }

                }
            }

Vše funguje jak má, až na to, že:

  1. Myší se velice snadno pohne tak rychle, že Rectangle chyceného objektu již neobsahuje pozici myši a domek zůstane "viset" nepostavený.
  2. Když člověk při braní malé textury přejede přes jinou, tak vezme obě dvě - díky break už nevezme ty, které jsou v Listu za ním, ale ty nalevo stále bere.

Toť vše. Akorát nevím, jestli je k pochopení co tím myslím :D

 
Odpovědět 21.11.2012 21:45
Avatar
matesax
Redaktor
Avatar
Odpovídá na davous267
matesax:

Já bych udělal každý objekt jako samovykreslovací komponentku - Drawable Component. A v Update si hlídal, zda já.Intersects(rec­tangle myši - cca 6x6). Takže "já" bude buď nově vytvořený Rectangle z vastnosti Position, nebo si pozici objektu můžeš zaznamenávat rovnou v Rectangle - v případě, že je každý objekt jinak veliký bych ukládal pozici v Rectangle i za cenu, že se mu hůře mění pozice - při kliknutí a překrývání s myší budeš muset nesutále vytvářet nové Rectangly - ovšem s X a Y v smoatatných proměnných by bylo asi mnohem více práce... :) Takže abych to shrnul - každý objekt udělej jako Drawable Component. Předávej si jeden SpriteBatch a v komponentkách již nemusíš volat Begin a End. A v update hlídej kolize s ostatnímy obekty včetně myši, atp...

PS.: Intersects je skutečně metoda Rectangle...

Editováno 22.11.2012 6:24
 
Nahoru Odpovědět 22.11.2012 6:21
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na davous267
David Čápka:

Domy jako komponenty prosím nedělej, je to hloupost a už jsem to Matesaxovi několikrát říkal. Pokud je každý dům stejně velký, mohl by sis to velmi zjednodušit 2D polem místo toho listu. Pokud ne, je list nutný. Tvůj kód se mi moc nelíbí, proč si prostě neuložíš aktuálně držený dům do proměnné? Pokud dům držet nebudeš, bude v proměnné hodnota null. Vůbec nechápu všechny ty cykly a asi ani nechci chápat.

Nahoru Odpovědět 22.11.2012 12:40
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
user
Redaktor
Avatar
Odpovídá na davous267
user:

Souhlasím se Sdracem, komponenta se v tomto pripade nehodi. Nastesti jsem pohyb objektu uz delal. Trochu jsem to zjednodusil, snad si to preberes, kdyby neco nebylo jasne, klidne se zeptej. :)

public class ObjectMover : GameComponent
    {
        InputState inputState;

        public MovementObject movementObject;
        MovementObject selectedObject;
        bool isPressed = false;
        Vector2 lastCursorPosition;

        Point mousePressedPoint;

        public ObjectMover(Game1 game)
            : base(game)
        {
            this.inputState = new InputState();
        }

        public override void Initialize()
        {
            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            inputState.Update();
            MouseState mouse = inputState.CurrentMouseState;

            if (inputState.IsNewMouseLeftButtonPress())
                mousePressedPoint = new Point(mouse.X, mouse.Y);

            if (movementObject != null)
            {

                if (mouse.LeftButton == ButtonState.Released)
                    reset();

                if (!isPressed)
                    if (movementObject.rectangle.Contains(mouse.X, mouse.Y) && mouse.LeftButton == ButtonState.Pressed && movementObject.rectangle.Contains(mousePressedPoint))
                        selectObject(entity);

                if (isPressed && movementObject == selectedObject)
                {
                    movementObject.isInMove = true;
                    Move(entity);
                }
                else
                    movementObject.isInMove = false;

            }

            base.Update(gameTime);
        }

        public void reset()
        {
            isPressed = false;
            selectedObject = null;
        }

        private void selectObject(MovementObject entity)
        {
            isPressed = true;
            selectedObject = entity;
            lastCursorPosition = new Vector2(inputState.CurrentMouseState.X, inputState.CurrentMouseState.Y);
        }

        private void Move(MovementObject entity)
        {
            Vector2 drift = new Vector2(inputState.CurrentMouseState.X - lastCursorPosition.X, inputState.CurrentMouseState.Y - lastCursorPosition.Y);
            entity.position += drift;
            lastCursorPosition = new Vector2(inputState.CurrentMouseState.X, inputState.CurrentMouseState.Y);
        }

    }
 
Nahoru Odpovědět 22.11.2012 18:20
Avatar
davous267
Člen
Avatar
davous267:

Díky za rady. Pomocí proměnné mě to vůbec nenapadlo.
David Čápka Ty cykly jsem tam měl z důvodu, abych rozpoznal na kterém domku jsem najetý.

 
Nahoru Odpovědět 22.11.2012 20:04
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.