Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar

Člen
Avatar
:21.11.2012 21:45

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
Tvůrce
Avatar
Odpovídá na
matesax:22.11.2012 6:21

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 Hartinger
Vlastník
Avatar
Odpovídá na
David Hartinger:22.11.2012 12:40

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
You are the greatest project you will ever work on.
Avatar
user
Tvůrce
Avatar
Odpovídá na
user:22.11.2012 18:20

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

Člen
Avatar
:22.11.2012 20:04

Díky za rady. Pomocí proměnné mě to vůbec nenapadlo.
David Hartinger 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.