C#: Moving images around a screen based on arrow keys pressed

Started by
5 comments, last by Orymus3 9 years, 9 months ago
Hey, I'm not 100% sure this is in the right section, but A mod will move it if need be.

Anyway, At the moment I'm attempting to create a basic Pacman Clone for practice. I plan on using this to help me understand programming more and get a stronger grasp on programming for games, as well as strengthening my knowledge of Finite State Machines. At the moment I've only just started creating the basics, and So far I've managed to get an image on the screen, and Now I'm trying to get that image to move about by pressing the arrow keys (UP, DOWN, LEFT, RIGHT). I've tried to use KeyPress, but it won't work (It tells me that a '(' is expected, even if I add One and then click away)

So, Does anyone have some advice on how to do this? I'm using XNA 4.0, conding in Microsoft Visual C# in Visual Studio 2010 Professional.

Here's the Source Code:
[spoiler]using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Pacman
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}

/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here

base.Initialize();
}

/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>

//This is to create a renderable texture, specifically a 2d texture.
Texture2D PacmanTestSprite; //Same as C++ a ";" is needed to show the end of a line. Within the code, Texture2D is the identifier,
//And "PacmanTestSprite" is the actual name of the texture that I will be using. Since, for now, I
//Only need to have a basic sprite to move about, it will not be animated until later.
//*****************************************************************************************************
Vector2 spriteSpeed = Vector2.One; //This will come into use later, when I use this variable to move the sprite around the screen.
//*****************************************************************************************************
Vector2 spritePosition = Vector2.Zero; //This sets the co-ordinates for the sprite to be drawn at. In this case, it draws it at the origin,
//Or (0,0) I plan on changing this once I find out how large my window is.
//*****************************************************************************************************

protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
PacmanTestSprite = Content.Load<Texture2D>("PacmanTest"); //This is telling the program that the 2D texture I created earlier,
//PacmanTestSprite, is to be loaded as the image in the Content folder named
//pacmantest.
//******************************************************************************************************

// TODO: use this.Content to load your game content here
}

/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}

/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

// TODO: Add your update logic here

int MaxX = graphics.GraphicsDevice.Viewport.Width - PacmanTestSprite.Width;
int MaxY = graphics.GraphicsDevice.Viewport.Height - PacmanTestSprite.Height;
//int MinX = 0;
//int MinY = 0;


base.Update(gameTime);
}

/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

// TODO: Add your drawing code here
//Draw the sprite
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
spriteBatch.Draw(PacmanTestSprite, spritePosition, Color.White);
spriteBatch.End();

base.Draw(gameTime);
}
}
}
[/spoiler]


Advertisement
You will need to add the code into your Update function and change the spritePosition based on input.

Check out this tutorial on Keyboard input and see if it's what your are after. http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2D/Keyboard_input.php

You need to use a Keyboard state object to detect the key presses.
Well Jimmy already got you covered, but your source code also seems to be messed up a bit. You have the summary of your loadcontent method inside your initialize method and the Texture2d should be a class member I think. I'm not sure what you want to with MaxX in the update but ok.

So you don't really need to change your draw method, only the update(). You need to adjust the spriteposition according to button presses.
Add a new class member

KeyboardState currentKeyboardState;

and in the update() check for key presses and update the position, for example:

currentKeyboardState = Keyboard.GetState();
if (currentKeyboardState.IsKeyDown(Keys.Right))
{
spritePosition.X += 1f;
}


You have to test different values here. And to find out how big your window is, well you already got it I think:
graphics.GraphicsDevice.Viewport.Width

So you should wrap another if statement and check if the spriteposition is within the viewport, and if not you do not increase the position any further.

I hope that helps a bit, but the best thing is to get some book on XNA or use the online educational resources over at the Microsoft page. There are a few XNA books freely available on books.google.com I think.

In order to capture keystrokes in a Forms control, you must derive a new class that is based on the class of the control that you want, and you override the ProcessCmdKey().

Syntax: C#:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
	//handle your keys here
}

Source: http://net-informations.com/q/faq/arrowkeys.html

Bikitha

It is generally good practice to make render and logic independant.
I would advise to make a camera and input that don't directly refer to x and y. I realize pacman has a fixed camera but I am assuming you are doing this to learn?

Hey Elmepo, I recently did something similiar with a 2D RPG I made... Below is entire code I used:

Create KeyDown Event Handler


this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.GameForm_KeyDown);

Create logic for KeyDown Event Handler:


private void GameForm_KeyDown(object sender, KeyEventArgs e)
        {
        if (e.KeyCode == Keys.A) // Player wants to move left
                {
                    Player.Direction = 1;
                    Player.DrawCharacter(CharacterPictureBox[Player.ID], MapPictureBox); //Ignore this for now
                    if (Player.X_Location > 0) 
                    {
                        if (Map.CollisionCheck(Player.Direction, Map.MapNumber, Player, NPC) == true)
                        {
                            PlayerAnimation.Start(); // <---- This is what you want to use to move your sprite
                        }
                    }
                }

Now you have something that will "catch" your player's input and start a ticker... Here is what PlayerAnimation does.... (This function is trigger every X ms until PlayerAnimation.stop() is called)


private void PlayerAnimation_Tick(object sender, EventArgs e)
        {
            Player.Movement(Player.Direction, CharacterPictureBox[Player.ID], MapPictureBox); // <--- This is the important part
            if (Player.AnimationTicker == 4)
            {
                PlayerAnimation.Stop(); // This stops the ticker

//////////////////////// Below is used to check if player entered LoS of an enemy//////////////////
                if (Map.AggroCheck(Player, NPC) == true)
                {
                    ButtonState = 1.1;
                    if (Player.Y_Location - NPC[Map.NPCNumber].Y_Location > 1 || Player.Y_Location - NPC[Map.NPCNumber].Y_Location < -1 || Player.X_Location - NPC[Map.NPCNumber].X_Location > 1 || Player.X_Location - NPC[Map.NPCNumber].X_Location < -1)
                    {
                        NPCAnimation.Start();
                    }
                    else
                    {
                        DrawButtons();
                        CalculateTurns(Player.Companion[Player.ActiveCompanion], NPC[Map.NPCNumber].Companion[NPC[Map.NPCNumber].ActiveCompanion]);
                        StartBattle();
                    }
                }
                Player.AnimationTicker = 0;
            }
        }

Now to see what the movement function does


public void Movement(int direction, PictureBox CharPictureBox, PictureBox MapPictureBox)
        {            
         if (direction == 1) //Move West/Left
            {
                AnimationTicker++;
                CharPictureBox.Left -= 8;
                if (AnimationTicker == 1)
                {
                    SetSpriteBMP(SelectSprite(GetSprite(), 0, direction));
                    CharPictureBox.Image = GetSpriteBMP();
                }
                if (AnimationTicker == 2)
                {
                    SetSpriteBMP(SelectSprite(GetSprite(), 2, direction));
                    CharPictureBox.Image = GetSpriteBMP();
                }
                if (AnimationTicker == 3)
                {
                    SetSpriteBMP(SelectSprite(GetSprite(), 0, direction));
                    CharPictureBox.Image = GetSpriteBMP();
                }
                if (AnimationTicker == 4)
                {
                    SetSpriteBMP(SelectSprite(GetSprite(), 1, direction));
                    X_Location--;
                    DrawCharacter(CharPictureBox, MapPictureBox);
                }
            }
       }

I know I just threw a bunch of code at you, but movement/sprite animation is one of the more complex aspects of a game, since you are essentially loading images fast enough to trick the player to think the character is walking/running across the screen. If you have any questions feel free to ask and I'll try to answer as fast as possible

Edit: Just realized this was necro'd oh well....

wow, from 2011 no less :S

This topic is closed to new replies.

Advertisement