tsuikit159 / IERG3080-group-project

This is a group project from course IERG3080 group 12
0 stars 0 forks source link

Include physical phenomena into the game #2

Open tsuikit159 opened 10 months ago

tsuikit159 commented 10 months ago

TODO: Follow the physics rule as the instructions have mentioned,

  1. Make a formula that the sun generates a gravitational force to attract all other orbs in the game, i.e., all orbs have an acceleration pointing to the sun. The enemies and the player do not generate gravitational interaction against each other.
  2. Make a formula such that at the beginning of the stage, each of the players and the enemies is moving in a stable circular orbit. That is, the Euclidean distance between the sun and the orb is a constant.

The instructions state that you might include Newton's Mechanic, but it seems optional to do that.

Zappeddy commented 10 months ago

I have changed a bit to enable the player movement bounded due to the sun's gravity.

However, some of the previous functions like splitting the player do not work.

Do you guys think of a way to fix this?

MainWindow.xaml.cs

using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; using System.Threading.Tasks; using Circle; namespace Project { ///

/// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { private DispatcherTimer timer = new DispatcherTimer(); private DispatcherTimer gametimer = new DispatcherTimer(); private Canvas canvas; private bool MousePressed = false; private float speed = 2, speedx, speedy; private MouseButtonEventArgs mouseEventArgs; private int tickcount = 0; private bool isPlayerSplitting; private Vector playerVelocity; private Vector playerForceSpeed; private Point playerPosition; private Point sunPosition; private Point mousePosition; private List enemies; private Orb sun, player; private double sunSize = 100; private double playerSize = 20;

    public static bool CheckCollision(Orb e1, Orb e2)
    {
        var r1 = e1.Size / 2;
        var x1 = e1.Position.X + r1;
        var y1 = e1.Position.Y + r1;
        var r2 = e2.Size / 2;
        var x2 = e2.Position.X + r2;
        var y2 = e2.Position.Y + r2;
        var d = new Vector(x2 - x1, y2 - y1);
        return d.Length <= r1 + r2;
    }
    public MainWindow()
    {
        InitializeComponent();
        /// initzialize the canvas
        /// 

        canvas = new Canvas();
        playerPosition = new Point(100, 640);
        sunPosition = new Point(400, 640);
        sun = new Orb(1280, 800, sunSize, Colors.Yellow);
        player = new Orb(1280, 800, playerSize, Colors.Blue);
        playerVelocity = new Vector(0, 0);
        enemies = new List<Orb>();

        Window.AddHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(MouseDown), true);
        Window.AddHandler(PreviewMouseLeftButtonUpEvent, new MouseButtonEventHandler(MouseUp), true);
        timer.Interval = TimeSpan.FromMilliseconds(16);
        timer.Tick += GameTick;
        timer.Start();

    }

    private void GameTick(object sender, EventArgs e)
    {
        UpdatePlayerPosition();
        DrawGameObjects();
        collide();
        if (MousePressed == true)
        {   // get the mouse position
            tickcount ++;

            float speed = 0.2f;
            double centerX = mouseEventArgs.GetPosition(GameScreen).X;
            double centerY = mouseEventArgs.GetPosition(GameScreen).Y;
            // get the player position
            double playerX = playerPosition.X;
            double playerY = playerPosition.Y;
            // get the angle between the mouse and the player
            double dx = centerX - playerX;
            double dy = centerY - playerY;
            double angle = Math.Atan2(dy, dx);
            double oppositeAngle = angle + Math.PI;
            // move the player to the opposite side
            double oppositeX = (playerX + Math.Cos(oppositeAngle));
            double oppositeY = (playerY + Math.Sin(oppositeAngle));
            // set the player position in the canvas
            playerPosition.X = oppositeX;
            playerPosition.Y = oppositeY;
            DrawOrb(playerPosition, player.Size, player.Color);

            if (tickcount > 8)
            {
                tickcount = 0;
                // Code to execute when the gametimer reaches 500 milliseconds
                IShapeFactory factory = new CircleFactory((playerSize)/4);
                Shape circle = factory.CreateShape();
                Ellipse checkellipse = circle as Ellipse;
                // Move the circle to the opposite of the player side

                double circleX = (playerPosition.X - Math.Cos(oppositeAngle) - (player.Size / 4) *2);
                double circleY = (playerPosition.Y - Math.Sin(oppositeAngle) - (player.Size / 4) * 2 );
                /*
                foreach (var x in GameScreen.Children.OfType<Ellipse>().ToList())
                {
                    if (CheckCollision(checkellipse,x))
                    {
                        if (player.Size > x.Width)
                        {
                            GameScreen.Children.Remove(x);
                            circle.Width += 2;
                            circle.Height += 2;
                        }
                        else
                        {
                            GameScreen.Children.Remove(circle);
                            x.Width += 2;
                            x.Height += 2;
                        }
                    }
                }
                */
                Canvas.SetLeft(circle, circleX);
                Canvas.SetTop(circle, circleY);
                GameScreen.Children.Add(circle);
            }
        }
    }

    private void MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            MousePressed = true;
            mouseEventArgs = e;
            MouseMove += (sender, e) => mousePosition = e.GetPosition(GameScreen);
            // set the circle position in the canvas

        }
    }
    public void MouseUp(object sender, MouseButtonEventArgs e)
    {
        if (e.ChangedButton == MouseButton.Left)
        {
            MousePressed = false;
            Console.WriteLine("mouse released");
        }
    }
    public void collide()
    {
        foreach (var x in GameScreen.Children.OfType<Ellipse>().ToList())
        {
            foreach(var enemy in enemies)
            {
                if ((string)x.Tag == "circle")
                {
                    if (CheckCollision(player, enemy))
                    {
                        if (player.Size > x.Width)
                        {
                            GameScreen.Children.Remove(x);
                            player.Size += player.Size / 10;
                        }
                        else
                        {
                            MessageBox.Show("Game Over");
                            this.Close();
                        }
                    }
                    else if (CheckCollision(sun, enemy))
                    {
                        GameScreen.Children.Remove(x);
                        sun.Size += 2;
                    }

                }
                else if (CheckCollision(player, sun))
                {
                    MessageBox.Show("Game Over");
                    this.Close();
                }
            }

        }
    }

    private void UpdatePlayerPosition()
    {
        playerVelocity += (sunPosition - playerPosition) * 0.0001;
        playerPosition += playerVelocity;

        playerPosition = ClampPosition(playerPosition);
    }

    private Point ClampPosition(Point position)
    {
        double x = Math.Max(0, Math.Min(1280, position.X));
        double y = Math.Max(0, Math.Min(800, position.Y));
        return new Point(x, y);
    }

    private void DrawGameObjects()
    {
        GameScreen.Children.Clear();

        DrawOrb(playerPosition, player.Size, Colors.Blue);
        DrawOrb(sunPosition, sun.Size, Colors.Yellow);

        foreach (var enemy in enemies)
        {
            DrawOrb(enemy.Position, enemy.Size, enemy.Color);
        }
    }

    private void DrawOrb(Point position, double size, Color color)
    {
        var ellipse = new Ellipse
        {
            Width = size,
            Height = size,
            Fill = new SolidColorBrush(color)
        };

        Canvas.SetLeft(ellipse, position.X - size / 2);
        Canvas.SetTop(ellipse, position.Y - size / 2);

        GameScreen.Children.Add(ellipse);
    }
}
public class Orb
{
    public Point Position { get; set; }
    public Vector Velocity { get; set; }
    public double Size { get; set; }
    public Color Color { get; set; }

    public Orb(double x, double y, double size, Color color, Vector velocity = default)
    {
        Position = new Point(x, y);
        Size = size;
        Color = color;
        Velocity = velocity;
    }

    public bool Contains(Point point, double radius)
    {
        return (Position - point).Length <= (Size / 2 + radius / 2);
    }

    public void AccelerateTowards(Point target)
    {
        var acceleration = (target - Position) * 0.001;
        Velocity += acceleration;
    }

    public void UpdatePosition()
    {
        Position += Velocity;
    }
}

}

Zappeddy commented 10 months ago

螢幕擷取畫面 2023-12-27 004440

tsuikit159 commented 10 months ago

what do you mean by splitting the player? you can commit your progress to the dev branch so I can see what happened in your case

Zappeddy commented 10 months ago

I have just put the codes inside the gravitational-force branch. You can check it out.

tsuikit159 commented 10 months ago

i just put some adjustment into the code, but is not totally work. private void UpdatePosition() { double angle = Math.Atan2(Canvas.GetTop(Sun) - Canvas.GetTop(Player), Canvas.GetLeft(Sun) - Canvas.GetLeft(Player)); foreach (var x in GameScreen.Children.OfType().ToList().Where(x => (string)x.Tag != "Sun" && x != Sun)) {

     double Gangle = Math.Atan2(Canvas.GetTop(Sun) - Canvas.GetTop(Player), Canvas.GetLeft(Sun) - Canvas.GetLeft(Player));
     double dx = Canvas.GetLeft(Sun) - Canvas.GetLeft(Player);
     double dy = Canvas.GetTop(Sun) - Canvas.GetTop(Player);
     double distance = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));

     // Calculate the acceleration

     // Update the speed

     // Set the position of the player and the circle
     Canvas.SetLeft(x, Canvas.GetLeft(x) + speedx);
     Canvas.SetTop(x, Canvas.GetTop(x) + speedy);
 }
 for (int i = 0; i < GameScreen.Children.Count; i++)
 {
     if (GameScreen.Children[i] is Ellipse circle && (string)circle.Tag == "circle")
     {
         double dx = Canvas.GetLeft(Sun) - Canvas.GetLeft(circle);
         double dy = Canvas.GetTop(Sun) - Canvas.GetTop(circle);
         double distance = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
         double force = G * (Player.Width * circle.Width) / Math.Pow(distance, 2);
         double acceleration = force / (Player.Width * circle.Width);
         double velocity = Math.Sqrt(acceleration * distance);
         double velocityX = velocity * Math.Cos((double)Math.Atan2(dy, dx));
         double velocityY = velocity * Math.Sin((double)Math.Atan2(dy, dx));
         double newX = Canvas.GetLeft(circle) + velocityX;
         double newY = Canvas.GetTop(circle) + velocityY;
         if (distance > range)
         {
             double PlayerX = Canvas.GetLeft(Player) + velocityX;
             double PlayerY = Canvas.GetTop(Player) + velocityY;
             Canvas.SetLeft(Player, PlayerX);
             Canvas.SetTop(Player, PlayerY);
         }
         else
         {
             double PlayerX = Canvas.GetLeft(Player) -velocityX;
             double PlayerY = Canvas.GetTop(Player) - velocityY;
             Canvas.SetLeft(Player, PlayerX);
             Canvas.SetTop(Player, PlayerY);
         }
         Canvas.SetLeft(circle, newX);
         Canvas.SetTop(circle, newY);

     }
 }

}