Verschieben meines Sprites in XNA mithilfe von Klassen

7

Hey, ich bin ein Neuling in dieser Programmierlerche und es ist wirklich frustrierend für mich. Ich versuche, eine Schlange in alle Richtungen zu bewegen, während ich Klassen benutze. Ich habe einen Vektor2 für Geschwindigkeit erstellt und versucht, eine Methode zu erstellen, die die Schlange innerhalb der Schlangenklasse bewegt.

Jetzt bin ich verwirrt und nicht sicher, was ich als nächstes tun soll.

Schätzen Sie jede Hilfe. Danke: D

Dies ist, was ich in Bezug auf die Methode getan habe ...

  public Vector2 direction()
        {
                Vector2 inputDirection = Vector2.Zero;

                if (Keyboard.GetState().IsKeyDown(Keys.Left)) inputDirection.X -= -1;
                if (Keyboard.GetState().IsKeyDown(Keys.Right)) inputDirection.X += 1;
                if (Keyboard.GetState().IsKeyDown(Keys.Up)) inputDirection.Y -= -1;
                if (Keyboard.GetState().IsKeyDown(Keys.Down)) inputDirection.Y += 1;

                return inputDirection * snakeSpeed;

        }

Schätzen Sie jede Hilfe. Danke: D

EDIT:
Nun, lassen Sie mich alles klarstellen. Ich mache ein kleines Grundspiel für eine Aufgabe. Das Spiel ähnelt dem alten Schlangenspiel auf den alten Nokia-Handys. Ich habe eine Schlangenklasse erstellt (obwohl ich nicht sicher bin, ob dies erforderlich ist, da ich nur ein sich bewegendes Sprite im Spiel haben werde). Nachdem ich den obigen Code (in der Schlangenklasse) geschrieben hatte, lief das Spiel ohne Fehler, aber ich konnte das Bild nicht wirklich verschieben :(

EDIT2: Vielen Dank für alle Antworten!


quelle
Entschuldigung für das schlechte Zitat meines Codes: /
Dies scheint ein praktikabler Ansatz zu sein, aber ich sehe hier keine wirkliche Frage. Fragen Sie sich, wie Sie das Ergebnis Ihrer "Richtungs" -Funktion nutzen können, um ein Objekt tatsächlich zu bewegen?
Ich denke, wenn Sie den Code veröffentlichen, der tatsächlich die Ausgabe dieser Richtungsmethode verwendet, können wir Ihnen möglicherweise helfen. Ich denke, der Fehler liegt darin, wie Sie die Position des Sprites aktualisieren.
Michael Coleman
Das Upvoting und Akzeptieren von Antworten ist ein weiterer Weg. GD bedankt sich bei Ihren Entwicklerkollegen, die Ihnen geholfen haben, Ihr Ziel zu erreichen. =)
Will Marcouiller

Antworten:

2

Obwohl ich auch ein Neuling in der Spieleentwicklung bin, würde ich wetten, dass Sie Ihre inputDirectionVariable immer neu initialisieren Vector2.Zero.

Ich weiß nicht viel über Spieleentwicklung, aber was die objektorientierte Programmierung betrifft, ist das eine andere Sache! Hier ist, was ich mitgekommen bin, nachdem ich Ihren Kommentar über Klassen gelesen habe.

public class Snake {
    private Texture2D _snake; // Represents your snake's sprite.
    private Vector2 _snakePos; // Field that determines your snake's position.
    private Vector2 _snakeSpeed = new Vector2(10.0f, 10.0f); // Field that determines the number of pixels your snake will move at once while moving.

    public Snake(Vector2 initialPosition) {
        _snakePos = initialPosition;
    }

    public void MoveDown() {
        _snakePos.Y += _snakeSpeed.Y;
    }

    public void MoveLeft() {
        _snakePos.X -= _snakeSpeed.X;
    }

    public void MoveRight() {
        _snakePos.X += _snakeSpeed.Y;
    }

    public void MoveUp() {
        _snakePos.Y -= _snakeSpeed.Y;
    }
}

public class Game Game1 {
    private Snake _snake = new Snake();

    protected override void Update(GameTime gameTime) {
        Keys[] keys = Keyboard.GetState().GetPressedKeys();

        if (keys != null && keys.Length > 0)
            switch (keys[0]) {
                case Keys.Escape:
                    Exit();
                    break;
                case Keys.Down:
                    _snake.MoveDown();
                    break;
                case Keys.Left:
                    _snake.MoveLeft();
                    break;
                case Keys.Right:
                    _snake.MoveRight();
                    break;
                case Keys.Up:
                    _snake.MoveUp();
                    break;
                default:
                    break;
            }
    }
}

Ich hoffe, das hilft und auf dem richtigen Weg zu einer tragfähigen Lösung zu sein! =)

Will Marcouiller
quelle
Dies scheint ein langwieriger Weg zu sein, um ein paar Knöpfe zu benutzen .. aber was weiß ich lol. Ich habe eigentlich keine Ahnung, was ich in Bezug auf Klassen
2
In der Tat ist dies Ihre SnakeKlasse, die sich ihrer Geschwindigkeit und Richtung bewusst sein sollte. Abgesehen davon ist dies das Spiel, das die Benutzereingaben erhält. Also, in meinem Verständnis, müssen Sie die Schlange Know machen welche Richtung es beim nächsten Kopf soll, das ist, glaube ich , dass Sie in Ihrem haben, sollten SnakeKlasse, vier Methoden: MoveDown(), MoveLeft(), MoveRight()und MoveUp(). Es ist die Schlange, die weiß, was zu tun ist, um sich in die eine oder andere Richtung zu bewegen, und da sie auch ihre Geschwindigkeit kennt, soll sie sich entsprechend bewegen. GameInstanziieren Sie dann in Ihrer Klasse Ihre Schlange und geben Sie die Anweisungen durch ihre Methoden ein!
Will Marcouiller
1
Bitte lesen Sie meine bearbeitete Antwort, da ich eine mögliche SnakeKlasse aufgenommen habe, die vier MoveMethoden offenlegt . Die Schlange muss nicht wissen, welche Taste gedrückt wurde, sondern Ihr Spiel erhält die Tasten. Dann ist es Ihr Spiel, das Ihrer Schlange sagt, wohin sie gehen soll, abhängig von den Tasten, die der Spieler gedrückt hat. Dann Ihr Spiel erzählt eine _snakeInstanz MoveLeft, MoveDownusw. abhängig von den Tasten , die Sie gedrückt. Lassen Sie mich wissen, ob das hilft! Und zögern Sie nicht, Kommentare zu Dingen abzugeben, bei denen Sie nicht arbeiten oder so. Ich werde Ihnen gerne helfen, so gut ich kann.
Will Marcouiller
Vielen Dank, genau das habe ich in Bezug auf eine Antwort gesucht. Du hast dich Neuling genannt, aber anders gezeigt :). Ich bin buchstäblich schrecklich in diesem Coding Jazz. Meine Verwirrung ist, wenn ich Klassen für alles benutze (was wahrscheinlich der Schlüssel ist).
1
Imo, Head First C # ist ein ordentliches Buch, um eine gute objektorientierte Grundierung zu erhalten und gleichzeitig sichtbare Ergebnisse zu erzielen.
Oskar Duveborn
2

Ich verwende Code wie diesen, um meine Sprites zu verschieben. Er funktioniert in der Regel recht gut für mich. Außerdem wird "GameTime" verwendet, um sicherzustellen, dass die Bewegung über die Frameraten hinweg konsistent ist.

// Sprite Protecteds
Vector2 direction;
Vector2 position;
float speed;

// Sprite Code
void Update(GameTime time, KeyboardState kb)
{
    // reset to zero for no keys pressed
    direction = Vector2.Zero;

    if (Keyboard.GetState().IsKeyDown(Keys.Left)) direction.X = -1;
    if (Keyboard.GetState().IsKeyDown(Keys.Right)) direction.X = 1;
    if (Keyboard.GetState().IsKeyDown(Keys.Up)) direction.Y = -1;
    if (Keyboard.GetState().IsKeyDown(Keys.Down)) direction.Y = 1;

    position += direction * speed * time. Milliseconds;
}

// Game "Update" method (not sure of exact code here)
sprite.Update(gameTime, Keyboard.GetState());

Offensichtlich möchten Sie dem Sprite während des Aktualisierungsprozesses möglicherweise mehr Parameter zur Verfügung stellen, sodass Sie möglicherweise auch die Geschwindigkeit oder andere Faktoren berücksichtigen.

Nate
quelle
3
Überall in jedem XNA-Tutorial sollten riesige rote Aufkleber angebracht sein, um die Benutzer über die Verwendung von GameTime zu informieren und alle Frame-für-Frame-Ereignisse zu ändern, die Sie mit einer konstanten Echtzeitrate aktualisieren möchten, um unabhängig von der Hardware ein konsistentes Spielerlebnis zu bieten .
Bill
@ Bill: Genau meine Gefühle.
Michael Coleman
2

Diese Frage braucht mehr Lambdas.

Beachten Sie, dass dies aus einem WIP stammt, sodass einige nicht verwendete und implizierte, aber nicht implementierte Funktionen vorhanden sind. Wo Sie das sehen, () =>fügen Sie Ihre hinzu inputDirection.X -= -1;. Mir ist klar, dass dies für ein Gamepad gilt und Sie eine Tastatur verwenden, aber das Gruppierungsprinzip oder zumindest der Begriff der Aktionskarte gilt weiterhin.

Das ist wahrscheinlich übertrieben, macht aber viel Spaß!

Setup-Funktion, die die Steuerelemente abbildet:

public void SetController(MyGamePad controller)
{
    controller.ClearActions();

    controller.BindAction(Buttons.Start, ButtonGroup.FullyExclusive, () => sine.play());

    controller.BindAction(Buttons.A,
        ButtonGroup.FaceButtons, () => showText("A!"));
    controller.BindAction(Buttons.A | Buttons.B,
        ButtonGroup.FaceButtons, () => showText("A and B!"));
    controller.BindAction(Buttons.B,
        ButtonGroup.FaceButtons, () => showText("B"));
    controller.BindAction(Buttons.B | Buttons.Y,
        ButtonGroup.FaceButtons, () => showText("B and Y!"));
    controller.BindAction(Buttons.Y,
        ButtonGroup.FaceButtons, () => showText("Y!"));
    controller.BindAction(Buttons.Y | Buttons.X,
        ButtonGroup.FaceButtons, () => showText("Y and X!"));
    controller.BindAction(Buttons.X,
        ButtonGroup.FaceButtons, () => showText("X!"));
    controller.BindAction(Buttons.X | Buttons.A,
        ButtonGroup.FaceButtons, () => showText("X n A, I made a funny!"));
    controller.BindAction(0x0,
        ButtonGroup.FaceButtons, () => showText("Nothing on the face buttons."));

    controller.BindAction(0x0,
        ButtonGroup.ShoulderButtons, () => showText("No shoulder buttons"));
    controller.BindAction(Buttons.LeftShoulder,
        ButtonGroup.ShoulderButtons, () => showText("Left shoulder button!"));
    controller.BindAction(Buttons.RightShoulder,
        ButtonGroup.ShoulderButtons, () => showText("Right shoulder button!"));

    controller.BindAction(0x0,
        ButtonGroup.DirectionalPad, () => showText("Nothin' on the dpad!"));
    controller.BindAction(Buttons.DPadUp,
        ButtonGroup.DirectionalPad, () => showText("DPAD UP!"));
    controller.BindAction(Buttons.DPadDown,
        ButtonGroup.DirectionalPad, () => showText("DPAD DOWN!"));
}

Die Spielkomponente, mit der es funktioniert (1 pro Spieler instanziieren):

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using System.Collections.Generic;

namespace MyGame
{
    [Flags]
    public enum ButtonGroup
    {
        NonExclusive            = 0x00,
        FaceButtons             = 0x01,
        DirectionalPad          = 0x02,
        ShoulderButtons         = 0x04,
        LeftSide                = 0x08,
        RightSide               = 0x10,
        FullyExclusive          = 0xFF,
    }

    class MyGamePad : GameComponent
    {
        private Buttons FaceButtons;
        private Buttons DirectionalButtons;
        private Buttons ShoulderButtons;
        private Buttons LeftSideButtons;
        private Buttons RightSideButtons;
        private Buttons AllButtons;

        private PlayerIndex playerIndex;
        private Dictionary<KeyValuePair<Buttons, ButtonGroup>, Action> actionMap = new Dictionary<KeyValuePair<Buttons, ButtonGroup>, Action>();

        public InstrumentPad(Game game, PlayerIndex playerIndex) : base(game)
        {
            this.playerIndex = playerIndex;
        }

        public void ClearActions()
        {
            actionMap.Clear();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            updateButtons();

            foreach (KeyValuePair<Buttons, ButtonGroup> pair in actionMap.Keys)
            {
                switch (pair.Value)
                {
                    case ButtonGroup.DirectionalPad:
                        if (DirectionalButtons == pair.Key)
                            actionMap[pair].Invoke();
                        break;
                    case ButtonGroup.FaceButtons:
                        if (FaceButtons == pair.Key)
                            actionMap[pair].Invoke();
                        break;
                    case ButtonGroup.ShoulderButtons:
                        if (ShoulderButtons == pair.Key)
                            actionMap[pair].Invoke();
                        break;
                    case ButtonGroup.LeftSide:
                        if (LeftSideButtons == pair.Key)
                            actionMap[pair].Invoke();
                        break;
                    case ButtonGroup.RightSide:
                        if (RightSideButtons == pair.Key)
                            actionMap[pair].Invoke();
                        break;
                    case ButtonGroup.FullyExclusive:
                        if (AllButtons == pair.Key)
                            actionMap[pair].Invoke();
                        break;
                    case ButtonGroup.NonExclusive:
                        if ((AllButtons & pair.Key) == pair.Key)
                            actionMap[pair].Invoke();
                        break;
                }
            }
        }

        public void BindAction(Buttons buttonCombo, ButtonGroup buttonGrouping, Action action)
        {
            KeyValuePair<Buttons, ButtonGroup> pair = new KeyValuePair<Buttons, ButtonGroup>(buttonCombo, buttonGrouping);
            if (!actionMap.ContainsKey(pair))
                actionMap.Add(pair, action);
            else
                actionMap[pair] = action;
        }

        private void updateButtons()
        {
            GamePadState padState = GamePad.GetState(playerIndex);
            LeftSideButtons = 0x0;
            RightSideButtons = 0x0;

            FaceButtons = 0x0;
            if (padState.Buttons.A == ButtonState.Pressed)
                FaceButtons |= Buttons.A;
            if (padState.Buttons.B == ButtonState.Pressed)
                FaceButtons |= Buttons.B;
            if (padState.Buttons.X == ButtonState.Pressed)
                FaceButtons |= Buttons.X;
            if (padState.Buttons.Y == ButtonState.Pressed)
                FaceButtons |= Buttons.Y;

            RightSideButtons |= FaceButtons;

            DirectionalButtons = 0x0;
            if (padState.DPad.Up == ButtonState.Pressed)
                DirectionalButtons |= Buttons.DPadUp;
            if (padState.DPad.Down == ButtonState.Pressed)
                DirectionalButtons |= Buttons.DPadDown;
            if (padState.DPad.Left == ButtonState.Pressed)
                DirectionalButtons |= Buttons.DPadLeft;
            if (padState.DPad.Right == ButtonState.Pressed)
                DirectionalButtons |= Buttons.DPadRight;

            LeftSideButtons |= DirectionalButtons;

            ShoulderButtons = 0x0;
            if (padState.Buttons.LeftShoulder == ButtonState.Pressed)
            {
                ShoulderButtons |= Buttons.LeftShoulder;
                LeftSideButtons |= Buttons.LeftShoulder;
            }
            if (padState.Buttons.RightShoulder == ButtonState.Pressed)
            {
                ShoulderButtons |= Buttons.RightShoulder;
                RightSideButtons |= Buttons.RightShoulder;
            }

            AllButtons = LeftSideButtons | RightSideButtons;

            if (padState.Buttons.Start == ButtonState.Pressed)
                AllButtons |= Buttons.Start;
            if (padState.Buttons.Back == ButtonState.Pressed)
                AllButtons |= Buttons.Back;
        }
    }
}
michael.bartnett
quelle
1

Jetzt bin ich verwirrt und nicht sicher, was ich als nächstes tun soll.

Bedeutet dies, dass Ihr Code nicht das tut, was Sie denken, dass er tun sollte, oder haben Sie eine Funktion, die Sie implementieren müssen, die Sie nicht wissen, wie oder möchten Sie Ratschläge, welche Funktion als nächstes implementiert werden soll?

So oder so...

if (Keyboard.GetState().IsKeyDown(Keys.Left)) inputDirection.X -= -1;
if (Keyboard.GetState().IsKeyDown(Keys.Right)) inputDirection.X += 1;

Sie möchten kein Negativ für eine Richtung subtrahieren und kein Positiv in der anderen Richtung hinzufügen. Diese beiden bewerten dasselbe.

Tetrad
quelle
Nun, lassen Sie mich alles klarstellen. Ich mache ein kleines Grundspiel für eine Aufgabe. Das Spiel ähnelt dem alten Schlangenspiel auf den alten Nokia-Handys. Ich habe eine Schlangenklasse erstellt (obwohl ich nicht sicher bin, ob dies erforderlich ist, da ich nur ein sich bewegendes Sprite im Spiel haben werde). Nachdem ich den obigen Code (in der Schlangenklasse) geschrieben hatte, lief das Spiel ohne Fehler, aber ich konnte das Bild nicht wirklich verschieben :(
1
@ Tom, du solltest die Klarstellung in die Frage selbst setzen.
Tetrad
1

So mache ich das in einem meiner Spiele unter Windows Phone. Denken Sie daran, dass ich zum Beispiel einige Vereinfachungen vorgenommen habe. In meinem Spiel folgen Feinde einer Reihe von Wegpunkten entlang eines Pfades.

Bei der UpdateMethode in meiner Enemy.csKlasse bewerte ich Enemy.Waypoints.Peek() - Enemy.Position(normalisiert), um zu bestimmen, in welche Richtung sich der Feind bewegen soll.

this.Direction = this.Waypoints.Peek() - this.Position;
this.Direction.Normalize();

Dann berechne ich die Geschwindigkeit (Richtung + Geschwindigkeit) für den aktuellen Frame anhand der Richtung.

this.Velocity = Vector2.Multiply(this.Direction, Settings.Speed * this.Speed);

Schließlich passe ich die tatsächliche Position des Feindes an.

// Adjust the position according to the velocity.
this.Position += this.Velocity;

Es hilft, die Mathematik zu verstehen, aber so können Sie ein Objekt bewegen.

Ed Altorfer
quelle