I am pretty new at C# and I wanted to make a simple 2D RPG (Role-Playing-Game) character which can move around with its walking animation by simply using 'W' 'A' 'S' 'D' keywords. To do that, I used Picture Box to hold character image and 2 Timers Tool, one for managing the 'walking' animation by changing the picture every 100 ms, and the another timer is for moving that Picture Box location every 1 ms.
In the 'Form_KeyDown' event, I set those 2 timers Enabled = True whenever user presses one of the moving keywords and I set those 2 timers Enabled = False in the 'Form_KeyUp' event to indicate that the character is no longer moving.
Here is the first timer code that control the animation by changing the picture on each tick:
private void timerchangepic_Tick(object sender, EventArgs e)
{
//movementPhase will determine the picture to be displayed, added by 1
//every tick means character image change every tick
movementPhase++;
if (movementPhase > 4) movementPhase = 1;
//determining which image is currently displayed
if (charDirection == Direction.Front)
{
if (movementPhase == 1)
pbcharacter.BackgroundImage = Image.FromFile("Icon\\front.png");
else if (movementPhase == 2)
pbcharacter.BackgroundImage = Image.FromFile("Icon\\front2.png");
else if (movementPhase == 3)
pbcharacter.BackgroundImage = Image.FromFile("Icon\\front3.png");
else if (movementPhase == 4)
pbcharacter.BackgroundImage = Image.FromFile("Icon\\front4.png");
}
//and goes the same for another 3 directions (left, right, and back)
}
Here is the second timer code that move the location of the character on each tick:
private void timermovement_Tick(object sender, EventArgs e)
{
if (charDirection == Direction.Front)
{
pbcharacter.Location = new Point(pbcharacter.Location.X, pbcharacter.Location.Y + 5);
}
//and goes the same for another 3 directions (left, right, and back)
}
My problem is: the character can't move well when I hold one of the moving keystroke. In a first second it works fine, but after a few second (2-3 seconds) pressing and holding 'S' stroke made the character stopped, moved a little, stopped again, moved a little and over and over. Besides, the animation only worked for 1 lap, the picture changed from 'front' to 'front2' until 'front4' well, but not from 'front4' back to 'front'. In conclusion, the character's animation only ran for 1 shift, then it became a static image which moved a little, stopped, moved again, and stopped again whenever i hold 'S' button.
What is wrong with my codes? Are there any better approaches to implement a moving 2D character task with its animation?
I suggest you to use somethimg more specific to build your application: XNA, MonoGame or Unity3D. But if you are using winforms I have several suggestion for you:
1) Cache images instead load them from file every time.
2) Cause Timer Events interval is not very accurate calculate ElapsedTime from last event. And make change +5 to something dependent of ElapsedTime.
3) Instead using several timers organize game loop to handle your events.
4) Use Double Buffer on your form.
Building a game using windows forms can be incredible hard, and also extremely inefficient. If you were to use XNA, which isn't that difficult to learn, you could create a much better and much stronger game.
If your using WinForms i will presume your a beginner so I wouldn't bother with unity or mono as they are much more complicated. If you still reject this I would advise you to:
Cache images
more accurately calculate ElapsedTime and use dependencies
use a while loop to repeat for each tick, this point should fix your problem
Hope to have been of help.
I think if you must make your game using windows form then you need to
at least handle your update with a gameloop instead of form timers and
if your moving things around your going to need some kind of clock to
help your game run at the same speed on any cpu
Related
I want to set the animation frame without playing it currently i am doing this it work perfectly but can i make it possible without playing the animation?
GO.GetComponent<Animation>().Play("Start");
GO.GetComponent<Animation>()["Start"].time = ((1f / 30f) * 0);
GO.GetComponent<Animation>()["Start"].speed = 0;
My advice would be to create a new state that simply contain that one frame.
It is counter-intuitive to think of a state that is stuck on its first frame. It is like saying you are int eating state but only holding the fork without any movement. Something is not quite right in that statement.
So you'd rather have a Immobile state and then run it in loop. When you need to start doing other actions, then just switch as would.
Now if you want to start an animation at a specific position:
animator.Play("AnimName",layer, normPosition);
I am making the character run but the animation is extremely quick as I am doing:
_frameIndex++;
_frameIndex; is the value which points to the image in the SpriteSheet. Does anyone know how I can use gameTime.ElapsedGameTime.TotalMilliseconds to slow the animation down?
I saw that you've asked a couple of questions tonight concerning animation and spritesheets, so here's an example from Aaron Reed's "Learning XNA 4.0," from Chapter 3 under the "Adjusting the Animation Speed" heading.
First, create two class-level variables to track time between animation frames:
int timeSinceLastFrame = 0;
int millisecondsPerFrame = 50;
The first variable tracks time passed since the animation frame was changed, and the second is an arbitrary amount of time that you specify to wait before moving the frame index again. So making millisecondsPerFrame smaller will increase the animation speed, and making it larger will decrease the animation speed.
Now, in your update method, you can take advantage of game.ElapsedGameTime to check time passed since the last frame change, and change the frame when when that value greater than millisecondsPerFrame, you can do work:
timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
if (timeSinceLastFrame > millisecondsPerFrame){
timeSinceLastFrame -= millisecondsPerFrame;
// Increment Current Frame here (See link for implementation)
}
This sort of solution is similar to what you've found works, except that you can take an extra step to specify exactly how often you want the animation to update, or even change that duration later on in your code if you like. For example, if have some condition that would "speed up" the sprite (like a power-up) or likewise slow it down, you could do so by changing millisecondsPerFrame.
I removed the code that actually updates the current frame, since you should already have something that does that since you have a working animation. If you'd like to see the example in-full, you can download it from the textbook's website.
I debugged the code and noticed that the gameTime.ElapsedGameTime.TotalMilliseconds always equated to 33. So I did the following:
milliSeconds += gameTime.ElapsedGameTime.Milliseconds;
if (milliSeconds > 99)
{
_frameIndex++;
milliSeconds = 0;
}
Which basically means that if this is the THIRD frame of the game, then make he _frameIndex go up. Reset the milliseconds to start over.
I'm making a side-scrolling Mega Man based game in C#. I am NOT using the XNA frame work to do so. I'm looking at creating multiple "bullets" from one location using one single image within my game class. The only thing I can think of at this point is something similar to this:
if (shooting == true)
{
BulletLocation.X += 3.0F;
Bullet = Properties.Resources.Bullet;
Charecter = Properties.Resources.shooting;
}
Shooting is set true on the keyDown event, and set to false on the keyUp event. I'm positive i would need an array of the sorts, but I'm not sure exactly how I should go about it. Thanks for your help!
EDIT:
What portion of that code would actually allow you to generate multiple "bullets" from one sprite single sprite? When the user presses the space bar, I would like to create a bullet that moves forward until it reaches the end of the screen. I can do that part easily. I cannot, however, do it with multiple bullets. I can only have one bullet alive at a time. I'm not sure how I would go about creating multiple bullets on the forum from one single image.
If I understand it correctly, you want to show multiple bullets, right?
I would make a variable for # of bullets and bulletposition.
So lets say:
const DISTBETWEENBULLETS = 3.0;
int distToOpponent = 9.0:
int curBulletDist = 0;
do{
curBulletDist += DISTBETWEENBULLETS;
//Draw bullet
}while(distToOpponent <= curBulletDist);
I hope this helps, and if it doesn't answer your question, or you mean something else, feel free to ask.
My update function gets called like 60 times a second, and the player is meant to move in 32 pixel steps on my grid, so the player moves very quickly, i want a way to only recieve certain key inputs every like 10 frames, and still have my game run at 60fps.
You can
require user to do full keyboard clicks with releasing each key
have user's position to be sort-of float instead of int where whole part represents grid steps. While user tries to move in particular direction it will move with some defined speed (like 2 per sec) and when float position becomes next cell player jumps
you can require player to stay in particular cell some given amount of time (like .5 seconds) - thus definind speed how fast it moves.
The easiest way is to keep time on when a key was pressed. There isn't a way to slow down the speed of the input system, so you have to fake it yourself. Here is some pseudocode to get you started.
// See if the key is currently down
if (KeyIsDown(key))
{
if (gameTime.TotalGameTime >= nextTime)
{
// Move the character, and indicate that you want to wait another second for movement.
moveTheCharacter();
nextTime = gameTime.TotalGameTime + 1;
}
}
The main advantage of this approach is that it will always be based on time as opposed to the framerate of your game. So if you drop frames for some reason your character will still move at the same speed.
I want to create a simple game like tic tac toe where the human user is playing against the computer. The computer function takes a couple of milliseconds to run but I would like to give the perception of the computer taking 5 seconds to make a move. Which method should I use?
1) Create two memory threads. One for the computer and one for the human user. When the computer is taking 5 seconds to imitate thinking, the human user thread is paused for 5 seconds.
2) Disable input devices for 5 seconds using timer or dispatchertimer
3) Any better methods you can think of..
Thanks!
Edit - The question is about the how and now the why. 5 seconds is just an example. I prefer 1-2 seconds but for example purposes I just chose 5. So please focus on what is the best way to do this and not on the 5 seconds. Thanks again.
Noise and Blinking lights = digital thought.
Rev up the CPU to 100% with an infinite loop to generate heat.
Start looping through all the files to get the hard drive light blinking and making spinning noises.
Run a shell command to change directory to the optical drive to make the optical drive spin.
Set caps lock, numlock and scroll lock on and off, some keyboards have lights for that.
Check to see if your motherboard supports any additional blinking lights.
Ah! Good point. Many fans have API access, so turning the fans on to 100% is cool. The revert to normal could be dangerous though, because if you accidentally turn off the fans for good, it could be serious damage.
you could just make the cursor into an hourglass and disable the main form (which will stop the user from inputting anything), start a timer for 5 secs (i'd make this time configurable), when the timer fires enable the main form and set the cursor back to normal again. Something like this:
Call this method when the user has made their move:
private void UserHasMoved()
{
Enabled = false;
timer1.Interval = 5000;
timer1.Start ();
}
then the event for the timer:
private void timer1_Tick(object sender, EventArgs e)
{
Enabled = true;
timer1.Stop ();
}
wouldn't this be annoying to the faster players? Maybe a second for the turn, but you'll soon find out that 5 seconds is too much.
Either way, do not pause the UI thread, because the interface would 'freeze'.
Because the human is using the GUI as its interface, you can't pause its thread. Pausing the GUI thread would disable your form from repainting, thus not showing the computer's move.
I'd just disable all game related input, and show an animation of the computer working its brain.
Two very important usability principles:
Don't block the UI thread! Only disable the game control so that the player cannot perform a step during the thinking.
Show a visual feedback to the user indicating the thinking and that he can't perform the step for a while.
And of course, balance the exact duration of thinking carefully. Treat the players' time as very precious.
From your question it seems you do not want the computer play to be so lightning fast that the human player can't see it. For that effect, why don't you display some random animation showing possible plays, and ultimately animating the chosen move.
Edit: I have to agree that disabling input devices is a bit harsh. Maybe switch the application to a state in which any input by the user cannot affect the board, but can affect other commands, such as save, restart or quit.