Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
user
Tvůrce
Avatar
user:11.9.2012 20:54

Cus, zasek sem se u takovy hovadiny... :(
mám rectangle s černou barvou. A potřibuji ho "animovat". V časovém úseku budu postupně měnit jeho průhlednost tak, že vynásobím složku barvy float číslem od 0-1. Pokud přechod udělám z 1 (neprůhledný) do 0 (průhledný), vše funguje, ale v případě že přechod dělám z 0 do 1 tak mi rectangle jenom "problikne" tzn. rychle z 0 do 1 a pak zase do 0...
Přidám oba dva příklady:

Přechod průhlednosti z 1 do 0:
V tomto případě vše funguje bez problému. Animace proběhne v průběhu 3s:

Color color = Color.Black;
private float time = 3000f, timeCount = 3000f;

//Update:
double elapsed = gameTime.ElapsedGameTime.TotalMilliseconds;

color *= (float)((timeCount / time));
                timeCount -= (float)elapsed;

Přechod průhlednosti z 0 do 1:
Dělá problém, "problikne":

Color color = Color.Black;
private float time = 3000f, timeCount = 0f;

//Update:
double elapsed = gameTime.ElapsedGameTime.TotalMilliseconds;

color *= (float)((timeCount / time));
                timeCount += (float)elapsed;

Co dělám špatně?
Díky za pomoc.

Editováno 11.9.2012 20:57
 
Odpovědět
11.9.2012 20:54
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na user
David Hartinger:11.9.2012 22:27

Tohle jsem řešil takto:

if (!zamerovacZvyseni)
  zamerovacAlfa -= 0.02f;
else
  zamerovacAlfa += 0.02f;
if (zamerovacAlfa > 0.5)
  zamerovacZvyseni = false;
if (zamerovacAlfa < 0.2)
  zamerovacZvyseni = true;

Pulzuje mezi 0.2 a 0.5. Je to zbastlené, šlo by to lépe, ale zatím jsem to neřešil

Také se tě na něco zeptám, používáš GameComponents? Já jsem se na tom šíleně zasekl ;(

Nahoru Odpovědět
11.9.2012 22:27
You are the greatest project you will ever work on.
Avatar
user
Tvůrce
Avatar
user:12.9.2012 0:05
GameComponents:
----------------------
1. GameComponents:
metody volané automaticky: Initialize() a Upadate()

2.DrawableGameComponent:
autamaticky volané metody: vlastně všechny (tzn.: Initialize(), LoadContent(), UnloadContent(), Update(), Draw() )


Použití Components:

public class Trida: DrawableGameComponent
{
      public Trida(Game game)
         : base(game)
      {
      }

      protected override void Initialize()// přetížené metody "volané automaticky"
      {
           base.Initialize(); // v teto metode povine => vola se metoda LoadContent(), v ostatnich metodach jen pokud mas vnoreny Komponenty
      }
      protected override void LoadContent()
      {
           ...
      }

      protected override void UnloadContent()
      {
            ...

      }

      public override void Draw()
      {
        ...
      }

       atd...
}

Game1.cs:

protected override void Initialize()
{
     Trida trida = new Trida(this);
     Components.Add(trida); // Zaregistrovani komponenty
}

Snad to pomohlo :) ,myslim ze jsem na nic nezapomel...
Jinak diky za tip, uz jsem to nejak takto taky zkousel osetrit, v tom hlavni problem nebude... Asi budu mit nekde nejakou blbou chybku... zase do toho moc dlouho cumim :)

 
Nahoru Odpovědět
12.9.2012 0:05
Avatar
user
Tvůrce
Avatar
Odpovídá na user
user:12.9.2012 0:12

Jo a jeste musis mit v Game1.cs ve vsech metodach: base.NazavMetody(); napr:base.Ini­tialize();
Jinak se ti dana metoda na Komponente automaticky nezavola.

 
Nahoru Odpovědět
12.9.2012 0:12
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na user
David Hartinger:12.9.2012 11:23

Ahoj, jsem rád, že s tím také děláš :) Toto jsem ještě pochopil.

První problém je s tím, co je to komponenta. Po zběsilém hodinovém Googlení jsem zjistil, že MS asi nijak nedeklaruje, pro co by se komponenta měla použít, jen popisuje jak funguje. Ani nikde jinde jsem nenašel kloudné vysvětlení. Spokojil jsem se s tím, že komponenty budu používat pro všechno, co má nějakou logiku v update a vykreslování.

V mém Tetrisu jsou komponenty: Menu, Obrazovka autoři, Obrazovka HiScore, GamePlay, HraciPole, Kostka.

Problém mám hlavně s tím, jak do komponenty dostanu závislosti. V konstruktrou se předává objekt typu obecné Game. Tak si mohu vytvořit věci jako SpriteBatch a podobně, o tom žádná. Když ale 3 komponenty využívají tu samou texturu, nebudu ji přece 3x načítat v LoadContent, nějak ji předám.

Napadlo mě změnit konstruktor na:

public Trida(TetrisGame game) : base(game)
{
        this.game = game;
}

Potom budu vidět proměnné a metody mojí specifické hry, tam si mohu vystavit textury, případně metodu JdiDoMenu(), kterou když komponenta zavolá, hra ji zastaví a zapne komponentu menu.

V tutoriálu přímo od někoho z Microsoftu jsem viděl předání instance konkrétní hry přes statiku na té třídě, fuj :X

Editováno 12.9.2012 11:24
Nahoru Odpovědět
12.9.2012 11:23
You are the greatest project you will ever work on.
Avatar
user
Tvůrce
Avatar
user:12.9.2012 18:42

Ma hra bezi jen na jedne komponente ScreenManager, ta se stara o zobrazeni obrazovek (jako: MenuScreen, GamePlayScreen, HelpMenuScreen, GameOverScreen atp...), v ni pak volam na prislusnych mistech metody (Initialize(), LoadContent() atp...) obrazovky ktera je zrovna aktivni. Pak mam jeste abstraktni tridu GameScreen z ktere ostatni obrazovky dedi. Mohu zde i nacitat spolecny obsah. Pokud bych v nektere obrazovce zaregistroval dalsi komponentu, jeji metody by se volali jen pokud by byla obrazovka aktivni - zatim nevyzkouseno, ale melo by to tak byt.
Snad to neni vysvetleno moc abstraktne :)
Na zadny lepsi zpusob vyuziti komponent sem zatim neprisel.

Editováno 12.9.2012 18:45
 
Nahoru Odpovědět
12.9.2012 18:42
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na user
David Hartinger:12.9.2012 18:57

IMHO bys měl mít komponentu pro více věcí ve hře, často jsem vídával např. komponentu sprite, která měla texture, velocity, position, speed a tak dále. U hvězdné střílečky jsem viděl komponentu na pozadí, kde se vygenerovaly hvězdy, které potom jely různou rychlostí. Vše bylo zapouzdřené v komponentě, aby se to nemíchalo s další logikou hry. Jediný problém je ty komponenty nějak zmanažovat, povypínat ty které nepotřebuješ v dané obrazovce. Z toho co jsem viděl ale usuzuji, že v XNA prostě není dán jeden základní přístup, viděl jsem hodně bastlů, tak snad to nějak udělám :) Teď si od toho dávám pauzu, včera jsem do půlnoci komponentoval :D Rád sem potom dám svůj zdroják, co na to řekneš, jen nevím, kdy to konečně dodělám. Hra jako taková mi zabrala pár dní, ale architekturu již měním týden a stále se mi nelíbí.

Editováno 12.9.2012 18:58
Nahoru Odpovědět
12.9.2012 18:57
You are the greatest project you will ever work on.
Avatar
user
Tvůrce
Avatar
Odpovídá na David Hartinger
user:12.9.2012 19:25

Jo s architekturou s tebou plne souhlasim, s tou nebudu asi nikdy spokojeny, porad je co vylepsovat. Komponenty je urcite dobre pouzivat, vsude tam kde aspon trochu zprehledni kod, jen vim ze jsem s tim taky nekdy pred koncem prazdnin silene zapasil, moc jsem toho nevymyslel, tak jsem si dal pauzu as doted :D . Components pro zaregistrovani komponenty je obycejny List, mela by z nej jit komponenta odebrat, nevim, spise se ptam? Mas problem jen s architektonickym navrhem kodu, nebo i s "funkcnosti"?
Jinak se tesim na tvuj vytvor, jsem zvedav na vysledek.

 
Nahoru Odpovědět
12.9.2012 19:25
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na user
David Hartinger:12.9.2012 19:28

Funkční hru mám již týden, vůbec se nemění. Ale desítky hodin překopávám návrh :D Ono by to chtělo, aby každá obrazovka měla svůj seznam komponent a ty pak screenmanager vypnul, je tam nějaká vlastnost Enabled. Asi si taky udělám tu třídu GameScreen. Ta ti dědí z GameComponent, ne?

Nahoru Odpovědět
12.9.2012 19:28
You are the greatest project you will ever work on.
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na user
David Hartinger:12.9.2012 19:48

Úplně špatné není tohle, až na to příšernou statiku: http://blogs.microsoft.co.il/…14-last.aspx

Nahoru Odpovědět
12.9.2012 19:48
You are the greatest project you will ever work on.
Avatar
user
Tvůrce
Avatar
user:12.9.2012 20:11

"muj" GameScreen od zadne tridy nededi, neni to potreba (domnivam se :) ), obsahuje metody pro praci/manipulaci s obrazovkami a uchovava stav obrazovky.
jo diky za novy materialy, tohle sem jeste necetl :)

Editováno 12.9.2012 20:15
 
Nahoru Odpovědět
12.9.2012 20:11
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na user
David Hartinger:12.9.2012 20:29

A jak funguje? Pokud tam máš ty metody jako LoadContent, Initialize, Update atd, tak by to skoro měla být komponenta, ne? Můžeš sem hodit kód?

Nahoru Odpovědět
12.9.2012 20:29
You are the greatest project you will ever work on.
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na user
David Hartinger:12.9.2012 20:33

Já měl předtím hru složenou jen z tříd, co měly metodu draw a tam se předával spritebatch, ale chci to udělat celé z těch komponent.

Nahoru Odpovědět
12.9.2012 20:33
You are the greatest project you will ever work on.
Avatar
user
Tvůrce
Avatar
Odpovídá na David Hartinger
user:12.9.2012 21:01

ScreenManager:

public class ScreenManager : DrawableGameComponent
    {
        List<GameScreen> screens = new List<GameScreen>();
        List<GameScreen> currentScreens = new List<GameScreen>();

        InputState input = new InputState();
        ContentManager content;
        SpriteBatch spriteBatch;
        SpriteFont gameFont;
        public InputState Input
        {
            get { return input; }
        }
        public ContentManager Content
        {
            get { return content; }
        }
        public SpriteBatch SpriteBatch
        {
            get { return spriteBatch; }
        }

        public ScreenManager(Game game)
            : base(game)
        {
            content = new ContentManager(game.Services, "Content");
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }
        protected override void UnloadContent()
        {
            content.Unload();
        }
        public void Add(GameScreen screen)
        {
            screen.ScreenManager = this;
            screen.LoadContent();

            screens.Add(screen);
        }
        public void Remove(GameScreen screen)
        {
            screen.UnloadContent();
            screens.Remove(screen);
        }
        public override void Update(GameTime gameTime)
        {
            input.Update();

            currentScreens.Clear();

            foreach (GameScreen screen in screens)
                currentScreens.Add(screen);

            bool firstActiveScreen = true;

            while (currentScreens.Count > 0)
            {
                GameScreen screen = currentScreens[currentScreens.Count - 1];
                currentScreens.RemoveAt(currentScreens.Count - 1);

                if (screen.ScreenState == ScreenState.Inactive)
                    continue;

                if (screen.ScreenState == ScreenState.Active)
                {
                    if (firstActiveScreen)
                    {
                        screen.HandleInput();
                        firstActiveScreen = false;
                    }
                }

                screen.Update(gameTime);
            }
        }
        public override void Draw(GameTime gameTime)
        {
            currentScreens.Clear();

            foreach (GameScreen screen in screens)
                currentScreens.Add(screen);

            foreach (GameScreen screen in currentScreens)
            {
                if (screen.ScreenState == ScreenState.Inactive)
                    continue;
                else
                    screen.Draw(gameTime);
            }
        }
    }

GameScreen:

public enum ScreenState
{
    TransitionOn,
    TransitionOff,
    Active,
    Frozen,
    Inactive
}
public abstract class GameScreen
{
    public TimeSpan TransitionOnTime
    {
        get { return transitionOnTime; }
        protected set { transitionOnTime = value; }
    }
    TimeSpan transitionOnTime = TimeSpan.Zero;

    public TimeSpan TransitionOffTime
    {
        get { return transitionOffTime; }
        protected set { transitionOffTime = value; }
    }
    TimeSpan transitionOffTime = TimeSpan.Zero;

    public ScreenState ScreenState
    {
        get { return screenState; }
        set { screenState = value; }
    }
    ScreenState screenState = ScreenState.TransitionOn;

    public float TransitionPercent
    {
        get { return transitionPercent; }
    }
    float transitionPercent = 0.00f;

    public byte ScreenAlpha
    {
        get { return (byte)(transitionPercent * 255); }
    }

    public float TransitionSpeed
    {
        get { return transitionSpeed; }
    }
    float transitionSpeed = 2f;

    public int TransitionDirection
    {
        get { return transitionDirection; }
    }
    int transitionDirection = 1;

    public ScreenManager ScreenManager
    {
        get { return screenManager; }
        internal set { screenManager = value; }
    }
    ScreenManager screenManager;
    public virtual void LoadContent() { }

    public virtual void UnloadContent() { }

    public virtual void Update(GameTime gameTime)
    {
        if (screenState == ScreenState.TransitionOn)
        {
            if (transitionPercent >= 1)
            {
                screenState = ScreenState.Active;
                transitionDirection *= -1;
            }
            else
                ScreenTransition(gameTime, transitionOnTime, transitionDirection);
        }
        else if (screenState == ScreenState.TransitionOff)
        {
            if (transitionPercent <= 0)
            {
                RemoveScreen();
            }
            else
                ScreenTransition(gameTime, transitionOffTime, transitionDirection);
        }
    }

    public virtual void RemoveScreen()
    {
        screenManager.Remove(this);
    }

    private void ScreenTransition(GameTime gameTime, TimeSpan transitionTime, int direction)
    {
        float transitionDelta;

        if (transitionTime == TimeSpan.Zero)
            transitionDelta = 1;
        else
            transitionDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / transitionTime.TotalMilliseconds);

        transitionPercent += transitionDelta * direction * transitionSpeed;

        transitionPercent = MathHelper.Clamp(transitionPercent, 0, 1);
    }

    public virtual void HandleInput()
    {
        if (screenState != ScreenState.Active)
            return;
    }

    public abstract void Draw(GameTime gameTime);

    public virtual void ExitScreen()
    {
        screenState = ScreenState.TransitionOff;
    }

    public void FreezeScreen()
    {
        screenState = ScreenState.Frozen;
    }
}

Pak napr: Game1.cs:

Initialize()
{
screenManager­.Add(new MainMenuScreen());
}

 
Nahoru Odpovědět
12.9.2012 21:01
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na user
David Hartinger:12.9.2012 21:27

No jelikož tam máš ty Update a Draw, tak je to také vlastně komponenta, jen má něco navíc. Zapínání/vypínání komponent to také neřeší. Takže to dělám vlastně podobně, to je dobré vědět :)

BTW proč máš takhle rozepsané ty vlastnosti? Stačí jen:

public TimeSpan TransitionOnTime { get; protected set; }

Udělám tam injekci do konstruktoru přes tu třídu s hrou, změním Game na TetrisGame a bude :) Jen nevím, kdy se k tomu zas dostanu, už mi to sežralo moooc hodin.

Nahoru Odpovědět
12.9.2012 21:27
You are the greatest project you will ever work on.
Avatar
user
Tvůrce
Avatar
Odpovídá na David Hartinger
user:12.9.2012 21:42

Myslim, ze by slo vypinani/zapinani udelat na zpusob jaky jsi uz tady navrhoval, nebylo by to spatne. U kazde obrazovky by jsi mel ten List s nazvy komponent, po kazdym volani screenManager­.Add(new MainMenuScreen()) nebo ExitScreen() by si prosel List a povypinal/pozapinal komponenty. To neni spatnej napad, nebo co se na nem nezda?

 
Nahoru Odpovědět
12.9.2012 21:42
Avatar
David Hartinger
Vlastník
Avatar
Odpovídá na user
David Hartinger:13.9.2012 12:07

Zdá se mi, myslím, že je to v pořádku, i se o to tak pokusím :) Musím ale hru rozdělit nejprve do komponent a to je porod, když to je vše zamotané do sebe.

Nahoru Odpovědět
13.9.2012 12:07
You are the greatest project you will ever work on.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 17 zpráv z 17.