All three of my screen/states works fine, however, i implemented a fourth one to act as an information screen. Fine so far, but when i run the game, and press the 'H' key, it doesn't change the screen to another background (what I have done so far). Below is the code:
public void UpdateInformation(GameTime currentTime)
{
if (Keyboard.GetState().IsKeyDown(Keys.H))
{
GameState = 4;
} // GAMESTATE 4 which is the instruction/Information screen.
}
This is the code for the game state in the update method:
protected override void Update(GameTime gameTime)
{
switch (GameState)
{
case 1: UpdateStarted(gameTime);
break;
case 2: UpdatePlaying(gameTime);
break;
case 3: UpdateEnded(gameTime);
break;
case 4: UpdateInformation(gameTime);
break;
}
base.Update(gameTime);
}
Here i am drawing the screen.
public void DrawInformation(GameTime currentTime)
{
spriteBatch.Begin();
spriteBatch.Draw(InfoBackground, Vector2.Zero, Color.White);
spriteBatch.End();
}
Below is the draw information code for the states:
protected override void Draw(GameTime gameTime)
{
switch (GameState)
{
case 1: DrawStarted(gameTime);
break;
case 2: DrawPlaying(gameTime);
break;
case 3: DrawEnded(gameTime);
break;
case 4: DrawInformation(gameTime);
break;
}
}
I hope this helps, it's just my H key is not responding, but my S key responds well and starts the game. Are four state/screens compatible with 'Gamestate'?
Thank you.
The H key will not work, because your Update code for the H key is in UpdateInformation...
What it actually does is: If you're in the Information screen, press H to go to the Information screen (which doesn't make sense)
You should move your H detection code somewhere more appropriate. Where is your S detection code?
Also, I would recommend using an enum instead of numbers for your game states.
enum gameStates
{
Started,
Playing,
Ended,
Information,
}
That way, it's much easier to maintain and understand. (See example below)
switch(GameState)
{
case gameStates.Started:
//Do something
break;
}
Related
I've been trying to create a game where once you hit the 'repeat' symbol you have to return to the position of the first repeat symbol i.e
once the player hits the "end-repeat sign" they'll return to the "begin-repeat sign" but only once then they'll continue the level, but for some reason the game won't register the symbols even when a rigidbody is added
void OnCollisionEnter(Collision collision){
if(state != State.alive || collisionsDisabled){ return; }
switch(collision.gameObject.tag){
case "Win":
print("win");
StartSucessSequence();
break;
case "Lose":
StartDeathSequence();
break;
case "StartRepeat":
print("touched");
OnTriggerEnter(other);
break;
default:
StartDeathSequence();
break;
}
}
void OnTriggerEnter(Collider other){
// if startrepeat is touched go to endrepeat
//for only once
StartRepeat = GameObject.FindWithTag("StartRepeat");
EndRepeat = GameObject.FindWithTag("EndRepeat");
for (int i = 0; i < 1; i++){
if(other.gameObject.tag == "StartRepeat") {
other.transform.position = EndRepeat.transform.position;
other.transform.rotation = EndRepeat.transform.rotation;
}
}
}
my "Lose" tag is working perfectly, but not my "Win" or "StartRepeat"
I was thinking perhaps it's an issue with the Z-axis cause everything else is similar to the obstacle ("Lose" - which is the red notes)
if anything else is needed please tell me
First of all if you want to use a 2d rigidbody change your OnCollision and OnTrigger to 2d , then i suggest that you don't call OnTrigger by your own and create another method that contains the OnTrigger Code and use that instead.
Basically, I have a list of enemy objects and timed events using gameTime.TotalGameTime.TotalSeconds. Every 0.1 seconds it calls upon a method to check for enemy spawns, and if we're at second 2.5 we add an enemy to the enemy list.
Now what happens is that keyboard input lags for a second, for example, if i'm moving continuously to the left, my character will stop for a short period (like 0.1 secs i think) before resuming moving.
I'm using gameTime to check for keyboard input every millisecond, but i've tried not using it too and it still happens. It's also weird because I have code that creates bullet objects every 0.5 seconds if i hold down Z the same way it does with enemies (through adding the object to a list), but that doesn't make it lagg the input
if (elapsedMs > oldElapsedMs + 0.001) //Millisecond update, for movement
{
oldElapsedMs = elapsedMs;
//Keys to be held down.
newState = Keyboard.GetState();
Keys[] pressed_Key = Keyboard.GetState().GetPressedKeys();
for (int i = 0; i < pressed_Key.Length; i++)
{
switch (pressed_Key[i])
{
case Keys.Escape:
this.Exit();
break;
case Keys.Left:
player.tryMoveLeft();
break;
case Keys.Right:
player.tryMoveRight();
break;
case Keys.Up:
player.tryMoveUp();
break;
case Keys.Down:
player.tryMoveDown();
break;
default:
break;
}
}
}
Spawn check code:
//0.1sec Update, spawning code
if (elapsedSpawnTime > oldElapsedSpawnTime + 0.1)
{
oldElapsedSpawnTime = elapsedSpawnTime;
spawnTimer += 1; //Every 0.1 sec add one to spawnTimer. The spawn timer int is what stage.Spawn() uses to check for spawns.
stage.Spawn();
}
my spawning method in my stage class:
public void Spawn()
{
switch (game.spawnTimer) //Each int is 0.1sec
{
//10 spawnTimer = 1 Second
case 40:
case 42:
case 44:
case 46:
game.enemyList.Add(new Enemy(game.enemySprite, 500, 500, 1, true));
break;
default:
break;
}
}
Thanks. If you want to help me but need more info you can add my skype # emil1000123
The code in the screenshot says
( elapsedMs > oldElapsedMs + 0.001 )
The variable names tell that those values are in milliseconds, so are you are checking every 0.001 milliseconds?
It seems that the issue lies in the millisecond update:
if (elapsedMs > oldElapsedMs + 0.001)
So, what happens if it gets at this statement, but havn't passed 1 millisecond yet?
A computer looks at code in ticks, those are way faster than milliseconds, and thus it'll ignore that statement at all, which can result in a tiny lag, depending on your PC's performance and file size (which will increase by adding arrays or lists)
Now, I don't know what you've used in the TryMoveLeft() (ect.) methodes. But I think you're better of my getting rid of the said if-statement. and try to rework the way how you player walks.
Maybe I might give a few tips if I can see how the player.TryMoveRight method looks like.
I'm creating a simple game, where whenever I leave the menu I want a 3 second timer to cover up the screen, while the game is paused. I had imagined I would do something like this
protected void Draw(GameTime gameTime)
{
//..//
for(int i = 3; i > 0; i--)
{
spriteBatch(gameFont, i.ToString(), new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2), Color.White);
Thread.Sleep(1000);
}
//..//
}
However, this just pauses at the menu for three seconds, then immediatly puts you in game. You can for a split second see a random number, but not at all a real countdown. What can I do to pause the games running and still draw the game?
Thread.Sleep(1000);
At the best of times you want to avoid using Thread.Sleep() and I can't think of any-time you should use it in a game. Games should be running flat-out and you want to minimise situations where the CPU is blocking or just sleeping.
What can I do to pause the games running and still draw the game?
Generally in games (and XNA is no exception), the draw code is separate from state update mechanics. This means your Draw() should be focused on drawing and nothing else.
Pausing can be considered a game state and is better served being processed in your game's Update().
Consider adding a state to your game, perhaps:
enum States
{
Initialising,
InMenu,
LeavingMenu,
InGame,
}
States _state;
Then in your Update() you could work on your state machine, switching from in-menu; to leaving menu; to finally in game:
DateTime timeOfEscPressed;
protected virtual void Update(GameTime gameTime)
{
switch (_state)
{
case States.Initialising:
break;
case States.InMenu:
// *** pseudo-code here ***
// if ESC pressed then
// _state = States.LeavingMenu
// timeOfEscPressed = DateTime.Now;
break;
case States.LeavingMenu:
// stay in this state for 3 seconds
if ((DateTime.Now - timeOfEscPressed).TotalSeconds >= 3)
{
_state = States.InGame;
}
break;
case States.InGame:
if (menuKeyPressed) // pseudo code
{
_state = States.InMenu;
timeOfEscPressed = DateTime.Now;
}
break;
}
}
Your draw code becomes just that, draw code:
protected void Draw(GameTime gameTime)
{
switch (_state)
{
case States.InMenu:
DrawMenu();
break;
case States.LeavingMenu:
ShowTimer();
break;
}
}
In this way, you gain the illusion of your game pausing but without freezing the update-draw loop.
I'am developing a Vuforia app that uses Virtual Buttons. I used the example of virtual buttons and I found this part on the script
public void OnButtonPressed(VirtualButtonBehaviour vb)
{
Debug.Log("OnButtonPressed");
if (!IsValid())
{
return;
}
// Add the material corresponding to this virtual button
// to the active material list:
switch (vb.VirtualButtonName)
{
case "red":
mActiveMaterials.Add(m_TeapotMaterials[0]);
break;
case "blue":
mActiveMaterials.Add(m_TeapotMaterials[1]);
break;
case "yellow":
mActiveMaterials.Add(m_TeapotMaterials[2]);
break;
case "green":
mActiveMaterials.Add(m_TeapotMaterials[3]);
break;
}
// Apply the new material:
if (mActiveMaterials.Count > 0)
mTeapot.renderer.material = mActiveMaterials[mActiveMaterials.Count - 1];
}
As is seen, I just must add the code at each case to 'do something'. Well, the thing I want to do is to change the color of an object.
The object is a fbx exported from Maya and has an animation. I want to change the color of a mesh inside the object.
The object is called "path", inside it has 3 meshes (polySurface1_MeshPart0, ..1, ..2), and each mesh has different materials corresponding to different parts of the mesh, they are materials without texture, just a solid color with shader diffuse.
I need to change the color of one of these materials in a specific mesh of the object :)
Any help is highly appreciated.
From the Unity3D Documentation: http://docs.unity3d.com/Documentation/ScriptReference/Material-color.html
You would need to either find the GameObjects at run time via GameObject.Find() or assign them to your scripts public members. Each mesh should be retrievable as a GameObject. Once you have reference to the GameObject in question you should be able to access it's material like so:
myGameObject.renderer.material.color = Color.Red;
An example using the code provided would be:
switch (vb.VirtualButtonName)
{
case "red":
mActiveMaterials.Add(m_TeapotMaterials[0]);
GameObject go = GameObject.Find("The Name Of The Object You Are Looking For");
go.renderer.material.color = Color.Red;
break;
}
First off, gameObject.renderer has been depreciated a long time ago, you should be using GetComponent() explicitly.
Secondly, you are adding to mActiveMaterials (which I assume to be a List or equivalent), but you don't seem to be clearing that list, whlist the code might work fine, you are creating a serious memory leak this way (unless you clear the list elsewhere)
Now, for each mesh renderer, there's two ways to access the material, theres Material[] materials, and material, which is effectively an equivalent of (with the omission of array boundary check and null checks)
material { get { return material[0]; } set {material[0]=value;}}
For meshes with only 1 sub-mesh, only material[0] is used, but for meshes with submaterials (it depends how models were imported, sometimes they get split into seperate single-material objects, and sometimes you get a single mesh with multiple materials).
Now I am not sure i understeand the reason behind adding a new material to the list, than only ever using the last material from the list (the list makes sense
if you are working with multiple sub-meshes)
I would suggest something along the lines of
void Start()
{
teapotRenderer=mTeapot.GetComponent<MeshRenderer>():
}
Material FindMaterial(string buttonName)
{
switch (buttonName)
{
case "red": return m_TeapotMaterials[0];
case "blue": return m_TeapotMaterials[1];
case "yellow": return m_TeapotMaterials[2];
case "green": return m_TeapotMaterials[3];
default: return mdefaultMaterial;
}
}
public void OnButtonPressed(VirtualButtonBehaviour vb)
{
mTeapotRenderer.material=FindMaterial(vb.VirtualButtonName);
}
I'm trying to make my first game, a console tetris.
I have a class Block, that contains x and y integers. Then I have a class Piece : List<Block>, and a class Pieces : List<Piece>.
I can already randomly generate pieces, and make them fall one row per second. I still didn't get to collisions detection, but I think that I already know how to work it out later.
The problem is that I don't know how to control the pieces. I've read a bit about keyboard hooking and checked some tetris tutorials, but most of them are for windows forms, which really simplifies events handling and the such.
So... Could you please point me the beginning of the path to controlling the pieces on a console? Thanks!
public class Program
{
static void Main(string[] args)
{
const int limite = 60;
Piezas listaDePiezas = new Piezas(); //list of pieces
bool gameOver = false;
Pieza pieza; //piece
Console.CursorVisible = false;
while (gameOver != true)
{
pieza = CrearPieza(); //Cretes a piece
if (HayColision(listaDePiezas, pieza) == true) //if there's a collition
{
gameOver = true;
break;
}
else
listaDePiezas.Add(pieza); //The piece is added to the list of pieces
while (true) //This is where the piece falls. I know that I shouldn't use a sleep. I'll take care of that later
{
Thread.Sleep(1000);
pieza.Bajar(); //Drop the piece one row.
Dibujar(listaDePiezas); //Redraws the gameplay enviroment.
}
}
}
What you are looking for is non-blocking console input.
Here is an example:
http://www.dutton.me.uk/2009/02/24/non-blocking-keyboard-input-in-c/
Basically, you would check Console.KeyAvailable in your while loop and then move the piece according to what key was pressed.
if (Console.KeyAvailable)
{
ConsoleKeyInfo cki = Console.ReadKey();
switch (cki.Key)
{
case ConsoleKey.UpArrow:
// not used in tetris game?
break;
case ConsoleKey.DownArrow:
// drop piece
break;
case ConsoleKey.LeftArrow:
// move piece left
break;
case ConsoleKey.RightArrow:
// move piece right
break;
}
}
You could use a Low-Level Keyboard Hook as shown here