I'm working on a game, and I made all the building blocks. now I'm working on the game logic and rendering.
I have abstract Monster class and a class call GreenMonster that inherits from it.
Now the weird thing is, when I try to init a GreenMonster object.
when I do this:
private void initGreenMonsters()
{
for (int i = 0; i < greenMonsters.Length; i++)
{
greenMonsters[i] = new GreenMonster(new Point(0,40),new Size(40, 40));
}
}
every thing works like I planned and I can render the images on the form.
but when I try to init like that:
private void initGreenMonsters()
{
for (int i = 0; i < greenMonsters.Length; i++)
{
greenMonsters[i] = new GreenMonster();
greenMonsters[i].Position = new Point(0, 40);
greenMonsters[i].Size = new Size(40, 40);
}
}
I don't get any errors, and the app runs, but I can render the monsters.
This is the Monster class constructor and the Draw Method I use to draw a Monster:
public Monster(Point _startPosition,Size _size)
{
this.size = _size;
this.position = _startPosition;
}
public virtual void Draw(Graphics g)
{
Rectangle monsterRec = new Rectangle(position, size);
g.DrawImage(img, monsterRec);
}
and this is the GreenMonster class constructor:
public GreenMonster(Point _startPosition, Size _size)
: base(_startPosition, _size)
{
this.img = new Bitmap(SpaceInvadersGame.Properties.Resources.NormalMonster);
this.hp = 1;
this.speed = 1;
}
public GreenMonster()
{
this.img = new Bitmap(SpaceInvadersGame.Properties.Resources.NormalMonster);
this.hp = 1;
this.speed = 1;
}
the only thing that bothers me is, that when I'm looking at both ways I init the objects, it just looks the same..
I just can't find any different between in both of the ways.
someone have any idea how its different?
If you need more code so the question is more clear, I would be happy to add!
this is the Monster class and its properties
public abstract class Monster
{
protected Point position;
public Point Position { get { return position; } set { position = value; } }
protected Size size;
public Size Size { get { return size; } set { value = size; } }
public int speed;
protected Bitmap img;
protected int hp;
public int HP { get { return hp; } }
public void SetStartingPosition(int x, int y)
{
this.position = new Point(x, y);
}
public virtual void Draw(Graphics g)
{
Rectangle monsterRec = new Rectangle(position, size);
g.DrawImage(img, monsterRec);
}
}
You are setting your incoming value to the current size, rather than setting the current size to the incoming value, in the method below:
public Size Size { get { return size; } set { value = size; } }
should be
public Size Size { get { return size; } set { size = value; } }
Your code for Position looks OK though:
public Point Position { get { return position; } set { position = value; } }
Related
I'm trying to learn Monogame / XNA by creating a little Terraria-like game. I currently want to create a world, which is completely filled with dirt. My problem is that only one block from an block array gets drawn. Here is my code:
public class Survival2DGame : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private World world;
private Block dirtBlock;
public Survival2DGame()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
dirtBlock = new Block(Content.Load<Texture2D>("Dirt"), Vector2.Zero);
world = new World(100, 100);
WorldGeneration.GenerateWorld(world, dirtBlock);
Debug.WriteLine(world.blocks[50, 50].Texture);
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
_spriteBatch.Begin();
world.Draw(_spriteBatch);
_spriteBatch.End();
base.Draw(gameTime);
}
}
static class WorldGeneration
{
public static void GenerateWorld(World world, Block dirtBlock)
{
for (int x = 0; x < world.Length; x++)
{
for (int y = 0; y < world.Height; y++)
{
world.blocks[x, y] = dirtBlock;
world.blocks[x, y].Position = new Vector2(x * 16, y * 16);
}
}
}
}
class World
{
public int Length { get; set; }
public int Height { get; set; }
public Block[,] blocks;
public World(int length, int height)
{
Length = length;
Height = height;
blocks = new Block[length, height];
}
public void Draw(SpriteBatch spriteBatch)
{
foreach (Block block in blocks)
{
block.Draw(spriteBatch);
}
}
}
class Block
{
public Texture2D Texture { get; set; }
public Vector2 Position { get; set; }
public Block(Texture2D texture, Vector2 position)
{
Texture = texture;
Position = position;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, Color.White);
}
}
When i run the game its completely empty.
I think it has something to do with me only creating one dirt block and not a new one everytime i add it to the array. I so far only have experience with unity and there i would handle this with Scriptable Objects.
There is a subtle bug in your game, but the critical issue is in your code for WorldGeneration.GenerateWorld()
In your implementation, you have done
static class WorldGeneration
{
public static void GenerateWorld(World world, Block dirtBlock)
{
for (int x = 0; x < world.Length; x++)
{
for (int y = 0; y < world.Height; y++)
{
world.blocks[x, y] = dirtBlock; // THIS IS THE PROBLEM
world.blocks[x, y].Position = new Vector2(x * 16, y * 16);
}
}
}
}
You see, in C# all class instances are reference types, meaning when you do world.blocks[x,y]=dirtblock for all iterations, All of your instances are referring/pointing at the same instance dirtblock.
To explain the above step by step, let's say the dirtblock instance is allocated in memory location 0x10. In the first iteration (x=0, y=0), the following is executed:
world.blocks[0, 0] = dirtblock;
Then world.blocks[0,0] is also at the same location 0x10. At this point, changing the value dirtblock or the value of world.blocks[0,0] would change the same variable. So at the end of the iteration, dirtblock and world.block[0, 0] has their Position variable at (0, 0)
In the next iteration, world.blocks[0, 1] is also assigned to the same memory location, and its Position is made to be (0, 16). But this also means that world.blocks[0, 0] and dirtblock's Position value is made to be (0, 16) since all these variables are pointing at the same reference.
At the end of the entire loop, all blocks in your code have their Position value the same as the Position value of the last block, i.e world.blocks[99, 99]. Since this is outside the dimension of the game (i.e 640x480) You don't see anything.
So to get your code working, make a new memory instance for every block, as shown:
static class WorldGeneration
{
public static void GenerateWorld(World world, Block dirtBlock)
{
for (int x = 0; x < world.Length; x++)
{
for (int y = 0; y < world.Height; y++)
{
world.blocks[x, y] = new Block(dirtBlock.Texture, new Vector2(x * 16, y * 16));
}
}
}
}
Alternatively, you can keep the world generation code unchanged, and have the Block as a struct instead of a class, and that will work just as you expect.
struct Block
{
....// Rest of the code unchanged
}
This will work because now Block is a value type, and on each assignment, a new instance is automatically created.
I recommend you to give this article a read for some more info on value and reference types in C# if this is a new topic for you. You only need to read up to the first 3 headings ("Introduction", "First, What Are Structs?", "Value and Reference Types").
where should I insert Graphics it to make the game work???
I want to develop a multithreaded application that simulates the movement of billiard balls on a gaming table. The behavior of each ball (i.e. calculating new coordinates and redrawing) is programmed as a separate thread. The usual physical laws apply on the game table - balls bounce off the walls and corners of the table so that the angle of incidence is equal to the angle of reflection, the only exception for this problem is the absence of interactions between the balls (i.e., simply put, they do not collide).
When starting the simulation process, each ball receives some (random) impulse, under the influence of which it moves by inertia, gradually stopping. When the ball stops, the corresponding flow should end. The application
makes sure that there is at least one thread that has not finished its work yet. When all the threads are completed, you need to issue the appropriate message. The program should provide the user with the ability to pause/continue or interrupt the motion simulation process.
To do this, I created everything that is above, and then I don't understand where to move a little
public partial class Form1 : Form
{
private List<Circle> circles = new List<Circle>();
private List<Thread> threads = new List<Thread>();
private bool pause = false;
public Form1()
{
InitializeComponent();
}
public void AddCircle()
{
Circle circle = new Circle();
circles.Add(circle);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
pause = !pause;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = CreateGraphics();
g.Clear(Color.White);
foreach (Circle circle in circles)
g.FillEllipse(new SolidBrush(circle.color), circle.X, circle.Y, circle.Weidth, circle.Heidth);
}
private void Form1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(t =>
{
AddCircle();
Thread.Sleep(30);
})
{ IsBackground = true };
threads.Add(thread);
thread.Start();
}
}
}
this is my class circle
public class Circle
{
public float x;
public float y;
public float heidth;
public float weidth;
public float dy;
public float dx;
public Color color;
public List<Color> colors = (new Color[] { Color.Pink, Color.Red, Color.Brown, Color.Black }).ToList();
public float X
{
set { x = value; }
get { return x; }
}
public float Y
{
set { y = value; }
get { return y; }
}
public float Heidth
{
set { heidth = value; }
get { return heidth; }
}
public float Weidth
{
set { weidth = value; }
get { return weidth; }
}
public float Dy
{
set { dy = value; }
get { return dy; }
}
public float Dx
{
set { dx = value; }
get { return dx; }
}
public Color Color
{
set { color = value; }
get { return color; }
}
public Circle()
{
Random random = new Random();
x = random.Next(10, 600);
y = random.Next(10, 500);
color = colors[random.Next(colors.Count)];
weidth = 10;
heidth = 10;
dx = random.Next(-50, 50);
dy = random.Next(-50, 50);
}
}
}
I can’t realize the possibility of continuing the game after a collision. The snake should stop and start moving after clicking on one of the arrow buttons.
In a collision, a window appears about the loss, I need to continue the game.
I press the button and the following happens:
I don’t understand how I can save the coordinates of the snake just before the collision.
In the moveTimer_Tick method, all elements move, i.e. new coordinates have already appeared at the head and body, then there is a check for collisions with the wall and body. If they are found, a window appears about the loss.
New snake coordinates are not displayed. But after clicking the "Continue" button, an update occurs and the snake climbs to the border.
The question is: how can I save the coordinates of the snake, before the collision, and after continuing to start with them.
namespace Snake{
public partial class MainWindow : Window
{
//The field on which the snake lives
Entity field;
// snake head
Head head;
// whole snake
List<PositionedEntity> snake;
// apple
Apple apple;
//number of points
int score;
// Is movement paused
bool paused;
//time
DispatcherTimer moveTimer;
//constructor form
public MainWindow()
{
InitializeComponent();
snake = new List<PositionedEntity>();
//create field 600x600pixels
field = new Entity(600, 600, "pack://application:,,,/Resources/snake.png");
//create a timer that runs every 300 ms
moveTimer = new DispatcherTimer();
moveTimer.Interval = new TimeSpan(0, 0, 0, 0, 300);
moveTimer.Tick += new EventHandler(moveTimer_Tick);
}
//redraw screen method
private void UpdateField()
{
//update the position of the elements of the snake
foreach (var p in snake)
{
Canvas.SetTop(p.image, p.y);
Canvas.SetLeft(p.image, p.x);
}
//update the position of apple
Canvas.SetTop(apple.image, apple.y);
Canvas.SetLeft(apple.image, apple.x);
//points update
lblScore.Content = String.Format("{0}000", score);
}
//timer tick handler. All movement takes place here.
void moveTimer_Tick(object sender, EventArgs e)
{
// Do not update if movement is paused
if(paused) {
return;
}
//in the reverse order we move all the elements of the snake
foreach (var p in Enumerable.Reverse(snake))
{
p.move();
}
//we check that the head of the snake did not crash into the body
foreach (var p in snake.Where(x => x != head))
{
if (p.x == head.x && p.y == head.y)
{
//we lose
moveTimer.Stop();
GameOver.Visibility = Visibility.Visible;
btnRestart.Visibility = Visibility.Visible;
tbScore.Text = String.Format("SCORE: {0}000", score);
return;
}
}
//check that the head of the snake did not go out of the field
if (head.x < 40 || head.x >= 540 || head.y < 40 || head.y >= 540)
{
//we lose
moveTimer.Stop();
GameOver.Visibility = Visibility.Visible;
btnRestart.Visibility = Visibility.Visible;
tbScore.Text = String.Format("SCORE: {0}000", score);
return;
}
//check that the head of the snake crashed into an apple
if (head.x == apple.x && head.y == apple.y)
{
//increase the score
score++;
//move the apple to a new place
apple.move();
var part = new BodyPart(snake.Last());
canvas1.Children.Add(part.image);
snake.Add(part);
}
UpdateField();
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
// Unpause movement when any key is pressed
if(paused) {
paused = false;
}
switch (e.Key)
{
case Key.Up:
head.direction = Head.Direction.UP;
break;
case Key.Down:
head.direction = Head.Direction.DOWN;
break;
case Key.Left:
head.direction = Head.Direction.LEFT;
break;
case Key.Right:
head.direction = Head.Direction.RIGHT;
break;
}
}
// "Start"
private void button1_Click(object sender, RoutedEventArgs e)
{
btnStart.Visibility = Visibility.Hidden;
btnRestart.Visibility = Visibility.Hidden;
tBNotEnoughPoints.Visibility = Visibility.Hidden;
score = 0;
snake.Clear();
canvas1.Children.Clear();
// "Game Over"
GameOver.Visibility = Visibility.Hidden;
canvas1.Children.Add(field.image);
apple = new Apple(snake);
canvas1.Children.Add(apple.image);
head = new Head();
snake.Add(head);
canvas1.Children.Add(head.image);
moveTimer.Start();
UpdateField();
}
private void btnContinue_Click(object sender, RoutedEventArgs e)
{
if (score >= 2)
{
GameOver.Visibility = Visibility.Hidden;
btnRestart.Visibility = Visibility.Hidden;
score -= 2;
// Pause movement
paused = true;
moveTimer.Start();
UpdateField();
}
else
{
tBNotEnoughPoints.Visibility = Visibility.Visible;
}
}
public class Entity
{
protected int m_width;
protected int m_height;
Image m_image;
public Entity(int w, int h, string image)
{
m_width = w;
m_height = h;
m_image = new Image();
m_image.Source = (new ImageSourceConverter()).ConvertFromString(image) as ImageSource;
m_image.Width = w;
m_image.Height = h;
}
public Image image
{
get
{
return m_image;
}
}
}
public class PositionedEntity : Entity
{
protected int m_x;
protected int m_y;
public PositionedEntity(int x, int y, int w, int h, string image)
: base(w, h, image)
{
m_x = x;
m_y = y;
}
public virtual void move() { }
public int x
{
get
{
return m_x;
}
set
{
m_x = value;
}
}
public int y
{
get
{
return m_y;
}
set
{
m_y = value;
}
}
}
public class Apple : PositionedEntity
{
List<PositionedEntity> m_snake;
public Apple(List<PositionedEntity> s)
: base(0, 0, 40, 40, "pack://application:,,,/Resources/fruit.png")
{
m_snake = s;
move();
}
public override void move()
{
Random rand = new Random();
do
{
x = rand.Next(13) * 40 + 40 ;
y = rand.Next(13) * 40 + 40 ;
bool overlap = false;
foreach (var p in m_snake)
{
if (p.x == x && p.y == y)
{
overlap = true;
break;
}
}
if (!overlap)
break;
} while (true);
}
}
public class Head : PositionedEntity
{
public enum Direction
{
RIGHT, DOWN, LEFT, UP, NONE
};
Direction m_direction;
public Direction direction {
set
{
m_direction = value;
RotateTransform rotateTransform = new RotateTransform(90 * (int)value);
image.RenderTransform = rotateTransform;
}
}
public Head()
: base(280, 280, 40, 40, "pack://application:,,,/Resources/head.png")
{
image.RenderTransformOrigin = new Point(0.5, 0.5);
m_direction = Direction.NONE;
}
public override void move()
{
switch (m_direction)
{
case Direction.DOWN:
y += 40;
break;
case Direction.UP:
y -= 40;
break;
case Direction.LEFT:
x -= 40;
break;
case Direction.RIGHT:
x += 40;
break;
}
}
}
public class BodyPart : PositionedEntity
{
PositionedEntity m_next;
public BodyPart(PositionedEntity next)
: base(next.x, next.y, 40, 40, "pack://application:,,,/Resources/body.png")
{
m_next = next;
}
public override void move()
{
x = m_next.x;
y = m_next.y;
}
}
}
}
There is something to say about the design of your code, but if you don't care and you want a fast (and ugly) solution you can modify your PositionEntity in order to store old coordinates:
public class PositionedEntity : Entity
{
protected int m_x;
protected int m_y;
protected int m_oldX;
protected int m_oldY;
public PositionedEntity(int x, int y, int w, int h, string image)
: base(w, h, image)
{
m_x = x;
m_y = y;
m_oldX = x;
m_oldY = y;
}
public virtual void move() { }
public virtual void RestorePrevious()
{
m_x = m_oldX;
m_y = m_oldY;
}
public int x
{
get
{
return m_x;
}
set
{
m_oldX = m_x;
m_x = value;
}
}
public int y
{
get
{
return m_y;
}
set
{
m_oldY = m_y;
m_y = value;
}
}
}
When you have a collision you should call the RestorePrevious() on the head and on all the rest of the snake
I'm trying to make a game in which I use a statemachine.
The "GameState" creates the world (on entering) by calling getInstance() from the "World" class which is a singleton.
The World singleton has a 2D List with "Tile" objects (the world is made out of tiles). In the constructor of the World class the list is filled by a nested for loop which uses the SimpleTileFactory class to create tiles and puts them in the list.
Problem is that I get a StackOverflow. I debugged the code and found that the constructor of the World singleton is called more than once, which is probably causing the stack overflow. I can't find out why it's called more than once though and have the feeling I'm overlooking something simple. Is my singleton correct?
The Code is below.
Thanks in advance.
GameState Class
public partial class GameState : UserControl, IState<MainView>
{
private bool ready = false;
public GameState()
{
InitializeComponent();
}
public void enter(MainView owner)
{
this.Width = owner.Width;
this.Height = owner.Height;
this.Location = new Point(0, 0);
owner.Controls.Add(this);
World.getInstance();
this.ready = true;
}
public void update(MainView owner)
{
this.Refresh();
}
public void exit(MainView owner)
{
owner.Controls.Remove(this);
}
public bool isReady()
{
return this.ready;
}
private void GameState_Paint(object sender, PaintEventArgs e)
{
//for (int i = 0; i < World.getInstance().tiles.Count; i++)
//{
// for (int j = 0; j < World.getInstance().tiles[0].Count; j++)
// {
// //e.Graphics.DrawImage(new Image(), new Rectangle());
// }
//}
}
}
World Class
class World
{
private static World instance;
public GameResources gameResources;
public SimpleTileFactory tileFactory;
public List<List<Tile>> tiles = new List<List<Tile>>();
public Size worldSize = new Size(100, 100);
private World()
{
this.gameResources = new GameResources();
this.tileFactory = new SimpleTileFactory();
for (int i = 0; i < worldSize.Height; i++)
{
List<Tile> row = new List<Tile>();
for (int j = 0; j < worldSize.Width; j++)
{
row.Add(tileFactory.createTile(new Point(j, i)));
}
}
}
public static World getInstance()
{
if (instance == null)
{
instance = new World();
}
return instance;
}
}
SimpleTileFactory Class
class SimpleTileFactory
{
public SimpleResourceFactory resourceFactory = new SimpleResourceFactory();
private Random random = new Random();
private int maxNumOfResourcesPerTile = 5;
public SimpleTileFactory()
{
}
public Tile createTile(Point location)
{
//create tile
Tile tile = new Tile();
tile.location = location;
//give tile terrain type
Terrain terrain = new Terrain();
terrain.type = random.Next(0, World.getInstance().gameResources.terrainNames.Count);
terrain.name = World.getInstance().gameResources.terrainNames[terrain.type];
terrain.accessability = 1000;
//add resources to terrain
int numberOfResources = random.Next(0, maxNumOfResourcesPerTile + 1);
for (int i = 0; i < numberOfResources; i++)
{
terrain.resources.Add(resourceFactory.createTerrainResource(terrain.type));
}
tile.terrain = terrain;
return tile;
}
}
SimpleResourceFactory Class
class SimpleResourceFactory
{
public List<string> resourceNames = new List<string>();
public List<Image> resourceImages = new List<Image>();
private Random random = new Random();
public SimpleResourceFactory()
{
resourceNames.Add("asdfasfd");
resourceNames.Add("asdfasfd");
resourceNames.Add("asdfasfd");
}
public TerrainResource createTerrainResource(int terrainType)
{
TerrainResource resource = new TerrainResource();
resource.type = random.Next(0, resourceNames.Count);
resource.name = this.resourceNames[resource.type];
resource.amount = 100;
return resource;
}
}
Tile Class
class Tile
{
public Point location;
public Terrain terrain;
public Tile()
{
}
}
Terrain Class
class Terrain
{
public int type;
public string name;
public int accessability;
public List<TerrainResource> resources = new List<TerrainResource>();
public Terrain()
{
}
}
TerrainResource Class
class TerrainResource
{
public int type;
public string name;
public int amount;
public TerrainResource()
{
}
}
createTile is calling getInstance, and causing the overflow:
WpfApplication2.exe!WpfApplication2.SimpleResourceFactory.SimpleResourceFactory() Line 116 C#
WpfApplication2.exe!WpfApplication2.SimpleTileFactory.SimpleTileFactory() Line 76 C#
WpfApplication2.exe!WpfApplication2.World.World() Line 49 C#
WpfApplication2.exe!WpfApplication2.World.getInstance() Line 66 C#
WpfApplication2.exe!WpfApplication2.SimpleTileFactory.createTile(System.Windows.Point location) Line 95 C#
WpfApplication2.exe!WpfApplication2.World.World() Line 56 C#
WpfApplication2.exe!WpfApplication2.World.getInstance() Line 66 C#
WpfApplication2.exe!WpfApplication2.SimpleTileFactory.createTile(System.Windows.Point location) Line 95 C#
WpfApplication2.exe!WpfApplication2.World.World() Line 56 C#
WpfApplication2.exe!WpfApplication2.World.getInstance() Line 66 C#
WpfApplication2.exe!WpfApplication2.SimpleTileFactory.createTile(System.Windows.Point location) Line 95 C#
The problem was that createTile() was called within the World constructor. This way the World object isn't fully created yet when createTile() is executed which will then call getInstance() which in it's turn creates a new World (because it wasn't fully created yet) which calls createTile() again. It's an infinite loop.
I did a quick fix to check it by changing the World constructor and createTile() code as can be seen below. This is not the most beautiful way to solve it, so I'll probably just seperate GameResources from World.
private World()
{
this.gameResources = new GameResources();
this.tileFactory = new SimpleTileFactory();
for (int i = 0; i < this.worldSize.Height; i++)
{
List<Tile> row = new List<Tile>();
for (int j = 0; j < this.worldSize.Width; j++)
{
row.Add(tileFactory.createTile(new Point(j, i), this));
}
this.tiles.Add(row);
}
}
And the createTile method:
public Tile createTile(Point location, World world)
{
//create tile
Tile tile = new Tile();
tile.location = location;
//give tile terrain type
Terrain terrain = new Terrain();
terrain.type = random.Next(0, world.gameResources.terrainNames.Count);
terrain.name = world.gameResources.terrainNames[terrain.type];
terrain.accessability = 1000;
//add resources to terrain
int numberOfResources = random.Next(0, maxNumOfResourcesPerTile + 1);
for (int i = 0; i < numberOfResources; i++)
{
terrain.resources.Add(resourceFactory.createTerrainResource(terrain.type));
}
tile.terrain = terrain;
return tile;
}
I am only learning C# and I am trying to make a 2D game. I am at the stage where I have my Form1 set up with a 'PictureBox' for the player and the start of a player class:
class Player
{
private string _name;
private int _health;
internal Player(string name, int health = 100)
{
_name = name;
_health = health;
}
int X = 0;
internal void Draw()
{
updateInput();
Draw();
}
internal void updateInput()
{
if(Keyboard.IsKeyDown(Key.Right))
X = 1;
else if (Keyboard.IsKeyDown(Key.Left))
X = -1;
else
X = 0;
}
}
There is a PictureBox "pb_play" which contains the character's sprite on the main form. I tried setting its access modifier to public but that did not help. I want to change the position of the character by whatever the X value becomes. So I was trying to essentially access that member of the form the class.
I was attempting to do this inside the draw method, so it would update the input, then after that it would set the position, and then repeat the Draw method, looping constantly.
If there is a better way though, feel free to educate me. How can I fix this?
EDIT: Okay, I moved the methods into the UI, as mentioned by a comment. Here is what I have, but the sprite refuses to move:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Draw();
}
int X = 0;
internal void Draw()
{
updateInput();
pb_play.Location = new Point((pb_play.Location.X + X), 0);
Draw();
}
internal void updateInput()
{
if (Keyboard.IsKeyDown(Key.Right))
X = 5;
else if (Keyboard.IsKeyDown(Key.Left))
X = -5;
else
X = 0;
}
}
I used a timer to fix the issue:
internal void Draw()
{
pb_play.Location = new Point((pb_play.Location.X + X), (pb_play.Location.Y + Y));
}
internal void updateInput()
{
if (Keyboard.IsKeyDown(Key.Right))
X = 1;
else if (Keyboard.IsKeyDown(Key.Left))
X = -1;
else
X = 0;
if (Keyboard.IsKeyDown(Key.Up))
Y = -1;
else if (Keyboard.IsKeyDown(Key.Down))
Y = 1;
else
Y = 0;
}
private void timer1_Tick(object sender, EventArgs e)
{
updateInput();
Draw();
}