• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed niedokładność typu float?

Object Storage Arubacloud
0 głosów
248 wizyt
pytanie zadane 27 czerwca 2018 w C# przez DODO Bywalec (2,950 p.)
zamknięte 27 czerwca 2018 przez DODO

Witam.

Programuję sobie spokojnie spirograf(takie patyki co się kręcą, jeden przyczepiony do kolejnego i ostatni rysuje kreskę), odpalam, a tu takie dziwne cuś:

Jak widać, kolejne patyki nie są dokładnie przyczepione do poprzedników. latają w okolicy zakończeń poprzednich, ale niedokładnie. Kolejne patyki są coraz mniej dokładne. Warto dodać, że wartości przechowuję jako float'y. Czy to może być powodem problemów?

(używam Monogame i C#)

Główny kod:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;

namespace SPIROGRAF
{

    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        public Texture2D rect;

        List<Rod> allRods;
        
        Vector2 rod1Att = new Vector2(400, 300);

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
        
        protected override void Initialize()
        {
            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
            graphics.ApplyChanges();


            allRods = new List<Rod> { new Rod(100, 180, this), new Rod(80, 500, this), new Rod(90, 300, this), new Rod(100, 1000, this) }; //new Rod(100, 100, this)
            //allRods = new List<Rod> { new Rod(50, 10, this), new Rod(50, 20, this), new Rod(50, 30, this), new Rod(50, 40, this), new Rod(50, 50, this) }; //new Rod(100, 100, this)
            //allRods = new List<Rod> { };
            //for (int i = 0; i < 10; i++)
            //{
            //    allRods.Add(new Rod(50, i*10, this));
            //}
            base.Initialize();
        }
        
        protected override void LoadContent()
        {
            
            spriteBatch = new SpriteBatch(GraphicsDevice);

            rect = Content.Load<Texture2D>("rect"); // To biały kwadrat 1x1 px
        }
        
        protected override void UnloadContent()
        {
            
        }
        
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
            

            for (int i = 0; i < allRods.Count; i++)
            {
                allRods[i].update(gameTime);

                if (i == 0)
                {
                    allRods[i].attachment = rod1Att;
                }
                else
                {
                    allRods[i].attachment = allRods[i - 1].end;
                }
            }

            

            base.Update(gameTime);
        }
        
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            spriteBatch.Begin();
            

            for (int i = 0; i < allRods.Count; i++)
            {
                allRods[i].draw(spriteBatch);
            }

            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

Klasa Rod:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;

namespace SPIROGRAF
{
    class Rod
    {
        public int length;
        public float degreesPerSeconds;

        public float degrees;
        public Vector2 attachment;
        public Vector2 end;

        Game1 g;

        public Rod(int l, int dps, Game1 game)
        {
            length = l;
            degreesPerSeconds = dps;
            g = game;
        }

        public void update(GameTime gameTime)
        {
            int fps = 60;
            try
            {
                fps = (int)(1 / gameTime.ElapsedGameTime.TotalSeconds);
            }
            catch (DivideByZeroException)
            {
                
            }
            
            degrees += degreesPerSeconds / fps;
            degrees = degrees % 360;
            float radians = MathHelper.ToRadians(degrees);
            end = Vector2.Transform(new Vector2(length, 0), Matrix.CreateRotationZ(radians)) + attachment; 
        }

        public void draw(SpriteBatch spriteBatch)
        {
            
            spriteBatch.Draw(g.rect, new Rectangle((int)attachment.X, (int)attachment.Y-1, length, 2), null, Color.CornflowerBlue, MathHelper.ToRadians(degrees), Vector2.Zero, SpriteEffects.None, 0);
            
        }
    }
}

Z góry dziękuję za przydatne odpowiedzi :)

komentarz zamknięcia: problem rozwiązany

1 odpowiedź

+1 głos
odpowiedź 27 czerwca 2018 przez DODO Bywalec (2,950 p.)

Dobra, sam rozwiązałem problem, więc zamykam, ale podzielę się rozwiązaniem coby przyszłe pokolenia nie miały takich problemów:

Obiekty klasy Rod pracowały na przestarzałych o jedną klatkę danych, a były rysowane na nowych, stąd niedokładności. Aby to naprawić, trzeba zamienić kolejność wywoływania funkcji update i przypisywania pozycji zaczepienia patyka.

Więc zamiast:

for (int i = 0; i < allRods.Count; i++)
            {
                allRods[i].update(gameTime);
 
                if (i == 0)
                {
                    allRods[i].attachment = rod1Att;
                }
                else
                {
                    allRods[i].attachment = allRods[i - 1].end;
                }
            }

powinno być:

for (int i = 0; i < allRods.Count; i++)
            {
                if (i == 0)
                {
                    allRods[i].attachment = rod1Att;
                }
                else
                {
                    allRods[i].attachment = allRods[i - 1].end;
                }

                allRods[i].update(gameTime);
            }

 

Podobne pytania

0 głosów
1 odpowiedź 334 wizyt
pytanie zadane 13 marca 2016 w C i C++ przez milosz503 Początkujący (270 p.)
0 głosów
0 odpowiedzi 85 wizyt
pytanie zadane 13 lutego 2019 w PHP przez Grzegorz Mikina Dyskutant (8,060 p.)
0 głosów
2 odpowiedzi 153 wizyt
pytanie zadane 5 grudnia 2018 w Java przez kvbq Obywatel (1,490 p.)

92,575 zapytań

141,424 odpowiedzi

319,649 komentarzy

61,960 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...