Isometric Tile Waves

Started by
1 comment, last by Stealth Kill 7 years, 5 months ago

Hi guys!!

I wanted to make an ocean with Isometric Tiles.

I found this JavaScript example here http://codepen.io/arnaudrocca/pen/reNpaP and I tried to port it to XNA/Monogame

My wave doesn't look good and I don't know what is wrong.

This is my whole code


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

namespace IsometricWaveDemo
{
    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Texture2D tileTex;
        float min = 1.25f;
        int mapSize = 12;
	    int width = 50;
	    int height = 25;
	    int speed = 5;
	    int strength = 2;
	    char direction = 'x';

        float timer = 0;
        float deltaTime = 0;
        float lastTime = 0;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.PreferredBackBufferHeight = 900;
            graphics.PreferredBackBufferWidth = 1600;
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            FileStream fs = new FileStream("Content\\water4.png", FileMode.Open);
            tileTex = Texture2D.FromStream(GraphicsDevice,fs);
            fs.Close();
        }

        protected override void Update(GameTime gameTime)
        { 

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();

            deltaTime = (float)gameTime.TotalGameTime.TotalMilliseconds - lastTime;
            lastTime = (float)gameTime.TotalGameTime.TotalMilliseconds;
            timer += speed * deltaTime / 1000;
            for (int x = 0; x < mapSize; x++)
            {
                for(int y= 0; y < mapSize; y++)
                {

                    float z = 0;
                    if (direction == 'x')
                    {
                        z = (float)(min + Math.Sin(timer + Math.Sin((y - x) * strength / 10)));
                    }
                    else
                    {
                        z = (float)(min + Math.Cos(timer + Math.Cos((x + y) * strength / 10)));
                    }
                    spriteBatch.Draw(tileTex, new Rectangle(400 + (x - y) * width / 2, 200 + (int)((x + y - z) * height  / 2), width, height), Color.White);
                }
            }

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

I attached the tile which I used. Can someone help me?

Advertisement

Hi!

Checked your code, tried it out actually in a vanilla sample so thx. for the out of the box compiling code sample you posted :wink: !
I've found the issue. It is somewhat "decipherable" based on the resulting visuals.

What you have here is the result of "Integer division", and if I'm not mistaken this is a difference between javascript and C#, that is why the straight port doesn't work.
In javascript you have integers and doubles if I'm not mistaken (integers: 1, 33, 42, doubles: 1.25, 3.14) and the result of the division operator on two numbers (be it integer or double) will be double so 1 / 2 == 0.5, but in C# this is not the case because C# has a language construct called integer division.
This means when the dividend and the divisor are both integers, the result will be an integer too! So in the first case 1 / 2 == 0 is what you will get in C# or another case: 10 / 3 == 3...

I modified your code just a tiny little to make it work:


float z = 0;
if (direction == 'x')
{
	z = (float)(min + Math.Sin(timer + Math.Sin((y - x) * strength / 10f))); // Divide by 10f (float) or 10.0 (double)!
}
else
{
	z = (float)(min + Math.Cos(timer + Math.Cos((x + y) * strength / 10f))); // Divide by 10f (float) or 10.0 (double)!
}
spriteBatch.Draw(
	tileTex,
        // The destination rectangle needs integer coordinates for drawing but calculate the position with floats or doubles
	new Rectangle(
		(int)(400f + (x - y) * width / 2f), // Divide by 2f (float) or 2.0 (double)!
		(int)(200f + ((x + y - z) * height / 2f)), // Divide by 2f (float) or 2.0 (double)!
		width, height
	),
	Color.White
);

This code is the modified version of the core of your drawing loop.

Little explanation why/how this works:
C# automatically promotes types to more precise ones when using operations which would result in a more precise data (e.g.: multiplying an integer by a float will result in a float and the first operand integer will be handled as a float), but it is a statically typed "explicit" language and does not do automatic truncating, that is why you have to explicitly write out (int) integer casts, because that can truncate the data (loose precision).
This is usually a good approach regarding programming languages as it promotes explicit control over calculations and results (safty) but it is indeed a bit more complex, requiring more code and more care and it less pleasant to look at.

What is a float/double:
Floating point representations of numbers (e.g.: 33.33333, 3.14, 1.25...) with a specific structure to be able to represent ridiculously big and small numbers alike. In C# (and usually in most static languages) float is a 32 bit floating point number and double is 64 bit hence the name: double precision (float may be called single in many cases).

Hope this helps,
Br.

Blog | Overburdened | KREEP | Memorynth | @blindmessiah777 Magic Item Tech+30% Enhanced GameDev

Wow!! I learned alot from your post, thank you very much for taking so much time and explaining everything perfectly!

I hope this thread will help others too!

This topic is closed to new replies.

Advertisement