Diskuze: XNA - opacity sprite

C# .NET .NET (C# a Visual Basic) XNA - opacity sprite American English version English version

Avatar
user
Redaktor
Avatar
user:

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 Čápka
Tým ITnetwork
Avatar
Odpovídá na user
David Čápka:

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
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
user
Redaktor
Avatar
user:
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
Redaktor
Avatar
Odpovídá na user
user:

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 Čápka
Tým ITnetwork
Avatar
Odpovídá na user
David Čápka:

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
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
user
Redaktor
Avatar
user:

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 Čápka
Tým ITnetwork
Avatar
Odpovídá na user
David Čápka:

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
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
user
Redaktor
Avatar
Odpovídá na David Čápka
user:

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 Čápka
Tým ITnetwork
Avatar
Odpovídá na user
David Čápka:

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
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na user
David Čápka:

Ú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
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
user
Redaktor
Avatar
user:

"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 Čápka
Tým ITnetwork
Avatar
Odpovídá na user
David Čápka:

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
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na user
David Čápka:

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
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
user
Redaktor
Avatar
Odpovídá na David Čápka
user:

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 Čápka
Tým ITnetwork
Avatar
Odpovídá na user
David Čápka:

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
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
user
Redaktor
Avatar
Odpovídá na David Čápka
user:

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 Čápka
Tým ITnetwork
Avatar
Odpovídá na user
David Čápka:

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
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
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.